[Babel-users] [PATCH 2/3] Use standard v4mapped encoding for source prefixes.

Matthieu Boutier boutier at pps.univ-paris-diderot.fr
Mon May 2 08:56:34 UTC 2016


---
 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




More information about the Babel-users mailing list