media/mtransport/third_party/nICEr/src/stun/addrs.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2 Copyright (c) 2007, Adobe Systems, Incorporated
     3 All rights reserved.
     5 Redistribution and use in source and binary forms, with or without
     6 modification, are permitted provided that the following conditions are
     7 met:
     9 * Redistributions of source code must retain the above copyright
    10   notice, this list of conditions and the following disclaimer.
    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.
    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.
    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 */
    34 static char *RCSSTRING __UNUSED__="$Id: addrs.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
    36 #include <csi_platform.h>
    37 #include <assert.h>
    38 #include <string.h>
    40 #ifdef WIN32
    41 #include <winsock2.h>
    42 #include <iphlpapi.h>
    43 #include <tchar.h>
    44 #else   /* UNIX */
    45 #include <sys/param.h>
    46 #include <sys/socket.h>
    47 #ifndef ANDROID
    48 #include <sys/sysctl.h>
    49 #include <sys/syslog.h>
    50 #else
    51 #include <syslog.h>
    52 /* Work around an Android NDK < r8c bug */
    53 #undef __unused
    54 #include <linux/sysctl.h>
    55 #endif
    56 #include <net/if.h>
    57 #ifndef LINUX
    58 #if !defined(__OpenBSD__) && !defined(__NetBSD__)
    59 #include <net/if_var.h>
    60 #endif
    61 #include <net/if_dl.h>
    62 #include <net/if_types.h>
    63 #include <sys/sockio.h>
    64 #else
    65 #include <linux/sockios.h>
    66 #include <linux/if.h>
    67 #include <linux/kernel.h>
    68 #include <linux/wireless.h>
    69 #ifndef ANDROID
    70 #include <linux/ethtool.h>
    71 #endif
    72 #endif
    73 #include <net/route.h>
    75 /* IP */
    76 #include <netinet/in.h>
    77 #ifdef LINUX
    78 #include "sys/ioctl.h"
    79 #else
    80 #include <netinet/in_var.h>
    81 #endif
    82 #include <arpa/inet.h>
    83 #include <netdb.h>
    84 #endif  /* UNIX */
    86 #include "stun.h"
    87 #include "addrs.h"
    91 #if defined(BSD) || defined(DARWIN)
    92 /*
    93  * Copyright (c) 1983, 1993
    94  *    The Regents of the University of California.  All rights reserved.
    95  *
    96  * Redistribution and use in source and binary forms, with or without
    97  * modification, are permitted provided that the following conditions
    98  * are met:
    99  * 1. Redistributions of source code must retain the above copyright
   100  *    notice, this list of conditions and the following disclaimer.
   101  * 2. Redistributions in binary form must reproduce the above copyright
   102  *    notice, this list of conditions and the following disclaimer in the
   103  *    documentation and/or other materials provided with the distribution.
   104  *[3 Deleted as of 22nd July 1999; see
   105  *    ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
   106  *    for details]
   107  * 4. Neither the name of the University nor the names of its contributors
   108  *    may be used to endorse or promote products derived from this software
   109  *    without specific prior written permission.
   110  *
   111  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   112  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   113  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   114  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   115  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   116  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   117  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   118  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   119  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   120  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   121  * SUCH DAMAGE.
   122  */
   124 #include <err.h>
   126 static void stun_rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
   127 static int stun_grab_addrs(char *name, int addrcount,
   128                struct ifa_msghdr *ifam,
   129                nr_local_addr addrs[], int maxaddrs, int *count);
   130 static int
   131 nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr);
   134 /*
   135  * Expand the compacted form of addresses as returned via the
   136  * configuration read via sysctl().
   137  */
   138 #define ROUNDUP(a) \
   139     ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
   140 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
   142 static void
   143 stun_rt_xaddrs(cp, cplim, rtinfo)
   144     caddr_t cp, cplim;
   145     struct rt_addrinfo *rtinfo;
   146 {
   147     struct sockaddr *sa;
   148     int i;
   150     memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
   151     for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
   152         if ((rtinfo->rti_addrs & (1 << i)) == 0)
   153             continue;
   154         rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
   155         ADVANCE(cp, sa);
   156     }
   157 }
   159 static int
   160 stun_grab_addrs(char *name, int addrcount, struct ifa_msghdr *ifam, nr_local_addr addrs[], int maxaddrs, int *count)
   161 {
   162     int r,_status;
   163     int s = -1;
   164     struct ifreq ifr;
   165     struct rt_addrinfo info;
   166     struct sockaddr_in *sin;
   168     ifr.ifr_addr.sa_family = AF_INET;
   169     strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
   171     if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) {
   172       r_log(NR_LOG_STUN, LOG_ERR, "unable to obtain addresses from socket");
   173       ABORT(R_FAILED);
   174     }
   176     while (addrcount > 0) {
   177         info.rti_addrs = ifam->ifam_addrs;
   179         /* Expand the compacted addresses */
   180         stun_rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info);
   181         addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
   182         addrs[*count].interface.estimated_speed = 0;
   183         /* TODO (Bug 895790) Get interface properties for Darwin */
   185         switch (info.rti_info[RTAX_IFA]->sa_family) {
   186         case AF_INET:
   187             sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA];
   189             if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sin, sizeof(*sin), IPPROTO_UDP, 0, &(addrs[*count].addr))))
   190                 ABORT(r);
   192             strlcpy(addrs[*count].addr.ifname, name, sizeof(addrs[*count].addr.ifname));
   194             ++*count;
   195             break;
   196         case AF_INET6:
   197             UNIMPLEMENTED;
   198             break;
   199         }
   201         addrcount--;
   203         if (*count >= maxaddrs) {
   204             r_log(NR_LOG_STUN, LOG_WARNING, "Address list truncated at %d out of %d entries", maxaddrs, maxaddrs+addrcount);
   205             break;
   206         }
   208         ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
   209     }
   211     _status = 0;
   212   abort:
   213     if (s != -1) close(s);
   214     return _status;
   215 }
   217 static int
   218 stun_get_mib_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
   219 {
   220     int _status;
   221     char name[32];
   222     int flags;
   223     int addrcount;
   224     struct if_msghdr *ifm, *nextifm;
   225     struct ifa_msghdr *ifam;
   226     struct sockaddr_dl *sdl;
   227     char *buf = 0;
   228     char *lim;
   229     char *next;
   230     size_t needed;
   231     int mib[6];
   233     *count = 0;
   235     mib[0] = CTL_NET;
   236     mib[1] = PF_ROUTE;
   237     mib[2] = 0;
   238     mib[3] = AF_INET;
   239     mib[4] = NET_RT_IFLIST;
   240     mib[5] = 0;
   242     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
   243         errx(1, "iflist-sysctl-estimate");
   244     if ((buf = malloc(needed)) == NULL)
   245         errx(1, "malloc");
   246     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
   247         errx(1, "actual retrieval of interface table");
   248     lim = buf + needed;
   250     next = buf;
   251     while (next < lim) {
   252         ifm = (struct if_msghdr *)next;
   254         if (ifm->ifm_type == RTM_IFINFO) {
   255             sdl = (struct sockaddr_dl *)(ifm + 1);
   256             flags = ifm->ifm_flags;
   257         } else {
   258             r_log(NR_LOG_STUN, LOG_WARNING, "out of sync parsing NET_RT_IFLIST");
   259             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);
   260             ABORT(R_FAILED);
   261         }
   263         next += ifm->ifm_msglen;
   264         ifam = NULL;
   265         addrcount = 0;
   266         while (next < lim) {
   268             nextifm = (struct if_msghdr *)next;
   270             if (nextifm->ifm_type != RTM_NEWADDR)
   271                 break;
   273             if (ifam == NULL)
   274                 ifam = (struct ifa_msghdr *)nextifm;
   276             addrcount++;
   277             next += nextifm->ifm_msglen;
   278         }
   280         if (sdl->sdl_nlen > sizeof(name) - 1) {
   281             ABORT(R_INTERNAL);
   282         }
   284         memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
   285         name[sdl->sdl_nlen] = '\0';
   287         stun_grab_addrs(name, addrcount, ifam, addrs, maxaddrs, count);
   288     }
   290     _status = 0;
   291 abort:
   292     if (buf) free(buf);
   293     return _status;
   294 }
   296 #elif defined(WIN32)
   298 #define WIN32_MAX_NUM_INTERFACES  20
   301 #define _NR_MAX_KEY_LENGTH 256
   302 #define _NR_MAX_NAME_LENGTH 512
   304 #define _ADAPTERS_BASE_REG "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
   306 static int nr_win32_get_adapter_friendly_name(char *adapter_GUID, char **friendly_name)
   307 {
   308     int r,_status;
   309     HKEY adapter_reg;
   310     TCHAR adapter_key[_NR_MAX_KEY_LENGTH];
   311     TCHAR keyval_buf[_NR_MAX_KEY_LENGTH];
   312     TCHAR adapter_GUID_tchar[_NR_MAX_NAME_LENGTH];
   313     DWORD keyval_len, key_type;
   314     size_t converted_chars, newlen;
   315     char *my_fn = 0;
   317 #ifdef _UNICODE
   318     mbstowcs_s(&converted_chars, adapter_GUID_tchar, strlen(adapter_GUID)+1,
   319                adapter_GUID, _TRUNCATE);
   320 #else
   321     strlcpy(adapter_GUID_tchar, adapter_GUID, _NR_MAX_NAME_LENGTH);
   322 #endif
   324     _tcscpy_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT(_ADAPTERS_BASE_REG));
   325     _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\"));
   326     _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, adapter_GUID_tchar);
   327     _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\Connection"));
   329     r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, adapter_key, 0, KEY_READ, &adapter_reg);
   331     if (r != ERROR_SUCCESS) {
   332       r_log(NR_LOG_STUN, LOG_ERR, "Got error %d opening adapter reg key\n", r);
   333       ABORT(R_INTERNAL);
   334     }
   336     keyval_len = sizeof(keyval_buf);
   337     r = RegQueryValueEx(adapter_reg, TEXT("Name"), NULL, &key_type,
   338                         (BYTE *)keyval_buf, &keyval_len);
   340     RegCloseKey(adapter_reg);
   342 #ifdef UNICODE
   343     newlen = wcslen(keyval_buf)+1;
   344     my_fn = (char *) RCALLOC(newlen);
   345     if (!my_fn) {
   346       ABORT(R_NO_MEMORY);
   347     }
   348     wcstombs_s(&converted_chars, my_fn, newlen, keyval_buf, _TRUNCATE);
   349 #else
   350     my_fn = r_strdup(keyval_buf);
   351 #endif
   353     *friendly_name = my_fn;
   354     _status=0;
   356 abort:
   357     if (_status) {
   358       if (my_fn) free(my_fn);
   359     }
   360     return(_status);
   361 }
   364 static int
   365 stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
   366 {
   367     int r,_status;
   368     PIP_ADAPTER_INFO pAdapterInfo;
   369     PIP_ADAPTER_INFO pAdapter = NULL;
   370     PIP_ADDR_STRING pAddrString;
   371     ULONG out_buf_len;
   372     char *friendly_name=0;
   373     char munged_ifname[IFNAMSIZ];
   374     int n = 0;
   376     *count = 0;
   378     pAdapterInfo = (IP_ADAPTER_INFO *) RMALLOC(sizeof(IP_ADAPTER_INFO));
   379     out_buf_len = sizeof(IP_ADAPTER_INFO);
   381     /* First call to GetAdaptersInfo is mainly to get length */
   383     if (GetAdaptersInfo(pAdapterInfo, &out_buf_len) == ERROR_BUFFER_OVERFLOW) {
   384       RFREE(pAdapterInfo);
   385       pAdapterInfo = (IP_ADAPTER_INFO *) RMALLOC(out_buf_len);
   386       if (pAdapterInfo == NULL) {
   387         r_log(NR_LOG_STUN, LOG_ERR, "Error allocating memory for GetAdaptersInfo output");
   388         ABORT(R_NO_MEMORY);
   389       }
   390     }
   391     if ((r = GetAdaptersInfo(pAdapterInfo, &out_buf_len)) != NO_ERROR) {
   392       r_log(NR_LOG_STUN, LOG_ERR, "Got error from GetAdaptersInfo");
   393       ABORT(R_INTERNAL);
   394     }
   395     r_log(NR_LOG_STUN, LOG_DEBUG, "Got AdaptersInfo");
   397     pAdapter = pAdapterInfo;
   399     while (pAdapter) {
   400       char *c;
   402       r_log(NR_LOG_STUN, LOG_DEBUG, "Adapter Name (GUID) = %s", pAdapter->AdapterName);
   403       r_log(NR_LOG_STUN, LOG_DEBUG, "Adapter Description = %s", pAdapter->Description);
   405       if (nr_win32_get_adapter_friendly_name(pAdapter->AdapterName, &friendly_name)) {
   406         friendly_name = 0;
   407       }
   408       if (friendly_name && *friendly_name) {
   409         r_log(NR_LOG_STUN, LOG_INFO, "Found adapter with friendly name: %s", friendly_name);
   410         snprintf(munged_ifname, IFNAMSIZ, "%s%c", friendly_name, 0);
   411         RFREE(friendly_name);
   412         friendly_name = 0;
   413       } else {
   414         // Not all adapters follow the friendly name convention. Windows' PPTP
   415         // VPN adapter puts "VPN Connection 2" in the Description field instead.
   416         // Windows's renaming-logic appears to enforce uniqueness in spite of this.
   417         r_log(NR_LOG_STUN, LOG_INFO, "Found adapter with description: %s", pAdapter->Description);
   418         snprintf(munged_ifname, IFNAMSIZ, "%s%c", pAdapter->Description, 0);
   419       }
   420       /* replace spaces with underscores */
   421       c = strchr(munged_ifname, ' ');
   422       while (c != NULL) {
   423         *c = '_';
   424          c = strchr(munged_ifname, ' ');
   425       }
   426       c = strchr(munged_ifname, '.');
   427       while (c != NULL) {
   428         *c = '+';
   429          c = strchr(munged_ifname, '.');
   430       }
   432       r_log(NR_LOG_STUN, LOG_INFO, "Converted ifname: %s", munged_ifname);
   434       for (pAddrString = &(pAdapter->IpAddressList); pAddrString != NULL; pAddrString = pAddrString->Next) {
   435         unsigned long this_addr = inet_addr(pAddrString->IpAddress.String);
   436         nr_transport_addr *addr = &(addrs[n].addr);
   438         if (this_addr == 0)
   439           continue;
   441         r_log(NR_LOG_STUN, LOG_INFO, "Adapter %s address: %s", munged_ifname, pAddrString->IpAddress.String);
   443         addr->ip_version=NR_IPV4;
   444         addr->protocol = IPPROTO_UDP;
   446         addr->u.addr4.sin_family=PF_INET;
   447         addr->u.addr4.sin_port=0;
   448         addr->u.addr4.sin_addr.s_addr=this_addr;
   449         addr->addr=(struct sockaddr *)&(addr->u.addr4);
   450         addr->addr_len=sizeof(struct sockaddr_in);
   452         strlcpy(addr->ifname, munged_ifname, sizeof(addr->ifname));
   453         snprintf(addr->as_string,40,"IP4:%s:%d",
   454                  inet_ntoa(addr->u.addr4.sin_addr),
   455                  ntohs(addr->u.addr4.sin_port));
   457         /* TODO: (Bug 895793) Getting interface properties for Windows */
   458         addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
   459         addrs[n].interface.estimated_speed = 0;
   461         if (++n >= maxaddrs)
   462           goto done;
   463       }
   465       pAdapter = pAdapter->Next;
   466     }
   468   done:
   469     *count = n;
   470     _status = 0;
   472   abort:
   473     RFREE(pAdapterInfo);
   474     RFREE(friendly_name);
   475     return _status;
   476 }
   478 #ifdef GET_WIN32_ADDRS_NO_WIN2K
   479    /* Here's a nice way to get adapter addresses and names, but it
   480     * isn't supported on Win2000.
   481     */
   482 static int
   483 stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
   484 {
   485     int r,_status;
   486     PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL, tmpAddress = NULL;
   487     ULONG buflen;
   488     char munged_ifname[IFNAMSIZ];
   489     int n = 0;
   491     *count = 0;
   493     if (maxaddrs <= 0)
   494       ABORT(R_INTERNAL);
   496     /* Call GetAdaptersAddresses() twice.  First, just to get the buf length */
   498     buflen = 0;
   500     r = GetAdaptersAddresses(AF_INET, 0, NULL, AdapterAddresses, &buflen);
   501     if (r != ERROR_BUFFER_OVERFLOW) {
   502       r_log(NR_LOG_STUN, LOG_ERR, "Error getting buf len from GetAdaptersAddresses()");
   503       ABORT(R_INTERNAL);
   504     }
   506     AdapterAddresses = (PIP_ADAPTER_ADDRESSES) RMALLOC(buflen);
   507     if (AdapterAddresses == NULL) {
   508       r_log(NR_LOG_STUN, LOG_ERR, "Error allocating buf for GetAdaptersAddresses()");
   509       ABORT(R_NO_MEMORY);
   510     }
   512     /* for real, this time */
   514     r = GetAdaptersAddresses(AF_INET, 0, NULL, AdapterAddresses, &buflen);
   515     if (r != NO_ERROR) {
   516       r_log(NR_LOG_STUN, LOG_ERR, "Error getting addresses from GetAdaptersAddresses()");
   517       ABORT(R_INTERNAL);
   518     }
   520     /* Loop through the adapters */
   522     for (tmpAddress = AdapterAddresses; tmpAddress != NULL; tmpAddress = tmpAddress->Next) {
   523       char *c;
   525       if (tmpAddress->OperStatus != IfOperStatusUp)
   526         continue;
   528       snprintf(munged_ifname, IFNAMSIZ, "%S%c", tmpAddress->FriendlyName, 0);
   529       /* replace spaces with underscores */
   530       c = strchr(munged_ifname, ' ');
   531       while (c != NULL) {
   532         *c = '_';
   533          c = strchr(munged_ifname, ' ');
   534       }
   535       c = strchr(munged_ifname, '.');
   536       while (c != NULL) {
   537         *c = '+';
   538          c = strchr(munged_ifname, '+');
   539       }
   541       if ((tmpAddress->IfIndex != 0) || (tmpAddress->Ipv6IfIndex != 0)) {
   542         IP_ADAPTER_UNICAST_ADDRESS *u = 0;
   544         for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) {
   545           SOCKET_ADDRESS *sa_addr = &u->Address;
   547           if ((sa_addr->lpSockaddr->sa_family == AF_INET) ||
   548               (sa_addr->lpSockaddr->sa_family == AF_INET6)) {
   549             if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, sizeof(*sa_addr->lpSockaddr), IPPROTO_UDP, 0, &(addrs[n].addr))))
   550                 ABORT(r);
   551           }
   552           else {
   553             r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized sa_family for adapteraddress %s",munged_ifname);
   554             continue;
   555           }
   557           strlcpy(addrs[n].addr.ifname, munged_ifname, sizeof(addrs[n].addr.ifname));
   558           /* TODO: (Bug 895793) Getting interface properties for Windows */
   559           addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
   560           addrs[n].interface.estimated_speed = 0;
   561           if (++n >= maxaddrs)
   562             goto done;
   563         }
   564       }
   565     }
   567    done:
   568     *count = n;
   569     _status = 0;
   571   abort:
   572     RFREE(AdapterAddresses);
   573     return _status;
   574 }
   575 #endif  /* GET_WIN32_ADDRS_NO_WIN2K */
   577 #elif defined(__sparc__)
   579 static int
   580 stun_get_sparc_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
   581 {
   582     *count = 0;
   583     UNIMPLEMENTED; /*TODO !nn! - sparc */
   584     return 0;
   585 }
   587 #else
   589 static int
   590 stun_get_siocgifconf_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
   591 {
   592    struct ifconf ifc;
   593    int _status;
   594    int s = socket( AF_INET, SOCK_DGRAM, 0 );
   595    int len = 100 * sizeof(struct ifreq);
   596    int r;
   597    int e;
   598    char *ptr;
   599    int tl;
   600    int n;
   601    struct ifreq ifr2;
   603    char buf[ len ];
   605    ifc.ifc_len = len;
   606    ifc.ifc_buf = buf;
   608    e = ioctl(s,SIOCGIFCONF,&ifc);
   609    ptr = buf;
   610    tl = ifc.ifc_len;
   611    n=0;
   613    while ( (tl > 0) && ( n < maxaddrs) )
   614    {
   615       struct ifreq* ifr = (struct ifreq *)ptr;
   617 #ifdef LINUX
   618       int si = sizeof(struct ifreq);
   619 #ifndef ANDROID
   620       struct ethtool_cmd ecmd;
   621       struct iwreq wrq;
   622 #endif
   623 #else
   624       int si = sizeof(ifr->ifr_name) + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr));
   625 #endif
   626       tl -= si;
   627       ptr += si;
   629       ifr2 = *ifr;
   631       e = ioctl(s,SIOCGIFADDR,&ifr2);
   632       if ( e == -1 )
   633       {
   634           continue;
   635       }
   637       //r_log(NR_LOG_STUN, LOG_ERR, "ioctl addr e = %d",e);
   639       if ((r=nr_sockaddr_to_transport_addr(&ifr2.ifr_addr, sizeof(ifr2.ifr_addr), IPPROTO_UDP, 0, &(addrs[n].addr)))) {
   640           r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address");
   641       }
   642       else {
   643           addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
   644           addrs[n].interface.estimated_speed = 0;
   645 #if defined(LINUX) && !defined(ANDROID)
   646           /* TODO (Bug 896851): interface property for Android */
   647           /* Getting ethtool for ethernet information. */
   648           ecmd.cmd = ETHTOOL_GSET;
   649           ifr2.ifr_data = (void*)&ecmd;
   650           e = ioctl(s, SIOCETHTOOL, &ifr2);
   651           if (e == 0)
   652           {
   653              /* For wireless network, we won't get ethtool, it's a wired
   654                 connection */
   655              addrs[n].interface.type = NR_INTERFACE_TYPE_WIRED;
   656 #ifdef DONT_HAVE_ETHTOOL_SPEED_HI
   657              addrs[n].interface.estimated_speed = ecmd.speed;
   658 #else
   659              addrs[n].interface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000;
   660 #endif
   661           }
   663           strncpy(wrq.ifr_name, ifr->ifr_name, sizeof(wrq.ifr_name));
   664           e = ioctl(s, SIOCGIWRATE, &wrq);
   665           if (e == 0)
   666           {
   667              addrs[n].interface.type = NR_INTERFACE_TYPE_WIFI;
   668              addrs[n].interface.estimated_speed = wrq.u.bitrate.value / 1000;
   669           }
   671           ifr2 = *ifr;
   672           e = ioctl(s, SIOCGIFFLAGS, &ifr2);
   673           if (e == 0)
   674           {
   675              if (ifr2.ifr_flags & IFF_POINTOPOINT)
   676              {
   677                 addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN;
   678                 /* TODO (Bug 896913): find backend network type of this VPN */
   679              }
   680           }
   681 #endif
   682           strlcpy(addrs[n].addr.ifname, ifr->ifr_name, sizeof(addrs[n].addr.ifname));
   683           ++n;
   684       }
   685    }
   687    close(s);
   689    *count = n;
   691     _status = 0;
   692     return _status;
   693 }
   694 #endif
   696 static int
   697 nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr)
   698 {
   699     int i;
   700     int different;
   702     for (i = 0; i < count; ++i) {
   703         different = nr_transport_addr_cmp(&addrs[i].addr, &(addr->addr),
   704           NR_TRANSPORT_ADDR_CMP_MODE_ALL);
   705         if (!different)
   706             return 1;  /* duplicate */
   707     }
   709     return 0;
   710 }
   712 int
   713 nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int *count)
   714 {
   715     int r, _status;
   716     nr_local_addr *tmp = 0;
   717     int i;
   718     int n;
   720     tmp = RMALLOC(*count * sizeof(*tmp));
   721     if (!tmp)
   722         ABORT(R_NO_MEMORY);
   724     n = 0;
   725     for (i = 0; i < *count; ++i) {
   726         if (nr_stun_is_duplicate_addr(tmp, n, &addrs[i])) {
   727             /* skip addrs[i], it's a duplicate */
   728         }
   729         else if (remove_loopback && nr_transport_addr_is_loopback(&addrs[i].addr)) {
   730             /* skip addrs[i], it's a loopback */
   731         }
   732         else {
   733             /* otherwise, copy it to the temporary array */
   734             if ((r=nr_local_addr_copy(&tmp[n], &addrs[i])))
   735                 ABORT(r);
   736             ++n;
   737         }
   738     }
   740     *count = n;
   742     /* copy temporary array into passed in/out array */
   743     for (i = 0; i < *count; ++i) {
   744         if ((r=nr_local_addr_copy(&addrs[i], &tmp[i])))
   745             ABORT(r);
   746     }
   748     _status = 0;
   749   abort:
   750     RFREE(tmp);
   751     return _status;
   752 }
   754 #ifndef USE_PLATFORM_NR_STUN_GET_ADDRS
   756 int
   757 nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int drop_loopback, int *count)
   758 {
   759     int _status=0;
   760     int i;
   761     char typestr[100];
   763 #if defined(BSD) || defined(DARWIN)
   764     _status = stun_get_mib_addrs(addrs, maxaddrs, count);
   765 #elif defined(WIN32)
   766     _status = stun_get_win32_addrs(addrs, maxaddrs, count);
   767 #elif defined(__sparc__)
   768     _status = stun_get_sparc_addrs(addrs, maxaddrs, count);
   769 #else
   770     _status = stun_get_siocgifconf_addrs(addrs, maxaddrs, count);
   771 #endif
   773     nr_stun_remove_duplicate_addrs(addrs, drop_loopback, count);
   775     for (i = 0; i < *count; ++i) {
   776     nr_local_addr_fmt_info_string(addrs+i,typestr,sizeof(typestr));
   777         r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s, type: %s\n",
   778             i,addrs[i].addr.as_string,addrs[i].addr.ifname,typestr);
   779     }
   781     return _status;
   782 }
   784 #endif

mercurial