Commit 83476045 authored by Théophile Bastian's avatar Théophile Bastian

Handle v4-over-v6 routes in Netlink backend.

parent 6f4a505a
...@@ -953,7 +953,7 @@ kernel_route(int operation, int table, ...@@ -953,7 +953,7 @@ kernel_route(int operation, int table,
struct rtmsg *rtm; struct rtmsg *rtm;
struct rtattr *rta; struct rtattr *rta;
int len = sizeof(buf.raw); int len = sizeof(buf.raw);
int rc, ipv4, use_src = 0; int rc, ipv4, is_v4_over_v6, use_src = 0;
if(!nl_setup) { if(!nl_setup) {
fprintf(stderr,"kernel_route: netlink not initialized.\n"); fprintf(stderr,"kernel_route: netlink not initialized.\n");
...@@ -975,8 +975,7 @@ kernel_route(int operation, int table, ...@@ -975,8 +975,7 @@ kernel_route(int operation, int table,
/* Check that the protocol family is consistent. */ /* Check that the protocol family is consistent. */
if(plen >= 96 && v4mapped(dest)) { if(plen >= 96 && v4mapped(dest)) {
if(!v4mapped(gate) || if(!v4mapped(src)) {
!v4mapped(src)) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
...@@ -1015,7 +1014,8 @@ kernel_route(int operation, int table, ...@@ -1015,7 +1014,8 @@ kernel_route(int operation, int table,
} }
ipv4 = v4mapped(gate); ipv4 = v4mapped(dest);
is_v4_over_v6 = ipv4 && !v4mapped(gate);
use_src = (!is_default(src, src_plen) && kernel_disambiguate(ipv4)); use_src = (!is_default(src, src_plen) && kernel_disambiguate(ipv4));
kdebugf("kernel_route: %s %s from %s " kdebugf("kernel_route: %s %s from %s "
...@@ -1086,22 +1086,31 @@ kernel_route(int operation, int table, ...@@ -1086,22 +1086,31 @@ kernel_route(int operation, int table,
*(int*)RTA_DATA(rta) = ifindex; *(int*)RTA_DATA(rta) = ifindex;
#define ADD_IPARG(type, addr) \ #define ADD_IPARG(type, addr) \
do if(ipv4) { \ do { \
rta = RTA_NEXT(rta, len); \ rta = RTA_NEXT(rta, len); \
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr)); \
rta->rta_type = type; \ rta->rta_type = type; \
if(v4mapped(addr)) { \
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr)); \
memcpy(RTA_DATA(rta), addr + 12, sizeof(struct in_addr)); \ memcpy(RTA_DATA(rta), addr + 12, sizeof(struct in_addr)); \
} else { \ } else { \
rta = RTA_NEXT(rta, len); \ if(type == RTA_VIA) { \
rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr) + 2); \
*((sa_family_t*) RTA_DATA(rta)) = AF_INET6; \
memcpy(RTA_DATA(rta) + 2, addr, sizeof(struct in6_addr)); \
} else { \
rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); \ rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); \
rta->rta_type = type; \
memcpy(RTA_DATA(rta), addr, sizeof(struct in6_addr)); \ memcpy(RTA_DATA(rta), addr, sizeof(struct in6_addr)); \
} \
} \
} while (0) } while (0)
if(is_v4_over_v6)
ADD_IPARG(RTA_VIA, gate);
else
ADD_IPARG(RTA_GATEWAY, gate); ADD_IPARG(RTA_GATEWAY, gate);
if(pref_src) if(pref_src)
ADD_IPARG(RTA_PREFSRC, pref_src); ADD_IPARG(RTA_PREFSRC, pref_src);
#undef ADD_IPARG #undef ADD_IPARG
} else { } else {
*(int*)RTA_DATA(rta) = -1; *(int*)RTA_DATA(rta) = -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