From c834ed88303ceeffea5e7d9fbae6c9901064aff9 Mon Sep 17 00:00:00 2001 From: dlg Date: Tue, 6 Feb 2018 03:07:51 +0000 Subject: [PATCH] rework ppp, pptp, and gre parsing. this started cos i was looking at pptp, which came out like this: 23:52:00.197893 call 24 seq 7: gre-ppp-payload (gre encap) 23:52:00.198930 call 1 seq 7 ack 7: gre-ppp-payload (gre encap) now it looks like this: 23:52:00.197893 20.0.0.2 > 20.0.0.1: pptp callid 24 seq 7: 17.1.1.122 > 40.0.0.2: icmp: echo request 23:52:00.198930 20.0.0.1 > 20.0.0.2: pptp callid 1 seq 7 ack 7: 40.0.0.2 > 17.1.1.122: icmp: echo reply the big improvement in ppp parsing is it stops parsing based on what the ppp headers say, rather than what bytes have been captured. this also adds parsing of EAP packets. DLT_PPP_SERIAL is now recognised and printed. gre now prints the outer addresses always, not just when it's encapsulated by ipv6 or -v is passed to tcpdump. ok sthen@ --- usr.sbin/tcpdump/interface.h | 9 +- usr.sbin/tcpdump/print-gre.c | 227 +++--- usr.sbin/tcpdump/print-ip.c | 13 +- usr.sbin/tcpdump/print-ip6.c | 6 +- usr.sbin/tcpdump/print-ppp.c | 1275 +++++++++++++++++++++++----------- usr.sbin/tcpdump/tcpdump.c | 3 +- 6 files changed, 1005 insertions(+), 528 deletions(-) diff --git a/usr.sbin/tcpdump/interface.h b/usr.sbin/tcpdump/interface.h index 5037695640d..d5a718a847d 100644 --- a/usr.sbin/tcpdump/interface.h +++ b/usr.sbin/tcpdump/interface.h @@ -1,4 +1,4 @@ -/* $OpenBSD: interface.h,v 1.70 2018/02/03 13:39:48 mpi Exp $ */ +/* $OpenBSD: interface.h,v 1.71 2018/02/06 03:07:51 dlg 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.70 2018/02/03 13:39:48 mpi Exp $ (LBL) + * @(#) $Id: interface.h,v 1.71 2018/02/06 03:07:51 dlg Exp $ (LBL) */ #ifndef tcpdump_interface_h @@ -244,7 +244,10 @@ extern void ospf_print(const u_char *, u_int, const u_char *); extern void mobile_print(const u_char *, u_int); extern void pim_print(const u_char *, u_int); extern void ppp_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); -extern void ppp_hdlc_print(const u_char *, int); +extern void ppp_hdlc_if_print(u_char *, const struct pcap_pkthdr *, + const u_char *); +extern void ppp_print(const u_char *, u_int); +extern void ppp_hdlc_print(const u_char *, u_int); extern void raw_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); extern void rip_print(const u_char *, u_int); extern void sl_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); diff --git a/usr.sbin/tcpdump/print-gre.c b/usr.sbin/tcpdump/print-gre.c index 09dd3651e50..712968e1cd1 100644 --- a/usr.sbin/tcpdump/print-gre.c +++ b/usr.sbin/tcpdump/print-gre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: print-gre.c,v 1.12 2016/12/13 06:40:21 dlg Exp $ */ +/* $OpenBSD: print-gre.c,v 1.13 2018/02/06 03:07:51 dlg Exp $ */ /* * Copyright (c) 2002 Jason L. Wright (jason@thought.net) @@ -73,25 +73,25 @@ void gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int); void gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int); void -gre_print(const u_char *bp, u_int length) +gre_print(const u_char *p, u_int length) { - u_int len = length, vers; + uint16_t vers; + int l; - if (bp + len > snapend) - len = snapend - bp; + l = snapend - p; - if (len < 2) { + if (l < sizeof(vers)) { printf("[|gre]"); return; } - vers = EXTRACT_16BITS(bp) & GRE_VERS; + vers = EXTRACT_16BITS(p) & GRE_VERS; switch (vers) { case 0: - gre_print_0(bp, len); + gre_print_0(p, length); break; case 1: - gre_print_1(bp, len); + gre_print_1(p, length); break; default: printf("gre-unknown-version=%u", vers); @@ -100,14 +100,22 @@ gre_print(const u_char *bp, u_int length) } void -gre_print_0(const u_char *bp, u_int length) +gre_print_0(const u_char *p, u_int length) { - u_int len = length; - u_int16_t flags, prot; + uint16_t flags, proto; + u_int l; + + l = snapend - p; + + flags = EXTRACT_16BITS(p); + p += sizeof(flags); + l -= sizeof(flags); + length -= sizeof(flags); + + printf("gre"); - flags = EXTRACT_16BITS(bp); if (vflag) { - printf("[%s%s%s%s%s] ", + printf(" [%s%s%s%s%s]", (flags & GRE_CP) ? "C" : "", (flags & GRE_RP) ? "R" : "", (flags & GRE_KP) ? "K" : "", @@ -115,57 +123,54 @@ gre_print_0(const u_char *bp, u_int length) (flags & GRE_sP) ? "s" : ""); } - len -= 2; - bp += 2; - - if (len < 2) + if (l < sizeof(proto)) goto trunc; - prot = EXTRACT_16BITS(bp); - printf("%s", etherproto_string(prot)); - - len -= 2; - bp += 2; + proto = EXTRACT_16BITS(p); + p += sizeof(proto); + l -= sizeof(proto); + length -= sizeof(proto); if ((flags & GRE_CP) | (flags & GRE_RP)) { - if (len < 2) + if (l < 2) goto trunc; - if (vflag) - printf(" sum 0x%x", EXTRACT_16BITS(bp)); - bp += 2; - len -= 2; + if ((flags & GRE_CP) && vflag) + printf(" sum 0x%x", EXTRACT_16BITS(p)); + p += 2; + l -= 2; + length -= 2; - if (len < 2) + if (l < 2) goto trunc; - printf(" off 0x%x", EXTRACT_16BITS(bp)); - bp += 2; - len -= 2; + if (flags & GRE_RP) + printf(" off 0x%x", EXTRACT_16BITS(p)); + p += 2; + l -= 2; + length -= 2; } if (flags & GRE_KP) { uint32_t key, vsid; - if (len < 4) + if (l < sizeof(key)) goto trunc; - key = EXTRACT_32BITS(bp); - - /* maybe NVGRE? */ - if (flags == (GRE_KP | 0) && prot == ETHERTYPE_TRANSETHER) { - vsid = (key & NVGRE_VSID_MASK) >> NVGRE_VSID_SHIFT; - printf(" NVGRE vsid=%u (0x%x)+flowid=0x%02x /", - vsid, vsid, - (key & NVGRE_FLOWID_MASK) >> NVGRE_FLOWID_SHIFT); - } - printf(" key=%u (0x%x)", key, key); - bp += 4; - len -= 4; + key = EXTRACT_32BITS(p); + p += sizeof(key); + l -= sizeof(key); + length -= sizeof(key); + + /* maybe NVGRE, or key entropy? */ + vsid = (key & NVGRE_VSID_MASK) >> NVGRE_VSID_SHIFT; + printf(" vsid=%u+flow=0x%02x/key=%u", + vsid, (key & NVGRE_FLOWID_MASK) >> NVGRE_FLOWID_SHIFT, key); } if (flags & GRE_SP) { - if (len < 4) + if (l < 4) goto trunc; - printf(" seq %u", EXTRACT_32BITS(bp)); - bp += 4; - len -= 4; + printf(" seq %u", EXTRACT_32BITS(p)); + p += 4; + l -= 4; + length -= 4; } if (flags & GRE_RP) { @@ -174,43 +179,45 @@ gre_print_0(const u_char *bp, u_int length) u_int8_t sreoff; u_int8_t srelen; - if (len < 4) + if (l < 4) goto trunc; - af = EXTRACT_16BITS(bp); - sreoff = *(bp + 2); - srelen = *(bp + 3); - bp += 4; - len -= 4; + af = EXTRACT_16BITS(p); + sreoff = *(p + 2); + srelen = *(p + 3); + p += 4; + l -= 4; + length -= 4; if (af == 0 && srelen == 0) break; - gre_sre_print(af, sreoff, srelen, bp, len); + gre_sre_print(af, sreoff, srelen, p, l); - if (len < srelen) + if (l < srelen) goto trunc; - bp += srelen; - len -= srelen; + p += srelen; + l -= srelen; + length -= srelen; } } - printf(": "); + printf(" "); - switch (prot) { + switch (proto) { case ETHERTYPE_IP: - ip_print(bp, len); + ip_print(p, length); break; case ETHERTYPE_IPV6: - ip6_print(bp, len); + ip6_print(p, length); break; case ETHERTYPE_MPLS: - mpls_print(bp, len); + mpls_print(p, length); break; case ETHERTYPE_TRANSETHER: - ether_print(bp, len); + ether_print(p, length); break; default: - printf("gre-proto-0x%x", prot); + printf("unknown-proto-%04x", proto); } return; @@ -219,17 +226,22 @@ trunc: } void -gre_print_1(const u_char *bp, u_int length) +gre_print_1(const u_char *p, u_int length) { - u_int len = length; - u_int16_t flags, prot; + uint16_t flags, proto, len; + int l; + + l = snapend - p; - flags = EXTRACT_16BITS(bp); - len -= 2; - bp += 2; + flags = EXTRACT_16BITS(p); + p += sizeof(flags); + l -= sizeof(flags); + length -= sizeof(flags); + + printf("pptp"); if (vflag) { - printf("[%s%s%s%s%s%s]", + printf(" [%s%s%s%s%s%s] ", (flags & GRE_CP) ? "C" : "", (flags & GRE_RP) ? "R" : "", (flags & GRE_KP) ? "K" : "", @@ -238,11 +250,13 @@ gre_print_1(const u_char *bp, u_int length) (flags & GRE_AP) ? "A" : ""); } - if (len < 2) + if (l < sizeof(proto)) goto trunc; - prot = EXTRACT_16BITS(bp); - len -= 2; - bp += 2; + + proto = EXTRACT_16BITS(p); + p += sizeof(proto); + l -= sizeof(proto); + length -= sizeof(proto); if (flags & GRE_CP) { printf(" cpset!"); @@ -261,52 +275,65 @@ gre_print_1(const u_char *bp, u_int length) return; } - if (flags & GRE_KP) { - u_int32_t k; + /* GRE_KP */ + if (l < sizeof(len)) + goto trunc; + len = EXTRACT_16BITS(p); + p += sizeof(len); + l -= sizeof(len); + length -= sizeof(len); - if (len < 4) - goto trunc; - k = EXTRACT_32BITS(bp); - printf(" call %d", k & 0xffff); - len -= 4; - bp += 4; - } + if (vflag) + printf(" len %u", EXTRACT_16BITS(p)); + + if (l < 2) + goto trunc; + printf(" callid %u", EXTRACT_16BITS(p)); + p += 2; + l -= 2; + length -= 2; if (flags & GRE_SP) { - if (len < 4) + if (l < 4) goto trunc; - printf(" seq %u", EXTRACT_32BITS(bp)); - bp += 4; - len -= 4; + printf(" seq %u", EXTRACT_32BITS(p)); + p += 4; + l -= 4; + length -= 4; } if (flags & GRE_AP) { - if (len < 4) + if (l < 4) goto trunc; - printf(" ack %u", EXTRACT_32BITS(bp)); - bp += 4; - len -= 4; + printf(" ack %u", EXTRACT_32BITS(p)); + p += 4; + l -= 4; + length -= 4; } - if ((flags & GRE_SP) == 0) { - printf(" no-payload"); + if ((flags & GRE_SP) == 0) return; + + if (length < len) { + (void)printf(" truncated-pptp - %d bytes missing!", + len - length); + len = length; } printf(": "); - switch (prot) { + switch (proto) { case ETHERTYPE_PPP: - printf("gre-ppp-payload"); + ppp_hdlc_print(p, len); break; default: - printf("gre-proto-0x%x", prot); + printf("unknown-proto-%04x", proto); break; } return; trunc: - printf("[|gre]"); + printf("[|pptp]"); } void diff --git a/usr.sbin/tcpdump/print-ip.c b/usr.sbin/tcpdump/print-ip.c index 254ace611fc..b433cbb7678 100644 --- a/usr.sbin/tcpdump/print-ip.c +++ b/usr.sbin/tcpdump/print-ip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: print-ip.c,v 1.47 2016/10/30 04:10:21 jsg Exp $ */ +/* $OpenBSD: print-ip.c,v 1.48 2018/02/06 03:07:51 dlg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -497,16 +497,11 @@ ip_print(const u_char *bp, u_int length) #define IPPROTO_GRE 47 #endif case IPPROTO_GRE: - if (vflag) - (void)printf("gre %s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); + (void)printf("%s > %s: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); /* do it */ gre_print(cp, len); - if (! vflag) { - printf(" (gre encap)"); - goto out; - } break; #ifndef IPPROTO_ESP diff --git a/usr.sbin/tcpdump/print-ip6.c b/usr.sbin/tcpdump/print-ip6.c index 2a13577433f..42efd0d7a0b 100644 --- a/usr.sbin/tcpdump/print-ip6.c +++ b/usr.sbin/tcpdump/print-ip6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: print-ip6.c,v 1.24 2016/12/13 06:40:21 dlg Exp $ */ +/* $OpenBSD: print-ip6.c,v 1.25 2018/02/06 03:07:51 dlg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 @@ -190,10 +190,6 @@ ip6_print(const u_char *bp, u_int length) #endif case IPPROTO_GRE: gre_print(cp, len); - if (! vflag) { - printf(" (gre encap)"); - goto out; - } goto end; case IPPROTO_NONE: diff --git a/usr.sbin/tcpdump/print-ppp.c b/usr.sbin/tcpdump/print-ppp.c index 3c9e850356f..40692371440 100644 --- a/usr.sbin/tcpdump/print-ppp.c +++ b/usr.sbin/tcpdump/print-ppp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: print-ppp.c,v 1.30 2017/07/25 16:07:28 espie Exp $ */ +/* $OpenBSD: print-ppp.c,v 1.31 2018/02/06 03:07:51 dlg Exp $ */ /* * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 @@ -48,30 +48,65 @@ struct rtentry; #include "addrtoname.h" #include "extract.h" +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +#ifndef PPP_EAP +#define PPP_EAP 0xc227 +#endif + +#ifndef PPP_CDP +#define PPP_CDP 0x0207 +#endif + +#ifndef PPP_CDPCP +#define PPP_CDPCP 0x8207 +#endif + struct protonames { u_short protocol; char *name; }; -static struct protonames protonames[] = { +static const struct protonames protonames[] = { /* * Protocol field values. */ { PPP_IP, "IP" }, /* Internet Protocol */ { PPP_XNS, "XNS" }, /* Xerox NS */ { PPP_IPX, "IPX" }, /* IPX Datagram (RFC1552) */ + { PPP_AT, "AppleTalk" }, /* AppleTalk Protocol */ { PPP_VJC_COMP, "VJC_UNCOMP" }, /* VJ compressed TCP */ { PPP_VJC_UNCOMP,"VJC_UNCOMP" },/* VJ uncompressed TCP */ + { PPP_IPV6, "IPv6" }, /* Internet Protocol version 6 */ { PPP_COMP, "COMP" }, /* compressed packet */ { PPP_IPCP, "IPCP" }, /* IP Control Protocol */ + { PPP_ATCP, "AppleTalkCP" },/* AppleTalk Control Protocol */ { PPP_IPXCP, "IPXCP" }, /* IPX Control Protocol (RFC1552) */ { PPP_IPV6CP, "IPV6CP" }, /* IPv6 Control Protocol */ { PPP_CCP, "CCP" }, /* Compression Control Protocol */ { PPP_LCP, "LCP" }, /* Link Control Protocol */ { PPP_PAP, "PAP" }, /* Password Authentication Protocol */ { PPP_LQR, "LQR" }, /* Link Quality Report protocol */ + { PPP_CBCP, "CBCP" }, /* Callback Control Protocol */ { PPP_CHAP, "CHAP" }, /* Cryptographic Handshake Auth. Proto */ - { PPP_IPV6, "IPV6" }, /* Internet Protocol v6 */ + { PPP_EAP, "EAP" }, /* Extensible Auth. Protocol */ + { PPP_CDP, "CDP" }, + { PPP_CDPCP, "CDPCP" }, +}; + +struct ppp_control { + uint8_t code; + uint8_t id; + uint16_t len; +}; + +struct ppp_cp_type { + const char *unkname; + int mincode; + int maxcode; + const char **codes; }; /* LCP */ @@ -91,7 +126,7 @@ static struct protonames protonames[] = { #define LCP_MIN LCP_CONF_REQ #define LCP_MAX LCP_DISC_REQ -static char *lcpcodes[] = { +static const char *lcpcodes[] = { /* * LCP code values (RFC1661, pp26) */ @@ -158,7 +193,7 @@ static char *lcpconfopts[] = { #define CHAP_CODEMIN 1 #define CHAP_CODEMAX 4 -static char *chapcode[] = { +static const char *chapcode[] = { "Challenge", "Response", "Success", @@ -174,12 +209,49 @@ static char *chapcode[] = { #define PAP_CODEMIN 1 #define PAP_CODEMAX 3 -static char *papcode[] = { +static const char *papcode[] = { "Authenticate-Request", "Authenticate-Ack", "Authenticate-Nak", }; +/* EAP */ + +#define EAP_CHAL 1 +#define EAP_RESP 2 +#define EAP_SUCC 3 +#define EAP_FAIL 4 + +#define EAP_CODEMIN EAP_CHAL +#define EAP_CODEMAX EAP_FAIL + +#define EAP_TYPE_IDENTITY 1 +#define EAP_TYPE_NOTIFICATION 2 +#define EAP_TYPE_NAK 3 +#define EAP_TYPE_MD5_CHALLENGE 4 +#define EAP_TYPE_OTP 5 +#define EAP_TYPE_TOKEN 6 + +#define EAP_TYPEMIN EAP_TYPE_IDENTITY +#define EAP_TYPEMAX EAP_TYPE_TOKEN + +static const char *eapcode[] = { + "Challenge", + "Response", + "Success", + "Failure", +}; + +static const char *eaptype[] = { + "Identity", + "Notification", + "Nak", + "MD5-Challenge", + "One-Time-Password", + "Token", +}; + + /* IPCP */ #define IPCP_CODE_CFG_REQ 1 @@ -212,12 +284,15 @@ static char *papcode[] = { #define IPV6CP_IFID 1 -static int print_lcp_config_options(u_char *p); -static void handle_lcp(const u_char *p, int length); -static void handle_chap(const u_char *p, int length); -static void handle_ipcp(const u_char *p, int length); -static void handle_ipv6cp(const u_char *p, int length); -static void handle_pap(const u_char *p, int length); +static int print_lcp_config_options(const u_char *p, int); +static void handle_lcp(const u_char *, int); +static void handle_chap(const u_char *p, int); +static void handle_eap(const u_char *p, int); +static void handle_ipcp(const u_char *p, int); +static int print_ipcp_config_options(const u_char *, int); +static void handle_ipv6cp(const u_char *p, int); +static int print_ipv6cp_config_options(const u_char *, int); +static void handle_pap(const u_char *p, int); struct pppoe_header { u_int8_t vertype; /* PPPoE version/type */ @@ -243,87 +318,162 @@ struct pppoe_header { #define PPPOE_TAG_AC_SYSTEM_ERROR 0x0202 /* Acc. Concentrator Error */ #define PPPOE_TAG_GENERIC_ERROR 0x0203 /* Generic Error */ -void -ppp_hdlc_print(p, length) - const u_char *p; - int length; +static void +ppp_protoname(uint16_t proto) { - int proto = PPP_PROTOCOL(p); + const struct protonames *protoname; int i; - for (i = sizeof(protonames) / sizeof(protonames[0]) - 1; i >= 0; i--) { - if (proto == protonames[i].protocol) { - printf("%s: ", protonames[i].name); - - switch(proto) { + /* bsearch? */ + for (i = 0; i < nitems(protonames); i++) { + protoname = &protonames[i]; - case PPP_LCP: - handle_lcp(p, length); - break; - case PPP_CHAP: - handle_chap(p, length); - break; - case PPP_PAP: - handle_pap(p, length); - break; - case PPP_IPCP: - handle_ipcp(p, length); - break; - case PPP_IPV6CP: - handle_ipv6cp(p, length); - break; - } - break; + if (proto == protoname->protocol) { + printf("%s ", protoname->name); + return; } } - if (i < 0) - printf("%04x: ", proto); + + printf("unknown-ppp-%04x", proto); +} + +void +ppp_print(const u_char *p, u_int length) +{ + uint16_t proto; + int l; + + l = snapend - p; + + if (l < sizeof(proto)) { + printf("[|ppp]"); + return; + } + + proto = EXTRACT_16BITS(p); + + p += sizeof(proto); + l -= sizeof(proto); + length -= sizeof(proto); + + if (eflag) + ppp_protoname(proto); + + switch (proto) { + case PPP_IP: + ip_print(p, length); + return; + case PPP_IPV6: + ip6_print(p, length); + return; + } + + if (!eflag) + ppp_protoname(proto); + + switch(proto) { + case PPP_LCP: + handle_lcp(p, l); + break; + case PPP_CHAP: + handle_chap(p, l); + break; + case PPP_EAP: + handle_eap(p, l); + break; + case PPP_PAP: + handle_pap(p, l); + break; + case PPP_IPCP: + handle_ipcp(p, l); + break; + case PPP_IPV6CP: + handle_ipv6cp(p, l); + break; + } +} + +static int +ppp_cp_header(struct ppp_control *pc, const u_char *p, int l, + const struct ppp_cp_type *t) +{ + uint8_t code; + int off = 0; + int len; + + len = sizeof(pc->code); + if (l < len) + return (-1); + + pc->code = code = *(p + off); + if (code >= t->mincode && code <= t->maxcode) + printf("%s ", t->codes[code - 1]); + else + printf("unknown-%s-%u ", t->unkname, pc->code); + + off = len; + len += sizeof(pc->id); + if (l < len) + return (-1); + + pc->id = *(p + off); + printf("Id=0x%02x:", pc->id); + + off = len; + len += sizeof(pc->len); + if (l < len) + return (-1); + + pc->len = EXTRACT_16BITS(p + off); + + return (len); } /* print LCP frame */ +static const struct ppp_cp_type ppp_cp_lcp = { + "lcp", + LCP_MIN, LCP_MAX, + lcpcodes, +}; + static void -handle_lcp(p, length) - const u_char *p; - int length; +handle_lcp(const u_char *p, int l) { - int x, j; - u_char *ptr; + struct ppp_control pc; - TCHECK(*(p + 4)); - x = *(p + 4); + if (ppp_cp_header(&pc, p, l, &ppp_cp_lcp) == -1) + goto trunc; - if ((x >= LCP_MIN) && (x <= LCP_MAX)) - printf("%s", lcpcodes[x-1]); - else { - printf("0x%02x", x); - return; - } + if (l > pc.len) + l = pc.len; - length -= 4; - - switch(x) { + p += sizeof(pc); + l -= sizeof(pc); + switch (pc.code) { case LCP_CONF_REQ: case LCP_CONF_ACK: case LCP_CONF_NAK: case LCP_CONF_REJ: - x = length; - ptr = (u_char *)p+8; - do { - if((j = print_lcp_config_options(ptr)) == 0) + while (l > 0) { + int optlen; + + optlen = print_lcp_config_options(p, l); + if (optlen == -1) + goto trunc; + if (optlen == 0) break; - x -= j; - ptr += j; + + p += optlen; + l -= optlen; } - while(x > 0); break; - case LCP_ECHO_REQ: case LCP_ECHO_RPL: - TCHECK2(*(p + 8), 4); - printf(", Magic-Number=%d", ((*(p+ 8) << 24) + (*(p+9) << 16) + - (*(p+10) << 8) + (*(p+11)))); + if (l < 4) + goto trunc; + printf(" Magic-Number=%u", EXTRACT_32BITS(p)); break; case LCP_TERM_REQ: case LCP_TERM_ACK: @@ -342,69 +492,111 @@ trunc: /* LCP config options */ static int -print_lcp_config_options(p) - u_char *p; +print_lcp_config_options(const u_char *p, int l) { - int len, opt; + uint8_t type, length; + uint16_t proto; - TCHECK2(*p, 2); - len = *(p+1); - opt = *p; + if (l < sizeof(type)) + return (-1); - if((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX)) - printf(", %s", lcpconfopts[opt]); + type = p[0]; + if (type <= LCPOPT_MAX) + printf(" %s", lcpconfopts[type]); + else + printf(" unknown-lcp-%u", type); - switch(opt) { + if (l < sizeof(type) + sizeof(length)) + return (-1); + + length = p[1]; + + if (length < sizeof(type) + sizeof(length)) + return (0); + + if (l > length) + l = length; + + p += sizeof(type) + sizeof(length); + l -= sizeof(type) + sizeof(length); + + switch (type) { case LCPOPT_MRU: - if(len == 4) { - TCHECK2(*(p + 2), 2); - printf("=%d", (*(p+2) << 8) + *(p+3)); - } + if (length != 4) + goto invalid; + if (l < 2) + return (-1); + + printf("=%u", EXTRACT_16BITS(p)); break; case LCPOPT_AP: - if(len >= 4) { - TCHECK2(*(p + 2), 2); - if(*(p+2) == 0xc0 && *(p+3) == 0x23) - printf(" PAP"); - else if(*(p+2) == 0xc2 && *(p+3) == 0x23) { - printf(" CHAP/"); - TCHECK(*(p+4)); - switch(*(p+4)) { - default: - printf("unknown-algorithm-%d", *(p+4)); - break; - case 5: - printf("MD5"); - break; - case 0x80: - printf("Microsoft"); - break; - } - } else if(*(p+2) == 0xc2 && *(p+3) == 0x27) - printf(" EAP"); - else if(*(p+2) == 0xc0 && *(p+3) == 0x27) - printf(" SPAP"); - else if(*(p+2) == 0xc1 && *(p+3) == 0x23) - printf(" Old-SPAP"); - else - printf("unknown"); + if (length < 4) + goto invalid; + if (l < sizeof(proto)) + return (-1); + + proto = EXTRACT_16BITS(p); + switch (proto) { + case PPP_PAP: + printf("=PAP"); + break; + case PPP_CHAP: + printf("=CHAP"); + if (length < 5) + goto invalid; + + p += sizeof(proto); + l -= sizeof(proto); + + type = *p; + switch (type) { + case 0x05: + printf("/MD5"); + break; + case 0x80: + printf("/Microsoft"); + break; + default: + printf("/unknown-algorithm-%02x", type); + break; + } + break; + case PPP_EAP: + printf("=EAP"); + break; + case 0xc027: + printf("=SPAP"); + break; + case 0xc127: + printf("=Old-SPAP"); + break; + default: + printf("=unknown-ap-%04x", proto); + break; } break; case LCPOPT_QP: - if(len >= 4) { - TCHECK2(*(p + 2), 2); - if(*(p+2) == 0xc0 && *(p+3) == 0x25) - printf(" LQR"); - else - printf(" unknown"); + if (length < 4) + goto invalid; + if (l < sizeof(proto)) + return (-1); + + proto = EXTRACT_16BITS(p); + switch (proto) { + case PPP_LQR: + printf(" LQR"); + break; + default: + printf(" unknown-qp-%u", proto); } break; case LCPOPT_MN: - if(len == 6) { - TCHECK2(*(p + 2), 4); - printf("=%d", ((*(p+2) << 24) + (*(p+3) << 16) + - (*(p+4) << 8) + (*(p+5)))); - } + if (length < 6) + goto invalid; + if (l < 4) + return (-1); + + printf("=%u", EXTRACT_32BITS(p)); break; case LCPOPT_PFC: printf(" PFC"); @@ -413,51 +605,86 @@ print_lcp_config_options(p) printf(" ACFC"); break; } - return(len); -trunc: - printf("[|lcp]"); - return 0; + return (length); + +invalid: + printf(" invalid opt len %u", length); + return (length); } /* CHAP */ +static const struct ppp_cp_type ppp_cp_chap = { + "chap", + CHAP_CODEMIN, CHAP_CODEMAX, + chapcode, +}; + static void -handle_chap(p, length) - const u_char *p; - int length; +handle_chap(const u_char *p, int l) { - int x; - u_char *ptr; + struct ppp_control pc; + uint8_t vsize; + int i; - TCHECK(*(p+4)); - x = *(p+4); + if (ppp_cp_header(&pc, p, l, &ppp_cp_chap) == -1) + goto trunc; - if((x >= CHAP_CODEMIN) && (x <= CHAP_CODEMAX)) - printf("%s", chapcode[x-1]); - else { - printf("0x%02x", x); - return; - } + if (l > pc.len) + l = pc.len; - length -= 4; - - switch(x) { + p += sizeof(pc); + l -= sizeof(pc); + + switch (pc.code) { case CHAP_CHAL: case CHAP_RESP: - printf(", Value="); - TCHECK(*(p+8)); - x = *(p+8); /* value size */ - ptr = (u_char *)p+9; - while(--x >= 0) { - TCHECK(*ptr); - printf("%02x", *ptr++); + if (l < sizeof(vsize)) + goto trunc; + + vsize = *p; + if (vsize < 1) { + printf(" invalid Value-Size"); + return; } - x = length - *(p+8) - 1; - printf(", Name="); - while(--x >= 0) { - TCHECK(*ptr); - safeputchar(*ptr++); + + p += sizeof(vsize); + l -= sizeof(vsize); + + printf(" Value="); + for (i = 0; i < vsize; i++) { + if (l == 0) + goto trunc; + + printf("%02x", *p); + + p++; + l--; + } + + printf(" Name="); + for (i += sizeof(pc) + sizeof(vsize); i < pc.len; i++) { + if (l == 0) + goto trunc; + + safeputchar(*p); + + p++; + l--; + } + break; + case CHAP_SUCC: + case CHAP_FAIL: + printf(" Message="); + for (i = sizeof(pc); i < pc.len; i++) { + if (l == 0) + goto trunc; + + safeputchar(*p); + + p++; + l--; } break; } @@ -467,50 +694,195 @@ trunc: printf("[|chap]"); } -/* PAP */ +/* EAP */ + +static const struct ppp_cp_type ppp_cp_eap = { + "eap", + EAP_CODEMIN, EAP_CODEMAX, + eapcode, +}; static void -handle_pap(p, length) - const u_char *p; - int length; +handle_eap(const u_char *p, int l) { - int x; - u_char *ptr; + struct ppp_control pc; + uint8_t type, vsize; + int i; - TCHECK(*(p+4)); - x = *(p+4); + if (ppp_cp_header(&pc, p, l, &ppp_cp_eap) == -1) + goto trunc; - if((x >= PAP_CODEMIN) && (x <= PAP_CODEMAX)) - printf("%s", papcode[x-1]); - else { - printf("0x%02x", x); - return; + if (l > pc.len) + l = pc.len; + + p += sizeof(pc); + l -= sizeof(pc); + + switch (pc.code) { + case EAP_CHAL: + case EAP_RESP: + if (l < sizeof(type)) + goto trunc; + + type = *p; + p += sizeof(type); + l -= sizeof(type); + + if (type >= EAP_TYPEMIN && type <= EAP_TYPEMAX) + printf(" %s", eaptype[type - 1]); + else { + printf(" unknown-eap-type-%u", type); + return; + } + + switch (type) { + case EAP_TYPE_IDENTITY: + case EAP_TYPE_NOTIFICATION: + case EAP_TYPE_OTP: + i = sizeof(pc) + sizeof(type); + if (i == pc.len) + break; + + printf("="); + do { + if (l == 0) + goto trunc; + + safeputchar(*p); + + p++; + l--; + } while (++i < pc.len); + break; + + case EAP_TYPE_NAK: + if (l < sizeof(type)) + goto trunc; + type = *p; + if (type >= EAP_TYPEMIN && type <= EAP_TYPEMAX) + printf(" %s", eaptype[type - 1]); + else + printf(" unknown-eap-type-%u", type); + break; + case EAP_TYPE_MD5_CHALLENGE: + if (l < sizeof(vsize)) + goto trunc; + + vsize = *p; + p += sizeof(vsize); + l -= sizeof(vsize); + + printf("="); + for (i = 0; i < vsize; i++) { + if (l == 0) + goto trunc; + + printf("%02x", *p); + + p++; + l--; + } + break; + } + break; + case CHAP_SUCC: + case CHAP_FAIL: + break; } + return; + +trunc: + printf("[|eap]"); +} - length -= 4; +/* PAP */ - switch(x) { +static const struct ppp_cp_type ppp_cp_pap = { + "pap", + PAP_CODEMIN, PAP_CODEMAX, + papcode, +}; + +static void +handle_pap(const u_char *p, int l) +{ + struct ppp_control pc; + uint8_t x; + int i; + + if (ppp_cp_header(&pc, p, l, &ppp_cp_pap) == -1) + goto trunc; + + if (l > pc.len) + l = pc.len; + + p += sizeof(pc); + l -= sizeof(pc); + + switch (pc.code) { case PAP_AREQ: - printf(", Peer-Id="); - TCHECK(*(p+8)); - x = *(p+8); /* peerid size */ - ptr = (u_char *)p+9; - while(--x >= 0) { - TCHECK(*ptr); - safeputchar(*ptr++); + if (l < sizeof(x)) /* Peer-ID Length */ + goto trunc; + + x = *p; + + p += sizeof(x); + l -= sizeof(x); + + printf(" Peer-Id="); + for (i = 0; i < x; i++) { + if (l == 0) + goto trunc; + + safeputchar(*p); + + p++; + l--; } - TCHECK(*ptr); - x = *ptr++; - printf(", Passwd="); - while(--x >= 0) { - TCHECK(*ptr); - safeputchar(*ptr++); + + if (l < sizeof(x)) /* Passwd-Length */ + goto trunc; + + x = *p; + + p += sizeof(x); + l -= sizeof(x); + + printf(" Passwd="); + for (i = 0; i < x; i++) { + if (l == 0) + goto trunc; + + safeputchar(*p); + + p++; + l--; } break; + case PAP_AACK: - case PAP_ANAK: - break; + case PAP_ANAK: + if (l < sizeof(x)) /* Msg-Length */ + goto trunc; + + x = *p; + + p += sizeof(x); + l -= sizeof(x); + + printf(" Message="); + for (i = 0; i < x; i++) { + if (l == 0) + goto trunc; + + safeputchar(*p); + + p++; + l--; + } + break; } + return; trunc: @@ -519,187 +891,289 @@ trunc: /* IPCP */ +#define IP_LEN 4 +#define IP_FMT "%u.%u.%u.%u" +#define IP_ARG(_p) (_p)[0], (_p)[1], (_p)[2], (_p)[3] + +static const struct ppp_cp_type ppp_cp_ipcp = { + "ipcp", + IPCP_CODE_MIN, IPCP_CODE_MAX, + lcpcodes, +}; + static void -handle_ipcp(p, length) - const u_char *p; - int length; +handle_ipcp(const u_char *p, int l) { - int x; + struct ppp_control pc; - TCHECK(*(p+4)); - x = *(p+4); + if (ppp_cp_header(&pc, p, l, &ppp_cp_ipcp) == -1) + goto trunc; - if((x >= IPCP_CODE_MIN) && (x <= IPCP_CODE_MAX)) - printf("%s", lcpcodes[x-1]); /* share table with LCP */ - else { - printf("0x%02x", x); - return; + if (l > pc.len) + l = pc.len; + + p += sizeof(pc); + l -= sizeof(pc); + + switch (pc.code) { + case IPCP_CODE_CFG_REQ: + case IPCP_CODE_CFG_ACK: + case IPCP_CODE_CFG_NAK: + case IPCP_CODE_CFG_REJ: + while (l > 0) { + int optlen; + + optlen = print_ipcp_config_options(p, l); + if (optlen == -1) + goto trunc; + if (optlen == 0) + break; + + p += optlen; + l -= optlen; + } + break; + + case IPCP_CODE_TRM_REQ: + case IPCP_CODE_TRM_ACK: + case IPCP_CODE_COD_REJ: + default: + break; } - length -= 4; + return; - TCHECK(*(p+8)); - switch(*(p+8)) { +trunc: + printf("[|ipcp]"); +} + +static int +print_ipcp_config_options(const u_char *p, int l) +{ + uint8_t type, length; + + if (l < sizeof(type)) + return (-1); + + type = p[0]; + switch (type) { case IPCP_2ADDR: - printf(", IP-Addresses"); - TCHECK2(*(p+10), 8); - printf(", Src=%d.%d.%d.%d", - *(p+10), *(p+11), *(p+12), *(p+13)); - printf(", Dst=%d.%d.%d.%d", - *(p+14), *(p+15), *(p+16), *(p+17)); + printf(" IP-Addresses"); break; - case IPCP_CP: - printf(", IP-Compression-Protocol"); + printf(" IP-Compression-Protocol"); break; - case IPCP_ADDR: - TCHECK2(*(p+10), 4); - printf(", IP-Address=%d.%d.%d.%d", - *(p+10), *(p+11), *(p+12), *(p+13)); + printf(" IP-Address"); break; default: - printf(", Unknown IPCP code 0x%x", *(p+8)); + printf(" ipcp-type-%u", type); break; } - return; -trunc: - printf("[|ipcp]"); + if (l < sizeof(type) + sizeof(length)) + return (-1); + + length = p[1]; + + p += (sizeof(type) + sizeof(length)); + l -= (sizeof(type) + sizeof(length)); + + switch (type) { + case IPCP_2ADDR: + if (length != 10) + goto invalid; + if (l < IP_LEN) + return (-1); + + printf(" Src=" IP_FMT, IP_ARG(p)); + + p += IP_LEN; + l -= IP_LEN; + + if (l < IP_LEN) + return (-1); + + printf(" Dst=" IP_FMT, IP_ARG(p)); + break; + case IPCP_CP: + if (length < 4) + goto invalid; + if (l < sizeof(type)) + return (-1); + + type = EXTRACT_16BITS(p); + switch (type) { + case 0x0037: + printf(" Van Jacobsen Compressed TCP/IP"); + break; + default: + printf("ipcp-compression-type-%u", type); + break; + } + break; + case IPCP_ADDR: + if (length != 6) + goto invalid; + if (l < IP_LEN) + return (-1); + + printf("=" IP_FMT, IP_ARG(p)); + break; + } + + return (length); + +invalid: + printf(" invalid opt len %u", length); + return (length); } /* IPV6CP */ +static const struct ppp_cp_type ppp_cp_ipv6cp = { + "ipv6cp", + IPV6CP_CODE_MIN, IPV6CP_CODE_MAX, + lcpcodes, +}; + static void -handle_ipv6cp(p, length) - const u_char *p; - int length; +handle_ipv6cp(const u_char *p, int l) { - int x; + struct ppp_control pc; - TCHECK(*(p+4)); - x = *(p+4); + if (ppp_cp_header(&pc, p, l, &ppp_cp_ipv6cp) == -1) + goto trunc; - if((x >= IPV6CP_CODE_MIN) && (x <= IPV6CP_CODE_MAX)) - printf("%s", lcpcodes[x-1]); /* share table with LCP */ - else { - printf("0x%02x", x); - return; - } + if (l > pc.len) + l = pc.len; - TCHECK(*(p+8)); - switch(*(p+8)) { - case IPV6CP_IFID: - TCHECK2(*(p + 10), 8); - printf(", Interface-ID=%04x:%04x:%04x:%04x", - EXTRACT_16BITS(p + 10), - EXTRACT_16BITS(p + 12), - EXTRACT_16BITS(p + 14), - EXTRACT_16BITS(p + 16)); + p += sizeof(pc); + l -= sizeof(pc); + + switch (pc.code) { + case IPV6CP_CODE_CFG_REQ: + case IPV6CP_CODE_CFG_ACK: + case IPV6CP_CODE_CFG_NAK: + case IPV6CP_CODE_CFG_REJ: + while (l > 0) { + int optlen; + + optlen = print_ipv6cp_config_options(p, l); + if (optlen == -1) + goto trunc; + if (optlen == 0) + break; + + p += optlen; + l -= optlen; + } break; + case IPV6CP_CODE_TRM_REQ: + case IPV6CP_CODE_TRM_ACK: + case IPV6CP_CODE_COD_REJ: default: - printf(", Unknown IPV6CP code 0x%x", *(p+8)); break; } + return; trunc: printf("[|ipv6cp]"); } -void -ppp_if_print(user, h, p) - u_char *user; - const struct pcap_pkthdr *h; - const u_char *p; +static int +print_ipv6cp_config_options(const u_char *p, int l) { - u_int length = h->len; - u_int caplen = h->caplen; + uint8_t type, length; - ts_print(&h->ts); + if (l < sizeof(type)) + return (-1); - if (caplen < PPP_HDRLEN) { - printf("[|ppp]"); - goto out; + type = p[0]; + switch (type) { + case IPV6CP_IFID: + printf(" IPv6-Interface-Id"); + break; + default: + printf(" ipv6cp-type-%u", type); + break; } - /* - * Some printers want to get back at the link level 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; + if (l < sizeof(type) + sizeof(length)) + return (-1); - if (eflag) - ppp_hdlc_print(p, length); + length = p[1]; - length -= PPP_HDRLEN; + p += (sizeof(type) + sizeof(length)); + l -= (sizeof(type) + sizeof(length)); - switch(PPP_PROTOCOL(p)) { - case PPP_IP: - case ETHERTYPE_IP: - ip_print((const u_char *)(p + PPP_HDRLEN), length); - break; - case PPP_IPV6: - case ETHERTYPE_IPV6: - ip6_print((const u_char *)(p + PPP_HDRLEN), length); + switch (type) { + case IPV6CP_IFID: + if (length != 10) + goto invalid; + if (l < 8) + return (-1); + + printf("=%04x:%04x:%04x:%04x", EXTRACT_16BITS(p + 0), + EXTRACT_16BITS(p + 2), EXTRACT_16BITS(p + 4), + EXTRACT_16BITS(p + 6)); break; - case PPP_IPX: - case ETHERTYPE_IPX: - ipx_print((const u_char *)(p + PPP_HDRLEN), length); + default: break; + } -#ifndef PPP_MPLS -#define PPP_MPLS 0x0281 -#endif - case PPP_MPLS: - mpls_print((const u_char *)(p + PPP_HDRLEN), length); - break; + return (length); +invalid: + printf(" invalid opt len %u", length); + return (length); +} - default: - if(!eflag) - ppp_hdlc_print(p, length); - if(!xflag) - default_print((const u_char *)(p + PPP_HDRLEN), - caplen - PPP_HDRLEN); - } +void +ppp_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) +{ + u_int length = h->len; + u_int caplen = h->caplen; + + packetp = p; + snapend = p + caplen; + + ts_print(&h->ts); + + ppp_hdlc_print(p, length); if (xflag) default_print((const u_char *)(p + PPP_HDRLEN), - caplen - PPP_HDRLEN); -out: + caplen - PPP_HDRLEN); + putchar('\n'); } void -ppp_ether_if_print(user, h, p) - u_char *user; - const struct pcap_pkthdr *h; - const u_char *p; +ppp_ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { u_int16_t pppoe_sid, pppoe_len; - u_int caplen = h->caplen; - u_int16_t length = h->len; - u_int16_t proto; - int i; - - ts_print(&h->ts); + u_int l = h->caplen; + u_int length = h->len; packetp = p; - snapend = p + caplen; + snapend = p + l; + + ts_print(&h->ts); if (eflag) printf("PPPoE "); - if (caplen < sizeof(struct pppoe_header)) { + if (l < sizeof(struct pppoe_header)) { printf("[|pppoe]"); return; } - if(eflag) - { + pppoe_sid = EXTRACT_16BITS(p + 2); + pppoe_len = EXTRACT_16BITS(p + 4); + + if (eflag) { printf("\n\tcode "); switch (p[1]) { case PPPOE_CODE_PADI: @@ -724,82 +1198,36 @@ ppp_ether_if_print(user, h, p) printf("Unknown(0x%02x)", p[1]); break; } - } - - pppoe_sid = EXTRACT_16BITS(p + 2); - pppoe_len = EXTRACT_16BITS(p + 4); - - if(eflag) - printf(", version %d, type %d, id 0x%04x, length %d", + printf(", version %d, type %d, id 0x%04x, length %d\n\t", (p[0] & 0xf), (p[0] & 0xf0) >> 4, pppoe_sid, pppoe_len); - - length -= sizeof(struct pppoe_header); - caplen -= sizeof(struct pppoe_header); - p += sizeof(struct pppoe_header); - - if (pppoe_len > caplen) - pppoe_len = caplen; - - if (pppoe_len < 2) { - printf("[|pppoe]"); - return; } - proto = EXTRACT_16BITS(p); - for (i = sizeof(protonames)/sizeof(protonames[0]) - 1; i >= 0; i--) { - if (proto == protonames[i].protocol) { - if (eflag) - printf("\n\t%s: ", protonames[i].name); - switch (proto) { - case PPP_LCP: - handle_lcp(p - 2, length + 2); - break; - case PPP_CHAP: - handle_chap(p - 2, length + 2); - break; - case PPP_PAP: - handle_pap(p - 2, length + 2); - break; - case PPP_IPCP: - handle_ipcp(p - 2, length + 2); - break; - case PPP_IPV6CP: - handle_ipv6cp(p - 2, length + 2); - break; - case PPP_IP: - ip_print(p + 2, length - 2); - break; - case PPP_IPV6: - ip6_print(p + 2, length - 2); - break; - case PPP_IPX: - ipx_print(p + 2, length - 2); - } - break; - } - } - if (i < 0) - printf("\n\t%04x: ", proto); + if (length < pppoe_len) { + (void)printf(" truncated-pppoe - %d bytes missing!", + pppoe_len - length); + pppoe_len = length; + } + + ppp_print(p + sizeof(struct pppoe_header), pppoe_len); if (xflag) - default_print(p + 2, caplen - 2); + default_print(p, h->caplen); + putchar('\n'); } int -pppoe_if_print(u_short ethertype, const u_char *p, u_int length, u_int caplen) +pppoe_if_print(u_short ethertype, const u_char *p, u_int length, u_int l) { - u_int16_t pppoe_sid, pppoe_len; + uint16_t pppoe_sid, pppoe_len; if (ethertype == ETHERTYPE_PPPOEDISC) printf("PPPoE-Discovery"); else printf("PPPoE-Session"); - if (caplen < sizeof(struct pppoe_header)) { - printf("[|pppoe]"); - return (1); - } + if (l < sizeof(struct pppoe_header)) + goto trunc; printf("\n\tcode "); switch (p[1]) { @@ -831,31 +1259,33 @@ pppoe_if_print(u_short ethertype, const u_char *p, u_int length, u_int caplen) printf(", version %d, type %d, id 0x%04x, length %d", (p[0] & 0xf), (p[0] & 0xf0) >> 4, pppoe_sid, pppoe_len); - length -= sizeof(struct pppoe_header); - caplen -= sizeof(struct pppoe_header); p += sizeof(struct pppoe_header); + l -= sizeof(struct pppoe_header); + length -= sizeof(struct pppoe_header); - if (pppoe_len > caplen) - pppoe_len = caplen; + if (length < pppoe_len) { + (void)printf(" truncated-pppoe - %d bytes missing!", + pppoe_len - length); + pppoe_len = length; + } + + if (l > pppoe_len) + l = pppoe_len; if (ethertype == ETHERTYPE_PPPOEDISC) { - while (pppoe_len > 0) { + while (l > 0) { u_int16_t t_type, t_len; - if (pppoe_len < 4) { - printf("\n\t[|pppoe]"); - break; - } + if (l < 4) + goto trunc; t_type = EXTRACT_16BITS(p); t_len = EXTRACT_16BITS(p + 2); - pppoe_len -= 4; p += 4; + l -= 4; - if (pppoe_len < t_len) { - printf("\n\t[|pppoe]"); - break; - } + if (l < t_len) + goto trunc; printf("\n\ttag "); switch (t_type) { @@ -905,57 +1335,82 @@ pppoe_if_print(u_short ethertype, const u_char *p, u_int length, u_int caplen) printf("\\%03o", p[t_type]); } } - pppoe_len -= t_len; p += t_len; + l -= t_len; } + } else if (ethertype == ETHERTYPE_PPPOE) { + printf("\n\t"); + ppp_print(p, pppoe_len); } - else if (ethertype == ETHERTYPE_PPPOE) { - u_int16_t proto; - int i; - if (pppoe_len < 2) { - printf("[|pppoe]"); - return (1); - } - proto = EXTRACT_16BITS(p); + return (1); - for (i = sizeof(protonames)/sizeof(protonames[0]) - 1; i >= 0; - i--) { - if (proto == protonames[i].protocol) { - printf("\n\t%s: ", protonames[i].name); - switch (proto) { - case PPP_LCP: - handle_lcp(p - 2, length + 2); - break; - case PPP_CHAP: - handle_chap(p - 2, length + 2); - break; - case PPP_PAP: - handle_pap(p - 2, length + 2); - break; - case PPP_IPCP: - handle_ipcp(p - 2, length + 2); - break; - case PPP_IPV6CP: - handle_ipv6cp(p - 2, length + 2); - break; - case PPP_IP: - ip_print(p + 2, length - 2); - break; - case PPP_IPV6: - ip6_print(p + 2, length - 2); - break; - case PPP_IPX: - ipx_print(p + 2, length - 2); - } - break; - } +trunc: + printf("[|pppoe]"); + return (1); +} + +void +ppp_hdlc_print(const u_char *p, u_int length) +{ + uint8_t address, control; + int l; + + l = snapend - p; + + if (l < sizeof(address) + sizeof(control)) + goto trunc; + + address = p[0]; + control = p[1]; + + p += sizeof(address) + sizeof(control); + l -= sizeof(address) + sizeof(control); + length -= sizeof(address) + sizeof(control); + + switch (address) { + case 0xff: /* All-Stations */ + if (eflag) + printf("%02x %02x %u ", address, control, length); + + if (control != 0x3) { + printf(" discard"); + break; } - if (i < 0) - printf("\n\t%04x: ", proto); + + ppp_print(p, length); + break; + + default: + printf("ppp address 0x%02x unknown", address); + break; } + return; - return (1); +trunc: + printf("[|ppp]"); +} + +void +ppp_hdlc_if_print(u_char *user, const struct pcap_pkthdr *h, + const u_char *p) +{ + int l = h->caplen; + + packetp = p; + snapend = p + l; + + ts_print(&h->ts); + + if (eflag) + printf("PPP "); + + ppp_hdlc_print(p, h->len); + + if (xflag) + default_print(p, l); + + printf("\n"); } #else diff --git a/usr.sbin/tcpdump/tcpdump.c b/usr.sbin/tcpdump/tcpdump.c index c40a8f4ed37..4fd60fc152e 100644 --- a/usr.sbin/tcpdump/tcpdump.c +++ b/usr.sbin/tcpdump/tcpdump.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcpdump.c,v 1.82 2018/02/03 13:39:48 mpi Exp $ */ +/* $OpenBSD: tcpdump.c,v 1.83 2018/02/06 03:07:51 dlg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -115,6 +115,7 @@ static struct printer printers[] = { { sl_if_print, DLT_SLIP }, { sl_bsdos_if_print, DLT_SLIP_BSDOS }, { ppp_if_print, DLT_PPP }, + { ppp_hdlc_if_print, DLT_PPP_SERIAL }, { fddi_if_print, DLT_FDDI }, { null_if_print, DLT_NULL }, { raw_if_print, DLT_RAW }, -- 2.20.1