]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wpa_supplicant: Don't reply to EAPOL if pkt_type is PACKET_OTHERHOST
authorDavide Caratti <davide.caratti@gmail.com>
Wed, 28 Mar 2018 14:34:56 +0000 (16:34 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 2 Apr 2018 09:21:27 +0000 (12:21 +0300)
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 <davide.caratti@gmail.com>
src/l2_packet/l2_packet.h
src/l2_packet/l2_packet_linux.c
wpa_supplicant/wpa_supplicant.c

index 2a452458214be7d124c2e8481829893b553733d1..53871774b4e75d486cfb6ff30d2af895c0d3e4b9 100644 (file)
@@ -42,6 +42,7 @@ struct l2_ethhdr {
 enum l2_packet_filter_type {
        L2_PACKET_FILTER_DHCP,
        L2_PACKET_FILTER_NDISC,
+       L2_PACKET_FILTER_PKTTYPE,
 };
 
 /**
index 65b490679a08cfcf03514d1c5f50d0dae4e78d2a..291c9dd263a6e6279862fe9442eb8d0bd6fbe955 100644 (file)
@@ -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 - <<EOF
+ * > 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;
        }
index 2a05ef910f95fd2fd0bed212864ce60f07ccd666..dcec68a0383b4ecd553ee904eb25152e5c23809b 100644 (file)
@@ -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)