add support for the olsr protocol as per rfc3626 plus the LQ extensions from olsr.org
authorhannes <hannes>
Wed, 28 Mar 2007 07:45:45 +0000 (07:45 +0000)
committerhannes <hannes>
Wed, 28 Mar 2007 07:45:45 +0000 (07:45 +0000)
FILES
Makefile.in
interface.h
print-olsr.c [new file with mode: 0644]
print-udp.c
udp.h
win32/prj/GNUmakefile
win32/prj/WinDump.dsp

diff --git a/FILES b/FILES
index 8d0f527e015d92449a6e15762390d110280ca23e..54fc774d7e351e61f95c5bb6fe2885d22c0cd075 100644 (file)
--- a/FILES
+++ b/FILES
@@ -173,6 +173,7 @@ print-netbios.c
 print-nfs.c
 print-ntp.c
 print-null.c
+print-olsr.c
 print-ospf.c
 print-ospf6.c
 print-pflog.c
index 0852abc6152212f6fce9dbe4828219730599ab4d..929d7f1f15f280ae4c9cb5e85b03a900b4dfa26d 100644 (file)
@@ -17,7 +17,7 @@
 #  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 #  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 #
-# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.293.2.4 2007-02-26 13:31:33 hannes Exp $ (LBL)
+# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.293.2.5 2007-03-28 07:45:45 hannes Exp $ (LBL)
 
 #
 # Various configurable paths (remember to edit Makefile.in, not Makefile)
@@ -80,7 +80,7 @@ CSRC =        addrtoname.c af.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c \
        print-l2tp.c print-lane.c print-ldp.c print-llc.c \
         print-lmp.c print-lspping.c \
        print-lwres.c print-mobile.c print-mpls.c print-msdp.c \
-       print-nfs.c print-ntp.c print-null.c print-ospf.c \
+       print-nfs.c print-ntp.c print-null.c print-olsr.c print-ospf.c \
        print-pflog.c print-pgm.c print-pim.c print-ppp.c print-pppoe.c \
        print-pptp.c print-radius.c print-raw.c print-rip.c \
        print-rsvp.c print-rx.c print-sctp.c print-sip.c print-sl.c print-sll.c \
index adb53cfe76bf13e4bb615a59f8edbeebcbdac326..d65cb4bf695a9898edea09081638cdfaf7ebe046 100644 (file)
@@ -18,7 +18,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.244.2.20 2006-02-08 01:40:09 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.244.2.21 2007-03-28 07:45:46 hannes Exp $ (LBL)
  */
 
 #ifndef tcpdump_interface_h
@@ -108,6 +108,10 @@ extern char *strsep(char **, const char *);
 #endif
 #endif
 
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
 extern char *program_name;     /* used to generate self-identifying messages */
 
 extern int32_t thiszone;       /* seconds offset from gmt to local time */
@@ -227,6 +231,7 @@ extern void ns_print(const u_char *, u_int, int);
 extern void ntp_print(const u_char *, u_int);
 extern u_int null_if_print(const struct pcap_pkthdr *, const u_char *);
 extern void ospf_print(const u_char *, u_int, const u_char *);
+extern void olsr_print (const u_char *, u_int);
 extern void pimv1_print(const u_char *, u_int);
 extern void cisco_autorp_print(const u_char *, u_int);
 extern void rsvp_print(const u_char *, u_int);
diff --git a/print-olsr.c b/print-olsr.c
new file mode 100644 (file)
index 0000000..174a51e
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 1998-2007 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * Optimized Link State Protocl (OLSR) as per rfc3626
+ *
+ * Original code by Hannes Gredler <hannes@juniper.net>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"           
+#include "ip.h"
+
+/*
+ * RFC 3626 common header
+ *
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |         Packet Length         |    Packet Sequence Number     |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  Message Type |     Vtime     |         Message Size          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                      Originator Address                       |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  Time To Live |   Hop Count   |    Message Sequence Number    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                                                               |
+ * :                            MESSAGE                            :
+ * |                                                               |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  Message Type |     Vtime     |         Message Size          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                      Originator Address                       |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  Time To Live |   Hop Count   |    Message Sequence Number    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                                                               |
+ * :                            MESSAGE                            :
+ * |                                                               |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * :                                                               :
+ */
+
+struct olsr_common {
+    u_int8_t packet_len[2];
+    u_int8_t packet_seq[2];
+};
+
+#define OLSR_HELLO_MSG         1 /* rfc3626 */
+#define OLSR_TC_MSG            2 /* rfc3626 */
+#define OLSR_MID_MSG           3 /* rfc3626 */
+#define OLSR_HNA_MSG           4 /* rfc3626 */
+#define OLSR_POWERINFO_MSG   128
+#define OLSR_NAMESERVICE_MSG 130
+#define OLSR_HELLO_LQ_MSG    201 /* LQ extensions olsr.org */
+#define OLSR_TC_LQ_MSG       202 /* LQ extensions olsr.org */
+
+static struct tok olsr_msg_values[] = {
+    { OLSR_HELLO_MSG, "Hello" },
+    { OLSR_TC_MSG, "TC" },
+    { OLSR_MID_MSG, "MID" },
+    { OLSR_HNA_MSG, "HNA" },
+    { OLSR_POWERINFO_MSG, "Powerinfo" },
+    { OLSR_NAMESERVICE_MSG, "Nameservice" },
+    { OLSR_HELLO_LQ_MSG, "Hello-LQ" },
+    { OLSR_TC_LQ_MSG, "TC-LQ" },
+    { 0, NULL}
+};
+
+struct olsr_msg {
+    u_int8_t msg_type;
+    u_int8_t vtime;
+    u_int8_t msg_len[2];
+    u_int8_t originator[4];
+    u_int8_t ttl;
+    u_int8_t hopcount;
+    u_int8_t msg_seq[2];
+};
+
+struct olsr_hello {
+    u_int8_t res[2];
+    u_int8_t htime;
+    u_int8_t will;
+};
+
+struct olsr_hello_link {
+    u_int8_t link_code;
+    u_int8_t res;
+    u_int8_t len[2];
+};
+
+struct olsr_tc {
+    u_int8_t ans_seq[2];
+    u_int8_t res[2];
+};
+
+struct olsr_hna {
+    u_int8_t network[4];
+    u_int8_t mask[4];
+};
+
+
+#define OLSR_EXTRACT_LINK_TYPE(link_code) (link_code & 0x3)
+#define OLSR_EXTRACT_NEIGHBOR_TYPE(link_code) (link_code >> 2)
+
+static struct tok olsr_link_type_values[] = {
+    { 0, "Unspecified" },
+    { 1, "Asymmetric" },
+    { 2, "Symmetric" },
+    { 3, "Lost" },
+    { 0, NULL}
+};
+
+static struct tok olsr_neighbor_type_values[] = {
+    { 0, "Not-Neighbor" },
+    { 1, "Symmetric" },
+    { 2, "Symmetric-MPR" },
+    { 0, NULL}
+};
+
+struct olsr_lq_neighbor {
+    u_int8_t neighbor[4];
+    u_int8_t link_quality;
+    u_int8_t neighbor_link_quality;
+    u_int8_t res[2];
+};
+
+/*
+ * macro to convert the 8-bit mantissa/exponent to a double float
+ * taken from olsr.org.
+ */
+#define VTIME_SCALE_FACTOR    0.0625
+#define ME_TO_DOUBLE(me) \
+  (double)(VTIME_SCALE_FACTOR*(1+(double)(me>>4)/16)*(double)(1<<(me&0x0F)))
+
+/*
+ * print a neighbor list with LQ extensions.
+ */
+static void
+olsr_print_lq_neighbor (const u_char *msg_data, u_int hello_len)
+{
+    struct olsr_lq_neighbor *lq_neighbor;
+
+    while (hello_len >= sizeof(struct olsr_lq_neighbor)) {
+
+        lq_neighbor = (struct olsr_lq_neighbor *)msg_data;
+
+        printf("\n\t      neighbor %s, link-quality %.2lf%%"
+               ", neighbor-link-quality %.2lf%%",
+               ipaddr_string(lq_neighbor->neighbor),
+               ((double)lq_neighbor->link_quality/2.55),
+               ((double)lq_neighbor->neighbor_link_quality/2.55));
+
+        msg_data += sizeof(struct olsr_lq_neighbor);
+        hello_len -= sizeof(struct olsr_lq_neighbor);
+    }
+}
+
+/*
+ * print a neighbor list.
+ */
+static void
+olsr_print_neighbor (const u_char *msg_data, u_int hello_len)
+{
+    int neighbor;
+
+    printf("\n\t      neighbor\n\t\t");
+    neighbor = 1;
+
+    while (hello_len >= sizeof(struct in_addr)) {
+
+        /* print 4 neighbors per line */
+
+        printf("%s%s", ipaddr_string(msg_data),
+               neighbor % 4 == 0 ? "\n\t\t" : " ");
+
+        msg_data += sizeof(struct in_addr);
+        hello_len -= sizeof(struct in_addr);
+    }
+}
+
+
+void
+olsr_print (const u_char *pptr, u_int length)
+{
+    union {
+        const struct olsr_common *common;
+        const struct olsr_msg *msg;
+        const struct olsr_hello *hello;
+        const struct olsr_hello_link *hello_link;
+        const struct olsr_lq_neighbor *lq_neighbor;
+        const struct olsr_tc *tc;
+        const struct olsr_hna *hna;
+    } ptr;
+
+    u_int msg_type, msg_len, msg_tlen, hello_len, prefix;
+    u_int8_t link_type, neighbor_type;
+    const u_char *tptr, *msg_data;
+
+    tptr = pptr; 
+
+    if (length < sizeof(struct olsr_common)) {
+        goto trunc;
+    }
+
+    if (!TTEST2(*tptr, sizeof(struct olsr_common))) {
+       goto trunc;
+    }
+
+    ptr.common = (struct olsr_common *)tptr;
+    length = MIN(length, EXTRACT_16BITS(ptr.common->packet_len));
+
+    printf("OLSR, seq 0x%04x, length %u",
+           EXTRACT_16BITS(ptr.common->packet_seq),
+           length);
+
+    tptr += sizeof(struct olsr_common);
+
+    /*
+     * In non-verbose mode, just print version.
+     */
+    if (vflag < 1) {
+       return;
+    }
+
+    while (tptr < (pptr+length)) {
+
+        if (!TTEST2(*tptr, sizeof(struct olsr_msg)))   
+            goto trunc;
+
+        ptr.msg = (struct olsr_msg *)tptr;
+
+        msg_type = ptr.msg->msg_type;
+        msg_len = EXTRACT_16BITS(ptr.msg->msg_len);
+
+        /* infinite loop check */
+        if (msg_type == 0 || msg_len == 0) {
+            return;
+        }
+
+        printf("\n\t%s Message (%u), originator %s, ttl %u, hop %u"
+               "\n\t  vtime %.3lfs, msg-seq 0x%04x, length %u",
+               tok2str(olsr_msg_values, "Unknown", msg_type),
+               msg_type, ipaddr_string(ptr.msg->originator),
+               ptr.msg->ttl,
+               ptr.msg->hopcount,
+               ME_TO_DOUBLE(ptr.msg->vtime),
+               EXTRACT_16BITS(ptr.msg->msg_seq),
+               msg_len);
+
+        msg_tlen = msg_len - sizeof(struct olsr_msg);
+        msg_data = tptr + sizeof(struct olsr_msg);
+
+        switch (msg_type) {
+        case OLSR_HELLO_MSG:
+        case OLSR_HELLO_LQ_MSG:
+            if (!TTEST2(*msg_data, sizeof(struct olsr_hello))) 
+                goto trunc;
+
+            ptr.hello = (struct olsr_hello *)msg_data;
+            printf("\n\t  hello-time %.3lfs, MPR willingness %u",
+                   ME_TO_DOUBLE(ptr.hello->htime), ptr.hello->will);
+            msg_data += sizeof(struct olsr_hello);
+            msg_tlen -= sizeof(struct olsr_hello);
+
+            while (msg_tlen >= sizeof(struct olsr_hello_link)) {
+
+                /*
+                 * link-type.
+                 */
+                if (!TTEST2(*msg_data, sizeof(struct olsr_hello_link)))        
+                    goto trunc;
+
+                ptr.hello_link = (struct olsr_hello_link *)msg_data;
+
+                hello_len = EXTRACT_16BITS(ptr.hello_link->len);
+                link_type = OLSR_EXTRACT_LINK_TYPE(ptr.hello_link->link_code);
+                neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(ptr.hello_link->link_code);
+
+                printf("\n\t    link-type %s, neighbor-type %s, len %u",
+                       tok2str(olsr_link_type_values, "Unknown", link_type),
+                       tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type),
+                       hello_len);
+
+                msg_data += sizeof(struct olsr_hello_link);
+                msg_tlen -= sizeof(struct olsr_hello_link);
+                hello_len -= sizeof(struct olsr_hello_link);
+
+                if (msg_type == OLSR_HELLO_MSG) {
+                    olsr_print_neighbor(msg_data, hello_len);
+                } else {
+                    olsr_print_lq_neighbor(msg_data, hello_len);
+                }
+
+                msg_data += hello_len;
+                msg_tlen -= hello_len;
+            }
+            break;
+
+        case OLSR_TC_MSG:
+        case OLSR_TC_LQ_MSG:
+            if (!TTEST2(*msg_data, sizeof(struct olsr_tc)))    
+                goto trunc;
+
+            ptr.tc = (struct olsr_tc *)msg_data;
+            printf("\n\t    advertised neighbor seq 0x%04x",
+                   EXTRACT_16BITS(ptr.tc->ans_seq));
+            msg_data += sizeof(struct olsr_tc);
+            msg_tlen -= sizeof(struct olsr_tc);
+
+            if (msg_type == OLSR_TC_MSG) {
+                olsr_print_neighbor(msg_data, msg_tlen);
+            } else {
+                olsr_print_lq_neighbor(msg_data, msg_tlen);
+            }
+            break;
+
+        case OLSR_MID_MSG:
+            if (!TTEST2(*msg_data, sizeof(struct in_addr)))    
+                goto trunc;
+
+            while (msg_tlen >= sizeof(struct in_addr)) {
+                printf("\n\t  interface address %s", ipaddr_string(msg_data));
+                msg_data += sizeof(struct in_addr);
+                msg_tlen -= sizeof(struct in_addr);
+            }
+            break;
+
+        case OLSR_HNA_MSG:
+            prefix = 1;
+            printf("\n\t  advertised networks\n\t    ");
+            while (msg_tlen >= sizeof(struct olsr_hna)) {
+                if (!TTEST2(*msg_data, sizeof(struct olsr_hna)))       
+                    goto trunc;
+
+                ptr.hna = (struct olsr_hna *)msg_data;
+
+                /* print 4 prefixes per line */
+
+                printf("%s/%u%s",
+                       ipaddr_string(ptr.hna->network),
+                       mask2plen(EXTRACT_32BITS(ptr.hna->mask)),                       
+                       prefix % 4 == 0 ? "\n\t    " : " ");
+
+                msg_data += sizeof(struct olsr_hna);
+                msg_tlen -= sizeof(struct olsr_hna);
+                prefix ++;
+            }
+            break;
+
+            /*
+             * FIXME those are the defined messages that lack a decoder
+             * you are welcome to contribute code ;-)
+             */
+
+        case OLSR_POWERINFO_MSG:
+        case OLSR_NAMESERVICE_MSG:
+        default:
+           print_unknown_data(msg_data, "\n\t    ", msg_tlen);
+            break;
+        }      
+        tptr += msg_len;
+    }
+
+    return;
+
+ trunc:
+    printf("[|olsr]");
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 4
+ * End:
+ */
index 2109a72cffdf04d5154731bbb2d9d8b2ef2a2eaa..ec87f47f764fde4551df9cc965e2e33d67138a47 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.138 2005-04-07 00:28:17 mcr Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.138.2.1 2007-03-28 07:45:46 hannes Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -674,6 +674,8 @@ udp_print(register const u_char *bp, u_int length,
                        lwres_print((const u_char *)(up + 1), length);
                 else if (ISPORT(LDP_PORT))
                        ldp_print((const u_char *)(up + 1), length);
+                else if (ISPORT(OLSR_PORT))
+                       olsr_print((const u_char *)(up + 1), length);
                 else if (ISPORT(MPLS_LSP_PING_PORT))
                        lspping_print((const u_char *)(up + 1), length);
                else if (dport == BFD_CONTROL_PORT ||
diff --git a/udp.h b/udp.h
index 6de21246466eb4466cad57f3331a276dcfb0b6ad..bb1988f383ec690debbf7c966f795570a13369e5 100644 (file)
--- a/udp.h
+++ b/udp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/udp.h,v 1.8.2.1 2006-02-09 23:34:07 hannes Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/udp.h,v 1.8.2.2 2007-03-28 07:45:46 hannes Exp $ (LBL) */
 /*
  * Copyright (c) 1982, 1986, 1993
  *     The Regents of the University of California.  All rights reserved.
@@ -57,6 +57,7 @@ struct udphdr {
 #define RIP_PORT 520           /*XXX*/
 #define LDP_PORT 646
 #define AODV_PORT 654          /*XXX*/
+#define OLSR_PORT 698           /* rfc3626 */
 #define KERBEROS_SEC_PORT 750  /*XXX*/
 #define L2TP_PORT 1701         /*XXX*/
 #define SIP_PORT 5060
index 5006407669e8def1e898438360453d0184f0adf4..ff344e775e8f99f4f30fcc0c707477993f8ff4fc 100644 (file)
@@ -97,6 +97,7 @@ OBJS = \
        ../../print-nfs.o \
        ../../print-ntp.o \
        ../../print-null.o \
+       ../../print-olsr.o \
        ../../print-ospf.o \
        ../../print-ospf6.o \
        ../../print-pflog.o \
index 357054fbe45a74a1da54499d51273af4b976e02a..6e6f4871f63f82cc77a2429bcf2bfba950f0bf5f 100644 (file)
@@ -405,6 +405,10 @@ SOURCE="..\..\print-null.c"
 # End Source File
 # Begin Source File
 
+SOURCE="..\..\print-olsr.c"
+# End Source File
+# Begin Source File
+
 SOURCE="..\..\print-ospf.c"
 # End Source File
 # Begin Source File