]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-ppp.c
The stuff in the "linux-include" directory is no longer needed, as we no
[tcpdump] / print-ppp.c
index 9332bcdeba6bd6c682a1963992b2d223f35fea09..8ba6710bb7e55334d1ca3e95b41c059731e7b079 100644 (file)
@@ -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 <sys/param.h>
 #include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
 
-struct mbuf;
-struct rtentry;
-#include <net/if.h>
+#ifdef __bsdi__
+#include <net/slcompress.h>
+#include <net/if_ppp.h>
+#endif
 
 #include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/if_ether.h>
 
 #include <ctype.h>
 #include <netdb.h>
 #include <pcap.h>
 #include <stdio.h>
-#ifdef __bsdi__
-#include <net/slcompress.h>
-#include <net/if_ppp.h>
-#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
         * ([email protected]).
+        *
+        * 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 ([email protected]) 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];