tcpdump mailing list archives

[PATCH] Add printer for the Babel routing protocol (RFC 6126).


From: Juliusz Chroboczek <jch () pps jussieu fr>
Date: Sat, 9 Apr 2011 00:13:52 +0200

---
 CREDITS       |    2 +
 Makefile.in   |    6 +-
 interface.h   |    1 +
 print-babel.c |  422 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 print-udp.c   |    5 +-
 udp.h         |    1 +
 6 files changed, 432 insertions(+), 5 deletions(-)
 create mode 100644 print-babel.c

diff --git a/CREDITS b/CREDITS
index 14850b7..eececc0 100644
--- a/CREDITS
+++ b/CREDITS
@@ -69,6 +69,7 @@ Additional people who have contributed patches:
     Gert Doering                  <gert at greenie dot muc dot de>
     Greg Minshall                 <minshall at acm dot org>
     Greg Stark                    <gsstark at mit dot edu>
+    Grégoire Henry                <henry () pps jussieu fr>
     Gilbert Ramirez Jr.           <gram at xiexie dot org>
     Gisle Vanem                   <gvanem at broadpark dot no>
     Hannes Viertel                <hviertel at juniper dot net>
@@ -93,6 +94,7 @@ Additional people who have contributed patches:
     Joerg Mayer                   <jmayer () loplof de>
     Jørgen Thomsen                <jth at jth dot net> 
     Julian Cowley                 <julian at lava dot net>
+    Juliusz Chroboczek            <jch () pps jussieu fr>
     Kaarthik Sivakumar            <kaarthik at torrentnet dot com>
     Karl Norby                    <karl-norby at sourceforge dot net>
     Kazushi Sugyo                 <sugyo at pb dot jp dot nec dot com>
diff --git a/Makefile.in b/Makefile.in
index 1b73a27..530894b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -72,9 +72,9 @@ CSRC =        addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c
         nlpid.c l2vpn.c machdep.c parsenfsfh.c \
        print-802_11.c print-802_15_4.c print-ap1394.c print-ah.c \
        print-arcnet.c print-aodv.c print-arp.c print-ascii.c print-atalk.c \
-       print-atm.c print-beep.c print-bfd.c print-bgp.c print-bootp.c \
-       print-bt.c print-cdp.c print-cfm.c print-chdlc.c print-cip.c \
-       print-cnfp.c print-dccp.c print-decnet.c \
+       print-atm.c print-babel.c print-beep.c print-bfd.c print-bgp.c \
+       print-bootp.c print-bt.c print-cdp.c print-cfm.c print-chdlc.c \
+       print-cip.c print-cnfp.c print-dccp.c print-decnet.c \
        print-domain.c print-dtp.c print-dvmrp.c print-enc.c print-egp.c \
        print-eap.c print-eigrp.c\
        print-esp.c print-ether.c print-fddi.c print-fr.c \
diff --git a/interface.h b/interface.h
index 09da6cb..aa3954f 100644
--- a/interface.h
+++ b/interface.h
@@ -324,6 +324,7 @@ extern void ripng_print(const u_char *, unsigned int);
 extern int rt6_print(const u_char *, const u_char *);
 extern void ospf6_print(const u_char *, u_int);
 extern void dhcp6_print(const u_char *, u_int);
+extern void babel_print(const u_char *, u_int);
 extern int mask62plen(const u_char *);
 #endif /*INET6*/
 extern u_short in_cksum(const u_short *, register u_int, int);
diff --git a/print-babel.c b/print-babel.c
new file mode 100644
index 0000000..b3570b0
--- /dev/null
+++ b/print-babel.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2007-2011 Grégoire Henry, Juliusz Chroboczek
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "addrtoname.h"
+#include "interface.h"
+
+static void babel_print_v2(const u_char *cp, u_int length);
+
+void
+babel_print(const u_char *cp, u_int length) {
+    printf("babel");
+
+    TCHECK2(*cp, 4);
+
+    if(cp[0] != 42) {
+        printf(" malformed header");
+        return;
+    } else {
+        printf(" %d", cp[1]);
+    }
+
+    switch(cp[1]) {
+    case 2:
+        babel_print_v2(cp,length);
+        break;
+    default:
+        printf(" unknown version");
+        break;
+    }
+
+    return;
+
+ trunc:
+    printf(" [|babel]");
+    return;
+}
+
+#if defined __GNUC__
+struct __us { unsigned short x __attribute__((packed)); };
+#define DO_NTOHS(_d, _s) \
+    do { _d = ntohs(((const struct __us*)(_s))->x); } while(0)
+#define DO_HTONS(_d, _s) \
+    do { ((struct __us*)(_d))->x = htons(_s); } while(0)
+#else
+#define DO_NTOHS(_d, _s) \
+    do { short _dd; \
+         memcpy(&(_dd), (_s), 2); \
+         _d = ntohs(_dd); } while(0)
+#define DO_HTONS(_d, _s) \
+    do { unsigned short _dd; \
+         _dd = htons(_s); \
+         memcpy((_d), &(_dd), 2); } while(0)
+#endif
+
+#define MESSAGE_PAD1 0
+#define MESSAGE_PADN 1
+#define MESSAGE_ACK_REQ 2
+#define MESSAGE_ACK 3
+#define MESSAGE_HELLO 4
+#define MESSAGE_IHU 5
+#define MESSAGE_ROUTER_ID 6
+#define MESSAGE_NH 7
+#define MESSAGE_UPDATE 8
+#define MESSAGE_REQUEST 9
+#define MESSAGE_MH_REQUEST 10
+
+static const char *
+format_id(const u_char *id)
+{
+    static char buf[25];
+    snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+             id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]);
+    buf[24] = '\0';
+    return buf;
+}
+
+static const unsigned char v4prefix[16] =
+    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
+
+static const char *
+format_prefix(const u_char *prefix, unsigned char plen)
+{
+    static char buf[50];
+    if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0)
+        snprintf(buf, 50, "%s/%u", ipaddr_string(prefix + 12), plen - 96);
+    else
+        snprintf(buf, 50, "%s/%u", ip6addr_string(prefix), plen);
+    buf[49] = '\0';
+    return buf;
+}
+
+static const char *
+format_address(const u_char *prefix)
+{
+    if(memcmp(prefix, v4prefix, 12) == 0)
+        return ipaddr_string(prefix + 12);
+    else
+        return ip6addr_string(prefix);
+}
+
+static int
+network_prefix(int ae, int plen, unsigned int omitted,
+               const unsigned char *p, const unsigned char *dp,
+               unsigned int len, unsigned char *p_r)
+{
+    unsigned pb;
+    unsigned char prefix[16];
+
+    if(plen >= 0)
+        pb = (plen + 7) / 8;
+    else if(ae == 1)
+        pb = 4;
+    else
+        pb = 16;
+
+    if(pb > 16)
+        return -1;
+
+    memset(prefix, 0, 16);
+
+    switch(ae) {
+    case 0: break;
+    case 1:
+        if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
+            return -1;
+        memcpy(prefix, v4prefix, 12);
+        if(omitted) {
+            if (dp == NULL) return -1;
+            memcpy(prefix, dp, 12 + omitted);
+        }
+        if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb);
+        break;
+    case 2:
+        if(omitted > 4 || (pb > omitted && len < pb - omitted))
+            return -1;
+        if(omitted) {
+            if (dp == NULL) return -1;
+            memcpy(prefix, dp, omitted);
+        }
+        if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted);
+        break;
+    case 3:
+        if(pb > 8 && len < pb - 8) return -1;
+        prefix[0] = 0xfe;
+        prefix[1] = 0x80;
+        if(pb > 8) memcpy(prefix + 8, p, pb - 8);
+        break;
+    default:
+        return -1;
+    }
+
+    memcpy(p_r, prefix, 16);
+    return 1;
+}
+
+static int
+network_address(int ae, const unsigned char *a, unsigned int len,
+                unsigned char *a_r)
+{
+    return network_prefix(ae, -1, 0, a, NULL, len, a_r);
+}
+
+static void
+babel_print_v2(const u_char *cp, u_int length) {
+    int i;
+    u_short bodylen;
+    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};
+
+    DO_NTOHS(bodylen, cp + 2);
+    printf(" (%d)", bodylen);
+
+    i = 0;
+    while(i < bodylen) {
+        const u_char *message;
+        u_char type, len;
+
+        TCHECK2(*cp, 4 + i);
+
+        message = cp + 4 + i;
+        type = message[0];
+        len = message[1];
+
+        TCHECK2(*cp, 4 + i + 2 + len);
+
+        switch(type) {
+        case MESSAGE_PAD1: {
+            if(!vflag)
+                printf(" pad1");
+            else
+                printf("\n\tPad 1");
+        }
+            break;
+
+        case MESSAGE_PADN: {
+            if(!vflag)
+                printf(" padN");
+            else
+                printf("\n\tPad %d", len + 2);
+        }
+            break;
+
+        case MESSAGE_ACK_REQ: {
+            u_short nonce, interval;
+            if(!vflag)
+                printf(" ack-req");
+            else {
+                printf("\n\tAcknowledgment Request ");
+                if(len < 6) goto corrupt;
+                DO_NTOHS(nonce, message + 4);
+                DO_NTOHS(interval, message + 6);
+                printf("%04x %d", nonce, interval);
+            }
+        }
+            break;
+
+        case MESSAGE_ACK: {
+            u_short nonce;
+            if(!vflag)
+                printf(" ack");
+            else {
+                printf("\n\tAcknowledgment ");
+                if(len < 2) goto corrupt;
+                DO_NTOHS(nonce, message + 2);
+                printf("%04x", nonce);
+            }
+        }
+            break;
+
+        case MESSAGE_HELLO:  {
+            u_short seqno, interval;
+            if(!vflag)
+                printf(" hello");
+            else {
+                printf("\n\tHello ");
+                if(len < 6) goto corrupt;
+                DO_NTOHS(seqno, message + 4);
+                DO_NTOHS(interval, message + 6);
+                printf("seqno %u interval %u", seqno, interval);
+            }
+        }
+            break;
+
+        case MESSAGE_IHU: {
+            unsigned short txcost, interval;
+            if(!vflag)
+                printf(" ihu");
+            else {
+                u_char address[16];
+                int rc;
+                printf("\n\tIHU ");
+                if(len < 6) goto corrupt;
+                DO_NTOHS(txcost, message + 4);
+                DO_NTOHS(interval, message + 6);
+                rc = network_address(message[2], message + 8, len - 6, address);
+                if(rc < 0) { printf("[|babel]"); break; }
+                printf("%s txcost %u interval %d",
+                       format_address(address), txcost, interval);
+            }
+        }
+            break;
+
+        case MESSAGE_ROUTER_ID: {
+            if(!vflag)
+                printf(" router-id");
+            else {
+                printf("\n\tRouter Id");
+                if(len < 10) goto corrupt;
+                printf(" %s", format_id(message + 4));
+            }
+        }
+            break;
+
+        case MESSAGE_NH: {
+            if(!vflag)
+                printf(" nh");
+            else {
+                int rc;
+                u_char nh[16];
+                printf("\n\tNext Hop");
+                if(len < 2) goto corrupt;
+                rc = network_address(message[2], message + 4, len - 2, nh);
+                if(rc < 0) goto corrupt;
+                printf(" %s", format_address(nh));
+            }
+        }
+            break;
+
+        case MESSAGE_UPDATE: {
+            if(!vflag) {
+                printf(" update");
+                if(len < 1)
+                    printf("/truncated");
+                else
+                    printf("%s%s%s",
+                           (message[3] & 0x80) ? "/prefix": "",
+                           (message[3] & 0x40) ? "/id" : "",
+                           (message[3] & 0x3f) ? "/unknown" : "");
+            } else {
+                u_short interval, seqno, metric;
+                u_char plen;
+                int rc;
+                u_char prefix[16];
+                printf("\n\tUpdate");
+                if(len < 10) goto corrupt;
+                plen = message[4] + (message[2] == 1 ? 96 : 0);
+                rc = network_prefix(message[2], message[4], message[5],
+                                    message + 12,
+                                    message[2] == 1 ? v4_prefix : v6_prefix,
+                                    len - 10, prefix);
+                if(rc < 0) goto corrupt;
+                DO_NTOHS(interval, message + 6);
+                DO_NTOHS(seqno, message + 8);
+                DO_NTOHS(metric, message + 10);
+                printf("%s%s%s %s metric %u seqno %u interval %u",
+                       (message[3] & 0x80) ? "/prefix": "",
+                       (message[3] & 0x40) ? "/id" : "",
+                       (message[3] & 0x3f) ? "/unknown" : "",
+                       format_prefix(prefix, plen),
+                       metric, seqno, interval);
+                if(message[3] & 0x80) {
+                    if(message[2] == 1)
+                        memcpy(v4_prefix, prefix, 16);
+                    else
+                        memcpy(v6_prefix, prefix, 16);
+                }
+            }
+        }
+            break;
+
+        case MESSAGE_REQUEST: {
+            if(!vflag)
+                printf(" request");
+            else {
+                int rc;
+                u_char prefix[16], plen;
+                printf("\n\tRequest ");
+                if(len < 2) goto corrupt;
+                plen = message[3] + (message[2] == 1 ? 96 : 0);
+                rc = network_prefix(message[2], message[3], 0,
+                                    message + 4, NULL, len - 2, prefix);
+                if(rc < 0) goto corrupt;
+                plen = message[3] + (message[2] == 1 ? 96 : 0);
+                printf("for %s",
+                       message[2] == 0 ? "any" : format_prefix(prefix, plen));
+            }
+        }
+            break;
+
+        case MESSAGE_MH_REQUEST : {
+            if(!vflag)
+                printf(" mh-request");
+            else {
+                int rc;
+                u_short seqno;
+                u_char prefix[16], plen;
+                printf("\n\tMH-Request ");
+                if(len < 14) goto corrupt;
+                DO_NTOHS(seqno, message + 4);
+                rc = network_prefix(message[2], message[3], 0,
+                                    message + 16, NULL, len - 14, prefix);
+                if(rc < 0) goto corrupt;
+                plen = message[3] + (message[2] == 1 ? 96 : 0);
+                printf("(%u hops) for %s seqno %u id %s",
+                       message[6], format_prefix(prefix, plen),
+                       seqno, format_id(message + 8));
+            }
+        }
+            break;
+        default:
+            if(!vflag)
+                printf(" unknown");
+            else
+                printf("\n\tUnknown message type %d", type);
+        }
+        i += len + 2;
+    }
+    return;
+
+ trunc:
+    printf(" [|babel]");
+    return;
+
+ corrupt:
+    printf(" (corrupt)");
+    return;
+}
diff --git a/print-udp.c b/print-udp.c
index d71e4d3..278d648 100644
--- a/print-udp.c
+++ b/print-udp.c
@@ -651,9 +651,10 @@ udp_print(register const u_char *bp, u_int length,
 #ifdef INET6
                else if (ISPORT(RIPNG_PORT))
                        ripng_print((const u_char *)(up + 1), length);
-               else if (ISPORT(DHCP6_SERV_PORT) || ISPORT(DHCP6_CLI_PORT)) {
+               else if (ISPORT(DHCP6_SERV_PORT) || ISPORT(DHCP6_CLI_PORT))
                        dhcp6_print((const u_char *)(up + 1), length);
-               }
+               else if (ISPORT(BABEL_PORT))
+                       babel_print((const u_char *)(up + 1), length);
 #endif /*INET6*/
                /*
                 * Kludge in test for whiteboard packets.
diff --git a/udp.h b/udp.h
index fb45d68..0dc5227 100644
--- a/udp.h
+++ b/udp.h
@@ -90,4 +90,5 @@ struct udphdr {
 #define RIPNG_PORT 521         /*XXX*/
 #define DHCP6_SERV_PORT 546    /*XXX*/
 #define DHCP6_CLI_PORT 547     /*XXX*/
+#define BABEL_PORT 6697
 #endif
-- 
1.7.4.1

-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.


Current thread: