Teach tcpdump to recognize MPLS pseudowire with control words. Added
authorrzalamena <rzalamena@openbsd.org>
Mon, 11 Jul 2016 00:27:50 +0000 (00:27 +0000)
committerrzalamena <rzalamena@openbsd.org>
Mon, 11 Jul 2016 00:27:50 +0000 (00:27 +0000)
support to print encapsulated ethernet packets as well.

"Looks good" deraadt@

usr.sbin/tcpdump/interface.h
usr.sbin/tcpdump/print-ether.c
usr.sbin/tcpdump/print-mpls.c

index c915133..b7dffce 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: interface.h,v 1.66 2015/11/15 20:35:36 mmcc Exp $     */
+/*     $OpenBSD: interface.h,v 1.67 2016/07/11 00:27:50 rzalamena Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -20,7 +20,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Id: interface.h,v 1.66 2015/11/15 20:35:36 mmcc Exp $ (LBL)
+ * @(#) $Id: interface.h,v 1.67 2016/07/11 00:27:50 rzalamena Exp $ (LBL)
  */
 
 #ifndef tcpdump_interface_h
@@ -205,6 +205,7 @@ extern void pfsync_if_print(u_char *, const struct pcap_pkthdr *,
 extern void pfsync_ip_print(const u_char *, u_int, const u_char *);
 extern void ether_if_print(u_char *, const struct pcap_pkthdr *,
        const u_char *);
+extern void ether_tryprint(const u_char *, u_int, int);
 extern void fddi_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
 extern void ppp_ether_if_print(u_char *, const struct pcap_pkthdr *,
        const u_char *);
index 0dc4548..d701f1e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: print-ether.c,v 1.30 2015/11/16 00:16:39 mmcc Exp $   */
+/*     $OpenBSD: print-ether.c,v 1.31 2016/07/11 00:27:50 rzalamena Exp $      */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -89,29 +89,34 @@ u_short extracted_ethertype;
 void
 ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
 {
-       u_int caplen = h->caplen;
-       u_int length = h->len;
-       struct ether_header *ep;
-       u_short ether_type;
-
        ts_print(&h->ts);
 
-       if (caplen < sizeof(struct ether_header)) {
-               printf("[|ether]");
-               goto out;
-       }
-
        /*
         * Some printers want to get back at the ethernet addresses,
         * and/or check that they're not walking off the end of the packet.
         * Rather than pass them all the way down, we set these globals.
         */
-       packetp = p;
-       snapend = p + caplen;
+       snapend = p + h->caplen;
+
+       ether_tryprint(p, h->len, 1);
+}
+
+void
+ether_tryprint(const u_char *p, u_int length, int first_header)
+{
+       struct ether_header *ep;
+       u_int caplen = snapend - p;
+       u_short ether_type;
+
+       if (caplen < sizeof(struct ether_header)) {
+               printf("[|ether]");
+               goto out;
+       }
 
        if (eflag)
                ether_print(p, length);
 
+       packetp = p;
        length -= sizeof(struct ether_header);
        caplen -= sizeof(struct ether_header);
        ep = (struct ether_header *)p;
@@ -152,14 +157,15 @@ ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
                                default_print(p, caplen);
                }
        }
-       if (xflag) {
+       if (xflag && first_header) {
                if (eflag)
                        default_print(packetp, snapend - packetp);
                else
                        default_print(p, caplen);
        }
  out:
-       putchar('\n');
+       if (first_header)
+               putchar('\n');
 }
 
 /*
index 3228e1a..bb73a00 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: print-mpls.c,v 1.2 2010/06/30 19:01:06 claudio Exp $  */
+/*     $OpenBSD: print-mpls.c,v 1.3 2016/07/11 00:27:50 rzalamena Exp $        */
 
 /*
  * Copyright (c) 2005 Jason L. Wright (jason@thought.net)
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netmpls/mpls.h>
+
 #include <stdio.h>
 
 #include "interface.h"
 #include "extract.h"               /* must come after interface.h */
 
+#define CW_SEQUENCE_MASK       (0x0000ffffU)
+
+int controlword_tryprint(const u_char **, u_int *);
+
 void
 mpls_print(const u_char *bp, u_int len)
 {
        u_int32_t tag, label, exp, bottom, ttl;
+       int has_cw;
 
  again:
        if (bp + sizeof(tag) > snapend)
@@ -56,6 +65,9 @@ mpls_print(const u_char *bp, u_int len)
        if (!bottom)
                goto again;
 
+       /* Handle pseudowire control word. */
+       has_cw = controlword_tryprint(&bp, &len);
+
        /*
         * guessing the underlying protocol is about all we can do if
         * it's not explicitly defined.
@@ -107,7 +119,34 @@ mpls_print(const u_char *bp, u_int len)
                }
        }
 
+       if (has_cw)
+               ether_tryprint(bp, len, 0);
+
        return;
 trunc:
        printf("[|mpls]");
 }
+
+/* Print control word if any and returns 1 on success. */
+int
+controlword_tryprint(const u_char **bp, u_int *lenp)
+{
+       uint32_t cw, frag, seq;
+
+       if (*lenp < 4)
+               return (0);
+
+       cw = EXTRACT_32BITS(*bp);
+       if (cw & CW_ZERO_MASK)
+               return (0);
+
+       *bp += sizeof(cw);
+       *lenp += sizeof(cw);
+
+       frag = (cw & CW_FRAG_MASK) >> 16;
+       seq = cw & CW_SEQUENCE_MASK;
+
+       printf("CW(frag %u, sequence %u) ", frag, seq);
+
+       return (1);
+}