Commit d2838459 authored by Matthieu Boutier's avatar Matthieu Boutier Committed by Juliusz Chroboczek

Kernel-side implementation of source-sensitive routing.

parent b221c564
......@@ -28,6 +28,8 @@ THE SOFTWARE.
struct kernel_route {
unsigned char prefix[16];
int plen;
unsigned char src_prefix[16];
int src_plen; /* no source prefix <=> src_plen == 0 */
int metric;
unsigned int ifindex;
int proto;
......@@ -60,6 +62,7 @@ int kernel_interface_mtu(const char *ifname, int ifindex);
int kernel_interface_wireless(const char *ifname, int ifindex);
int kernel_interface_channel(const char *ifname, int ifindex);
int kernel_route(int operation, const unsigned char *dest, unsigned short plen,
const unsigned char *src, unsigned short src_plen,
const unsigned char *gate, int ifindex, unsigned int metric,
const unsigned char *newgate, int newifindex,
unsigned int newmetric);
......
......@@ -554,6 +554,7 @@ kernel_setup(int setup)
return 1;
} else {
release_tables();
close(dgram_socket);
dgram_socket = -1;
......@@ -912,16 +913,16 @@ kernel_interface_channel(const char *ifname, int ifindex)
int
kernel_route(int operation, const unsigned char *dest, unsigned short plen,
const unsigned char *src, unsigned short src_plen,
const unsigned char *gate, int ifindex, unsigned int metric,
const unsigned char *newgate, int newifindex,
unsigned int newmetric)
{
union { char raw[1024]; struct nlmsghdr nh; } buf;
struct rtmsg *rtm;
struct rtattr *rta;
int len = sizeof(buf.raw);
int rc, ipv4;
int rc, ipv4, table;
if(!nl_setup) {
fprintf(stderr,"kernel_route: netlink not initialized.\n");
......@@ -941,14 +942,19 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
}
}
table = find_table(src, src_plen);
if(table < 0)
return -1;
/* Check that the protocol family is consistent. */
if(plen >= 96 && v4mapped(dest)) {
if(!v4mapped(gate)) {
if(!v4mapped(gate) ||
(src_plen > 0 && (!v4mapped(src) || src_plen < 96))) {
errno = EINVAL;
return -1;
}
} else {
if(v4mapped(gate)) {
if(v4mapped(gate)|| (src_plen > 0 && v4mapped(src))) {
errno = EINVAL;
return -1;
}
......@@ -967,9 +973,11 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
stick with the naive approach, and hope that the window is
small enough to be negligible. */
kernel_route(ROUTE_FLUSH, dest, plen,
src, src_plen,
gate, ifindex, metric,
NULL, 0, 0);
rc = kernel_route(ROUTE_ADD, dest, plen,
src, src_plen,
newgate, newifindex, newmetric,
NULL, 0, 0);
if(rc < 0) {
......@@ -981,11 +989,12 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
return rc;
}
kdebugf("kernel_route: %s %s/%d metric %d dev %d nexthop %s\n",
operation == ROUTE_ADD ? "add" :
operation == ROUTE_FLUSH ? "flush" : "???",
format_address(dest), plen, metric, ifindex,
format_address(gate));
kdebugf("kernel_route: %s %s from %s "
"table %d metric %d dev %d nexthop %s\n",
operation == ROUTE_ADD ? "add" :
operation == ROUTE_FLUSH ? "flush" : "???",
format_prefix(dest, plen), format_prefix(src, src_plen),
table, metric, ifindex, format_address(gate));
/* Unreachable default routes cause all sort of weird interactions;
ignore them. */
......@@ -1004,7 +1013,7 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
rtm = NLMSG_DATA(&buf.nh);
rtm->rtm_family = ipv4 ? AF_INET : AF_INET6;
rtm->rtm_dst_len = ipv4 ? plen - 96 : plen;
rtm->rtm_table = export_table;
rtm->rtm_table = table;
rtm->rtm_scope = RT_SCOPE_UNIVERSE;
if(metric < KERNEL_INFINITY)
rtm->rtm_type = RTN_UNICAST;
......
......@@ -29,8 +29,6 @@ THE SOFTWARE.
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <strings.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
......@@ -53,7 +51,6 @@ THE SOFTWARE.
static int get_sdl(struct sockaddr_dl *sdl, char *ifname);
static const unsigned char v4prefix[16] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
......@@ -387,6 +384,7 @@ kernel_interface_channel(const char *ifname, int ifindex)
int
kernel_route(int operation, const unsigned char *dest, unsigned short plen,
const unsigned char *src, unsigned short src_plen,
const unsigned char *gate, int ifindex, unsigned int metric,
const unsigned char *newgate, int newifindex,
unsigned int newmetric)
......@@ -427,9 +425,11 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
/* Avoid atomic route changes that is buggy on OS X. */
kernel_route(ROUTE_FLUSH, dest, plen,
src, src_plen,
gate, ifindex, metric,
NULL, 0, 0);
return kernel_route(ROUTE_ADD, dest, plen,
src, src_plen,
newgate, newifindex, newmetric,
NULL, 0, 0);
......@@ -668,7 +668,7 @@ kernel_routes(struct kernel_route *routes, int maxroutes)
size_t len;
struct rt_msghdr *rtm;
int rc, i;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
......
......@@ -416,6 +416,7 @@ install_route(struct babel_route *route)
}
rc = kernel_route(ROUTE_ADD, route->src->prefix, route->src->plen,
zeroes, 0,
route->nexthop,
route->neigh->ifp->ifindex,
metric_to_kernel(route_metric(route)), NULL, 0, 0);
......@@ -440,6 +441,7 @@ uninstall_route(struct babel_route *route)
return;
rc = kernel_route(ROUTE_FLUSH, route->src->prefix, route->src->plen,
zeroes, 0,
route->nexthop,
route->neigh->ifp->ifindex,
metric_to_kernel(route_metric(route)), NULL, 0, 0);
......@@ -472,6 +474,7 @@ switch_routes(struct babel_route *old, struct babel_route *new)
"(this shouldn't happen).");
rc = kernel_route(ROUTE_MODIFY, old->src->prefix, old->src->plen,
zeroes, 0,
old->nexthop, old->neigh->ifp->ifindex,
metric_to_kernel(route_metric(old)),
new->nexthop, new->neigh->ifp->ifindex,
......@@ -502,6 +505,7 @@ change_route_metric(struct babel_route *route,
if(route->installed && old != new) {
int rc;
rc = kernel_route(ROUTE_MODIFY, route->src->prefix, route->src->plen,
zeroes, 0,
route->nexthop, route->neigh->ifp->ifindex,
old,
route->nexthop, route->neigh->ifp->ifindex,
......
......@@ -170,7 +170,7 @@ check_xroutes(int send_updates)
debugf("\nChecking kernel routes.\n");
again:
routes = malloc(maxroutes * sizeof(struct kernel_route));
routes = calloc(maxroutes, sizeof(struct kernel_route));
if(routes == NULL)
return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment