X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/8e045dcd4935a465d67d80d9afdc936a87d8e170..f243e70b91b9a25a4cda052f37f48fb5aa49bf39:/print-ppp.c?ds=sidebyside diff --git a/print-ppp.c b/print-ppp.c index 9332bcde..8ba6710b 100644 --- a/print-ppp.c +++ b/print-ppp.c @@ -31,7 +31,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.42 2000-08-18 08:20:10 itojun Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.57 2000-12-04 06:47:18 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -40,35 +40,25 @@ static const char rcsid[] = #include #include -#include -#include -#include -struct mbuf; -struct rtentry; -#include +#ifdef __bsdi__ +#include +#include +#endif #include -#include -#include -#include #include #include #include #include -#ifdef __bsdi__ -#include -#include -#endif #include "interface.h" #include "extract.h" #include "addrtoname.h" #include "ppp.h" - -/* XXX This goes somewhere else. */ -#define PPP_HDRLEN 4 +#include "chdlc.h" +#include "ethertype.h" /* * The following constatns are defined by IANA. Please refer to @@ -339,16 +329,16 @@ static const char *papcode[] = { #define BAP_CSIND 7 #define BAP_CSRES 8 -static const char *ppp_protoname __P((u_int proto)); -static void handle_ctrl_proto __P((u_int proto,const u_char *p, int length)); -static void handle_chap __P((const u_char *p, int length)); -static void handle_pap __P((const u_char *p, int length)); -static void handle_bap __P((const u_char *p, int length)); -static int print_lcp_config_options __P((const u_char *p, int)); -static int print_ipcp_config_options __P((const u_char *p, int)); -static int print_ccp_config_options __P((const u_char *p, int)); -static int print_bacp_config_options __P((const u_char *p, int)); -static void handle_ppp __P((u_int proto, const u_char *p, int length)); +static const char *ppp_protoname (u_int proto); +static void handle_ctrl_proto (u_int proto,const u_char *p, int length); +static void handle_chap (const u_char *p, int length); +static void handle_pap (const u_char *p, int length); +static void handle_bap (const u_char *p, int length); +static int print_lcp_config_options (const u_char *p, int); +static int print_ipcp_config_options (const u_char *p, int); +static int print_ccp_config_options (const u_char *p, int); +static int print_bacp_config_options (const u_char *p, int); +static void handle_ppp (u_int proto, const u_char *p, int length); static const char * ppp_protoname(u_int proto) @@ -360,42 +350,24 @@ ppp_protoname(u_int proto) #ifdef PPP_XNS case PPP_XNS: return "XNS"; #endif -#ifdef PPP_IPX case PPP_IPX: return "IPX"; -#endif + case PPP_VJC: return "VJC"; + case PPP_VJNC: return "VJNC"; #ifdef PPP_COMP case PPP_COMP: return "COMP"; #endif -#ifdef PPP_IPCP case PPP_IPCP: return "IPCP"; -#endif -#ifdef PPP_IPV6CP case PPP_IPV6CP: return "IPV6CP"; -#endif -#ifdef PPP_IPXCP case PPP_IPXCP: return "IPXCP"; -#endif -#ifdef PPP_CCP case PPP_CCP: return "CCP"; -#endif -#ifdef PPP_LCP case PPP_LCP: return "LCP"; -#endif -#ifdef PPP_PAP case PPP_PAP: return "PAP"; -#endif #ifdef PPP_LQR case PPP_LQR: return "LQR"; #endif -#ifdef PPP_CHAP case PPP_CHAP: return "CHAP"; -#endif -#ifdef PPP_BACP case PPP_BACP: return "BACP"; -#endif -#ifdef PPP_BAP case PPP_BAP: return "BAP"; -#endif default: snprintf(buf, sizeof(buf), "unknown-0x%04x", proto); return buf; @@ -464,6 +436,14 @@ handle_ctrl_proto(u_int proto, const u_char *p, int length) case PPP_BACP: pfunc = print_bacp_config_options; break; + default: + /* + * This should never happen, but we set + * "pfunc" to squelch uninitialized + * variable warnings from compilers. + */ + pfunc = NULL; + break; } if ((j = (*pfunc)(p, len)) == 0) break; @@ -512,7 +492,6 @@ static int print_lcp_config_options(const u_char *p, int length) { int len, opt; - int i; if (length < 2) return 0; @@ -754,7 +733,7 @@ handle_chap(const u_char *p, int length) } } -/* PAP */ +/* PAP (see RFC 1334) */ static void handle_pap(const u_char *p, int length) { @@ -773,7 +752,6 @@ handle_pap(const u_char *p, int length) } code = *p; - if (length < 4) if ((code >= PAP_CODEMIN) && (code <= PAP_CODEMAX)) printf("%s", papcode[code - 1]); else { @@ -816,7 +794,7 @@ handle_pap(const u_char *p, int length) return; msg_len = *p; /* Msg-Length */ p++; - if (length - (p - p0) < passwd_len) + if (length - (p - p0) < msg_len) return; printf(", Msg="); for (i = 0; i< msg_len; i++) @@ -855,7 +833,7 @@ print_ipcp_config_options(const u_char *p, int length) ipaddr_string(p + 6)); break; case IPCPOPT_IPCOMP: - if (len != 4) + if (len < 4) goto invlen; printf(", IP-Comp"); if (EXTRACT_16BITS(p + 2) == PPP_VJC) { @@ -998,6 +976,10 @@ handle_ppp(u_int proto, const u_char *p, int length) ip6_print(p, length); break; #endif + case ETHERTYPE_IPX: /*XXX*/ + case PPP_IPX: + ipx_print(p, length); + break; } } @@ -1006,6 +988,7 @@ void ppp_print(register const u_char *p, u_int length) { u_int proto; + u_int full_length = length; /* * Here, we assume that p points to the Address and Control @@ -1030,7 +1013,7 @@ ppp_print(register const u_char *p, u_int length) length -= 2; } - printf("%s: ", ppp_protoname(proto)); + printf("%s %d: ", ppp_protoname(proto), full_length); handle_ppp(proto, p, length); return; @@ -1046,8 +1029,6 @@ ppp_if_print(u_char *user, const struct pcap_pkthdr *h, { register u_int length = h->len; register u_int caplen = h->caplen; - const struct ip *ip; - u_int proto; ts_print(&h->ts); @@ -1070,6 +1051,36 @@ ppp_if_print(u_char *user, const struct pcap_pkthdr *h, * actual PPP frame. The 1st octet looks like Input/Output flag * while 2nd octet is unknown, at least to me * (mshindo@mshindo.net). + * + * That was what the original tcpdump code did. + * + * FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound + * packets and 0 for inbound packets - but only if the + * protocol field has the 0x8000 bit set (i.e., it's a network + * control protocol); it does so before running the packet through + * "bpf_filter" to see if it should be discarded, and to see + * if we should update the time we sent the most recent packet... + * + * ...but it puts the original address field back after doing + * so. + * + * NetBSD's "if_ppp.c" doesn't set the first octet in that fashion. + * + * I don't know if any PPP implementation handed up to a BPF + * device packets with the first octet being 1 for outbound and + * 0 for inbound packets, so I (guy@alum.mit.edu) don't know + * whether that ever needs to be checked or not. + * + * Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP, + * and its tcpdump appears to assume that the frame always + * begins with an address field and a control field, and that + * the address field might be 0x0f or 0x8f, for Cisco + * point-to-point with HDLC framing as per section 4.3.1 of RFC + * 1547, as well as 0xff, for PPP in HDLC-like framing as per + * RFC 1662. + * + * (Is the Cisco framing in question what DLT_C_HDLC, in + * BSD/OS, is?) */ if (eflag) printf("%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1]); @@ -1083,6 +1094,88 @@ out: putchar('\n'); } +/* + * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like + * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547, + * is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL, + * discard them *if* those are the first two octets, and parse the remaining + * packet as a PPP packet, as "ppp_print()" does). + * + * This handles, for example, DLT_PPP_SERIAL in NetBSD. + */ +void +ppp_hdlc_if_print(u_char *user, const struct pcap_pkthdr *h, + register const u_char *p) +{ + register u_int length = h->len; + register u_int caplen = h->caplen; + u_int proto; + + if (caplen < 2) { + printf("[|ppp]"); + goto out; + } + + /* + * 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; + + switch (p[0]) { + + case PPP_ADDRESS: + if (caplen < 4) { + printf("[|ppp]"); + goto out; + } + + ts_print(&h->ts); + if (eflag) + printf("%02x %02x %d ", p[0], p[1], length); + p += 2; + length -= 2; + + proto = EXTRACT_16BITS(p); + p += 2; + length -= 2; + printf("%s: ", ppp_protoname(proto)); + + handle_ppp(proto, p, length); + break; + + case CHDLC_UNICAST: + case CHDLC_BCAST: + /* + * Have the Cisco HDLC print routine do all the work. + */ + chdlc_if_print(user, h, p); + return; + + default: + ts_print(&h->ts); + if (eflag) + printf("%02x %02x %d ", p[0], p[1], length); + p += 2; + length -= 2; + + /* + * XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats + * the next two octets as an Ethernet type; does that + * ever happen? + */ + printf("unknown addr %02x; ctrl %02x", p[0], p[1]); + break; + } + + if (xflag) + default_print(p, caplen); +out: + putchar('\n'); +} + struct tok ppptype2str[] = { @@ -1204,9 +1297,9 @@ ppp_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, printf("] "); } } - if (eflag) - printf("%d ", length); } + if (eflag) + printf("%d ", length); if (p[SLC_CHL]) { q = p + SLC_BPFHDRLEN + p[SLC_LLHL];