Browse Source

l2_packet: Add support for DHCP packet filter in l2_packet_linux

Signed-off-by: Kyeyoon Park <kyeyoonp@qca.qualcomm.com>
Kyeyoon Park 10 years ago
parent
commit
7d20dd66f3

+ 16 - 0
src/l2_packet/l2_packet.h

@@ -39,6 +39,10 @@ struct l2_ethhdr {
 #pragma pack(pop)
 #endif /* _MSC_VER */
 
+enum l2_packet_filter_type {
+	L2_PACKET_FILTER_DHCP,
+};
+
 /**
  * l2_packet_init - Initialize l2_packet interface
  * @ifname: Interface name
@@ -121,4 +125,16 @@ int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len);
  */
 void l2_packet_notify_auth_start(struct l2_packet_data *l2);
 
+/**
+ * l2_packet_set_packet_filter - Set socket filter for l2_packet
+ * @l2: Pointer to internal l2_packet data from l2_packet_init()
+ * @type: enum l2_packet_filter_type, type of filter
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to set the socket filter for l2_packet socket.
+ *
+ */
+int l2_packet_set_packet_filter(struct l2_packet_data *l2,
+				enum l2_packet_filter_type type);
+
 #endif /* L2_PACKET_H */

+ 7 - 0
src/l2_packet/l2_packet_freebsd.c

@@ -308,3 +308,10 @@ int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 }
+
+
+int l2_packet_set_packet_filter(struct l2_packet_data *l2,
+				enum l2_packet_filter_type type)
+{
+	return -1;
+}

+ 52 - 0
src/l2_packet/l2_packet_linux.c

@@ -10,6 +10,7 @@
 #include <sys/ioctl.h>
 #include <netpacket/packet.h>
 #include <net/if.h>
+#include <linux/filter.h>
 
 #include "common.h"
 #include "eloop.h"
@@ -28,6 +29,32 @@ struct l2_packet_data {
 		     * buffers */
 };
 
+/* Generated by 'sudo tcpdump -s 3000 -dd greater 278 and ip and udp and
+ * src port bootps and dst port bootpc'
+ */
+static struct sock_filter dhcp_sock_filter_insns[] = {
+	{ 0x80, 0, 0, 0x00000000 },
+	{ 0x35, 0, 12, 0x00000116 },
+	{ 0x28, 0, 0, 0x0000000c },
+	{ 0x15, 0, 10, 0x00000800 },
+	{ 0x30, 0, 0, 0x00000017 },
+	{ 0x15, 0, 8, 0x00000011 },
+	{ 0x28, 0, 0, 0x00000014 },
+	{ 0x45, 6, 0, 0x00001fff },
+	{ 0xb1, 0, 0, 0x0000000e },
+	{ 0x48, 0, 0, 0x0000000e },
+	{ 0x15, 0, 3, 0x00000043 },
+	{ 0x48, 0, 0, 0x00000010 },
+	{ 0x15, 0, 1, 0x00000044 },
+	{ 0x6, 0, 0, 0x00000bb8 },
+	{ 0x6, 0, 0, 0x00000000 },
+};
+
+static const struct sock_fprog dhcp_sock_filter = {
+	.len = ARRAY_SIZE(dhcp_sock_filter_insns),
+	.filter = dhcp_sock_filter_insns,
+};
+
 
 int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
 {
@@ -202,3 +229,28 @@ int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 }
+
+
+int l2_packet_set_packet_filter(struct l2_packet_data *l2,
+				enum l2_packet_filter_type type)
+{
+	const struct sock_fprog *sock_filter;
+
+	switch (type) {
+	case L2_PACKET_FILTER_DHCP:
+		sock_filter = &dhcp_sock_filter;
+		break;
+	default:
+		return -1;
+	}
+
+	if (setsockopt(l2->fd, SOL_SOCKET, SO_ATTACH_FILTER,
+		       sock_filter, sizeof(struct sock_fprog))) {
+		wpa_printf(MSG_ERROR,
+			   "l2_packet_linux: setsockopt(SO_ATTACH_FILTER) failed: %s",
+			   strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}

+ 7 - 0
src/l2_packet/l2_packet_ndis.c

@@ -514,3 +514,10 @@ int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 }
+
+
+int l2_packet_set_packet_filter(struct l2_packet_data *l2,
+				enum l2_packet_filter_type type)
+{
+	return -1;
+}

+ 7 - 0
src/l2_packet/l2_packet_none.c

@@ -116,3 +116,10 @@ void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 	/* This function can be left empty */
 }
+
+
+int l2_packet_set_packet_filter(struct l2_packet_data *l2,
+				enum l2_packet_filter_type type)
+{
+	return -1;
+}

+ 7 - 0
src/l2_packet/l2_packet_pcap.c

@@ -378,3 +378,10 @@ void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 			       l2, l2->pcap);
 #endif /* CONFIG_WINPCAP */
 }
+
+
+int l2_packet_set_packet_filter(struct l2_packet_data *l2,
+				enum l2_packet_filter_type type)
+{
+	return -1;
+}

+ 7 - 0
src/l2_packet/l2_packet_privsep.c

@@ -259,3 +259,10 @@ void l2_packet_notify_auth_start(struct l2_packet_data *l2)
 {
 	wpa_priv_cmd(l2, PRIVSEP_CMD_L2_NOTIFY_AUTH_START, NULL, 0);
 }
+
+
+int l2_packet_set_packet_filter(struct l2_packet_data *l2,
+				enum l2_packet_filter_type type)
+{
+	return -1;
+}