--- interface.h | 2 +- kernel.h | 2 +- kernel_netlink.c | 7 +++-- kernel_socket.c | 2 +- message.c | 92 ++++++++++++++++++++++++++++++++++++-------------------- route.c | 19 ++++++------ rule.c | 2 +- util.h | 6 ++++ 8 files changed, 82 insertions(+), 50 deletions(-)
diff --git a/interface.h b/interface.h index 5d0eedd..97ad77d 100644 --- a/interface.h +++ b/interface.h @@ -25,7 +25,7 @@ struct buffered_update { unsigned char prefix[16]; unsigned char src_prefix[16]; unsigned char plen; - unsigned char src_plen; /* 0 <=> no src prefix */ + unsigned char src_plen; unsigned char pad[2]; }; diff --git a/kernel.h b/kernel.h index b6286fc..5688d01 100644 --- a/kernel.h +++ b/kernel.h @@ -29,7 +29,7 @@ struct kernel_route { unsigned char prefix[16]; int plen; unsigned char src_prefix[16]; - int src_plen; /* no source prefix <=> src_plen == 0 */ + int src_plen; int metric; unsigned int ifindex; int proto; diff --git a/kernel_netlink.c b/kernel_netlink.c index 4eadc39..30cc6fb 100644 --- a/kernel_netlink.c +++ b/kernel_netlink.c @@ -951,12 +951,12 @@ kernel_route(int operation, int table, /* Check that the protocol family is consistent. */ if(plen >= 96 && v4mapped(dest)) { if(!v4mapped(gate) || - (src_plen > 0 && (!v4mapped(src) || src_plen < 96))) { + !v4mapped(src)) { errno = EINVAL; return -1; } } else { - if(v4mapped(gate)|| (src_plen > 0 && v4mapped(src))) { + if(v4mapped(gate) || v4mapped(src)) { errno = EINVAL; return -1; } @@ -991,7 +991,7 @@ kernel_route(int operation, int table, 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 " "table %d metric %d dev %d nexthop %s\n", @@ -1092,6 +1092,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 */ const unsigned char zeroes[4] = {0, 0, 0, 0}; v4tov6(route->prefix, zeroes); + v4tov6(route->src_prefix, zeroes); route->plen = 96; } route->proto = rtm->rtm_protocol; diff --git a/kernel_socket.c b/kernel_socket.c index 92ff93d..7b5419b 100644 --- a/kernel_socket.c +++ b/kernel_socket.c @@ -424,7 +424,7 @@ kernel_route(int operation, int table, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01 }}}; /* Source-specific routes are not implemented yet for BSD. */ - if(src_plen > 0) { + if(!is_default(src, src_plen)) { errno = ENOSYS; return -1; } diff --git a/message.c b/message.c index fdc1999..a8d307c 100644 --- a/message.c +++ b/message.c @@ -443,8 +443,8 @@ parse_packet(const unsigned char *from, struct interface *ifp, have_v6_nh = 1; } } else if(type == MESSAGE_UPDATE) { - unsigned char prefix[16], *nh; - unsigned char plen; + unsigned char prefix[16], src_prefix[16], *nh; + unsigned char plen, src_plen; unsigned char channels[MAX_CHANNEL_HOPS]; int channels_len = MAX_CHANNEL_HOPS; unsigned short interval, seqno, metric; @@ -465,6 +465,13 @@ parse_packet(const unsigned char *from, struct interface *ifp, len - 10, prefix); else 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(message[3] & 0x80) have_v4_prefix = have_v6_prefix = 0; @@ -527,11 +534,11 @@ parse_packet(const unsigned char *from, struct interface *ifp, parse_update_subtlv(ifp, metric, message + 2 + parsed_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, channels, channels_len); } else if(type == MESSAGE_REQUEST) { - unsigned char prefix[16], plen; + unsigned char prefix[16], src_prefix[16], plen, src_plen; int rc; if(len < 2) goto fail; rc = network_prefix(message[2], message[3], 0, @@ -553,10 +560,17 @@ parse_packet(const unsigned char *from, struct interface *ifp, now.tv_sec - MAX(neigh->ifp->hello_interval / 100, 1)) send_update(neigh->ifp, 0, NULL, 0, zeroes, 0); } 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) { - unsigned char prefix[16], plen; + unsigned char prefix[16], src_prefix[16], plen, src_plen; unsigned short seqno; int rc; if(len < 14) goto fail; @@ -565,12 +579,19 @@ parse_packet(const unsigned char *from, struct interface *ifp, message + 16, NULL, len - 14, prefix); if(rc < 0) goto fail; 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", message[6], format_prefix(prefix, plen), format_address(from), ifp->name, format_eui64(message + 8), seqno); - handle_request(neigh, prefix, plen, zeroes, 0, message[6], + handle_request(neigh, prefix, plen, src_prefix, src_plen, message[6], seqno, message + 8); } else if(type == MESSAGE_UPDATE_SRC_SPECIFIC) { unsigned char prefix[16], src_prefix[16], *nh; @@ -1121,6 +1142,7 @@ really_send_update(struct interface *ifp, int real_src_plen = 0; unsigned short flags = 0; int channels_size; + int no_src = is_default(src_prefix, src_plen); if(diversity_kind != DIVERSITY_CHANNEL) channels_len = -1; @@ -1157,17 +1179,15 @@ really_send_update(struct interface *ifp, real_prefix = prefix + 12; real_plen = plen - 96; - if(src_plen != 0 /* it should never be 96 */) { - real_src_prefix = src_prefix + 12; - real_src_plen = src_plen - 96; - } + real_src_prefix = src_prefix + 12; + real_src_plen = src_plen - 96; } else { if(ifp->have_buffered_prefix) { while(omit < plen / 8 && ifp->buffered_prefix[omit] == prefix[omit]) omit++; } - if(src_plen == 0 && (!ifp->have_buffered_prefix || plen >= 48)) + if(no_src && (!ifp->have_buffered_prefix || plen >= 48)) flags |= 0x80; real_prefix = prefix; real_plen = plen; @@ -1176,7 +1196,7 @@ really_send_update(struct interface *ifp, } if(!ifp->have_buffered_id || memcmp(id, ifp->buffered_id, 8) != 0) { - if(src_plen == 0 && real_plen == 128 && + if(no_src && real_plen == 128 && memcmp(real_prefix + 8, id, 8) == 0) { flags |= 0x40; } else { @@ -1189,7 +1209,7 @@ really_send_update(struct interface *ifp, ifp->have_buffered_id = 1; } - if(src_plen == 0) + if(no_src) start_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit + channels_size); else @@ -1197,7 +1217,7 @@ really_send_update(struct interface *ifp, 10 + (real_plen + 7) / 8 - omit + (real_src_plen + 7) / 8 + channels_size); accumulate_byte(ifp, v4 ? 1 : 2); - if(src_plen != 0) + if(!no_src) accumulate_byte(ifp, real_src_plen); else accumulate_byte(ifp, flags); @@ -1207,7 +1227,7 @@ really_send_update(struct interface *ifp, accumulate_short(ifp, seqno); accumulate_short(ifp, metric); accumulate_bytes(ifp, real_prefix + omit, (real_plen + 7) / 8 - omit); - if(src_plen != 0) + if(!no_src) accumulate_bytes(ifp, real_src_prefix, (real_src_plen + 7) / 8); /* Note that an empty channels TLV is different from no such TLV. */ if(channels_len >= 0) { @@ -1215,7 +1235,7 @@ really_send_update(struct interface *ifp, accumulate_byte(ifp, channels_len); accumulate_bytes(ifp, channels, channels_len); } - if(src_plen == 0) + if(no_src) end_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit + channels_size); else @@ -1502,11 +1522,13 @@ send_update(struct interface *ifp, int urgent, routes = route_stream(ROUTE_INSTALLED); if(routes) { while(1) { + int no_src; struct babel_route *route = route_stream_next(routes); if(route == NULL) break; - if((src_prefix && route->src->src_plen != 0) || - (prefix && route->src->src_plen == 0)) + no_src = is_default(route->src->src_prefix, + route->src->src_plen); + if((src_prefix && !no_src) || (prefix && no_src)) continue; buffer_update(ifp, route->src->prefix, route->src->plen, route->src->src_prefix, route->src->src_plen); @@ -1723,7 +1745,7 @@ send_request(struct interface *ifp, const unsigned char *prefix, unsigned char plen, const unsigned char *src_prefix, unsigned char src_plen) { - int v4, pb, spb, len; + int v4, pb, spb, len, no_src; if(ifp == NULL) { struct interface *ifp_auxn; @@ -1770,7 +1792,8 @@ send_request(struct interface *ifp, pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; len = 2 + pb; - if(src_plen != 0) { + no_src = is_default(src_prefix, src_plen); + if(!no_src) { spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8; len += spb + 1; start_message(ifp, MESSAGE_REQUEST_SRC_SPECIFIC, len); @@ -1780,13 +1803,13 @@ send_request(struct interface *ifp, } accumulate_byte(ifp, v4 ? 1 : 2); accumulate_byte(ifp, v4 ? plen - 96 : plen); - if(src_plen != 0) + if(!no_src) accumulate_byte(ifp, v4 ? src_plen - 96 : src_plen); if(v4) accumulate_bytes(ifp, prefix + 12, pb); else accumulate_bytes(ifp, prefix, pb); - if(src_plen != 0) { + if(!no_src) { if(v4) accumulate_bytes(ifp, src_prefix + 12, spb); else @@ -1802,7 +1825,7 @@ send_unicast_request(struct neighbour *neigh, const unsigned char *prefix, unsigned char plen, const unsigned char *src_prefix, unsigned char src_plen) { - int rc, v4, pb, spb, len; + int rc, v4, pb, spb, len, no_src; /* make sure any buffered updates go out before this request. */ flushupdates(neigh->ifp); @@ -1841,7 +1864,8 @@ send_unicast_request(struct neighbour *neigh, pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; len = 2 + pb; - if(src_plen != 0) { + no_src = is_default(src_prefix, src_plen); + if(!no_src) { spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8; len += spb + 1; rc = start_unicast_message(neigh, MESSAGE_REQUEST_SRC_SPECIFIC, len); @@ -1852,13 +1876,13 @@ send_unicast_request(struct neighbour *neigh, if(rc < 0) return; accumulate_unicast_byte(neigh, v4 ? 1 : 2); accumulate_unicast_byte(neigh, v4 ? plen - 96 : plen); - if(src_plen != 0) + if(!no_src) accumulate_unicast_byte(neigh, v4 ? src_plen - 96 : src_plen); if(v4) accumulate_unicast_bytes(neigh, prefix + 12, pb); else accumulate_unicast_bytes(neigh, prefix, pb); - if(src_plen != 0) { + if(!no_src) { if(v4) accumulate_unicast_bytes(neigh, src_prefix + 12, spb); else @@ -1876,7 +1900,7 @@ send_multihop_request(struct interface *ifp, unsigned short seqno, const unsigned char *id, unsigned short hop_count) { - int v4, pb, spb, len; + int v4, pb, spb, len, no_src; /* Make sure any buffered updates go out before this request. */ flushupdates(ifp); @@ -1902,7 +1926,8 @@ send_multihop_request(struct interface *ifp, pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; len = 6 + 8 + pb; - if(src_plen != 0) { + no_src = is_default(src_prefix, src_plen); + if(!no_src) { spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8; len += spb; start_message(ifp, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len); @@ -1922,7 +1947,7 @@ send_multihop_request(struct interface *ifp, else accumulate_bytes(ifp, prefix, pb); } - if(src_plen != 0) { + if(!no_src) { if(v4) accumulate_bytes(ifp, src_prefix + 12, spb); else @@ -1941,7 +1966,7 @@ send_unicast_multihop_request(struct neighbour *neigh, unsigned short seqno, const unsigned char *id, unsigned short hop_count) { - int rc, v4, pb, spb, len; + int rc, v4, pb, spb, len, no_src; /* Make sure any buffered updates go out before this request. */ flushupdates(neigh->ifp); @@ -1954,7 +1979,8 @@ send_unicast_multihop_request(struct neighbour *neigh, pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; len = 6 + 8 + pb; - if(src_plen != 0) { + no_src = is_default(src_prefix, src_plen); + if(!no_src) { spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8; len += spb; rc = start_unicast_message(neigh, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len); @@ -1975,7 +2001,7 @@ send_unicast_multihop_request(struct neighbour *neigh, else accumulate_unicast_bytes(neigh, prefix, pb); } - if(src_plen != 0) { + if(!no_src) { if(v4) accumulate_unicast_bytes(neigh, src_prefix + 12, spb); else diff --git a/route.c b/route.c index 0eacd00..2e8918e 100644 --- a/route.c +++ b/route.c @@ -59,7 +59,7 @@ check_specific_first(void) int specific = 1; int 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; } else if(!specific) { return 0; @@ -78,11 +78,13 @@ route_compare(const unsigned char *prefix, unsigned char plen, struct babel_route *route) { int i; + int no_src = is_default(src_prefix, src_plen); + int no_src_rt = is_default(route->src->src_prefix, route->src->src_plen); /* Put all source-specific routes in the front of the list. */ - if(src_plen == 0 && route->src->src_plen > 0) { + if(no_src && !no_src_rt) { return 1; - } else if(src_plen > 0 && route->src->src_plen == 0) { + } else if(!no_src && no_src_rt) { return -1; } @@ -95,10 +97,7 @@ route_compare(const unsigned char *prefix, unsigned char plen, if(plen > route->src->plen) return 1; - if(src_plen == 0) { - if(route->src->src_plen > 0) - return -1; - } else { + if(!no_src) { i = memcmp(src_prefix, route->src->src_prefix, 16); if(i != 0) return i; @@ -401,7 +400,8 @@ route_stream_next(struct route_stream *stream) if(stream->installed) { while(stream->index < route_slots) 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; else if(routes[stream->index]->installed) break; @@ -858,10 +858,9 @@ update_route(const unsigned char *id, } is_v4 = v4mapped(prefix); - if(src_plen != 0 && is_v4 != v4mapped(src_prefix)) + if(is_v4 != v4mapped(src_prefix)) return NULL; - add_metric = input_filter(id, prefix, plen, src_prefix, src_plen, neigh->address, neigh->ifp->ifindex); if(add_metric >= INFINITY) diff --git a/rule.c b/rule.c index d8e826f..6f4de53 100644 --- a/rule.c +++ b/rule.c @@ -185,7 +185,7 @@ find_table(const unsigned char *dest, unsigned short plen, install_filter(dest, plen, src, src_plen, &filter_result); if(filter_result.table) { return filter_result.table; - } else if(src_plen == 0) { + } else if(is_default(src, src_plen)) { return export_table; } else if(kernel_disambiguate(v4mapped(dest))) { return export_table; diff --git a/util.h b/util.h index dd7bfb7..585bf7a 100644 --- a/util.h +++ b/util.h @@ -103,6 +103,12 @@ void v4tov6(unsigned char *dst, const unsigned char *src); int daemonise(void); 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 { PST_EQUALS = 0, PST_DISJOINT, -- 2.8.0.rc3 _______________________________________________ Babel-users mailing list Babel-users@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/babel-users