Bug 1579424 - P1 Traverse the whole routing table, r=michal
authorJunior Hsu <juhsu@mozilla.com>
Tue, 12 Nov 2019 16:04:09 +0000
changeset 502267 224557872391ae18c2885ca91e98f07e3bb48983
parent 502266 6b3e85d6a39fc22cfe75106920cd004d71c6b617
child 502268 500126439162e6a839f8c0bc0d8355ad0f5386e2
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmichal
bugs1579424
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1579424 - P1 Traverse the whole routing table, r=michal Differential Revision: https://phabricator.services.mozilla.com/D48803
netwerk/system/mac/nsNetworkLinkService.mm
--- a/netwerk/system/mac/nsNetworkLinkService.mm
+++ b/netwerk/system/mac/nsNetworkLinkService.mm
@@ -421,26 +421,87 @@ static int routingTable(char* gw, size_t
   struct sockaddr_in* sockin;
 
   mib[0] = CTL_NET;
   mib[1] = PF_ROUTE;
   mib[2] = 0;
   mib[3] = 0;
   mib[4] = NET_RT_DUMP;
   mib[5] = 0;
+
   if (sysctl(mib, 6, nullptr, &needed, nullptr, 0) < 0) {
     return 1;
   }
 
   UniquePtr<char[]> buf(new char[needed]);
 
   if (sysctl(mib, 6, &buf[0], &needed, nullptr, 0) < 0) {
     return 3;
   }
 
+  char ip[INET_ADDRSTRLEN];
+
+  char* lim = &buf[0] + needed;
+
+  // `next + 1 < lim` ensures we have valid `rtm->rtm_msglen` which is an
+  // unsigned short at the beginning of `rt_msghdr`.
+  for (char* next = &buf[0]; next + 1 < lim; next += rtm->rtm_msglen) {
+    rtm = reinterpret_cast<struct rt_msghdr*>(next);
+
+    if (next + rtm->rtm_msglen > lim) {
+      LOG(("Rt msg is truncated..."));
+      break;
+    }
+
+    // Ignore the routing table message without destination/gateway sockaddr.
+    // Destination address is needed to check if the gateway is default or
+    // overwritten by VPN. If yes, hash the mac address or IP/interface name.
+    if ((rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) != (RTA_DST | RTA_GATEWAY)) {
+      continue;
+    }
+
+    sa = reinterpret_cast<struct sockaddr*>(rtm + 1);
+
+    struct sockaddr* destination =
+        reinterpret_cast<struct sockaddr*>((char*)sa + RTAX_DST * SA_SIZE(sa));
+    if (!destination || destination->sa_family != AF_INET) {
+      continue;
+    }
+
+    sockin = reinterpret_cast<struct sockaddr_in*>(destination);
+    inet_ntop(AF_INET, &sockin->sin_addr.s_addr, ip, sizeof(ip) - 1);
+
+    // TODO: only filtered non-predefined destination
+    // Ignore if destination is non-predefined.
+    if (strcmp(ip, "0.0.0.0")) {
+      continue;
+    }
+
+    struct sockaddr* gateway =
+        reinterpret_cast<struct sockaddr*>((char*)sa + RTAX_GATEWAY * SA_SIZE(sa));
+
+    if (!gateway) {
+      continue;
+    }
+    if (gateway->sa_family == AF_INET) {
+      sockin = reinterpret_cast<struct sockaddr_in*>(gateway);
+      inet_ntop(AF_INET, &sockin->sin_addr.s_addr, ip, sizeof(ip) - 1);
+      char mac[18];
+      if (scanArp(ip, mac, sizeof(mac))) {
+        // TODO: use the mac to calculate network id
+      }
+    } else if (gateway->sa_family == AF_LINK) {
+      char buf[64];
+      struct sockaddr_dl* sockdl = reinterpret_cast<struct sockaddr_dl*>(gateway);
+      if (getMac(sockdl, buf, sizeof(buf))) {
+        // TODO: use the mac to calculate network id
+      }
+    }
+  }
+
   // There's no need to iterate over the routing table
   // We're only looking for the first (default) gateway
   rtm = reinterpret_cast<struct rt_msghdr*>(&buf[0]);
   sa = reinterpret_cast<struct sockaddr*>(rtm + 1);
   sa = reinterpret_cast<struct sockaddr*>(SA_SIZE(sa) + (char*)sa);
   sockin = reinterpret_cast<struct sockaddr_in*>(sa);
   inet_ntop(AF_INET, &sockin->sin_addr.s_addr, gw, aGwLen - 1);