xref: /dflybsd-src/contrib/wpa_supplicant/src/common/ctrl_iface_common.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
1*a1157835SDaniel Fojt /*
2*a1157835SDaniel Fojt  * Common hostapd/wpa_supplicant ctrl iface code.
3*a1157835SDaniel Fojt  * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
4*a1157835SDaniel Fojt  * Copyright (c) 2015, Qualcomm Atheros, Inc.
5*a1157835SDaniel Fojt  *
6*a1157835SDaniel Fojt  * This software may be distributed under the terms of the BSD license.
7*a1157835SDaniel Fojt  * See README for more details.
8*a1157835SDaniel Fojt  */
9*a1157835SDaniel Fojt 
10*a1157835SDaniel Fojt #include "utils/includes.h"
11*a1157835SDaniel Fojt #include <netdb.h>
12*a1157835SDaniel Fojt #include <sys/un.h>
13*a1157835SDaniel Fojt 
14*a1157835SDaniel Fojt #include "utils/common.h"
15*a1157835SDaniel Fojt #include "ctrl_iface_common.h"
16*a1157835SDaniel Fojt 
sockaddr_compare(struct sockaddr_storage * a,socklen_t a_len,struct sockaddr_storage * b,socklen_t b_len)17*a1157835SDaniel Fojt static int sockaddr_compare(struct sockaddr_storage *a, socklen_t a_len,
18*a1157835SDaniel Fojt 			    struct sockaddr_storage *b, socklen_t b_len)
19*a1157835SDaniel Fojt {
20*a1157835SDaniel Fojt 	if (a->ss_family != b->ss_family)
21*a1157835SDaniel Fojt 		return 1;
22*a1157835SDaniel Fojt 
23*a1157835SDaniel Fojt 	switch (a->ss_family) {
24*a1157835SDaniel Fojt #ifdef CONFIG_CTRL_IFACE_UDP
25*a1157835SDaniel Fojt 	case AF_INET:
26*a1157835SDaniel Fojt 	{
27*a1157835SDaniel Fojt 		struct sockaddr_in *in_a, *in_b;
28*a1157835SDaniel Fojt 
29*a1157835SDaniel Fojt 		in_a = (struct sockaddr_in *) a;
30*a1157835SDaniel Fojt 		in_b = (struct sockaddr_in *) b;
31*a1157835SDaniel Fojt 
32*a1157835SDaniel Fojt 		if (in_a->sin_port != in_b->sin_port)
33*a1157835SDaniel Fojt 			return 1;
34*a1157835SDaniel Fojt 		if (in_a->sin_addr.s_addr != in_b->sin_addr.s_addr)
35*a1157835SDaniel Fojt 			return 1;
36*a1157835SDaniel Fojt 		break;
37*a1157835SDaniel Fojt 	}
38*a1157835SDaniel Fojt 	case AF_INET6:
39*a1157835SDaniel Fojt 	{
40*a1157835SDaniel Fojt 		struct sockaddr_in6 *in6_a, *in6_b;
41*a1157835SDaniel Fojt 
42*a1157835SDaniel Fojt 		in6_a = (struct sockaddr_in6 *) a;
43*a1157835SDaniel Fojt 		in6_b = (struct sockaddr_in6 *) b;
44*a1157835SDaniel Fojt 
45*a1157835SDaniel Fojt 		if (in6_a->sin6_port != in6_b->sin6_port)
46*a1157835SDaniel Fojt 			return 1;
47*a1157835SDaniel Fojt 		if (os_memcmp(&in6_a->sin6_addr, &in6_b->sin6_addr,
48*a1157835SDaniel Fojt 			      sizeof(in6_a->sin6_addr)) != 0)
49*a1157835SDaniel Fojt 			return 1;
50*a1157835SDaniel Fojt 		break;
51*a1157835SDaniel Fojt 	}
52*a1157835SDaniel Fojt #endif /* CONFIG_CTRL_IFACE_UDP */
53*a1157835SDaniel Fojt #ifdef CONFIG_CTRL_IFACE_UNIX
54*a1157835SDaniel Fojt 	case AF_UNIX:
55*a1157835SDaniel Fojt 	{
56*a1157835SDaniel Fojt 		struct sockaddr_un *u_a, *u_b;
57*a1157835SDaniel Fojt 
58*a1157835SDaniel Fojt 		u_a = (struct sockaddr_un *) a;
59*a1157835SDaniel Fojt 		u_b = (struct sockaddr_un *) b;
60*a1157835SDaniel Fojt 
61*a1157835SDaniel Fojt 		if (a_len != b_len ||
62*a1157835SDaniel Fojt 		    os_memcmp(u_a->sun_path, u_b->sun_path,
63*a1157835SDaniel Fojt 			      a_len - offsetof(struct sockaddr_un, sun_path))
64*a1157835SDaniel Fojt 		    != 0)
65*a1157835SDaniel Fojt 			return 1;
66*a1157835SDaniel Fojt 		break;
67*a1157835SDaniel Fojt 	}
68*a1157835SDaniel Fojt #endif /* CONFIG_CTRL_IFACE_UNIX */
69*a1157835SDaniel Fojt 	default:
70*a1157835SDaniel Fojt 		return 1;
71*a1157835SDaniel Fojt 	}
72*a1157835SDaniel Fojt 
73*a1157835SDaniel Fojt 	return 0;
74*a1157835SDaniel Fojt }
75*a1157835SDaniel Fojt 
76*a1157835SDaniel Fojt 
sockaddr_print(int level,const char * msg,struct sockaddr_storage * sock,socklen_t socklen)77*a1157835SDaniel Fojt void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock,
78*a1157835SDaniel Fojt 		    socklen_t socklen)
79*a1157835SDaniel Fojt {
80*a1157835SDaniel Fojt 	switch (sock->ss_family) {
81*a1157835SDaniel Fojt #ifdef CONFIG_CTRL_IFACE_UDP
82*a1157835SDaniel Fojt 	case AF_INET:
83*a1157835SDaniel Fojt 	case AF_INET6:
84*a1157835SDaniel Fojt 	{
85*a1157835SDaniel Fojt 		char host[NI_MAXHOST] = { 0 };
86*a1157835SDaniel Fojt 		char service[NI_MAXSERV] = { 0 };
87*a1157835SDaniel Fojt 
88*a1157835SDaniel Fojt 		getnameinfo((struct sockaddr *) sock, socklen,
89*a1157835SDaniel Fojt 			    host, sizeof(host),
90*a1157835SDaniel Fojt 			    service, sizeof(service),
91*a1157835SDaniel Fojt 			    NI_NUMERICHOST);
92*a1157835SDaniel Fojt 
93*a1157835SDaniel Fojt 		wpa_printf(level, "%s %s:%s", msg, host, service);
94*a1157835SDaniel Fojt 		break;
95*a1157835SDaniel Fojt 	}
96*a1157835SDaniel Fojt #endif /* CONFIG_CTRL_IFACE_UDP */
97*a1157835SDaniel Fojt #ifdef CONFIG_CTRL_IFACE_UNIX
98*a1157835SDaniel Fojt 	case AF_UNIX:
99*a1157835SDaniel Fojt 	{
100*a1157835SDaniel Fojt 		char addr_txt[200];
101*a1157835SDaniel Fojt 
102*a1157835SDaniel Fojt 		printf_encode(addr_txt, sizeof(addr_txt),
103*a1157835SDaniel Fojt 			      (u8 *) ((struct sockaddr_un *) sock)->sun_path,
104*a1157835SDaniel Fojt 			      socklen - offsetof(struct sockaddr_un, sun_path));
105*a1157835SDaniel Fojt 		wpa_printf(level, "%s %s", msg, addr_txt);
106*a1157835SDaniel Fojt 		break;
107*a1157835SDaniel Fojt 	}
108*a1157835SDaniel Fojt #endif /* CONFIG_CTRL_IFACE_UNIX */
109*a1157835SDaniel Fojt 	default:
110*a1157835SDaniel Fojt 		wpa_printf(level, "%s", msg);
111*a1157835SDaniel Fojt 		break;
112*a1157835SDaniel Fojt 	}
113*a1157835SDaniel Fojt }
114*a1157835SDaniel Fojt 
115*a1157835SDaniel Fojt 
ctrl_set_events(struct wpa_ctrl_dst * dst,const char * input)116*a1157835SDaniel Fojt static int ctrl_set_events(struct wpa_ctrl_dst *dst, const char *input)
117*a1157835SDaniel Fojt {
118*a1157835SDaniel Fojt 	const char *value;
119*a1157835SDaniel Fojt 	int val;
120*a1157835SDaniel Fojt 
121*a1157835SDaniel Fojt 	if (!input)
122*a1157835SDaniel Fojt 		return 0;
123*a1157835SDaniel Fojt 
124*a1157835SDaniel Fojt 	value = os_strchr(input, '=');
125*a1157835SDaniel Fojt 	if (!value)
126*a1157835SDaniel Fojt 		return -1;
127*a1157835SDaniel Fojt 	value++;
128*a1157835SDaniel Fojt 	val = atoi(value);
129*a1157835SDaniel Fojt 	if (val < 0 || val > 1)
130*a1157835SDaniel Fojt 		return -1;
131*a1157835SDaniel Fojt 
132*a1157835SDaniel Fojt 	if (str_starts(input, "probe_rx_events=")) {
133*a1157835SDaniel Fojt 		if (val)
134*a1157835SDaniel Fojt 			dst->events |= WPA_EVENT_RX_PROBE_REQUEST;
135*a1157835SDaniel Fojt 		else
136*a1157835SDaniel Fojt 			dst->events &= ~WPA_EVENT_RX_PROBE_REQUEST;
137*a1157835SDaniel Fojt 	}
138*a1157835SDaniel Fojt 
139*a1157835SDaniel Fojt 	return 0;
140*a1157835SDaniel Fojt }
141*a1157835SDaniel Fojt 
142*a1157835SDaniel Fojt 
ctrl_iface_attach(struct dl_list * ctrl_dst,struct sockaddr_storage * from,socklen_t fromlen,const char * input)143*a1157835SDaniel Fojt int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
144*a1157835SDaniel Fojt 		      socklen_t fromlen, const char *input)
145*a1157835SDaniel Fojt {
146*a1157835SDaniel Fojt 	struct wpa_ctrl_dst *dst;
147*a1157835SDaniel Fojt 
148*a1157835SDaniel Fojt 	/* Update event registration if already attached */
149*a1157835SDaniel Fojt 	dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
150*a1157835SDaniel Fojt 		if (!sockaddr_compare(from, fromlen,
151*a1157835SDaniel Fojt 				      &dst->addr, dst->addrlen))
152*a1157835SDaniel Fojt 			return ctrl_set_events(dst, input);
153*a1157835SDaniel Fojt 	}
154*a1157835SDaniel Fojt 
155*a1157835SDaniel Fojt 	/* New attachment */
156*a1157835SDaniel Fojt 	dst = os_zalloc(sizeof(*dst));
157*a1157835SDaniel Fojt 	if (dst == NULL)
158*a1157835SDaniel Fojt 		return -1;
159*a1157835SDaniel Fojt 	os_memcpy(&dst->addr, from, fromlen);
160*a1157835SDaniel Fojt 	dst->addrlen = fromlen;
161*a1157835SDaniel Fojt 	dst->debug_level = MSG_INFO;
162*a1157835SDaniel Fojt 	ctrl_set_events(dst, input);
163*a1157835SDaniel Fojt 	dl_list_add(ctrl_dst, &dst->list);
164*a1157835SDaniel Fojt 
165*a1157835SDaniel Fojt 	sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor attached", from, fromlen);
166*a1157835SDaniel Fojt 	return 0;
167*a1157835SDaniel Fojt }
168*a1157835SDaniel Fojt 
169*a1157835SDaniel Fojt 
ctrl_iface_detach(struct dl_list * ctrl_dst,struct sockaddr_storage * from,socklen_t fromlen)170*a1157835SDaniel Fojt int ctrl_iface_detach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
171*a1157835SDaniel Fojt 		      socklen_t fromlen)
172*a1157835SDaniel Fojt {
173*a1157835SDaniel Fojt 	struct wpa_ctrl_dst *dst;
174*a1157835SDaniel Fojt 
175*a1157835SDaniel Fojt 	dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
176*a1157835SDaniel Fojt 		if (!sockaddr_compare(from, fromlen,
177*a1157835SDaniel Fojt 				      &dst->addr, dst->addrlen)) {
178*a1157835SDaniel Fojt 			sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor detached",
179*a1157835SDaniel Fojt 				       from, fromlen);
180*a1157835SDaniel Fojt 			dl_list_del(&dst->list);
181*a1157835SDaniel Fojt 			os_free(dst);
182*a1157835SDaniel Fojt 			return 0;
183*a1157835SDaniel Fojt 		}
184*a1157835SDaniel Fojt 	}
185*a1157835SDaniel Fojt 
186*a1157835SDaniel Fojt 	return -1;
187*a1157835SDaniel Fojt }
188*a1157835SDaniel Fojt 
189*a1157835SDaniel Fojt 
ctrl_iface_level(struct dl_list * ctrl_dst,struct sockaddr_storage * from,socklen_t fromlen,const char * level)190*a1157835SDaniel Fojt int ctrl_iface_level(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
191*a1157835SDaniel Fojt 		     socklen_t fromlen, const char *level)
192*a1157835SDaniel Fojt {
193*a1157835SDaniel Fojt 	struct wpa_ctrl_dst *dst;
194*a1157835SDaniel Fojt 
195*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
196*a1157835SDaniel Fojt 
197*a1157835SDaniel Fojt 	dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
198*a1157835SDaniel Fojt 		if (!sockaddr_compare(from, fromlen,
199*a1157835SDaniel Fojt 				      &dst->addr, dst->addrlen)) {
200*a1157835SDaniel Fojt 			sockaddr_print(MSG_DEBUG,
201*a1157835SDaniel Fojt 				       "CTRL_IFACE changed monitor level",
202*a1157835SDaniel Fojt 				       from, fromlen);
203*a1157835SDaniel Fojt 			dst->debug_level = atoi(level);
204*a1157835SDaniel Fojt 			return 0;
205*a1157835SDaniel Fojt 		}
206*a1157835SDaniel Fojt 	}
207*a1157835SDaniel Fojt 
208*a1157835SDaniel Fojt 	return -1;
209*a1157835SDaniel Fojt }
210