summaryrefslogtreecommitdiff
path: root/ctdb
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2022-08-15 09:43:58 +1000
committerAmitay Isaacs <amitay@samba.org>2022-09-20 10:43:37 +0000
commit3bf20300ac5962e71069be3998ef7f0502045d24 (patch)
tree50d025cdb7889c9646c40a1fd78f84d855067fcc /ctdb
parent5dd964aa0297b6e9ab8e1d0ff9fa0565c97ea43e (diff)
downloadsamba-3bf20300ac5962e71069be3998ef7f0502045d24.tar.gz
ctdb-common: Add packet type detection to pcap-based capture
The current code will almost certainly generate ENOMSG for non-ethernet packets, even for ethernet packets when the "any" interface is used. pcap_datalink(3PCAP) says: Do NOT assume that the packets for a given capture or ``savefile`` will have any given link-layer header type, such as DLT_EN10MB for Ethernet. For example, the "any" device on Linux will have a link-layer header type of DLT_LINUX_SLL or DLT_LINUX_SLL2 even if all devices on the sys‐ tem at the time the "any" device is opened have some other data link type, such as DLT_EN10MB for Ethernet. So, pcap_datalink() must be used. Detect pcap packet types that are supported (currently only ethernet) in the open code. There is no use continuing if the read code can't parse packets. The pattern of using switch statements supports future addition of other packet types. Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com>
Diffstat (limited to 'ctdb')
-rw-r--r--ctdb/common/system_socket.c67
1 files changed, 49 insertions, 18 deletions
diff --git a/ctdb/common/system_socket.c b/ctdb/common/system_socket.c
index e8ccd301f6c..51f5d030906 100644
--- a/ctdb/common/system_socket.c
+++ b/ctdb/common/system_socket.c
@@ -971,6 +971,8 @@ 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;
int fd;
pt = pcap_open_live(iface, 100, 0, 0, errbuf);
@@ -981,9 +983,22 @@ int ctdb_sys_open_capture_socket(const char *iface, void **private_data)
return -1;
}
*((pcap_t **)private_data) = pt;
- fd = pcap_get_selectable_fd(pt);
- DBG_DEBUG("Opened pcap capture for TCP tickle capture (fd=%d)\n", fd);
+ pcap_packet_type = pcap_datalink(pt);
+ switch (pcap_packet_type) {
+ case DLT_EN10MB:
+ t = "DLT_EN10MB";
+ break;
+ default:
+ DBG_ERR("Unknown pcap packet type %d\n", pcap_packet_type);
+ pcap_close(pt);
+ return -1;
+ }
+
+ fd = pcap_get_selectable_fd(pt);
+ DBG_DEBUG("Opened pcap capture for TCP tickle (type=%s, fd=%d)\n",
+ t,
+ fd);
return fd;
}
@@ -1005,10 +1020,12 @@ int ctdb_sys_read_tcp_packet(int s,
uint16_t *window)
{
int ret;
- const struct ether_header *eth;
struct pcap_pkthdr pkthdr;
const u_char *buffer;
pcap_t *pt = (pcap_t *)private_data;
+ int pcap_packet_type;
+ uint16_t ether_type;
+ size_t ll_hdr_len;
buffer=pcap_next(pt, &pkthdr);
if (buffer==NULL) {
@@ -1018,36 +1035,50 @@ int ctdb_sys_read_tcp_packet(int s,
ZERO_STRUCTP(src);
ZERO_STRUCTP(dst);
- /* Ethernet */
- eth = (const struct ether_header *)buffer;
+ pcap_packet_type = pcap_datalink(pt);
+ switch (pcap_packet_type) {
+ case DLT_EN10MB: {
+ const struct ether_header *eth =
+ (const struct ether_header *)buffer;
+ ether_type = ntohs(eth->ether_type);
+ ll_hdr_len = sizeof(struct ether_header);
+ break;
+ }
+ default:
+ DBG_DEBUG("Unknown pcap packet type %d\n", pcap_packet_type);
+ return EPROTONOSUPPORT;
+ }
- /* we want either IPv4 or IPv6 */
- if (eth->ether_type == htons(ETHERTYPE_IP)) {
- ret = tcp4_extract(buffer + sizeof(struct ether_header),
- (size_t)(pkthdr.caplen -
- sizeof(struct ether_header)),
+ switch (ether_type) {
+ case ETHERTYPE_IP:
+ ret = tcp4_extract(buffer + ll_hdr_len,
+ (size_t)pkthdr.caplen - ll_hdr_len,
&src->ip,
&dst->ip,
ack_seq,
seq,
rst,
window);
- return ret;
-
- } else if (eth->ether_type == htons(ETHERTYPE_IP6)) {
- ret = tcp6_extract(buffer + sizeof(struct ether_header),
- (size_t)(pkthdr.caplen -
- sizeof(struct ether_header)),
+ break;
+ case ETHERTYPE_IP6:
+ ret = tcp6_extract(buffer + ll_hdr_len,
+ (size_t)pkthdr.caplen - ll_hdr_len,
&src->ip6,
&dst->ip6,
ack_seq,
seq,
rst,
window);
- return ret;
+ break;
+ case ETHERTYPE_ARP:
+ /* Silently ignore ARP packets */
+ return EPROTO;
+ default:
+ DBG_DEBUG("Unknown ether type %"PRIu16"\n", ether_type);
+ return EPROTO;
}
- return ENOMSG;
+ return ret;
}
#endif /* defined(HAVE_AF_PACKET) && !defined(ENABLE_PCAP) */