mirror of https://github.com/oxen-io/lokinet
initial netlink jizz
This commit is contained in:
parent
b0bb0b7609
commit
8472aea93f
|
@ -1,5 +1,15 @@
|
|||
#include "route.hpp"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#endif
|
||||
|
||||
namespace llarp::net
|
||||
{
|
||||
#ifndef __linux__
|
||||
|
@ -51,10 +61,154 @@ namespace llarp::net
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
struct NLSocket
|
||||
{
|
||||
NLSocket() : fd(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
|
||||
{
|
||||
}
|
||||
|
||||
~NLSocket()
|
||||
{
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
const int fd;
|
||||
};
|
||||
|
||||
/* Helper structure for ip address data and attributes */
|
||||
typedef struct
|
||||
{
|
||||
char family;
|
||||
char bitlen;
|
||||
unsigned char data[sizeof(struct in6_addr)];
|
||||
} _inet_addr;
|
||||
|
||||
/* */
|
||||
|
||||
#define NLMSG_TAIL(nmsg) ((struct rtattr*)(((void*)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||
|
||||
/* Add new data to rtattr */
|
||||
int
|
||||
rtattr_add(struct nlmsghdr* n, int maxlen, int type, const void* data, int alen)
|
||||
{
|
||||
int len = RTA_LENGTH(alen);
|
||||
struct rtattr* rta;
|
||||
|
||||
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen)
|
||||
{
|
||||
fprintf(stderr, "rtattr_add error: message exceeded bound of %d\n", maxlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rta = NLMSG_TAIL(n);
|
||||
rta->rta_type = type;
|
||||
rta->rta_len = len;
|
||||
|
||||
if (alen)
|
||||
{
|
||||
memcpy(RTA_DATA(rta), data, alen);
|
||||
}
|
||||
|
||||
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_route(int sock, int cmd, int flags, _inet_addr* dst, _inet_addr* gw, int def_gw, int if_idx)
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct nlmsghdr n;
|
||||
struct rtmsg r;
|
||||
char buf[4096];
|
||||
} nl_request;
|
||||
|
||||
/* Initialize request structure */
|
||||
nl_request.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||
nl_request.n.nlmsg_flags = NLM_F_REQUEST | flags;
|
||||
nl_request.n.nlmsg_type = cmd;
|
||||
nl_request.r.rtm_family = dst->family;
|
||||
nl_request.r.rtm_table = RT_TABLE_MAIN;
|
||||
nl_request.r.rtm_scope = RT_SCOPE_NOWHERE;
|
||||
|
||||
/* Set additional flags if NOT deleting route */
|
||||
if (cmd != RTM_DELROUTE)
|
||||
{
|
||||
nl_request.r.rtm_protocol = RTPROT_BOOT;
|
||||
nl_request.r.rtm_type = RTN_UNICAST;
|
||||
}
|
||||
|
||||
nl_request.r.rtm_family = dst->family;
|
||||
nl_request.r.rtm_dst_len = dst->bitlen;
|
||||
|
||||
/* Select scope, for simplicity we supports here only IPv6 and IPv4 */
|
||||
if (nl_request.r.rtm_family == AF_INET6)
|
||||
{
|
||||
nl_request.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nl_request.r.rtm_scope = RT_SCOPE_LINK;
|
||||
}
|
||||
|
||||
/* Set gateway */
|
||||
if (gw->bitlen != 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* Don't set destination and interface in case of default gateways */
|
||||
if (!def_gw)
|
||||
{
|
||||
/* Set destination network */
|
||||
rtattr_add(
|
||||
&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &dst->data, dst->bitlen / 8);
|
||||
|
||||
/* Set interface */
|
||||
rtattr_add(&nl_request.n, sizeof(nl_request), RTA_OIF, &if_idx, sizeof(int));
|
||||
}
|
||||
|
||||
/* Send message to the netlink */
|
||||
return send(sock, &nl_request, sizeof(nl_request), 0);
|
||||
}
|
||||
|
||||
int
|
||||
read_addr(char* addr, _inet_addr* res)
|
||||
{
|
||||
if (strchr(addr, ':'))
|
||||
{
|
||||
res->family = AF_INET6;
|
||||
res->bitlen = 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
res->family = AF_INET;
|
||||
res->bitlen = 32;
|
||||
}
|
||||
return inet_pton(res->family, addr, res->data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
AddRoute(std::string ip, std::string gateway)
|
||||
{
|
||||
#ifdef __linux__
|
||||
NLSocket sock;
|
||||
int default_gw = 0;
|
||||
int if_idx = 0;
|
||||
_inet_addr to_addr = {0};
|
||||
_inet_addr gw_addr = {0};
|
||||
int nl_cmd = RTM_NEWROUTE;
|
||||
int nl_flags = NLM_F_CREATE | NLM_F_EXCL;
|
||||
read_addr(gateway.c_str(), &gw_addr);
|
||||
read_addr(ip.c_str(), &to_addr);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx);
|
||||
#else
|
||||
std::stringstream ss;
|
||||
#if _WIN32
|
||||
|
@ -72,9 +226,18 @@ namespace llarp::net
|
|||
DelRoute(std::string ip, std::string gateway)
|
||||
{
|
||||
#ifdef __linux__
|
||||
NLSocket sock;
|
||||
int default_gw = 0;
|
||||
int if_idx = 0;
|
||||
_inet_addr to_addr = {0};
|
||||
_inet_addr gw_addr = {0};
|
||||
int nl_cmd = RTM_DELROUTE;
|
||||
int nl_flags = 0;
|
||||
read_addr(gateway.c_str(), &gw_addr);
|
||||
read_addr(ip.c_str(), &to_addr);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx);
|
||||
#else
|
||||
std::stringstream ss;
|
||||
|
||||
#if _WIN32
|
||||
ss << "route DELETE " << ip << " MASK 255.255.255.255 " << gateway << " METRIC 2";
|
||||
#elif __APPLE__
|
||||
|
@ -90,7 +253,14 @@ namespace llarp::net
|
|||
AddDefaultRouteViaInterface(std::string ifname)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// Execute("/sbin/ip route add default dev " + ifname);
|
||||
NLSocket sock;
|
||||
int default_gw = 1;
|
||||
int if_idx = if_nametoindex(ifname.c_str());
|
||||
_inet_addr to_addr = {0};
|
||||
_inet_addr gw_addr = {0};
|
||||
int nl_cmd = RTM_NEWROUTE;
|
||||
int nl_flags = NLM_F_CREATE | NLM_F_EXCL;
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx);
|
||||
#elif _WIN32
|
||||
ifname.back()++;
|
||||
Execute("route ADD 0.0.0.0 MASK 128.0.0.0 " + ifname);
|
||||
|
@ -106,7 +276,15 @@ namespace llarp::net
|
|||
DelDefaultRouteViaInterface(std::string ifname)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// Execute("/sbin/ip route del default dev " + ifname);
|
||||
|
||||
NLSocket sock;
|
||||
int default_gw = 1;
|
||||
int if_idx = if_nametoindex(ifname.c_str());
|
||||
_inet_addr to_addr = {0};
|
||||
_inet_addr gw_addr = {0};
|
||||
int nl_cmd = RTM_DELROUTE;
|
||||
int nl_flags = 0;
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx);
|
||||
#elif _WIN32
|
||||
ifname.back()++;
|
||||
Execute("route DELETE 0.0.0.0 MASK 128.0.0.0 " + ifname);
|
||||
|
|
Loading…
Reference in New Issue