From d89edb6112f54fb65036c31eba291bda5fcad2b3 Mon Sep 17 00:00:00 2001 From: Davide Caratti Date: Wed, 28 Mar 2018 16:34:56 +0200 Subject: [PATCH] wpa_supplicant: Don't reply to EAPOL if pkt_type is PACKET_OTHERHOST When wpa_supplicant is running on a Linux interface that is configured in promiscuous mode, and it is not a member of a bridge, incoming EAPOL packets are processed regardless of the Destination Address in the frame. As a consequence, there are situations where wpa_supplicant replies to EAPOL packets that are not destined for it. This behavior seems undesired (see IEEE Std 802.1X-2010, 11.4.a), and can be avoided by attaching a BPF filter that lets the kernel discard packets having pkt_type equal to PACKET_OTHERHOST. Signed-off-by: Davide Caratti --- src/l2_packet/l2_packet.h | 1 + src/l2_packet/l2_packet_linux.c | 23 +++++++++++++++++++++++ wpa_supplicant/wpa_supplicant.c | 5 +++++ 3 files changed, 29 insertions(+) diff --git a/src/l2_packet/l2_packet.h b/src/l2_packet/l2_packet.h index 2a4524582..53871774b 100644 --- a/src/l2_packet/l2_packet.h +++ b/src/l2_packet/l2_packet.h @@ -42,6 +42,7 @@ struct l2_ethhdr { enum l2_packet_filter_type { L2_PACKET_FILTER_DHCP, L2_PACKET_FILTER_NDISC, + L2_PACKET_FILTER_PKTTYPE, }; /** diff --git a/src/l2_packet/l2_packet_linux.c b/src/l2_packet/l2_packet_linux.c index 65b490679..291c9dd26 100644 --- a/src/l2_packet/l2_packet_linux.c +++ b/src/l2_packet/l2_packet_linux.c @@ -84,6 +84,26 @@ static const struct sock_fprog ndisc_sock_filter = { .filter = ndisc_sock_filter_insns, }; +/* drop packet if skb->pkt_type is PACKET_OTHERHOST (0x03). Generated by: + * $ bpfc - < ldb #type + * > jeq #0x03, drop + * > pass: ret #-1 + * > drop: ret #0 + * > EOF + */ +static struct sock_filter pkt_type_filter_insns[] = { + { 0x30, 0, 0, 0xfffff004 }, + { 0x15, 1, 0, 0x00000003 }, + { 0x6, 0, 0, 0xffffffff }, + { 0x6, 0, 0, 0x00000000 }, +}; + +static const struct sock_fprog pkt_type_sock_filter = { + .len = ARRAY_SIZE(pkt_type_filter_insns), + .filter = pkt_type_filter_insns, +}; + int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) { @@ -471,6 +491,9 @@ int l2_packet_set_packet_filter(struct l2_packet_data *l2, case L2_PACKET_FILTER_NDISC: sock_filter = &ndisc_sock_filter; break; + case L2_PACKET_FILTER_PKTTYPE: + sock_filter = &pkt_type_sock_filter; + break; default: return -1; } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 2a05ef910..dcec68a03 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4014,6 +4014,11 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) wpa_supplicant_rx_eapol, wpa_s, 0); if (wpa_s->l2 == NULL) return -1; + + if (l2_packet_set_packet_filter(wpa_s->l2, + L2_PACKET_FILTER_PKTTYPE)) + wpa_dbg(wpa_s, MSG_DEBUG, + "Failed to attach pkt_type filter"); } else { const u8 *addr = wpa_drv_get_mac_addr(wpa_s); if (addr)