xref: /dflybsd-src/contrib/wpa_supplicant/src/ap/x_snoop.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
1*a1157835SDaniel Fojt /*
2*a1157835SDaniel Fojt  * Generic Snooping for Proxy ARP
3*a1157835SDaniel Fojt  * Copyright (c) 2014, Qualcomm Atheros, Inc.
4*a1157835SDaniel Fojt  *
5*a1157835SDaniel Fojt  * This software may be distributed under the terms of the BSD license.
6*a1157835SDaniel Fojt  * See README for more details.
7*a1157835SDaniel Fojt  */
8*a1157835SDaniel Fojt 
9*a1157835SDaniel Fojt #include "utils/includes.h"
10*a1157835SDaniel Fojt 
11*a1157835SDaniel Fojt #include "utils/common.h"
12*a1157835SDaniel Fojt #include "hostapd.h"
13*a1157835SDaniel Fojt #include "sta_info.h"
14*a1157835SDaniel Fojt #include "ap_drv_ops.h"
15*a1157835SDaniel Fojt #include "x_snoop.h"
16*a1157835SDaniel Fojt 
17*a1157835SDaniel Fojt 
x_snoop_init(struct hostapd_data * hapd)18*a1157835SDaniel Fojt int x_snoop_init(struct hostapd_data *hapd)
19*a1157835SDaniel Fojt {
20*a1157835SDaniel Fojt 	struct hostapd_bss_config *conf = hapd->conf;
21*a1157835SDaniel Fojt 
22*a1157835SDaniel Fojt 	if (!conf->isolate) {
23*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
24*a1157835SDaniel Fojt 			   "x_snoop: ap_isolate must be enabled for x_snoop");
25*a1157835SDaniel Fojt 		return -1;
26*a1157835SDaniel Fojt 	}
27*a1157835SDaniel Fojt 
28*a1157835SDaniel Fojt 	if (conf->bridge[0] == '\0') {
29*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
30*a1157835SDaniel Fojt 			   "x_snoop: Bridge must be configured for x_snoop");
31*a1157835SDaniel Fojt 		return -1;
32*a1157835SDaniel Fojt 	}
33*a1157835SDaniel Fojt 
34*a1157835SDaniel Fojt 	if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE,
35*a1157835SDaniel Fojt 					 1)) {
36*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
37*a1157835SDaniel Fojt 			   "x_snoop: Failed to enable hairpin_mode on the bridge port");
38*a1157835SDaniel Fojt 		return -1;
39*a1157835SDaniel Fojt 	}
40*a1157835SDaniel Fojt 
41*a1157835SDaniel Fojt 	if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) {
42*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
43*a1157835SDaniel Fojt 			   "x_snoop: Failed to enable proxyarp on the bridge port");
44*a1157835SDaniel Fojt 		return -1;
45*a1157835SDaniel Fojt 	}
46*a1157835SDaniel Fojt 
47*a1157835SDaniel Fojt 	if (hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
48*a1157835SDaniel Fojt 					 1)) {
49*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
50*a1157835SDaniel Fojt 			   "x_snoop: Failed to enable accepting gratuitous ARP on the bridge");
51*a1157835SDaniel Fojt 		return -1;
52*a1157835SDaniel Fojt 	}
53*a1157835SDaniel Fojt 
54*a1157835SDaniel Fojt #ifdef CONFIG_IPV6
55*a1157835SDaniel Fojt 	if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
56*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
57*a1157835SDaniel Fojt 			   "x_snoop: Failed to enable multicast snooping on the bridge");
58*a1157835SDaniel Fojt 		return -1;
59*a1157835SDaniel Fojt 	}
60*a1157835SDaniel Fojt #endif /* CONFIG_IPV6 */
61*a1157835SDaniel Fojt 
62*a1157835SDaniel Fojt 	return 0;
63*a1157835SDaniel Fojt }
64*a1157835SDaniel Fojt 
65*a1157835SDaniel Fojt 
66*a1157835SDaniel Fojt struct l2_packet_data *
x_snoop_get_l2_packet(struct hostapd_data * hapd,void (* handler)(void * ctx,const u8 * src_addr,const u8 * buf,size_t len),enum l2_packet_filter_type type)67*a1157835SDaniel Fojt x_snoop_get_l2_packet(struct hostapd_data *hapd,
68*a1157835SDaniel Fojt 		      void (*handler)(void *ctx, const u8 *src_addr,
69*a1157835SDaniel Fojt 				      const u8 *buf, size_t len),
70*a1157835SDaniel Fojt 		      enum l2_packet_filter_type type)
71*a1157835SDaniel Fojt {
72*a1157835SDaniel Fojt 	struct hostapd_bss_config *conf = hapd->conf;
73*a1157835SDaniel Fojt 	struct l2_packet_data *l2;
74*a1157835SDaniel Fojt 
75*a1157835SDaniel Fojt 	l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
76*a1157835SDaniel Fojt 	if (l2 == NULL) {
77*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
78*a1157835SDaniel Fojt 			   "x_snoop: Failed to initialize L2 packet processing %s",
79*a1157835SDaniel Fojt 			   strerror(errno));
80*a1157835SDaniel Fojt 		return NULL;
81*a1157835SDaniel Fojt 	}
82*a1157835SDaniel Fojt 
83*a1157835SDaniel Fojt 	if (l2_packet_set_packet_filter(l2, type)) {
84*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
85*a1157835SDaniel Fojt 			   "x_snoop: Failed to set L2 packet filter for type: %d",
86*a1157835SDaniel Fojt 			   type);
87*a1157835SDaniel Fojt 		l2_packet_deinit(l2);
88*a1157835SDaniel Fojt 		return NULL;
89*a1157835SDaniel Fojt 	}
90*a1157835SDaniel Fojt 
91*a1157835SDaniel Fojt 	return l2;
92*a1157835SDaniel Fojt }
93*a1157835SDaniel Fojt 
94*a1157835SDaniel Fojt 
x_snoop_mcast_to_ucast_convert_send(struct hostapd_data * hapd,struct sta_info * sta,u8 * buf,size_t len)95*a1157835SDaniel Fojt void x_snoop_mcast_to_ucast_convert_send(struct hostapd_data *hapd,
96*a1157835SDaniel Fojt 					 struct sta_info *sta, u8 *buf,
97*a1157835SDaniel Fojt 					 size_t len)
98*a1157835SDaniel Fojt {
99*a1157835SDaniel Fojt 	int res;
100*a1157835SDaniel Fojt 	u8 addr[ETH_ALEN];
101*a1157835SDaniel Fojt 	u8 *dst_addr = buf;
102*a1157835SDaniel Fojt 
103*a1157835SDaniel Fojt 	if (!(dst_addr[0] & 0x01))
104*a1157835SDaniel Fojt 		return;
105*a1157835SDaniel Fojt 
106*a1157835SDaniel Fojt 	wpa_printf(MSG_EXCESSIVE, "x_snoop: Multicast-to-unicast conversion "
107*a1157835SDaniel Fojt 		   MACSTR " -> " MACSTR " (len %u)",
108*a1157835SDaniel Fojt 		   MAC2STR(dst_addr), MAC2STR(sta->addr), (unsigned int) len);
109*a1157835SDaniel Fojt 
110*a1157835SDaniel Fojt 	/* save the multicast destination address for restoring it later */
111*a1157835SDaniel Fojt 	os_memcpy(addr, buf, ETH_ALEN);
112*a1157835SDaniel Fojt 
113*a1157835SDaniel Fojt 	os_memcpy(buf, sta->addr, ETH_ALEN);
114*a1157835SDaniel Fojt 	res = l2_packet_send(hapd->sock_dhcp, NULL, 0, buf, len);
115*a1157835SDaniel Fojt 	if (res < 0) {
116*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
117*a1157835SDaniel Fojt 			   "x_snoop: Failed to send mcast to ucast converted packet to "
118*a1157835SDaniel Fojt 			   MACSTR, MAC2STR(sta->addr));
119*a1157835SDaniel Fojt 	}
120*a1157835SDaniel Fojt 
121*a1157835SDaniel Fojt 	/* restore the multicast destination address */
122*a1157835SDaniel Fojt 	os_memcpy(buf, addr, ETH_ALEN);
123*a1157835SDaniel Fojt }
124*a1157835SDaniel Fojt 
125*a1157835SDaniel Fojt 
x_snoop_deinit(struct hostapd_data * hapd)126*a1157835SDaniel Fojt void x_snoop_deinit(struct hostapd_data *hapd)
127*a1157835SDaniel Fojt {
128*a1157835SDaniel Fojt 	hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0);
129*a1157835SDaniel Fojt 	hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0);
130*a1157835SDaniel Fojt 	hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0);
131*a1157835SDaniel Fojt }
132