Example #1
0
std::string macAsString(const struct ifaddrs *addr) {
  static std::string blank_mac = "00:00:00:00:00:00";
  if (addr->ifa_addr == nullptr) {
    // No link or MAC exists.
    return blank_mac;
  }

#if defined(__linux__)
  struct ifreq ifr;
  ifr.ifr_addr.sa_family = AF_INET;
  memcpy(ifr.ifr_name, addr->ifa_name, IFNAMSIZ);

  int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (socket_fd < 0) {
    return blank_mac;
  }
  ioctl(socket_fd, SIOCGIFHWADDR, &ifr);
  close(socket_fd);

  return macAsString(ifr.ifr_hwaddr.sa_data);
#else
  auto sdl = (struct sockaddr_dl *)addr->ifa_addr;
  if (sdl->sdl_alen != 6) {
    // Do not support MAC address that are not 6 bytes...
    return blank_mac;
  }

  return macAsString(&sdl->sdl_data[sdl->sdl_nlen]);
#endif
}
Example #2
0
Status genArp(const struct rt_msghdr *route,
              const AddressMap &addr_map,
              Row &r) {
  if (addr_map[RTAX_DST]->sa_family != AF_INET) {
    return Status(1, "Not in ARP cache");
  }

  // The cache will always know the address.
  r["address"] = ipAsString(addr_map[RTAX_DST]);

  auto sdl = (struct sockaddr_dl *)addr_map[RTA_DST];
  if (sdl->sdl_alen > 0) {
    r["mac"] = macAsString(LLADDR(sdl));
  } else {
    r["mac"] = "incomplete";
  }

  // Note: also possible to detect published.
  if (route->rtm_rmx.rmx_expire == 0) {
    r["permanent"] = "1";
  } else {
    r["permanent"] = "0";
  }

  return Status(0, "OK");
}
void genDetailsFromAddr(const struct ifaddrs *addr, QueryData &results) {
  Row r;
  r["interface"] = std::string(addr->ifa_name);
  r["mac"] = macAsString(addr);

  if (addr->ifa_data != nullptr) {
#ifdef __linux__
    // Linux/Netlink interface details parsing.
    auto ifd = (struct rtnl_link_stats *)addr->ifa_data;
    r["ipackets"] = BIGINT_FROM_UINT32(ifd->rx_packets);
    r["opackets"] = BIGINT_FROM_UINT32(ifd->tx_packets);
    r["ibytes"] = BIGINT_FROM_UINT32(ifd->rx_bytes);
    r["obytes"] = BIGINT_FROM_UINT32(ifd->tx_bytes);
    r["ierrors"] = BIGINT_FROM_UINT32(ifd->rx_errors);
    r["oerrors"] = BIGINT_FROM_UINT32(ifd->tx_errors);

    // Get Linux physical properties for the AF_PACKET entry.
    int fd = socket(AF_INET, SOCK_DGRAM, 0); 
    if (fd >= 0) {
      struct ifreq ifr;
      memcpy(ifr.ifr_name, addr->ifa_name, IFNAMSIZ);
      if (ioctl(fd, SIOCGIFMTU, &ifr) >= 0) {
        r["mtu"] = BIGINT_FROM_UINT32(ifr.ifr_mtu);
      }

      if (ioctl(fd, SIOCGIFMETRIC, &ifr) >= 0) {
       r["metric"] = BIGINT_FROM_UINT32(ifr.ifr_metric);
      }

      if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0) {
        r["type"] = INTEGER_FROM_UCHAR(ifr.ifr_hwaddr.sa_family); 
      }
    }

    r["last_change"] = "-1";
#else
    // Apple and FreeBSD interface details parsing.
    auto ifd = (struct if_data *)addr->ifa_data;
    r["type"] = INTEGER_FROM_UCHAR(ifd->ifi_type);
    r["mtu"] = BIGINT_FROM_UINT32(ifd->ifi_mtu);
    r["metric"] = BIGINT_FROM_UINT32(ifd->ifi_metric);
    r["ipackets"] = BIGINT_FROM_UINT32(ifd->ifi_ipackets);
    r["opackets"] = BIGINT_FROM_UINT32(ifd->ifi_opackets);
    r["ibytes"] = BIGINT_FROM_UINT32(ifd->ifi_ibytes);
    r["obytes"] = BIGINT_FROM_UINT32(ifd->ifi_obytes);
    r["ierrors"] = BIGINT_FROM_UINT32(ifd->ifi_ierrors);
    r["oerrors"] = BIGINT_FROM_UINT32(ifd->ifi_oerrors);
    r["last_change"] = BIGINT_FROM_UINT32(ifd->ifi_lastchange.tv_sec);
#endif
  }

  results.push_back(r);
}