-struct tok ppptype2str[] = {
- { PPP_IP, "IP" },
- { PPP_OSI, "OSI" },
- { PPP_NS, "NS" },
- { PPP_DECNET, "DECNET" },
- { PPP_APPLE, "APPLE" },
- { PPP_IPX, "IPX" },
- { PPP_VJC, "VJC" },
- { PPP_VJNC, "VJNC" },
- { PPP_BRPDU, "BRPDU" },
- { PPP_STII, "STII" },
- { PPP_VINES, "VINES" },
-
- { PPP_HELLO, "HELLO" },
- { PPP_LUXCOM, "LUXCOM" },
- { PPP_SNS, "SNS" },
- { PPP_IPCP, "IPCP" },
- { PPP_OSICP, "OSICP" },
- { PPP_NSCP, "NSCP" },
- { PPP_DECNETCP, "DECNETCP" },
- { PPP_APPLECP, "APPLECP" },
- { PPP_IPXCP, "IPXCP" },
- { PPP_STIICP, "STIICP" },
- { PPP_VINESCP, "VINESCP" },
-
- { PPP_LCP, "LCP" },
- { PPP_PAP, "PAP" },
- { PPP_LQM, "LQM" },
- { PPP_CHAP, "CHAP" },
- { 0, NULL }
-};
+/* Standard PPP printer */
+u_int
+ppp_print(register const u_char *p, u_int length)
+{
+ u_int proto;
+ u_int olen = length; /* _o_riginal length */
+ u_int hdr_len = 0;
+
+ /*
+ * Here, we assume that p points to the Address and Control
+ * field (if they present).
+ */
+ if (length < 2)
+ goto trunc;
+ TCHECK2(*p, 2);
+ if (*p == PPP_ADDRESS && *(p + 1) == PPP_CONTROL) {
+ p += 2; /* ACFC not used */
+ length -= 2;
+ hdr_len += 2;
+ }
+
+ if (length < 2)
+ goto trunc;
+ TCHECK(*p);
+ if (*p % 2) {
+ proto = *p; /* PFC is used */
+ p++;
+ length--;
+ hdr_len++;
+ } else {
+ TCHECK2(*p, 2);
+ proto = EXTRACT_16BITS(p);
+ p += 2;
+ length -= 2;
+ hdr_len += 2;
+ }
+
+ if (eflag)
+ printf("%s (0x%04x), length %u: ",
+ tok2str(ppptype2str, "unknown", proto),
+ proto,
+ olen);
+
+ handle_ppp(proto, p, length);
+ return (hdr_len);
+trunc:
+ printf("[|ppp]");
+ return (0);
+}
+
+
+/* PPP I/F printer */
+u_int
+ppp_if_print(const struct pcap_pkthdr *h, register const u_char *p)
+{
+ register u_int length = h->len;
+ register u_int caplen = h->caplen;
+
+ if (caplen < PPP_HDRLEN) {
+ printf("[|ppp]");
+ return (caplen);
+ }
+
+#if 0
+ /*
+ * XXX: seems to assume that there are 2 octets prepended to an
+ * actual PPP frame. The 1st octet looks like Input/Output flag
+ * while 2nd octet is unknown, at least to me
+ *
+ * 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
+ * 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]);
+#endif
+
+ ppp_print(p, length);
+
+ return (0);
+}
+
+/*
+ * 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.
+ */
+u_int
+ppp_hdlc_if_print(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;
+ u_int hdrlen = 0;
+
+ if (caplen < 2) {
+ printf("[|ppp]");
+ return (caplen);
+ }
+
+ switch (p[0]) {
+
+ case PPP_ADDRESS:
+ if (caplen < 4) {
+ printf("[|ppp]");
+ return (caplen);
+ }
+
+ if (eflag)
+ printf("%02x %02x %d ", p[0], p[1], length);
+ p += 2;
+ length -= 2;
+ hdrlen += 2;
+
+ proto = EXTRACT_16BITS(p);
+ p += 2;
+ length -= 2;
+ hdrlen += 2;
+ printf("%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));
+
+ handle_ppp(proto, p, length);
+ break;
+
+ case CHDLC_UNICAST:
+ case CHDLC_BCAST:
+ return (chdlc_if_print(h, p));
+
+ default:
+ if (eflag)
+ printf("%02x %02x %d ", p[0], p[1], length);
+ p += 2;
+ length -= 2;
+ hdrlen += 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;
+ }
+
+ return (hdrlen);
+}