From 18a5dcf9ef6f9bde77326bb363ec61bbf6b5e587 Mon Sep 17 00:00:00 2001
From: David Härdeman <david@hardeman.nu>
Date: Tue, 16 Jun 2020 10:42:56 +0200
Subject: Use SOCK_DGRAM instead of SOCK_RAW in igmp to not have to deal with
 ethernet headers

---
 igmp.c | 36 +++++++++++++-----------------------
 1 file changed, 13 insertions(+), 23 deletions(-)

diff --git a/igmp.c b/igmp.c
index b3d7d2c..ab55aef 100644
--- a/igmp.c
+++ b/igmp.c
@@ -175,18 +175,14 @@ igmp_match()
 }
 
 static void
-igmp_parse(struct cfg *cfg, struct igmp *igmp, int res)
+igmp_parse(struct cfg *cfg, struct igmp *igmp)
 {
-	char *buf = &igmp->task.tbuf->buf[ETH_HDR_LEN];
+	char *buf = igmp->task.tbuf->buf;
+	size_t len = igmp->task.tbuf->len;
 	struct ipv4_hdr *hdr = (struct ipv4_hdr *)buf;
 	size_t body_len;
 	union igmp_msg *igmp_msg;
-	size_t len;
 
-	if (res < ETH_HDR_LEN)
-		return;
-
-	len = res - ETH_HDR_LEN;
 	if (len <= IPV4_MIN_HDR_LEN)
 		return;
 
@@ -399,7 +395,7 @@ igmp_read_cb(struct cfg *cfg, struct uring_task *task, int res)
 
 	if (task->addr.storage.ss_family == AF_PACKET ||
 	    task->addr.ll.sll_protocol == htons(ETH_P_IP))
-		igmp_parse(cfg, igmp, res);
+		igmp_parse(cfg, igmp);
 	else
 		fprintf(stderr, "Invalid packet type received\n");
 
@@ -444,46 +440,41 @@ igmp_init(struct cfg *cfg)
 {
 	static const struct sock_filter filter[] = {
 		BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),					/* A <- packet length */
-		BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ethhdr) + sizeof(struct iphdr), 1, 0), /* A < eth + ip */
+		BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct iphdr), 1, 0),	/* A < sizeof(iphdr) */
                 BPF_STMT(BPF_RET + BPF_K, 0),						/* drop packet */
 
-                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_proto)),	/* A <- ethernet protocol */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0),		/* A != ETHERTYPE_IP */
-                BPF_STMT(BPF_RET + BPF_K, 0),						/* drop packet */
-
-		BPF_STMT(BPF_LD + BPF_B + BPF_ABS, sizeof(struct ethhdr) + 0 /* iphdr[0] */), /* A <- version + ihl */
+		BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 0 /* iphdr[0] */),			/* A <- version + ihl */
 		BPF_STMT(BPF_ALU + BPF_RSH + BPF_K, 4),					/* A <- A >> 4 (version) */
                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x04, 1, 0),			/* A != 4 */
                 BPF_STMT(BPF_RET + BPF_K, 0),						/* drop packet */
 
-		BPF_STMT(BPF_LD + BPF_B + BPF_ABS, sizeof(struct ethhdr) + offsetof(struct iphdr, protocol)), /* A <- ip protocol */
+		BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct iphdr, protocol)),	/* A <- ip protocol */
                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_IGMP, 1, 0),		/* A != IPPROTO_IGMP */
                 BPF_STMT(BPF_RET + BPF_K, 0),						/* drop packet */
 
-		BPF_STMT(BPF_LD + BPF_W + BPF_ABS, sizeof(struct ethhdr) + offsetof(struct iphdr, daddr)),	/* A <- ip dst addr */
+		BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct iphdr, daddr)),	/* A <- ip dst addr */
                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, chtobe32(cinet_addr(224,0,2,60)), 2, 0),	/* A != 224.0.2.60 */
                 //BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0xe000023c, 2, 0),			/* A != 224.0.2.60 */
                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, chtobe32(cinet_addr(224,0,0,22)), 1, 0),	/* A != 224.0.0.22 */
                 //BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0xe0000016, 1, 0),			/* A != 224.0.0.22 */
                 BPF_STMT(BPF_RET + BPF_K, 0),						/* drop packet */
 
-		BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, sizeof(struct ethhdr) + 0 /* iphdr[0] */), /* X <- pkt->ihl * 4 */
+		BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 0 /* iphdr[0] */),			/* X <- pkt->ihl * 4 */
 		BPF_STMT(BPF_LD + BPF_IMM, 20),						/* A <- 20 */
 		BPF_JUMP(BPF_JMP + BPF_JGT + BPF_X, 0, 0, 1),				/* A > X */
                 BPF_STMT(BPF_RET + BPF_K, 0),						/* drop packet */
 
-		BPF_STMT(BPF_LD + BPF_H + BPF_ABS, sizeof(struct ethhdr) + offsetof(struct iphdr, tot_len)), /* A <- ip tot_len */
+		BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct iphdr, tot_len)),	/* A <- ip tot_len */
 		BPF_JUMP(BPF_JMP + BPF_JGT + BPF_X, 0, 1, 0),				/* A <= ip->ihl * 4 */ 
                 BPF_STMT(BPF_RET + BPF_K, 0),						/* drop packet */
 		BPF_STMT(BPF_ALU + BPF_SUB + BPF_X, 0),					/* A <- A - X (bodylen) */
 		BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, 8, 1, 0),				/* A < 8 */
                 BPF_STMT(BPF_RET + BPF_K, 0),						/* drop packet */
 
-		BPF_STMT(BPF_LD + BPF_H + BPF_ABS, sizeof(struct ethhdr) + offsetof(struct iphdr, tot_len)), /* A <- ip->tot_len */
-		BPF_STMT(BPF_ALU + BPF_ADD + BPF_K, sizeof(struct ethhdr)),             /* A <- A + sizeof(struct ethhdr) */
+		BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct iphdr, tot_len)),	/* A <- ip->tot_len */
 		BPF_STMT(BPF_MISC + BPF_TAX, 0),					/* X <- A */
 		BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),					/* A <- packet length */
-		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0),				/* A != sizeof(ethhdr) + ip->tot_len */
+		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0),				/* A != ip->tot_len */
                 BPF_STMT(BPF_RET + BPF_K, 0),						/* drop packet */
 
                 BPF_STMT(BPF_RET + BPF_K, (uint32_t) -1),				/* accept packet */
@@ -508,7 +499,7 @@ igmp_init(struct cfg *cfg)
 	 * Kernel limitation, must be ETH_P_ALL, not ETH_P_IP or we won't get
 	 * outgoing packets, https://lkml.org/lkml/1999/12/23/112
 	 */
-	sfd = socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC, htons(ETH_P_ALL));
+	sfd = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, htons(ETH_P_ALL));
 	if (sfd < 0) {
 		perror("igmp socket");
 		goto out_free;
@@ -547,7 +538,6 @@ igmp_init(struct cfg *cfg)
 	*/
 
 	/* can't set .sll_protocol to htons(ETH_P_IP), see comment above */
-
 	if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
 		perror("bind");
 		goto out_fd;
-- 
cgit v1.2.3