]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-mpls.c
The patches attached to this email are required to get a fully working tcpdump
[tcpdump] / print-mpls.c
index c579dd79203460aa3ab141dc7389614e4c3aa768..c6b0814ffefcac2f5c848584849cc9f70748b161 100644 (file)
  */
 
 #ifndef lint
-static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-mpls.c,v 1.2 2001-06-26 06:24:57 guy Exp $ (LBL)";
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/tcpdump/print-mpls.c,v 1.14 2005-07-05 09:38:19 hannes Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-
-#include <netinet/in.h>
+#include <tcpdump-stdinc.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 
 #include "addrtoname.h"
 #include "interface.h"
 #include "extract.h"                   /* must come after interface.h */
-
-#define LABEL_MASK     0xfffff000
-#define LABEL_SHIFT    12
-#define        EXP_MASK        0x00000e00
-#define EXP_SHIFT      9
-#define        STACK_MASK      0x00000100
-#define STACK_SHIFT    8
-#define TTL_MASK       0x000000ff
-#define TTL_SHIFT      0
-
-#define MPLS_LABEL(x)  (((x) & LABEL_MASK) >> LABEL_SHIFT)
-#define MPLS_EXP(x)    (((x) & EXP_MASK) >> EXP_SHIFT)
-#define MPLS_STACK(x)  (((x) & STACK_MASK) >> STACK_SHIFT)
-#define MPLS_TTL(x)    (((x) & TTL_MASK) >> TTL_SHIFT)
+#include "mpls.h"
 
 static const char *mpls_labelname[] = {
 /*0*/  "IPv4 explicit NULL", "router alert", "IPv6 explicit NULL",
@@ -79,45 +61,129 @@ void
 mpls_print(const u_char *bp, u_int length)
 {
        const u_char *p;
-       u_int32_t v;
+       u_int32_t label_entry;
+        u_int16_t label_stack_depth = 0;
 
        p = bp;
        printf("MPLS");
-       TCHECK2(*p, sizeof(v));
-       memcpy(&v, p, sizeof(v));
-       v = (u_int32_t)ntohl(v);
-       printf(" (");   /*)*/
-       printf("label 0x%x", MPLS_LABEL(v));
-       if (vflag &&
-           MPLS_LABEL(v) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0]))
-               printf("(%s)", mpls_labelname[MPLS_LABEL(v)]);
-       if (MPLS_EXP(v))
-               printf(" exp 0x%x", MPLS_EXP(v));
-       if (MPLS_STACK(v))
-               printf("[S]");
-       printf(" TTL %u", MPLS_TTL(v));
-       /*(*/
-       printf(")");
+       do {
+               TCHECK2(*p, sizeof(label_entry));
+               label_entry = EXTRACT_32BITS(p);
+               printf("%s(label %u",
+                       label_stack_depth ? "\n\t" : " ",
+                       MPLS_LABEL(label_entry));
+                label_stack_depth++;
+               if (vflag &&
+                   MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0]))
+                       printf(" (%s)", mpls_labelname[MPLS_LABEL(label_entry)]);
+               printf(", exp %u", MPLS_EXP(label_entry));
+               if (MPLS_STACK(label_entry))
+                       printf(", [S]");
+               printf(", ttl %u)", MPLS_TTL(label_entry));
 
-       p += sizeof(v);
+               p += sizeof(label_entry);
+       } while (!MPLS_STACK(label_entry));
 
-       switch (MPLS_LABEL(v)) {
+       switch (MPLS_LABEL(label_entry)) {
        case 0: /* IPv4 explicit NULL label */
-               ip_print(p, length - (p - bp));
+        case 3:        /* IPv4 implicit NULL label */
+                if (vflag>0) {
+                        printf("\n\t");
+                        ip_print(gndo, p, length - (p - bp));
+                }
+                else printf(", IP, length: %u",length);
                break;
 #ifdef INET6
        case 2: /* IPv6 explicit NULL label */
-               ip6_print(p, length - (p - bp));
+                if (vflag>0) {
+                        printf("\n\t");
+                        ip6_print(p, length - (p - bp));
+                }
+                else printf(", IPv6, length: %u",length);
                break;
 #endif
        default:
                /*
-                * Since there's no indication of protocol in MPLS label
-                * encoding, we can print nothing further.
+                * Generally there's no indication of protocol in MPLS label
+                * encoding, however draft-hsmit-isis-aal5mux-00.txt describes
+                 * a technique that looks at the first payload byte if the BOS (bottom of stack)
+                 * bit is set and tries to determine the network layer protocol
+                 * 0x45-0x4f is IPv4
+                 * 0x60-0x6f is IPv6
+                 * 0x81-0x83 is OSI (CLNP,ES-IS,IS-IS)
+                 * this technique is sometimes known as NULL encapsulation
+                 * and decoding is particularly useful for control-plane traffic [BGP]
+                 * which cisco by default sends MPLS encapsulated
                 */
-               return;
+
+                if (MPLS_STACK(label_entry)) { /* only do this if the stack bit is set */
+                    switch(*p) {
+                    case 0x45:
+                    case 0x46:
+                    case 0x47:
+                    case 0x48:
+                    case 0x49:
+                    case 0x4a:
+                    case 0x4b:
+                    case 0x4c:
+                    case 0x4d:
+                    case 0x4e:
+                    case 0x4f:
+                       if (vflag>0) {
+                            printf("\n\t");
+                            ip_print(gndo, p, length - (p - bp));
+                           }
+                        else printf(", IP, length: %u",length);
+                        break;
+#ifdef INET6
+                    case 0x60:
+                    case 0x61:
+                    case 0x62:
+                    case 0x63:
+                    case 0x64:
+                    case 0x65:
+                    case 0x66:
+                    case 0x67:
+                    case 0x68:
+                    case 0x69:
+                    case 0x6a:
+                    case 0x6b:
+                    case 0x6c:
+                    case 0x6d:
+                    case 0x6e:
+                    case 0x6f:
+                       if (vflag>0) {
+                            printf("\n\t");
+                            ip6_print(p, length - (p - bp));
+                            }
+                       else printf(", IPv6, length: %u",length);
+                        break;
+#endif
+                    case 0x81:
+                    case 0x82:
+                    case 0x83:
+                       if (vflag>0) {
+                            printf("\n\t");
+                            isoclns_print(p, length - (p - bp), length - (p - bp));
+                           }
+                       else printf(", OSI, length: %u",length);
+                        break;
+                    default:
+                        /* ok bail out - we did not figure out what it is*/
+                        break;
+                    }
+                }
+                return;
        }
 
 trunc:
        printf("[|MPLS]");
 }
+
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */