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

Use standard v4mapped encoding for source prefixes.

parent 221c60ce
...@@ -25,7 +25,7 @@ struct buffered_update { ...@@ -25,7 +25,7 @@ struct buffered_update {
unsigned char prefix[16]; unsigned char prefix[16];
unsigned char src_prefix[16]; unsigned char src_prefix[16];
unsigned char plen; unsigned char plen;
unsigned char src_plen; /* 0 <=> no src prefix */ unsigned char src_plen;
unsigned char pad[2]; unsigned char pad[2];
}; };
......
...@@ -29,7 +29,7 @@ struct kernel_route { ...@@ -29,7 +29,7 @@ struct kernel_route {
unsigned char prefix[16]; unsigned char prefix[16];
int plen; int plen;
unsigned char src_prefix[16]; unsigned char src_prefix[16];
int src_plen; /* no source prefix <=> src_plen == 0 */ int src_plen;
int metric; int metric;
unsigned int ifindex; unsigned int ifindex;
int proto; int proto;
......
...@@ -955,12 +955,12 @@ kernel_route(int operation, int table, ...@@ -955,12 +955,12 @@ 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(gate) ||
(src_plen > 0 && (!v4mapped(src) || src_plen < 96))) { !v4mapped(src)) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
} else { } else {
if(v4mapped(gate)|| (src_plen > 0 && v4mapped(src))) { if(v4mapped(gate) || v4mapped(src)) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
...@@ -995,7 +995,7 @@ kernel_route(int operation, int table, ...@@ -995,7 +995,7 @@ kernel_route(int operation, int table,
ipv4 = v4mapped(gate); ipv4 = v4mapped(gate);
use_src = (src_plen != 0 && 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 "
"table %d metric %d dev %d nexthop %s\n", "table %d metric %d dev %d nexthop %s\n",
...@@ -1096,6 +1096,7 @@ parse_kernel_route_rta(struct rtmsg *rtm, int len, struct kernel_route *route) ...@@ -1096,6 +1096,7 @@ parse_kernel_route_rta(struct rtmsg *rtm, int len, struct kernel_route *route)
/* if RTA_DST is not a TLV, that's a default destination */ /* if RTA_DST is not a TLV, that's a default destination */
const unsigned char zeroes[4] = {0, 0, 0, 0}; const unsigned char zeroes[4] = {0, 0, 0, 0};
v4tov6(route->prefix, zeroes); v4tov6(route->prefix, zeroes);
v4tov6(route->src_prefix, zeroes);
route->plen = 96; route->plen = 96;
} }
route->proto = rtm->rtm_protocol; route->proto = rtm->rtm_protocol;
......
...@@ -424,7 +424,7 @@ kernel_route(int operation, int table, ...@@ -424,7 +424,7 @@ kernel_route(int operation, int table,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01 }}}; 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01 }}};
/* Source-specific routes are not implemented yet for BSD. */ /* Source-specific routes are not implemented yet for BSD. */
if(src_plen > 0) { if(!is_default(src, src_plen)) {
errno = ENOSYS; errno = ENOSYS;
return -1; return -1;
} }
......
...@@ -463,8 +463,8 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -463,8 +463,8 @@ parse_packet(const unsigned char *from, struct interface *ifp,
have_v6_nh = 1; have_v6_nh = 1;
} }
} else if(type == MESSAGE_UPDATE) { } else if(type == MESSAGE_UPDATE) {
unsigned char prefix[16], *nh; unsigned char prefix[16], src_prefix[16], *nh;
unsigned char plen; unsigned char plen, src_plen;
unsigned char channels[MAX_CHANNEL_HOPS]; unsigned char channels[MAX_CHANNEL_HOPS];
int channels_len = MAX_CHANNEL_HOPS; int channels_len = MAX_CHANNEL_HOPS;
unsigned short interval, seqno, metric; unsigned short interval, seqno, metric;
...@@ -485,6 +485,13 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -485,6 +485,13 @@ parse_packet(const unsigned char *from, struct interface *ifp,
len - 10, prefix); len - 10, prefix);
else else
rc = -1; rc = -1;
if(message[2] == 1) {
v4tov6(src_prefix, zeroes);
src_plen = 96;
} else {
memcpy(src_prefix, zeroes, 16);
src_plen = 0;
}
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 = 0;
...@@ -547,11 +554,11 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -547,11 +554,11 @@ parse_packet(const unsigned char *from, struct interface *ifp,
parse_update_subtlv(ifp, metric, message + 2 + parsed_len, parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
len - parsed_len, channels, &channels_len); len - parsed_len, channels, &channels_len);
update_route(router_id, prefix, plen, zeroes, 0, seqno, update_route(router_id, prefix, plen, src_prefix, src_plen, seqno,
metric, interval, neigh, nh, metric, interval, neigh, nh,
channels, channels_len); channels, channels_len);
} else if(type == MESSAGE_REQUEST) { } else if(type == MESSAGE_REQUEST) {
unsigned char prefix[16], plen; unsigned char prefix[16], src_prefix[16], plen, src_plen;
int rc; int rc;
if(len < 2) goto fail; if(len < 2) goto fail;
rc = network_prefix(message[2], message[3], 0, rc = network_prefix(message[2], message[3], 0,
...@@ -573,10 +580,17 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -573,10 +580,17 @@ parse_packet(const unsigned char *from, struct interface *ifp,
now.tv_sec - MAX(neigh->ifp->hello_interval / 100, 1)) now.tv_sec - MAX(neigh->ifp->hello_interval / 100, 1))
send_update(neigh->ifp, 0, NULL, 0, zeroes, 0); send_update(neigh->ifp, 0, NULL, 0, zeroes, 0);
} else { } else {
send_update(neigh->ifp, 0, prefix, plen, zeroes, 0); if(message[2] == 1) {
v4tov6(src_prefix, zeroes);
src_plen = 96;
} else {
memcpy(src_prefix, zeroes, 16);
src_plen = 0;
}
send_update(neigh->ifp, 0, prefix, plen, src_prefix, src_plen);
} }
} else if(type == MESSAGE_MH_REQUEST) { } else if(type == MESSAGE_MH_REQUEST) {
unsigned char prefix[16], plen; unsigned char prefix[16], src_prefix[16], plen, src_plen;
unsigned short seqno; unsigned short seqno;
int rc; int rc;
if(len < 14) goto fail; if(len < 14) goto fail;
...@@ -585,13 +599,20 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -585,13 +599,20 @@ parse_packet(const unsigned char *from, struct interface *ifp,
message + 16, NULL, len - 14, prefix); message + 16, NULL, len - 14, prefix);
if(rc < 0) goto fail; if(rc < 0) goto fail;
plen = message[3] + (message[2] == 1 ? 96 : 0); plen = message[3] + (message[2] == 1 ? 96 : 0);
if(message[2] == 1) {
v4tov6(src_prefix, zeroes);
src_plen = 96;
} else {
memcpy(src_prefix, zeroes, 16);
src_plen = 0;
}
debugf("Received request (%d) for %s from %s on %s (%s, %d).\n", debugf("Received request (%d) for %s from %s on %s (%s, %d).\n",
message[6], message[6],
format_prefix(prefix, plen), format_prefix(prefix, plen),
format_address(from), ifp->name, format_address(from), ifp->name,
format_eui64(message + 8), seqno); format_eui64(message + 8), seqno);
handle_request(neigh, prefix, plen, zeroes, 0, message[6], handle_request(neigh, prefix, plen, src_prefix, src_plen,
seqno, message + 8); message[6], seqno, message + 8);
} else if(type == MESSAGE_UPDATE_SRC_SPECIFIC) { } else if(type == MESSAGE_UPDATE_SRC_SPECIFIC) {
unsigned char prefix[16], src_prefix[16], *nh; unsigned char prefix[16], src_prefix[16], *nh;
unsigned char ae, plen, src_plen, omitted; unsigned char ae, plen, src_plen, omitted;
...@@ -1141,6 +1162,7 @@ really_send_update(struct interface *ifp, ...@@ -1141,6 +1162,7 @@ really_send_update(struct interface *ifp,
int real_src_plen = 0; int real_src_plen = 0;
unsigned short flags = 0; unsigned short flags = 0;
int channels_size; int channels_size;
int is_ss = !is_default(src_prefix, src_plen);
if(diversity_kind != DIVERSITY_CHANNEL) if(diversity_kind != DIVERSITY_CHANNEL)
channels_len = -1; channels_len = -1;
...@@ -1177,17 +1199,15 @@ really_send_update(struct interface *ifp, ...@@ -1177,17 +1199,15 @@ really_send_update(struct interface *ifp,
real_prefix = prefix + 12; real_prefix = prefix + 12;
real_plen = plen - 96; real_plen = plen - 96;
if(src_plen != 0 /* it should never be 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 {
if(ifp->have_buffered_prefix) { if(ifp->have_buffered_prefix) {
while(omit < plen / 8 && while(omit < plen / 8 &&
ifp->buffered_prefix[omit] == prefix[omit]) ifp->buffered_prefix[omit] == prefix[omit])
omit++; omit++;
} }
if(src_plen == 0 && (!ifp->have_buffered_prefix || plen >= 48)) if(!is_ss && (!ifp->have_buffered_prefix || plen >= 48))
flags |= 0x80; flags |= 0x80;
real_prefix = prefix; real_prefix = prefix;
real_plen = plen; real_plen = plen;
...@@ -1196,7 +1216,7 @@ really_send_update(struct interface *ifp, ...@@ -1196,7 +1216,7 @@ really_send_update(struct interface *ifp,
} }
if(!ifp->have_buffered_id || memcmp(id, ifp->buffered_id, 8) != 0) { if(!ifp->have_buffered_id || memcmp(id, ifp->buffered_id, 8) != 0) {
if(src_plen == 0 && real_plen == 128 && if(!is_ss && real_plen == 128 &&
memcmp(real_prefix + 8, id, 8) == 0) { memcmp(real_prefix + 8, id, 8) == 0) {
flags |= 0x40; flags |= 0x40;
} else { } else {
...@@ -1209,7 +1229,7 @@ really_send_update(struct interface *ifp, ...@@ -1209,7 +1229,7 @@ really_send_update(struct interface *ifp,
ifp->have_buffered_id = 1; ifp->have_buffered_id = 1;
} }
if(src_plen == 0) if(!is_ss)
start_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit + start_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit +
channels_size); channels_size);
else else
...@@ -1217,7 +1237,7 @@ really_send_update(struct interface *ifp, ...@@ -1217,7 +1237,7 @@ really_send_update(struct interface *ifp,
10 + (real_plen + 7) / 8 - omit + 10 + (real_plen + 7) / 8 - omit +
(real_src_plen + 7) / 8 + channels_size); (real_src_plen + 7) / 8 + channels_size);
accumulate_byte(ifp, v4 ? 1 : 2); accumulate_byte(ifp, v4 ? 1 : 2);
if(src_plen != 0) if(is_ss)
accumulate_byte(ifp, real_src_plen); accumulate_byte(ifp, real_src_plen);
else else
accumulate_byte(ifp, flags); accumulate_byte(ifp, flags);
...@@ -1227,7 +1247,7 @@ really_send_update(struct interface *ifp, ...@@ -1227,7 +1247,7 @@ really_send_update(struct interface *ifp,
accumulate_short(ifp, seqno); accumulate_short(ifp, seqno);
accumulate_short(ifp, metric); accumulate_short(ifp, metric);
accumulate_bytes(ifp, real_prefix + omit, (real_plen + 7) / 8 - omit); accumulate_bytes(ifp, real_prefix + omit, (real_plen + 7) / 8 - omit);
if(src_plen != 0) if(is_ss)
accumulate_bytes(ifp, real_src_prefix, (real_src_plen + 7) / 8); accumulate_bytes(ifp, real_src_prefix, (real_src_plen + 7) / 8);
/* Note that an empty channels TLV is different from no such TLV. */ /* Note that an empty channels TLV is different from no such TLV. */
if(channels_len >= 0) { if(channels_len >= 0) {
...@@ -1235,7 +1255,7 @@ really_send_update(struct interface *ifp, ...@@ -1235,7 +1255,7 @@ really_send_update(struct interface *ifp,
accumulate_byte(ifp, channels_len); accumulate_byte(ifp, channels_len);
accumulate_bytes(ifp, channels, channels_len); accumulate_bytes(ifp, channels, channels_len);
} }
if(src_plen == 0) if(!is_ss)
end_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit + end_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit +
channels_size); channels_size);
else else
...@@ -1522,11 +1542,13 @@ send_update(struct interface *ifp, int urgent, ...@@ -1522,11 +1542,13 @@ send_update(struct interface *ifp, int urgent,
routes = route_stream(ROUTE_INSTALLED); routes = route_stream(ROUTE_INSTALLED);
if(routes) { if(routes) {
while(1) { while(1) {
int is_ss;
struct babel_route *route = route_stream_next(routes); struct babel_route *route = route_stream_next(routes);
if(route == NULL) if(route == NULL)
break; break;
if((src_prefix && route->src->src_plen != 0) || is_ss = !is_default(route->src->src_prefix,
(prefix && route->src->src_plen == 0)) route->src->src_plen);
if((src_prefix && is_ss) || (prefix && !is_ss))
continue; continue;
buffer_update(ifp, route->src->prefix, route->src->plen, buffer_update(ifp, route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen); route->src->src_prefix, route->src->src_plen);
...@@ -1743,7 +1765,7 @@ send_request(struct interface *ifp, ...@@ -1743,7 +1765,7 @@ send_request(struct interface *ifp,
const unsigned char *prefix, unsigned char plen, const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen) const unsigned char *src_prefix, unsigned char src_plen)
{ {
int v4, pb, spb, len; int v4, pb, spb, len, is_ss;
if(ifp == NULL) { if(ifp == NULL) {
struct interface *ifp_auxn; struct interface *ifp_auxn;
...@@ -1790,7 +1812,8 @@ send_request(struct interface *ifp, ...@@ -1790,7 +1812,8 @@ send_request(struct interface *ifp,
pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
len = 2 + pb; len = 2 + pb;
if(src_plen != 0) { is_ss = !is_default(src_prefix, src_plen);
if(is_ss) {
spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8; spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8;
len += spb + 1; len += spb + 1;
start_message(ifp, MESSAGE_REQUEST_SRC_SPECIFIC, len); start_message(ifp, MESSAGE_REQUEST_SRC_SPECIFIC, len);
...@@ -1800,13 +1823,13 @@ send_request(struct interface *ifp, ...@@ -1800,13 +1823,13 @@ send_request(struct interface *ifp,
} }
accumulate_byte(ifp, v4 ? 1 : 2); accumulate_byte(ifp, v4 ? 1 : 2);
accumulate_byte(ifp, v4 ? plen - 96 : plen); accumulate_byte(ifp, v4 ? plen - 96 : plen);
if(src_plen != 0) if(is_ss)
accumulate_byte(ifp, v4 ? src_plen - 96 : src_plen); accumulate_byte(ifp, v4 ? src_plen - 96 : src_plen);
if(v4) if(v4)
accumulate_bytes(ifp, prefix + 12, pb); accumulate_bytes(ifp, prefix + 12, pb);
else else
accumulate_bytes(ifp, prefix, pb); accumulate_bytes(ifp, prefix, pb);
if(src_plen != 0) { if(is_ss) {
if(v4) if(v4)
accumulate_bytes(ifp, src_prefix + 12, spb); accumulate_bytes(ifp, src_prefix + 12, spb);
else else
...@@ -1822,7 +1845,7 @@ send_unicast_request(struct neighbour *neigh, ...@@ -1822,7 +1845,7 @@ send_unicast_request(struct neighbour *neigh,
const unsigned char *prefix, unsigned char plen, const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen) const unsigned char *src_prefix, unsigned char src_plen)
{ {
int rc, v4, pb, spb, len; int rc, v4, pb, spb, len, is_ss;
/* make sure any buffered updates go out before this request. */ /* make sure any buffered updates go out before this request. */
flushupdates(neigh->ifp); flushupdates(neigh->ifp);
...@@ -1861,7 +1884,8 @@ send_unicast_request(struct neighbour *neigh, ...@@ -1861,7 +1884,8 @@ send_unicast_request(struct neighbour *neigh,
pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
len = 2 + pb; len = 2 + pb;
if(src_plen != 0) { is_ss = !is_default(src_prefix, src_plen);
if(is_ss) {
spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8; spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8;
len += spb + 1; len += spb + 1;
rc = start_unicast_message(neigh, MESSAGE_REQUEST_SRC_SPECIFIC, len); rc = start_unicast_message(neigh, MESSAGE_REQUEST_SRC_SPECIFIC, len);
...@@ -1872,13 +1896,13 @@ send_unicast_request(struct neighbour *neigh, ...@@ -1872,13 +1896,13 @@ send_unicast_request(struct neighbour *neigh,
if(rc < 0) return; if(rc < 0) return;
accumulate_unicast_byte(neigh, v4 ? 1 : 2); accumulate_unicast_byte(neigh, v4 ? 1 : 2);
accumulate_unicast_byte(neigh, v4 ? plen - 96 : plen); accumulate_unicast_byte(neigh, v4 ? plen - 96 : plen);
if(src_plen != 0) if(is_ss)
accumulate_unicast_byte(neigh, v4 ? src_plen - 96 : src_plen); accumulate_unicast_byte(neigh, v4 ? src_plen - 96 : src_plen);
if(v4) if(v4)
accumulate_unicast_bytes(neigh, prefix + 12, pb); accumulate_unicast_bytes(neigh, prefix + 12, pb);
else else
accumulate_unicast_bytes(neigh, prefix, pb); accumulate_unicast_bytes(neigh, prefix, pb);
if(src_plen != 0) { if(is_ss) {
if(v4) if(v4)
accumulate_unicast_bytes(neigh, src_prefix + 12, spb); accumulate_unicast_bytes(neigh, src_prefix + 12, spb);
else else
...@@ -1896,7 +1920,7 @@ send_multihop_request(struct interface *ifp, ...@@ -1896,7 +1920,7 @@ send_multihop_request(struct interface *ifp,
unsigned short seqno, const unsigned char *id, unsigned short seqno, const unsigned char *id,
unsigned short hop_count) unsigned short hop_count)
{ {
int v4, pb, spb, len; int v4, pb, spb, len, is_ss;
/* Make sure any buffered updates go out before this request. */ /* Make sure any buffered updates go out before this request. */
flushupdates(ifp); flushupdates(ifp);
...@@ -1922,7 +1946,8 @@ send_multihop_request(struct interface *ifp, ...@@ -1922,7 +1946,8 @@ send_multihop_request(struct interface *ifp,
pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
len = 6 + 8 + pb; len = 6 + 8 + pb;
if(src_plen != 0) { is_ss = !is_default(src_prefix, src_plen);
if(is_ss) {
spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8; spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8;
len += spb; len += spb;
start_message(ifp, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len); start_message(ifp, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len);
...@@ -1942,7 +1967,7 @@ send_multihop_request(struct interface *ifp, ...@@ -1942,7 +1967,7 @@ send_multihop_request(struct interface *ifp,
else else
accumulate_bytes(ifp, prefix, pb); accumulate_bytes(ifp, prefix, pb);
} }
if(src_plen != 0) { if(is_ss) {
if(v4) if(v4)
accumulate_bytes(ifp, src_prefix + 12, spb); accumulate_bytes(ifp, src_prefix + 12, spb);
else else
...@@ -1961,7 +1986,7 @@ send_unicast_multihop_request(struct neighbour *neigh, ...@@ -1961,7 +1986,7 @@ send_unicast_multihop_request(struct neighbour *neigh,
unsigned short seqno, const unsigned char *id, unsigned short seqno, const unsigned char *id,
unsigned short hop_count) unsigned short hop_count)
{ {
int rc, v4, pb, spb, len; int rc, v4, pb, spb, len, is_ss;
/* Make sure any buffered updates go out before this request. */ /* Make sure any buffered updates go out before this request. */
flushupdates(neigh->ifp); flushupdates(neigh->ifp);
...@@ -1974,7 +1999,8 @@ send_unicast_multihop_request(struct neighbour *neigh, ...@@ -1974,7 +1999,8 @@ send_unicast_multihop_request(struct neighbour *neigh,
pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
len = 6 + 8 + pb; len = 6 + 8 + pb;
if(src_plen != 0) { is_ss = !is_default(src_prefix, src_plen);
if(is_ss) {
spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8; spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8;
len += spb; len += spb;
rc = start_unicast_message(neigh, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len); rc = start_unicast_message(neigh, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len);
...@@ -1995,7 +2021,7 @@ send_unicast_multihop_request(struct neighbour *neigh, ...@@ -1995,7 +2021,7 @@ send_unicast_multihop_request(struct neighbour *neigh,
else else
accumulate_unicast_bytes(neigh, prefix, pb); accumulate_unicast_bytes(neigh, prefix, pb);
} }
if(src_plen != 0) { if(is_ss) {
if(v4) if(v4)
accumulate_unicast_bytes(neigh, src_prefix + 12, spb); accumulate_unicast_bytes(neigh, src_prefix + 12, spb);
else else
......
...@@ -59,7 +59,7 @@ check_specific_first(void) ...@@ -59,7 +59,7 @@ check_specific_first(void)
int specific = 1; int specific = 1;
int i; int i;
for(i = 0; i < route_slots; i++) { for(i = 0; i < route_slots; i++) {
if(routes[i]->src->src_plen == 0) { if(is_default(routes[i]->src->src_prefix, routes[i]->src->src_plen)) {
specific = 0; specific = 0;
} else if(!specific) { } else if(!specific) {
return 0; return 0;
...@@ -78,11 +78,13 @@ route_compare(const unsigned char *prefix, unsigned char plen, ...@@ -78,11 +78,13 @@ route_compare(const unsigned char *prefix, unsigned char plen,
struct babel_route *route) struct babel_route *route)
{ {
int i; int i;
int is_ss = !is_default(src_prefix, src_plen);
int is_ss_rt = !is_default(route->src->src_prefix, route->src->src_plen);
/* Put all source-specific routes in the front of the list. */ /* Put all source-specific routes in the front of the list. */
if(src_plen == 0 && route->src->src_plen > 0) { if(!is_ss && is_ss_rt) {
return 1; return 1;
} else if(src_plen > 0 && route->src->src_plen == 0) { } else if(is_ss && !is_ss_rt) {
return -1; return -1;
} }
...@@ -95,10 +97,7 @@ route_compare(const unsigned char *prefix, unsigned char plen, ...@@ -95,10 +97,7 @@ route_compare(const unsigned char *prefix, unsigned char plen,
if(plen > route->src->plen) if(plen > route->src->plen)
return 1; return 1;
if(src_plen == 0) { if(is_ss) {
if(route->src->src_plen > 0)
return -1;
} else {
i = memcmp(src_prefix, route->src->src_prefix, 16); i = memcmp(src_prefix, route->src->src_prefix, 16);
if(i != 0) if(i != 0)
return i; return i;
...@@ -401,7 +400,8 @@ route_stream_next(struct route_stream *stream) ...@@ -401,7 +400,8 @@ route_stream_next(struct route_stream *stream)
if(stream->installed) { if(stream->installed) {
while(stream->index < route_slots) while(stream->index < route_slots)
if(stream->installed == ROUTE_SS_INSTALLED && if(stream->installed == ROUTE_SS_INSTALLED &&
routes[stream->index]->src->src_plen == 0) is_default(routes[stream->index]->src->src_prefix,
routes[stream->index]->src->src_plen))
return NULL; return NULL;
else if(routes[stream->index]->installed) else if(routes[stream->index]->installed)
break; break;
...@@ -858,10 +858,9 @@ update_route(const unsigned char *id, ...@@ -858,10 +858,9 @@ update_route(const unsigned char *id,
} }
is_v4 = v4mapped(prefix); is_v4 = v4mapped(prefix);
if(src_plen != 0 && is_v4 != v4mapped(src_prefix)) if(is_v4 != v4mapped(src_prefix))
return NULL; return NULL;
add_metric = input_filter(id, prefix, plen, src_prefix, src_plen, add_metric = input_filter(id, prefix, plen, src_prefix, src_plen,
neigh->address, neigh->ifp->ifindex); neigh->address, neigh->ifp->ifindex);
if(add_metric >= INFINITY) if(add_metric >= INFINITY)
......
...@@ -185,7 +185,7 @@ find_table(const unsigned char *dest, unsigned short plen, ...@@ -185,7 +185,7 @@ find_table(const unsigned char *dest, unsigned short plen,
install_filter(dest, plen, src, src_plen, &filter_result); install_filter(dest, plen, src, src_plen, &filter_result);
if(filter_result.table) { if(filter_result.table) {
return filter_result.table; return filter_result.table;
} else if(src_plen == 0) { } else if(is_default(src, src_plen)) {
return export_table; return export_table;
} else if(kernel_disambiguate(v4mapped(dest))) { } else if(kernel_disambiguate(v4mapped(dest))) {
return export_table; return export_table;
......
...@@ -103,6 +103,12 @@ void v4tov6(unsigned char *dst, const unsigned char *src); ...@@ -103,6 +103,12 @@ 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);
static inline int
is_default(const unsigned char *prefix, int plen)
{
return plen == 0 || (plen == 96 && v4mapped(prefix));
}
enum prefix_status { enum prefix_status {
PST_EQUALS = 0, PST_EQUALS = 0,
PST_DISJOINT, PST_DISJOINT,
......
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