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 <davide.caratti@gmail.com>
This commit is contained in:
Davide Caratti 2018-03-28 16:34:56 +02:00 committed by Jouni Malinen
parent 8fb2b35735
commit d89edb6112
3 changed files with 29 additions and 0 deletions

View 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,
};
/**

View 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;
}

View 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)