static int _getifaddrs(int domain, char* buffer, size_t len, struct ifaddrs** previous) { int socket = ::socket(domain, SOCK_DGRAM, 0); if (socket < 0) return -1; FileDescriptorCloser closer(socket); // Get interfaces configuration ifconf config; config.ifc_buf = buffer; config.ifc_len = len; if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) return -1; ifreq* interfaces = (ifreq*)buffer; ifreq* end = (ifreq*)(buffer + config.ifc_len); while (interfaces < end) { struct ifaddrs* current = new(std::nothrow) ifaddrs(); if (current == NULL) { errno = B_NO_MEMORY; return -1; } // Chain this interface with the next one current->ifa_next = *previous; *previous = current; current->ifa_name = strdup(interfaces[0].ifr_name); current->ifa_addr = copy_address(interfaces[0].ifr_addr); current->ifa_netmask = NULL; current->ifa_dstaddr = NULL; current->ifa_data = NULL; ifreq request; strlcpy(request.ifr_name, interfaces[0].ifr_name, IF_NAMESIZE); if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0) current->ifa_flags = request.ifr_flags; if (ioctl(socket, SIOCGIFNETMASK, &request, sizeof(struct ifreq)) == 0) { current->ifa_netmask = copy_address(request.ifr_mask); } if (ioctl(socket, SIOCGIFDSTADDR, &request, sizeof(struct ifreq)) == 0) { current->ifa_dstaddr = copy_address(request.ifr_dstaddr); } // Move on to next interface interfaces = (ifreq*)((uint8_t*)interfaces + _SIZEOF_ADDR_IFREQ(interfaces[0])); } return 0; }
status_t BNetworkRoster::GetNextInterface(uint32* cookie, BNetworkInterface& interface) const { // TODO: think about caching the interfaces! if (cookie == NULL) return B_BAD_VALUE; // get a list of all interfaces int socket = ::socket(AF_INET, SOCK_DGRAM, 0); if (socket < 0) return errno; FileDescriptorCloser closer(socket); ifconf config; config.ifc_len = sizeof(config.ifc_value); if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) return errno; size_t count = (size_t)config.ifc_value; if (count == 0) return B_BAD_VALUE; char* buffer = (char*)malloc(count * sizeof(struct ifreq)); if (buffer == NULL) return B_NO_MEMORY; MemoryDeleter deleter(buffer); config.ifc_len = count * sizeof(struct ifreq); config.ifc_buf = buffer; if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) return errno; ifreq* interfaces = (ifreq*)buffer; ifreq* end = (ifreq*)(buffer + config.ifc_len); for (uint32 i = 0; interfaces < end; i++) { interface.SetTo(interfaces[0].ifr_name); if (i == *cookie) { (*cookie)++; return B_OK; } interfaces = (ifreq*)((uint8*)interfaces + _SIZEOF_ADDR_IFREQ(interfaces[0])); } return B_BAD_VALUE; }
static int GetIfConfig(AG_NetAddrList *nal) { #ifdef HAVE_SIOCGIFCONF enum ag_net_addr_family af; AG_NetAddr *na; char buf[4096]; struct ifconf conf; struct ifreq *ifr; int sock; AG_NetAddrListClear(nal); if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { AG_SetError("socket: %s", strerror(errno)); return (-1); } conf.ifc_len = sizeof(buf); conf.ifc_buf = (caddr_t)buf; if (ioctl(sock, SIOCGIFCONF, &conf) < 0) { AG_SetError("SIOCGIFCONF: %s", strerror(errno)); goto fail; } #if !defined(_SIZEOF_ADDR_IFREQ) #define _SIZEOF_ADDR_IFREQ sizeof #endif for (ifr = (struct ifreq *)buf; (char *)ifr < &buf[conf.ifc_len]; ifr = (struct ifreq *)((char *)ifr + _SIZEOF_ADDR_IFREQ(*ifr))) { if ((af = GetAddrFamily(ifr->ifr_addr.sa_family)) == 0) { continue; } if ((na = SockAddrToNetAddr(af, &ifr->ifr_addr)) == NULL) { goto fail; } na->port = 0; TAILQ_INSERT_TAIL(nal, na, addrs); } close(sock); return (0); fail: close(sock); return (-1); #else AG_SetError("GetIfConfig: SIOCGIFCONF unavailable"); return (-1); #endif /* !HAVE_SIOCGIFCONF */ }
int main (int argc, const char* argv[]) { // File descriptor for socket int socketfd; struct ifconf conf; char data[4096]; struct ifreq *ifr; char addrbuf[1024]; int i; printf("Opening socket..."); socketfd = socket(AF_INET, SOCK_DGRAM, 0); if (socketfd >= 0) { printf(" OK\n"); conf.ifc_len = sizeof(data); conf.ifc_buf = (caddr_t) data; if (ioctl(socketfd,SIOCGIFCONF,&conf) < 0) { perror("ioctl"); } printf("Discovering interfaces...\n"); i = 0; ifr = (struct ifreq*)data; while ((char*)ifr < data+conf.ifc_len) { switch (ifr->ifr_addr.sa_family) { case AF_INET: ++i; printf("%d. %s : %s\n", i, ifr->ifr_name, inet_ntop(ifr->ifr_addr.sa_family, &((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr, addrbuf, sizeof(addrbuf))); break; #if 0 case AF_INET6: ++i; printf("%d. %s : %s\n", i, ifr->ifr_name, inet_ntop(ifr->ifr_addr.sa_family, &((struct sockaddr_in6*)&ifr->ifr_addr)->sin6_addr, addrbuf, sizeof(addrbuf))); break; #endif } ifr = (struct ifreq*)((char*)ifr +_SIZEOF_ADDR_IFREQ(*ifr)); } close(socketfd); } else { printf(" Failed!\n"); } return 0; }
static int MPIDI_CH3U_GetIPInterface( MPIDU_Sock_ifaddr_t *ifaddr, int *found ) { char *buf_ptr, *ptr; int buf_len, buf_len_prev; int fd; MPIDU_Sock_ifaddr_t myifaddr; int nfound = 0, foundLocalhost = 0; /* We predefine the LSB and MSB localhost addresses */ unsigned int localhost = 0x0100007f; #ifdef WORDS_BIGENDIAN unsigned int MSBlocalhost = 0x7f000001; #endif if (dbg_ifname < 0) { int rc; rc = MPL_env2bool( "MPICH_DBG_IFNAME", &dbg_ifname ); if (rc != 1) dbg_ifname = 0; } fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { fprintf( stderr, "Unable to open an AF_INET socket\n" ); return 1; } /* Use MSB localhost if necessary */ #ifdef WORDS_BIGENDIAN localhost = MSBlocalhost; #endif /* * Obtain the interface information from the operating system * * Note: much of this code is borrowed from W. Richard Stevens' book * entitled "UNIX Network Programming", Volume 1, Second Edition. See * section 16.6 for details. */ buf_len = NUM_IFREQS * sizeof(struct ifreq); buf_len_prev = 0; for(;;) { struct ifconf ifconf; int rc; buf_ptr = (char *) MPIU_Malloc(buf_len); if (buf_ptr == NULL) { fprintf( stderr, "Unable to allocate %d bytes\n", buf_len ); return 1; } ifconf.ifc_buf = buf_ptr; ifconf.ifc_len = buf_len; rc = ioctl(fd, SIOCGIFCONF, &ifconf); if (rc < 0) { if (errno != EINVAL || buf_len_prev != 0) { fprintf( stderr, "Error from ioctl = %d\n", errno ); perror(" Error is: "); return 1; } } else { if (ifconf.ifc_len == buf_len_prev) { buf_len = ifconf.ifc_len; break; } buf_len_prev = ifconf.ifc_len; } MPIU_Free(buf_ptr); buf_len += NUM_IFREQS * sizeof(struct ifreq); } /* * Now that we've got the interface information, we need to run through * the interfaces and check out the ip addresses. If we find a * unique, non-lcoal host (127.0.0.1) address, return that, otherwise * return nothing. */ ptr = buf_ptr; while(ptr < buf_ptr + buf_len) { struct ifreq * ifreq; ifreq = (struct ifreq *) ptr; if (dbg_ifname) { fprintf( stdout, "%10s\t", ifreq->ifr_name ); fflush(stdout); } if (ifreq->ifr_addr.sa_family == AF_INET) { struct in_addr addr; addr = ((struct sockaddr_in *) &(ifreq->ifr_addr))->sin_addr; if (dbg_ifname) { fprintf( stdout, "IPv4 address = %08x (%s)\n", addr.s_addr, inet_ntoa( addr ) ); } if (addr.s_addr == localhost && dbg_ifname) { fprintf( stdout, "Found local host\n" ); } /* Save localhost if we find it. Let any new interface overwrite localhost. However, if we find more than one non-localhost interface, then we'll choose none for the interfaces */ if (addr.s_addr == localhost) { foundLocalhost = 1; if (nfound == 0) { myifaddr.type = AF_INET; myifaddr.len = 4; MPIU_Memcpy( myifaddr.ifaddr, &addr.s_addr, 4 ); } } else { nfound++; myifaddr.type = AF_INET; myifaddr.len = 4; MPIU_Memcpy( myifaddr.ifaddr, &addr.s_addr, 4 ); } } else { if (dbg_ifname) { fprintf( stdout, "\n" ); } } /* * Increment pointer to the next ifreq; some adjustment may be * required if the address is an IPv6 address */ /* This is needed for MAX OSX */ #ifdef _SIZEOF_ADDR_IFREQ ptr += _SIZEOF_ADDR_IFREQ(*ifreq); #else ptr += sizeof(struct ifreq); # if defined(AF_INET6) { if (ifreq->ifr_addr.sa_family == AF_INET6) { ptr += sizeof(struct sockaddr_in6) - sizeof(struct sockaddr); } } # endif #endif } MPIU_Free(buf_ptr); close(fd); /* If we found a unique address, use that */ if (nfound == 1 || (nfound == 0 && foundLocalhost == 1)) { *ifaddr = myifaddr; *found = 1; } else { *found = 0; } return 0; }
/* * First, we find all shaper devices and down them. Then we * down all real interfaces. This is because the comment in the * shaper driver says "if you down the shaper device before the * attached inerface your computer will follow". */ int ifdown(void) { char ifr_buf[sizeof(struct ifreq) * MAX_IFS]; char *ifr_end; struct ifconf ifc; int fd; int shaper; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "ifdown: "); perror("socket"); return -1; } ifc.ifc_len = sizeof(ifr_buf); ifc.ifc_buf = ifr_buf; if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { fprintf(stderr, "ifdown: "); perror("SIOCGIFCONF"); close(fd); return -1; } ifr_end = ifr_buf + ifc.ifc_len; for (shaper = 1; shaper >= 0; shaper--) { char *ifr_next = ifr_buf; while (ifr_next < ifr_end) { struct ifreq *ifr; int flags; ifr = (struct ifreq *)ifr_next; ifr_next += _SIZEOF_ADDR_IFREQ(*ifr); if ((strncmp(ifr->ifr_name, "shaper", 6) == 0) != shaper) continue; if (strncmp(ifr->ifr_name, "lo", 2) == 0) continue; if (strchr(ifr->ifr_name, ':') != NULL) continue; /* Read interface flags */ if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0) { fprintf(stderr, "ifdown: shutdown "); perror(ifr->ifr_name); continue; } /* * Expected in <net/if.h> according to * "UNIX Network Programming". */ #ifdef ifr_flagshigh flags = (ifr->ifr_flags & 0xffff) | (ifr->ifr_flagshigh << 16); #else flags = ifr->ifr_flags; #endif if (flags & IFF_UP) { flags &= ~(IFF_UP); #ifdef ifr_flagshigh ifr->ifr_flags = flags & 0xffff; ifr->ifr_flagshigh = flags >> 16; #else ifr->ifr_flags = flags; #endif if (ioctl(fd, SIOCSIFFLAGS, ifr) < 0) { fprintf(stderr, "ifdown: shutdown "); perror(ifr->ifr_name); } } } }
/* for when all other options fail, as can happen on Android, if the permissions for the socket-based method are broken. Down side is that it while it gets the interface name and broadcast, it doesn't get the local address for that interface. */ int scrapeProcNetRoute() { if (debug & DEBUG_OVERLAYINTERFACES) DEBUG("called"); FILE *f=fopen("/proc/net/route","r"); if (!f) return WHY_perror("fopen(\"/proc/net/route\")"); char line[1024],name[1024],dest[1024],mask[1024]; /* skip header line */ line[0]=0; fgets(line,1024,f); line[0]=0; fgets(line,1024,f); while(line[0]) { int r; if ((r=sscanf(line,"%s %s %*s %*s %*s %*s %*s %s",name,dest,mask))==3) { struct in_addr addr = {.s_addr=strtol(dest,NULL,16)}; struct in_addr netmask = {.s_addr=strtol(mask,NULL,16)}; overlay_interface_register(name,addr,netmask); } line[0]=0; fgets(line,1024,f); } fclose(f); return 0; } #endif #ifdef SIOCGIFCONF /* Not present in Linux */ #ifndef _SIZEOF_ADDR_IFREQ #define _SIZEOF_ADDR_IFREQ(x) sizeof(struct ifreq) #endif int lsif(void) { char buf[8192]; struct ifconf ifc; int sck, nInterfaces, ofs; struct ifreq *ifr; struct in_addr addr, netmask; if (debug & DEBUG_OVERLAYINTERFACES) DEBUG("called"); /* Get a socket handle. */ sck = socket(PF_INET, SOCK_DGRAM, 0); if(sck < 0) { WHY_perror("socket"); return 1; } /* Query available interfaces. */ ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if(ioctl(sck, SIOCGIFCONF, &ifc) < 0) { WHY_perror("ioctl(SIOCGIFCONF)"); close(sck); return 1; } /* Iterate through the list of interfaces. */ nInterfaces = 0; ofs = 0; while (ofs < ifc.ifc_len && ofs < sizeof(buf)) { ifr = (struct ifreq *)(ifc.ifc_ifcu.ifcu_buf + ofs); ofs += _SIZEOF_ADDR_IFREQ(*ifr); /* We're only interested in IPv4 addresses */ if (ifr->ifr_ifru.ifru_addr.sa_family != AF_INET) { if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Skipping non-AF_INET address on %s", ifr->ifr_name); continue; } addr = ((struct sockaddr_in *)&ifr->ifr_ifru.ifru_addr)->sin_addr; /* Get interface flags */ if (ioctl(sck, SIOCGIFFLAGS, ifr) == -1) FATAL_perror("ioctl(SIOCGIFFLAGS)"); /* Not broadcast? Not interested.. */ if ((ifr->ifr_ifru.ifru_flags & IFF_BROADCAST) == 0) { if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Skipping non-broadcast address on %s", ifr->ifr_name); continue; } /* Get netmask */ if (ioctl(sck, SIOCGIFNETMASK, ifr, sizeof(*ifr)) != 0) { WHY_perror("ioctl(SIOCGIFNETMASK)"); continue; } netmask = ((struct sockaddr_in *)&ifr->ifr_ifru.ifru_addr)->sin_addr; overlay_interface_register(ifr->ifr_name, addr, netmask); nInterfaces++; } if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Examined %d interface addresses", nInterfaces); close(sck); return 0; } #endif #ifdef HAVE_IFADDRS_H int doifaddrs(void) { struct ifaddrs *ifaddr, *ifa; char *name; struct in_addr addr, netmask; if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("called"); if (getifaddrs(&ifaddr) == -1) return WHY_perror("getifaddr()"); for (ifa = ifaddr; ifa != NULL ; ifa = ifa->ifa_next) { /* We're only interested in IPv4 addresses */ if (ifa->ifa_addr->sa_family != AF_INET) { if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Skipping non-AF_INET address on %s", ifa->ifa_name); continue; } /* Not broadcast? Not interested.. */ if ((ifa->ifa_flags & IFF_BROADCAST) == 0) { if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Skipping non-broadcast address on %s", ifa->ifa_name); continue; } name = ifa->ifa_name; addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; netmask = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; overlay_interface_register(name, addr, netmask); } freeifaddrs(ifaddr); return 0; }
/* this function returns the total number of interface addresses ** the buffer has to be passed in by the caller */ #else /* UKERNEL indirectly, on DARWIN or XBSD */ static int rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks) { int s; int i, len, count = 0; struct ifconf ifc; struct ifreq ifs[NIFS], *ifr; struct sockaddr_in *a; /* can't ever be AFS_DARWIN_ENV or AFS_XBSD_ENV, no? */ #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) char *cp, *cplim, *cpnext; /* used only for AIX 41 */ #endif s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) return 0; ifc.ifc_len = sizeof(ifs); ifc.ifc_buf = (caddr_t) ifs; i = ioctl(s, SIOCGIFCONF, &ifc); if (i < 0) return 0; len = ifc.ifc_len / sizeof(struct ifreq); if (len > NIFS) len = NIFS; #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) if (ifc.ifc_len > sizeof(ifs)) /* safety check */ ifc.ifc_len = sizeof(ifs); for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len; cp < cplim; #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) cp += _SIZEOF_ADDR_IFREQ(*ifr) #else #ifdef AFS_AIX51_ENV cp = cpnext #else cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a)) #endif #endif ) #else for (i = 0; i < len; ++i) #endif { #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) ifr = (struct ifreq *)cp; #else ifr = &ifs[i]; #endif a = (struct sockaddr_in *)&ifr->ifr_addr; #ifdef AFS_AIX51_ENV cpnext = cp + sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a)); #endif if (a->sin_family != AF_INET) continue; if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) { perror("SIOCGIFFLAGS"); continue; /* ignore this address */ } if (a->sin_addr.s_addr != 0) { if (!loopbacks) { if (a->sin_addr.s_addr == htonl(0x7f000001)) continue; /* skip loopback address as well. */ } else { if (ifr->ifr_flags & IFF_LOOPBACK) continue; /* skip aliased loopbacks as well. */ } if (count >= maxSize) /* no more space */ dpf(("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr)); else buffer[count++] = a->sin_addr.s_addr; } } close(s); return count; }
//***************************************************************************** // NETADDRESS_s NETWORK_GetLocalAddress( void ) { char szBuffer[512]; struct sockaddr_in SocketAddress; NETADDRESS_s Address; int iNameLength; #ifndef __WINE__ gethostname( szBuffer, 512 ); #endif szBuffer[512-1] = 0; // Convert the host name to our local bool stringToAddress = NETWORK_StringToAddress( szBuffer, &Address ); iNameLength = sizeof( SocketAddress ); #ifndef WIN32 if ( getsockname ( g_NetworkSocket, (struct sockaddr *)&SocketAddress, (socklen_t *)&iNameLength) == -1 ) #else if ( getsockname ( g_NetworkSocket, (struct sockaddr *)&SocketAddress, &iNameLength ) == -1 ) #endif { Printf( "NETWORK_GetLocalAddress: Error getting socket name: %s", strerror( errno )); } #ifdef unix // [BB] The "gethostname -> gethostbyname" trick didn't reveal the local IP. // Now we need to resort to something more complicated. if ( stringToAddress == false ); { #ifndef __FreeBSD__ unsigned char *u; int size = 1; struct ifreq *ifr; struct ifconf ifc; struct sockaddr_in sa; ifc.ifc_len = IFRSIZE; ifc.ifc_req = NULL; do { ++size; /* realloc buffer size until no overflow occurs */ if (NULL == (ifc.ifc_req = (ifreq*)realloc(ifc.ifc_req, IFRSIZE))) { fprintf(stderr, "Out of memory.\n"); exit(EXIT_FAILURE); } ifc.ifc_len = IFRSIZE; if (ioctl(g_NetworkSocket, SIOCGIFCONF, &ifc)) { perror("ioctl SIOCFIFCONF"); exit(EXIT_FAILURE); } } while (IFRSIZE <= ifc.ifc_len); ifr = ifc.ifc_req; for (;(char *) ifr < (char *) ifc.ifc_req + ifc.ifc_len; ++ifr) { if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data) { continue; /* duplicate, skip it */ } if (ioctl(g_NetworkSocket, SIOCGIFFLAGS, ifr)) { continue; /* failed to get flags, skip it */ } Printf("Found interface %s", ifr->ifr_name); Printf(" with IP address: %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data))); *(int *)&Address.abIP = *(int *)&inaddrr(ifr_addr.sa_data); if ( Address.abIP[0] != 127 ) { Printf ( "Using IP address of interface %s as local address.\n", ifr->ifr_name ); break; } } if ( ifc.ifc_req != NULL ) free ( ifc.ifc_req ); #else struct ifreq *ifr; struct ifconf ifc; bzero(&ifc, sizeof(ifc)); unsigned int n = 1; struct ifreq *lifr; ifr = (ifreq*)calloc( ifc.ifc_len, sizeof(*ifr) ); do { n *= 2; ifr = (ifreq*)realloc( ifr, PAGE_SIZE * n ); bzero( ifr, PAGE_SIZE * n ); ifc.ifc_req = ifr; ifc.ifc_len = n * PAGE_SIZE; } while( ( ioctl( g_NetworkSocket, SIOCGIFCONF, &ifc ) == -1 ) || ( ifc.ifc_len >= ( (n-1) * PAGE_SIZE)) ); lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; while (ifr < lifr) { struct sockaddr *sa = &ifr->ifr_ifru.ifru_addr; if( AF_INET == sa->sa_family ) { struct sockaddr_in dummysa; in_addr inAddr = *(struct in_addr *) &ifr->ifr_addr.sa_data[sizeof dummysa.sin_port]; Printf("Found interface %s", ifr->ifr_name); Printf(" with IP address: %s\n", inet_ntoa(inAddr)); *(int *)&Address.abIP = *(int *)&inAddr; if ( Address.abIP[0] != 127 ) { Printf ( "Using IP address of interface %s as local address.\n", ifr->ifr_name ); break; } } ifr = (struct ifreq *)(((char *)ifr) + _SIZEOF_ADDR_IFREQ(*ifr)); } #endif } #endif Address.usPort = SocketAddress.sin_port; return ( Address ); }
int lsif(void) { char buf[8192]; struct ifconf ifc; int sck; struct ifreq *ifr; struct in_addr netmask; struct socket_address addr, broadcast; bzero(&addr, sizeof(addr)); bzero(&broadcast, sizeof(broadcast)); if (config.debug.overlayinterfaces) DEBUG("called"); /* Get a socket handle. */ sck = socket(PF_INET, SOCK_DGRAM, 0); if(sck < 0) { WHY_perror("socket"); return 1; } /* Query available interfaces. */ ifc.ifc_len = sizeof buf; ifc.ifc_buf = buf; if(ioctl(sck, SIOCGIFCONF, &ifc) < 0) { WHY_perror("ioctl(SIOCGIFCONF)"); close(sck); return 1; } broadcast.addrlen = sizeof(addr.inet); broadcast.inet.sin_family = AF_INET; /* Iterate through the list of interfaces. */ unsigned nInterfaces = 0; unsigned ofs = 0; while (ofs < (unsigned)ifc.ifc_len && ofs < sizeof buf) { ifr = (struct ifreq *)(ifc.ifc_ifcu.ifcu_buf + ofs); ofs += _SIZEOF_ADDR_IFREQ(*ifr); /* We're only interested in IPv4 addresses */ if (ifr->ifr_ifru.ifru_addr.sa_family != AF_INET) { if (config.debug.overlayinterfaces) DEBUGF("Skipping non-AF_INET address on %s", ifr->ifr_name); continue; } addr.addrlen = sizeof(addr.inet); bcopy(&ifr->ifr_ifru.ifru_addr, &addr.addr, addr.addrlen); /* Get interface flags */ if (ioctl(sck, SIOCGIFFLAGS, ifr) == -1) FATAL_perror("ioctl(SIOCGIFFLAGS)"); /* Not broadcast? Not interested.. */ if ((ifr->ifr_ifru.ifru_flags & IFF_BROADCAST) == 0) { if (config.debug.overlayinterfaces) DEBUGF("Skipping non-broadcast address on %s", ifr->ifr_name); continue; } /* Get netmask */ if (ioctl(sck, SIOCGIFNETMASK, ifr, sizeof(*ifr)) != 0) { WHY_perror("ioctl(SIOCGIFNETMASK)"); continue; } netmask = ((struct sockaddr_in *)&ifr->ifr_ifru.ifru_addr)->sin_addr; broadcast.inet.sin_addr.s_addr=addr.inet.sin_addr.s_addr | ~netmask.s_addr; overlay_interface_register(ifr->ifr_name, &addr, &broadcast); nInterfaces++; } if (config.debug.overlayinterfaces) DEBUGF("Examined %u interface addresses", nInterfaces); close(sck); return 0; }
/*! Returns a chained list of all interfaces. We follow BSD semantics, and only return one entry per interface, not per address; since this is mainly used by NetBSD's netresolv, it's probably what it expects. */ int getifaddrs(struct ifaddrs** _ifaddrs) { if (_ifaddrs == NULL) { errno = B_BAD_VALUE; return -1; } int socket = ::socket(AF_INET, SOCK_DGRAM, 0); if (socket < 0) return -1; FileDescriptorCloser closer(socket); // Get interface count ifconf config; config.ifc_len = sizeof(config.ifc_value); if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) return -1; size_t count = (size_t)config.ifc_value; if (count == 0) { errno = B_BAD_VALUE; return -1; } // Allocate a buffer for ifreqs for all interfaces char* buffer = (char*)malloc(count * sizeof(struct ifreq)); if (buffer == NULL) { errno = B_NO_MEMORY; return -1; } MemoryDeleter deleter(buffer); // Get interfaces configuration config.ifc_len = count * sizeof(struct ifreq); config.ifc_buf = buffer; if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) return -1; ifreq* interfaces = (ifreq*)buffer; ifreq* end = (ifreq*)(buffer + config.ifc_len); struct ifaddrs* previous = NULL; for (uint32_t i = 0; interfaces < end; i++) { struct ifaddrs* current = new(std::nothrow) ifaddrs(); if (current == NULL) { freeifaddrs(previous); errno = B_NO_MEMORY; return -1; } // Chain this interface with the next one current->ifa_next = previous; previous = current; current->ifa_name = strdup(interfaces[0].ifr_name); current->ifa_addr = copy_address(interfaces[0].ifr_addr); current->ifa_netmask = NULL; current->ifa_dstaddr = NULL; current->ifa_data = NULL; ifreq request; strlcpy(request.ifr_name, interfaces[0].ifr_name, IF_NAMESIZE); if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0) current->ifa_flags = request.ifr_flags; if (ioctl(socket, SIOCGIFNETMASK, &request, sizeof(struct ifreq)) == 0) { current->ifa_netmask = copy_address(request.ifr_mask); } if (ioctl(socket, SIOCGIFDSTADDR, &request, sizeof(struct ifreq)) == 0) { current->ifa_dstaddr = copy_address(request.ifr_dstaddr); } // Move on to next interface interfaces = (ifreq*)((uint8_t*)interfaces + _SIZEOF_ADDR_IFREQ(interfaces[0])); } *_ifaddrs = previous; return 0; }
/* * SDL_netx.cpp * * Copyright (c) 2001 Woody Zenfell, III. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * SDL_netx is intended to provide a few capabilities (like broadcast) that * SDL_net seems like it ought to support (but doesn't). * * Created by Woody Zenfell, III on Mon Sep 24 2001. */ #include "config.h" #if !defined(DISABLE_NETWORKING) #ifndef __MWERKS__ #include <sys/types.h> #if defined(WIN32) # include <winsock.h> #elif defined(__BEOS__) # include <sys/socket.h> # include <netinet/in.h> #else # include <unistd.h> # include <sys/socket.h> # include <netinet/in.h> # include <net/if.h> # if defined(__svr4__) # define BSD_COMP 1 // This is required to get SIOC* under Solaris # endif # include <sys/ioctl.h> #endif #endif #include "SDL_netx.h" // PREPROCESSOR MACROS // VC++6 chokes if I don't explicitly cast int* to const char* in setsockopt(). #ifdef WIN32 # define MY_TYPE_CAST (const char*) #else # define MY_TYPE_CAST #endif // Win32 allows 255.255.255.255 as broadcast, much easier #if !defined(WIN32) && !defined(__BEOS__) && !(defined(mac) /*&& !defined(TARGET_API_MAC_CARBON)*/) // FILE-LOCAL (static) CONSTANTS static const int kMaxNumBroadcastAddresses = 8; static const int kIFConfigBufferSize = 1024; // in bytes // FILE-LOCAL (static) STORAGE static bool sCollectedBroadcastAddresses = false; // set to true if we've tried static int sNumberOfBroadcastAddresses = 0; // set to number of valid addresses static long sBroadcastAddresses[kMaxNumBroadcastAddresses]; // collection of addresses to try // note that we only store the host-part since the packet the user wants to broadcast will specify the port. // FILE-LOCAL (static) FUNCTIONS static int SDLNetxint_CollectBroadcastAddresses(UDPsocket inSocket); #endif //////// START OF CODE //////// // EXTERNALLY-VISIBLE FUNCTIONS int SDLNetx_EnableBroadcast(UDPsocket inSocket) { #if !defined(WIN32) && !defined(__BEOS__) && !defined(mac) && !defined(__MWERKS__)/*&& !defined(TARGET_API_MAC_CARBON))*/ if(!sCollectedBroadcastAddresses) SDLNetxint_CollectBroadcastAddresses(inSocket); #endif // This works in Mac OS X and probably other BSD's... and now on Win32 (Win 98, anyway). // May need modification for Linux, etc. // Absolutely needs modification for "classic" Mac OS (i.e. Open Transport) // XXX: this depends on intimate carnal knowledge of the SDL_net struct _UDPsocket // if it changes that structure, we are hosed. (this works with 1.2.2) int theSocketFD = ((int*)inSocket)[1]; // Sanity check if(theSocketFD < 0) return 0; #if defined(__BEOS__) || defined(__MWERKS__) // Neither possible nor necessary return 0; #else // Try to enable broadcast option on underlying socket int theOnValue = 1; int theResult = setsockopt(theSocketFD, SOL_SOCKET, SO_BROADCAST, MY_TYPE_CAST &theOnValue, sizeof(theOnValue)); if(theResult < 0) return 0; else return theOnValue; #endif } int SDLNetx_DisableBroadcast(UDPsocket inSocket) { // This works in Mac OS X and probably other BSD's... and now in Win32 (Win 98, at least). // Might need modification for Linux, etc. // Absolutely needs modification for "classic" Mac OS (i.e. Open Transport) // XXX: this depends on intimate carnal knowledge of the SDL_net struct _UDPsocket // if it changes that structure, we are hosed. int theSocketFD = ((int*)inSocket)[1]; // Sanity check if(theSocketFD < 0) return 0; #if defined(__BEOS__) || defined(__MWERKS__) // Neither possible nor necessary return 0; #else // Try to disable broadcast option on underlying socket int theOffValue = 0; int theResult = setsockopt(theSocketFD, SOL_SOCKET, SO_BROADCAST, MY_TYPE_CAST &theOffValue, sizeof(theOffValue)); if(theResult < 0) return 0; else return (theOffValue == 0) ? 1 : 0; #endif } // see simpler function below for Win32 #if !defined(WIN32) && !defined(__BEOS__) && !(defined(mac) /*&& !defined(TARGET_API_MAC_CARBON)*/) int SDLNetx_UDP_Broadcast(UDPsocket inSocket, UDPpacket* inPacket) { int theCountOfSuccessfulSends = 0; // We re-use the packet's destination-address "host" part, but don't want to trample it... so we save it Uint32 theSavedHostAddress = inPacket->address.host; // Write each broadcast address into the packet, in turn, and send it off. for(int i = 0; i < sNumberOfBroadcastAddresses; i++) { inPacket->address.host = sBroadcastAddresses[i]; if(SDLNet_UDP_Send(inSocket, -1, inPacket) == 1) theCountOfSuccessfulSends++; } // for each broadcast address // restore the saved destination host-part inPacket->address.host = theSavedHostAddress; return theCountOfSuccessfulSends; } #else // Win32 (at least, Win 98) seems to accept 255.255.255.255 as a valid broadcast address. // I'll live with that for now. // Also doing that for the BeOS and Mac Classic int SDLNetx_UDP_Broadcast(UDPsocket inSocket, UDPpacket* inPacket) { Uint32 theSavedHostAddress = inPacket->address.host; inPacket->address.host = 0xffffffff; int theResult = SDLNet_UDP_Send(inSocket, -1, inPacket); inPacket->address.host = theSavedHostAddress; return theResult; } #endif // INTERNAL (static) FUNCTIONS #if !defined(WIN32) && !defined(__BEOS__) && !defined(mac) && !defined(__MWERKS__)/*&& !defined(TARGET_API_MAC_CARBON))*/ int SDLNetxint_CollectBroadcastAddresses(UDPsocket inSocket) { // Win or lose, we played the game. sCollectedBroadcastAddresses = true; // This works in Mac OS X and probably other BSD's. // I have no idea whether this is the right way or the best way to do this. // Probably needs modification for Win32, Linux, etc. // Absolutely needs modification for "classic" Mac OS (i.e. Open Transport) // XXX: this depends on intimate carnal knowledge of the SDL_net struct _UDPsocket // if it changes that structure, we are hosed. int theSocketFD = ((int*)inSocket)[1]; // Sanity check if(theSocketFD < 0) return 0; // Ask the system for interfaces and their addresses char theRequestBuffer[kIFConfigBufferSize]; struct ifconf theConfigRequest; int theOffset = 0; theConfigRequest.ifc_len = sizeof(theRequestBuffer); theConfigRequest.ifc_buf = theRequestBuffer; int theResult = ioctl(theSocketFD, SIOCGIFCONF, &theConfigRequest); if(theResult < 0) return 0; // theOffset marches through the return buffer to help us find subsequent entries // (entries can have various sizes, but always >= sizeof(struct ifreq)... IP entries have minimum size.) // The while() condition avoids misbehaving in case there's only a partial entry at the end // of the buffer. while(theConfigRequest.ifc_len - theOffset >= int(sizeof(struct ifreq))) { // Point at the next result struct ifreq* theReq = (struct ifreq*) &(theRequestBuffer[theOffset]); // Make sure it's an entry for IP (not AppleTalk, ARP, etc.) if(theReq->ifr_addr.sa_family == AF_INET) { // Now we may interpret the address as an IP address. struct sockaddr_in* theInetAddr = (struct sockaddr_in*) &theReq->ifr_addr; // Who cares about the actual address? Turn this around into a request for the interface's // broadcast address. theResult = ioctl(theSocketFD, SIOCGIFBRDADDR, theReq); if(theResult >= 0) { // we retrieved an actual broadcast address for IP networking... assume it's good. // make sure there's room to store another broadcast address... if(sNumberOfBroadcastAddresses < kMaxNumBroadcastAddresses) { // We can still use theInetAddr, since it's just a reference to actual storage sBroadcastAddresses[sNumberOfBroadcastAddresses] = theInetAddr->sin_addr.s_addr; sNumberOfBroadcastAddresses++; } // room for address in array } // broadcast-address lookup succeeded } // entry is IP // Increment theOffset to point at the next entry. // _SIZEOF_ADDR_IFREQ() is provided in Mac OS X. It accounts for entries whose address families // use long addresses. Use theReq->ifr_addr.sa_len (and add the overhead for the rest of *theReq) // if it's not provided for you. #ifdef _SIZEOF_ADDR_IFREQ theOffset += _SIZEOF_ADDR_IFREQ(*theReq); #else theOffset += sizeof(ifreq); #endif } // while more entries return sNumberOfBroadcastAddresses; }
main() { #ifdef SIOCRPHYSADDR struct ifdevea req = { 0 }; #endif struct ifconf list = { 0 }; int s = { 0 }; int i = { 0 }; union { struct ifreq a; char b[4096]; } buf; struct ifreq* p = { 0 }; #ifdef HAS_GETIFADDRS struct ifaddrs* if1; struct ifaddrs* if2; #endif memset(&buf, 0, sizeof(buf)); s = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC); if (s < 0) { perror("socket"); exit(1); } #ifdef HAS_GETIFADDRS getifaddrs(&if1); for (if2 = if1; if2; if2 = if2->ifa_next) { if (if2->ifa_addr->sa_family == AF_LINK) { struct sockaddr_dl* dl = (struct sockaddr_dl*)if2->ifa_addr; unsigned char* mac = (unsigned char*)LLADDR(dl); if (dl->sdl_alen == 6) /* 48 bits */ { printf("%s %02X:%02X:%02X:%02X:%02X:%02X\n", if2->ifa_name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } else if (dl->sdl_alen == 8) /* 64 bits IP over firewire */ { printf("%s %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", if2->ifa_name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mac[6], mac[7]); } breakpoint(); } } freeifaddrs(if1); #endif list.ifc_len = sizeof(buf); list.ifc_req = &buf.a; if (-1 == ioctl(s, SIOCGIFCONF, &list)) {perror("SIOCGIFCONF"); exit(2);} printf("list.ifc_len %d\n", list.ifc_len); for (i = 0; i < list.ifc_len; i += _SIZEOF_ADDR_IFREQ(*p)) { p = (struct ifreq*)&buf.b[i]; printf("buf[%d] = %s\n", i, p->ifr_name); #ifdef SIOCRPHYSADDR strcpy(req.ifr_name, p->ifr_name); if (-1 == ioctl(s, SIOCRPHYSADDR, &req)) { perror(" SIOCRPHYSADDR"); } else { printf(" Device address %02x%02x%02x%02x%02x%02x\n", req.default_pa[0], req.default_pa[1], req.default_pa[2], req.default_pa[3], req.default_pa[4], req.default_pa[5]);} } #endif }
extern int/*bool*/ NcbiGetHostIfConfEx(SNcbiIfConf* c, int s, int flag) { unsigned int a, b; struct ifconf ifc; struct ifreq ifr; char *buf, *p; size_t size; size_t mtu; int n, m; errno = 0; if (!c || s < 0) return 0; for (size = 1024; ; size += 1024) { if (!(buf = (char*) calloc(1, size))) return 0; ifc.ifc_len = (SOCK_socklen_t) size; ifc.ifc_buf = buf; if ((n = ioctl(s, SIOCGIFCONF, &ifc)) >= 0 && ifc.ifc_len + 2*sizeof(ifr) < size) { break; } free(buf); if (n < 0 && errno != EINVAL) return 0; if (size > 100000) { errno = E2BIG; return 0; } } mtu = 0; size = 0; errno = 0; n = m = 0; a = INADDR_NONE; /* Host byte order */ b = INADDR_ANY; /* Host byte order */ for (p = buf; p < buf + ifc.ifc_len; p += size) { unsigned int ip; memcpy(&ifr, p, sizeof(ifr)); #ifdef _SIZEOF_ADDR_IFREQ size = _SIZEOF_ADDR_IFREQ(ifr); #else size = sizeof(ifr); #endif /*_SIZEOF_ADDR_IFREQ*/ if (ioctl(s, SIOCGIFADDR, &ifr) < 0) continue; n++; if (ifr.ifr_addr.sa_family != AF_INET) { m++; continue; } ip = ntohl(((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr); if (ip == INADDR_NONE || ip == INADDR_LOOPBACK) { if (ip != INADDR_LOOPBACK) m++; else a = ip; continue; } if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) continue; if ((ifr.ifr_flags & IFF_LOOPBACK) || #ifdef IFF_PRIVATE (ifr.ifr_flags & IFF_PRIVATE) || #endif /*IFF_PRIVATE*/ !(ifr.ifr_flags & IFF_UP) || !(ifr.ifr_flags & IFF_RUNNING) || (flag && !(ifr.ifr_flags & flag))) continue; if (ioctl(s, SIOCGIFNETMASK, &ifr) < 0) continue; b = ntohl(((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr); if (b != INADDR_ANY) { a = ip; #ifdef SIOCGIFMTU if (ioctl(s, SIOCGIFMTU, &ifr) >= 0) mtu = (size_t)(ifr.ifr_mtu > 0 ? ifr.ifr_mtu : 0); #endif /*SIOCGIFMTU*/ break; } } free(buf); c->address = htonl(a); c->netmask = htonl(b); c->broadcast = ((a == INADDR_NONE || b == INADDR_ANY) ? 0 : (c->address & c->netmask) | ~c->netmask); c->nifs = n; c->sifs = m; c->mtu = mtu; return 1; }
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count) { int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == HDHOMERUN_SOCK_INVALID) { return -1; } struct ifconf ifc; size_t ifreq_buffer_size = 1024; while (1) { ifc.ifc_len = ifreq_buffer_size; ifc.ifc_buf = (char *)malloc(ifreq_buffer_size); if (!ifc.ifc_buf) { close(sock); return -1; } memset(ifc.ifc_buf, 0, ifreq_buffer_size); if (ioctl(sock, SIOCGIFCONF, &ifc) != 0) { free(ifc.ifc_buf); close(sock); return -1; } if (ifc.ifc_len < ifreq_buffer_size) { break; } free(ifc.ifc_buf); ifreq_buffer_size += 1024; } char *ptr = ifc.ifc_buf; char *end = ifc.ifc_buf + ifc.ifc_len; int count = 0; while (ptr < end) { struct ifreq *ifr = (struct ifreq *)ptr; ptr += _SIZEOF_ADDR_IFREQ(*ifr); /* Flags. */ if (ioctl(sock, SIOCGIFFLAGS, ifr) != 0) { continue; } if ((ifr->ifr_flags & IFF_UP) == 0) { continue; } if ((ifr->ifr_flags & IFF_RUNNING) == 0) { continue; } /* Local IP address. */ if (ioctl(sock, SIOCGIFADDR, ifr) != 0) { continue; } struct sockaddr_in *ip_addr_in = (struct sockaddr_in *)&(ifr->ifr_addr); uint32_t ip_addr = ntohl(ip_addr_in->sin_addr.s_addr); if (ip_addr == 0) { continue; } /* Subnet mask. */ if (ioctl(sock, SIOCGIFNETMASK, ifr) != 0) { continue; } struct sockaddr_in *subnet_mask_in = (struct sockaddr_in *)&(ifr->ifr_addr); uint32_t subnet_mask = ntohl(subnet_mask_in->sin_addr.s_addr); /* Report. */ if (count < max_count) { struct hdhomerun_local_ip_info_t *ip_info = &ip_info_list[count]; ip_info->ip_addr = ip_addr; ip_info->subnet_mask = subnet_mask; } count++; } free(ifc.ifc_buf); close(sock); return count; }
int SDLNet_GetLocalAddresses(IPaddress *addresses, int maxcount) { int count = 0; #ifdef SIOCGIFCONF /* Defined on Mac OS X */ #ifndef _SIZEOF_ADDR_IFREQ #define _SIZEOF_ADDR_IFREQ sizeof #endif SOCKET sock; struct ifconf conf; char data[4096]; struct ifreq *ifr; struct sockaddr_in *sock_addr; sock = socket(AF_INET, SOCK_DGRAM, 0); if ( sock == INVALID_SOCKET ) { return 0; } conf.ifc_len = sizeof(data); conf.ifc_buf = (caddr_t) data; if ( ioctl(sock, SIOCGIFCONF, &conf) < 0 ) { closesocket(sock); return 0; } ifr = (struct ifreq*)data; while ((char*)ifr < data+conf.ifc_len) { if (ifr->ifr_addr.sa_family == AF_INET) { if (count < maxcount) { sock_addr = (struct sockaddr_in*)&ifr->ifr_addr; addresses[count].host = sock_addr->sin_addr.s_addr; addresses[count].port = sock_addr->sin_port; } ++count; } ifr = (struct ifreq*)((char*)ifr + _SIZEOF_ADDR_IFREQ(*ifr)); } closesocket(sock); #elif defined(__WIN32__) PIP_ADAPTER_INFO pAdapterInfo; PIP_ADAPTER_INFO pAdapter; PIP_ADDR_STRING pAddress; unsigned long dwRetVal = 0; ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO); pAdapterInfo = (IP_ADAPTER_INFO *) SDL_malloc(sizeof (IP_ADAPTER_INFO)); if (pAdapterInfo == NULL) { return 0; } if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == ERROR_BUFFER_OVERFLOW) { pAdapterInfo = (IP_ADAPTER_INFO *) SDL_realloc(pAdapterInfo, ulOutBufLen); if (pAdapterInfo == NULL) { return 0; } dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); } if (dwRetVal == NO_ERROR) { for (pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next) { for (pAddress = &pAdapterInfo->IpAddressList; pAddress; pAddress = pAddress->Next) { if (count < maxcount) { addresses[count].host = inet_addr(pAddress->IpAddress.String); addresses[count].port = 0; } ++count; } } } SDL_free(pAdapterInfo); #endif return count; }
struct raw_iface *find_raw_ifaces4(void) { static const int on = TRUE; /* by-reference parameter; constant, we hope */ int j; /* index into buf */ struct ifconf ifconf; struct ifreq *buf = NULL; /* for list of interfaces -- arbitrary limit */ struct ifreq *bp; /* cursor into buf */ struct raw_iface *rifaces = NULL; int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ /* * Current upper bound on number of interfaces. * Tricky: because this is a static, we won't have to start from * 64 in subsequent calls. */ static int num = 64; /* number of interfaces */ /* get list of interfaces with assigned IPv4 addresses from system */ if (master_sock == -1) exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0) exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); /* bind the socket */ { ip_address any; happy(anyaddr(AF_INET, &any)); setportof(htons(pluto_port), &any); if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); } /* a million interfaces is probably the maximum, ever... */ for (; num < (1024 * 1024); num *= 2) { /* Get num local interfaces. See netdevice(7). */ ifconf.ifc_len = num * sizeof(struct ifreq); buf = realloc(buf, ifconf.ifc_len); if (buf == NULL) { exit_log_errno((e, "realloc of %d in find_raw_ifaces4()", ifconf.ifc_len)); } memset(buf, 0xDF, ifconf.ifc_len); /* stomp */ ifconf.ifc_buf = (void *) buf; if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); /* if we got back less than we asked for, we have them all */ if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num)) break; } /* Add an entry to rifaces for each interesting interface. On Apple, the size of struct ifreq depends on the contents of the union. See if.h */ for (bp = buf, j = 0; bp < (unsigned char *)buf + (size_t)ifconf.ifc_len; bp = (struct ifreq *) ((unsigned char *)bp +_SIZEOF_ADDR_IFREQ(*bp)), j++) { struct raw_iface ri; const struct sockaddr_in *rs = (struct sockaddr_in *) &bp->ifr_addr; struct ifreq auxinfo; /* ignore all but AF_INET interfaces */ if (rs->sin_family != AF_INET) continue; /* not interesting */ /* build a NUL-terminated copy of the rname field */ memcpy(ri.name, bp->ifr_name, IFNAMSIZ); ri.name[IFNAMSIZ] = '\0'; /* ignore if our interface names were specified, and this isn't one */ if (pluto_ifn_roof != 0) { int i; for (i = 0; i != pluto_ifn_roof; i++) if (streq(ri.name, pluto_ifn[i])) break; if (i == pluto_ifn_roof) continue; /* not found -- skip */ } /* Find out stuff about this interface. See netdevice(7). */ zero(&auxinfo); /* paranoia */ memcpy(auxinfo.ifr_name, bp->ifr_name, IFNAMSIZ); if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) { exit_log_errno((e, "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()", ri.name)); } if (!(auxinfo.ifr_flags & IFF_UP)) continue; /* ignore an interface that isn't UP */ /* ignore unconfigured interfaces */ if (rs->sin_addr.s_addr == 0) continue; happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr), AF_INET, &ri.addr)); DBG(DBG_CONTROL, { ipstr_buf b; DBG_log("found %s with address %s", ri.name, ipstr(&ri.addr, &b)); }); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); }
/* * Enumerate the system's network interface addresses and call the callback * for each one. Returns 0 if successful, -1 if trouble. * * This version uses ioctl(SIOCGIFCONF). */ int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data) { struct ifconf ifc; struct ifreq *ifr, *end, addr, mask; char *ptr, *buffer = NULL; size_t n_buffer = 1024; int sock; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) return -1; while (n_buffer < 1024 * 100) { n_buffer += 1024; ptr = realloc(buffer, n_buffer); if (!ptr) { free(buffer); close(sock); errno = ENOMEM; return -1; } memset(&ifc, 0, sizeof(ifc)); ifc.ifc_buf = buffer = ptr; ifc.ifc_len = n_buffer; if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { if (errno == EINVAL) continue; free(buffer); close(sock); return -1; } /* * Some Unixes try to return as much data as possible, with no * indication of whether enough space allocated. Don't believe we have * it all unless there's lots of slop. */ if (ifc.ifc_len < n_buffer - 1024) break; } end = (struct ifreq *) (buffer + ifc.ifc_len); for (ifr = ifc.ifc_req; ifr < end;) { memcpy(&addr, ifr, sizeof(addr)); memcpy(&mask, ifr, sizeof(mask)); if (ioctl(sock, SIOCGIFADDR, &addr, sizeof(addr)) == 0 && ioctl(sock, SIOCGIFNETMASK, &mask, sizeof(mask)) == 0) run_ifaddr_callback(callback, cb_data, &addr.ifr_addr, &mask.ifr_addr); ifr = (struct ifreq *) ((char *) ifr + _SIZEOF_ADDR_IFREQ(*ifr)); } free(buffer); close(sock); return 0; }
static void reply_cb(gpointer data, gint source, PurpleInputCondition cond) { struct stun_conn *sc = data; guchar buffer[65536]; struct ifreq buffer_ifr[1000]; guchar *it, *it_end; gssize len; struct in_addr in; struct stun_attrib attrib; struct stun_header hdr; struct ifconf ifc; struct ifreq *ifr; struct sockaddr_in *sinptr; memset(&in, 0, sizeof(in)); len = recv(source, buffer, sizeof(buffer) - 1, 0); if (len <= 0) { purple_debug_warning("stun", "unable to read stun response\n"); return; } buffer[len] = '\0'; if ((gsize)len < sizeof(struct stun_header)) { purple_debug_warning("stun", "got invalid response\n"); return; } memcpy(&hdr, buffer, sizeof(hdr)); if ((gsize)len != (ntohs(hdr.len) + sizeof(struct stun_header))) { purple_debug_warning("stun", "got incomplete response\n"); return; } /* wrong transaction */ if(hdr.transid[0] != sc->packet->transid[0] || hdr.transid[1] != sc->packet->transid[1] || hdr.transid[2] != sc->packet->transid[2] || hdr.transid[3] != sc->packet->transid[3]) { purple_debug_warning("stun", "got wrong transid\n"); return; } if(sc->test==1) { if (hdr.type != MSGTYPE_BINDINGRESPONSE) { purple_debug_warning("stun", "Expected Binding Response, got %d\n", hdr.type); return; } it = buffer + sizeof(struct stun_header); while((buffer + len) > (it + sizeof(struct stun_attrib))) { memcpy(&attrib, it, sizeof(attrib)); it += sizeof(struct stun_attrib); if (!((buffer + len) > (it + ntohs(attrib.len)))) break; if(attrib.type == htons(ATTRIB_MAPPEDADDRESS) && ntohs(attrib.len) == 8) { char *ip; /* Skip the first unused byte, * the family(1 byte), and the port(2 bytes); * then read the 4 byte IPv4 address */ memcpy(&in.s_addr, it + 4, 4); ip = inet_ntoa(in); if(ip) g_strlcpy(nattype.publicip, ip, sizeof(nattype.publicip)); } it += ntohs(attrib.len); } purple_debug_info("stun", "got public ip %s\n", nattype.publicip); nattype.status = PURPLE_STUN_STATUS_DISCOVERED; nattype.type = PURPLE_STUN_NAT_TYPE_UNKNOWN_NAT; nattype.lookup_time = time(NULL); /* is it a NAT? */ ifc.ifc_len = sizeof(buffer_ifr); ifc.ifc_req = buffer_ifr; ioctl(source, SIOCGIFCONF, &ifc); it = buffer; it_end = it + ifc.ifc_len; while (it < it_end) { ifr = (struct ifreq*)(gpointer)it; it += _SIZEOF_ADDR_IFREQ(*ifr); if(ifr->ifr_addr.sa_family == AF_INET) { /* we only care about ipv4 interfaces */ sinptr = (struct sockaddr_in *)(gpointer)&ifr->ifr_addr; if(sinptr->sin_addr.s_addr == in.s_addr) { /* no NAT */ purple_debug_info("stun", "no nat\n"); nattype.type = PURPLE_STUN_NAT_TYPE_PUBLIC_IP; } } } #if 1 close_stun_conn(sc); do_callbacks(); #else purple_timeout_remove(sc->timeout); sc->timeout = 0; do_test2(sc); } else if(sc->test == 2) { close_stun_conn(sc); nattype.type = PURPLE_STUN_NAT_TYPE_FULL_CONE; do_callbacks(); #endif /* 1 */ } }
std::vector<ip_interface> enum_net_interfaces(io_service& ios, error_code& ec) { std::vector<ip_interface> ret; #if TORRENT_USE_IFADDRS int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { ec = error_code(errno, asio::error::system_category); return ret; } ifaddrs *ifaddr; if (getifaddrs(&ifaddr) == -1) { ec = error_code(errno, asio::error::system_category); close(s); return ret; } for (ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr == 0) continue; if ((ifa->ifa_flags & IFF_UP) == 0) continue; int family = ifa->ifa_addr->sa_family; if (family == AF_INET #if TORRENT_USE_IPV6 || family == AF_INET6 #endif ) { ip_interface iface; if (iface_from_ifaddrs(ifa, iface, ec)) { ifreq req; memset(&req, 0, sizeof(req)); // -1 to leave a null terminator strncpy(req.ifr_name, iface.name, IF_NAMESIZE - 1); if (ioctl(s, SIOCGIFMTU, &req) < 0) { continue; } iface.mtu = req.ifr_mtu; ret.push_back(iface); } } } close(s); freeifaddrs(ifaddr); // MacOS X, BSD and solaris #elif TORRENT_USE_IFCONF int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { ec = error_code(errno, asio::error::system_category); return ret; } ifconf ifc; // make sure the buffer is aligned to hold ifreq structs ifreq buf[40]; ifc.ifc_len = sizeof(buf); ifc.ifc_buf = (char*)buf; if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { ec = error_code(errno, asio::error::system_category); close(s); return ret; } char *ifr = (char*)ifc.ifc_req; int remaining = ifc.ifc_len; while (remaining > 0) { ifreq const& item = *reinterpret_cast<ifreq*>(ifr); #ifdef _SIZEOF_ADDR_IFREQ int current_size = _SIZEOF_ADDR_IFREQ(item); #elif defined TORRENT_BSD int current_size = item.ifr_addr.sa_len + IFNAMSIZ; #else int current_size = sizeof(ifreq); #endif if (remaining < current_size) break; if (item.ifr_addr.sa_family == AF_INET #if TORRENT_USE_IPV6 || item.ifr_addr.sa_family == AF_INET6 #endif ) { ip_interface iface; iface.interface_address = sockaddr_to_address(&item.ifr_addr); strcpy(iface.name, item.ifr_name); ifreq req; memset(&req, 0, sizeof(req)); // -1 to leave a null terminator strncpy(req.ifr_name, item.ifr_name, IF_NAMESIZE - 1); if (ioctl(s, SIOCGIFMTU, &req) < 0) { ec = error_code(errno, asio::error::system_category); close(s); return ret; } #ifndef TORRENT_OS2 iface.mtu = req.ifr_mtu; #else iface.mtu = req.ifr_metric; // according to tcp/ip reference #endif memset(&req, 0, sizeof(req)); strncpy(req.ifr_name, item.ifr_name, IF_NAMESIZE - 1); if (ioctl(s, SIOCGIFNETMASK, &req) < 0) { #if TORRENT_USE_IPV6 if (iface.interface_address.is_v6()) { // this is expected to fail (at least on MacOS X) iface.netmask = address_v6::any(); } else #endif { ec = error_code(errno, asio::error::system_category); close(s); return ret; } } else { iface.netmask = sockaddr_to_address(&req.ifr_addr, item.ifr_addr.sa_family); } ret.push_back(iface); } ifr += current_size; remaining -= current_size; } close(s); #elif TORRENT_USE_GETADAPTERSADDRESSES #if _WIN32_WINNT >= 0x0501 // Load Iphlpapi library HMODULE iphlp = LoadLibraryA("Iphlpapi.dll"); if (iphlp) { // Get GetAdaptersAddresses() pointer typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG); GetAdaptersAddresses_t GetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress( iphlp, "GetAdaptersAddresses"); if (GetAdaptersAddresses) { PIP_ADAPTER_ADDRESSES adapter_addresses = 0; ULONG out_buf_size = 0; if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST, NULL, adapter_addresses, &out_buf_size) != ERROR_BUFFER_OVERFLOW) { FreeLibrary(iphlp); ec = asio::error::operation_not_supported; return std::vector<ip_interface>(); } adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(out_buf_size); if (!adapter_addresses) { FreeLibrary(iphlp); ec = asio::error::no_memory; return std::vector<ip_interface>(); } if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST, NULL, adapter_addresses, &out_buf_size) == NO_ERROR) { for (PIP_ADAPTER_ADDRESSES adapter = adapter_addresses; adapter != 0; adapter = adapter->Next) { ip_interface r; strncpy(r.name, adapter->AdapterName, sizeof(r.name)); r.name[sizeof(r.name)-1] = 0; r.mtu = adapter->Mtu; IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress; while (unicast) { r.interface_address = sockaddr_to_address(unicast->Address.lpSockaddr); ret.push_back(r); unicast = unicast->Next; } } } // Free memory free(adapter_addresses); FreeLibrary(iphlp); return ret; } FreeLibrary(iphlp); } #endif SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); if (s == SOCKET_ERROR) { ec = error_code(WSAGetLastError(), asio::error::system_category); return ret; } INTERFACE_INFO buffer[30]; DWORD size; if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buffer, sizeof(buffer), &size, 0, 0) != 0) { ec = error_code(WSAGetLastError(), asio::error::system_category); closesocket(s); return ret; } closesocket(s); int n = size / sizeof(INTERFACE_INFO); ip_interface iface; for (int i = 0; i < n; ++i) { iface.interface_address = sockaddr_to_address(&buffer[i].iiAddress.Address); if (iface.interface_address == address_v4::any()) continue; iface.netmask = sockaddr_to_address(&buffer[i].iiNetmask.Address , iface.interface_address.is_v4() ? AF_INET : AF_INET6); iface.name[0] = 0; iface.mtu = 1500; // how to get the MTU? ret.push_back(iface); } #else #warning THIS OS IS NOT RECOGNIZED, enum_net_interfaces WILL PROBABLY NOT WORK // make a best guess of the interface we're using and its IP udp::resolver r(ios); udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(ec), "0"), ec); if (ec) return ret; ip_interface iface; for (;i != udp::resolver_iterator(); ++i) { iface.interface_address = i->endpoint().address(); iface.mtu = 1500; if (iface.interface_address.is_v4()) iface.netmask = address_v4::netmask(iface.interface_address.to_v4()); ret.push_back(iface); } #endif return ret; }
/* Build a list of interfaces/IP-addresses/MAC adresses this machine currently has configured. ifs points to a buffer large enough to hold size entries */ int if_list_ips(struct interface *ifs, int size) { int count=0; struct ifconf d; struct ifreq *ifr, *end, *cur, *temp; struct in_addr ipaddr; char buffer[128]; /* temporary storage for getting broadcast address */ temp= (struct ifreq *)buffer; d.ifc_len= 4096; d.ifc_buf= malloc (d.ifc_len); if(ioctl (_if_sock, SIOCGIFCONF, &d) == -1) { perror("ioctl (SIOCGIFCONF)"); free(d.ifc_buf); return 0; } ifr=(struct ifreq *)(d.ifc_req); end=(struct ifreq *)(((char *) ifr) + d.ifc_len); while((ifr<end) && (count<size)) { cur= ifr; ifr = (struct ifreq *)(((char *)ifr)+_SIZEOF_ADDR_IFREQ(*ifr)); /* Handle LL adresses (MAC adress) */ if(cur->ifr_addr.sa_family == AF_LINK) { struct sockaddr_dl *sdl = (struct sockaddr_dl *)&cur->ifr_addr; if(sdl->sdl_alen != ETH_ALEN) continue; memset(&ifs[count], sizeof(struct interface), 0); strncpy(ifs[count].ifname, sdl->sdl_data, sdl->sdl_nlen); ifs[count].ifname[sdl->sdl_nlen] = '\0'; memcpy(ifs[count].mac, sdl->sdl_data+sdl->sdl_nlen, ETH_ALEN); continue; } /* Not AF_INET or AF_LINK, then ignore it */ if(cur->ifr_addr.sa_family != AF_INET) continue; /* Handle AF_INET */ memcpy(&ipaddr, &(((struct sockaddr_in *)&cur->ifr_addr)->sin_addr), sizeof(struct in_addr)); memcpy(temp, cur, sizeof(struct ifreq)); if(ioctl (_if_sock, SIOCGIFFLAGS, (char *) cur) < 0) continue; if((cur->ifr_flags & IFF_UP) && (cur->ifr_flags & IFF_BROADCAST)) { memcpy(&ifs[count].ipaddr, &ipaddr, sizeof(struct in_addr)); if(ioctl(_if_sock, SIOCGIFBRDADDR, (char *)temp) != -1) memcpy(&ifs[count].bcast, &(((struct sockaddr_in *)&temp->ifr_addr)->sin_addr), sizeof(struct in_addr)); if(ioctl(_if_sock, SIOCGIFNETMASK, (char *)temp) != -1) memcpy(&ifs[count].netmask, &(((struct sockaddr_in *)&temp->ifr_addr)->sin_addr), sizeof(struct in_addr)); strncpy(ifs[count].ifname, cur->ifr_name, IFNAMSIZ); count++; memcpy(&ifs[count], &ifs[count-1], sizeof(struct interface)); } } free(d.ifc_buf); return count; }