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