Socket-More-Interface
view release on metacpan or search on metacpan
Interface.xs view on Meta::CPAN
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "const-c.inc"
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <sys/un.h>
//Copy a sockaddr into an sv. BSD type systems have length field in struct
//sockaddr linux does not. So we cast the pointer to the correct family and
//then access the length field
//Returns a SV with the full sockaddr_* data
SV* sv_from_sockaddr(pTHX_ struct sockaddr *sockaddr){
switch(sockaddr->sa_family){
case AF_INET:
return newSVpv((char *)sockaddr, sizeof(struct sockaddr_in));
break;
case AF_INET6:
return newSVpv((char *)sockaddr, sizeof(struct sockaddr_in6));
break;
case AF_UNIX:
return newSVpv((char *)sockaddr, sizeof(struct sockaddr_un));
break;
default:
//TODO: use sockaddr_storage on linux?
return newSVpv((char *)sockaddr, sizeof(struct sockaddr));
break;
}
return NULL;
}
MODULE = Socket::More::Interface PACKAGE = Socket::More::Interface
INCLUDE: const-xs.inc
void
getifaddrs()
INIT:
struct ifaddrs *a;
struct ifaddrs *next;
int ret;
HV* h;
UV count=0;
PPCODE:
ret=getifaddrs(&a);
if(ret<0){
switch(GIMME_V){
case G_SCALAR:
case G_VOID:
XSRETURN_UNDEF;
break;
case G_ARRAY:
XSRETURN_EMPTY;
break;
default:
break;
}
}
else{
next=a->ifa_next;
switch(GIMME_V){
case G_SCALAR:
while(next){
count++;
next=next->ifa_next;
}
//Free contents
freeifaddrs(a);
mXPUSHs(newSVuv(count));
XSRETURN(1);
break;
case G_VOID:
XSRETURN_UNDEF;
break;
case G_ARRAY:
//Copy contents
while(next){
//Create hash
h=newHV();
//Copy Values
if(next->ifa_name){
hv_stores(h, "name", newSVpv(next->ifa_name,0));
}
if(next->ifa_flags){
hv_stores(h, "flags",newSVuv(next->ifa_flags));
}
if(next->ifa_addr){
hv_stores(h, "addr", sv_from_sockaddr(aTHX_ next->ifa_addr));
}
if(next->ifa_netmask){
hv_stores(h, "netmask", sv_from_sockaddr(aTHX_ next->ifa_netmask));
}
if(next->ifa_dstaddr){
hv_stores(h, "dstaddr", sv_from_sockaddr(aTHX_ next->ifa_dstaddr));
}
//a->ifa_data... read into this more
next=next->ifa_next;
mXPUSHs(newRV((SV *)h));
count++;
}
//Free contents
freeifaddrs(a);
XSRETURN(count);
break;
default:
break;
}
}
SV *
if_nametoindex(name)
SV *name;
INIT:
char *p;
unsigned int ret;
int len;
PPCODE:
if(SvOK(name)&&SvPOK(name)){
len=SvCUR(name);
p=SvGROW(name, len+1);
p[len]='\0';
ret=if_nametoindex(p);
mXPUSHs(newSVuv(ret));
XSRETURN(1);
}
else {
XSRETURN_UNDEF;
}
SV *
if_indextoname(index)
SV *index;
INIT:
SV *result=newSV(IF_NAMESIZE);
char *p=SvPVX(result);
char *ret;
PPCODE:
if(SvOK(index)){
ret=if_indextoname(SvUV(index), p);
if(ret == p){
SvPOK_on(result);
SvCUR_set(result, strlen(p));
mXPUSHs(result);
XSRETURN(1);
}
else {
XSRETURN_UNDEF;
}
}
else {
XSRETURN_UNDEF;
}
void
if_nameindex()
INIT:
UV count=0;
struct if_nameindex *results, *next;
PPCODE:
results=if_nameindex();
if(results ==NULL){
XSRETURN_UNDEF;
}
else {
next=results;
while((next->if_index !=0 )&&
(next->if_name != NULL)){
EXTEND(SP,2);
mPUSHs(newSVuv(next->if_index));
mPUSHs(newSVpv(next->if_name, 0));
count++;
next=results+count;
}
if_freenameindex(results);
XSRETURN(count);
}
( run in 0.586 second using v1.01-cache-2.11-cpan-5511b514fd6 )