On Sat, Sep 19, 2020 at 2:07 PM Denis Fondras <open...@ledeuns.net> wrote:

> On Wed, Sep 16, 2020 at 03:06:32PM -0400, Sven F. wrote:
> > On Wed, Jun 3, 2020 at 2:13 PM sven falempin <sven.falem...@gmail.com>
> > wrote:
> >
>
> Can you send a proper diff please for review please ?
>

bpf.c is sort of ok, the rest need choices .
The configuration of bpf should probably be updated if someone changes the
lladdr after launching dhclient.
Index: bpf.c
===================================================================
RCS file: /cvs/src/sbin/dhclient/bpf.c,v
retrieving revision 1.75
diff -u -p -r1.75 bpf.c
--- bpf.c	18 Mar 2019 00:00:59 -0000	1.75
+++ bpf.c	21 Sep 2020 19:18:52 -0000
@@ -102,6 +102,49 @@ get_udp_sock(int rdomain)
 	return sock;
 }
 
+
+/*
+ * Packet MAC filter program.
+ *
+ * N.B.: Changes to the filter program may require changes to the
+ * constant offsets used in if_register_receive to patch the BPF program!
+ */
+
+struct bpf_insn dhcp_bpf_mac_filter[] = {
+	/* Make sure this is an IP packet. */
+	BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
+
+	/* Make sure it's a UDP packet. */
+	BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
+
+	/* Make sure this isn't a fragment. */
+	BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
+	BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 8, 0),
+
+	/* Get the IP header length. */
+	BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14),
+
+	/* Make sure it's to the right port. */
+	BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),		/* patch */
+
+	/* check bootp.hw.addr 2 bytes */
+	BPF_STMT(BPF_LD + BPF_H + BPF_IND, 50),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 0, 3),      /* patch */
+	/* check bootp.hw.addr 4 bytes */
+	BPF_STMT(BPF_LD + BPF_W + BPF_IND, 52),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x00000000, 0, 1),  /* patch */ 
+
+	/* If we passed all the tests, ask for the whole packet. */
+	BPF_STMT(BPF_RET+BPF_K, (unsigned int)-1),
+
+	/* Otherwise, drop it. */
+	BPF_STMT(BPF_RET+BPF_K, 0),
+};
+int dhcp_bpf_mac_filter_len = sizeof(dhcp_bpf_mac_filter) / sizeof(struct bpf_insn);
+
 /*
  * Packet filter program.
  *
@@ -177,13 +220,19 @@ struct bpf_insn dhcp_bpf_wfilter[] = {
 
 int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn);
 
+
+extern int cmd_opts;
+
 int
-configure_bpf_sock(int bpffd)
+configure_bpf_sock(struct interface_info *ifi)
 {
 	struct bpf_version	 v;
 	struct bpf_program	 p;
 	int			 flag = 1, sz;
 	int			 fildrop = BPF_FILDROP_CAPTURE;
+	uint32_t	 bits;
+	uint16_t	 bits16;
+	int bpffd = ifi->bpffd;
 
 	/* Make sure the BPF version is in range. */
 	if (ioctl(bpffd, BIOCVERSION, &v) == -1)
@@ -218,7 +267,18 @@ configure_bpf_sock(int bpffd)
 	 * N.B.: changes to filter program may require changes to the
 	 * insn number(s) used below!
 	 */
-	dhcp_bpf_filter[8].k = LOCAL_PORT;
+
+	if (cmd_opts & OPT_MAC_FITLER) {
+		p.bf_len = dhcp_bpf_mac_filter_len;
+		p.bf_insns = dhcp_bpf_mac_filter;
+		dhcp_bpf_mac_filter[8].k = LOCAL_PORT;
+		memcpy(&bits16, ifi->hw_address.ether_addr_octet, sizeof(bits16));
+		dhcp_bpf_mac_filter[10].k = ntohs(bits16);
+		memcpy(&bits, ifi->hw_address.ether_addr_octet + 2, sizeof(bits));
+		dhcp_bpf_mac_filter[12].k = ntohl(bits);
+	} else {
+		dhcp_bpf_filter[8].k = LOCAL_PORT;
+	}
 
 	if (ioctl(bpffd, BIOCSETF, &p) == -1)
 		fatal("BIOCSETF");
Index: dhclient.c
===================================================================
RCS file: /cvs/src/sbin/dhclient/dhclient.c,v
retrieving revision 1.678
diff -u -p -r1.678 dhclient.c
--- dhclient.c	31 Jul 2020 12:12:11 -0000	1.678
+++ dhclient.c	21 Sep 2020 19:18:53 -0000
@@ -471,7 +471,7 @@ main(int argc, char *argv[])
 
 	log_setverbose(0);	/* Don't show log_debug() messages. */
 
-	while ((ch = getopt(argc, argv, "c:di:L:nrv")) != -1)
+	while ((ch = getopt(argc, argv, "c:di:L:nrvm")) != -1)
 		switch (ch) {
 		case 'c':
 			if (optarg == NULL)
@@ -494,6 +494,9 @@ main(int argc, char *argv[])
 			cmd_opts |= OPT_DBPATH;
 			path_option_db = optarg;
 			break;
+		case 'm':
+			cmd_opts |= OPT_MAC_FITLER;
+			break;
 		case 'n':
 			cmd_opts |= OPT_NOACTION;
 			break;
@@ -670,7 +673,7 @@ main(int argc, char *argv[])
 	/* Create the udp and bpf sockets, growing rbuf if needed. */
 	ifi->udpfd = get_udp_sock(ifi->rdomain);
 	ifi->bpffd = get_bpf_sock(ifi->name);
-	newsize = configure_bpf_sock(ifi->bpffd);
+	newsize = configure_bpf_sock(ifi);
 	if (newsize > ifi->rbuf_max) {
 		if ((newp = realloc(ifi->rbuf, newsize)) == NULL)
 			fatal("rbuf");
Index: dhcpd.h
===================================================================
RCS file: /cvs/src/sbin/dhclient/dhcpd.h,v
retrieving revision 1.287
diff -u -p -r1.287 dhcpd.h
--- dhcpd.h	21 May 2020 01:07:52 -0000	1.287
+++ dhcpd.h	21 Sep 2020 19:18:53 -0000
@@ -191,7 +191,7 @@ void		 parse_warn(char *);
 /* bpf.c */
 int		 get_bpf_sock(char *);
 int		 get_udp_sock(int);
-int		 configure_bpf_sock(int);
+int		 configure_bpf_sock(struct interface_info *);
 ssize_t		 send_packet(struct interface_info *, struct in_addr,
     struct in_addr, const char *);
 ssize_t		 receive_packet(unsigned char *, unsigned char *,
@@ -218,6 +218,7 @@ extern int			 cmd_opts;
 #define		OPT_CONFPATH	0x10
 #define		OPT_DBPATH	0x20
 #define		OPT_IGNORELIST	0x40
+#define		OPT_MAC_FITLER	0x80
 
 void		 dhcpoffer(struct interface_info *, struct option_data *,
     const char *);

Reply via email to