]> The Tcpdump Group git mirrors - tcpdump/commitdiff
DLT_LINUX_SLL2 support.
authorGuy Harris <[email protected]>
Thu, 12 Jul 2018 18:49:28 +0000 (11:49 -0700)
committerGuy Harris <[email protected]>
Thu, 12 Jul 2018 18:49:38 +0000 (11:49 -0700)
netdissect.h
print-sll.c
print.c

index 4f3c666adc41cfe562175fdbd6d99dae8777f8c9..93fa8be6514405333709df7b6bf5e814181ba5e3 100644 (file)
@@ -465,6 +465,7 @@ extern u_int raw_if_print IF_PRINTER_ARGS;
 extern u_int sl_bsdos_if_print IF_PRINTER_ARGS;
 extern u_int sl_if_print IF_PRINTER_ARGS;
 extern u_int sll_if_print IF_PRINTER_ARGS;
+extern u_int sll2_if_print IF_PRINTER_ARGS;
 extern u_int sunatm_if_print IF_PRINTER_ARGS;
 extern u_int symantec_if_print IF_PRINTER_ARGS;
 extern u_int token_if_print IF_PRINTER_ARGS;
index 571b7c5e5a1967edf1a4a2dad5f84b4dbd925ec3..5a4e2f687031d62c423ad56b75cb85ba2ef308d9 100644 (file)
@@ -84,6 +84,21 @@ struct sll_header {
        nd_uint16_t     sll_protocol;   /* protocol */
 };
 
+/*
+ * A DLT_LINUX_SLL2 fake link-layer header.
+ */
+#define SLL2_HDR_LEN   20              /* total header length */
+
+struct sll2_header {
+       nd_uint16_t     sll2_protocol;          /* protocol */
+       nd_uint16_t     sll2_reserved_mbz;      /* reserved - must be zero */
+       nd_uint32_t     sll2_if_index;          /* 1-based interface index */
+       nd_uint16_t     sll2_hatype;            /* link-layer address type */
+       nd_uint8_t      sll2_pkttype;           /* packet type */
+       nd_uint8_t      sll2_halen;             /* link-layer address length */
+       nd_byte         sll2_addr[SLL_ADDRLEN]; /* link-layer address */
+};
+
 /*
  * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
  * PACKET_ values on Linux, but are defined here so that they're
@@ -308,3 +323,183 @@ recurse:
 
        return (hdrlen);
 }
+
+static void
+sll2_print(netdissect_options *ndo, const struct sll2_header *sllp, u_int length)
+{
+       u_short ether_type;
+
+       ndo->ndo_protocol = "sll2";
+        ND_PRINT("%3s ",tok2str(sll_pkttype_values,"?",EXTRACT_BE_U_2(sllp->sll2_pkttype)));
+
+       /*
+        * XXX - check the link-layer address type value?
+        * For now, we just assume 6 means Ethernet.
+        * XXX - print others as strings of hex?
+        */
+       if (EXTRACT_U_1(sllp->sll2_halen) == 6)
+               ND_PRINT("%s ", etheraddr_string(ndo, sllp->sll2_addr));
+
+       if (!ndo->ndo_qflag) {
+               ether_type = EXTRACT_BE_U_2(sllp->sll2_protocol);
+
+               if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
+                       /*
+                        * Not an Ethernet type; what type is it?
+                        */
+                       switch (ether_type) {
+
+                       case LINUX_SLL_P_802_3:
+                               /*
+                                * Ethernet_802.3 IPX frame.
+                                */
+                               ND_PRINT("802.3");
+                               break;
+
+                       case LINUX_SLL_P_802_2:
+                               /*
+                                * 802.2.
+                                */
+                               ND_PRINT("802.2");
+                               break;
+
+                       default:
+                               /*
+                                * What is it?
+                                */
+                               ND_PRINT("ethertype Unknown (0x%04x)",
+                                   ether_type);
+                               break;
+                       }
+               } else {
+                       ND_PRINT("ethertype %s (0x%04x)",
+                           tok2str(ethertype_values, "Unknown", ether_type),
+                           ether_type);
+               }
+               ND_PRINT(", length %u: ", length);
+       }
+}
+
+/*
+ * This is the top level routine of the printer.  'p' points to the
+ * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
+ * 'h->len' is the length of the packet off the wire, and 'h->caplen'
+ * is the number of bytes actually captured.
+ */
+u_int
+sll2_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
+{
+       u_int caplen = h->caplen;
+       u_int length = h->len;
+       const struct sll2_header *sllp;
+       u_short ether_type;
+       int llc_hdrlen;
+       u_int hdrlen;
+
+       ndo->ndo_protocol = "sll2_if";
+       if (caplen < SLL2_HDR_LEN) {
+               /*
+                * XXX - this "can't happen" because "pcap-linux.c" always
+                * adds this many bytes of header to every packet in a
+                * cooked socket capture.
+                */
+               nd_print_trunc(ndo);
+               return (caplen);
+       }
+
+       sllp = (const struct sll2_header *)p;
+
+       if (ndo->ndo_eflag)
+               sll2_print(ndo, sllp, length);
+
+       /*
+        * Go past the cooked-mode header.
+        */
+       length -= SLL2_HDR_LEN;
+       caplen -= SLL2_HDR_LEN;
+       p += SLL2_HDR_LEN;
+       hdrlen = SLL2_HDR_LEN;
+
+       ether_type = EXTRACT_BE_U_2(sllp->sll2_protocol);
+
+recurse:
+       /*
+        * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
+        * packet type?
+        */
+       if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
+               /*
+                * Yes - what type is it?
+                */
+               switch (ether_type) {
+
+               case LINUX_SLL_P_802_3:
+                       /*
+                        * Ethernet_802.3 IPX frame.
+                        */
+                       ipx_print(ndo, p, length);
+                       break;
+
+               case LINUX_SLL_P_802_2:
+                       /*
+                        * 802.2.
+                        * Try to print the LLC-layer header & higher layers.
+                        */
+                       llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
+                       if (llc_hdrlen < 0)
+                               goto unknown;   /* unknown LLC type */
+                       hdrlen += llc_hdrlen;
+                       break;
+
+               default:
+                       /*FALLTHROUGH*/
+
+               unknown:
+                       /* packet type not known, print raw packet */
+                       if (!ndo->ndo_suppress_default_print)
+                               ND_DEFAULTPRINT(p, caplen);
+                       break;
+               }
+       } else if (ether_type == ETHERTYPE_8021Q) {
+               /*
+                * Print VLAN information, and then go back and process
+                * the enclosed type field.
+                */
+               if (caplen < 4) {
+                       ND_PRINT("[|vlan]");
+                       return (hdrlen + caplen);
+               }
+               if (length < 4) {
+                       ND_PRINT("[|vlan]");
+                       return (hdrlen + length);
+               }
+               if (ndo->ndo_eflag) {
+                       uint16_t tag = EXTRACT_BE_U_2(p);
+
+                       ND_PRINT("%s, ", ieee8021q_tci_string(tag));
+               }
+
+               ether_type = EXTRACT_BE_U_2(p + 2);
+               if (ether_type <= MAX_ETHERNET_LENGTH_VAL)
+                       ether_type = LINUX_SLL_P_802_2;
+               if (!ndo->ndo_qflag) {
+                       ND_PRINT("ethertype %s, ",
+                           tok2str(ethertype_values, "Unknown", ether_type));
+               }
+               p += 4;
+               length -= 4;
+               caplen -= 4;
+               hdrlen += 4;
+               goto recurse;
+       } else {
+               if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
+                       /* ether_type not known, print raw packet */
+                       if (!ndo->ndo_eflag)
+                               sll2_print(ndo, sllp, length + SLL_HDR_LEN);
+                       if (!ndo->ndo_suppress_default_print)
+                               ND_DEFAULTPRINT(p, caplen);
+               }
+       }
+
+       return (hdrlen);
+}
diff --git a/print.c b/print.c
index b9c92adc2eea0f81362a0521b45860d04e2a74d1..4cc35bab980d0789cf3f101aee1ef036b7115982 100644 (file)
--- a/print.c
+++ b/print.c
@@ -126,6 +126,9 @@ static const struct printer printers[] = {
 #ifdef DLT_LINUX_SLL
        { sll_if_print,         DLT_LINUX_SLL },
 #endif
+#ifdef DLT_LINUX_SLL2
+       { sll2_if_print,        DLT_LINUX_SLL2 },
+#endif
 #ifdef DLT_FR
        { fr_if_print,          DLT_FR },
 #endif