tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

addrs-bsd.c (3029B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #if defined(BSD) || defined(DARWIN)
      6 #include "addrs-bsd.h"
      7 #include <csi_platform.h>
      8 #include <assert.h>
      9 #include <string.h>
     10 #include "util.h"
     11 #include "stun_util.h"
     12 #include "util.h"
     13 #include <r_macros.h>
     14 
     15 #include <sys/types.h> /* getifaddrs */
     16 #include <ifaddrs.h> /* getifaddrs */
     17 #include <sys/socket.h>
     18 #include <sys/ioctl.h>
     19 #include <errno.h>
     20 #include <netinet/in.h>
     21 #include <netinet6/in6_var.h>
     22 
     23 static int
     24 stun_ifaddr_get_v6_flags(struct ifaddrs *ifaddr)
     25 {
     26  if (ifaddr->ifa_addr->sa_family != AF_INET6) {
     27    return 0;
     28  }
     29 
     30  int flags = 0;
     31  int s = socket(AF_INET6, SOCK_DGRAM, 0);
     32  if (!s) {
     33    r_log(NR_LOG_STUN, LOG_ERR, "socket(AF_INET6, SOCK_DGRAM, 0) failed, errno=%d", errno);
     34    assert(0);
     35    return 0;
     36  }
     37  struct in6_ifreq ifr6;
     38  memset(&ifr6, 0, sizeof(ifr6));
     39  strncpy(ifr6.ifr_name, ifaddr->ifa_name, sizeof(ifr6.ifr_name));
     40  /* ifr_addr is a sockaddr_in6, ifa_addr is a sockaddr* */
     41  struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)ifaddr->ifa_addr;
     42  ifr6.ifr_addr = *sin6;
     43  if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) != -1) {
     44    flags = ifr6.ifr_ifru.ifru_flags6;
     45  } else {
     46    r_log(NR_LOG_STUN, LOG_ERR, "ioctl(SIOCGIFAFLAG_IN6) failed, errno=%d", errno);
     47    assert(0);
     48  }
     49  close(s);
     50  return flags;
     51 }
     52 
     53 static int
     54 stun_ifaddr_is_disallowed_v6(int flags) {
     55  return flags & (IN6_IFF_ANYCAST | IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED);
     56 }
     57 
     58 int stun_getaddrs_filtered(nr_local_addr addrs[], int maxaddrs, int *count)
     59 {
     60  int r,_status,flags;
     61  struct ifaddrs* if_addrs_head=NULL;
     62  struct ifaddrs* if_addr;
     63 
     64  *count = 0;
     65 
     66  if (maxaddrs <= 0)
     67    ABORT(R_BAD_ARGS);
     68 
     69  if (getifaddrs(&if_addrs_head) == -1) {
     70    r_log(NR_LOG_STUN, LOG_ERR, "getifaddrs error e = %d", errno);
     71    ABORT(R_INTERNAL);
     72  }
     73 
     74  if_addr = if_addrs_head;
     75 
     76  while (if_addr && *count < maxaddrs) {
     77    /* This can be null */
     78    if (if_addr->ifa_addr) {
     79      switch (if_addr->ifa_addr->sa_family) {
     80        case AF_INET:
     81        case AF_INET6:
     82          flags = stun_ifaddr_get_v6_flags(if_addr);
     83          if (!stun_ifaddr_is_disallowed_v6(flags)) {
     84            if (r=nr_sockaddr_to_transport_addr(if_addr->ifa_addr, IPPROTO_UDP, 0, &(addrs[*count].addr))) {
     85              r_log(NR_LOG_STUN, LOG_ERR, "nr_sockaddr_to_transport_addr error r = %d", r);
     86            } else {
     87              if (flags & IN6_IFF_TEMPORARY) {
     88                addrs[*count].flags |= NR_ADDR_FLAG_TEMPORARY;
     89              }
     90              (void)strlcpy(addrs[*count].addr.ifname, if_addr->ifa_name, sizeof(addrs[*count].addr.ifname));
     91              ++(*count);
     92            }
     93          }
     94          break;
     95        default:
     96          ;
     97      }
     98    }
     99 
    100    if_addr = if_addr->ifa_next;
    101  }
    102 
    103  _status=0;
    104 abort:
    105  if (if_addrs_head) {
    106    freeifaddrs(if_addrs_head);
    107  }
    108  return(_status);
    109 }
    110 #endif