diff --git a/Android.mk b/Android.mk index 51fa22c5..fc2cec73 100644 --- a/Android.mk +++ b/Android.mk @@ -64,7 +64,8 @@ LOCAL_SRC_FILES:= \ serval-dna/simulate.c \ serval-dna/srandomdev.c \ serval-dna/keyring.c \ - serval-dna/vomp.c + serval-dna/vomp.c \ + serval-dna/lsif.c LOCAL_MODULE:= serval diff --git a/Makefile.in b/Makefile.in index 2cf417ed..1a67adeb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -37,7 +37,8 @@ SRCS= batman.c \ sqlite3.c \ srandomdev.c \ trans_cache.c \ - vomp.c + vomp.c \ + lsif.c HAVE_VOIPTEST= @HAVE_VOIPTEST@ ifeq ($(HAVE_VOIPTEST), 1) diff --git a/lsif.c b/lsif.c new file mode 100644 index 00000000..3cf49537 --- /dev/null +++ b/lsif.c @@ -0,0 +1,109 @@ +/* + * Derived from https://github.com/ajrisi/lsif/blob/master/lsif.c + * No copyright information in the file, and published publicly, + * so presume no rights reserved. + * + * This method doesn't work properly on OSX, but is for Android where no other + * option seems to work. Should work on any linux system. + * ******************************** + * + * Updated code to obtain IP and MAC address for all "up" network + * interfaces on a linux system. Now IPv6 friendly and updated to use + * inet_ntop instead of the deprecated inet_ntoa function. This version + * should not seg fault on newer linux systems + * + * Version 2.0 + * + * Authors: + * Adam Pierce + * Adam Risi + * William Schaub + * + * Date: 11/11/2009 + * http://www.adamrisi.com + * http://www.doctort.org/adam/ + * http://teotwawki.steubentech.com/ + * + */ + #include +#include +#include +#include +#include +#include +#include +#include +#include +#if __MACH__ || __NetBSD__ || __OpenBSD__ || __FreeBSD__ +#include +#endif +/* Include sockio.h if needed */ +#ifndef SIOCGIFCONF +#include +#endif +#include +#include +#include +#if __MACH__ +#include +#endif + +/* On platforms that have variable length + ifreq use the old fixed length interface instead */ +#ifdef OSIOCGIFCONF +#undef SIOCGIFCONF +#define SIOCGIFCONF OSIOCGIFCONF +#undef SIOCGIFADDR +#define SIOCGIFADDR OSIOCGIFADDR +#undef SIOCGIFBRDADDR +#define SIOCGIFBRDADDR OSIOCGIFBRDADDR +#endif + +#ifdef HAVE_LINUX_IF_H +int lsif(void) +{ + char buf[8192] = {0}; + struct ifconf ifc = {0}; + struct ifreq *ifr = NULL; + int sck = 0; + int nInterfaces = 0; + int i = 0; + struct ifreq *item; + struct sockaddr_in local,broadcast; + + /* Get a socket handle. */ + sck = socket(PF_INET, SOCK_DGRAM, 0); + if(sck < 0) { + return 1; + } + + /* Query available interfaces. */ + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + if(ioctl(sck, SIOCGIFCONF, &ifc) < 0) { + return 1; + } + + /* Iterate through the list of interfaces. */ + ifr = ifc.ifc_req; + nInterfaces = ifc.ifc_len / sizeof(struct ifreq); + for(i = 0; i < nInterfaces; i++) { + item = &ifr[i]; + + bcopy(&item->ifr_addr,&local,sizeof(local)); + + /* get broadcast address */ + if(ioctl(sck, SIOCGIFBRDADDR, item)== 0) { + bcopy(&item->ifr_broadaddr,&broadcast,sizeof(broadcast)); + } else continue; + + printf("name=%s addr=%08x, broad=%08x\n", + item->ifr_name, + local.sin_addr, + broadcast.sin_addr); + overlay_interface_register(item->ifr_name,local,broadcast); + } + + return 0; +} +#endif diff --git a/overlay_interface.c b/overlay_interface.c index 6acb2e41..9100c15f 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -175,13 +175,11 @@ int overlay_interface_args(char *arg) return 0; } -int overlay_interface_init_socket(int interface,struct sockaddr_in src_addr,struct sockaddr_in broadcast, - struct sockaddr_in netmask) +int overlay_interface_init_socket(int interface,struct sockaddr_in src_addr,struct sockaddr_in broadcast) { #define I(X) overlay_interfaces[interface].X I(local_address)=src_addr; I(broadcast_address)=broadcast; - I(netmask)=netmask; I(fileP)=0; I(fd)=socket(PF_INET,SOCK_DGRAM,0); @@ -219,7 +217,7 @@ int overlay_interface_init_socket(int interface,struct sockaddr_in src_addr,stru } int overlay_interface_init(char *name,struct sockaddr_in src_addr,struct sockaddr_in broadcast, - struct sockaddr_in netmask,int speed_in_bits,int port,int type) + int speed_in_bits,int port,int type) { /* Too many interfaces */ if (overlay_interface_count>=OVERLAY_MAX_INTERFACES) return WHY("Too many interfaces -- Increase OVERLAY_MAX_INTERFACES"); @@ -258,7 +256,7 @@ int overlay_interface_init(char *name,struct sockaddr_in src_addr,struct sockadd /* XXX later add pretend location information so that we can decide which "packets" to receive based on closeness */ } else { - if (overlay_interface_init_socket(overlay_interface_count,src_addr,broadcast,netmask)) + if (overlay_interface_init_socket(overlay_interface_count,src_addr,broadcast)) return WHY("overlay_interface_init_socket() failed"); } @@ -477,6 +475,52 @@ int overlay_sendto(struct sockaddr_in *recipientaddr,unsigned char *bytes,int le return len; } +int overlay_interface_register(unsigned char *name, + struct sockaddr_in local, + struct sockaddr_in broadcast) +{ + /* Now register the interface, or update the existing interface registration */ + struct interface_rules *r=interface_filter,*me=NULL; + while(r) { + if (!strcasecmp((char *)name,r->namespec)) me=r; + if (!r->namespec[0]) me=r; + r=r->next; + } + if (me&&(!me->excludeP)) { + if (debug&DEBUG_OVERLAYINTERFACES) + fprintf(stderr,"Interface %s is interesting.\n",name); + /* We should register or update this interface. */ + int i; + for(i=0;ispeed_in_bits,me->port,me->type)) + WHY("Could not initialise newly seen interface"); + else + if (debug&DEBUG_OVERLAYINTERFACES) fprintf(stderr,"Registered interface %s\n",name); + } + } + return 0; +} + time_t overlay_last_interface_discover_time=0; int overlay_interface_discover() { @@ -485,16 +529,15 @@ int overlay_interface_discover() if ((time(0)-overlay_last_interface_discover_time)<2) return 0; overlay_last_interface_discover_time=time(0); -#ifdef HAVE_IFADDRS_H - struct ifaddrs *ifaddr,*ifa; - int family,i; - - if (getifaddrs(&ifaddr) == -1) { - perror("getifaddr()"); - return WHY("getifaddrs() failed"); - } + /* The Android ndk doesn't have ifaddrs.h, so we have to use the netlink interface. + However, netlink is only available on Linux, so for BSD systems, e.g., Mac, we + need to use the ifaddrs method. + + Also, ifaddrs will work on non-linux systems which is considered critical. + */ /* Mark all interfaces as not observed, so that we know if we need to cull any */ + int i; for(i=0;inamespec,dummyaddr,dummyaddr,dummyaddr, + if (overlay_interface_init(r->namespec,dummyaddr,dummyaddr, 1000000,PORT_DNA,OVERLAY_INTERFACE_WIFI)) WHY("Could not initialise newly seen interface"); else @@ -518,6 +561,15 @@ int overlay_interface_discover() r=r->next; } +#ifdef HAVE_IFADDRS_H + struct ifaddrs *ifaddr,*ifa; + int family; + + if (getifaddrs(&ifaddr) == -1) { + perror("getifaddr()"); + return WHY("getifaddrs() failed"); + } + /* Check through actual network interfaces */ for (ifa=ifaddr;ifa!=NULL;ifa=ifa->ifa_next) { family=ifa->ifa_addr->sa_family; @@ -527,56 +579,24 @@ int overlay_interface_discover() unsigned char *name=(unsigned char *)ifa->ifa_name; struct sockaddr_in local=*(struct sockaddr_in *)ifa->ifa_addr; struct sockaddr_in netmask=*(struct sockaddr_in *)ifa->ifa_netmask; - unsigned int broadcast_bits=local.sin_addr.s_addr|~netmask.sin_addr.s_addr; - struct sockaddr_in broadcast=local; - broadcast.sin_addr.s_addr=broadcast_bits; + struct sockaddr_in broadcast=local; if (debug&DEBUG_OVERLAYINTERFACES) printf("%s: %08x %08x %08x\n",name,local.sin_addr.s_addr,netmask.sin_addr.s_addr,broadcast.sin_addr.s_addr); - /* Now register the interface, or update the existing interface registration */ - struct interface_rules *r=interface_filter,*me=NULL; - while(r) { - if (!strcasecmp((char *)name,r->namespec)) me=r; - if (!r->namespec[0]) me=r; - r=r->next; - } - if (me&&(!me->excludeP)) { - if (debug&DEBUG_OVERLAYINTERFACES) - fprintf(stderr,"Interface %s is interesting.\n",name); - /* We should register or update this interface. */ - int i; - for(i=0;ispeed_in_bits,me->port,me->type)) - WHY("Could not initialise newly seen interface"); - else - if (debug&DEBUG_OVERLAYINTERFACES) fprintf(stderr,"Registered interface %s\n",name); - } - } + overlay_interface_register(name,local,broadcast); + break; } } } freeifaddrs(ifaddr); +#else +#ifdef HAVE_LINUX_IF_H + /* Use alternative linux-only method to find and register interfaces. */ + lsif(); +#else +#error Don't know how to get interface list on this platform #endif +#endif + return 0; } @@ -689,7 +709,7 @@ int overlay_stuff_packet_from_queue(int i,overlay_buffer *e,int q,long long now, /* Consider next in queue */ p=&(*p)->next; - if (0) printf("D p=%p, *p=%p, queue=%d\n",p,p?*p:-1,q); + if (0) printf("D p=%p, *p=%p, queue=%d\n",p,p?*p:NULL,q); } if (0) printf("returning from stuffing\n"); return 0; diff --git a/serval.h b/serval.h index 1ee94894..d7e9aba8 100644 --- a/serval.h +++ b/serval.h @@ -603,7 +603,6 @@ typedef struct overlay_interface { /* Broadcast address and netmask, if known */ struct sockaddr_in local_address; struct sockaddr_in broadcast_address; - struct sockaddr_in netmask; /* Not necessarily the real MTU, but the largest frame size we are willing to TX on this interface. For radio links the actual maximum and the maximum that is likely to be delivered reliably are @@ -756,9 +755,8 @@ overlay_frame *op_dup(overlay_frame *f); long long parse_quantity(char *q); int overlay_interface_init(char *name,struct sockaddr_in src_addr,struct sockaddr_in broadcast, - struct sockaddr_in netmask,int speed_in_bits,int port,int type); -int overlay_interface_init_socket(int i,struct sockaddr_in src_addr,struct sockaddr_in broadcast, - struct sockaddr_in netmask); + int speed_in_bits,int port,int type); +int overlay_interface_init_socket(int i,struct sockaddr_in src_addr,struct sockaddr_in broadcast); int overlay_interface_discover(); int overlay_interface_discover(); long long overlay_time_until_next_tick();