From 405883250fa7718872ae8e9226565291062822b6 Mon Sep 17 00:00:00 2001 From: rzalamena Date: Mon, 11 Jul 2016 00:27:50 +0000 Subject: [PATCH] Teach tcpdump to recognize MPLS pseudowire with control words. Added support to print encapsulated ethernet packets as well. "Looks good" deraadt@ --- usr.sbin/tcpdump/interface.h | 5 +++-- usr.sbin/tcpdump/print-ether.c | 36 ++++++++++++++++------------- usr.sbin/tcpdump/print-mpls.c | 41 +++++++++++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/usr.sbin/tcpdump/interface.h b/usr.sbin/tcpdump/interface.h index c915133f15c..b7dffceb002 100644 --- a/usr.sbin/tcpdump/interface.h +++ b/usr.sbin/tcpdump/interface.h @@ -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 *); diff --git a/usr.sbin/tcpdump/print-ether.c b/usr.sbin/tcpdump/print-ether.c index 0dc454802b0..d701f1e795c 100644 --- a/usr.sbin/tcpdump/print-ether.c +++ b/usr.sbin/tcpdump/print-ether.c @@ -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'); } /* diff --git a/usr.sbin/tcpdump/print-mpls.c b/usr.sbin/tcpdump/print-mpls.c index 3228e1a28be..bb73a0064cc 100644 --- a/usr.sbin/tcpdump/print-mpls.c +++ b/usr.sbin/tcpdump/print-mpls.c @@ -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) @@ -26,15 +26,24 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include +#include +#include + #include #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); +} -- 2.20.1