From a152748adbadd26f5a2658679ab50b96dac4d2dc Mon Sep 17 00:00:00 2001
From: Matthieu Boutier <boutier@pps.univ-paris-diderot.fr>
Date: Thu, 6 Feb 2014 23:38:31 +0000
Subject: [PATCH] Babel: add decoder for source-specific extension.

---
 print-babel.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 124 insertions(+), 7 deletions(-)

diff --git a/print-babel.c b/print-babel.c
index bb2612c..50a5c3c 100644
--- a/print-babel.c
+++ b/print-babel.c
@@ -88,6 +88,9 @@ babel_print(netdissect_options *ndo,
 #define MESSAGE_MH_REQUEST 10
 #define MESSAGE_TSPC 11
 #define MESSAGE_HMAC 12
+#define MESSAGE_UPDATE_SRC_SPECIFIC 13
+#define MESSAGE_REQUEST_SRC_SPECIFIC 14
+#define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15
 
 /* sub-TLVs */
 #define MESSAGE_SUB_PAD1 0
@@ -118,17 +121,19 @@ static const unsigned char v4prefix[16] =
 static const char *
 format_prefix(netdissect_options *ndo, const u_char *prefix, unsigned char plen)
 {
-    static char buf[50];
+    static char buf[4][50];
+    static int i = 0;
+    i = (i + 1) % 4;
     if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0)
-        snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96);
+        snprintf(buf[i], 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96);
     else
 #ifdef INET6
-        snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen);
+        snprintf(buf[i], 50, "%s/%u", ip6addr_string(ndo, prefix), plen);
 #else
-        snprintf(buf, 50, "IPv6 addresses not supported");
+        snprintf(buf[i], 50, "IPv6 addresses not supported");
 #endif
-    buf[49] = '\0';
-    return buf;
+    buf[i][49] = '\0';
+    return buf[i];
 }
 
 static const char *
@@ -304,7 +309,8 @@ subtlvs_print(netdissect_options *ndo,
                 ND_PRINT((ndo, "%s%s", sep, tok2str(diversity_str, "%u", *cp++)));
                 sep = "-";
             }
-            if(tlv_type != MESSAGE_UPDATE)
+            if(tlv_type != MESSAGE_UPDATE &&
+               tlv_type != MESSAGE_UPDATE_SRC_SPECIFIC)
                 ND_PRINT((ndo, " (bogus)"));
             break;
         case MESSAGE_SUB_TIMESTAMP:
@@ -348,6 +354,9 @@ babel_print_v2(netdissect_options *ndo,
     u_char v4_prefix[16] =
         {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
     u_char v6_prefix[16] = {0};
+    u_char v4_src_prefix[16] =
+        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
+    u_char v6_src_prefix[16] = {0};
 
     ND_TCHECK2(*cp, 4);
     if (length < 4)
@@ -585,6 +594,114 @@ babel_print_v2(netdissect_options *ndo,
             }
         }
             break;
+
+        case MESSAGE_UPDATE_SRC_SPECIFIC : {
+            if(!ndo->ndo_vflag) {
+                ND_PRINT((ndo, " ss-update"));
+                if(len < 1)
+                    ND_PRINT((ndo, "/truncated"));
+            } else {
+                u_char prefix[16], src_prefix[16];
+                u_short interval, seqno, metric;
+                u_char ae, plen, src_plen, omitted;
+                int rc;
+                const unsigned char *src_prefix_beginning = NULL;
+                int parsed_len = 0;
+                ND_PRINT((ndo, "\n\tSS-Update"));
+                if(len < 10) goto corrupt;
+                ae = message[2];
+                src_plen = message[3];
+                plen = message[4];
+                omitted = message[5];
+                interval = EXTRACT_16BITS(message + 6);
+                seqno = EXTRACT_16BITS(message + 8);
+                metric = EXTRACT_16BITS(message + 10);
+                rc = network_prefix(ae, plen, omitted, message + 12,
+                                    ae == 1 ? v4_prefix : v6_prefix,
+                                    len - 10, prefix);
+                if(rc < 0)
+                    goto corrupt;
+
+                parsed_len = 10 + rc;
+                src_prefix_beginning = message + 2 + parsed_len;
+
+                rc = network_prefix(ae, src_plen, 0, src_prefix_beginning, NULL,
+                                    len - parsed_len, src_prefix);
+                if(rc < 0)
+                    goto corrupt;
+                parsed_len += rc;
+                if(ae == 1) {
+                    plen += 96;
+                    src_plen += 96;
+                }
+
+                ND_PRINT((ndo, " %s from %s metric %u seqno %u interval %s",
+                          format_prefix(ndo, prefix, plen),
+                          format_prefix(ndo, src_prefix, src_plen),
+                          metric, seqno, format_interval_update(interval)));
+                /* extra data? */
+                if((u_int)parsed_len < len)
+                    subtlvs_print(ndo, message + 2 + parsed_len,
+                                  message + 2 + len, type);
+            }
+        }
+            break;
+
+        case MESSAGE_REQUEST_SRC_SPECIFIC : {
+            if(!ndo->ndo_vflag)
+                ND_PRINT((ndo, " ss-request"));
+            else {
+                int rc;
+                u_char prefix[16], src_prefix[16], plen, src_plen;
+                ND_PRINT((ndo, "\n\tSS-Request "));
+                if(len < 3) goto corrupt;
+                plen = message[3] + (message[2] == 1 ? 96 : 0);
+                src_plen = message[4] + (message[2] == 1 ? 96 : 0);
+                rc = network_prefix(message[2], message[3], 0,
+                                    message + 4, NULL, len - 2, prefix);
+                if(rc < 0) goto corrupt;
+                rc = network_prefix(message[2], message[4], 0,
+                                    message + 4 + rc, NULL, len - 2,
+                                    src_prefix);
+                if(rc < 0) goto corrupt;
+                if(message[2] == 0) {
+                    ND_PRINT((ndo, "for any"));
+                } else {
+                    ND_PRINT((ndo, "for (%s, ", format_prefix(ndo, prefix, plen)));
+                    ND_PRINT((ndo, "%s)", format_prefix(ndo, src_prefix, src_plen)));
+                }
+            }
+        }
+            break;
+
+        case MESSAGE_MH_REQUEST_SRC_SPECIFIC : {
+            if(!ndo->ndo_vflag)
+                ND_PRINT((ndo, " ss-mh-request"));
+            else {
+                int rc;
+                u_short seqno;
+                u_char prefix[16], src_prefix[16], plen, src_plen;
+                ND_PRINT((ndo, "\n\tSS-MH-Request "));
+                if(len < 14) goto corrupt;
+                seqno = EXTRACT_16BITS(message + 4);
+                rc = network_prefix(message[2], message[3], 0,
+                                    message + 16, NULL, len - 14, prefix);
+                if(rc < 0) goto corrupt;
+                rc = network_prefix(message[2], message[7], 0,
+                                    message + 16 + rc, NULL, len - 14,
+                                    src_prefix);
+                if(rc < 0) goto corrupt;
+                plen = message[3] + (message[2] == 1 ? 96 : 0);
+                src_plen = message[7] + (message[2] == 1 ? 96 : 0);
+                ND_PRINT((ndo, "(%u hops) for (%s, ",
+                          message[6], format_prefix(ndo, prefix, plen)));
+                ND_PRINT((ndo, "%s) seqno %u id %s",
+                          format_prefix(ndo, src_prefix, src_plen),
+                          seqno, format_id(message + 8)));
+            }
+        }
+            break;
+
         default:
             if (!ndo->ndo_vflag)
                 ND_PRINT((ndo, " unknown"));
-- 
1.7.12.4 (Apple Git-37)

