diff --git a/lsif.c b/lsif.c index 0420f8fb..4e5e5b0f 100644 --- a/lsif.c +++ b/lsif.c @@ -28,6 +28,7 @@ #include "serval.h" +#include #include #include #include @@ -70,6 +71,8 @@ */ int scrapeProcNetRoute() { + if (debug & DEBUG_OVERLAYINTERFACES) INFO("called"); + FILE *f=fopen("/proc/net/route","r"); if (!f) return fprintf(stderr,"Can't read from /proc/net/route\n"); @@ -101,22 +104,26 @@ int scrapeProcNetRoute() #endif #ifdef SIOCGIFCONF -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; + +/* Not present in Linux */ +#ifndef _SIZEOF_ADDR_IFREQ +#define _SIZEOF_ADDR_IFREQ(x) sizeof(struct ifreq) +#endif + +int +lsif(void) { + char buf[8192], addrtxt[INET_ADDRSTRLEN], bcasttxt[INET_ADDRSTRLEN]; + struct ifconf ifc; + int sck, nInterfaces, ofs; + struct ifreq *ifr; + struct sockaddr_in local, broadcast; + + if (debug & DEBUG_OVERLAYINTERFACES) INFO("called"); /* Get a socket handle. */ sck = socket(PF_INET, SOCK_DGRAM, 0); if(sck < 0) { - fprintf(stderr,"Failed to gt socket handle to list addresses, errno=%d\n", - errno); + WHY_perror("socket"); return 1; } @@ -124,31 +131,91 @@ int lsif(void) ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if(ioctl(sck, SIOCGIFCONF, &ifc) < 0) { - fprintf(stderr,"Failed to read interface list\n"); + WHY_perror("ioctl(SIOCGIFCONF)"); return 1; } /* Iterate through the list of interfaces. */ - ifr = ifc.ifc_req; - nInterfaces = ifc.ifc_len / sizeof(struct ifreq); - fprintf(stderr,"Examining %d interfaces\n",nInterfaces); - for(i = 0; i < nInterfaces; i++) { - item = &ifr[i]; - - bcopy(&item->ifr_addr,&local,sizeof(local)); + nInterfaces = 0; + ofs = 0; + while (ofs < ifc.ifc_len) { + ifr = (struct ifreq *)(ifc.ifc_ifcu.ifcu_buf + ofs); + ofs += _SIZEOF_ADDR_IFREQ(*ifr); - /* get broadcast address */ - if(ioctl(sck, SIOCGIFBRDADDR, item)== 0) { - bcopy(&item->ifr_broadaddr,&broadcast,sizeof(broadcast)); - } else continue; + /* We're only interested in IPv4 addresses */ + if (ifr->ifr_ifru.ifru_addr.sa_family != AF_INET) { + if (debug & DEBUG_OVERLAYINTERFACES) INFOF("Skipping non-AF_INET address on %s", ifr->ifr_name); + continue; + } + + /* Get interface flags */ + if (ioctl(sck, SIOCGIFFLAGS, ifr) == -1) + FATAL_perror("ioctl(SIOCGIFFLAGS)"); - 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); + /* Not broadcast? Not interested.. */ + if ((ifr->ifr_ifru.ifru_flags & IFF_BROADCAST) == 0) { + if (debug & DEBUG_OVERLAYINTERFACES) INFOF("Skipping non-broadcast address on %s", ifr->ifr_name); + continue; + } + + /* Get broadcast address */ + if (ioctl(sck, SIOCGIFBRDADDR, ifr, sizeof(*ifr)) == -1) + FATAL_perror("ioctl(SIOCGIFBRDADDR)"); + + bcopy(&ifr->ifr_ifru.ifru_addr, &local, sizeof(local)); + bcopy(&ifr->ifr_ifru.ifru_broadaddr, &broadcast ,sizeof(broadcast)); + + assert(inet_ntop(AF_INET, (const void *)&local.sin_addr, addrtxt, INET_ADDRSTRLEN) != NULL); + assert(inet_ntop(AF_INET, (const void *)&broadcast.sin_addr, bcasttxt, INET_ADDRSTRLEN) != NULL); + + if (debug & DEBUG_OVERLAYINTERFACES) INFOF("name=%s addr=%s, broad=%s\n", + ifr->ifr_name, + addrtxt, bcasttxt); + overlay_interface_register(ifr->ifr_name, local, broadcast); + nInterfaces++; } + + if (debug & DEBUG_OVERLAYINTERFACES) INFOF("Examined %d interface addresses\n", nInterfaces); + close(sck); return 0; } + #endif + +#ifdef HAVE_IFADDRS_H +int doifaddrs(void) { + struct ifaddrs *ifaddr,*ifa; + int family; + + if (debug & DEBUG_OVERLAYINTERFACES) INFOF("called"); + + if (getifaddrs(&ifaddr) == -1) { + WHY_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; + switch(family) { + case AF_INET: + { + 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; + struct sockaddr_in broadcast=local; + broadcast.sin_addr.s_addr|=(~netmask.sin_addr.s_addr); + 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); + overlay_interface_register(name,local,broadcast); + + break; + } + } + } + freeifaddrs(ifaddr); + + return 0; +} +#endif + diff --git a/overlay_interface.c b/overlay_interface.c index e226aa53..e9c2299e 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -556,6 +556,8 @@ int overlay_interface_register(unsigned char *name, time_t overlay_last_interface_discover_time=0; int overlay_interface_discover() { + int have_route; + /* Don't waste too much time and effort on interface discovery, especially if we can't attach to a given interface for some reason. */ if (overlay_last_interface_discover_time>time(0)) @@ -595,45 +597,27 @@ int overlay_interface_discover() } r=r->next; } + have_route = 1; + +#ifdef HAVE_IFADDRS_H + if (have_route != 0) + have_route = doifaddrs(); +#endif #ifdef SIOCGIFCONF - lsif(); + if (have_route != 0) + have_route = lsif(); #endif #ifdef linux - scrapeProcNetRoute(); + if (have_route != 0) + have_route = scrapeProcNetRoute(); #endif -#ifdef HAVE_IFADDRS_H - struct ifaddrs *ifaddr,*ifa; - int family; + if (have_route != 0) { + FATAL("Unable to get any routing information"); + } - if (getifaddrs(&ifaddr) == -1) { - WHY_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; - switch(family) { - case AF_INET: - { - 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; - struct sockaddr_in broadcast=local; - broadcast.sin_addr.s_addr|=(~netmask.sin_addr.s_addr); - 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); - overlay_interface_register(name,local,broadcast); - - break; - } - } - } - freeifaddrs(ifaddr); -#endif - return 0; } diff --git a/serval.h b/serval.h index 7b0d9222..1b0dc42b 100755 --- a/serval.h +++ b/serval.h @@ -623,10 +623,9 @@ typedef struct overlay_interface { int sequence_number; /* XXX need recent packet buffers to support the above */ - /* Broadcast address and netmask, if known */ - /* We really only case about distinct broadcast addresses on interfaces. - Also simplifies aliases on interfaces. - struct sockaddr_in local_address; */ + /* Broadcast address and netmask, if known + We really only case about distinct broadcast addresses on interfaces. + Also simplifies aliases on interfaces. */ struct sockaddr_in broadcast_address; /* Not necessarily the real MTU, but the largest frame size we are willing to TX on this interface. @@ -1500,6 +1499,7 @@ int encodeAndDispatchRecordedAudio(int fd,int callSessionToken, int sampleBytes); int scrapeProcNetRoute(); int lsif(); +int doifaddrs(); int bufferAudioForPlayback(int codec,long long start_time,long long end_time, unsigned char *data,int dataLen); int startAudio();