ctdb-common: Support "any" interface for pcap-based capture
authorMartin Schwenke <martin@meltin.net>
Mon, 15 Aug 2022 00:51:47 +0000 (10:51 +1000)
committerJule Anger <janger@samba.org>
Tue, 29 Aug 2023 09:35:11 +0000 (09:35 +0000)
This uses Linux cooked capture link-layer headers.  See:

  https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html
  https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html

The header type needs to be checked to ensure the protocol
type (i.e. ether type, for the protocols we might be interested in) is
meaningful.  The size of the header needs to be known so it can be
skipped, allowing the IP header to be found and parsed.

It would be possible to define support for DLT_LINUX_SLL2 if it is
missing.  However, if a platform is missing support in the header file
then it is almost certainly missing in the run-time library too.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
(cherry picked from commit e5541a7e0220a88d59d574d501626b0598050c52)

ctdb/common/system_socket.c

index 51f5d03090650f2c9a2c22be424e6e32cff227b7..9f7ca07e0982c49210e5f2851ddeec5eda1cc648 100644 (file)
@@ -967,12 +967,18 @@ int ctdb_sys_read_tcp_packet(int s, void *private_data,
 
 #include <pcap.h>
 
+/*
+ * Assume this exists if pcap.h exists - it has been around for a
+ * while
+ */
+#include <pcap/sll.h>
+
 int ctdb_sys_open_capture_socket(const char *iface, void **private_data)
 {
        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_t *pt;
        int pcap_packet_type;
-       const char *t;
+       const char *t = NULL;
        int fd;
 
        pt = pcap_open_live(iface, 100, 0, 0, errbuf);
@@ -989,6 +995,14 @@ int ctdb_sys_open_capture_socket(const char *iface, void **private_data)
        case DLT_EN10MB:
                t = "DLT_EN10MB";
                break;
+       case DLT_LINUX_SLL:
+               t = "DLT_LINUX_SLL";
+               break;
+#ifdef DLT_LINUX_SLL2
+       case DLT_LINUX_SLL2:
+               t = "DLT_LINUX_SLL2";
+               break;
+#endif /* DLT_LINUX_SLL2 */
        default:
                DBG_ERR("Unknown pcap packet type %d\n", pcap_packet_type);
                pcap_close(pt);
@@ -1044,6 +1058,40 @@ int ctdb_sys_read_tcp_packet(int s,
                ll_hdr_len = sizeof(struct ether_header);
                break;
        }
+       case DLT_LINUX_SLL: {
+               const struct sll_header *sll =
+                       (const struct sll_header *)buffer;
+               uint16_t arphrd_type = ntohs(sll->sll_hatype);
+               switch (arphrd_type) {
+               case ARPHRD_ETHER:
+                       break;
+               default:
+                       DBG_DEBUG("SLL: Unknown arphrd_type %"PRIu16"\n",
+                                 arphrd_type);
+                       return EPROTONOSUPPORT;
+               }
+               ether_type = ntohs(sll->sll_protocol);
+               ll_hdr_len = SLL_HDR_LEN;
+               break;
+       }
+#ifdef DLT_LINUX_SLL2
+       case DLT_LINUX_SLL2: {
+               const struct sll2_header *sll2 =
+                       (const struct sll2_header *)buffer;
+               uint16_t arphrd_type = ntohs(sll2->sll2_hatype);
+               switch (arphrd_type) {
+               case ARPHRD_ETHER:
+                       break;
+               default:
+                       DBG_DEBUG("SLL2: Unknown arphrd_type %"PRIu16"\n",
+                                 arphrd_type);
+                       return EPROTONOSUPPORT;
+               }
+               ether_type = ntohs(sll2->sll2_protocol);
+               ll_hdr_len = SLL2_HDR_LEN;
+               break;
+       }
+#endif /* DLT_LINUX_SLL2 */
        default:
                DBG_DEBUG("Unknown pcap packet type %d\n", pcap_packet_type);
                return EPROTONOSUPPORT;