Make routset()/route6set() use netlink.

Signed-off-by: Benjamin Cama <benoar@dolka.fr>
This commit is contained in:
Benjamin Cama 2011-08-17 02:23:13 +02:00
parent d02a243397
commit 1455a9c9bb

102
l2tpns.c
View file

@ -200,6 +200,8 @@ struct Tstats *_statistics = NULL;
struct Tringbuffer *ringbuffer = NULL; struct Tringbuffer *ringbuffer = NULL;
#endif #endif
static ssize_t netlink_send(struct nlmsghdr *nh);
static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
static void cache_ipmap(in_addr_t ip, sessionidt s); static void cache_ipmap(in_addr_t ip, sessionidt s);
static void uncache_ipmap(in_addr_t ip); static void uncache_ipmap(in_addr_t ip);
static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s); static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s);
@ -423,36 +425,51 @@ void random_data(uint8_t *buf, int len)
// //
static void routeset(sessionidt s, in_addr_t ip, int prefixlen, in_addr_t gw, int add) static void routeset(sessionidt s, in_addr_t ip, int prefixlen, in_addr_t gw, int add)
{ {
struct rtentry r; struct {
in_addr_t mask; struct nlmsghdr nh;
struct rtmsg rt;
char buf[32];
} req;
int i; int i;
in_addr_t n_ip;
if (!prefixlen) prefixlen = 32; if (!prefixlen) prefixlen = 32;
mask = 0xffffffff << (32 - prefixlen); ip &= 0xffffffff << (32 - prefixlen);; // Force the ip to be the first one in the route.
ip &= mask; // Force the ip to be the first one in the route. memset(&req, 0, sizeof(req));
memset(&r, 0, sizeof(r)); if (add)
r.rt_dev = config->tundevice; {
r.rt_dst.sa_family = AF_INET; req.nh.nlmsg_type = RTM_NEWROUTE;
*(uint32_t *) & (((struct sockaddr_in *) &r.rt_dst)->sin_addr.s_addr) = htonl(ip); req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
r.rt_gateway.sa_family = AF_INET; }
*(uint32_t *) & (((struct sockaddr_in *) &r.rt_gateway)->sin_addr.s_addr) = htonl(gw); else
r.rt_genmask.sa_family = AF_INET; req.nh.nlmsg_type = RTM_DELROUTE;
*(uint32_t *) & (((struct sockaddr_in *) &r.rt_genmask)->sin_addr.s_addr) = htonl(mask); req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.rt));
r.rt_flags = (RTF_UP | RTF_STATIC);
req.rt.rtm_family = AF_INET;
req.rt.rtm_dst_len = prefixlen;
req.rt.rtm_table = RT_TABLE_MAIN;
req.rt.rtm_protocol = RTPROT_BOOT; // XXX
req.rt.rtm_scope = RT_SCOPE_LINK;
req.rt.rtm_type = RTN_UNICAST;
netlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int));
n_ip = htonl(ip);
netlink_addattr(&req.nh, RTA_DST, &n_ip, sizeof(n_ip));
if (gw) if (gw)
r.rt_flags |= RTF_GATEWAY; {
else if (prefixlen == 32) n_ip = htonl(gw);
r.rt_flags |= RTF_HOST; netlink_addattr(&req.nh, RTA_GATEWAY, &n_ip, sizeof(n_ip));
}
LOG(1, s, 0, "Route %s %s/%d%s%s\n", add ? "add" : "del", LOG(1, s, 0, "Route %s %s/%d%s%s\n", add ? "add" : "del",
fmtaddr(htonl(ip), 0), prefixlen, fmtaddr(htonl(ip), 0), prefixlen,
gw ? " via" : "", gw ? fmtaddr(htonl(gw), 2) : ""); gw ? " via" : "", gw ? fmtaddr(htonl(gw), 2) : "");
if (ioctl(ifrfd, add ? SIOCADDRT : SIOCDELRT, (void *) &r) < 0) if (netlink_send(&req.nh) < 0)
LOG(0, 0, 0, "routeset() error in ioctl: %s\n", strerror(errno)); LOG(0, 0, 0, "routeset() error in sending netlink message: %s\n", strerror(errno));
#ifdef BGP #ifdef BGP
if (add) if (add)
@ -481,31 +498,50 @@ static void routeset(sessionidt s, in_addr_t ip, int prefixlen, in_addr_t gw, in
void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add) void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add)
{ {
struct in6_rtmsg rt; struct {
struct nlmsghdr nh;
struct rtmsg rt;
char buf[64];
} req;
int metric;
char ipv6addr[INET6_ADDRSTRLEN]; char ipv6addr[INET6_ADDRSTRLEN];
if (ifr6fd < 0) if (!config->ipv6_prefix.s6_addr[0])
{ {
LOG(0, 0, 0, "Asked to set IPv6 route, but IPv6 not setup.\n"); LOG(0, 0, 0, "Asked to set IPv6 route, but IPv6 not setup.\n");
return; return;
} }
memset(&rt, 0, sizeof(rt)); memset(&req, 0, sizeof(req));
memcpy(&rt.rtmsg_dst, &ip, sizeof(struct in6_addr)); if (add)
rt.rtmsg_dst_len = prefixlen; {
rt.rtmsg_metric = 1; req.nh.nlmsg_type = RTM_NEWROUTE;
rt.rtmsg_flags = RTF_UP; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
rt.rtmsg_ifindex = tunidx; }
else
req.nh.nlmsg_type = RTM_DELROUTE;
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.rt));
req.rt.rtm_family = AF_INET6;
req.rt.rtm_dst_len = prefixlen;
req.rt.rtm_table = RT_TABLE_MAIN;
req.rt.rtm_protocol = RTPROT_BOOT; // XXX
req.rt.rtm_scope = RT_SCOPE_LINK;
req.rt.rtm_type = RTN_UNICAST;
netlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int));
netlink_addattr(&req.nh, RTA_DST, &ip, sizeof(ip));
metric = 1;
netlink_addattr(&req.nh, RTA_METRICS, &metric, sizeof(metric));
LOG(1, 0, 0, "Route %s %s/%d\n", LOG(1, 0, 0, "Route %s %s/%d\n",
add ? "add" : "del", add ? "add" : "del",
inet_ntop(AF_INET6, &ip, ipv6addr, INET6_ADDRSTRLEN), inet_ntop(AF_INET6, &ip, ipv6addr, INET6_ADDRSTRLEN),
prefixlen); prefixlen);
if (ioctl(ifr6fd, add ? SIOCADDRT : SIOCDELRT, (void *) &rt) < 0) if (netlink_send(&req.nh) < 0)
LOG(0, 0, 0, "route6set() error in ioctl: %s\n", LOG(0, 0, 0, "route6set() error in sending netlink message: %s\n", strerror(errno));
strerror(errno));
// FIXME: need to add BGP routing (RFC2858) // FIXME: need to add BGP routing (RFC2858)
@ -580,7 +616,7 @@ static ssize_t netlink_recv(void *buf, ssize_t len)
} }
/* adapted from iproute2 */ /* adapted from iproute2 */
void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen)
{ {
int len = RTA_LENGTH(alen); int len = RTA_LENGTH(alen);
struct rtattr *rta; struct rtattr *rta;
@ -634,9 +670,7 @@ static void inittun(void)
// get the interface index // get the interface index
struct { struct {
struct nlmsghdr nh; struct nlmsghdr nh;
struct ifinfomsg ifinfo __attribute__ ((aligned(NLMSG_ALIGNTO))); struct ifinfomsg ifinfo;
struct rtattr ifname_rta __attribute__ ((aligned(RTA_ALIGNTO)));
char ifname[IFNAMSIZ];
} req; } req;
char buf[4096]; char buf[4096];
ssize_t len; ssize_t len;
@ -674,7 +708,7 @@ static void inittun(void)
union { union {
struct ifinfomsg ifinfo; struct ifinfomsg ifinfo;
struct ifaddrmsg ifaddr; struct ifaddrmsg ifaddr;
} ifmsg __attribute__ ((aligned(NLMSG_ALIGNTO))); } ifmsg;
char rtdata[32]; // 32 should be enough char rtdata[32]; // 32 should be enough
} req; } req;
uint32_t txqlen, mtu; uint32_t txqlen, mtu;