[vtable] Unify routes table for OSX/Linux

This commit is contained in:
Teddy Reed 2014-10-03 18:00:15 -07:00
parent 1598892ab1
commit 3d7c8b5684
6 changed files with 73 additions and 23 deletions

View File

@ -12,6 +12,7 @@
#include <net/route.h> #include <net/route.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <glog/logging.h> #include <glog/logging.h>
@ -38,8 +39,7 @@ const std::vector<RouteType> kRouteTypes = {
std::make_pair(RTF_STATIC, "static"), std::make_pair(RTF_STATIC, "static"),
std::make_pair(RTF_BLACKHOLE, "blackhole"), std::make_pair(RTF_BLACKHOLE, "blackhole"),
std::make_pair(RTF_ROUTER, "router"), std::make_pair(RTF_ROUTER, "router"),
std::make_pair(RTF_PROXY, "proxy"), std::make_pair(RTF_PROXY, "proxy"), };
};
InterfaceMap genInterfaceMap() { InterfaceMap genInterfaceMap() {
InterfaceMap ifmap; InterfaceMap ifmap;
@ -55,9 +55,9 @@ InterfaceMap genInterfaceMap() {
InterfaceMap::iterator it = ifmap.begin(); InterfaceMap::iterator it = ifmap.begin();
for (if_addr = if_addrs; if_addr != NULL; if_addr = if_addr->ifa_next) { for (if_addr = if_addrs; if_addr != NULL; if_addr = if_addr->ifa_next) {
if (if_addr->ifa_addr != NULL && if_addr->ifa_addr->sa_family == AF_LINK) { if (if_addr->ifa_addr != NULL && if_addr->ifa_addr->sa_family == AF_LINK) {
std::string route_type = std::string(if_addr->ifa_name);
sdl = (struct sockaddr_dl *)if_addr->ifa_addr; sdl = (struct sockaddr_dl *)if_addr->ifa_addr;
ifmap.insert( ifmap.insert(it, std::make_pair(sdl->sdl_index, route_type));
it, std::make_pair(sdl->sdl_index, std::string(if_addr->ifa_name)));
} }
} }
@ -104,8 +104,8 @@ void genRouteTableType(RouteType type, InterfaceMap ifmap, QueryData &results) {
Row r; Row r;
r["type"] = type.second; r["type"] = type.second;
r["flags"] = boost::lexical_cast<std::string>(route->rtm_flags); r["flags"] = boost::lexical_cast<std::string>(route->rtm_flags);
r["use"] = boost::lexical_cast<std::string>(route->rtm_use);
r["mtu"] = boost::lexical_cast<std::string>(route->rtm_rmx.rmx_mtu); r["mtu"] = boost::lexical_cast<std::string>(route->rtm_rmx.rmx_mtu);
if ((route->rtm_addrs & RTA_DST) == RTA_DST) { if ((route->rtm_addrs & RTA_DST) == RTA_DST) {
@ -119,12 +119,22 @@ void genRouteTableType(RouteType type, InterfaceMap ifmap, QueryData &results) {
} }
if (kDefaultRoute.compare(r["destination"]) == 0) { if (kDefaultRoute.compare(r["destination"]) == 0) {
r["netmask"] = kDefaultRoute; r["netmask"] = "0";
} else if ((route->rtm_addrs & RTA_NETMASK) == RTA_NETMASK) { } else if ((route->rtm_addrs & RTA_NETMASK) == RTA_NETMASK) {
sa_table[RTAX_NETMASK]->sa_family = sa_table[RTAX_DST]->sa_family; sa_table[RTAX_NETMASK]->sa_family = sa_table[RTAX_DST]->sa_family;
r["netmask"] = canonical_ip_address(sa_table[RTAX_NETMASK]); r["netmask"] = boost::lexical_cast<std::string>(
netmaskFromIP(sa_table[RTAX_NETMASK]));
} else {
if (sa_table[RTA_DST]->sa_family == AF_INET6) {
r["netmask"] = "128";
} else {
r["netmask"] = "32";
}
} }
// Fields not supported by OSX routes:
r["source"] = "";
r["metric"] = "0";
results.push_back(r); results.push_back(r);
} }

View File

@ -85,6 +85,7 @@ void genNetlinkRoutes(const struct nlmsghdr* netlink_msg, QueryData& results) {
// Iterate over each route in the netlink message // Iterate over each route in the netlink message
has_destination = false; has_destination = false;
r["metric"] = "0";
while (RTA_OK(attr, attr_size)) { while (RTA_OK(attr, attr_size)) {
switch (attr->rta_type) { switch (attr->rta_type) {
case RTA_OIF: case RTA_OIF:
@ -121,9 +122,26 @@ void genNetlinkRoutes(const struct nlmsghdr* netlink_msg, QueryData& results) {
} }
} }
// This is the cidr-formatted mask // Route type determination
r["genmask"] = boost::lexical_cast<std::string>(mask); if (message->rtm_type == RTN_UNICAST) {
r["type"] = "gateway";
} else if (message->rtm_type == RTN_LOCAL) {
r["type"] = "local";
} else if (message->rtm_type == RTN_BROADCAST) {
r["type"] = "broadcast";
} else if (message->rtm_type == RTN_ANYCAST) {
r["type"] = "anycast";
} else {
r["type"] = "other";
}
r["flags"] = boost::lexical_cast<std::string>(message->rtm_flags);
// This is the cidr-formatted mask
r["netmask"] = boost::lexical_cast<std::string>(mask);
// Fields not supported by Linux routes:
r["mtu"] = "0";
results.push_back(r); results.push_back(r);
} }

View File

@ -37,6 +37,36 @@ std::string canonical_ip_address(const struct sockaddr *in) {
return address; return address;
} }
inline short addBits(unsigned char byte) {
short bits = 0;
for (int i = 7; i >= 0; --i) {
if ((byte & (1 << i)) == 0) {
break;
}
bits++;
}
return bits;
}
int netmaskFromIP(const struct sockaddr *in) {
int mask = 0;
if (in->sa_family == AF_INET6) {
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)in;
for (size_t i = 0; i < 16; i++) {
mask += addBits(in6->sin6_addr.s6_addr[i]);
}
} else {
struct sockaddr_in *in4 = (struct sockaddr_in *)in;
char *address = reinterpret_cast<char *>(&in4->sin_addr.s_addr);
for (size_t i = 0; i < 4; i++) {
mask += addBits(address[i]);
}
}
return mask;
}
std::string canonical_mac_address(const struct ifaddrs *addr) { std::string canonical_mac_address(const struct ifaddrs *addr) {
std::stringstream mac; std::stringstream mac;

View File

@ -8,5 +8,6 @@
#include <arpa/inet.h> #include <arpa/inet.h>
// Return a string representation for an IPv4/IPv6 struct. // Return a string representation for an IPv4/IPv6 struct.
std::string canonical_ip_address(const struct sockaddr *); std::string canonical_ip_address(const struct sockaddr *in);
std::string canonical_mac_address(const struct ifaddrs *addr); std::string canonical_mac_address(const struct ifaddrs *addr);
int netmaskFromIP(const struct sockaddr *in);

View File

@ -1,10 +0,0 @@
table_name("routes")
schema([
Column(name="destination", type="std::string"),
Column(name="genmask", type="std::string"),
Column(name="gateway", type="std::string"),
Column(name="source", type="std::string"),
Column(name="interface", type="std::string"),
Column(name="metric", type="std::string"),
])
implementation("routes@genRoutes")

View File

@ -3,10 +3,11 @@ schema([
Column(name="destination", type="std::string"), Column(name="destination", type="std::string"),
Column(name="netmask", type="std::string"), Column(name="netmask", type="std::string"),
Column(name="gateway", type="std::string"), Column(name="gateway", type="std::string"),
Column(name="source", type="std::string"),
Column(name="flags", type="int"), Column(name="flags", type="int"),
Column(name="use", type="int"),
Column(name="interface", type="std::string"), Column(name="interface", type="std::string"),
Column(name="mtu", type="int"), Column(name="mtu", type="int"),
Column(name="metric", type="int"),
Column(name="type", type="std::string"), Column(name="type", type="std::string"),
]) ])
implementation("routes@genRoutes") implementation("networking/routes@genRoutes")