16c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/* 26c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Generic Snooping for Proxy ARP 36c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Copyright (c) 2014, Qualcomm Atheros, Inc. 46c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * 56c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * This software may be distributed under the terms of the BSD license. 66c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * See README for more details. 76c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 86c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 96c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "utils/includes.h" 106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "utils/common.h" 126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "hostapd.h" 136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "sta_info.h" 146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "ap_drv_ops.h" 156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "x_snoop.h" 166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint x_snoop_init(struct hostapd_data *hapd) 196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct hostapd_bss_config *conf = hapd->conf; 216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!conf->isolate) { 236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "x_snoop: ap_isolate must be enabled for x_snoop"); 256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (conf->bridge[0] == '\0') { 296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "x_snoop: Bridge must be configured for x_snoop"); 316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1)) { 366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "x_snoop: Failed to enable hairpin_mode on the bridge port"); 386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) { 426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "x_snoop: Failed to enable proxyarp on the bridge port"); 446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1)) { 496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "x_snoop: Failed to enable accepting gratuitous ARP on the bridge"); 516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 548347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt#ifdef CONFIG_IPV6 558347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) { 568347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt wpa_printf(MSG_DEBUG, 578347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt "x_snoop: Failed to enable multicast snooping on the bridge"); 588347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt return -1; 598347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt } 608347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt#endif /* CONFIG_IPV6 */ 618347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt 626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstruct l2_packet_data * 676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtx_snoop_get_l2_packet(struct hostapd_data *hapd, 686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt void (*handler)(void *ctx, const u8 *src_addr, 696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *buf, size_t len), 706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum l2_packet_filter_type type) 716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct hostapd_bss_config *conf = hapd->conf; 736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct l2_packet_data *l2; 746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1); 766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (l2 == NULL) { 776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "x_snoop: Failed to initialize L2 packet processing %s", 796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt strerror(errno)); 806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (l2_packet_set_packet_filter(l2, type)) { 846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "x_snoop: Failed to set L2 packet filter for type: %d", 866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type); 876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt l2_packet_deinit(l2); 886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return l2; 926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid x_snoop_mcast_to_ucast_convert_send(struct hostapd_data *hapd, 966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct sta_info *sta, u8 *buf, 976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t len) 986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int res; 1006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 addr[ETH_ALEN]; 1016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 *dst_addr = buf; 1026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(dst_addr[0] & 0x01)) 1046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 1056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_EXCESSIVE, "x_snoop: Multicast-to-unicast conversion " 1076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MACSTR " -> " MACSTR " (len %u)", 1086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(dst_addr), MAC2STR(sta->addr), (unsigned int) len); 1096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* save the multicast destination address for restoring it later */ 1116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(addr, buf, ETH_ALEN); 1126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(buf, sta->addr, ETH_ALEN); 1146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = l2_packet_send(hapd->sock_dhcp, NULL, 0, buf, len); 1156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res < 0) { 1166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 1176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "x_snoop: Failed to send mcast to ucast converted packet to " 1186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MACSTR, MAC2STR(sta->addr)); 1196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 1206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* restore the multicast destination address */ 1226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(buf, addr, ETH_ALEN); 1236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 1246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid x_snoop_deinit(struct hostapd_data *hapd) 1276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 1286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0); 1296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0); 1306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0); 1316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 132