]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Apply the first step of the new way to update the link-layer header length
authorFrancois-Xavier Le Bail <[email protected]>
Thu, 26 Dec 2019 21:08:03 +0000 (22:08 +0100)
committerFrancois-Xavier Le Bail <[email protected]>
Sun, 2 Feb 2020 13:15:24 +0000 (14:15 +0100)
Currently the return value of link-layer dissectors is supposed to be
the length of the link-layer header, so that it can be skipped for -x
and -X.

If a link-layer dissector or a called function throws an exception, it
returns no value, so that length isn't available.

The goal is to change all the link-layer dissectors to be void functions
and dissectors should update a new field of the netdissect_options
structure "link-layer header length" rather than returning it as a value.

In this transition process, the link-layer dissectors will be moved, when
updated, from the uint_printers[] array (named before printers[]) to the
void_printers[] array.

In this transition process, a new field of the netdissect_options
structure, ndo_void_printer (TRUE/FALSE), set in the updated function
lookup_printer(), will permit to choose between the old and new way to
update the link-layer header length.

netdissect.h
print-pktap.c
print-ppi.c
print.c
print.h

index c25e8cbeae034084e1347992a15c8a1b800c087c..64b86d4f456ffb8de97e277aadb116fa0179697b 100644 (file)
@@ -164,7 +164,15 @@ typedef struct netdissect_options netdissect_options;
 
 #define IF_PRINTER_ARGS (netdissect_options *, const struct pcap_pkthdr *, const u_char *)
 
-typedef u_int (*if_printer) IF_PRINTER_ARGS;
+typedef u_int (*uint_if_printer) IF_PRINTER_ARGS;
+typedef void  (*void_if_printer) IF_PRINTER_ARGS;
+
+/* pointer to the uint_if_printer or the void_if_printer function */
+typedef union {
+       uint_if_printer uint_printer;
+       void_if_printer void_printer;
+       void* printer;          /* generic when testing if NULL or not */
+} if_printer_t;
 
 /*
  * In case the data in a buffer needs to be processed by being decrypted,
@@ -227,6 +235,7 @@ struct netdissect_options {
   int   ndo_packettype;        /* as specified by -T */
 
   int   ndo_snaplen;
+  int   ndo_ll_header_length;  /* link-layer header length */
 
   /*global pointers to beginning and end of current packet (during printing) */
   const u_char *ndo_packetp;
@@ -235,8 +244,9 @@ struct netdissect_options {
   /* stack of saved packet boundary and buffer information */
   struct netdissect_saved_packet_info *ndo_packet_info_stack;
 
-  /* pointer to the if_printer function */
-  if_printer ndo_if_printer;
+  /* pointer to the uint_if_printer or the void_if_printer function */
+  if_printer_t ndo_if_printer;
+  int ndo_void_printer; /* void_if_printer ? (FALSE/TRUE) */
 
   /* pointer to void function to output stuff */
   void (*ndo_default_print)(netdissect_options *,
@@ -443,7 +453,9 @@ extern int unaligned_memcmp(const void *, const void *, size_t);
 extern const char *tok2strary_internal(const char **, int, const char *, int);
 #define        tok2strary(a,f,i) tok2strary_internal(a, sizeof(a)/sizeof(a[0]),f,i)
 
-extern if_printer lookup_printer(int);
+extern uint_if_printer lookup_uint_printer(int);
+extern void_if_printer lookup_void_printer(int);
+extern if_printer_t lookup_printer(netdissect_options *, int);
 
 #define ND_DEBUG {printf(" [%s:%d %s] ", __FILE__, __LINE__, __FUNCTION__); fflush(stdout);}
 
index af3b3973aa7296b648ea2825c1875a2b766d95ca..182378ef775882b6264d764076fd72958a9352e2 100644 (file)
@@ -102,7 +102,7 @@ pktap_if_print(netdissect_options *ndo,
        uint32_t dlt, hdrlen, rectype;
        u_int caplen = h->caplen;
        u_int length = h->len;
-       if_printer printer;
+       if_printer_t printer;
        const pktap_header_t *hdr;
        struct pcap_pkthdr nhdr;
 
@@ -145,11 +145,16 @@ pktap_if_print(netdissect_options *ndo,
                break;
 
        case PKT_REC_PACKET:
-               if ((printer = lookup_printer(dlt)) != NULL) {
+               printer = lookup_printer(ndo, dlt);
+               if (printer.printer != NULL) {
                        nhdr = *h;
                        nhdr.caplen = caplen;
                        nhdr.len = length;
-                       hdrlen += printer(ndo, &nhdr, p);
+                       if (ndo->ndo_void_printer == TRUE) {
+                               printer.void_printer(ndo, &nhdr, p);
+                               hdrlen += ndo->ndo_ll_header_length;
+                       } else
+                               hdrlen += printer.uint_printer(ndo, &nhdr, p);
                } else {
                        if (!ndo->ndo_eflag)
                                pktap_header_print(ndo, (const u_char *)hdr,
index 8f47fcfcd7848cc337e1f3fc44749a326f6c165f..fe85fa51e699136d760f8bf131686ee0ec9c6606 100644 (file)
@@ -54,7 +54,7 @@ static u_int
 ppi_print(netdissect_options *ndo,
          const struct pcap_pkthdr *h, const u_char *p)
 {
-       if_printer printer;
+       if_printer_t printer;
        const ppi_header_t *hdr;
        u_int caplen = h->caplen;
        u_int length = h->len;
@@ -94,11 +94,16 @@ ppi_print(netdissect_options *ndo,
        caplen -= len;
        p += len;
 
-       if ((printer = lookup_printer(dlt)) != NULL) {
+       printer = lookup_printer(ndo, dlt);
+       if (printer.printer != NULL) {
                nhdr = *h;
                nhdr.caplen = caplen;
                nhdr.len = length;
-               hdrlen = printer(ndo, &nhdr, p);
+               if (ndo->ndo_void_printer == TRUE) {
+                       printer.void_printer(ndo, &nhdr, p);
+                       hdrlen = ndo->ndo_ll_header_length;
+               } else
+                       hdrlen = printer.uint_printer(ndo, &nhdr, p);
        } else {
                if (!ndo->ndo_eflag)
                        ppi_header_print(ndo, (const u_char *)hdr, length + len);
diff --git a/print.c b/print.c
index 418658ea5d4b9c6c356bea9dbf92c0dda77bf001..e272ce9ae89d5accf7feacb5336d8afc25733d99 100644 (file)
--- a/print.c
+++ b/print.c
 
 #include "pcap-missing.h"
 
-struct printer {
-       if_printer f;
+struct uint_printer {
+       uint_if_printer f;
        int type;
 };
 
-static const struct printer printers[] = {
+struct void_printer {
+       void_if_printer f;
+       int type;
+};
+
+static const struct uint_printer uint_printers[] = {
        { ether_if_print,       DLT_EN10MB },
 #ifdef DLT_IPNET
        { ipnet_if_print,       DLT_IPNET },
@@ -249,6 +254,10 @@ static const struct printer printers[] = {
        { NULL,                 0 },
 };
 
+static const struct void_printer void_printers[] = {
+       { NULL,                 0 },
+};
+
 static void    ndo_default_print(netdissect_options *ndo, const u_char *bp,
                    u_int length);
 
@@ -272,12 +281,49 @@ init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask)
        init_checksum();
 }
 
-if_printer
-lookup_printer(int type)
+uint_if_printer
+lookup_uint_printer(int type)
+{
+       const struct uint_printer *p;
+
+       for (p = uint_printers; p->f; ++p)
+               if (type == p->type)
+                       return p->f;
+
+#if defined(DLT_USER2) && defined(DLT_PKTAP)
+       /*
+        * Apple incorrectly chose to use DLT_USER2 for their PKTAP
+        * header.
+        *
+        * We map DLT_PKTAP, whether it's DLT_USER2 as it is on Darwin-
+        * based OSes or the same value as LINKTYPE_PKTAP as it is on
+        * other OSes, to LINKTYPE_PKTAP, so files written with
+        * this version of libpcap for a DLT_PKTAP capture have a link-
+        * layer header type of LINKTYPE_PKTAP.
+        *
+        * However, files written on OS X Mavericks for a DLT_PKTAP
+        * capture have a link-layer header type of LINKTYPE_USER2.
+        * If we don't have a printer for DLT_USER2, and type is
+        * DLT_USER2, we look up the printer for DLT_PKTAP and use
+        * that.
+        */
+       if (type == DLT_USER2) {
+               for (p = uint_printers; p->f; ++p)
+                       if (DLT_PKTAP == p->type)
+                               return p->f;
+       }
+#endif
+
+       return NULL;
+       /* NOTREACHED */
+}
+
+void_if_printer
+lookup_void_printer(int type)
 {
-       const struct printer *p;
+       const struct void_printer *p;
 
-       for (p = printers; p->f; ++p)
+       for (p = void_printers; p->f; ++p)
                if (type == p->type)
                        return p->f;
 
@@ -299,7 +345,7 @@ lookup_printer(int type)
         * that.
         */
        if (type == DLT_USER2) {
-               for (p = printers; p->f; ++p)
+               for (p = void_printers; p->f; ++p)
                        if (DLT_PKTAP == p->type)
                                return p->f;
        }
@@ -309,20 +355,35 @@ lookup_printer(int type)
        /* NOTREACHED */
 }
 
+if_printer_t
+lookup_printer(netdissect_options *ndo, int type)
+{
+       if_printer_t printer;
+
+       printer.void_printer = lookup_void_printer(type);
+       ndo->ndo_void_printer = TRUE;
+       if (printer.void_printer == NULL) {
+               printer.uint_printer = lookup_uint_printer(type);
+               ndo->ndo_void_printer = FALSE;
+       }
+       return printer;
+}
+
 int
 has_printer(int type)
 {
-       return (lookup_printer(type) != NULL);
+       return (lookup_void_printer(type) != NULL ||
+               lookup_uint_printer(type) != NULL);
 }
 
-if_printer
+if_printer_t
 get_if_printer(netdissect_options *ndo, int type)
 {
        const char *dltname;
-       if_printer printer;
+       if_printer_t printer;
 
-       printer = lookup_printer(type);
-       if (printer == NULL) {
+       printer = lookup_printer(ndo, type);
+       if (printer.printer == NULL) {
                dltname = pcap_datalink_val_to_name(type);
                if (dltname != NULL)
                        (*ndo->ndo_error)(ndo, S_ERR_ND_NO_PRINTER,
@@ -339,7 +400,7 @@ void
 pretty_print_packet(netdissect_options *ndo, const struct pcap_pkthdr *h,
                    const u_char *sp, u_int packets_captured)
 {
-       u_int hdrlen = 0;
+       u_int hdrlen;
        int invalid_header = 0;
 
        if (ndo->ndo_packet_number)
@@ -409,12 +470,18 @@ pretty_print_packet(netdissect_options *ndo, const struct pcap_pkthdr *h,
        ndo->ndo_snapend = sp + h->caplen;
 
        ndo->ndo_protocol = "";
+       ndo->ndo_ll_header_length = 0;
        if (setjmp(ndo->ndo_truncated) == 0) {
                /* Print the packet. */
-               hdrlen = (ndo->ndo_if_printer)(ndo, h, sp);
+               if (ndo->ndo_void_printer == TRUE) {
+                       (ndo->ndo_if_printer.void_printer)(ndo, h, sp);
+                       hdrlen = ndo->ndo_ll_header_length;
+               } else
+                       hdrlen = (ndo->ndo_if_printer.uint_printer)(ndo, h, sp);
        } else {
                /* A printer quit because the packet was truncated; report it */
                ND_PRINT(" [|%s]", ndo->ndo_protocol);
+               hdrlen = ndo->ndo_ll_header_length;
        }
 
        /*
diff --git a/print.h b/print.h
index 70ea9f8e821e781abe64aec2fd609908fa245294..5e67b33a782826a58f7015db696004cb55234a29 100644 (file)
--- a/print.h
+++ b/print.h
@@ -32,7 +32,7 @@ void  init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask);
 
 int    has_printer(int type);
 
-if_printer get_if_printer(netdissect_options *ndo, int type);
+if_printer_t get_if_printer(netdissect_options *ndo, int type);
 
 void   pretty_print_packet(netdissect_options *ndo,
            const struct pcap_pkthdr *h, const u_char *sp,