LCOV - code coverage report
Current view: top level - media/mtransport/third_party/nICEr/src/stun - addrs.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 75 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             : Copyright (c) 2007, Adobe Systems, Incorporated
       3             : All rights reserved.
       4             : 
       5             : Redistribution and use in source and binary forms, with or without
       6             : modification, are permitted provided that the following conditions are
       7             : met:
       8             : 
       9             : * Redistributions of source code must retain the above copyright
      10             :   notice, this list of conditions and the following disclaimer.
      11             : 
      12             : * Redistributions in binary form must reproduce the above copyright
      13             :   notice, this list of conditions and the following disclaimer in the
      14             :   documentation and/or other materials provided with the distribution.
      15             : 
      16             : * Neither the name of Adobe Systems, Network Resonance nor the names of its
      17             :   contributors may be used to endorse or promote products derived from
      18             :   this software without specific prior written permission.
      19             : 
      20             : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22             : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23             : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      24             : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      25             : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      26             : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      30             : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             : */
      32             : 
      33             : 
      34             : static char *RCSSTRING __UNUSED__="$Id: addrs.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
      35             : 
      36             : #include <csi_platform.h>
      37             : #include <assert.h>
      38             : #include <string.h>
      39             : 
      40             : #ifdef WIN32
      41             : #include <winsock2.h>
      42             : #include <iphlpapi.h>
      43             : #include <tchar.h>
      44             : #else   /* !WIN32 */
      45             : 
      46             : #include <sys/socket.h>
      47             : #include <sys/ioctl.h>
      48             : #include <errno.h>
      49             : 
      50             : #ifndef ANDROID
      51             : /* This works on linux and BSD, but not android */
      52             : #include <sys/types.h> /* getifaddrs */
      53             : #include <ifaddrs.h> /* getifaddrs */
      54             : #else
      55             : #include "ifaddrs-android.h"
      56             : #define getifaddrs android_getifaddrs
      57             : #define freeifaddrs android_freeifaddrs
      58             : #endif
      59             : 
      60             : #ifdef LINUX
      61             : 
      62             : #ifdef ANDROID
      63             : /* Work around an Android NDK < r8c bug */
      64             : #undef __unused
      65             : #else
      66             : #include <linux/if.h> /* struct ifreq, IFF_POINTTOPOINT */
      67             : #include <linux/wireless.h> /* struct iwreq */
      68             : #include <linux/ethtool.h> /* struct ethtool_cmd */
      69             : #include <linux/sockios.h> /* SIOCETHTOOL */
      70             : #endif /* ANDROID */
      71             : 
      72             : #endif /* LINUX */
      73             : 
      74             : #endif  /* !WIN32 */
      75             : 
      76             : #include "stun.h"
      77             : #include "addrs.h"
      78             : #include "nr_crypto.h"
      79             : #include "util.h"
      80             : 
      81             : #if defined(WIN32)
      82             : 
      83             : #define WIN32_MAX_NUM_INTERFACES  20
      84             : 
      85             : #define NR_MD5_HASH_LENGTH 16
      86             : 
      87             : #define _NR_MAX_KEY_LENGTH 256
      88             : #define _NR_MAX_NAME_LENGTH 512
      89             : 
      90             : #define _ADAPTERS_BASE_REG "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
      91             : 
      92             : static int nr_win32_get_adapter_friendly_name(char *adapter_GUID, char **friendly_name)
      93             : {
      94             :     int r,_status;
      95             :     HKEY adapter_reg;
      96             :     TCHAR adapter_key[_NR_MAX_KEY_LENGTH];
      97             :     TCHAR keyval_buf[_NR_MAX_KEY_LENGTH];
      98             :     TCHAR adapter_GUID_tchar[_NR_MAX_NAME_LENGTH];
      99             :     DWORD keyval_len, key_type;
     100             :     size_t converted_chars, newlen;
     101             :     char *my_fn = 0;
     102             : 
     103             : #ifdef _UNICODE
     104             :     mbstowcs_s(&converted_chars, adapter_GUID_tchar, strlen(adapter_GUID)+1,
     105             :                adapter_GUID, _TRUNCATE);
     106             : #else
     107             :     strlcpy(adapter_GUID_tchar, adapter_GUID, _NR_MAX_NAME_LENGTH);
     108             : #endif
     109             : 
     110             :     _tcscpy_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT(_ADAPTERS_BASE_REG));
     111             :     _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\"));
     112             :     _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, adapter_GUID_tchar);
     113             :     _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\Connection"));
     114             : 
     115             :     r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, adapter_key, 0, KEY_READ, &adapter_reg);
     116             : 
     117             :     if (r != ERROR_SUCCESS) {
     118             :       r_log(NR_LOG_STUN, LOG_ERR, "Got error %d opening adapter reg key\n", r);
     119             :       ABORT(R_INTERNAL);
     120             :     }
     121             : 
     122             :     keyval_len = sizeof(keyval_buf);
     123             :     r = RegQueryValueEx(adapter_reg, TEXT("Name"), NULL, &key_type,
     124             :                         (BYTE *)keyval_buf, &keyval_len);
     125             : 
     126             :     RegCloseKey(adapter_reg);
     127             : 
     128             : #ifdef UNICODE
     129             :     newlen = wcslen(keyval_buf)+1;
     130             :     my_fn = (char *) RCALLOC(newlen);
     131             :     if (!my_fn) {
     132             :       ABORT(R_NO_MEMORY);
     133             :     }
     134             :     wcstombs_s(&converted_chars, my_fn, newlen, keyval_buf, _TRUNCATE);
     135             : #else
     136             :     my_fn = r_strdup(keyval_buf);
     137             : #endif
     138             : 
     139             :     *friendly_name = my_fn;
     140             :     _status=0;
     141             : 
     142             : abort:
     143             :     if (_status) {
     144             :       if (my_fn) free(my_fn);
     145             :     }
     146             :     return(_status);
     147             : }
     148             : 
     149             : static int
     150             : stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
     151             : {
     152             :     int r, _status;
     153             :     PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL, tmpAddress = NULL;
     154             :     // recomended per https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx
     155             :     static const ULONG initialBufLen = 15000;
     156             :     ULONG buflen = initialBufLen;
     157             :     char bin_hashed_ifname[NR_MD5_HASH_LENGTH];
     158             :     char hex_hashed_ifname[MAXIFNAME];
     159             :     int n = 0;
     160             : 
     161             :     *count = 0;
     162             : 
     163             :     if (maxaddrs <= 0)
     164             :       ABORT(R_BAD_ARGS);
     165             : 
     166             :     /* According to MSDN (see above) we have try GetAdapterAddresses() multiple times */
     167             :     for (n = 0; n < 5; n++) {
     168             :       AdapterAddresses = (PIP_ADAPTER_ADDRESSES) RMALLOC(buflen);
     169             :       if (AdapterAddresses == NULL) {
     170             :         r_log(NR_LOG_STUN, LOG_ERR, "Error allocating buf for GetAdaptersAddresses()");
     171             :         ABORT(R_NO_MEMORY);
     172             :       }
     173             : 
     174             :       r = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, AdapterAddresses, &buflen);
     175             :       if (r == NO_ERROR) {
     176             :         break;
     177             :       }
     178             :       r_log(NR_LOG_STUN, LOG_ERR, "GetAdaptersAddresses() returned error (%d)", r);
     179             :       RFREE(AdapterAddresses);
     180             :       AdapterAddresses = NULL;
     181             :     }
     182             : 
     183             :     if (n >= 5) {
     184             :       r_log(NR_LOG_STUN, LOG_ERR, "5 failures calling GetAdaptersAddresses()");
     185             :       ABORT(R_INTERNAL);
     186             :     }
     187             : 
     188             :     n = 0;
     189             : 
     190             :     /* Loop through the adapters */
     191             : 
     192             :     for (tmpAddress = AdapterAddresses; tmpAddress != NULL; tmpAddress = tmpAddress->Next) {
     193             : 
     194             :       if (tmpAddress->OperStatus != IfOperStatusUp)
     195             :         continue;
     196             : 
     197             :       if ((tmpAddress->IfIndex != 0) || (tmpAddress->Ipv6IfIndex != 0)) {
     198             :         IP_ADAPTER_UNICAST_ADDRESS *u = 0;
     199             : 
     200             :         if(r=nr_crypto_md5((UCHAR *)tmpAddress->FriendlyName,
     201             :                            wcslen(tmpAddress->FriendlyName) * sizeof(wchar_t),
     202             :                            bin_hashed_ifname))
     203             :           ABORT(r);
     204             :         if(r=nr_bin2hex(bin_hashed_ifname, sizeof(bin_hashed_ifname),
     205             :           hex_hashed_ifname))
     206             :           ABORT(r);
     207             : 
     208             :         for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) {
     209             :           SOCKET_ADDRESS *sa_addr = &u->Address;
     210             : 
     211             :           if ((sa_addr->lpSockaddr->sa_family == AF_INET) ||
     212             :               (sa_addr->lpSockaddr->sa_family == AF_INET6)) {
     213             :             if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, IPPROTO_UDP, 0, &(addrs[n].addr))))
     214             :                 ABORT(r);
     215             :           }
     216             :           else {
     217             :             r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized sa_family for address on adapter %lu", tmpAddress->IfIndex);
     218             :             continue;
     219             :           }
     220             : 
     221             :           strlcpy(addrs[n].addr.ifname, hex_hashed_ifname, sizeof(addrs[n].addr.ifname));
     222             :           if (tmpAddress->IfType == IF_TYPE_ETHERNET_CSMACD) {
     223             :             addrs[n].interface.type = NR_INTERFACE_TYPE_WIRED;
     224             :           } else if (tmpAddress->IfType == IF_TYPE_IEEE80211) {
     225             :             /* Note: this only works for >= Win Vista */
     226             :             addrs[n].interface.type = NR_INTERFACE_TYPE_WIFI;
     227             :           } else {
     228             :             addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
     229             :           }
     230             : #if (_WIN32_WINNT >= 0x0600)
     231             :           /* Note: only >= Vista provide link speed information */
     232             :           addrs[n].interface.estimated_speed = tmpAddress->TransmitLinkSpeed / 1000;
     233             : #else
     234             :           addrs[n].interface.estimated_speed = 0;
     235             : #endif
     236             :           if (++n >= maxaddrs)
     237             :             goto done;
     238             :         }
     239             :       }
     240             :     }
     241             : 
     242             :    done:
     243             :     *count = n;
     244             :     _status = 0;
     245             : 
     246             :   abort:
     247             :     RFREE(AdapterAddresses);
     248             :     return _status;
     249             : }
     250             : 
     251             : #else /* WIN32 */
     252             : 
     253             : static int
     254             : nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr);
     255             : 
     256             : static int
     257           0 : stun_getifaddrs(nr_local_addr addrs[], int maxaddrs, int *count)
     258             : {
     259             :   int r,_status;
     260           0 :   struct ifaddrs* if_addrs_head=NULL;
     261             :   struct ifaddrs* if_addr;
     262             : 
     263           0 :   *count = 0;
     264             : 
     265           0 :   if (maxaddrs <= 0)
     266           0 :     ABORT(R_BAD_ARGS);
     267             : 
     268           0 :   if (getifaddrs(&if_addrs_head) == -1) {
     269           0 :     r_log(NR_LOG_STUN, LOG_ERR, "getifaddrs error e = %d", errno);
     270           0 :     ABORT(R_INTERNAL);
     271             :   }
     272             : 
     273           0 :   if_addr = if_addrs_head;
     274             : 
     275           0 :   while (if_addr && *count < maxaddrs) {
     276             :     /* This can be null */
     277           0 :     if (if_addr->ifa_addr) {
     278           0 :       switch (if_addr->ifa_addr->sa_family) {
     279             :         case AF_INET:
     280             :         case AF_INET6:
     281           0 :           if (r=nr_sockaddr_to_transport_addr(if_addr->ifa_addr, IPPROTO_UDP, 0, &(addrs[*count].addr))) {
     282           0 :             r_log(NR_LOG_STUN, LOG_ERR, "nr_sockaddr_to_transport_addr error r = %d", r);
     283             :           } else {
     284             : #if defined(LINUX) && !defined(ANDROID)
     285             :             struct ethtool_cmd ecmd;
     286             :             struct ifreq ifr;
     287             :             struct iwreq wrq;
     288             :             int e;
     289           0 :             int s = socket(AF_INET, SOCK_DGRAM, 0);
     290             : 
     291           0 :             strncpy(ifr.ifr_name, if_addr->ifa_name, sizeof(ifr.ifr_name));
     292             :             /* TODO (Bug 896851): interface property for Android */
     293             :             /* Getting ethtool for ethernet information. */
     294           0 :             ecmd.cmd = ETHTOOL_GSET;
     295             :             /* In/out param */
     296           0 :             ifr.ifr_data = (void*)&ecmd;
     297             : 
     298           0 :             e = ioctl(s, SIOCETHTOOL, &ifr);
     299           0 :             if (e == 0)
     300             :             {
     301             :                /* For wireless network, we won't get ethtool, it's a wired
     302             :                 * connection */
     303           0 :                addrs[*count].interface.type = NR_INTERFACE_TYPE_WIRED;
     304             : #ifdef DONT_HAVE_ETHTOOL_SPEED_HI
     305             :                addrs[*count].interface.estimated_speed = ecmd.speed;
     306             : #else
     307           0 :                addrs[*count].interface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000;
     308             : #endif
     309             :             }
     310             : 
     311           0 :             strncpy(wrq.ifr_name, if_addr->ifa_name, sizeof(wrq.ifr_name));
     312           0 :             e = ioctl(s, SIOCGIWRATE, &wrq);
     313           0 :             if (e == 0)
     314             :             {
     315           0 :                addrs[*count].interface.type = NR_INTERFACE_TYPE_WIFI;
     316           0 :                addrs[*count].interface.estimated_speed = wrq.u.bitrate.value / 1000;
     317             :             }
     318             : 
     319           0 :             close(s);
     320             : 
     321           0 :             if (if_addr->ifa_flags & IFF_POINTOPOINT)
     322             :             {
     323           0 :                addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN;
     324             :                /* TODO (Bug 896913): find backend network type of this VPN */
     325             :             }
     326             : #else
     327             :             addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
     328             :             addrs[*count].interface.estimated_speed = 0;
     329             : #endif
     330           0 :             strlcpy(addrs[*count].addr.ifname, if_addr->ifa_name, sizeof(addrs[*count].addr.ifname));
     331           0 :             ++(*count);
     332             :           }
     333           0 :           break;
     334             :         default:
     335             :           ;
     336             :       }
     337             :     }
     338             : 
     339           0 :     if_addr = if_addr->ifa_next;
     340             :   }
     341             : 
     342           0 :   _status=0;
     343             : abort:
     344           0 :   if (if_addrs_head) {
     345           0 :     freeifaddrs(if_addrs_head);
     346             :   }
     347           0 :   return(_status);
     348             : }
     349             : 
     350             : #endif
     351             : 
     352             : static int
     353           0 : nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr)
     354             : {
     355             :     int i;
     356             :     int different;
     357             : 
     358           0 :     for (i = 0; i < count; ++i) {
     359           0 :         different = nr_transport_addr_cmp(&addrs[i].addr, &(addr->addr),
     360             :           NR_TRANSPORT_ADDR_CMP_MODE_ALL);
     361           0 :         if (!different)
     362           0 :             return 1;  /* duplicate */
     363             :     }
     364             : 
     365           0 :     return 0;
     366             : }
     367             : 
     368             : int
     369           0 : nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int remove_link_local, int *count)
     370             : {
     371             :     int r, _status;
     372           0 :     nr_local_addr *tmp = 0;
     373             :     int i;
     374             :     int n;
     375             : 
     376           0 :     tmp = RMALLOC(*count * sizeof(*tmp));
     377           0 :     if (!tmp)
     378           0 :         ABORT(R_NO_MEMORY);
     379             : 
     380           0 :     n = 0;
     381           0 :     for (i = 0; i < *count; ++i) {
     382           0 :         if (nr_stun_is_duplicate_addr(tmp, n, &addrs[i])) {
     383             :             /* skip addrs[i], it's a duplicate */
     384             :         }
     385           0 :         else if (remove_loopback && nr_transport_addr_is_loopback(&addrs[i].addr)) {
     386             :             /* skip addrs[i], it's a loopback */
     387             :         }
     388           0 :         else if (remove_link_local &&
     389           0 :                  addrs[i].addr.ip_version == NR_IPV6 &&
     390           0 :                  nr_transport_addr_is_link_local(&addrs[i].addr)) {
     391             :             /* skip addrs[i], it's a link-local address */
     392             :         }
     393             :         else {
     394             :             /* otherwise, copy it to the temporary array */
     395           0 :             if ((r=nr_local_addr_copy(&tmp[n], &addrs[i])))
     396           0 :                 ABORT(r);
     397           0 :             ++n;
     398             :         }
     399             :     }
     400             : 
     401           0 :     *count = n;
     402             : 
     403           0 :     memset(addrs, 0, *count * sizeof(*addrs));
     404             :     /* copy temporary array into passed in/out array */
     405           0 :     for (i = 0; i < *count; ++i) {
     406           0 :         if ((r=nr_local_addr_copy(&addrs[i], &tmp[i])))
     407           0 :             ABORT(r);
     408             :     }
     409             : 
     410           0 :     _status = 0;
     411             :   abort:
     412           0 :     RFREE(tmp);
     413           0 :     return _status;
     414             : }
     415             : 
     416             : #ifndef USE_PLATFORM_NR_STUN_GET_ADDRS
     417             : 
     418             : int
     419           0 : nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
     420             : {
     421           0 :     int _status=0;
     422             :     int i;
     423             :     char typestr[100];
     424             : 
     425             : #ifdef WIN32
     426             :     _status = stun_get_win32_addrs(addrs, maxaddrs, count);
     427             : #else
     428           0 :     _status = stun_getifaddrs(addrs, maxaddrs, count);
     429             : #endif
     430             : 
     431           0 :     for (i = 0; i < *count; ++i) {
     432           0 :       nr_local_addr_fmt_info_string(addrs+i,typestr,sizeof(typestr));
     433           0 :       r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s, type: %s\n",
     434           0 :             i,addrs[i].addr.as_string,addrs[i].addr.ifname,typestr);
     435             :     }
     436             : 
     437           0 :     return _status;
     438             : }
     439             : 
     440             : #endif

Generated by: LCOV version 1.13