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