From 542120869bdfca684c03ef9c2cdf355556d09bf6 Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Wed, 20 Nov 2024 12:44:06 +0000 Subject: [PATCH] Indicate no-capture and no-inject devices. Introduce PCAP_IF_NO_CAPTURE and PCAP_IF_NO_INJECT interface flags. Set PCAP_IF_NO_INJECT on Bluetooth, DAG Rx stream, DPDK, Haiku network interface, Linux netfilter, RDMA, Linux USB and the "any" pseudo-interface devices. Set PCAP_IF_NO_CAPTURE on DAG Tx stream devices. Update related man pages and findalldevstest. --- CHANGES | 1 + pcap-bt-linux.c | 4 +++- pcap-bt-monitor-linux.c | 4 +++- pcap-dag.c | 36 ++++++++++++++++++++++++------------ pcap-dpdk.c | 2 +- pcap-haiku.c | 2 ++ pcap-netfilter-linux.c | 2 ++ pcap-rdmasniff.c | 4 +++- pcap-usb-linux.c | 5 ++++- pcap.c | 5 ++++- pcap/pcap.h | 2 ++ pcap_activate.3pcap | 7 +++++-- pcap_findalldevs.3pcap | 18 +++++++++++++++++- pcap_inject.3pcap | 7 +++++-- testprogs/findalldevstest.c | 10 ++++++++++ 15 files changed, 86 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index 32633356ff..7e7f3fd925 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,7 @@ DayOfTheWeek, Month DD, YYYY / The Tcpdump Group Fix "tcpdump -i " for something-only libpcap builds. Remove code related to Riverbed TurboCap card. Riverbed TurboCap hardware has reached EOA as of Jun 30 2014. + Indicate no-capture and no-inject devices. Link-layer types: Add LINKTYPE_ETW/DLT_ETW. Add LINKTYPE_NETANALYZER_NG/DLT_NETANALYZER_NG (pull request diff --git a/pcap-bt-linux.c b/pcap-bt-linux.c index 67d357c4d8..197c1bcaca 100644 --- a/pcap-bt-linux.c +++ b/pcap-bt-linux.c @@ -130,7 +130,9 @@ bt_findalldevs(pcap_if_list_t *devlistp, char *err_str) * the status to PCAP_IF_CONNECTION_STATUS_CONNECTED * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED. */ - if (pcapint_add_dev(devlistp, dev_name, PCAP_IF_WIRELESS, dev_descr, err_str) == NULL) + if (pcapint_add_dev(devlistp, dev_name, + PCAP_IF_WIRELESS | PCAP_IF_NO_INJECT, + dev_descr, err_str) == NULL) { ret = PCAP_ERROR; break; diff --git a/pcap-bt-monitor-linux.c b/pcap-bt-monitor-linux.c index 44d40e2efc..ee0a178dfa 100644 --- a/pcap-bt-monitor-linux.c +++ b/pcap-bt-monitor-linux.c @@ -80,7 +80,9 @@ bt_monitor_findalldevs(pcap_if_list_t *devlistp, char *err_str) * for the "any" device. */ if (pcapint_add_dev(devlistp, INTERFACE_NAME, - PCAP_IF_WIRELESS|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, + PCAP_IF_WIRELESS | + PCAP_IF_NO_INJECT | + PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "Bluetooth Linux Monitor", err_str) == NULL) { ret = PCAP_ERROR; diff --git a/pcap-dag.c b/pcap-dag.c index 6af3ff61e7..9126f5c547 100644 --- a/pcap-dag.c +++ b/pcap-dag.c @@ -1387,6 +1387,22 @@ dag_stream_long_description(const unsigned stream, const dag_size_t bufsize, return buf; } +static bpf_u_int32 +dag_flags(const int stream) +{ + /* + * A DAG card associates a link status with each physical port, but not + * with the data streams. The number of ports is a matter of hardware, + * the number of streams and how each stream associates with zero or + * more ports is a matter of how the user configures the card. In this + * context libpcap uses the streams only (i.e. "dag0" is a shorthand + * for "dag0:0"), thus the notion of link status does not apply to the + * resulting libpcap DAG capture devices. + */ + return PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE | + (RX_ONLY(stream) ? PCAP_IF_NO_INJECT : PCAP_IF_NO_CAPTURE); +} + /* * Add all DAG devices. */ @@ -1397,14 +1413,6 @@ dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf) int dagfd; const char * description; int stream, rxstreams; - // A DAG card associates a link status with each physical port, but not - // with the data streams. The number of ports is a matter of hardware, - // the number of streams and how each stream associates with zero or - // more ports is a matter of how the user configures the card. In this - // context libpcap uses the streams only (i.e. "dag0" is a shorthand - // for "dag0:0"), thus the notion of link status does not apply to the - // resulting libpcap DAG capture devices. - const bpf_u_int32 flags = PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE; FILE * sysfsinfo = NULL; /* Try all the DAGs 0-DAG_MAX_BOARDS */ @@ -1459,13 +1467,15 @@ dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf) description = dag_device_description (c); // a conditional shorthand device if (stream == 0 && - pcapint_add_dev(devlistp, name, flags, description, errbuf) == NULL) + pcapint_add_dev(devlistp, name, dag_flags(stream), + description, errbuf) == NULL) goto failclose; // and the stream device snprintf(name, sizeof(name), "dag%d:%d", c, stream); description = dag_stream_long_description(stream, dag_get_stream_buffer_size64(dagfd, stream), inf); - if (pcapint_add_dev(devlistp, name, flags, description, errbuf) == NULL) { + if (pcapint_add_dev(devlistp, name, dag_flags(stream), + description, errbuf) == NULL) { goto failclose; } } @@ -1496,13 +1506,15 @@ dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf) // a conditional shorthand device description = dag_device_description(c); if (stream == 0 && - pcapint_add_dev(devlistp, name, flags, description, errbuf) == NULL) + pcapint_add_dev(devlistp, name, dag_flags(stream), + description, errbuf) == NULL) goto failclose; // and the stream device snprintf(name, sizeof(name), "dag%u:%u", c, stream); // TODO: Parse and describe the buffer size too. description = dag_stream_short_description(stream); - if (pcapint_add_dev(devlistp, name, flags, description, errbuf) == NULL) + if (pcapint_add_dev(devlistp, name, dag_flags(stream), + description, errbuf) == NULL) goto failclose; } fclose(sysfsinfo); diff --git a/pcap-dpdk.c b/pcap-dpdk.c index 76de9b7690..31fa7da9a9 100644 --- a/pcap-dpdk.c +++ b/pcap-dpdk.c @@ -1039,7 +1039,7 @@ int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *ebuf) // PCI addr rte_eth_dev_get_name_by_port(i,pci_addr); snprintf(dpdk_desc,DPDK_DEV_DESC_MAX-1,"%s %s, MAC:%s, PCI:%s", DPDK_DESC, dpdk_name, mac_addr, pci_addr); - if (pcapint_add_dev(devlistp, dpdk_name, 0, dpdk_desc, ebuf)==NULL){ + if (pcapint_add_dev(devlistp, dpdk_name, PCAP_IF_NO_INJECT, dpdk_desc, ebuf)==NULL){ ret = PCAP_ERROR; break; } diff --git a/pcap-haiku.c b/pcap-haiku.c index 0ec1f18d62..681d4315e6 100644 --- a/pcap-haiku.c +++ b/pcap-haiku.c @@ -451,6 +451,8 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf) if (validate_ifname(name, errbuf) < 0) return PCAP_ERROR; + *flags |= PCAP_IF_NO_INJECT; + if (*flags & PCAP_IF_LOOPBACK || ! strncmp(name, "tun", strlen("tun")) || ! strncmp(name, "tap", strlen("tap"))) { diff --git a/pcap-netfilter-linux.c b/pcap-netfilter-linux.c index 90296be71b..e08db553d3 100644 --- a/pcap-netfilter-linux.c +++ b/pcap-netfilter-linux.c @@ -784,10 +784,12 @@ netfilter_findalldevs(pcap_if_list_t *devlistp, char *err_str) * XXX - what about "up" and "running"? */ if (pcapint_add_dev(devlistp, NFLOG_IFACE, + PCAP_IF_NO_INJECT | PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "Linux netfilter log (NFLOG) interface", err_str) == NULL) return -1; if (pcapint_add_dev(devlistp, NFQUEUE_IFACE, + PCAP_IF_NO_INJECT | PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "Linux netfilter queue (NFQUEUE) interface", err_str) == NULL) return -1; diff --git a/pcap-rdmasniff.c b/pcap-rdmasniff.c index ba4705b71a..f05c1dc71c 100644 --- a/pcap-rdmasniff.c +++ b/pcap-rdmasniff.c @@ -442,7 +442,9 @@ rdmasniff_findalldevs(pcap_if_list_t *devlistp, char *err_str) * XXX - do the notions of "up", "running", or * "connected" apply here? */ - if (!pcapint_add_dev(devlistp, dev_list[i]->name, 0, "RDMA sniffer", err_str)) { + if (!pcapint_add_dev(devlistp, dev_list[i]->name, + PCAP_IF_NO_INJECT, + "RDMA sniffer", err_str)) { ret = -1; break; } diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c index 4287585f15..1773e4af47 100644 --- a/pcap-usb-linux.c +++ b/pcap-usb-linux.c @@ -152,6 +152,7 @@ usb_dev_add(pcap_if_list_t *devlistp, int n, char *err_str) * that would apply to a particular USB interface. */ if (pcapint_add_dev(devlistp, dev_name, + PCAP_IF_NO_INJECT | PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "Raw USB traffic, all USB buses", err_str) == NULL) return -1; @@ -163,7 +164,9 @@ usb_dev_add(pcap_if_list_t *devlistp, int n, char *err_str) * PCAP_IF_CONNECTION_STATUS_DISCONNECTED? */ snprintf(dev_descr, sizeof(dev_descr), "Raw USB traffic, bus number %d", n); - if (pcapint_add_dev(devlistp, dev_name, 0, dev_descr, err_str) == NULL) + if (pcapint_add_dev(devlistp, dev_name, + PCAP_IF_NO_INJECT, + dev_descr, err_str) == NULL) return -1; } diff --git a/pcap.c b/pcap.c index 2ff17e1629..7995a7047c 100644 --- a/pcap.c +++ b/pcap.c @@ -1422,7 +1422,10 @@ pcap_add_any_dev(pcap_if_list_t *devlistp, char *errbuf) * doesn't apply to the "any" device. */ return pcapint_add_dev(devlistp, "any", - PCAP_IF_UP|PCAP_IF_RUNNING|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, + PCAP_IF_UP | + PCAP_IF_RUNNING | + PCAP_IF_NO_INJECT | + PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, any_descr, errbuf); } diff --git a/pcap/pcap.h b/pcap/pcap.h index 9560df524f..bc5532e507 100644 --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -336,6 +336,8 @@ struct pcap_if { #define PCAP_IF_CONNECTION_STATUS_CONNECTED 0x00000010 /* connected */ #define PCAP_IF_CONNECTION_STATUS_DISCONNECTED 0x00000020 /* disconnected */ #define PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE 0x00000030 /* not applicable */ +#define PCAP_IF_NO_CAPTURE 0x00000040 /* a no-capture device */ +#define PCAP_IF_NO_INJECT 0x00000080 /* a no-inject device */ /* * Representation of an interface address. diff --git a/pcap_activate.3pcap b/pcap_activate.3pcap index 9594641323..0c3d60c6b9 100644 --- a/pcap_activate.3pcap +++ b/pcap_activate.3pcap @@ -17,7 +17,7 @@ .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" -.TH PCAP_ACTIVATE 3PCAP "3 June 2024" +.TH PCAP_ACTIVATE 3PCAP "24 November 2024" .SH NAME pcap_activate \- activate a capture handle .SH SYNOPSIS @@ -90,7 +90,10 @@ monitor mode. The capture source device is not up. .TP .B PCAP_ERROR_CAPTURE_NOTSUP -Packet capture is not supported on the capture source. +Packet capture is not supported on the capture source. See also the +.B \%PCAP_IF_NO_CAPTURE +device flag in +.BR \%pcap_findalldevs (3PCAP). .TP .B PCAP_ERROR Another error occurred. diff --git a/pcap_findalldevs.3pcap b/pcap_findalldevs.3pcap index 8774eff17b..edcbd81935 100644 --- a/pcap_findalldevs.3pcap +++ b/pcap_findalldevs.3pcap @@ -17,7 +17,7 @@ .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" -.TH PCAP_FINDALLDEVS 3PCAP "9 August 2024" +.TH PCAP_FINDALLDEVS 3PCAP "24 November 2024" .SH NAME pcap_findalldevs, pcap_freealldevs \- get a list of capture devices, and free that list @@ -112,6 +112,16 @@ set if the device is a wireless interface; this includes IrDA as well as radio-based networks such as IEEE 802.15.4 and IEEE 802.11, so it doesn't just mean Wi-Fi .TP +.B PCAP_IF_NO_CAPTURE +set if the device does not support packet capture in principle, thus any +attempt to capture on the device will fail with an error; note that this flag +.B not +being set does not mean all attempts to capture will succeed: some may fail +as usual because of the capture parameters, device status, permissions etc. +.TP +.B PCAP_IF_NO_INJECT +same as the above, but with regard to packet injection +.TP .B PCAP_IF_CONNECTION_STATUS a bitmask for an indication of whether the adapter is connected or not; for wireless interfaces, "connected" means "associated with a network" @@ -262,5 +272,11 @@ The and .B PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE constants became available in libpcap release 1.9.0. +.PP +The +.B PCAP_IF_NO_CAPTURE +and +.B PCAP_IF_NO_INJECT +constants became available in libpcap release 1.11.0. .SH SEE ALSO .BR pcap (3PCAP) diff --git a/pcap_inject.3pcap b/pcap_inject.3pcap index 55e79e0d12..2b1b170cb8 100644 --- a/pcap_inject.3pcap +++ b/pcap_inject.3pcap @@ -17,7 +17,7 @@ .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" -.TH PCAP_INJECT 3PCAP "23 November 2024" +.TH PCAP_INJECT 3PCAP "24 November 2024" .SH NAME pcap_inject, pcap_sendpacket \- transmit a packet .SH SYNOPSIS @@ -50,7 +50,10 @@ The same limitation applies to .BR \%pcap_create (3PCAP) and .BR \%pcap_activate (3PCAP). -Note also that some devices might not support sending packets. +Note also that some devices might not support sending packets. See also the +.B \%PCAP_IF_NO_INJECT +device flag in +.BR \%pcap_findalldevs (3PCAP). .PP Note that, on some platforms, the link-layer header of the packet that's sent might not be the same as the link-layer header of the packet diff --git a/testprogs/findalldevstest.c b/testprogs/findalldevstest.c index 11e2f2ee3e..f8d3c618e0 100644 --- a/testprogs/findalldevstest.c +++ b/testprogs/findalldevstest.c @@ -234,6 +234,16 @@ static int ifprint(pcap_if_t *d) printf("%sLOOPBACK", sep); sep = ", "; } +#ifdef PCAP_IF_NO_CAPTURE + if (d->flags & PCAP_IF_NO_CAPTURE) { + printf("%sNO_CAPTURE", sep); + sep = ", "; + } + if (d->flags & PCAP_IF_NO_INJECT) { + printf("%sNO_INJECT", sep); + sep = ", "; + } +#endif if (d->flags & PCAP_IF_WIRELESS) { printf("%sWIRELESS", sep); switch (d->flags & PCAP_IF_CONNECTION_STATUS) {