18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - Layer2 packet handling with Linux packet sockets 3216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/ioctl.h> 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netpacket/packet.h> 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <net/if.h> 136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include <linux/filter.h> 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 177f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#include "crypto/sha1.h" 187f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#include "crypto/crypto.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct l2_packet_data { 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int fd; /* packet socket for EAPOL frames */ 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char ifname[IFNAMSIZ + 1]; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 own_addr[ETH_ALEN]; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*rx_callback)(void *ctx, const u8 *src_addr, 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len); 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *rx_callback_ctx; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int l2_hdr; /* whether to include layer 2 (Ethernet) header data 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * buffers */ 32216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 33216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt /* For working around Linux packet socket behavior and regression. */ 34216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt int fd_br_rx; 357f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt int last_from_br; 367f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt u8 last_hash[SHA1_MAC_LEN]; 377f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt unsigned int num_rx, num_rx_br; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/* Generated by 'sudo tcpdump -s 3000 -dd greater 278 and ip and udp and 416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * src port bootps and dst port bootpc' 426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct sock_filter dhcp_sock_filter_insns[] = { 446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x80, 0, 0, 0x00000000 }, 456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x35, 0, 12, 0x00000116 }, 466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x28, 0, 0, 0x0000000c }, 476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x15, 0, 10, 0x00000800 }, 486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x30, 0, 0, 0x00000017 }, 496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x15, 0, 8, 0x00000011 }, 506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x28, 0, 0, 0x00000014 }, 516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x45, 6, 0, 0x00001fff }, 526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0xb1, 0, 0, 0x0000000e }, 536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x48, 0, 0, 0x0000000e }, 546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x15, 0, 3, 0x00000043 }, 556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x48, 0, 0, 0x00000010 }, 566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x15, 0, 1, 0x00000044 }, 576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x6, 0, 0, 0x00000bb8 }, 586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x6, 0, 0, 0x00000000 }, 596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}; 606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic const struct sock_fprog dhcp_sock_filter = { 626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .len = ARRAY_SIZE(dhcp_sock_filter_insns), 636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .filter = dhcp_sock_filter_insns, 646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}; 656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/* Generated by 'sudo tcpdump -dd -s 1500 multicast and ip6[6]=58' */ 686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct sock_filter ndisc_sock_filter_insns[] = { 696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x30, 0, 0, 0x00000000 }, 706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x45, 0, 5, 0x00000001 }, 716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x28, 0, 0, 0x0000000c }, 726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x15, 0, 3, 0x000086dd }, 736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x30, 0, 0, 0x00000014 }, 746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x15, 0, 1, 0x0000003a }, 756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x6, 0, 0, 0x000005dc }, 766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 0x6, 0, 0, 0x00000000 }, 776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}; 786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic const struct sock_fprog ndisc_sock_filter = { 806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .len = ARRAY_SIZE(ndisc_sock_filter_insns), 816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .filter = ndisc_sock_filter_insns, 826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}; 836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(addr, l2->own_addr, ETH_ALEN); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2 == NULL) 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2->l2_hdr) { 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send(l2->fd, buf, len, 0); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "l2_packet_send - send: %s", 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strerror(errno)); 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_ll ll; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ll, 0, sizeof(ll)); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ll.sll_family = AF_PACKET; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ll.sll_ifindex = l2->ifindex; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ll.sll_protocol = htons(proto); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ll.sll_halen = ETH_ALEN; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ll.sll_addr, dst_addr, ETH_ALEN); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = sendto(l2->fd, buf, len, 0, (struct sockaddr *) &ll, 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(ll)); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "l2_packet_send - sendto: %s", 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strerror(errno)); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct l2_packet_data *l2 = eloop_ctx; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[2300]; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_ll ll; 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1307f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt l2->num_rx++; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ll, 0, sizeof(ll)); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen = sizeof(ll); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll, 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &fromlen); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "l2_packet_receive - recvfrom: %s", 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strerror(errno)); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1417f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d", 1427f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt __func__, MAC2STR(ll.sll_addr), (int) res); 143216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 144216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (l2->fd_br_rx >= 0) { 1457f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 1467f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt const u8 *addr[1]; 1477f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt size_t len[1]; 1487f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 1497f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt /* 1507f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * Close the workaround socket if the kernel version seems to be 1517f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * able to deliver packets through the packet socket before 1527f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * authorization has been completed (in dormant state). 1537f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt */ 1547f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (l2->num_rx_br <= 1) { 1557f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 1567f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "l2_packet_receive: Main packet socket for %s seems to have working RX - close workaround bridge socket", 1577f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt l2->ifname); 1587f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt eloop_unregister_read_sock(l2->fd_br_rx); 1597f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt close(l2->fd_br_rx); 1607f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt l2->fd_br_rx = -1; 1617f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 1627f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 1637f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt addr[0] = buf; 1647f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt len[0] = res; 1657f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt sha1_vector(1, addr, len, hash); 1667f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (l2->last_from_br && 1677f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt os_memcmp(hash, l2->last_hash, SHA1_MAC_LEN) == 0) { 1687f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", 1697f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt __func__); 1707f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return; 1717f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 1727f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN); 173216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 1747f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 1757f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt l2->last_from_br = 0; 1767f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); 177216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt} 178216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 179216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 180216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic void l2_packet_receive_br(int sock, void *eloop_ctx, void *sock_ctx) 181216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{ 182216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt struct l2_packet_data *l2 = eloop_ctx; 183216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt u8 buf[2300]; 184216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt int res; 185216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt struct sockaddr_ll ll; 186216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt socklen_t fromlen; 1877f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 1887f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt const u8 *addr[1]; 1897f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt size_t len[1]; 190216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 1917f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt l2->num_rx_br++; 192216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt os_memset(&ll, 0, sizeof(ll)); 193216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt fromlen = sizeof(ll); 194216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll, 195216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt &fromlen); 196216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (res < 0) { 197216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_printf(MSG_DEBUG, "l2_packet_receive_br - recvfrom: %s", 198216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt strerror(errno)); 199216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return; 200216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 201216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 2027f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d", 2037f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt __func__, MAC2STR(ll.sll_addr), (int) res); 2047f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 2057f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt addr[0] = buf; 2067f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt len[0] = res; 2077f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt sha1_vector(1, addr, len, hash); 2087f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!l2->last_from_br && 2097f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt os_memcmp(hash, l2->last_hash, SHA1_MAC_LEN) == 0) { 2107f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", __func__); 2117f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return; 2127f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 2137f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt l2->last_from_br = 1; 2147f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN); 215216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct l2_packet_data * l2_packet_init( 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname, const u8 *own_addr, unsigned short protocol, 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*rx_callback)(void *ctx, const u8 *src_addr, 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len), 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *rx_callback_ctx, int l2_hdr) 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct l2_packet_data *l2; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ifreq ifr; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_ll ll; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2 = os_zalloc(sizeof(struct l2_packet_data)); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2 == NULL) 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->rx_callback = rx_callback; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->rx_callback_ctx = rx_callback_ctx; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->l2_hdr = l2_hdr; 236216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt l2->fd_br_rx = -1; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt htons(protocol)); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2->fd < 0) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: socket(PF_PACKET): %s", 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, strerror(errno)); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ifr, 0, sizeof(ifr)); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) { 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFINDEX]: %s", 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, strerror(errno)); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(l2->fd); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->ifindex = ifr.ifr_ifindex; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ll, 0, sizeof(ll)); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ll.sll_family = PF_PACKET; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ll.sll_ifindex = ifr.ifr_ifindex; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ll.sll_protocol = htons(protocol); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) { 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: bind[PF_PACKET]: %s", 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, strerror(errno)); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(l2->fd); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) < 0) { 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFHWADDR]: %s", 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, strerror(errno)); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(l2->fd); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return l2; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 284216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstruct l2_packet_data * l2_packet_init_bridge( 285216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt const char *br_ifname, const char *ifname, const u8 *own_addr, 286216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt unsigned short protocol, 287216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt void (*rx_callback)(void *ctx, const u8 *src_addr, 288216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt const u8 *buf, size_t len), 289216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt void *rx_callback_ctx, int l2_hdr) 290216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{ 291216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt struct l2_packet_data *l2; 292216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt struct sock_filter ethertype_sock_filter_insns[] = { 293216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt /* Load ethertype */ 294216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 2 * ETH_ALEN), 295216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt /* Jump over next statement if ethertype does not match */ 296216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, protocol, 0, 1), 297216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt /* Ethertype match - return all */ 298216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt BPF_STMT(BPF_RET | BPF_K, ~0), 299216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt /* No match - drop */ 300216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt BPF_STMT(BPF_RET | BPF_K, 0) 301216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt }; 302216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt const struct sock_fprog ethertype_sock_filter = { 303216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt .len = ARRAY_SIZE(ethertype_sock_filter_insns), 304216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt .filter = ethertype_sock_filter_insns, 305216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt }; 306216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt struct sockaddr_ll ll; 307216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 308216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt l2 = l2_packet_init(br_ifname, own_addr, protocol, rx_callback, 309216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt rx_callback_ctx, l2_hdr); 310216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (!l2) 311216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return NULL; 312216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 313216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt /* 314216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * The Linux packet socket behavior has changed over the years and there 315216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * is an inconvenient regression in it that breaks RX for a specific 316216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * protocol from interfaces in a bridge when that interface is not in 317216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * fully operation state (i.e., when in station mode and not completed 318216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * authorization). To work around this, register ETH_P_ALL version of 319216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * the packet socket bound to the real netdev and use socket filter to 320216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * match the ethertype value. This version is less efficient, but 321216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * required for functionality with many kernel version. If the main 322216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * packet socket is found to be working, this less efficient version 323216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt * gets closed automatically. 324216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt */ 325216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 326216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt l2->fd_br_rx = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, 327216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt htons(ETH_P_ALL)); 328216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (l2->fd_br_rx < 0) { 329216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: socket(PF_PACKET-fd_br_rx): %s", 330216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt __func__, strerror(errno)); 331216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt /* try to continue without the workaround RX socket */ 332216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return l2; 333216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 334216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 335216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt os_memset(&ll, 0, sizeof(ll)); 336216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt ll.sll_family = PF_PACKET; 337216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt ll.sll_ifindex = if_nametoindex(ifname); 338216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt ll.sll_protocol = htons(ETH_P_ALL); 339216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (bind(l2->fd_br_rx, (struct sockaddr *) &ll, sizeof(ll)) < 0) { 340216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: bind[PF_PACKET-fd_br_rx]: %s", 341216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt __func__, strerror(errno)); 342216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt /* try to continue without the workaround RX socket */ 343216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt close(l2->fd_br_rx); 344216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt l2->fd_br_rx = -1; 345216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return l2; 346216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 347216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 348216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (setsockopt(l2->fd_br_rx, SOL_SOCKET, SO_ATTACH_FILTER, 349216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt ðertype_sock_filter, sizeof(struct sock_fprog))) { 350216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_printf(MSG_DEBUG, 351216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "l2_packet_linux: setsockopt(SO_ATTACH_FILTER) failed: %s", 352216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt strerror(errno)); 353216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt /* try to continue without the workaround RX socket */ 354216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt close(l2->fd_br_rx); 355216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt l2->fd_br_rx = -1; 356216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return l2; 357216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 358216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 359216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt eloop_register_read_sock(l2->fd_br_rx, l2_packet_receive_br, l2, NULL); 360216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 361216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return l2; 362216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt} 363216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 364216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid l2_packet_deinit(struct l2_packet_data *l2) 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2 == NULL) 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2->fd >= 0) { 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(l2->fd); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(l2->fd); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 374216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 375216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (l2->fd_br_rx >= 0) { 376216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt eloop_unregister_read_sock(l2->fd_br_rx); 377216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt close(l2->fd_br_rx); 378216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 379216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int s; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ifreq ifr; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *saddr; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t res; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = socket(PF_INET, SOCK_DGRAM, 0); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s < 0) { 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: socket: %s", 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, strerror(errno)); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ifr, 0, sizeof(ifr)); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (errno != EADDRNOTAVAIL) 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFADDR]: %s", 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, strerror(errno)); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(s); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(s); 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt saddr = aliasing_hide_typecast(&ifr.ifr_addr, struct sockaddr_in); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (saddr->sin_family != AF_INET) 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = os_strlcpy(buf, inet_ntoa(saddr->sin_addr), len); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res >= len) 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid l2_packet_notify_auth_start(struct l2_packet_data *l2) 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint l2_packet_set_packet_filter(struct l2_packet_data *l2, 4236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum l2_packet_filter_type type) 4246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 4256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const struct sock_fprog *sock_filter; 4266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (type) { 4286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case L2_PACKET_FILTER_DHCP: 4296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sock_filter = &dhcp_sock_filter; 4306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 4316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case L2_PACKET_FILTER_NDISC: 4326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sock_filter = &ndisc_sock_filter; 4336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 4346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 4356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 4366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 4376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (setsockopt(l2->fd, SOL_SOCKET, SO_ATTACH_FILTER, 4396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sock_filter, sizeof(struct sock_fprog))) { 4406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, 4416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "l2_packet_linux: setsockopt(SO_ATTACH_FILTER) failed: %s", 4426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt strerror(errno)); 4436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 4446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 4456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 4476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 448