Commit 3646ba98 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Merge remote-tracking branch 'remotes/theo/tobast/v6tethered-reimplem' into v4viav6

parents f82a10e9 a4aebc71
...@@ -22,6 +22,7 @@ This file lists people who have contributed to babeld (in alphabetical order): ...@@ -22,6 +22,7 @@ This file lists people who have contributed to babeld (in alphabetical order):
Matthieu Boutier <boutier at irif dot fr> Matthieu Boutier <boutier at irif dot fr>
Sawssen Hadded <saw dot hadded at gmail dot com> Sawssen Hadded <saw dot hadded at gmail dot com>
Stephane Glondu <steph at glondu dot net> Stephane Glondu <steph at glondu dot net>
Théophile Bastian <theophile dot bastian at ens dot fr>
Thomas Petazzoni <thomas dot petazzoni at free-electrons dot com> Thomas Petazzoni <thomas dot petazzoni at free-electrons dot com>
Toke Høiland-Jørgensen <toke at toke dot dk> Toke Høiland-Jørgensen <toke at toke dot dk>
Vincent Gross <dermiste at screwball-coders dot net> Vincent Gross <dermiste at screwball-coders dot net>
......
...@@ -63,6 +63,7 @@ int debug = 0; ...@@ -63,6 +63,7 @@ int debug = 0;
int link_detect = 0; int link_detect = 0;
int all_wireless = 0; int all_wireless = 0;
int has_ipv6_subtrees = 0; int has_ipv6_subtrees = 0;
int has_v4ov6 = 0;
int default_wireless_hello_interval = -1; int default_wireless_hello_interval = -1;
int default_wired_hello_interval = -1; int default_wired_hello_interval = -1;
int resend_delay = -1; int resend_delay = -1;
...@@ -151,6 +152,7 @@ main(int argc, char **argv) ...@@ -151,6 +152,7 @@ main(int argc, char **argv)
protocol_port = 6696; protocol_port = 6696;
change_smoothing_half_life(4); change_smoothing_half_life(4);
has_ipv6_subtrees = kernel_has_ipv6_subtrees(); has_ipv6_subtrees = kernel_has_ipv6_subtrees();
has_v4ov6 = kernel_has_v4ov6();
while(1) { while(1) {
opt = getopt(argc, argv, opt = getopt(argc, argv,
......
...@@ -92,6 +92,7 @@ extern const char *logfile, *pidfile, *state_file; ...@@ -92,6 +92,7 @@ extern const char *logfile, *pidfile, *state_file;
extern int link_detect; extern int link_detect;
extern int all_wireless; extern int all_wireless;
extern int has_ipv6_subtrees; extern int has_ipv6_subtrees;
extern int has_v4ov6;
extern unsigned char myid[8]; extern unsigned char myid[8];
extern int have_id; extern int have_id;
......
...@@ -200,6 +200,11 @@ This specifies whether to use native source-specific IPv6 forwarding ...@@ -200,6 +200,11 @@ This specifies whether to use native source-specific IPv6 forwarding
rather than multiple routing tables. The default is chosen automatically rather than multiple routing tables. The default is chosen automatically
depending on the kernel version. depending on the kernel version.
.TP .TP
.BR v4-over-v6 " {" true | false }
This specifies whether to use v4-over-v6 routes (IPv4 routes with an IPv6
next-hop). This should not be enabled unless your kernel supports it. The
default is chosen automatically depending on the kernel version.
.TP
.BI debug " level" .BI debug " level"
This specifies the debugging level, and is equivalent to the command-line This specifies the debugging level, and is equivalent to the command-line
option option
......
...@@ -1029,6 +1029,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token) ...@@ -1029,6 +1029,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
strcmp(token, "daemonise") == 0 || strcmp(token, "daemonise") == 0 ||
strcmp(token, "skip-kernel-setup") == 0 || strcmp(token, "skip-kernel-setup") == 0 ||
strcmp(token, "ipv6-subtrees") == 0 || strcmp(token, "ipv6-subtrees") == 0 ||
strcmp(token, "v4-over-v6") == 0 ||
strcmp(token, "reflect-kernel-metric") == 0) { strcmp(token, "reflect-kernel-metric") == 0) {
int b; int b;
c = getbool(c, &b, gnc, closure); c = getbool(c, &b, gnc, closure);
...@@ -1045,6 +1046,8 @@ parse_option(int c, gnc_t gnc, void *closure, char *token) ...@@ -1045,6 +1046,8 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
skip_kernel_setup = b; skip_kernel_setup = b;
else if(strcmp(token, "ipv6-subtrees") == 0) else if(strcmp(token, "ipv6-subtrees") == 0)
has_ipv6_subtrees = b; has_ipv6_subtrees = b;
else if(strcmp(token, "v4-over-v6") == 0)
has_v4ov6 = b;
else if(strcmp(token, "reflect-kernel-metric") == 0) else if(strcmp(token, "reflect-kernel-metric") == 0)
reflect_kernel_metric = b; reflect_kernel_metric = b;
else else
......
...@@ -95,3 +95,10 @@ int gettime(struct timeval *tv); ...@@ -95,3 +95,10 @@ int gettime(struct timeval *tv);
int read_random_bytes(void *buf, int len); int read_random_bytes(void *buf, int len);
int kernel_older_than(const char *sysname, int version, int sub_version); int kernel_older_than(const char *sysname, int version, int sub_version);
int kernel_has_ipv6_subtrees(void); int kernel_has_ipv6_subtrees(void);
int kernel_has_v4ov6(void);
int add_rule(int prio, const unsigned char *src_prefix, int src_plen,
int table);
int flush_rule(int prio, int family);
int change_rule(int new_prio, int old_prio, const unsigned char *src, int plen,
int table);
...@@ -943,6 +943,14 @@ kernel_has_ipv6_subtrees(void) ...@@ -943,6 +943,14 @@ kernel_has_ipv6_subtrees(void)
return (kernel_older_than("Linux", 3, 11) == 0); return (kernel_older_than("Linux", 3, 11) == 0);
} }
int
kernel_has_v4ov6(void)
{
/* v4-over-v6 was introduced in Linux by commit
d15662682db232da77136cd348f4c9df312ca6f9 first released as 5.2 */
return (kernel_older_than("Linux", 5, 2) == 0);
}
int int
kernel_route(int operation, int table, kernel_route(int operation, int table,
const unsigned char *dest, unsigned short plen, const unsigned char *dest, unsigned short plen,
...@@ -956,7 +964,7 @@ kernel_route(int operation, int table, ...@@ -956,7 +964,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");
...@@ -978,8 +986,7 @@ kernel_route(int operation, int table, ...@@ -978,8 +986,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;
} }
...@@ -1018,7 +1025,8 @@ kernel_route(int operation, int table, ...@@ -1018,7 +1025,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); use_src = !is_default(src, src_plen);
if(use_src) { if(use_src) {
if(ipv4 || !has_ipv6_subtrees) { if(ipv4 || !has_ipv6_subtrees) {
...@@ -1094,23 +1102,32 @@ kernel_route(int operation, int table, ...@@ -1094,23 +1102,32 @@ kernel_route(int operation, int table,
rta->rta_type = RTA_OIF; rta->rta_type = RTA_OIF;
*(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)) { \
memcpy(RTA_DATA(rta), addr + 12, sizeof(struct in_addr)); \ rta->rta_len = RTA_LENGTH(sizeof(struct in_addr)); \
} else { \ memcpy(RTA_DATA(rta), addr + 12, sizeof(struct in_addr)); \
rta = RTA_NEXT(rta, len); \ } else { \
rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); \ if(type == RTA_VIA) { \
rta->rta_type = type; \ rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr) + 2); \
memcpy(RTA_DATA(rta), addr, sizeof(struct in6_addr)); \ *((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)); \
memcpy(RTA_DATA(rta), addr, sizeof(struct in6_addr)); \
} \
} \
} while (0) } while (0)
ADD_IPARG(RTA_GATEWAY, gate); if(is_v4_over_v6)
ADD_IPARG(RTA_VIA, gate);
else
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;
......
...@@ -395,6 +395,12 @@ kernel_has_ipv6_subtrees(void) ...@@ -395,6 +395,12 @@ kernel_has_ipv6_subtrees(void)
return 0; return 0;
} }
int
kernel_has_v4ov6(void)
{
return 0;
}
int int
kernel_route(int operation, int table, kernel_route(int operation, int table,
const unsigned char *dest, unsigned short plen, const unsigned char *dest, unsigned short plen,
......
...@@ -56,7 +56,7 @@ struct timeval seqno_time = {0, 0}; ...@@ -56,7 +56,7 @@ struct timeval seqno_time = {0, 0};
static int static int
known_ae(int ae) known_ae(int ae)
{ {
return ae <= 3; return ae <= AE_IPV6_LOCAL || ae == AE_V4OV6;
} }
/* Parse a network prefix, encoded in the somewhat baroque compressed /* Parse a network prefix, encoded in the somewhat baroque compressed
...@@ -83,10 +83,11 @@ network_prefix(int ae, int plen, unsigned int omitted, ...@@ -83,10 +83,11 @@ network_prefix(int ae, int plen, unsigned int omitted,
memset(prefix, 0, 16); memset(prefix, 0, 16);
switch(ae) { switch(ae) {
case 0: case AE_WILDCARD:
ret = 0; ret = 0;
break; break;
case 1: case AE_IPV4:
case AE_V4OV6:
if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted)) if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
return -1; return -1;
memcpy(prefix, v4prefix, 12); memcpy(prefix, v4prefix, 12);
...@@ -97,7 +98,7 @@ network_prefix(int ae, int plen, unsigned int omitted, ...@@ -97,7 +98,7 @@ network_prefix(int ae, int plen, unsigned int omitted,
if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted); if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted);
ret = pb - omitted; ret = pb - omitted;
break; break;
case 2: case AE_IPV6:
if(omitted > 16 || (pb > omitted && len < pb - omitted)) return -1; if(omitted > 16 || (pb > omitted && len < pb - omitted)) return -1;
if(omitted) { if(omitted) {
if(dp == NULL || v4mapped(dp)) return -1; if(dp == NULL || v4mapped(dp)) return -1;
...@@ -106,7 +107,7 @@ network_prefix(int ae, int plen, unsigned int omitted, ...@@ -106,7 +107,7 @@ network_prefix(int ae, int plen, unsigned int omitted,
if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted); if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted);
ret = pb - omitted; ret = pb - omitted;
break; break;
case 3: case AE_IPV6_LOCAL:
if(pb > 8 && len < pb - 8) return -1; if(pb > 8 && len < pb - 8) return -1;
prefix[0] = 0xfe; prefix[0] = 0xfe;
prefix[1] = 0x80; prefix[1] = 0x80;
...@@ -117,7 +118,8 @@ network_prefix(int ae, int plen, unsigned int omitted, ...@@ -117,7 +118,8 @@ network_prefix(int ae, int plen, unsigned int omitted,
return -1; return -1;
} }
normalize_prefix(p_r, prefix, plen < 0 ? 128 : ae == 1 ? plen + 96 : plen); normalize_prefix(p_r, prefix,
plen < 0 ? 128 : ae_is_v4(ae) ? plen + 96 : plen);
return ret; return ret;
} }
...@@ -175,7 +177,7 @@ parse_update_subtlv(struct interface *ifp, int metric, int ae, ...@@ -175,7 +177,7 @@ parse_update_subtlv(struct interface *ifp, int metric, int ae,
len - 1, src_prefix); len - 1, src_prefix);
if(rc < 0) if(rc < 0)
goto fail; goto fail;
if(ae == 1) if(ae_is_v4(ae))
*src_plen = a[i + 2] + 96; *src_plen = a[i + 2] + 96;
else else
*src_plen = a[i + 2]; *src_plen = a[i + 2];
...@@ -341,7 +343,7 @@ parse_request_subtlv(int ae, const unsigned char *a, int alen, ...@@ -341,7 +343,7 @@ parse_request_subtlv(int ae, const unsigned char *a, int alen,
len - 1, src_prefix); len - 1, src_prefix);
if(rc < 0) if(rc < 0)
goto fail; goto fail;
if(ae == 1) if(ae_is_v4(ae))
*src_plen = a[i + 2] + 96; *src_plen = a[i + 2] + 96;
else else
*src_plen = a[i + 2]; *src_plen = a[i + 2];
...@@ -392,7 +394,7 @@ parse_seqno_request_subtlv(int ae, const unsigned char *a, int alen, ...@@ -392,7 +394,7 @@ parse_seqno_request_subtlv(int ae, const unsigned char *a, int alen,
len - 1, src_prefix); len - 1, src_prefix);
if(rc < 0) if(rc < 0)
goto fail; goto fail;
if(ae == 1) if(ae_is_v4(ae))
(*src_plen) += 96; (*src_plen) += 96;
} else { } else {
debugf("Received unknown%s Route Request sub-TLV %d.\n", debugf("Received unknown%s Route Request sub-TLV %d.\n",
...@@ -591,9 +593,10 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -591,9 +593,10 @@ parse_packet(const unsigned char *from, struct interface *ifp,
int bodylen; int bodylen;
struct neighbour *neigh = NULL; struct neighbour *neigh = NULL;
int have_router_id = 0, have_v4_prefix = 0, have_v6_prefix = 0, int have_router_id = 0, have_v4_prefix = 0, have_v6_prefix = 0,
have_v4ov6_prefix = 0,
have_v4_nh = 0, have_v6_nh = 0; have_v4_nh = 0, have_v6_nh = 0;
unsigned char router_id[8], v4_prefix[16], v6_prefix[16], unsigned char router_id[8], v4_prefix[16], v6_prefix[16],
v4_nh[16], v6_nh[16]; v4ov6_prefix[16], v4_nh[16], v6_nh[16];
int have_hello_rtt = 0; int have_hello_rtt = 0;
/* Content of the RTT sub-TLV on IHU messages. */ /* Content of the RTT sub-TLV on IHU messages. */
unsigned int hello_send_us = 0, hello_rtt_receive_time = 0; unsigned int hello_send_us = 0, hello_rtt_receive_time = 0;
...@@ -745,7 +748,8 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -745,7 +748,8 @@ parse_packet(const unsigned char *from, struct interface *ifp,
txcost, interval, txcost, interval,
format_address(from), ifp->name, format_address(from), ifp->name,
format_address(address)); format_address(address));
if(message[2] == 0 || interface_ll_address(ifp, address)) { if(message[2] == AE_WILDCARD ||
interface_ll_address(ifp, address)) {
int changed; int changed;
rc = parse_ihu_subtlv(message + 8 + rc, len - 6 - rc, rc = parse_ihu_subtlv(message + 8 + rc, len - 6 - rc,
&hello_send_us, &hello_rtt_receive_time, &hello_send_us, &hello_rtt_receive_time,
...@@ -800,12 +804,21 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -800,12 +804,21 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf("Received nh %s (%d) from %s on %s.\n", debugf("Received nh %s (%d) from %s on %s.\n",
format_address(nh), message[2], format_address(nh), message[2],
format_address(from), ifp->name); format_address(from), ifp->name);
if(message[2] == 1) { switch(message[2]) {
case AE_IPV4:
memcpy(v4_nh, nh, 16); memcpy(v4_nh, nh, 16);
have_v4_nh = 1; have_v4_nh = 1;
} else { break;
case AE_IPV6:
case AE_IPV6_LOCAL:
memcpy(v6_nh, nh, 16); memcpy(v6_nh, nh, 16);
have_v6_nh = 1; have_v6_nh = 1;
break;
case AE_V4OV6:
goto done;
default:
/* We should have guards against this before this point. */
goto fail;
} }
rc = parse_other_subtlv(message + 4 + rc, len - 2 - rc); rc = parse_other_subtlv(message + 4 + rc, len - 2 - rc);
if(rc < 0) if(rc < 0)
...@@ -819,7 +832,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -819,7 +832,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
int rc, parsed_len, is_ss; int rc, parsed_len, is_ss;
if(len < 10) { if(len < 10) {
if(len < 2 || message[3] & 0x80) if(len < 2 || message[3] & 0x80)
have_v4_prefix = have_v6_prefix = 0; have_v4_prefix = have_v6_prefix = have_v4ov6_prefix = 0;
goto fail; goto fail;
} }
if(!known_ae(message[2])) { if(!known_ae(message[2])) {
...@@ -827,18 +840,31 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -827,18 +840,31 @@ parse_packet(const unsigned char *from, struct interface *ifp,
message[2]); message[2]);
goto done; goto done;
} }
if(message[2] == AE_V4OV6 && !has_v4ov6) {
/* We can safely ignore the prefix update that might come
alongside with this TLV, since we ignore every v4-over-v6
TLVs */
debugf("Ignoring v4-over-v6 route (unsupported).\n");
goto done;
}
DO_NTOHS(interval, message + 6); DO_NTOHS(interval, message + 6);
DO_NTOHS(seqno, message + 8); DO_NTOHS(seqno, message + 8);
DO_NTOHS(metric, message + 10); DO_NTOHS(metric, message + 10);
if(message[5] == 0 || if(message[5] == 0 ||
(message[2] == 1 ? have_v4_prefix : have_v6_prefix)) (message[2] == AE_IPV4 ? have_v4_prefix :
message[2] == AE_IPV6 ? have_v6_prefix :
message[2] == AE_V4OV6 ? have_v4ov6_prefix :
0))
rc = network_prefix(message[2], message[4], message[5], rc = network_prefix(message[2], message[4], message[5],
message + 12, message + 12,
message[2] == 1 ? v4_prefix : v6_prefix, (message[2] == AE_IPV4 ? v4_prefix :
message[2] == AE_IPV6 ? v6_prefix :
message[2] == AE_V4OV6 ? v4ov6_prefix :
NULL),
len - 10, prefix); len - 10, prefix);
else else
rc = -1; rc = -1;
if(message[2] == 1) { if(ae_is_v4(message[2])) {
v4tov6(src_prefix, zeroes); v4tov6(src_prefix, zeroes);
src_plen = 96; src_plen = 96;
} else { } else {
...@@ -847,24 +873,36 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -847,24 +873,36 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} }
if(rc < 0) { if(rc < 0) {
if(message[3] & 0x80) if(message[3] & 0x80)
have_v4_prefix = have_v6_prefix = 0; have_v4_prefix = have_v6_prefix = have_v4ov6_prefix = 0;
goto fail; goto fail;
} }
parsed_len = 10 + rc; parsed_len = 10 + rc;
plen = message[4] + (message[2] == 1 ? 96 : 0); plen = message[4] + (ae_is_v4(message[2]) ? 96 : 0);
if(message[3] & 0x80) { if(message[3] & 0x80) {
if(message[2] == 1) { switch(message[2]) {
case AE_IPV4:
memcpy(v4_prefix, prefix, 16); memcpy(v4_prefix, prefix, 16);
have_v4_prefix = 1; have_v4_prefix = 1;
} else { break;
case AE_IPV6:
memcpy(v6_prefix, prefix, 16); memcpy(v6_prefix, prefix, 16);
have_v6_prefix = 1; have_v6_prefix = 1;
break;
case AE_V4OV6:
memcpy(v4ov6_prefix, prefix, 16);
have_v4ov6_prefix = 1;
break;
default:
debugf("Received default prefix update with invalid "
"AE %d.\n",
message[2]);
break;
} }
} }
if(message[3] & 0x40) { if(message[3] & 0x40) {
if(message[2] == 1) { if(ae_is_v4(message[2])) {
memset(router_id, 0, 4); memset(router_id, 0, 4);
memcpy(router_id + 4, prefix + 12, 4); memcpy(router_id + 4, prefix + 12, 4);
} else { } else {
...@@ -872,7 +910,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -872,7 +910,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} }
have_router_id = 1; have_router_id = 1;
} }
if(metric < INFINITY && !have_router_id && message[2] != 0) { if(metric < INFINITY &&
!have_router_id &&
message[2] != AE_WILDCARD) {
fprintf(stderr, "Received prefix with no router id.\n"); fprintf(stderr, "Received prefix with no router id.\n");
goto fail; goto fail;
} }
...@@ -881,7 +921,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -881,7 +921,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
(message[3] & 0x40) ? "/id" : "", (message[3] & 0x40) ? "/id" : "",
format_prefix(prefix, plen), format_prefix(prefix, plen),
format_address(from), ifp->name); format_address(from), ifp->name);
if(message[2] == 1) { if(message[2] == AE_IPV4) {
if(have_v4_nh) { if(have_v4_nh) {
nh = v4_nh; nh = v4_nh;
} else { } else {
...@@ -902,7 +942,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -902,7 +942,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(rc < 0) if(rc < 0)
goto done; goto done;
if(message[2] == 0) { if(message[2] == AE_WILDCARD) {
if(metric < 0xFFFF) { if(metric < 0xFFFF) {
fprintf(stderr, fprintf(stderr,
"Received wildcard update with finite metric.\n"); "Received wildcard update with finite metric.\n");
...@@ -926,7 +966,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -926,7 +966,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
is_ss ? format_prefix(src_prefix, src_plen) : "", is_ss ? format_prefix(src_prefix, src_plen) : "",
format_address(from), ifp->name); format_address(from), ifp->name);
if(message[2] == 1) { if(message[2] == AE_IPV4) {
if(!ifp->ipv4) if(!ifp->ipv4)
goto done; goto done;
} }
...@@ -947,8 +987,8 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -947,8 +987,8 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(message[2], message[3], 0, rc = network_prefix(message[2], message[3], 0,
message + 4, NULL, len - 2, prefix); message + 4, NULL, len - 2, prefix);
if(rc < 0) goto fail; if(rc < 0) goto fail;
plen = message[3] + (message[2] == 1 ? 96 : 0); plen = message[3] + (ae_is_v4(message[2]) ? 96 : 0);
if(message[2] == 1) { if(ae_is_v4(message[2])) {
v4tov6(src_prefix, zeroes); v4tov6(src_prefix, zeroes);
src_plen = 96; src_plen = 96;
} else { } else {
...@@ -960,7 +1000,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -960,7 +1000,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(rc < 0) if(rc < 0)
goto done; goto done;
is_ss = !is_default(src_prefix, src_plen); is_ss = !is_default(src_prefix, src_plen);
if(message[2] == 0) { if(message[2] == AE_WILDCARD) {
if(is_ss) { if(is_ss) {
/* Wildcard requests don't carry a source prefix. */ /* Wildcard requests don't carry a source prefix. */
fprintf(stderr, fprintf(stderr,
...@@ -982,7 +1022,8 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -982,7 +1022,8 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} }
} else { } else {
debugf("Received request for dst %s%s%s from %s on %s.\n", debugf("Received request for dst %s%s%s from %s on %s.\n",
message[2] == 0 ? "" : format_prefix(prefix, plen), message[2] == AE_WILDCARD ?
"" : format_prefix(prefix, plen),
is_ss ? " src " : "", is_ss ? " src " : "",
is_ss ? format_prefix(src_prefix, src_plen) : "", is_ss ? format_prefix(src_prefix, src_plen) : "",
format_address(from), ifp->name); format_address(from), ifp->name);
...@@ -1002,7 +1043,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -1002,7 +1043,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(message[2], message[3], 0, rc = network_prefix(message[2], message[3], 0,
message + 16, NULL, len - 14, prefix); message + 16, NULL, len - 14, prefix);
if(rc < 0) goto fail; if(rc < 0) goto fail;
if(message[2] == 1) { if(ae_is_v4(message[2])) {
v4tov6(src_prefix, zeroes); v4tov6(src_prefix, zeroes);
src_plen = 96; src_plen = 96;
} else { } else {
...@@ -1015,7 +1056,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -1015,7 +1056,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(rc < 0) if(rc < 0)
goto done; goto done;
is_ss = !is_default(src_prefix, src_plen); is_ss = !is_default(src_prefix, src_plen);
plen = message[3] + (message[2] == 1 ? 96 : 0); plen = message[3] + (ae_is_v4(message[2]) ? 96 : 0);
debugf("Received request (%d) for dst %s%s%s from %s on " debugf("Received request (%d) for dst %s%s%s from %s on "
"%s (%s, %d).\n", "%s (%s, %d).\n",
message[6], message[6],
...@@ -1400,7 +1441,7 @@ really_buffer_update(struct buffered *buf, struct interface *ifp, ...@@ -1400,7 +1441,7 @@ really_buffer_update(struct buffered *buf, struct interface *ifp,
unsigned char *channels, int channels_len) unsigned char *channels, int channels_len)
{ {
int add_metric, v4, real_plen, real_src_plen; int add_metric, v4, real_plen, real_src_plen;
int omit, spb, channels_size, len; int ae, omit, spb, channels_size, len;
const unsigned char *real_prefix, *real_src_prefix; const unsigned char *real_prefix, *real_src_prefix;
unsigned short flags = 0; unsigned short flags = 0;
int is_ss = !is_default(src_prefix, src_plen); int is_ss = !is_default(src_prefix, src_plen);
...@@ -1424,24 +1465,28 @@ really_buffer_update(struct buffered *buf, struct interface *ifp, ...@@ -1424,24 +1465,28 @@ really_buffer_update(struct buffered *buf, struct interface *ifp,
v4 = plen >= 96 && v4mapped(prefix); v4 = plen >= 96 && v4mapped(prefix);
if(v4) { if(v4) {
if(!ifp->ipv4) if(!ifp->ipv4) {
return; ae = AE_V4OV6;
omit = 0; } else {
if(!buf->have_nh || ae = AE_IPV4;
memcmp(buf->nh, ifp->ipv4, 4) != 0) { if(!buf->have_nh ||
start_message(buf, ifp, MESSAGE_NH, 6); memcmp(buf->nh, ifp->ipv4, 4) != 0) {
accumulate_byte(buf, 1); start_message(buf, ifp, MESSAGE_NH, 6);
accumulate_byte(buf, 0); accumulate_byte(buf, AE_IPV4);
accumulate_bytes(buf, ifp->ipv4, 4); accumulate_byte(buf, 0);
end_message(buf, MESSAGE_NH, 6); accumulate_bytes(buf, ifp->ipv4, 4);
memcpy(&buf->nh, ifp->ipv4, 4); end_message(buf, MESSAGE_NH, 6);
buf->have_nh = 1; memcpy(&buf->nh, ifp->ipv4, 4);
buf->have_nh = 1;
}
} }
omit = 0;
real_prefix = prefix + 12; real_prefix = prefix + 12;
real_plen = plen - 96; real_plen = plen - 96;
real_src_prefix = src_prefix + 12; real_src_prefix = src_prefix + 12;
real_src_plen = src_plen - 96; real_src_plen = src_plen - 96;
} else { } else {
ae = AE_IPV6;
omit = 0; omit = 0;
if(buf->have_prefix) { if(buf->have_prefix) {
while(omit < plen / 8 && while(omit < plen / 8 &&
...@@ -1477,7 +1522,7 @@ really_buffer_update(struct buffered *buf, struct interface *ifp, ...@@ -1477,7 +1522,7 @@ really_buffer_update(struct buffered *buf, struct interface *ifp,
len += 3 + spb; len += 3 + spb;
start_message(buf, ifp, MESSAGE_UPDATE, len); start_message(buf, ifp, MESSAGE_UPDATE, len);
accumulate_byte(buf, v4 ? 1 : 2); accumulate_byte(buf, ae);
accumulate_byte(buf, flags); accumulate_byte(buf, flags);
accumulate_byte(buf, real_plen); accumulate_byte(buf, real_plen);
accumulate_byte(buf, omit); accumulate_byte(buf, omit);
...@@ -1856,7 +1901,7 @@ void ...@@ -1856,7 +1901,7 @@ void
buffer_wildcard_retraction(struct buffered *buf, struct interface *ifp) buffer_wildcard_retraction(struct buffered *buf, struct interface *ifp)
{ {
start_message(buf, ifp, MESSAGE_UPDATE, 10); start_message(buf, ifp, MESSAGE_UPDATE, 10);
accumulate_byte(buf, 0); accumulate_byte(buf, AE_WILDCARD);
accumulate_byte(buf, 0); accumulate_byte(buf, 0);
accumulate_byte(buf, 0); accumulate_byte(buf, 0);
accumulate_byte(buf, 0); accumulate_byte(buf, 0);
...@@ -1941,7 +1986,7 @@ buffer_ihu(struct buffered *buf, struct interface *ifp, unsigned short rxcost, ...@@ -1941,7 +1986,7 @@ buffer_ihu(struct buffered *buf, struct interface *ifp, unsigned short rxcost,
msglen = (ll ? 14 : 22) + (rtt_data ? 10 : 0); msglen = (ll ? 14 : 22) + (rtt_data ? 10 : 0);
start_message(buf, ifp, MESSAGE_IHU, msglen); start_message(buf, ifp, MESSAGE_IHU, msglen);
accumulate_byte(buf, ll ? 3 : 2); accumulate_byte(buf, ll ? AE_IPV6_LOCAL : AE_IPV6);
accumulate_byte(buf, 0); accumulate_byte(buf, 0);
accumulate_short(buf, rxcost); accumulate_short(buf, rxcost);
accumulate_short(buf, interval); accumulate_short(buf, interval);
...@@ -2061,7 +2106,7 @@ send_request(struct buffered *buf, struct interface *ifp, ...@@ -2061,7 +2106,7 @@ send_request(struct buffered *buf, struct interface *ifp,
assert(!src_prefix); assert(!src_prefix);
debugf("sending request for any.\n"); debugf("sending request for any.\n");
start_message(buf, ifp, MESSAGE_REQUEST, 2); start_message(buf, ifp, MESSAGE_REQUEST, 2);
accumulate_byte(buf, 0); accumulate_byte(buf, AE_WILDCARD);
accumulate_byte(buf, 0); accumulate_byte(buf, 0);
end_message(buf, MESSAGE_REQUEST, 2); end_message(buf, MESSAGE_REQUEST, 2);
return; return;
...@@ -2077,7 +2122,7 @@ send_request(struct buffered *buf, struct interface *ifp, ...@@ -2077,7 +2122,7 @@ send_request(struct buffered *buf, struct interface *ifp,
len = 2 + pb + (is_ss ? 3 + spb : 0); len = 2 + pb + (is_ss ? 3 + spb : 0);
start_message(buf, ifp, MESSAGE_REQUEST, len); start_message(buf, ifp, MESSAGE_REQUEST, len);
accumulate_byte(buf, v4 ? 1 : 2); accumulate_byte(buf, v4 ? AE_IPV4 : AE_IPV6);
accumulate_byte(buf, v4 ? plen - 96 : plen); accumulate_byte(buf, v4 ? plen - 96 : plen);
if(v4) if(v4)
accumulate_bytes(buf, prefix + 12, pb); accumulate_bytes(buf, prefix + 12, pb);
...@@ -2164,7 +2209,7 @@ send_multihop_request(struct buffered *buf, struct interface *ifp, ...@@ -2164,7 +2209,7 @@ send_multihop_request(struct buffered *buf, struct interface *ifp,
len = 6 + 8 + pb + (is_ss ? 3 + spb : 0); len = 6 + 8 + pb + (is_ss ? 3 + spb : 0);
start_message(buf, ifp, MESSAGE_MH_REQUEST, len); start_message(buf, ifp, MESSAGE_MH_REQUEST, len);
accumulate_byte(buf, v4 ? 1 : 2); accumulate_byte(buf, v4 ? AE_IPV4 : AE_IPV6);
accumulate_byte(buf, v4 ? plen - 96 : plen); accumulate_byte(buf, v4 ? plen - 96 : plen);
accumulate_short(buf, seqno); accumulate_short(buf, seqno);
accumulate_byte(buf, hop_count); accumulate_byte(buf, hop_count);
......
...@@ -47,6 +47,13 @@ THE SOFTWARE. ...@@ -47,6 +47,13 @@ THE SOFTWARE.
#define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */ #define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */
#define SUBTLV_SOURCE_PREFIX 128 /* Source-specific routing. */ #define SUBTLV_SOURCE_PREFIX 128 /* Source-specific routing. */
/* Address encodings */
#define AE_WILDCARD 0
#define AE_IPV4 1
#define AE_IPV6 2
#define AE_IPV6_LOCAL 3
#define AE_V4OV6 4
extern unsigned short myseqno; extern unsigned short myseqno;
extern struct timeval seqno_time; extern struct timeval seqno_time;
......
...@@ -502,6 +502,12 @@ v4tov6(unsigned char *dst, const unsigned char *src) ...@@ -502,6 +502,12 @@ v4tov6(unsigned char *dst, const unsigned char *src)
memcpy(dst + 12, src, 4); memcpy(dst + 12, src, 4);
} }
int
ae_is_v4(int ae)
{
return ae == 1 || ae == 4;
}
int int
daemonise() daemonise()
{ {
......
...@@ -100,6 +100,7 @@ int wait_for_fd(int direction, int fd, int msecs); ...@@ -100,6 +100,7 @@ int wait_for_fd(int direction, int fd, int msecs);
int martian_prefix(const unsigned char *prefix, int plen) ATTRIBUTE ((pure)); int martian_prefix(const unsigned char *prefix, int plen) ATTRIBUTE ((pure));
int linklocal(const unsigned char *address) ATTRIBUTE ((pure)); int linklocal(const unsigned char *address) ATTRIBUTE ((pure));
int v4mapped(const unsigned char *address) ATTRIBUTE ((pure)); int v4mapped(const unsigned char *address) ATTRIBUTE ((pure));
int ae_is_v4(int ae) ATTRIBUTE ((pure));
void v4tov6(unsigned char *dst, const unsigned char *src); void v4tov6(unsigned char *dst, const unsigned char *src);
int daemonise(void); int daemonise(void);
int set_src_prefix(unsigned char *src_addr, unsigned char *src_plen); int set_src_prefix(unsigned char *src_addr, unsigned char *src_plen);
......
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