| OLD | NEW | 
 | (Empty) | 
|    1 /* |  | 
|    2  *  Copyright 2015 The WebRTC Project Authors. All rights reserved. |  | 
|    3  * |  | 
|    4  *  Use of this source code is governed by a BSD-style license |  | 
|    5  *  that can be found in the LICENSE file in the root of the source |  | 
|    6  *  tree. An additional intellectual property rights grant can be found |  | 
|    7  *  in the file PATENTS.  All contributing project authors may |  | 
|    8  *  be found in the AUTHORS file in the root of the source tree. |  | 
|    9  */ |  | 
|   10  |  | 
|   11 #include <memory> |  | 
|   12  |  | 
|   13 #include <net/if.h> |  | 
|   14 #include <sys/ioctl.h> |  | 
|   15 #include <unistd.h> |  | 
|   16  |  | 
|   17 #include "webrtc/base/checks.h" |  | 
|   18 #include "webrtc/base/ifaddrs_converter.h" |  | 
|   19 #include "webrtc/base/logging.h" |  | 
|   20  |  | 
|   21 #if !defined(WEBRTC_IOS) |  | 
|   22 #include <net/if_media.h> |  | 
|   23 #include <netinet/in_var.h> |  | 
|   24 #else  // WEBRTC_IOS |  | 
|   25 #define SCOPE6_ID_MAX 16 |  | 
|   26  |  | 
|   27 struct in6_addrlifetime { |  | 
|   28   time_t ia6t_expire;    /* valid lifetime expiration time */ |  | 
|   29   time_t ia6t_preferred; /* preferred lifetime expiration time */ |  | 
|   30   u_int32_t ia6t_vltime; /* valid lifetime */ |  | 
|   31   u_int32_t ia6t_pltime; /* prefix lifetime */ |  | 
|   32 }; |  | 
|   33  |  | 
|   34 struct in6_ifstat { |  | 
|   35   u_quad_t ifs6_in_receive;      /* # of total input datagram */ |  | 
|   36   u_quad_t ifs6_in_hdrerr;       /* # of datagrams with invalid hdr */ |  | 
|   37   u_quad_t ifs6_in_toobig;       /* # of datagrams exceeded MTU */ |  | 
|   38   u_quad_t ifs6_in_noroute;      /* # of datagrams with no route */ |  | 
|   39   u_quad_t ifs6_in_addrerr;      /* # of datagrams with invalid dst */ |  | 
|   40   u_quad_t ifs6_in_protounknown; /* # of datagrams with unknown proto */ |  | 
|   41                                  /* NOTE: increment on final dst if */ |  | 
|   42   u_quad_t ifs6_in_truncated;    /* # of truncated datagrams */ |  | 
|   43   u_quad_t ifs6_in_discard;      /* # of discarded datagrams */ |  | 
|   44                                  /* NOTE: fragment timeout is not here */ |  | 
|   45   u_quad_t ifs6_in_deliver;      /* # of datagrams delivered to ULP */ |  | 
|   46                                  /* NOTE: increment on final dst if */ |  | 
|   47   u_quad_t ifs6_out_forward;     /* # of datagrams forwarded */ |  | 
|   48                                  /* NOTE: increment on outgoing if */ |  | 
|   49   u_quad_t ifs6_out_request;     /* # of outgoing datagrams from ULP */ |  | 
|   50                                  /* NOTE: does not include forwrads */ |  | 
|   51   u_quad_t ifs6_out_discard;     /* # of discarded datagrams */ |  | 
|   52   u_quad_t ifs6_out_fragok;      /* # of datagrams fragmented */ |  | 
|   53   u_quad_t ifs6_out_fragfail;    /* # of datagrams failed on fragment */ |  | 
|   54   u_quad_t ifs6_out_fragcreat;   /* # of fragment datagrams */ |  | 
|   55                                  /* NOTE: this is # after fragment */ |  | 
|   56   u_quad_t ifs6_reass_reqd;      /* # of incoming fragmented packets */ |  | 
|   57                                  /* NOTE: increment on final dst if */ |  | 
|   58   u_quad_t ifs6_reass_ok;        /* # of reassembled packets */ |  | 
|   59                                  /* NOTE: this is # after reass */ |  | 
|   60                                  /* NOTE: increment on final dst if */ |  | 
|   61   u_quad_t ifs6_reass_fail;      /* # of reass failures */ |  | 
|   62                                  /* NOTE: may not be packet count */ |  | 
|   63                                  /* NOTE: increment on final dst if */ |  | 
|   64   u_quad_t ifs6_in_mcast;        /* # of inbound multicast datagrams */ |  | 
|   65   u_quad_t ifs6_out_mcast;       /* # of outbound multicast datagrams */ |  | 
|   66 }; |  | 
|   67 struct icmp6_ifstat { |  | 
|   68   /* |  | 
|   69    * Input statistics |  | 
|   70    */ |  | 
|   71   /* ipv6IfIcmpInMsgs, total # of input messages */ |  | 
|   72   u_quad_t ifs6_in_msg; |  | 
|   73   /* ipv6IfIcmpInErrors, # of input error messages */ |  | 
|   74   u_quad_t ifs6_in_error; |  | 
|   75   /* ipv6IfIcmpInDestUnreachs, # of input dest unreach errors */ |  | 
|   76   u_quad_t ifs6_in_dstunreach; |  | 
|   77   /* ipv6IfIcmpInAdminProhibs, # of input admin. prohibited errs */ |  | 
|   78   u_quad_t ifs6_in_adminprohib; |  | 
|   79   /* ipv6IfIcmpInTimeExcds, # of input time exceeded errors */ |  | 
|   80   u_quad_t ifs6_in_timeexceed; |  | 
|   81   /* ipv6IfIcmpInParmProblems, # of input parameter problem errors */ |  | 
|   82   u_quad_t ifs6_in_paramprob; |  | 
|   83   /* ipv6IfIcmpInPktTooBigs, # of input packet too big errors */ |  | 
|   84   u_quad_t ifs6_in_pkttoobig; |  | 
|   85   /* ipv6IfIcmpInEchos, # of input echo requests */ |  | 
|   86   u_quad_t ifs6_in_echo; |  | 
|   87   /* ipv6IfIcmpInEchoReplies, # of input echo replies */ |  | 
|   88   u_quad_t ifs6_in_echoreply; |  | 
|   89   /* ipv6IfIcmpInRouterSolicits, # of input router solicitations */ |  | 
|   90   u_quad_t ifs6_in_routersolicit; |  | 
|   91   /* ipv6IfIcmpInRouterAdvertisements, # of input router advertisements */ |  | 
|   92   u_quad_t ifs6_in_routeradvert; |  | 
|   93   /* ipv6IfIcmpInNeighborSolicits, # of input neighbor solicitations */ |  | 
|   94   u_quad_t ifs6_in_neighborsolicit; |  | 
|   95   /* ipv6IfIcmpInNeighborAdvertisements, # of input neighbor advs. */ |  | 
|   96   u_quad_t ifs6_in_neighboradvert; |  | 
|   97   /* ipv6IfIcmpInRedirects, # of input redirects */ |  | 
|   98   u_quad_t ifs6_in_redirect; |  | 
|   99   /* ipv6IfIcmpInGroupMembQueries, # of input MLD queries */ |  | 
|  100   u_quad_t ifs6_in_mldquery; |  | 
|  101   /* ipv6IfIcmpInGroupMembResponses, # of input MLD reports */ |  | 
|  102   u_quad_t ifs6_in_mldreport; |  | 
|  103   /* ipv6IfIcmpInGroupMembReductions, # of input MLD done */ |  | 
|  104   u_quad_t ifs6_in_mlddone; |  | 
|  105  |  | 
|  106   /* |  | 
|  107    * Output statistics. We should solve unresolved routing problem... |  | 
|  108    */ |  | 
|  109   /* ipv6IfIcmpOutMsgs, total # of output messages */ |  | 
|  110   u_quad_t ifs6_out_msg; |  | 
|  111   /* ipv6IfIcmpOutErrors, # of output error messages */ |  | 
|  112   u_quad_t ifs6_out_error; |  | 
|  113   /* ipv6IfIcmpOutDestUnreachs, # of output dest unreach errors */ |  | 
|  114   u_quad_t ifs6_out_dstunreach; |  | 
|  115   /* ipv6IfIcmpOutAdminProhibs, # of output admin. prohibited errs */ |  | 
|  116   u_quad_t ifs6_out_adminprohib; |  | 
|  117   /* ipv6IfIcmpOutTimeExcds, # of output time exceeded errors */ |  | 
|  118   u_quad_t ifs6_out_timeexceed; |  | 
|  119   /* ipv6IfIcmpOutParmProblems, # of output parameter problem errors */ |  | 
|  120   u_quad_t ifs6_out_paramprob; |  | 
|  121   /* ipv6IfIcmpOutPktTooBigs, # of output packet too big errors */ |  | 
|  122   u_quad_t ifs6_out_pkttoobig; |  | 
|  123   /* ipv6IfIcmpOutEchos, # of output echo requests */ |  | 
|  124   u_quad_t ifs6_out_echo; |  | 
|  125   /* ipv6IfIcmpOutEchoReplies, # of output echo replies */ |  | 
|  126   u_quad_t ifs6_out_echoreply; |  | 
|  127   /* ipv6IfIcmpOutRouterSolicits, # of output router solicitations */ |  | 
|  128   u_quad_t ifs6_out_routersolicit; |  | 
|  129   /* ipv6IfIcmpOutRouterAdvertisements, # of output router advs. */ |  | 
|  130   u_quad_t ifs6_out_routeradvert; |  | 
|  131   /* ipv6IfIcmpOutNeighborSolicits, # of output neighbor solicitations */ |  | 
|  132   u_quad_t ifs6_out_neighborsolicit; |  | 
|  133   /* ipv6IfIcmpOutNeighborAdvertisements, # of output neighbor advs. */ |  | 
|  134   u_quad_t ifs6_out_neighboradvert; |  | 
|  135   /* ipv6IfIcmpOutRedirects, # of output redirects */ |  | 
|  136   u_quad_t ifs6_out_redirect; |  | 
|  137   /* ipv6IfIcmpOutGroupMembQueries, # of output MLD queries */ |  | 
|  138   u_quad_t ifs6_out_mldquery; |  | 
|  139   /* ipv6IfIcmpOutGroupMembResponses, # of output MLD reports */ |  | 
|  140   u_quad_t ifs6_out_mldreport; |  | 
|  141   /* ipv6IfIcmpOutGroupMembReductions, # of output MLD done */ |  | 
|  142   u_quad_t ifs6_out_mlddone; |  | 
|  143 }; |  | 
|  144  |  | 
|  145 struct in6_ifreq { |  | 
|  146   char ifr_name[IFNAMSIZ]; |  | 
|  147   union { |  | 
|  148     struct sockaddr_in6 ifru_addr; |  | 
|  149     struct sockaddr_in6 ifru_dstaddr; |  | 
|  150     int ifru_flags; |  | 
|  151     int ifru_flags6; |  | 
|  152     int ifru_metric; |  | 
|  153     int ifru_intval; |  | 
|  154     caddr_t ifru_data; |  | 
|  155     struct in6_addrlifetime ifru_lifetime; |  | 
|  156     struct in6_ifstat ifru_stat; |  | 
|  157     struct icmp6_ifstat ifru_icmp6stat; |  | 
|  158     u_int32_t ifru_scope_id[SCOPE6_ID_MAX]; |  | 
|  159   } ifr_ifru; |  | 
|  160 }; |  | 
|  161  |  | 
|  162 #define SIOCGIFAFLAG_IN6 _IOWR('i', 73, struct in6_ifreq) |  | 
|  163  |  | 
|  164 #define IN6_IFF_ANYCAST 0x0001    /* anycast address */ |  | 
|  165 #define IN6_IFF_TENTATIVE 0x0002  /* tentative address */ |  | 
|  166 #define IN6_IFF_DUPLICATED 0x0004 /* DAD detected duplicate */ |  | 
|  167 #define IN6_IFF_DETACHED 0x0008   /* may be detached from the link */ |  | 
|  168 #define IN6_IFF_DEPRECATED 0x0010 /* deprecated address */ |  | 
|  169 #define IN6_IFF_TEMPORARY 0x0080  /* temporary (anonymous) address. */ |  | 
|  170  |  | 
|  171 #endif  // WEBRTC_IOS |  | 
|  172  |  | 
|  173 namespace rtc { |  | 
|  174  |  | 
|  175 namespace { |  | 
|  176  |  | 
|  177 class IPv6AttributesGetter { |  | 
|  178  public: |  | 
|  179   IPv6AttributesGetter(); |  | 
|  180   virtual ~IPv6AttributesGetter(); |  | 
|  181   bool IsInitialized() const; |  | 
|  182   bool GetIPAttributes(const char* ifname, |  | 
|  183                        const sockaddr* sock_addr, |  | 
|  184                        int* native_attributes); |  | 
|  185  |  | 
|  186  private: |  | 
|  187   // on MAC or IOS, we have to use ioctl with a socket to query an IPv6 |  | 
|  188   // interface's attribute. |  | 
|  189   int ioctl_socket_; |  | 
|  190 }; |  | 
|  191  |  | 
|  192 IPv6AttributesGetter::IPv6AttributesGetter() |  | 
|  193     : ioctl_socket_( |  | 
|  194           socket(AF_INET6, SOCK_DGRAM, 0 /* unspecified protocol */)) { |  | 
|  195   RTC_DCHECK_GE(ioctl_socket_, 0); |  | 
|  196 } |  | 
|  197  |  | 
|  198 bool IPv6AttributesGetter::IsInitialized() const { |  | 
|  199   return ioctl_socket_ >= 0; |  | 
|  200 } |  | 
|  201  |  | 
|  202 IPv6AttributesGetter::~IPv6AttributesGetter() { |  | 
|  203   if (!IsInitialized()) { |  | 
|  204     return; |  | 
|  205   } |  | 
|  206   close(ioctl_socket_); |  | 
|  207 } |  | 
|  208  |  | 
|  209 bool IPv6AttributesGetter::GetIPAttributes(const char* ifname, |  | 
|  210                                            const sockaddr* sock_addr, |  | 
|  211                                            int* native_attributes) { |  | 
|  212   if (!IsInitialized()) { |  | 
|  213     return false; |  | 
|  214   } |  | 
|  215  |  | 
|  216   struct in6_ifreq ifr = {}; |  | 
|  217   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); |  | 
|  218   memcpy(&ifr.ifr_ifru.ifru_addr, sock_addr, sock_addr->sa_len); |  | 
|  219   int rv = ioctl(ioctl_socket_, SIOCGIFAFLAG_IN6, &ifr); |  | 
|  220   if (rv >= 0) { |  | 
|  221     *native_attributes = ifr.ifr_ifru.ifru_flags; |  | 
|  222   } else { |  | 
|  223     LOG(LS_ERROR) << "ioctl returns " << errno; |  | 
|  224   } |  | 
|  225   return (rv >= 0); |  | 
|  226 } |  | 
|  227  |  | 
|  228 // Converts native IPv6 address attributes to net IPv6 address attributes.  If |  | 
|  229 // it returns false, the IP address isn't suitable for one-to-one communications |  | 
|  230 // applications and should be ignored. |  | 
|  231 bool ConvertNativeToIPAttributes(int native_attributes, int* net_attributes) { |  | 
|  232   // For MacOSX, we disallow addresses with attributes IN6_IFF_ANYCASE, |  | 
|  233   // IN6_IFF_DUPLICATED, IN6_IFF_TENTATIVE, and IN6_IFF_DETACHED as these are |  | 
|  234   // still progressing through duplicated address detection (DAD) or are not |  | 
|  235   // suitable for one-to-one communication applications. |  | 
|  236   if (native_attributes & (IN6_IFF_ANYCAST | IN6_IFF_DUPLICATED | |  | 
|  237                            IN6_IFF_TENTATIVE | IN6_IFF_DETACHED)) { |  | 
|  238     return false; |  | 
|  239   } |  | 
|  240  |  | 
|  241   if (native_attributes & IN6_IFF_TEMPORARY) { |  | 
|  242     *net_attributes |= IPV6_ADDRESS_FLAG_TEMPORARY; |  | 
|  243   } |  | 
|  244  |  | 
|  245   if (native_attributes & IN6_IFF_DEPRECATED) { |  | 
|  246     *net_attributes |= IPV6_ADDRESS_FLAG_DEPRECATED; |  | 
|  247   } |  | 
|  248  |  | 
|  249   return true; |  | 
|  250 } |  | 
|  251  |  | 
|  252 class MacIfAddrsConverter : public IfAddrsConverter { |  | 
|  253  public: |  | 
|  254   MacIfAddrsConverter() : ip_attribute_getter_(new IPv6AttributesGetter()) {} |  | 
|  255   ~MacIfAddrsConverter() override {} |  | 
|  256  |  | 
|  257   bool ConvertNativeAttributesToIPAttributes(const struct ifaddrs* interface, |  | 
|  258                                              int* ip_attributes) override { |  | 
|  259     int native_attributes; |  | 
|  260     if (!ip_attribute_getter_->GetIPAttributes( |  | 
|  261             interface->ifa_name, interface->ifa_addr, &native_attributes)) { |  | 
|  262       return false; |  | 
|  263     } |  | 
|  264  |  | 
|  265     if (!ConvertNativeToIPAttributes(native_attributes, ip_attributes)) { |  | 
|  266       return false; |  | 
|  267     } |  | 
|  268  |  | 
|  269     return true; |  | 
|  270   } |  | 
|  271  |  | 
|  272  private: |  | 
|  273   std::unique_ptr<IPv6AttributesGetter> ip_attribute_getter_; |  | 
|  274 }; |  | 
|  275  |  | 
|  276 }  // namespace |  | 
|  277  |  | 
|  278 IfAddrsConverter* CreateIfAddrsConverter() { |  | 
|  279   return new MacIfAddrsConverter(); |  | 
|  280 } |  | 
|  281  |  | 
|  282 }  // namespace rtc |  | 
| OLD | NEW |