]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/wpa_supplicant/wpa_priv.c
Update hostapd/wpa_supplicant to 2.8 to fix multiple vulnerabilities.
[FreeBSD/FreeBSD.git] / contrib / wpa / wpa_supplicant / wpa_priv.c
1 /*
2  * WPA Supplicant / privileged helper program
3  * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10 #ifdef __linux__
11 #include <fcntl.h>
12 #endif /* __linux__ */
13 #include <sys/un.h>
14 #include <sys/stat.h>
15
16 #include "common.h"
17 #include "eloop.h"
18 #include "common/version.h"
19 #include "drivers/driver.h"
20 #include "l2_packet/l2_packet.h"
21 #include "common/privsep_commands.h"
22 #include "common/ieee802_11_defs.h"
23
24 #define WPA_PRIV_MAX_L2 3
25
26 struct wpa_priv_interface {
27         struct wpa_priv_interface *next;
28         char *driver_name;
29         char *ifname;
30         char *sock_name;
31         int fd;
32
33         void *ctx;
34
35         const struct wpa_driver_ops *driver;
36         void *drv_priv;
37         void *drv_global_priv;
38         struct sockaddr_un drv_addr;
39         socklen_t drv_addr_len;
40         int wpas_registered;
41
42         struct l2_packet_data *l2[WPA_PRIV_MAX_L2];
43         struct sockaddr_un l2_addr[WPA_PRIV_MAX_L2];
44         socklen_t l2_addr_len[WPA_PRIV_MAX_L2];
45         struct wpa_priv_l2 {
46                 struct wpa_priv_interface *parent;
47                 int idx;
48         } l2_ctx[WPA_PRIV_MAX_L2];
49 };
50
51 struct wpa_priv_global {
52         struct wpa_priv_interface *interfaces;
53 };
54
55
56 static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
57                                   struct sockaddr_un *from, socklen_t fromlen)
58 {
59         int i;
60
61         if (iface->drv_priv) {
62                 wpa_printf(MSG_DEBUG, "Cleaning up forgotten driver instance");
63                 if (iface->driver->deinit)
64                         iface->driver->deinit(iface->drv_priv);
65                 iface->drv_priv = NULL;
66                 if (iface->drv_global_priv) {
67                         iface->driver->global_deinit(iface->drv_global_priv);
68                         iface->drv_global_priv = NULL;
69                 }
70                 iface->wpas_registered = 0;
71         }
72
73         for (i = 0; i < WPA_PRIV_MAX_L2; i++) {
74                 if (iface->l2[i]) {
75                         wpa_printf(MSG_DEBUG,
76                                    "Cleaning up forgotten l2_packet instance");
77                         l2_packet_deinit(iface->l2[i]);
78                         iface->l2[i] = NULL;
79                 }
80         }
81
82         if (iface->driver->init2) {
83                 if (iface->driver->global_init) {
84                         iface->drv_global_priv =
85                                 iface->driver->global_init(iface->ctx);
86                         if (!iface->drv_global_priv) {
87                                 wpa_printf(MSG_INFO,
88                                            "Failed to initialize driver global context");
89                                 return;
90                         }
91                 } else {
92                         iface->drv_global_priv = NULL;
93                 }
94                 iface->drv_priv = iface->driver->init2(iface, iface->ifname,
95                                                        iface->drv_global_priv);
96         } else if (iface->driver->init) {
97                 iface->drv_priv = iface->driver->init(iface, iface->ifname);
98         } else {
99                 return;
100         }
101         if (iface->drv_priv == NULL) {
102                 wpa_printf(MSG_DEBUG, "Failed to initialize driver wrapper");
103                 return;
104         }
105
106         wpa_printf(MSG_DEBUG, "Driver wrapper '%s' initialized for interface "
107                    "'%s'", iface->driver_name, iface->ifname);
108
109         os_memcpy(&iface->drv_addr, from, fromlen);
110         iface->drv_addr_len = fromlen;
111         iface->wpas_registered = 1;
112
113         if (iface->driver->set_param &&
114             iface->driver->set_param(iface->drv_priv, NULL) < 0) {
115                 wpa_printf(MSG_ERROR, "Driver interface rejected param");
116         }
117 }
118
119
120 static void wpa_priv_cmd_unregister(struct wpa_priv_interface *iface,
121                                     struct sockaddr_un *from)
122 {
123         if (iface->drv_priv) {
124                 if (iface->driver->deinit)
125                         iface->driver->deinit(iface->drv_priv);
126                 iface->drv_priv = NULL;
127                 if (iface->drv_global_priv) {
128                         iface->driver->global_deinit(iface->drv_global_priv);
129                         iface->drv_global_priv = NULL;
130                 }
131                 iface->wpas_registered = 0;
132         }
133 }
134
135
136 static void wpa_priv_cmd_scan(struct wpa_priv_interface *iface,
137                               void *buf, size_t len)
138 {
139         struct wpa_driver_scan_params params;
140         struct privsep_cmd_scan *scan;
141         unsigned int i;
142         int freqs[PRIVSEP_MAX_SCAN_FREQS + 1];
143
144         if (iface->drv_priv == NULL)
145                 return;
146
147         if (len < sizeof(*scan)) {
148                 wpa_printf(MSG_DEBUG, "Invalid scan request");
149                 return;
150         }
151
152         scan = buf;
153
154         os_memset(&params, 0, sizeof(params));
155         if (scan->num_ssids > WPAS_MAX_SCAN_SSIDS) {
156                 wpa_printf(MSG_DEBUG, "Invalid scan request (num_ssids)");
157                 return;
158         }
159         params.num_ssids = scan->num_ssids;
160         for (i = 0; i < scan->num_ssids; i++) {
161                 params.ssids[i].ssid = scan->ssids[i];
162                 params.ssids[i].ssid_len = scan->ssid_lens[i];
163         }
164
165         if (scan->num_freqs > PRIVSEP_MAX_SCAN_FREQS) {
166                 wpa_printf(MSG_DEBUG, "Invalid scan request (num_freqs)");
167                 return;
168         }
169         if (scan->num_freqs) {
170                 for (i = 0; i < scan->num_freqs; i++)
171                         freqs[i] = scan->freqs[i];
172                 freqs[i] = 0;
173                 params.freqs = freqs;
174         }
175
176         if (iface->driver->scan2)
177                 iface->driver->scan2(iface->drv_priv, &params);
178 }
179
180
181 static void wpa_priv_get_scan_results2(struct wpa_priv_interface *iface,
182                                        struct sockaddr_un *from,
183                                        socklen_t fromlen)
184 {
185         struct wpa_scan_results *res;
186         u8 *buf = NULL, *pos, *end;
187         int val;
188         size_t i;
189
190         res = iface->driver->get_scan_results2(iface->drv_priv);
191         if (res == NULL)
192                 goto fail;
193
194         buf = os_malloc(60000);
195         if (buf == NULL)
196                 goto fail;
197         pos = buf;
198         end = buf + 60000;
199         val = res->num;
200         os_memcpy(pos, &val, sizeof(int));
201         pos += sizeof(int);
202
203         for (i = 0; i < res->num; i++) {
204                 struct wpa_scan_res *r = res->res[i];
205                 val = sizeof(*r) + r->ie_len + r->beacon_ie_len;
206                 if (end - pos < (int) sizeof(int) + val)
207                         break;
208                 os_memcpy(pos, &val, sizeof(int));
209                 pos += sizeof(int);
210                 os_memcpy(pos, r, val);
211                 pos += val;
212         }
213
214         sendto(iface->fd, buf, pos - buf, 0, (struct sockaddr *) from, fromlen);
215
216         os_free(buf);
217         wpa_scan_results_free(res);
218         return;
219
220 fail:
221         os_free(buf);
222         wpa_scan_results_free(res);
223         sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
224 }
225
226
227 static void wpa_priv_cmd_get_scan_results(struct wpa_priv_interface *iface,
228                                           struct sockaddr_un *from,
229                                           socklen_t fromlen)
230 {
231         if (iface->drv_priv == NULL)
232                 return;
233
234         if (iface->driver->get_scan_results2)
235                 wpa_priv_get_scan_results2(iface, from, fromlen);
236         else
237                 sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
238 }
239
240
241 static void wpa_priv_cmd_authenticate(struct wpa_priv_interface *iface,
242                                       void *buf, size_t len)
243 {
244         struct wpa_driver_auth_params params;
245         struct privsep_cmd_authenticate *auth;
246         int res, i;
247
248         if (iface->drv_priv == NULL || iface->driver->authenticate == NULL)
249                 return;
250
251         if (len < sizeof(*auth)) {
252                 wpa_printf(MSG_DEBUG, "Invalid authentication request");
253                 return;
254         }
255
256         auth = buf;
257         if (sizeof(*auth) + auth->ie_len + auth->auth_data_len > len) {
258                 wpa_printf(MSG_DEBUG, "Authentication request overflow");
259                 return;
260         }
261
262         os_memset(&params, 0, sizeof(params));
263         params.freq = auth->freq;
264         params.bssid = auth->bssid;
265         params.ssid = auth->ssid;
266         if (auth->ssid_len > SSID_MAX_LEN)
267                 return;
268         params.ssid_len = auth->ssid_len;
269         params.auth_alg = auth->auth_alg;
270         for (i = 0; i < 4; i++) {
271                 if (auth->wep_key_len[i]) {
272                         params.wep_key[i] = auth->wep_key[i];
273                         params.wep_key_len[i] = auth->wep_key_len[i];
274                 }
275         }
276         params.wep_tx_keyidx = auth->wep_tx_keyidx;
277         params.local_state_change = auth->local_state_change;
278         params.p2p = auth->p2p;
279         if (auth->ie_len) {
280                 params.ie = (u8 *) (auth + 1);
281                 params.ie_len = auth->ie_len;
282         }
283         if (auth->auth_data_len) {
284                 params.auth_data = ((u8 *) (auth + 1)) + auth->ie_len;
285                 params.auth_data_len = auth->auth_data_len;
286         }
287
288         res = iface->driver->authenticate(iface->drv_priv, &params);
289         wpa_printf(MSG_DEBUG, "drv->authenticate: res=%d", res);
290 }
291
292
293 static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface,
294                                    void *buf, size_t len)
295 {
296         struct wpa_driver_associate_params params;
297         struct privsep_cmd_associate *assoc;
298         u8 *bssid;
299         int res;
300
301         if (iface->drv_priv == NULL || iface->driver->associate == NULL)
302                 return;
303
304         if (len < sizeof(*assoc)) {
305                 wpa_printf(MSG_DEBUG, "Invalid association request");
306                 return;
307         }
308
309         assoc = buf;
310         if (sizeof(*assoc) + assoc->wpa_ie_len > len) {
311                 wpa_printf(MSG_DEBUG, "Association request overflow");
312                 return;
313         }
314
315         os_memset(&params, 0, sizeof(params));
316         bssid = assoc->bssid;
317         if (bssid[0] | bssid[1] | bssid[2] | bssid[3] | bssid[4] | bssid[5])
318                 params.bssid = bssid;
319         params.ssid = assoc->ssid;
320         if (assoc->ssid_len > SSID_MAX_LEN)
321                 return;
322         params.ssid_len = assoc->ssid_len;
323         params.freq.mode = assoc->hwmode;
324         params.freq.freq = assoc->freq;
325         params.freq.channel = assoc->channel;
326         if (assoc->wpa_ie_len) {
327                 params.wpa_ie = (u8 *) (assoc + 1);
328                 params.wpa_ie_len = assoc->wpa_ie_len;
329         }
330         params.pairwise_suite = assoc->pairwise_suite;
331         params.group_suite = assoc->group_suite;
332         params.key_mgmt_suite = assoc->key_mgmt_suite;
333         params.auth_alg = assoc->auth_alg;
334         params.mode = assoc->mode;
335
336         res = iface->driver->associate(iface->drv_priv, &params);
337         wpa_printf(MSG_DEBUG, "drv->associate: res=%d", res);
338 }
339
340
341 static void wpa_priv_cmd_get_bssid(struct wpa_priv_interface *iface,
342                                    struct sockaddr_un *from, socklen_t fromlen)
343 {
344         u8 bssid[ETH_ALEN];
345
346         if (iface->drv_priv == NULL)
347                 goto fail;
348
349         if (iface->driver->get_bssid == NULL ||
350             iface->driver->get_bssid(iface->drv_priv, bssid) < 0)
351                 goto fail;
352
353         sendto(iface->fd, bssid, ETH_ALEN, 0, (struct sockaddr *) from,
354                fromlen);
355         return;
356
357 fail:
358         sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
359 }
360
361
362 static void wpa_priv_cmd_get_ssid(struct wpa_priv_interface *iface,
363                                   struct sockaddr_un *from, socklen_t fromlen)
364 {
365         u8 ssid[sizeof(int) + SSID_MAX_LEN];
366         int res;
367
368         if (iface->drv_priv == NULL)
369                 goto fail;
370
371         if (iface->driver->get_ssid == NULL)
372                 goto fail;
373
374         os_memset(ssid, 0, sizeof(ssid));
375         res = iface->driver->get_ssid(iface->drv_priv, &ssid[sizeof(int)]);
376         if (res < 0 || res > SSID_MAX_LEN)
377                 goto fail;
378         os_memcpy(ssid, &res, sizeof(int));
379
380         sendto(iface->fd, ssid, sizeof(ssid), 0, (struct sockaddr *) from,
381                fromlen);
382         return;
383
384 fail:
385         sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
386 }
387
388
389 static void wpa_priv_cmd_set_key(struct wpa_priv_interface *iface,
390                                  void *buf, size_t len)
391 {
392         struct privsep_cmd_set_key *params;
393         int res;
394
395         if (iface->drv_priv == NULL || iface->driver->set_key == NULL)
396                 return;
397
398         if (len != sizeof(*params)) {
399                 wpa_printf(MSG_DEBUG, "Invalid set_key request");
400                 return;
401         }
402
403         params = buf;
404
405         res = iface->driver->set_key(iface->ifname, iface->drv_priv,
406                                      params->alg,
407                                      params->addr, params->key_idx,
408                                      params->set_tx,
409                                      params->seq_len ? params->seq : NULL,
410                                      params->seq_len,
411                                      params->key_len ? params->key : NULL,
412                                      params->key_len);
413         wpa_printf(MSG_DEBUG, "drv->set_key: res=%d", res);
414 }
415
416
417 static void wpa_priv_cmd_get_capa(struct wpa_priv_interface *iface,
418                                   struct sockaddr_un *from, socklen_t fromlen)
419 {
420         struct wpa_driver_capa capa;
421
422         if (iface->drv_priv == NULL)
423                 goto fail;
424
425         if (iface->driver->get_capa == NULL ||
426             iface->driver->get_capa(iface->drv_priv, &capa) < 0)
427                 goto fail;
428
429         /* For now, no support for passing extended_capa pointers */
430         capa.extended_capa = NULL;
431         capa.extended_capa_mask = NULL;
432         capa.extended_capa_len = 0;
433         sendto(iface->fd, &capa, sizeof(capa), 0, (struct sockaddr *) from,
434                fromlen);
435         return;
436
437 fail:
438         sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
439 }
440
441
442 static void wpa_priv_l2_rx(void *ctx, const u8 *src_addr, const u8 *buf,
443                            size_t len)
444 {
445         struct wpa_priv_l2 *l2_ctx = ctx;
446         struct wpa_priv_interface *iface = l2_ctx->parent;
447         struct msghdr msg;
448         struct iovec io[2];
449
450         io[0].iov_base = (u8 *) src_addr;
451         io[0].iov_len = ETH_ALEN;
452         io[1].iov_base = (u8 *) buf;
453         io[1].iov_len = len;
454
455         os_memset(&msg, 0, sizeof(msg));
456         msg.msg_iov = io;
457         msg.msg_iovlen = 2;
458         msg.msg_name = &iface->l2_addr[l2_ctx->idx];
459         msg.msg_namelen = iface->l2_addr_len[l2_ctx->idx];
460
461         if (sendmsg(iface->fd, &msg, 0) < 0) {
462                 wpa_printf(MSG_ERROR, "sendmsg(l2 rx): %s", strerror(errno));
463         }
464 }
465
466
467 static int wpa_priv_allowed_l2_proto(u16 proto)
468 {
469         return proto == ETH_P_EAPOL || proto == ETH_P_RSN_PREAUTH ||
470                 proto == ETH_P_80211_ENCAP;
471 }
472
473
474 static void wpa_priv_cmd_l2_register(struct wpa_priv_interface *iface,
475                                      struct sockaddr_un *from,
476                                      socklen_t fromlen,
477                                      void *buf, size_t len)
478 {
479         int *reg_cmd = buf;
480         u8 own_addr[ETH_ALEN];
481         int res;
482         u16 proto;
483         int idx;
484
485         if (len != 2 * sizeof(int)) {
486                 wpa_printf(MSG_DEBUG, "Invalid l2_register length %lu",
487                            (unsigned long) len);
488                 return;
489         }
490
491         proto = reg_cmd[0];
492         if (!wpa_priv_allowed_l2_proto(proto)) {
493                 wpa_printf(MSG_DEBUG, "Refused l2_packet connection for "
494                            "ethertype 0x%x", proto);
495                 return;
496         }
497
498         for (idx = 0; idx < WPA_PRIV_MAX_L2; idx++) {
499                 if (!iface->l2[idx])
500                         break;
501         }
502         if (idx == WPA_PRIV_MAX_L2) {
503                 wpa_printf(MSG_DEBUG, "No free l2_packet connection found");
504                 return;
505         }
506
507         os_memcpy(&iface->l2_addr[idx], from, fromlen);
508         iface->l2_addr_len[idx] = fromlen;
509
510         iface->l2_ctx[idx].idx = idx;
511         iface->l2_ctx[idx].parent = iface;
512         iface->l2[idx] = l2_packet_init(iface->ifname, NULL, proto,
513                                         wpa_priv_l2_rx, &iface->l2_ctx[idx],
514                                         reg_cmd[1]);
515         if (!iface->l2[idx]) {
516                 wpa_printf(MSG_DEBUG, "Failed to initialize l2_packet "
517                            "instance for protocol %d", proto);
518                 return;
519         }
520
521         if (l2_packet_get_own_addr(iface->l2[idx], own_addr) < 0) {
522                 wpa_printf(MSG_DEBUG, "Failed to get own address from "
523                            "l2_packet");
524                 l2_packet_deinit(iface->l2[idx]);
525                 iface->l2[idx] = NULL;
526                 return;
527         }
528
529         res = sendto(iface->fd, own_addr, ETH_ALEN, 0,
530                      (struct sockaddr *) from, fromlen);
531         wpa_printf(MSG_DEBUG, "L2 registration[idx=%d]: res=%d", idx, res);
532 }
533
534
535 static void wpa_priv_cmd_l2_unregister(struct wpa_priv_interface *iface,
536                                        struct sockaddr_un *from,
537                                        socklen_t fromlen)
538 {
539         int idx;
540
541         for (idx = 0; idx < WPA_PRIV_MAX_L2; idx++) {
542                 if (iface->l2_addr_len[idx] == fromlen &&
543                     os_memcmp(&iface->l2_addr[idx], from, fromlen) == 0)
544                         break;
545         }
546         if (idx == WPA_PRIV_MAX_L2) {
547                 wpa_printf(MSG_DEBUG,
548                            "No registered l2_packet socket found for unregister request");
549                 return;
550         }
551
552         if (iface->l2[idx]) {
553                 l2_packet_deinit(iface->l2[idx]);
554                 iface->l2[idx] = NULL;
555         }
556 }
557
558
559 static void wpa_priv_cmd_l2_notify_auth_start(struct wpa_priv_interface *iface,
560                                               struct sockaddr_un *from)
561 {
562         int idx;
563
564         for (idx = 0; idx < WPA_PRIV_MAX_L2; idx++) {
565                 if (iface->l2[idx])
566                         l2_packet_notify_auth_start(iface->l2[idx]);
567         }
568 }
569
570
571 static void wpa_priv_cmd_l2_send(struct wpa_priv_interface *iface,
572                                  struct sockaddr_un *from, socklen_t fromlen,
573                                  void *buf, size_t len)
574 {
575         u8 *dst_addr;
576         u16 proto;
577         int res;
578         int idx;
579
580         for (idx = 0; idx < WPA_PRIV_MAX_L2; idx++) {
581                 if (iface->l2_addr_len[idx] == fromlen &&
582                     os_memcmp(&iface->l2_addr[idx], from, fromlen) == 0)
583                         break;
584         }
585         if (idx == WPA_PRIV_MAX_L2) {
586                 wpa_printf(MSG_DEBUG,
587                            "No registered l2_packet socket found for send request");
588                 return;
589         }
590
591         if (iface->l2[idx] == NULL)
592                 return;
593
594         if (len < ETH_ALEN + 2) {
595                 wpa_printf(MSG_DEBUG, "Too short L2 send packet (len=%lu)",
596                            (unsigned long) len);
597                 return;
598         }
599
600         dst_addr = buf;
601         os_memcpy(&proto, buf + ETH_ALEN, 2);
602
603         if (!wpa_priv_allowed_l2_proto(proto)) {
604                 wpa_printf(MSG_DEBUG, "Refused l2_packet send for ethertype "
605                            "0x%x", proto);
606                 return;
607         }
608
609         res = l2_packet_send(iface->l2[idx], dst_addr, proto,
610                              buf + ETH_ALEN + 2, len - ETH_ALEN - 2);
611         wpa_printf(MSG_DEBUG, "L2 send[idx=%d]: res=%d", idx, res);
612 }
613
614
615 static void wpa_priv_cmd_set_country(struct wpa_priv_interface *iface,
616                                      char *buf)
617 {
618         if (iface->drv_priv == NULL || iface->driver->set_country == NULL ||
619             *buf == '\0')
620                 return;
621
622         iface->driver->set_country(iface->drv_priv, buf);
623 }
624
625
626 static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
627 {
628         struct wpa_priv_interface *iface = eloop_ctx;
629         char buf[2000], *pos;
630         void *cmd_buf;
631         size_t cmd_len;
632         int res, cmd;
633         struct sockaddr_un from;
634         socklen_t fromlen = sizeof(from);
635
636         res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &from,
637                        &fromlen);
638         if (res < 0) {
639                 wpa_printf(MSG_ERROR, "recvfrom: %s", strerror(errno));
640                 return;
641         }
642
643         if (res < (int) sizeof(int)) {
644                 wpa_printf(MSG_DEBUG, "Too short command (len=%d)", res);
645                 return;
646         }
647
648         os_memcpy(&cmd, buf, sizeof(int));
649         wpa_printf(MSG_DEBUG, "Command %d for interface %s",
650                    cmd, iface->ifname);
651         cmd_buf = &buf[sizeof(int)];
652         cmd_len = res - sizeof(int);
653
654         switch (cmd) {
655         case PRIVSEP_CMD_REGISTER:
656                 wpa_priv_cmd_register(iface, &from, fromlen);
657                 break;
658         case PRIVSEP_CMD_UNREGISTER:
659                 wpa_priv_cmd_unregister(iface, &from);
660                 break;
661         case PRIVSEP_CMD_SCAN:
662                 wpa_priv_cmd_scan(iface, cmd_buf, cmd_len);
663                 break;
664         case PRIVSEP_CMD_GET_SCAN_RESULTS:
665                 wpa_priv_cmd_get_scan_results(iface, &from, fromlen);
666                 break;
667         case PRIVSEP_CMD_ASSOCIATE:
668                 wpa_priv_cmd_associate(iface, cmd_buf, cmd_len);
669                 break;
670         case PRIVSEP_CMD_GET_BSSID:
671                 wpa_priv_cmd_get_bssid(iface, &from, fromlen);
672                 break;
673         case PRIVSEP_CMD_GET_SSID:
674                 wpa_priv_cmd_get_ssid(iface, &from, fromlen);
675                 break;
676         case PRIVSEP_CMD_SET_KEY:
677                 wpa_priv_cmd_set_key(iface, cmd_buf, cmd_len);
678                 break;
679         case PRIVSEP_CMD_GET_CAPA:
680                 wpa_priv_cmd_get_capa(iface, &from, fromlen);
681                 break;
682         case PRIVSEP_CMD_L2_REGISTER:
683                 wpa_priv_cmd_l2_register(iface, &from, fromlen,
684                                          cmd_buf, cmd_len);
685                 break;
686         case PRIVSEP_CMD_L2_UNREGISTER:
687                 wpa_priv_cmd_l2_unregister(iface, &from, fromlen);
688                 break;
689         case PRIVSEP_CMD_L2_NOTIFY_AUTH_START:
690                 wpa_priv_cmd_l2_notify_auth_start(iface, &from);
691                 break;
692         case PRIVSEP_CMD_L2_SEND:
693                 wpa_priv_cmd_l2_send(iface, &from, fromlen, cmd_buf, cmd_len);
694                 break;
695         case PRIVSEP_CMD_SET_COUNTRY:
696                 pos = cmd_buf;
697                 if (pos + cmd_len >= buf + sizeof(buf))
698                         break;
699                 pos[cmd_len] = '\0';
700                 wpa_priv_cmd_set_country(iface, pos);
701                 break;
702         case PRIVSEP_CMD_AUTHENTICATE:
703                 wpa_priv_cmd_authenticate(iface, cmd_buf, cmd_len);
704                 break;
705         }
706 }
707
708
709 static void wpa_priv_interface_deinit(struct wpa_priv_interface *iface)
710 {
711         int i;
712
713         if (iface->drv_priv) {
714                 if (iface->driver->deinit)
715                         iface->driver->deinit(iface->drv_priv);
716                 if (iface->drv_global_priv)
717                         iface->driver->global_deinit(iface->drv_global_priv);
718         }
719
720         if (iface->fd >= 0) {
721                 eloop_unregister_read_sock(iface->fd);
722                 close(iface->fd);
723                 unlink(iface->sock_name);
724         }
725
726         for (i = 0; i < WPA_PRIV_MAX_L2; i++) {
727                 if (iface->l2[i])
728                         l2_packet_deinit(iface->l2[i]);
729         }
730
731         os_free(iface->ifname);
732         os_free(iface->driver_name);
733         os_free(iface->sock_name);
734         os_free(iface);
735 }
736
737
738 static struct wpa_priv_interface *
739 wpa_priv_interface_init(void *ctx, const char *dir, const char *params)
740 {
741         struct wpa_priv_interface *iface;
742         char *pos;
743         size_t len;
744         struct sockaddr_un addr;
745         int i;
746
747         pos = os_strchr(params, ':');
748         if (pos == NULL)
749                 return NULL;
750
751         iface = os_zalloc(sizeof(*iface));
752         if (iface == NULL)
753                 return NULL;
754         iface->fd = -1;
755         iface->ctx = ctx;
756
757         len = pos - params;
758         iface->driver_name = dup_binstr(params, len);
759         if (iface->driver_name == NULL) {
760                 wpa_priv_interface_deinit(iface);
761                 return NULL;
762         }
763
764         for (i = 0; wpa_drivers[i]; i++) {
765                 if (os_strcmp(iface->driver_name,
766                               wpa_drivers[i]->name) == 0) {
767                         iface->driver = wpa_drivers[i];
768                         break;
769                 }
770         }
771         if (iface->driver == NULL) {
772                 wpa_printf(MSG_ERROR, "Unsupported driver '%s'",
773                            iface->driver_name);
774                 wpa_priv_interface_deinit(iface);
775                 return NULL;
776         }
777
778         pos++;
779         iface->ifname = os_strdup(pos);
780         if (iface->ifname == NULL) {
781                 wpa_priv_interface_deinit(iface);
782                 return NULL;
783         }
784
785         len = os_strlen(dir) + 1 + os_strlen(iface->ifname);
786         iface->sock_name = os_malloc(len + 1);
787         if (iface->sock_name == NULL) {
788                 wpa_priv_interface_deinit(iface);
789                 return NULL;
790         }
791
792         os_snprintf(iface->sock_name, len + 1, "%s/%s", dir, iface->ifname);
793         if (os_strlen(iface->sock_name) >= sizeof(addr.sun_path)) {
794                 wpa_priv_interface_deinit(iface);
795                 return NULL;
796         }
797
798         iface->fd = socket(PF_UNIX, SOCK_DGRAM, 0);
799         if (iface->fd < 0) {
800                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
801                 wpa_priv_interface_deinit(iface);
802                 return NULL;
803         }
804
805         os_memset(&addr, 0, sizeof(addr));
806         addr.sun_family = AF_UNIX;
807         os_strlcpy(addr.sun_path, iface->sock_name, sizeof(addr.sun_path));
808
809         if (bind(iface->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
810                 wpa_printf(MSG_DEBUG, "bind(PF_UNIX) failed: %s",
811                            strerror(errno));
812                 if (connect(iface->fd, (struct sockaddr *) &addr,
813                             sizeof(addr)) < 0) {
814                         wpa_printf(MSG_DEBUG, "Socket exists, but does not "
815                                    "allow connections - assuming it was "
816                                    "leftover from forced program termination");
817                         if (unlink(iface->sock_name) < 0) {
818                                 wpa_printf(MSG_ERROR,
819                                            "Could not unlink existing ctrl_iface socket '%s': %s",
820                                            iface->sock_name, strerror(errno));
821                                 goto fail;
822                         }
823                         if (bind(iface->fd, (struct sockaddr *) &addr,
824                                  sizeof(addr)) < 0) {
825                                 wpa_printf(MSG_ERROR,
826                                            "wpa-priv-iface-init: bind(PF_UNIX): %s",
827                                            strerror(errno));
828                                 goto fail;
829                         }
830                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
831                                    "socket '%s'", iface->sock_name);
832                 } else {
833                         wpa_printf(MSG_INFO, "Socket exists and seems to be "
834                                    "in use - cannot override it");
835                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
836                                    "not used anymore", iface->sock_name);
837                         goto fail;
838                 }
839         }
840
841         if (chmod(iface->sock_name, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
842                 wpa_printf(MSG_ERROR, "chmod: %s", strerror(errno));
843                 goto fail;
844         }
845
846         eloop_register_read_sock(iface->fd, wpa_priv_receive, iface, NULL);
847
848         return iface;
849
850 fail:
851         wpa_priv_interface_deinit(iface);
852         return NULL;
853 }
854
855
856 static int wpa_priv_send_event(struct wpa_priv_interface *iface, int event,
857                                const void *data, size_t data_len)
858 {
859         struct msghdr msg;
860         struct iovec io[2];
861
862         io[0].iov_base = &event;
863         io[0].iov_len = sizeof(event);
864         io[1].iov_base = (u8 *) data;
865         io[1].iov_len = data_len;
866
867         os_memset(&msg, 0, sizeof(msg));
868         msg.msg_iov = io;
869         msg.msg_iovlen = data ? 2 : 1;
870         msg.msg_name = &iface->drv_addr;
871         msg.msg_namelen = iface->drv_addr_len;
872
873         if (sendmsg(iface->fd, &msg, 0) < 0) {
874                 wpa_printf(MSG_ERROR, "sendmsg(wpas_socket): %s",
875                            strerror(errno));
876                 return -1;
877         }
878
879         return 0;
880 }
881
882
883 static void wpa_priv_send_auth(struct wpa_priv_interface *iface,
884                                union wpa_event_data *data)
885 {
886         size_t buflen = sizeof(struct privsep_event_auth) + data->auth.ies_len;
887         struct privsep_event_auth *auth;
888         u8 *buf, *pos;
889
890         buf = os_zalloc(buflen);
891         if (buf == NULL)
892                 return;
893
894         auth = (struct privsep_event_auth *) buf;
895         pos = (u8 *) (auth + 1);
896
897         os_memcpy(auth->peer, data->auth.peer, ETH_ALEN);
898         os_memcpy(auth->bssid, data->auth.bssid, ETH_ALEN);
899         auth->auth_type = data->auth.auth_type;
900         auth->auth_transaction = data->auth.auth_transaction;
901         auth->status_code = data->auth.status_code;
902         if (data->auth.ies) {
903                 os_memcpy(pos, data->auth.ies, data->auth.ies_len);
904                 auth->ies_len = data->auth.ies_len;
905         }
906
907         wpa_priv_send_event(iface, PRIVSEP_EVENT_AUTH, buf, buflen);
908
909         os_free(buf);
910 }
911
912
913 static void wpa_priv_send_assoc(struct wpa_priv_interface *iface, int event,
914                                 union wpa_event_data *data)
915 {
916         size_t buflen = 3 * sizeof(int);
917         u8 *buf, *pos;
918         int len;
919
920         if (data) {
921                 buflen += data->assoc_info.req_ies_len +
922                         data->assoc_info.resp_ies_len +
923                         data->assoc_info.beacon_ies_len;
924         }
925
926         buf = os_malloc(buflen);
927         if (buf == NULL)
928                 return;
929
930         pos = buf;
931
932         if (data && data->assoc_info.req_ies) {
933                 len = data->assoc_info.req_ies_len;
934                 os_memcpy(pos, &len, sizeof(int));
935                 pos += sizeof(int);
936                 os_memcpy(pos, data->assoc_info.req_ies, len);
937                 pos += len;
938         } else {
939                 len = 0;
940                 os_memcpy(pos, &len, sizeof(int));
941                 pos += sizeof(int);
942         }
943
944         if (data && data->assoc_info.resp_ies) {
945                 len = data->assoc_info.resp_ies_len;
946                 os_memcpy(pos, &len, sizeof(int));
947                 pos += sizeof(int);
948                 os_memcpy(pos, data->assoc_info.resp_ies, len);
949                 pos += len;
950         } else {
951                 len = 0;
952                 os_memcpy(pos, &len, sizeof(int));
953                 pos += sizeof(int);
954         }
955
956         if (data && data->assoc_info.beacon_ies) {
957                 len = data->assoc_info.beacon_ies_len;
958                 os_memcpy(pos, &len, sizeof(int));
959                 pos += sizeof(int);
960                 os_memcpy(pos, data->assoc_info.beacon_ies, len);
961                 pos += len;
962         } else {
963                 len = 0;
964                 os_memcpy(pos, &len, sizeof(int));
965                 pos += sizeof(int);
966         }
967
968         wpa_priv_send_event(iface, event, buf, buflen);
969
970         os_free(buf);
971 }
972
973
974 static void wpa_priv_send_interface_status(struct wpa_priv_interface *iface,
975                                            union wpa_event_data *data)
976 {
977         int ievent;
978         size_t len, maxlen;
979         u8 *buf;
980         char *ifname;
981
982         if (data == NULL)
983                 return;
984
985         ievent = data->interface_status.ievent;
986         maxlen = sizeof(data->interface_status.ifname);
987         ifname = data->interface_status.ifname;
988         for (len = 0; len < maxlen && ifname[len]; len++)
989                 ;
990
991         buf = os_malloc(sizeof(int) + len);
992         if (buf == NULL)
993                 return;
994
995         os_memcpy(buf, &ievent, sizeof(int));
996         os_memcpy(buf + sizeof(int), ifname, len);
997
998         wpa_priv_send_event(iface, PRIVSEP_EVENT_INTERFACE_STATUS,
999                             buf, sizeof(int) + len);
1000
1001         os_free(buf);
1002
1003 }
1004
1005
1006 static void wpa_priv_send_ft_response(struct wpa_priv_interface *iface,
1007                                       union wpa_event_data *data)
1008 {
1009         size_t len;
1010         u8 *buf, *pos;
1011
1012         if (data == NULL || data->ft_ies.ies == NULL)
1013                 return;
1014
1015         len = sizeof(int) + ETH_ALEN + data->ft_ies.ies_len;
1016         buf = os_malloc(len);
1017         if (buf == NULL)
1018                 return;
1019
1020         pos = buf;
1021         os_memcpy(pos, &data->ft_ies.ft_action, sizeof(int));
1022         pos += sizeof(int);
1023         os_memcpy(pos, data->ft_ies.target_ap, ETH_ALEN);
1024         pos += ETH_ALEN;
1025         os_memcpy(pos, data->ft_ies.ies, data->ft_ies.ies_len);
1026
1027         wpa_priv_send_event(iface, PRIVSEP_EVENT_FT_RESPONSE, buf, len);
1028
1029         os_free(buf);
1030
1031 }
1032
1033
1034 void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
1035                           union wpa_event_data *data)
1036 {
1037         struct wpa_priv_interface *iface = ctx;
1038
1039         wpa_printf(MSG_DEBUG, "%s - event=%d", __func__, event);
1040
1041         if (!iface->wpas_registered) {
1042                 wpa_printf(MSG_DEBUG, "Driver event received, but "
1043                            "wpa_supplicant not registered");
1044                 return;
1045         }
1046
1047         switch (event) {
1048         case EVENT_ASSOC:
1049                 wpa_priv_send_assoc(iface, PRIVSEP_EVENT_ASSOC, data);
1050                 break;
1051         case EVENT_DISASSOC:
1052                 wpa_priv_send_event(iface, PRIVSEP_EVENT_DISASSOC, NULL, 0);
1053                 break;
1054         case EVENT_ASSOCINFO:
1055                 if (data == NULL)
1056                         return;
1057                 wpa_priv_send_assoc(iface, PRIVSEP_EVENT_ASSOCINFO, data);
1058                 break;
1059         case EVENT_MICHAEL_MIC_FAILURE:
1060                 if (data == NULL)
1061                         return;
1062                 wpa_priv_send_event(iface, PRIVSEP_EVENT_MICHAEL_MIC_FAILURE,
1063                                     &data->michael_mic_failure.unicast,
1064                                     sizeof(int));
1065                 break;
1066         case EVENT_SCAN_STARTED:
1067                 wpa_priv_send_event(iface, PRIVSEP_EVENT_SCAN_STARTED, NULL,
1068                                     0);
1069                 break;
1070         case EVENT_SCAN_RESULTS:
1071                 wpa_priv_send_event(iface, PRIVSEP_EVENT_SCAN_RESULTS, NULL,
1072                                     0);
1073                 break;
1074         case EVENT_INTERFACE_STATUS:
1075                 wpa_priv_send_interface_status(iface, data);
1076                 break;
1077         case EVENT_PMKID_CANDIDATE:
1078                 if (data == NULL)
1079                         return;
1080                 wpa_priv_send_event(iface, PRIVSEP_EVENT_PMKID_CANDIDATE,
1081                                     &data->pmkid_candidate,
1082                                     sizeof(struct pmkid_candidate));
1083                 break;
1084         case EVENT_FT_RESPONSE:
1085                 wpa_priv_send_ft_response(iface, data);
1086                 break;
1087         case EVENT_AUTH:
1088                 wpa_priv_send_auth(iface, data);
1089                 break;
1090         default:
1091                 wpa_printf(MSG_DEBUG, "Unsupported driver event %d (%s) - TODO",
1092                            event, event_to_string(event));
1093                 break;
1094         }
1095 }
1096
1097
1098 void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
1099                                  union wpa_event_data *data)
1100 {
1101         struct wpa_priv_global *global = ctx;
1102         struct wpa_priv_interface *iface;
1103
1104         if (event != EVENT_INTERFACE_STATUS)
1105                 return;
1106
1107         for (iface = global->interfaces; iface; iface = iface->next) {
1108                 if (os_strcmp(iface->ifname, data->interface_status.ifname) ==
1109                     0)
1110                         break;
1111         }
1112         if (iface && iface->driver->get_ifindex) {
1113                 unsigned int ifindex;
1114
1115                 ifindex = iface->driver->get_ifindex(iface->drv_priv);
1116                 if (ifindex != data->interface_status.ifindex) {
1117                         wpa_printf(MSG_DEBUG,
1118                                    "%s: interface status ifindex %d mismatch (%d)",
1119                                    iface->ifname, ifindex,
1120                                    data->interface_status.ifindex);
1121                         return;
1122                 }
1123         }
1124         if (iface)
1125                 wpa_supplicant_event(iface, event, data);
1126 }
1127
1128
1129 void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
1130                              const u8 *buf, size_t len)
1131 {
1132         struct wpa_priv_interface *iface = ctx;
1133         struct msghdr msg;
1134         struct iovec io[3];
1135         int event = PRIVSEP_EVENT_RX_EAPOL;
1136
1137         wpa_printf(MSG_DEBUG, "RX EAPOL from driver");
1138         io[0].iov_base = &event;
1139         io[0].iov_len = sizeof(event);
1140         io[1].iov_base = (u8 *) src_addr;
1141         io[1].iov_len = ETH_ALEN;
1142         io[2].iov_base = (u8 *) buf;
1143         io[2].iov_len = len;
1144
1145         os_memset(&msg, 0, sizeof(msg));
1146         msg.msg_iov = io;
1147         msg.msg_iovlen = 3;
1148         msg.msg_name = &iface->drv_addr;
1149         msg.msg_namelen = iface->drv_addr_len;
1150
1151         if (sendmsg(iface->fd, &msg, 0) < 0)
1152                 wpa_printf(MSG_ERROR, "sendmsg(wpas_socket): %s",
1153                            strerror(errno));
1154 }
1155
1156
1157 static void wpa_priv_terminate(int sig, void *signal_ctx)
1158 {
1159         wpa_printf(MSG_DEBUG, "wpa_priv termination requested");
1160         eloop_terminate();
1161 }
1162
1163
1164 static void wpa_priv_fd_workaround(void)
1165 {
1166 #ifdef __linux__
1167         int s, i;
1168         /* When started from pcmcia-cs scripts, wpa_supplicant might start with
1169          * fd 0, 1, and 2 closed. This will cause some issues because many
1170          * places in wpa_supplicant are still printing out to stdout. As a
1171          * workaround, make sure that fd's 0, 1, and 2 are not used for other
1172          * sockets. */
1173         for (i = 0; i < 3; i++) {
1174                 s = open("/dev/null", O_RDWR);
1175                 if (s > 2) {
1176                         close(s);
1177                         break;
1178                 }
1179         }
1180 #endif /* __linux__ */
1181 }
1182
1183
1184 static void usage(void)
1185 {
1186         printf("wpa_priv v" VERSION_STR "\n"
1187                "Copyright (c) 2007-2017, Jouni Malinen <j@w1.fi> and "
1188                "contributors\n"
1189                "\n"
1190                "usage:\n"
1191                "  wpa_priv [-Bdd] [-c<ctrl dir>] [-P<pid file>] "
1192                "<driver:ifname> \\\n"
1193                "           [driver:ifname ...]\n");
1194 }
1195
1196
1197 int main(int argc, char *argv[])
1198 {
1199         int c, i;
1200         int ret = -1;
1201         char *pid_file = NULL;
1202         int daemonize = 0;
1203         char *ctrl_dir = "/var/run/wpa_priv";
1204         struct wpa_priv_global global;
1205         struct wpa_priv_interface *iface;
1206
1207         if (os_program_init())
1208                 return -1;
1209
1210         wpa_priv_fd_workaround();
1211
1212         os_memset(&global, 0, sizeof(global));
1213         global.interfaces = NULL;
1214
1215         for (;;) {
1216                 c = getopt(argc, argv, "Bc:dP:");
1217                 if (c < 0)
1218                         break;
1219                 switch (c) {
1220                 case 'B':
1221                         daemonize++;
1222                         break;
1223                 case 'c':
1224                         ctrl_dir = optarg;
1225                         break;
1226                 case 'd':
1227                         wpa_debug_level--;
1228                         break;
1229                 case 'P':
1230                         pid_file = os_rel2abs_path(optarg);
1231                         break;
1232                 default:
1233                         usage();
1234                         goto out2;
1235                 }
1236         }
1237
1238         if (optind >= argc) {
1239                 usage();
1240                 goto out2;
1241         }
1242
1243         wpa_printf(MSG_DEBUG, "wpa_priv control directory: '%s'", ctrl_dir);
1244
1245         if (eloop_init()) {
1246                 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
1247                 goto out2;
1248         }
1249
1250         for (i = optind; i < argc; i++) {
1251                 wpa_printf(MSG_DEBUG, "Adding driver:interface %s", argv[i]);
1252                 iface = wpa_priv_interface_init(&global, ctrl_dir, argv[i]);
1253                 if (iface == NULL)
1254                         goto out;
1255                 iface->next = global.interfaces;
1256                 global.interfaces = iface;
1257         }
1258
1259         if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1260                 goto out;
1261
1262         eloop_register_signal_terminate(wpa_priv_terminate, NULL);
1263         eloop_run();
1264
1265         ret = 0;
1266
1267 out:
1268         iface = global.interfaces;
1269         while (iface) {
1270                 struct wpa_priv_interface *prev = iface;
1271                 iface = iface->next;
1272                 wpa_priv_interface_deinit(prev);
1273         }
1274
1275         eloop_destroy();
1276
1277 out2:
1278         if (daemonize)
1279                 os_daemonize_terminate(pid_file);
1280         os_free(pid_file);
1281         os_program_deinit();
1282
1283         return ret;
1284 }