]> The Tcpdump Group git mirrors - libpcap/commitdiff
Handle the pcap_t+private data in a fashion that makes fewer assumptions.
authorGuy Harris <[email protected]>
Wed, 1 Jul 2020 09:15:40 +0000 (02:15 -0700)
committerGuy Harris <[email protected]>
Wed, 1 Jul 2020 09:15:40 +0000 (02:15 -0700)
The sizeof operator and alignof macro can be given a type "name" that's
anonymous, e.g. sizeof(struct { int a; char *b; }).  Have
pcap_create_common() and pcap_open_offline_common() take, as arguments,
the total size of a structure containing both the pcap_t and the private
data as members, and the offset of the private data in that structure,
and define macros that calculate those given, as an argument, the data
type of the private data.

This avoids making assumptions about the alignment of those two items
within the structure; that *might* fix GitHub issue #940 if the issue is
that the ARM compiler being used does 16-byte alignment of the private
structure, rather than the 8-byte alignment we were wiring in.

30 files changed:
pcap-airpcap.c
pcap-bpf.c
pcap-bt-linux.c
pcap-bt-monitor-linux.c
pcap-dag.c
pcap-dbus.c
pcap-dlpi.c
pcap-dos.c
pcap-dpdk.c
pcap-haiku.cpp
pcap-int.h
pcap-libdlpi.c
pcap-linux.c
pcap-netfilter-linux.c
pcap-netmap.c
pcap-nit.c
pcap-npf.c
pcap-pf.c
pcap-rdmasniff.c
pcap-rpcap.c
pcap-septel.c
pcap-sita.c
pcap-snf.c
pcap-snit.c
pcap-snoop.c
pcap-tc.c
pcap-usb-linux.c
pcap.c
sf-pcap.c
sf-pcapng.c

index 7d7700ced2901c79472e86e2ad50e1dd4fda8eee..4876ec966584038c6ac712c369ecd56a07f4807d 100644 (file)
@@ -991,7 +991,7 @@ airpcap_create(const char *device, char *ebuf, int *is_ours)
         * Yes.
         */
        *is_ours = 1;
-       p = pcap_create_common(ebuf, sizeof (struct pcap_airpcap));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_airpcap);
        if (p == NULL)
                return (NULL);
 
index e2e4e91f9572b71ceadb9b76e1c6e9555cb06bfe..10e3fab4e5af2ddab342ab3f82cf38718e6d1821 100644 (file)
@@ -444,7 +444,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
 {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_bpf));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_bpf);
        if (p == NULL)
                return (NULL);
 
index dbaa92ea46ffa3a39567a50fd2929b7be6018dd3..2969ff8d24292ea4121df5249c07fe045333651c 100644 (file)
@@ -173,7 +173,7 @@ bt_create(const char *device, char *ebuf, int *is_ours)
        /* OK, it's probably ours. */
        *is_ours = 1;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_bt));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_bt);
        if (p == NULL)
                return (NULL);
 
index 7b75b5cc589abf03327afbba5a4a03d8caa480b8..ad4fc375c7c993fef384c4e774dc20629f73a989 100644 (file)
 #define BT_CONTROL_SIZE 32
 #define INTERFACE_NAME "bluetooth-monitor"
 
+/*
+ * Private data.
+ * Currently contains nothing.
+ */
+struct pcap_bt_monitor {
+       int     dummy;
+};
+
 /*
  * Fields and alignment must match the declaration in the Linux kernel 3.4+.
  * See struct hci_mon_hdr in include/net/bluetooth/hci_mon.h.
@@ -256,7 +264,7 @@ bt_monitor_create(const char *device, char *ebuf, int *is_ours)
     }
 
     *is_ours = 1;
-    p = pcap_create_common(ebuf, 0);
+    p = PCAP_CREATE_COMMON(ebuf, struct pcap_bt_monitor);
     if (p == NULL)
         return NULL;
 
index 62f6e649351f649d7cf575dc93dee311fd7cb32c..4df1527434ea6d5a101e547c7ad993951468dd55 100644 (file)
@@ -1071,7 +1071,7 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
        /* OK, it's probably ours. */
        *is_ours = 1;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_dag));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_dag);
        if (p == NULL)
                return NULL;
 
index 24c987a6c9a7c88c78ed11f62ccd50e78ca07498..506f150fa5c597d741902bc03984b0e8c42bac16 100644 (file)
@@ -314,7 +314,7 @@ dbus_create(const char *device, char *ebuf, int *is_ours)
        }
 
        *is_ours = 1;
-       p = pcap_create_common(ebuf, sizeof (struct pcap_dbus));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_dbus);
        if (p == NULL)
                return (NULL);
 
index c43c1b1593a8142481253084d9ff6a96b7372107..abba8aefcdd9bb4a13c58ce09eb43d8064f8303a 100644 (file)
@@ -1880,7 +1880,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
        struct pcap_dlpi *pd;
 #endif
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_dlpi);
        if (p == NULL)
                return (NULL);
 
index 2d897093a3efa490088e0defb9e68f790e7c220e..16f155647f050e24c71c4514c9bd96574fd83447 100644 (file)
@@ -153,7 +153,7 @@ pcap_t *pcap_create_interface (const char *device _U_, char *ebuf)
 {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_dos));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_dos);
        if (p == NULL)
                return (NULL);
 
index b00373f1952fbd0f0f5546450507cd69f27d10bc..837ad1c22ac61b4f28f9a78feffd58ab21015d56 100644 (file)
@@ -972,7 +972,7 @@ pcap_t * pcap_dpdk_create(const char *device, char *ebuf, int *is_ours)
        if (! *is_ours)
                return NULL;
        //memset will happen
-       p = pcap_create_common(ebuf, sizeof(struct pcap_dpdk));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_dpdk);
 
        if (p == NULL)
                return NULL;
index 38aefb76e2b40efc1d935902defdbe68f7ddeeeb..701cac3831ee738da8258437db4f2049796638c2 100644 (file)
@@ -238,8 +238,7 @@ pcap_create_interface(const char *device, char *errorBuffer)
                return NULL;
        }
 
-       pcap_t* handle = pcap_create_common(errorBuffer,
-               sizeof (struct pcap_haiku));
+       pcap_t* handle = PCAP_CREATE_COMMON(errorBuffer, struct pcap_haiku);
        if (handle == NULL) {
                snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "malloc: %s", strerror(errno));
                close(socket);
index 789ad5724c677a98ae906df59374f3e2ccaeb009..f612913e1c648e4b97ea6aa0f231ad2f30577043 100644 (file)
@@ -34,6 +34,8 @@
 #ifndef pcap_int_h
 #define        pcap_int_h
 
+#include <stddef.h>
+
 #include <signal.h>
 
 #include <pcap/pcap.h>
@@ -461,7 +463,19 @@ int        pcap_setnonblock_fd(pcap_t *p, int);
  * by pcap_create routines.
  */
 pcap_t *pcap_create_interface(const char *, char *);
-pcap_t *pcap_create_common(char *, size_t);
+
+/*
+ * This wrapper takes an error buffer pointer and a type to use for the
+ * private data, and calls pcap_create_common(), passing it the error
+ * buffer pointer, the size fo the private data type, in bytes, and the
+ * offset of the private data from the beginning of the structure, in
+ * bytes.
+ */
+#define PCAP_CREATE_COMMON(ebuf, type) \
+       pcap_create_common(ebuf, \
+           sizeof (struct { pcap_t __common; type __private; }), \
+           offsetof (struct { pcap_t __common; type __private; }, __private))
+pcap_t *pcap_create_common(char *, size_t, size_t);
 int    pcap_do_addexit(pcap_t *);
 void   pcap_add_to_pcaps_to_close(pcap_t *);
 void   pcap_remove_from_pcaps_to_close(pcap_t *);
@@ -533,7 +547,20 @@ int        add_addr_to_if(pcap_if_list_t *, const char *, bpf_u_int32,
  * treats the pathname as being in UTF-8, rather than the local
  * code page, on Windows.
  */
-pcap_t *pcap_open_offline_common(char *ebuf, size_t size);
+
+/*
+ * This wrapper takes an error buffer pointer and a type to use for the
+ * private data, and calls pcap_create_common(), passing it the error
+ * buffer pointer, the size fo the private data type, in bytes, and the
+ * offset of the private data from the beginning of the structure, in
+ * bytes.
+ */
+#define PCAP_OPEN_OFFLINE_COMMON(ebuf, type) \
+       pcap_open_offline_common(ebuf, \
+           sizeof (struct { pcap_t __common; type __private; }), \
+           offsetof (struct { pcap_t __common; type __private; }, __private))
+pcap_t *pcap_open_offline_common(char *ebuf, size_t total_size,
+    size_t private_data);
 bpf_u_int32 pcap_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen);
 void   sf_cleanup(pcap_t *p);
 #ifdef _WIN32
index 68328b4be37449906632f49ab75c450568021960..ef3fdac3779087903e94bb29a7b33516c6ff5f62 100644 (file)
@@ -477,7 +477,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
 {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_dlpi);
        if (p == NULL)
                return (NULL);
 
index 546d03690e0f4dfd6c0e55a304a4614fed63c708..de21cd431d4f990628493a25024025a70b731a31 100644 (file)
@@ -329,7 +329,7 @@ pcap_create_interface(const char *device, char *ebuf)
 {
        pcap_t *handle;
 
-       handle = pcap_create_common(ebuf, sizeof (struct pcap_linux));
+       handle = PCAP_CREATE_COMMON(ebuf, struct pcap_linux);
        if (handle == NULL)
                return NULL;
 
index ced930278def8d8c57d7d65e57a1ddd2d1f63cd4..cdd6d7fcc073309e28dd9ed736a16d7740ff5c56 100644 (file)
@@ -743,7 +743,7 @@ netfilter_create(const char *device, char *ebuf, int *is_ours)
        /* OK, it's probably ours. */
        *is_ours = 1;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_netfilter));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_netfilter);
        if (p == NULL)
                return (NULL);
 
index 3613a756a5b81c45d20af11255a5e97448a41006..27d36e5bb6d31b678e875887a5e9941f5540090c 100644 (file)
@@ -286,7 +286,7 @@ pcap_netmap_create(const char *device, char *ebuf, int *is_ours)
        *is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4));
        if (! *is_ours)
                return NULL;
-       p = pcap_create_common(ebuf, sizeof (struct pcap_netmap));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_netmap);
        if (p == NULL)
                return (NULL);
        p->activate_op = pcap_netmap_activate;
index b73eaad74089da6447b2276eda127a123fa57797..cfd95191d772b0c3df559a445e474cffd75bc38c 100644 (file)
@@ -370,7 +370,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
 {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_nit));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_nit);
        if (p == NULL)
                return (NULL);
 
index 688b21f7b1f3f5b7e854a40e5a16ce7c9d6f097e..cdc0a715fe2c39df084070e8958882e8d051241c 100644 (file)
@@ -1315,7 +1315,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
 {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, sizeof(struct pcap_win));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_win);
        if (p == NULL)
                return (NULL);
 
index c50507b912ea8848a06bd56907b30801ce59e66c..f483a0e66bc905c29626bf270f06d8a9f0535211 100644 (file)
--- a/pcap-pf.c
+++ b/pcap-pf.c
@@ -535,7 +535,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
 {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_pf));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_pf);
        if (p == NULL)
                return (NULL);
 
index 032b80f8aa3230048d168bbadf77eb87e72b5153..224821de4abdc8c36770cec4272690713465869c 100644 (file)
@@ -395,7 +395,7 @@ rdmasniff_create(const char *device, char *ebuf, int *is_ours)
                    !strncmp(device, dev_list[i]->name, namelen)) {
                        *is_ours = 1;
 
-                       p = pcap_create_common(ebuf, sizeof (struct pcap_rdmasniff));
+                       p = PCAP_CREATE_COMMON(ebuf, struct pcap_rdmasniff);
                        if (p) {
                                p->activate_op = rdmasniff_activate;
                                priv = p->priv;
index 836681a10c19c3878be6b5120bd4704e2ef70049..787b67a8d2468d851f9ba112cfe56fb2e6057784 100644 (file)
@@ -2319,7 +2319,7 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim
        struct rpcap_header header;             /* header of the RPCAP packet */
        struct rpcap_openreply openreply;       /* open reply message */
 
-       fp = pcap_create_common(errbuf, sizeof (struct pcap_rpcap));
+       fp = PCAP_CREATE_COMMON(errbuf, struct pcap_rpcap);
        if (fp == NULL)
        {
                return NULL;
index c59dbc1947605a9a4020452a751c0181af2ef72c..759e622c25fd8ed215e991b78490d50539c4199b 100644 (file)
@@ -233,7 +233,7 @@ pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) {
        /* OK, it's probably ours. */
        *is_ours = 1;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_septel));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_septel);
        if (p == NULL)
                return NULL;
 
index 03006332b400b09aeddb8eee722bbd570b1bbe78..90e7f6f176ae3967abc34ab0137acb63eb7c9459 100644 (file)
@@ -72,6 +72,14 @@ typedef struct unit {
        int                     len;            /* the current size of the inbound message */
 } unit_t;
 
+/*
+ * Private data.
+ * Currently contains nothing.
+ */
+struct pcap_sita {
+       int     dummy;
+};
+
 static unit_t          units[MAX_CHASSIS+1][MAX_GEOSLOT+1];    /* we use indexes of 1 through 8, but we reserve/waste index 0 */
 static fd_set          readfds;                                /* a place to store the file descriptors for the connections to the IOPs */
 static int             max_fs;
@@ -1033,7 +1041,7 @@ static int pcap_activate_sita(pcap_t *handle) {
 pcap_t *pcap_create_interface(const char *device _U_, char *ebuf) {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, 0);
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_sita);
        if (p == NULL)
                return (NULL);
 
index 6bf504ea0fd047817cd06a7ea4d432e3fd89af1d..3c37abf3eb009599735835cb6f007be814c22135 100644 (file)
@@ -540,7 +540,7 @@ snf_create(const char *device, char *ebuf, int *is_ours)
        /* OK, it's probably ours. */
        *is_ours = 1;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_snf));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_snf);
        if (p == NULL)
                return NULL;
        ps = p->priv;
index 6f063c9b3391b24f810f45949b5f2b3f9efd22a1..ca6222cf01666aac7d185a281ff6dac6eaf146e0 100644 (file)
@@ -459,7 +459,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
 {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_snit));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_snit);
        if (p == NULL)
                return (NULL);
 
index fe46314d18e17f4704112b0593329a7521f88c4b..2f44b1dd91bb53c650c7c9525636f290689ec567 100644 (file)
@@ -421,7 +421,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
 {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_snoop));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_snoop);
        if (p == NULL)
                return (NULL);
 
index ef409d323edc4162f40052727e6834e18a2a3e74..9902633a933f2d9599109016e215da6c7c77b65e 100644 (file)
--- a/pcap-tc.c
+++ b/pcap-tc.c
@@ -703,7 +703,7 @@ TcCreate(const char *device, char *ebuf, int *is_ours)
        /* OK, it's probably ours. */
        *is_ours = 1;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_tc));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_tc);
        if (p == NULL)
                return NULL;
 
index ddab03a9bbc9342338402d0415563d4861ba7342..98d22de4c865ed42c9d403da649042bb753ae50c 100644 (file)
@@ -617,7 +617,7 @@ usb_create(const char *device, char *ebuf, int *is_ours)
        /* OK, it's probably ours. */
        *is_ours = 1;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_usb_linux));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_usb_linux);
        if (p == NULL)
                return (NULL);
 
diff --git a/pcap.c b/pcap.c
index 0625e669c60653002c957ec9578a1fab00b99ed6..58ef71d279f142798ca071c264c62dd11494f4df 100644 (file)
--- a/pcap.c
+++ b/pcap.c
@@ -2437,27 +2437,16 @@ initialize_ops(pcap_t *p)
 }
 
 static pcap_t *
-pcap_alloc_pcap_t(char *ebuf, size_t size)
+pcap_alloc_pcap_t(char *ebuf, size_t total_size, size_t private_offset)
 {
        char *chunk;
        pcap_t *p;
 
        /*
-        * Allocate a chunk of memory big enough for a pcap_t
-        * plus a structure following it of size "size".  The
-        * structure following it is a private data structure
-        * for the routines that handle this pcap_t.
-        *
-        * The structure following it must be aligned on
-        * the appropriate alignment boundary for this platform.
-        * We align on an 8-byte boundary as that's probably what
-        * at least some platforms do, even with 32-bit integers,
-        * and because we can't be sure that some values won't
-        * require 8-byte alignment even on platforms with 32-bit
-        * integers.
+        * total_size is the size of a structure containing a pcap_t
+        * followed by a private structure.
         */
-#define PCAP_T_ALIGNED_SIZE    ((sizeof(pcap_t) + 7U) & ~0x7U)
-       chunk = calloc(PCAP_T_ALIGNED_SIZE + size, 1);
+       chunk = calloc(total_size, 1);
        if (chunk == NULL) {
                pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
                    errno, "malloc");
@@ -2479,26 +2468,24 @@ pcap_alloc_pcap_t(char *ebuf, size_t size)
 #endif /* MSDOS */
 #endif /* _WIN32 */
 
-       if (size == 0) {
-               /* No private data was requested. */
-               p->priv = NULL;
-       } else {
-               /*
-                * Set the pointer to the private data; that's the structure
-                * of size "size" following the pcap_t.
-                */
-               p->priv = (void *)(chunk + PCAP_T_ALIGNED_SIZE);
-       }
+       /*
+        * private_offset is the offset, in bytes, of the private
+        * data from the beginning of the structure.
+        *
+        * Set the pointer to the private data; that's private_offset
+        * bytes past the pcap_t.
+        */
+       p->priv = (void *)(chunk + private_offset);
 
        return (p);
 }
 
 pcap_t *
-pcap_create_common(char *ebuf, size_t size)
+pcap_create_common(char *ebuf, size_t total_size, size_t private_offset)
 {
        pcap_t *p;
 
-       p = pcap_alloc_pcap_t(ebuf, size);
+       p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
        if (p == NULL)
                return (NULL);
 
@@ -2878,11 +2865,11 @@ fail:
 }
 
 pcap_t *
-pcap_open_offline_common(char *ebuf, size_t size)
+pcap_open_offline_common(char *ebuf, size_t total_size, size_t private_offset)
 {
        pcap_t *p;
 
-       p = pcap_alloc_pcap_t(ebuf, size);
+       p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
        if (p == NULL)
                return (NULL);
 
index 5c416b0cef32593f800796922ad4036d2f00c931..d8443e982589502e9ce03859d40441d2a4214f75 100644 (file)
--- a/sf-pcap.c
+++ b/sf-pcap.c
@@ -240,7 +240,7 @@ pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
         * OK, this is a good pcap file.
         * Allocate a pcap_t for it.
         */
-       p = pcap_open_offline_common(errbuf, sizeof (struct pcap_sf));
+       p = PCAP_OPEN_OFFLINE_COMMON(errbuf, struct pcap_sf);
        if (p == NULL) {
                /* Allocation failed. */
                *err = 1;
index 24eb5f73c7c267e7d6daa442d3ec3b02eb0e49ae..f7f413d31fc002681ea6dafe54b6cdd844712e02 100644 (file)
@@ -876,7 +876,7 @@ pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision,
         * OK, this is a good pcapng file.
         * Allocate a pcap_t for it.
         */
-       p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf));
+       p = PCAP_OPEN_OFFLINE_COMMON(errbuf, struct pcap_ng_sf);
        if (p == NULL) {
                /* Allocation failed. */
                *err = 1;