int nr_praddr_to_transport_addr(const PRNetAddr *praddr, nr_transport_addr *addr, int protocol, int keep) { int _status; int r; struct sockaddr_in ip4; switch(praddr->raw.family) { case PR_AF_INET: ip4.sin_family = PF_INET; ip4.sin_addr.s_addr = praddr->inet.ip; ip4.sin_port = praddr->inet.port; if ((r = nr_sockaddr_to_transport_addr((sockaddr *)&ip4, sizeof(ip4), protocol, keep, addr))) ABORT(r); break; case PR_AF_INET6: #if 0 r = nr_sockaddr_to_transport_addr((sockaddr *)&praddr->raw, sizeof(struct sockaddr_in6),IPPROTO_UDP,keep,addr); break; #endif ABORT(R_BAD_ARGS); default: MOZ_ASSERT(false); ABORT(R_BAD_ARGS); } _status=0; abort: return(_status); }
static int stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) { int r,_status; PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL, tmpAddress = NULL; ULONG buflen; char munged_ifname[IFNAMSIZ]; int n = 0; *count = 0; if (maxaddrs <= 0) ABORT(R_INTERNAL); /* Call GetAdaptersAddresses() twice. First, just to get the buf length */ buflen = 0; r = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterAddresses, &buflen); if (r != ERROR_BUFFER_OVERFLOW) { r_log(NR_LOG_STUN, LOG_ERR, "Error getting buf len from GetAdaptersAddresses()"); ABORT(R_INTERNAL); } AdapterAddresses = (PIP_ADAPTER_ADDRESSES) RMALLOC(buflen); if (AdapterAddresses == NULL) { r_log(NR_LOG_STUN, LOG_ERR, "Error allocating buf for GetAdaptersAddresses()"); ABORT(R_NO_MEMORY); } /* for real, this time */ r = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, AdapterAddresses, &buflen); if (r != NO_ERROR) { r_log(NR_LOG_STUN, LOG_ERR, "Error getting addresses from GetAdaptersAddresses()"); ABORT(R_INTERNAL); } /* Loop through the adapters */ for (tmpAddress = AdapterAddresses; tmpAddress != NULL; tmpAddress = tmpAddress->Next) { char *c; if (tmpAddress->OperStatus != IfOperStatusUp) continue; snprintf(munged_ifname, IFNAMSIZ, "%S%c", tmpAddress->FriendlyName, 0); /* replace spaces with underscores */ c = strchr(munged_ifname, ' '); while (c != NULL) { *c = '_'; c = strchr(munged_ifname, ' '); } c = strchr(munged_ifname, '.'); while (c != NULL) { *c = '+'; c = strchr(munged_ifname, '.'); } if ((tmpAddress->IfIndex != 0) || (tmpAddress->Ipv6IfIndex != 0)) { IP_ADAPTER_UNICAST_ADDRESS *u = 0; for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) { SOCKET_ADDRESS *sa_addr = &u->Address; if ((sa_addr->lpSockaddr->sa_family == AF_INET) || (sa_addr->lpSockaddr->sa_family == AF_INET6)) { if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, IPPROTO_UDP, 0, &(addrs[n].addr)))) ABORT(r); } else { r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized sa_family for adapteraddress %s",munged_ifname); continue; } strlcpy(addrs[n].addr.ifname, munged_ifname, sizeof(addrs[n].addr.ifname)); /* TODO: (Bug 895793) Getting interface properties for Windows */ addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN; addrs[n].interface.estimated_speed = 0; if (++n >= maxaddrs) goto done; } } } done: *count = n; _status = 0; abort: RFREE(AdapterAddresses); return _status; }
static int stun_getifaddrs(nr_local_addr addrs[], int maxaddrs, int *count) { int r,_status; struct ifaddrs* if_addrs_head=NULL; struct ifaddrs* if_addr; *count=0; if (getifaddrs(&if_addrs_head) == -1) { r_log(NR_LOG_STUN, LOG_ERR, "getifaddrs error e = %d", errno); ABORT(R_INTERNAL); } if_addr = if_addrs_head; while (if_addr && *count < maxaddrs) { /* This can be null */ if (if_addr->ifa_addr) { switch (if_addr->ifa_addr->sa_family) { case AF_INET: case AF_INET6: if (r=nr_sockaddr_to_transport_addr(if_addr->ifa_addr, IPPROTO_UDP, 0, &(addrs[*count].addr))) { r_log(NR_LOG_STUN, LOG_ERR, "nr_sockaddr_to_transport_addr error r = %d", r); } else { #if defined(LINUX) && !defined(ANDROID) struct ethtool_cmd ecmd; struct ifreq ifr; struct iwreq wrq; int e; int s = socket(AF_INET, SOCK_DGRAM, 0); strncpy(ifr.ifr_name, if_addr->ifa_name, sizeof(ifr.ifr_name)); /* TODO (Bug 896851): interface property for Android */ /* Getting ethtool for ethernet information. */ ecmd.cmd = ETHTOOL_GSET; /* In/out param */ ifr.ifr_data = (void*)&ecmd; e = ioctl(s, SIOCETHTOOL, &ifr); if (e == 0) { /* For wireless network, we won't get ethtool, it's a wired * connection */ addrs[*count].interface.type = NR_INTERFACE_TYPE_WIRED; #ifdef DONT_HAVE_ETHTOOL_SPEED_HI addrs[*count].interface.estimated_speed = ecmd.speed; #else addrs[*count].interface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000; #endif } strncpy(wrq.ifr_name, if_addr->ifa_name, sizeof(wrq.ifr_name)); e = ioctl(s, SIOCGIWRATE, &wrq); if (e == 0) { addrs[*count].interface.type = NR_INTERFACE_TYPE_WIFI; addrs[*count].interface.estimated_speed = wrq.u.bitrate.value / 1000; } close(s); if (if_addr->ifa_flags & IFF_POINTOPOINT) { addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN; /* TODO (Bug 896913): find backend network type of this VPN */ } #else addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN; addrs[*count].interface.estimated_speed = 0; #endif strlcpy(addrs[*count].addr.ifname, if_addr->ifa_name, sizeof(addrs[*count].addr.ifname)); ++(*count); } break; default: ; } } if_addr = if_addr->ifa_next; } _status=0; abort: if (if_addrs_head) { freeifaddrs(if_addrs_head); } return(_status); }
static int stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) { int r, _status; PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL, tmpAddress = NULL; // recomended per https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx static const ULONG initialBufLen = 15000; ULONG buflen = initialBufLen; char bin_hashed_ifname[NR_MD5_HASH_LENGTH]; char hex_hashed_ifname[MAXIFNAME]; int n = 0; *count = 0; if (maxaddrs <= 0) ABORT(R_BAD_ARGS); /* According to MSDN (see above) we have try GetAdapterAddresses() multiple times */ for (n = 0; n < 5; n++) { AdapterAddresses = (PIP_ADAPTER_ADDRESSES) RMALLOC(buflen); if (AdapterAddresses == NULL) { r_log(NR_LOG_STUN, LOG_ERR, "Error allocating buf for GetAdaptersAddresses()"); ABORT(R_NO_MEMORY); } r = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, AdapterAddresses, &buflen); if (r == NO_ERROR) { break; } r_log(NR_LOG_STUN, LOG_ERR, "GetAdaptersAddresses() returned error (%d)", r); RFREE(AdapterAddresses); } if (n >= 5) { r_log(NR_LOG_STUN, LOG_ERR, "5 failures calling GetAdaptersAddresses()"); ABORT(R_INTERNAL); } n = 0; /* Loop through the adapters */ for (tmpAddress = AdapterAddresses; tmpAddress != NULL; tmpAddress = tmpAddress->Next) { if (tmpAddress->OperStatus != IfOperStatusUp) continue; if ((tmpAddress->IfIndex != 0) || (tmpAddress->Ipv6IfIndex != 0)) { IP_ADAPTER_UNICAST_ADDRESS *u = 0; if(r=nr_crypto_md5((UCHAR *)tmpAddress->FriendlyName, wcslen(tmpAddress->FriendlyName) * sizeof(wchar_t), bin_hashed_ifname)) ABORT(r); if(r=nr_bin2hex(bin_hashed_ifname, sizeof(bin_hashed_ifname), hex_hashed_ifname)) ABORT(r); for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) { SOCKET_ADDRESS *sa_addr = &u->Address; if ((sa_addr->lpSockaddr->sa_family == AF_INET) || (sa_addr->lpSockaddr->sa_family == AF_INET6)) { if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, IPPROTO_UDP, 0, &(addrs[n].addr)))) ABORT(r); } else { r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized sa_family for address on adapter %lu", tmpAddress->IfIndex); continue; } strlcpy(addrs[n].addr.ifname, hex_hashed_ifname, sizeof(addrs[n].addr.ifname)); if (tmpAddress->IfType == IF_TYPE_ETHERNET_CSMACD) { addrs[n].interface.type = NR_INTERFACE_TYPE_WIRED; } else if (tmpAddress->IfType == IF_TYPE_IEEE80211) { /* Note: this only works for >= Win Vista */ addrs[n].interface.type = NR_INTERFACE_TYPE_WIFI; } else { addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN; } #if (_WIN32_WINNT >= 0x0600) /* Note: only >= Vista provide link speed information */ addrs[n].interface.estimated_speed = tmpAddress->TransmitLinkSpeed / 1000; #else addrs[n].interface.estimated_speed = 0; #endif if (++n >= maxaddrs) goto done; } } } done: *count = n; _status = 0; abort: RFREE(AdapterAddresses); return _status; }