1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/mtransport/third_party/nICEr/src/stun/addrs.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,784 @@ 1.4 +/* 1.5 +Copyright (c) 2007, Adobe Systems, Incorporated 1.6 +All rights reserved. 1.7 + 1.8 +Redistribution and use in source and binary forms, with or without 1.9 +modification, are permitted provided that the following conditions are 1.10 +met: 1.11 + 1.12 +* Redistributions of source code must retain the above copyright 1.13 + notice, this list of conditions and the following disclaimer. 1.14 + 1.15 +* Redistributions in binary form must reproduce the above copyright 1.16 + notice, this list of conditions and the following disclaimer in the 1.17 + documentation and/or other materials provided with the distribution. 1.18 + 1.19 +* Neither the name of Adobe Systems, Network Resonance nor the names of its 1.20 + contributors may be used to endorse or promote products derived from 1.21 + this software without specific prior written permission. 1.22 + 1.23 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.25 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.26 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.27 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.28 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.29 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.30 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.31 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.32 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.33 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.34 +*/ 1.35 + 1.36 + 1.37 +static char *RCSSTRING __UNUSED__="$Id: addrs.c,v 1.2 2008/04/28 18:21:30 ekr Exp $"; 1.38 + 1.39 +#include <csi_platform.h> 1.40 +#include <assert.h> 1.41 +#include <string.h> 1.42 + 1.43 +#ifdef WIN32 1.44 +#include <winsock2.h> 1.45 +#include <iphlpapi.h> 1.46 +#include <tchar.h> 1.47 +#else /* UNIX */ 1.48 +#include <sys/param.h> 1.49 +#include <sys/socket.h> 1.50 +#ifndef ANDROID 1.51 +#include <sys/sysctl.h> 1.52 +#include <sys/syslog.h> 1.53 +#else 1.54 +#include <syslog.h> 1.55 +/* Work around an Android NDK < r8c bug */ 1.56 +#undef __unused 1.57 +#include <linux/sysctl.h> 1.58 +#endif 1.59 +#include <net/if.h> 1.60 +#ifndef LINUX 1.61 +#if !defined(__OpenBSD__) && !defined(__NetBSD__) 1.62 +#include <net/if_var.h> 1.63 +#endif 1.64 +#include <net/if_dl.h> 1.65 +#include <net/if_types.h> 1.66 +#include <sys/sockio.h> 1.67 +#else 1.68 +#include <linux/sockios.h> 1.69 +#include <linux/if.h> 1.70 +#include <linux/kernel.h> 1.71 +#include <linux/wireless.h> 1.72 +#ifndef ANDROID 1.73 +#include <linux/ethtool.h> 1.74 +#endif 1.75 +#endif 1.76 +#include <net/route.h> 1.77 + 1.78 +/* IP */ 1.79 +#include <netinet/in.h> 1.80 +#ifdef LINUX 1.81 +#include "sys/ioctl.h" 1.82 +#else 1.83 +#include <netinet/in_var.h> 1.84 +#endif 1.85 +#include <arpa/inet.h> 1.86 +#include <netdb.h> 1.87 +#endif /* UNIX */ 1.88 + 1.89 +#include "stun.h" 1.90 +#include "addrs.h" 1.91 + 1.92 + 1.93 + 1.94 +#if defined(BSD) || defined(DARWIN) 1.95 +/* 1.96 + * Copyright (c) 1983, 1993 1.97 + * The Regents of the University of California. All rights reserved. 1.98 + * 1.99 + * Redistribution and use in source and binary forms, with or without 1.100 + * modification, are permitted provided that the following conditions 1.101 + * are met: 1.102 + * 1. Redistributions of source code must retain the above copyright 1.103 + * notice, this list of conditions and the following disclaimer. 1.104 + * 2. Redistributions in binary form must reproduce the above copyright 1.105 + * notice, this list of conditions and the following disclaimer in the 1.106 + * documentation and/or other materials provided with the distribution. 1.107 + *[3 Deleted as of 22nd July 1999; see 1.108 + * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change 1.109 + * for details] 1.110 + * 4. Neither the name of the University nor the names of its contributors 1.111 + * may be used to endorse or promote products derived from this software 1.112 + * without specific prior written permission. 1.113 + * 1.114 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1.115 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.116 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.117 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1.118 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1.119 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1.120 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1.121 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1.122 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1.123 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1.124 + * SUCH DAMAGE. 1.125 + */ 1.126 + 1.127 +#include <err.h> 1.128 + 1.129 +static void stun_rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); 1.130 +static int stun_grab_addrs(char *name, int addrcount, 1.131 + struct ifa_msghdr *ifam, 1.132 + nr_local_addr addrs[], int maxaddrs, int *count); 1.133 +static int 1.134 +nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr); 1.135 + 1.136 + 1.137 +/* 1.138 + * Expand the compacted form of addresses as returned via the 1.139 + * configuration read via sysctl(). 1.140 + */ 1.141 +#define ROUNDUP(a) \ 1.142 + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 1.143 +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 1.144 + 1.145 +static void 1.146 +stun_rt_xaddrs(cp, cplim, rtinfo) 1.147 + caddr_t cp, cplim; 1.148 + struct rt_addrinfo *rtinfo; 1.149 +{ 1.150 + struct sockaddr *sa; 1.151 + int i; 1.152 + 1.153 + memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 1.154 + for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 1.155 + if ((rtinfo->rti_addrs & (1 << i)) == 0) 1.156 + continue; 1.157 + rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 1.158 + ADVANCE(cp, sa); 1.159 + } 1.160 +} 1.161 + 1.162 +static int 1.163 +stun_grab_addrs(char *name, int addrcount, struct ifa_msghdr *ifam, nr_local_addr addrs[], int maxaddrs, int *count) 1.164 +{ 1.165 + int r,_status; 1.166 + int s = -1; 1.167 + struct ifreq ifr; 1.168 + struct rt_addrinfo info; 1.169 + struct sockaddr_in *sin; 1.170 + 1.171 + ifr.ifr_addr.sa_family = AF_INET; 1.172 + strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1.173 + 1.174 + if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) { 1.175 + r_log(NR_LOG_STUN, LOG_ERR, "unable to obtain addresses from socket"); 1.176 + ABORT(R_FAILED); 1.177 + } 1.178 + 1.179 + while (addrcount > 0) { 1.180 + info.rti_addrs = ifam->ifam_addrs; 1.181 + 1.182 + /* Expand the compacted addresses */ 1.183 + stun_rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info); 1.184 + addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN; 1.185 + addrs[*count].interface.estimated_speed = 0; 1.186 + /* TODO (Bug 895790) Get interface properties for Darwin */ 1.187 + 1.188 + switch (info.rti_info[RTAX_IFA]->sa_family) { 1.189 + case AF_INET: 1.190 + sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA]; 1.191 + 1.192 + if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sin, sizeof(*sin), IPPROTO_UDP, 0, &(addrs[*count].addr)))) 1.193 + ABORT(r); 1.194 + 1.195 + strlcpy(addrs[*count].addr.ifname, name, sizeof(addrs[*count].addr.ifname)); 1.196 + 1.197 + ++*count; 1.198 + break; 1.199 + case AF_INET6: 1.200 + UNIMPLEMENTED; 1.201 + break; 1.202 + } 1.203 + 1.204 + addrcount--; 1.205 + 1.206 + if (*count >= maxaddrs) { 1.207 + r_log(NR_LOG_STUN, LOG_WARNING, "Address list truncated at %d out of %d entries", maxaddrs, maxaddrs+addrcount); 1.208 + break; 1.209 + } 1.210 + 1.211 + ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); 1.212 + } 1.213 + 1.214 + _status = 0; 1.215 + abort: 1.216 + if (s != -1) close(s); 1.217 + return _status; 1.218 +} 1.219 + 1.220 +static int 1.221 +stun_get_mib_addrs(nr_local_addr addrs[], int maxaddrs, int *count) 1.222 +{ 1.223 + int _status; 1.224 + char name[32]; 1.225 + int flags; 1.226 + int addrcount; 1.227 + struct if_msghdr *ifm, *nextifm; 1.228 + struct ifa_msghdr *ifam; 1.229 + struct sockaddr_dl *sdl; 1.230 + char *buf = 0; 1.231 + char *lim; 1.232 + char *next; 1.233 + size_t needed; 1.234 + int mib[6]; 1.235 + 1.236 + *count = 0; 1.237 + 1.238 + mib[0] = CTL_NET; 1.239 + mib[1] = PF_ROUTE; 1.240 + mib[2] = 0; 1.241 + mib[3] = AF_INET; 1.242 + mib[4] = NET_RT_IFLIST; 1.243 + mib[5] = 0; 1.244 + 1.245 + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 1.246 + errx(1, "iflist-sysctl-estimate"); 1.247 + if ((buf = malloc(needed)) == NULL) 1.248 + errx(1, "malloc"); 1.249 + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 1.250 + errx(1, "actual retrieval of interface table"); 1.251 + lim = buf + needed; 1.252 + 1.253 + next = buf; 1.254 + while (next < lim) { 1.255 + ifm = (struct if_msghdr *)next; 1.256 + 1.257 + if (ifm->ifm_type == RTM_IFINFO) { 1.258 + sdl = (struct sockaddr_dl *)(ifm + 1); 1.259 + flags = ifm->ifm_flags; 1.260 + } else { 1.261 + r_log(NR_LOG_STUN, LOG_WARNING, "out of sync parsing NET_RT_IFLIST"); 1.262 + r_log(NR_LOG_STUN, LOG_DEBUG, "expected %d, got %d, msglen = %d, buf:%p, next:%p, lim:%p", RTM_IFINFO, ifm->ifm_type, ifm->ifm_msglen, buf, next, lim); 1.263 + ABORT(R_FAILED); 1.264 + } 1.265 + 1.266 + next += ifm->ifm_msglen; 1.267 + ifam = NULL; 1.268 + addrcount = 0; 1.269 + while (next < lim) { 1.270 + 1.271 + nextifm = (struct if_msghdr *)next; 1.272 + 1.273 + if (nextifm->ifm_type != RTM_NEWADDR) 1.274 + break; 1.275 + 1.276 + if (ifam == NULL) 1.277 + ifam = (struct ifa_msghdr *)nextifm; 1.278 + 1.279 + addrcount++; 1.280 + next += nextifm->ifm_msglen; 1.281 + } 1.282 + 1.283 + if (sdl->sdl_nlen > sizeof(name) - 1) { 1.284 + ABORT(R_INTERNAL); 1.285 + } 1.286 + 1.287 + memcpy(name, sdl->sdl_data, sdl->sdl_nlen); 1.288 + name[sdl->sdl_nlen] = '\0'; 1.289 + 1.290 + stun_grab_addrs(name, addrcount, ifam, addrs, maxaddrs, count); 1.291 + } 1.292 + 1.293 + _status = 0; 1.294 +abort: 1.295 + if (buf) free(buf); 1.296 + return _status; 1.297 +} 1.298 + 1.299 +#elif defined(WIN32) 1.300 + 1.301 +#define WIN32_MAX_NUM_INTERFACES 20 1.302 + 1.303 + 1.304 +#define _NR_MAX_KEY_LENGTH 256 1.305 +#define _NR_MAX_NAME_LENGTH 512 1.306 + 1.307 +#define _ADAPTERS_BASE_REG "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 1.308 + 1.309 +static int nr_win32_get_adapter_friendly_name(char *adapter_GUID, char **friendly_name) 1.310 +{ 1.311 + int r,_status; 1.312 + HKEY adapter_reg; 1.313 + TCHAR adapter_key[_NR_MAX_KEY_LENGTH]; 1.314 + TCHAR keyval_buf[_NR_MAX_KEY_LENGTH]; 1.315 + TCHAR adapter_GUID_tchar[_NR_MAX_NAME_LENGTH]; 1.316 + DWORD keyval_len, key_type; 1.317 + size_t converted_chars, newlen; 1.318 + char *my_fn = 0; 1.319 + 1.320 +#ifdef _UNICODE 1.321 + mbstowcs_s(&converted_chars, adapter_GUID_tchar, strlen(adapter_GUID)+1, 1.322 + adapter_GUID, _TRUNCATE); 1.323 +#else 1.324 + strlcpy(adapter_GUID_tchar, adapter_GUID, _NR_MAX_NAME_LENGTH); 1.325 +#endif 1.326 + 1.327 + _tcscpy_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT(_ADAPTERS_BASE_REG)); 1.328 + _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\")); 1.329 + _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, adapter_GUID_tchar); 1.330 + _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\Connection")); 1.331 + 1.332 + r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, adapter_key, 0, KEY_READ, &adapter_reg); 1.333 + 1.334 + if (r != ERROR_SUCCESS) { 1.335 + r_log(NR_LOG_STUN, LOG_ERR, "Got error %d opening adapter reg key\n", r); 1.336 + ABORT(R_INTERNAL); 1.337 + } 1.338 + 1.339 + keyval_len = sizeof(keyval_buf); 1.340 + r = RegQueryValueEx(adapter_reg, TEXT("Name"), NULL, &key_type, 1.341 + (BYTE *)keyval_buf, &keyval_len); 1.342 + 1.343 + RegCloseKey(adapter_reg); 1.344 + 1.345 +#ifdef UNICODE 1.346 + newlen = wcslen(keyval_buf)+1; 1.347 + my_fn = (char *) RCALLOC(newlen); 1.348 + if (!my_fn) { 1.349 + ABORT(R_NO_MEMORY); 1.350 + } 1.351 + wcstombs_s(&converted_chars, my_fn, newlen, keyval_buf, _TRUNCATE); 1.352 +#else 1.353 + my_fn = r_strdup(keyval_buf); 1.354 +#endif 1.355 + 1.356 + *friendly_name = my_fn; 1.357 + _status=0; 1.358 + 1.359 +abort: 1.360 + if (_status) { 1.361 + if (my_fn) free(my_fn); 1.362 + } 1.363 + return(_status); 1.364 +} 1.365 + 1.366 + 1.367 +static int 1.368 +stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) 1.369 +{ 1.370 + int r,_status; 1.371 + PIP_ADAPTER_INFO pAdapterInfo; 1.372 + PIP_ADAPTER_INFO pAdapter = NULL; 1.373 + PIP_ADDR_STRING pAddrString; 1.374 + ULONG out_buf_len; 1.375 + char *friendly_name=0; 1.376 + char munged_ifname[IFNAMSIZ]; 1.377 + int n = 0; 1.378 + 1.379 + *count = 0; 1.380 + 1.381 + pAdapterInfo = (IP_ADAPTER_INFO *) RMALLOC(sizeof(IP_ADAPTER_INFO)); 1.382 + out_buf_len = sizeof(IP_ADAPTER_INFO); 1.383 + 1.384 + /* First call to GetAdaptersInfo is mainly to get length */ 1.385 + 1.386 + if (GetAdaptersInfo(pAdapterInfo, &out_buf_len) == ERROR_BUFFER_OVERFLOW) { 1.387 + RFREE(pAdapterInfo); 1.388 + pAdapterInfo = (IP_ADAPTER_INFO *) RMALLOC(out_buf_len); 1.389 + if (pAdapterInfo == NULL) { 1.390 + r_log(NR_LOG_STUN, LOG_ERR, "Error allocating memory for GetAdaptersInfo output"); 1.391 + ABORT(R_NO_MEMORY); 1.392 + } 1.393 + } 1.394 + if ((r = GetAdaptersInfo(pAdapterInfo, &out_buf_len)) != NO_ERROR) { 1.395 + r_log(NR_LOG_STUN, LOG_ERR, "Got error from GetAdaptersInfo"); 1.396 + ABORT(R_INTERNAL); 1.397 + } 1.398 + r_log(NR_LOG_STUN, LOG_DEBUG, "Got AdaptersInfo"); 1.399 + 1.400 + pAdapter = pAdapterInfo; 1.401 + 1.402 + while (pAdapter) { 1.403 + char *c; 1.404 + 1.405 + r_log(NR_LOG_STUN, LOG_DEBUG, "Adapter Name (GUID) = %s", pAdapter->AdapterName); 1.406 + r_log(NR_LOG_STUN, LOG_DEBUG, "Adapter Description = %s", pAdapter->Description); 1.407 + 1.408 + if (nr_win32_get_adapter_friendly_name(pAdapter->AdapterName, &friendly_name)) { 1.409 + friendly_name = 0; 1.410 + } 1.411 + if (friendly_name && *friendly_name) { 1.412 + r_log(NR_LOG_STUN, LOG_INFO, "Found adapter with friendly name: %s", friendly_name); 1.413 + snprintf(munged_ifname, IFNAMSIZ, "%s%c", friendly_name, 0); 1.414 + RFREE(friendly_name); 1.415 + friendly_name = 0; 1.416 + } else { 1.417 + // Not all adapters follow the friendly name convention. Windows' PPTP 1.418 + // VPN adapter puts "VPN Connection 2" in the Description field instead. 1.419 + // Windows's renaming-logic appears to enforce uniqueness in spite of this. 1.420 + r_log(NR_LOG_STUN, LOG_INFO, "Found adapter with description: %s", pAdapter->Description); 1.421 + snprintf(munged_ifname, IFNAMSIZ, "%s%c", pAdapter->Description, 0); 1.422 + } 1.423 + /* replace spaces with underscores */ 1.424 + c = strchr(munged_ifname, ' '); 1.425 + while (c != NULL) { 1.426 + *c = '_'; 1.427 + c = strchr(munged_ifname, ' '); 1.428 + } 1.429 + c = strchr(munged_ifname, '.'); 1.430 + while (c != NULL) { 1.431 + *c = '+'; 1.432 + c = strchr(munged_ifname, '.'); 1.433 + } 1.434 + 1.435 + r_log(NR_LOG_STUN, LOG_INFO, "Converted ifname: %s", munged_ifname); 1.436 + 1.437 + for (pAddrString = &(pAdapter->IpAddressList); pAddrString != NULL; pAddrString = pAddrString->Next) { 1.438 + unsigned long this_addr = inet_addr(pAddrString->IpAddress.String); 1.439 + nr_transport_addr *addr = &(addrs[n].addr); 1.440 + 1.441 + if (this_addr == 0) 1.442 + continue; 1.443 + 1.444 + r_log(NR_LOG_STUN, LOG_INFO, "Adapter %s address: %s", munged_ifname, pAddrString->IpAddress.String); 1.445 + 1.446 + addr->ip_version=NR_IPV4; 1.447 + addr->protocol = IPPROTO_UDP; 1.448 + 1.449 + addr->u.addr4.sin_family=PF_INET; 1.450 + addr->u.addr4.sin_port=0; 1.451 + addr->u.addr4.sin_addr.s_addr=this_addr; 1.452 + addr->addr=(struct sockaddr *)&(addr->u.addr4); 1.453 + addr->addr_len=sizeof(struct sockaddr_in); 1.454 + 1.455 + strlcpy(addr->ifname, munged_ifname, sizeof(addr->ifname)); 1.456 + snprintf(addr->as_string,40,"IP4:%s:%d", 1.457 + inet_ntoa(addr->u.addr4.sin_addr), 1.458 + ntohs(addr->u.addr4.sin_port)); 1.459 + 1.460 + /* TODO: (Bug 895793) Getting interface properties for Windows */ 1.461 + addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN; 1.462 + addrs[n].interface.estimated_speed = 0; 1.463 + 1.464 + if (++n >= maxaddrs) 1.465 + goto done; 1.466 + } 1.467 + 1.468 + pAdapter = pAdapter->Next; 1.469 + } 1.470 + 1.471 + done: 1.472 + *count = n; 1.473 + _status = 0; 1.474 + 1.475 + abort: 1.476 + RFREE(pAdapterInfo); 1.477 + RFREE(friendly_name); 1.478 + return _status; 1.479 +} 1.480 + 1.481 +#ifdef GET_WIN32_ADDRS_NO_WIN2K 1.482 + /* Here's a nice way to get adapter addresses and names, but it 1.483 + * isn't supported on Win2000. 1.484 + */ 1.485 +static int 1.486 +stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count) 1.487 +{ 1.488 + int r,_status; 1.489 + PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL, tmpAddress = NULL; 1.490 + ULONG buflen; 1.491 + char munged_ifname[IFNAMSIZ]; 1.492 + int n = 0; 1.493 + 1.494 + *count = 0; 1.495 + 1.496 + if (maxaddrs <= 0) 1.497 + ABORT(R_INTERNAL); 1.498 + 1.499 + /* Call GetAdaptersAddresses() twice. First, just to get the buf length */ 1.500 + 1.501 + buflen = 0; 1.502 + 1.503 + r = GetAdaptersAddresses(AF_INET, 0, NULL, AdapterAddresses, &buflen); 1.504 + if (r != ERROR_BUFFER_OVERFLOW) { 1.505 + r_log(NR_LOG_STUN, LOG_ERR, "Error getting buf len from GetAdaptersAddresses()"); 1.506 + ABORT(R_INTERNAL); 1.507 + } 1.508 + 1.509 + AdapterAddresses = (PIP_ADAPTER_ADDRESSES) RMALLOC(buflen); 1.510 + if (AdapterAddresses == NULL) { 1.511 + r_log(NR_LOG_STUN, LOG_ERR, "Error allocating buf for GetAdaptersAddresses()"); 1.512 + ABORT(R_NO_MEMORY); 1.513 + } 1.514 + 1.515 + /* for real, this time */ 1.516 + 1.517 + r = GetAdaptersAddresses(AF_INET, 0, NULL, AdapterAddresses, &buflen); 1.518 + if (r != NO_ERROR) { 1.519 + r_log(NR_LOG_STUN, LOG_ERR, "Error getting addresses from GetAdaptersAddresses()"); 1.520 + ABORT(R_INTERNAL); 1.521 + } 1.522 + 1.523 + /* Loop through the adapters */ 1.524 + 1.525 + for (tmpAddress = AdapterAddresses; tmpAddress != NULL; tmpAddress = tmpAddress->Next) { 1.526 + char *c; 1.527 + 1.528 + if (tmpAddress->OperStatus != IfOperStatusUp) 1.529 + continue; 1.530 + 1.531 + snprintf(munged_ifname, IFNAMSIZ, "%S%c", tmpAddress->FriendlyName, 0); 1.532 + /* replace spaces with underscores */ 1.533 + c = strchr(munged_ifname, ' '); 1.534 + while (c != NULL) { 1.535 + *c = '_'; 1.536 + c = strchr(munged_ifname, ' '); 1.537 + } 1.538 + c = strchr(munged_ifname, '.'); 1.539 + while (c != NULL) { 1.540 + *c = '+'; 1.541 + c = strchr(munged_ifname, '+'); 1.542 + } 1.543 + 1.544 + if ((tmpAddress->IfIndex != 0) || (tmpAddress->Ipv6IfIndex != 0)) { 1.545 + IP_ADAPTER_UNICAST_ADDRESS *u = 0; 1.546 + 1.547 + for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) { 1.548 + SOCKET_ADDRESS *sa_addr = &u->Address; 1.549 + 1.550 + if ((sa_addr->lpSockaddr->sa_family == AF_INET) || 1.551 + (sa_addr->lpSockaddr->sa_family == AF_INET6)) { 1.552 + if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, sizeof(*sa_addr->lpSockaddr), IPPROTO_UDP, 0, &(addrs[n].addr)))) 1.553 + ABORT(r); 1.554 + } 1.555 + else { 1.556 + r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized sa_family for adapteraddress %s",munged_ifname); 1.557 + continue; 1.558 + } 1.559 + 1.560 + strlcpy(addrs[n].addr.ifname, munged_ifname, sizeof(addrs[n].addr.ifname)); 1.561 + /* TODO: (Bug 895793) Getting interface properties for Windows */ 1.562 + addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN; 1.563 + addrs[n].interface.estimated_speed = 0; 1.564 + if (++n >= maxaddrs) 1.565 + goto done; 1.566 + } 1.567 + } 1.568 + } 1.569 + 1.570 + done: 1.571 + *count = n; 1.572 + _status = 0; 1.573 + 1.574 + abort: 1.575 + RFREE(AdapterAddresses); 1.576 + return _status; 1.577 +} 1.578 +#endif /* GET_WIN32_ADDRS_NO_WIN2K */ 1.579 + 1.580 +#elif defined(__sparc__) 1.581 + 1.582 +static int 1.583 +stun_get_sparc_addrs(nr_local_addr addrs[], int maxaddrs, int *count) 1.584 +{ 1.585 + *count = 0; 1.586 + UNIMPLEMENTED; /*TODO !nn! - sparc */ 1.587 + return 0; 1.588 +} 1.589 + 1.590 +#else 1.591 + 1.592 +static int 1.593 +stun_get_siocgifconf_addrs(nr_local_addr addrs[], int maxaddrs, int *count) 1.594 +{ 1.595 + struct ifconf ifc; 1.596 + int _status; 1.597 + int s = socket( AF_INET, SOCK_DGRAM, 0 ); 1.598 + int len = 100 * sizeof(struct ifreq); 1.599 + int r; 1.600 + int e; 1.601 + char *ptr; 1.602 + int tl; 1.603 + int n; 1.604 + struct ifreq ifr2; 1.605 + 1.606 + char buf[ len ]; 1.607 + 1.608 + ifc.ifc_len = len; 1.609 + ifc.ifc_buf = buf; 1.610 + 1.611 + e = ioctl(s,SIOCGIFCONF,&ifc); 1.612 + ptr = buf; 1.613 + tl = ifc.ifc_len; 1.614 + n=0; 1.615 + 1.616 + while ( (tl > 0) && ( n < maxaddrs) ) 1.617 + { 1.618 + struct ifreq* ifr = (struct ifreq *)ptr; 1.619 + 1.620 +#ifdef LINUX 1.621 + int si = sizeof(struct ifreq); 1.622 +#ifndef ANDROID 1.623 + struct ethtool_cmd ecmd; 1.624 + struct iwreq wrq; 1.625 +#endif 1.626 +#else 1.627 + int si = sizeof(ifr->ifr_name) + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)); 1.628 +#endif 1.629 + tl -= si; 1.630 + ptr += si; 1.631 + 1.632 + ifr2 = *ifr; 1.633 + 1.634 + e = ioctl(s,SIOCGIFADDR,&ifr2); 1.635 + if ( e == -1 ) 1.636 + { 1.637 + continue; 1.638 + } 1.639 + 1.640 + //r_log(NR_LOG_STUN, LOG_ERR, "ioctl addr e = %d",e); 1.641 + 1.642 + if ((r=nr_sockaddr_to_transport_addr(&ifr2.ifr_addr, sizeof(ifr2.ifr_addr), IPPROTO_UDP, 0, &(addrs[n].addr)))) { 1.643 + r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address"); 1.644 + } 1.645 + else { 1.646 + addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN; 1.647 + addrs[n].interface.estimated_speed = 0; 1.648 +#if defined(LINUX) && !defined(ANDROID) 1.649 + /* TODO (Bug 896851): interface property for Android */ 1.650 + /* Getting ethtool for ethernet information. */ 1.651 + ecmd.cmd = ETHTOOL_GSET; 1.652 + ifr2.ifr_data = (void*)&ecmd; 1.653 + e = ioctl(s, SIOCETHTOOL, &ifr2); 1.654 + if (e == 0) 1.655 + { 1.656 + /* For wireless network, we won't get ethtool, it's a wired 1.657 + connection */ 1.658 + addrs[n].interface.type = NR_INTERFACE_TYPE_WIRED; 1.659 +#ifdef DONT_HAVE_ETHTOOL_SPEED_HI 1.660 + addrs[n].interface.estimated_speed = ecmd.speed; 1.661 +#else 1.662 + addrs[n].interface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000; 1.663 +#endif 1.664 + } 1.665 + 1.666 + strncpy(wrq.ifr_name, ifr->ifr_name, sizeof(wrq.ifr_name)); 1.667 + e = ioctl(s, SIOCGIWRATE, &wrq); 1.668 + if (e == 0) 1.669 + { 1.670 + addrs[n].interface.type = NR_INTERFACE_TYPE_WIFI; 1.671 + addrs[n].interface.estimated_speed = wrq.u.bitrate.value / 1000; 1.672 + } 1.673 + 1.674 + ifr2 = *ifr; 1.675 + e = ioctl(s, SIOCGIFFLAGS, &ifr2); 1.676 + if (e == 0) 1.677 + { 1.678 + if (ifr2.ifr_flags & IFF_POINTOPOINT) 1.679 + { 1.680 + addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN; 1.681 + /* TODO (Bug 896913): find backend network type of this VPN */ 1.682 + } 1.683 + } 1.684 +#endif 1.685 + strlcpy(addrs[n].addr.ifname, ifr->ifr_name, sizeof(addrs[n].addr.ifname)); 1.686 + ++n; 1.687 + } 1.688 + } 1.689 + 1.690 + close(s); 1.691 + 1.692 + *count = n; 1.693 + 1.694 + _status = 0; 1.695 + return _status; 1.696 +} 1.697 +#endif 1.698 + 1.699 +static int 1.700 +nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr) 1.701 +{ 1.702 + int i; 1.703 + int different; 1.704 + 1.705 + for (i = 0; i < count; ++i) { 1.706 + different = nr_transport_addr_cmp(&addrs[i].addr, &(addr->addr), 1.707 + NR_TRANSPORT_ADDR_CMP_MODE_ALL); 1.708 + if (!different) 1.709 + return 1; /* duplicate */ 1.710 + } 1.711 + 1.712 + return 0; 1.713 +} 1.714 + 1.715 +int 1.716 +nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int *count) 1.717 +{ 1.718 + int r, _status; 1.719 + nr_local_addr *tmp = 0; 1.720 + int i; 1.721 + int n; 1.722 + 1.723 + tmp = RMALLOC(*count * sizeof(*tmp)); 1.724 + if (!tmp) 1.725 + ABORT(R_NO_MEMORY); 1.726 + 1.727 + n = 0; 1.728 + for (i = 0; i < *count; ++i) { 1.729 + if (nr_stun_is_duplicate_addr(tmp, n, &addrs[i])) { 1.730 + /* skip addrs[i], it's a duplicate */ 1.731 + } 1.732 + else if (remove_loopback && nr_transport_addr_is_loopback(&addrs[i].addr)) { 1.733 + /* skip addrs[i], it's a loopback */ 1.734 + } 1.735 + else { 1.736 + /* otherwise, copy it to the temporary array */ 1.737 + if ((r=nr_local_addr_copy(&tmp[n], &addrs[i]))) 1.738 + ABORT(r); 1.739 + ++n; 1.740 + } 1.741 + } 1.742 + 1.743 + *count = n; 1.744 + 1.745 + /* copy temporary array into passed in/out array */ 1.746 + for (i = 0; i < *count; ++i) { 1.747 + if ((r=nr_local_addr_copy(&addrs[i], &tmp[i]))) 1.748 + ABORT(r); 1.749 + } 1.750 + 1.751 + _status = 0; 1.752 + abort: 1.753 + RFREE(tmp); 1.754 + return _status; 1.755 +} 1.756 + 1.757 +#ifndef USE_PLATFORM_NR_STUN_GET_ADDRS 1.758 + 1.759 +int 1.760 +nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int drop_loopback, int *count) 1.761 +{ 1.762 + int _status=0; 1.763 + int i; 1.764 + char typestr[100]; 1.765 + 1.766 +#if defined(BSD) || defined(DARWIN) 1.767 + _status = stun_get_mib_addrs(addrs, maxaddrs, count); 1.768 +#elif defined(WIN32) 1.769 + _status = stun_get_win32_addrs(addrs, maxaddrs, count); 1.770 +#elif defined(__sparc__) 1.771 + _status = stun_get_sparc_addrs(addrs, maxaddrs, count); 1.772 +#else 1.773 + _status = stun_get_siocgifconf_addrs(addrs, maxaddrs, count); 1.774 +#endif 1.775 + 1.776 + nr_stun_remove_duplicate_addrs(addrs, drop_loopback, count); 1.777 + 1.778 + for (i = 0; i < *count; ++i) { 1.779 + nr_local_addr_fmt_info_string(addrs+i,typestr,sizeof(typestr)); 1.780 + r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s, type: %s\n", 1.781 + i,addrs[i].addr.as_string,addrs[i].addr.ifname,typestr); 1.782 + } 1.783 + 1.784 + return _status; 1.785 +} 1.786 + 1.787 +#endif