#include "common.h"
#include "eloop.h"
+#include "crypto/sha1.h"
+#include "crypto/crypto.h"
#include "l2_packet.h"
/* For working around Linux packet socket behavior and regression. */
int fd_br_rx;
+ int last_from_br;
+ u8 last_hash[SHA1_MAC_LEN];
+ unsigned int num_rx, num_rx_br;
};
/* Generated by 'sudo tcpdump -s 3000 -dd greater 278 and ip and udp and
struct sockaddr_ll ll;
socklen_t fromlen;
+ l2->num_rx++;
os_memset(&ll, 0, sizeof(ll));
fromlen = sizeof(ll);
res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
return;
}
+ wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d",
+ __func__, MAC2STR(ll.sll_addr), (int) res);
+
if (l2->fd_br_rx >= 0) {
- wpa_printf(MSG_DEBUG, "l2_packet_receive: Main packet socket for %s seems to have working RX - close workaround bridge socket",
- l2->ifname);
- eloop_unregister_read_sock(l2->fd_br_rx);
- close(l2->fd_br_rx);
- l2->fd_br_rx = -1;
+ u8 hash[SHA1_MAC_LEN];
+ const u8 *addr[1];
+ size_t len[1];
+
+ /*
+ * Close the workaround socket if the kernel version seems to be
+ * able to deliver packets through the packet socket before
+ * authorization has been completed (in dormant state).
+ */
+ if (l2->num_rx_br <= 1) {
+ wpa_printf(MSG_DEBUG,
+ "l2_packet_receive: Main packet socket for %s seems to have working RX - close workaround bridge socket",
+ l2->ifname);
+ eloop_unregister_read_sock(l2->fd_br_rx);
+ close(l2->fd_br_rx);
+ l2->fd_br_rx = -1;
+ }
+
+ addr[0] = buf;
+ len[0] = res;
+ sha1_vector(1, addr, len, hash);
+ if (l2->last_from_br &&
+ os_memcmp(hash, l2->last_hash, SHA1_MAC_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX",
+ __func__);
+ return;
+ }
+ os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
}
+ l2->last_from_br = 0;
l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
}
int res;
struct sockaddr_ll ll;
socklen_t fromlen;
+ u8 hash[SHA1_MAC_LEN];
+ const u8 *addr[1];
+ size_t len[1];
+ l2->num_rx_br++;
os_memset(&ll, 0, sizeof(ll));
fromlen = sizeof(ll);
res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
return;
}
+ wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d",
+ __func__, MAC2STR(ll.sll_addr), (int) res);
+
+ addr[0] = buf;
+ len[0] = res;
+ sha1_vector(1, addr, len, hash);
+ if (!l2->last_from_br &&
+ os_memcmp(hash, l2->last_hash, SHA1_MAC_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", __func__);
+ return;
+ }
+ l2->last_from_br = 1;
+ os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
}