From d21e0ab392df5e85d5b99bb0d445195b3e30f954 Mon Sep 17 00:00:00 2001 From: git-hulk Date: Wed, 2 Sep 2026 18:36:08 +0800 Subject: [PATCH] Build with -Wextra and modernise the capture device setup - hashtable compared strlen's size_t against an int in three places, which is what -Wextra was reporting, and read a uint32_t straight out of the key with a cast. That load is undefined for an unaligned key and faults outright on a strict-alignment target; memcpy says the same thing and compiles to the same instruction. - sniffer_online called pcap_lookupnet purely to bail out when it failed: neither the network nor the mask it returns is ever used. That made a capture on an interface with no IPv4 address fail for no reason. Dropped. - Replace pcap_lookupdev, which is deprecated and hands back a shared buffer, with pcap_findalldevs. The fallback now also skips loopback unless it is the only device there is. Reaching this path needs root, since the uid check runs first, so it is covered by inspection and by exercising pcap_findalldevs directly rather than by a test. - Turn on -Wextra now that the tree is clean under it. Assistant By Opus 5 Co-Authored-By: Claude Opus 5 (1M context) --- src/Makefile | 2 +- src/hashtable.c | 19 ++++++++++++------- src/sniffer.c | 33 ++++++++++++++++++++++++--------- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/Makefile b/src/Makefile index ec291fa..ce0b64e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,7 +5,7 @@ all: $(PROG) CC = gcc OPTIMIZATION ?= -O2 -CFLAGS = -g $(OPTIMIZATION) -Wall +CFLAGS = -g $(OPTIMIZATION) -Wall -Wextra # SANITIZE=address builds the binary and the test suite under ASan/UBSan. ifdef SANITIZE diff --git a/src/hashtable.c b/src/hashtable.c index 64b8f1f..0e545a4 100644 --- a/src/hashtable.c +++ b/src/hashtable.c @@ -26,7 +26,9 @@ unsigned int hash_function(const void *key, int len) { const unsigned char *data = (const unsigned char *)key; while(len >= 4) { - uint32_t k = *(uint32_t*)data; + uint32_t k; + + memcpy(&k, data, sizeof(k)); k *= m; k ^= k >> r; @@ -90,11 +92,12 @@ void hashtable_destroy(hashtable *ht) { } void *hashtable_add(hashtable *ht, char *key, void *value) { - int bucket, key_size; + int bucket; + size_t key_size; entry *current; key_size = strlen(key); - bucket = hash_function(key, strlen(key)) % ht->nbucket; + bucket = hash_function(key, (int)key_size) % ht->nbucket; current = ht->buckets[bucket]; while (current) { if (key_size == strlen(current->key) && !strncmp(key, current->key, key_size)) { @@ -117,11 +120,12 @@ void *hashtable_add(hashtable *ht, char *key, void *value) { } void *hashtable_get(hashtable *ht, char *key) { - int bucket, key_size; + int bucket; + size_t key_size; entry *current; key_size = strlen(key); - bucket = hash_function(key, key_size) % ht->nbucket; + bucket = hash_function(key, (int)key_size) % ht->nbucket; current = ht->buckets[bucket]; while(current) { if (strlen(current->key) == key_size && !strncmp(key, current->key, key_size)) { @@ -133,10 +137,11 @@ void *hashtable_get(hashtable *ht, char *key) { } int hashtable_del(hashtable *ht, char *key) { - int bucket, key_size = strlen(key); + int bucket; + size_t key_size = strlen(key); entry *current, *prev = NULL; - bucket = hash_function(key, key_size) % ht->nbucket; + bucket = hash_function(key, (int)key_size) % ht->nbucket; current = ht->buckets[bucket]; while (current) { if (key_size == strlen(current->key) && !strncmp(key, current->key, key_size)) { diff --git a/src/sniffer.c b/src/sniffer.c index 0a35029..6a02150 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -37,6 +37,24 @@ static void free_request(void *v) { free(req); } +/* pcap_lookupdev is deprecated and returns a shared buffer; the caller owns + * the name this returns. Loopback is a last resort, not a first guess. */ +static char *first_capture_device(char *err) { + pcap_if_t *devices, *d; + char *name = NULL; + + if (pcap_findalldevs(&devices, err) == -1) return NULL; + for (d = devices; d; d = d->next) { + if (d->flags & PCAP_IF_LOOPBACK) continue; + name = strdup(d->name); + break; + } + if (!name && devices) name = strdup(devices->name); + pcap_freealldevs(devices); + if (!name) snprintf(err, MAX_ERR_BUFF_SIZE, "no capture device available"); + return name; +} + struct bpf_program *sniffer_compile(pcap_t *pcap, const char *filter, char *err) { struct bpf_program *bpf; @@ -94,11 +112,13 @@ struct sniffer *sniffer_create(struct options *opts, char *err) { pcap = sniffer_offline(opts->offline_file, err); } else { pcap = sniffer_online(opts->dev, opts->snaplen, opts->buf_size, err); - if (!strcmp(opts->dev, "any") && !pcap) { - if ((dev = pcap_lookupdev(err)) != NULL) { + if (!pcap && !strcmp(opts->dev, "any")) { + if ((dev = first_capture_device(err)) != NULL) { pcap = sniffer_online(dev, opts->snaplen, opts->buf_size, err); free(opts->dev); - opts->dev = strdup(dev); + free(sniffer->dev); + opts->dev = dev; + sniffer->dev = strdup(dev); } } } @@ -161,13 +181,8 @@ pcap_t *sniffer_offline(const char *file, char *err) { pcap_t *sniffer_online(const char *dev, int snaplen, int buf_size, char *err) { int status; pcap_t *pcap; - bpf_u_int32 net = 0, mask = 0; - const char *new_dev = dev; - if (pcap_lookupnet(dev, &net, &mask, err) == -1) { - return NULL; - } - pcap = pcap_create(new_dev, err); + pcap = pcap_create(dev, err); if (!pcap) return NULL; status = pcap_set_snaplen(pcap, snaplen); if (status < 0) goto error;