do /1 route poker split on linux (#1480)

* do /1 route poker split on linux

i hate netlink so god damn much

* use an enum class for the gateway mode
pull/1482/head
Jeff 4 years ago committed by GitHub
parent dad66c50cb
commit db7abe8f09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -82,6 +82,14 @@ namespace llarp::net
#ifdef __linux__ #ifdef __linux__
#ifndef ANDROID #ifndef ANDROID
enum class GatewayMode
{
eFirstHop,
eLowerDefault,
eUpperDefault
};
struct NLSocket struct NLSocket
{ {
NLSocket() : fd(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) NLSocket() : fd(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
@ -139,7 +147,14 @@ namespace llarp::net
} }
int int
do_route(int sock, int cmd, int flags, _inet_addr* dst, _inet_addr* gw, int def_gw, int if_idx) do_route(
int sock,
int cmd,
int flags,
const _inet_addr* dst,
const _inet_addr* gw,
GatewayMode mode,
int if_idx)
{ {
struct struct
{ {
@ -187,27 +202,27 @@ namespace llarp::net
if (gw->bitlen != 0) if (gw->bitlen != 0)
{ {
rtattr_add(&nl_request.n, sizeof(nl_request), RTA_GATEWAY, &gw->data, gw->bitlen / 8); rtattr_add(&nl_request.n, sizeof(nl_request), RTA_GATEWAY, &gw->data, gw->bitlen / 8);
nl_request.r.rtm_scope = 0;
nl_request.r.rtm_family = gw->family;
} }
nl_request.r.rtm_scope = 0;
/* Don't set destination and interface in case of default gateways */ nl_request.r.rtm_family = gw->family;
if (!def_gw) if (mode == GatewayMode::eFirstHop)
{ {
/* Set destination network */
rtattr_add( rtattr_add(
&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &dst->data, dst->bitlen / 8); &nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &dst->data, dst->bitlen / 8);
/* Set interface */ /* Set interface */
rtattr_add(&nl_request.n, sizeof(nl_request), RTA_OIF, &if_idx, sizeof(int)); rtattr_add(&nl_request.n, sizeof(nl_request), RTA_OIF, &if_idx, sizeof(int));
} }
if (mode == GatewayMode::eUpperDefault)
{
rtattr_add(
&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &dst->data, sizeof(uint32_t));
}
/* Send message to the netlink */ /* Send message to the netlink */
return send(sock, &nl_request, sizeof(nl_request), 0); return send(sock, &nl_request, sizeof(nl_request), 0);
} }
int int
read_addr(const char* addr, _inet_addr* res) read_addr(const char* addr, _inet_addr* res, int bitlen = 32)
{ {
if (strchr(addr, ':')) if (strchr(addr, ':'))
{ {
@ -217,7 +232,7 @@ namespace llarp::net
else else
{ {
res->family = AF_INET; res->family = AF_INET;
res->bitlen = 32; res->bitlen = bitlen;
} }
return inet_pton(res->family, addr, res->data); return inet_pton(res->family, addr, res->data);
} }
@ -295,7 +310,6 @@ namespace llarp::net
#ifdef __linux__ #ifdef __linux__
#ifndef ANDROID #ifndef ANDROID
NLSocket sock; NLSocket sock;
int default_gw = 0;
int if_idx = 0; int if_idx = 0;
_inet_addr to_addr{}; _inet_addr to_addr{};
_inet_addr gw_addr{}; _inet_addr gw_addr{};
@ -303,7 +317,7 @@ namespace llarp::net
int nl_flags = NLM_F_CREATE | NLM_F_EXCL; int nl_flags = NLM_F_CREATE | NLM_F_EXCL;
read_addr(gateway.c_str(), &gw_addr); read_addr(gateway.c_str(), &gw_addr);
read_addr(ip.c_str(), &to_addr); read_addr(ip.c_str(), &to_addr);
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx); do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eFirstHop, if_idx);
#endif #endif
#else #else
std::stringstream ss; std::stringstream ss;
@ -325,7 +339,6 @@ namespace llarp::net
#ifdef __linux__ #ifdef __linux__
#ifndef ANDROID #ifndef ANDROID
NLSocket sock; NLSocket sock;
int default_gw = 0;
int if_idx = 0; int if_idx = 0;
_inet_addr to_addr{}; _inet_addr to_addr{};
_inet_addr gw_addr{}; _inet_addr gw_addr{};
@ -333,7 +346,7 @@ namespace llarp::net
int nl_flags = 0; int nl_flags = 0;
read_addr(gateway.c_str(), &gw_addr); read_addr(gateway.c_str(), &gw_addr);
read_addr(ip.c_str(), &to_addr); read_addr(ip.c_str(), &to_addr);
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx); do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eFirstHop, if_idx);
#endif #endif
#else #else
std::stringstream ss; std::stringstream ss;
@ -355,18 +368,19 @@ namespace llarp::net
#ifdef __linux__ #ifdef __linux__
#ifndef ANDROID #ifndef ANDROID
NLSocket sock; NLSocket sock;
int default_gw = 1;
int if_idx = if_nametoindex(ifname.c_str()); int if_idx = if_nametoindex(ifname.c_str());
_inet_addr to_addr{}; _inet_addr to_addr{};
_inet_addr gw_addr{}; _inet_addr gw_addr{};
const auto maybe = GetIFAddr(ifname); const auto maybe = GetIFAddr(ifname);
if (not maybe.has_value()) if (not maybe.has_value())
throw std::runtime_error("we dont have our own net interface?"); throw std::runtime_error("we dont have our own net interface?");
int nl_cmd = RTM_NEWROUTE; int nl_cmd = RTM_NEWROUTE;
int nl_flags = NLM_F_CREATE | NLM_F_EXCL; int nl_flags = NLM_F_CREATE | NLM_F_EXCL;
read_addr(maybe->toHost().c_str(), &gw_addr); read_addr(maybe->toHost().c_str(), &gw_addr);
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx); read_addr("0.0.0.0", &to_addr, 1);
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx);
read_addr("128.0.0.0", &to_addr, 1);
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
#endif #endif
#elif _WIN32 #elif _WIN32
// poke hole for loopback bacause god is dead on windows // poke hole for loopback bacause god is dead on windows
@ -389,7 +403,6 @@ namespace llarp::net
#ifdef __linux__ #ifdef __linux__
#ifndef ANDROID #ifndef ANDROID
NLSocket sock; NLSocket sock;
int default_gw = 1;
int if_idx = if_nametoindex(ifname.c_str()); int if_idx = if_nametoindex(ifname.c_str());
_inet_addr to_addr{}; _inet_addr to_addr{};
_inet_addr gw_addr{}; _inet_addr gw_addr{};
@ -400,7 +413,10 @@ namespace llarp::net
int nl_cmd = RTM_DELROUTE; int nl_cmd = RTM_DELROUTE;
int nl_flags = 0; int nl_flags = 0;
read_addr(maybe->toHost().c_str(), &gw_addr); read_addr(maybe->toHost().c_str(), &gw_addr);
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx); read_addr("0.0.0.0", &to_addr, 1);
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx);
read_addr("128.0.0.0", &to_addr, 1);
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
#endif #endif
#elif _WIN32 #elif _WIN32
ifname.back()++; ifname.back()++;

Loading…
Cancel
Save