Bug 1408218: ignore EUI 64 and Teredo addresses if not needed. r?bwc draft
authorNils Ohlmeier [:drno] <drno@ohlmeier.org>
Fri, 13 Oct 2017 08:32:16 -0700
changeset 683956 317b6b5abb97b36a8b31705b4314815915b7a981
parent 681681 7b75416fb54c6733b7403e340457007658c42c14
child 736783 664d4e7ebff299fd3d8895cf1000cdfe01f3b04c
push id85523
push userdrno@ohlmeier.org
push dateFri, 20 Oct 2017 17:10:40 +0000
reviewersbwc
bugs1408218
milestone58.0a1
Bug 1408218: ignore EUI 64 and Teredo addresses if not needed. r?bwc MozReview-Commit-ID: 5QHi9iC2e7y
media/mtransport/nrinterfaceprioritizer.cpp
media/mtransport/third_party/nICEr/src/net/local_addr.h
media/mtransport/third_party/nICEr/src/net/transport_addr.c
media/mtransport/third_party/nICEr/src/net/transport_addr.h
media/mtransport/third_party/nICEr/src/stun/addrs.c
--- a/media/mtransport/nrinterfaceprioritizer.cpp
+++ b/media/mtransport/nrinterfaceprioritizer.cpp
@@ -106,16 +106,20 @@ private:
       return 1;
     }
     if (type & NR_INTERFACE_TYPE_WIFI) {
       return 2;
     }
     if (type & NR_INTERFACE_TYPE_MOBILE) {
       return 3;
     }
+    if (type & NR_INTERFACE_TYPE_TEREDO) {
+      // Teredo gets penalty because it's IP relayed
+      return 5;
+    }
     return 4;
   }
 
   // TODO(bug 895790): Once we can get useful interface properties on Darwin,
   // we should remove this stuff.
   static const std::vector<std::string>& interface_preference_list()
   {
     static std::vector<std::string> list(build_interface_preference_list());
--- a/media/mtransport/third_party/nICEr/src/net/local_addr.h
+++ b/media/mtransport/third_party/nICEr/src/net/local_addr.h
@@ -40,16 +40,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
 typedef struct nr_interface_ {
   int type;
 #define NR_INTERFACE_TYPE_UNKNOWN 0x0
 #define NR_INTERFACE_TYPE_WIRED   0x1
 #define NR_INTERFACE_TYPE_WIFI    0x2
 #define NR_INTERFACE_TYPE_MOBILE  0x4
 #define NR_INTERFACE_TYPE_VPN     0x8
+#define NR_INTERFACE_TYPE_TEREDO  0x16
   int estimated_speed; /* Speed in kbps */
 } nr_interface;
 
 typedef struct nr_local_addr_ {
   nr_transport_addr addr;
   nr_interface interface;
 } nr_local_addr;
 
--- a/media/mtransport/third_party/nICEr/src/net/transport_addr.c
+++ b/media/mtransport/third_party/nICEr/src/net/transport_addr.c
@@ -431,16 +431,59 @@ int nr_transport_addr_is_link_local(nr_t
         break;
       default:
         UNIMPLEMENTED;
     }
 
     return(0);
   }
 
+int nr_transport_addr_is_mac_based(nr_transport_addr *addr)
+  {
+    switch(addr->ip_version){
+      case NR_IPV4:
+        // IPv4 has no MAC based self assigned IP addresses
+        return(0);
+      case NR_IPV6:
+        {
+          // RFC 2373, Appendix A: lower 64bit 0x020000FFFE000000
+          // indicates a MAC based IPv6 address
+          UINT4* macCom = (UINT4*)(addr->u.addr6.sin6_addr.s6_addr + 8);
+          UINT4* macExt = (UINT4*)(addr->u.addr6.sin6_addr.s6_addr + 12);
+          if ((*macCom & htonl(0x020000FF)) == htonl(0x020000FF) &&
+              (*macExt & htonl(0xFF000000)) == htonl(0xFE000000)) {
+            return(1);
+          }
+        }
+        break;
+      default:
+        UNIMPLEMENTED;
+    }
+    return(0);
+  }
+
+int nr_transport_addr_is_teredo(nr_transport_addr *addr)
+  {
+    switch(addr->ip_version){
+      case NR_IPV4:
+        return(0);
+      case NR_IPV6:
+        {
+          UINT4* addrTop = (UINT4*)(addr->u.addr6.sin6_addr.s6_addr);
+          if ((*addrTop & htonl(0xFFFF0000)) == htonl(0x20010000))
+            return(1);
+        }
+        break;
+      default:
+        UNIMPLEMENTED;
+    }
+
+    return(0);
+  }
+
 int nr_transport_addr_check_compatibility(nr_transport_addr *addr1, nr_transport_addr *addr2)
   {
     // first make sure we're comparing the same ip versions and protocols
     if ((addr1->ip_version != addr2->ip_version) ||
         (addr1->protocol != addr2->protocol)) {
       return(1);
     }
     // now make sure the link local status matches
--- a/media/mtransport/third_party/nICEr/src/net/transport_addr.h
+++ b/media/mtransport/third_party/nICEr/src/net/transport_addr.h
@@ -88,16 +88,18 @@ int nr_transport_addr_cmp(nr_transport_a
 #define NR_TRANSPORT_ADDR_CMP_MODE_PROTOCOL  2
 #define NR_TRANSPORT_ADDR_CMP_MODE_ADDR      3
 #define NR_TRANSPORT_ADDR_CMP_MODE_ALL       4
 
 int nr_transport_addr_is_wildcard(nr_transport_addr *addr);
 int nr_transport_addr_is_loopback(nr_transport_addr *addr);
 int nr_transport_addr_get_private_addr_range(nr_transport_addr *addr);
 int nr_transport_addr_is_link_local(nr_transport_addr *addr);
+int nr_transport_addr_is_mac_based(nr_transport_addr *addr);
+int nr_transport_addr_is_teredo(nr_transport_addr *addr);
 int nr_transport_addr_check_compatibility(nr_transport_addr *addr1, nr_transport_addr *addr2);
 int nr_transport_addr_copy(nr_transport_addr *to, nr_transport_addr *from);
 int nr_transport_addr_copy_keep_ifname(nr_transport_addr *to, nr_transport_addr *from);
 int nr_transport_addr_fmt_addr_string(nr_transport_addr *addr);
 int nr_transport_addr_fmt_ifname_addr_string(const nr_transport_addr *addr, char *buf, int len);
 int nr_transport_addr_set_port(nr_transport_addr *addr, int port);
 int nr_transport_addr_is_reliable_transport(nr_transport_addr *addr);
 
--- a/media/mtransport/third_party/nICEr/src/stun/addrs.c
+++ b/media/mtransport/third_party/nICEr/src/stun/addrs.c
@@ -367,34 +367,57 @@ nr_stun_is_duplicate_addr(nr_local_addr 
 
 int
 nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int remove_link_local, int *count)
 {
     int r, _status;
     nr_local_addr *tmp = 0;
     int i;
     int n;
+    int contains_mac_based_ipv6 = 0;
+    int contains_teredo_ipv6 = 0;
+    int contains_regular_ipv6 = 0;
 
     tmp = RMALLOC(*count * sizeof(*tmp));
     if (!tmp)
         ABORT(R_NO_MEMORY);
 
+    for (i = 0; i < *count; ++i) {
+        if (nr_transport_addr_is_mac_based(&addrs[i].addr)) {
+            contains_mac_based_ipv6 = 1;
+        }
+        else if (nr_transport_addr_is_teredo(&addrs[i].addr)) {
+            addrs[i].interface.type |= NR_INTERFACE_TYPE_TEREDO;
+            contains_teredo_ipv6 = 1;
+        }
+        else if (addrs[i].addr.ip_version == NR_IPV6) {
+            contains_regular_ipv6 = 1;
+        }
+    }
+
     n = 0;
     for (i = 0; i < *count; ++i) {
         if (nr_stun_is_duplicate_addr(tmp, n, &addrs[i])) {
             /* skip addrs[i], it's a duplicate */
         }
         else if (remove_loopback && nr_transport_addr_is_loopback(&addrs[i].addr)) {
             /* skip addrs[i], it's a loopback */
         }
         else if (remove_link_local &&
-                 addrs[i].addr.ip_version == NR_IPV6 &&
                  nr_transport_addr_is_link_local(&addrs[i].addr)) {
             /* skip addrs[i], it's a link-local address */
         }
+        else if (contains_regular_ipv6 &&
+                 nr_transport_addr_is_mac_based(&addrs[i].addr)) {
+            /* skip addrs[i], it's MAC based */
+        }
+        else if (contains_regular_ipv6 &&
+                 nr_transport_addr_is_teredo(&addrs[i].addr)) {
+            /* skip addrs[i], it's a Teredo address */
+        }
         else {
             /* otherwise, copy it to the temporary array */
             if ((r=nr_local_addr_copy(&tmp[n], &addrs[i])))
                 ABORT(r);
             ++n;
         }
     }