]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa_supplicant/ctrl_iface.c
This commit was generated by cvs2svn to compensate for changes in r155364,
[FreeBSD/FreeBSD.git] / contrib / wpa_supplicant / ctrl_iface.c
1 /*
2  * WPA Supplicant / UNIX domain socket -based control interface
3  * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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 <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <errno.h>
22 #ifndef CONFIG_NATIVE_WINDOWS
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <sys/uio.h>
26 #endif /* CONFIG_NATIVE_WINDOWS */
27
28 #include "common.h"
29 #include "eloop.h"
30 #include "wpa.h"
31 #include "wpa_supplicant.h"
32 #include "config.h"
33 #include "eapol_sm.h"
34 #include "wpa_supplicant_i.h"
35 #include "ctrl_iface.h"
36 #include "l2_packet.h"
37
38
39 #ifdef CONFIG_NATIVE_WINDOWS
40 typedef int socklen_t;
41 #endif /* CONFIG_NATIVE_WINDOWS */
42
43 #ifdef CONFIG_CTRL_IFACE_UDP
44 #define CTRL_IFACE_SOCK struct sockaddr_in
45 #else /* CONFIG_CTRL_IFACE_UDP */
46 #define CTRL_IFACE_SOCK struct sockaddr_un
47 #endif /* CONFIG_CTRL_IFACE_UDP */
48
49
50 struct wpa_ctrl_dst {
51         struct wpa_ctrl_dst *next;
52         CTRL_IFACE_SOCK addr;
53         socklen_t addrlen;
54         int debug_level;
55         int errors;
56 };
57
58
59 static const char * wpa_state_txt(int state)
60 {
61         switch (state) {
62         case WPA_DISCONNECTED:
63                 return "DISCONNECTED";
64         case WPA_SCANNING:
65                 return "SCANNING";
66         case WPA_ASSOCIATING:
67                 return "ASSOCIATING";
68         case WPA_ASSOCIATED:
69                 return "ASSOCIATED";
70         case WPA_4WAY_HANDSHAKE:
71                 return "4WAY_HANDSHAKE";
72         case WPA_GROUP_HANDSHAKE:
73                 return "GROUP_HANDSHAKE";
74         case WPA_COMPLETED:
75                 return "COMPLETED";
76         default:
77                 return "UNKNOWN";
78         }
79 }
80
81
82 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
83                                          char *cmd)
84 {
85         char *value;
86
87         value = strchr(cmd, ' ');
88         if (value == NULL)
89                 return -1;
90         *value++ = '\0';
91
92         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
93         if (strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
94                 eapol_sm_configure(wpa_s->eapol,
95                                    atoi(value), -1, -1, -1);
96         } else if (strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
97                 eapol_sm_configure(wpa_s->eapol,
98                                    -1, atoi(value), -1, -1);
99         } else if (strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
100                 eapol_sm_configure(wpa_s->eapol,
101                                    -1, -1, atoi(value), -1);
102         } else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) {
103                 eapol_sm_configure(wpa_s->eapol,
104                                    -1, -1, -1, atoi(value));
105         } else
106                 return -1;
107         return 0;
108 }
109
110
111 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
112                                              char *addr)
113 {
114         u8 bssid[ETH_ALEN];
115
116         if (hwaddr_aton(addr, bssid)) {
117                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
118                            "'%s'", addr);
119                 return -1;
120         }
121
122         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
123         rsn_preauth_deinit(wpa_s);
124         if (rsn_preauth_init(wpa_s, bssid))
125                 return -1;
126
127         return 0;
128 }
129
130
131 static int wpa_supplicant_ctrl_iface_attach(struct wpa_supplicant *wpa_s,
132                                             CTRL_IFACE_SOCK *from,
133                                             socklen_t fromlen)
134 {
135         struct wpa_ctrl_dst *dst;
136
137         dst = malloc(sizeof(*dst));
138         if (dst == NULL)
139                 return -1;
140         memset(dst, 0, sizeof(*dst));
141         memcpy(&dst->addr, from, sizeof(CTRL_IFACE_SOCK));
142         dst->addrlen = fromlen;
143         dst->debug_level = MSG_INFO;
144         dst->next = wpa_s->ctrl_dst;
145         wpa_s->ctrl_dst = dst;
146 #ifdef CONFIG_CTRL_IFACE_UDP
147         wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
148                    inet_ntoa(from->sin_addr), ntohs(from->sin_port));
149 #else /* CONFIG_CTRL_IFACE_UDP */
150         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
151                     (u8 *) from->sun_path, fromlen);
152 #endif /* CONFIG_CTRL_IFACE_UDP */
153         return 0;
154 }
155
156
157 static int wpa_supplicant_ctrl_iface_detach(struct wpa_supplicant *wpa_s,
158                                             CTRL_IFACE_SOCK *from,
159                                             socklen_t fromlen)
160 {
161         struct wpa_ctrl_dst *dst, *prev = NULL;
162
163         dst = wpa_s->ctrl_dst;
164         while (dst) {
165 #ifdef CONFIG_CTRL_IFACE_UDP
166                 if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
167                     from->sin_port == dst->addr.sin_port) {
168                         if (prev == NULL)
169                                 wpa_s->ctrl_dst = dst->next;
170                         else
171                                 prev->next = dst->next;
172                         free(dst);
173                         wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
174                                    "%s:%d", inet_ntoa(from->sin_addr),
175                                    ntohs(from->sin_port));
176                         return 0;
177                 }
178 #else /* CONFIG_CTRL_IFACE_UDP */
179                 if (fromlen == dst->addrlen &&
180                     memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) {
181                         if (prev == NULL)
182                                 wpa_s->ctrl_dst = dst->next;
183                         else
184                                 prev->next = dst->next;
185                         free(dst);
186                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
187                                     (u8 *) from->sun_path, fromlen);
188                         return 0;
189                 }
190 #endif /* CONFIG_CTRL_IFACE_UDP */
191                 prev = dst;
192                 dst = dst->next;
193         }
194         return -1;
195 }
196
197
198 static int wpa_supplicant_ctrl_iface_level(struct wpa_supplicant *wpa_s,
199                                            CTRL_IFACE_SOCK *from,
200                                            socklen_t fromlen,
201                                            char *level)
202 {
203         struct wpa_ctrl_dst *dst;
204
205         wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
206
207         dst = wpa_s->ctrl_dst;
208         while (dst) {
209 #ifdef CONFIG_CTRL_IFACE_UDP
210                 if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
211                     from->sin_port == dst->addr.sin_port) {
212                         wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
213                                    "level %s:%d", inet_ntoa(from->sin_addr),
214                                    ntohs(from->sin_port));
215                         dst->debug_level = atoi(level);
216                         return 0;
217                 }
218 #else /* CONFIG_CTRL_IFACE_UDP */
219                 if (fromlen == dst->addrlen &&
220                     memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) {
221                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
222                                     "level", (u8 *) from->sun_path, fromlen);
223                         dst->debug_level = atoi(level);
224                         return 0;
225                 }
226 #endif /* CONFIG_CTRL_IFACE_UDP */
227                 dst = dst->next;
228         }
229
230         return -1;
231 }
232
233
234 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
235                                               char *rsp)
236 {
237         char *pos, *id_pos;
238         int id;
239         struct wpa_ssid *ssid;
240
241         pos = strchr(rsp, '-');
242         if (pos == NULL)
243                 return -1;
244         *pos++ = '\0';
245         id_pos = pos;
246         pos = strchr(pos, ':');
247         if (pos == NULL)
248                 return -1;
249         *pos++ = '\0';
250         id = atoi(id_pos);
251         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
252         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
253                               (u8 *) pos, strlen(pos));
254
255         ssid = wpa_s->conf->ssid;
256         while (ssid) {
257                 if (id == ssid->id)
258                         break;
259                 ssid = ssid->next;
260         }
261
262         if (ssid == NULL) {
263                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
264                            "to update", id);
265                 return -1;
266         }
267
268         if (strcmp(rsp, "IDENTITY") == 0) {
269                 free(ssid->identity);
270                 ssid->identity = (u8 *) strdup(pos);
271                 ssid->identity_len = strlen(pos);
272                 ssid->pending_req_identity = 0;
273                 if (ssid == wpa_s->current_ssid)
274                         wpa_s->reassociate = 1;
275         } else if (strcmp(rsp, "PASSWORD") == 0) {
276                 free(ssid->password);
277                 ssid->password = (u8 *) strdup(pos);
278                 ssid->password_len = strlen(pos);
279                 ssid->pending_req_password = 0;
280                 if (ssid == wpa_s->current_ssid)
281                         wpa_s->reassociate = 1;
282         } else if (strcmp(rsp, "OTP") == 0) {
283                 free(ssid->otp);
284                 ssid->otp = (u8 *) strdup(pos);
285                 ssid->otp_len = strlen(pos);
286                 free(ssid->pending_req_otp);
287                 ssid->pending_req_otp = NULL;
288                 ssid->pending_req_otp_len = 0;
289         } else {
290                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
291                 return -1;
292         }
293
294         return 0;
295 }
296
297
298 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
299                                             const char *params,
300                                             char *buf, size_t buflen)
301 {
302         char *pos, *end;
303         int res, verbose;
304
305         verbose = strcmp(params, "-VERBOSE") == 0;
306         pos = buf;
307         end = buf + buflen;
308         pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n",
309                         MAC2STR(wpa_s->bssid));
310         if (wpa_s->current_ssid) {
311                 pos += snprintf(pos, end - pos, "ssid=%s\n",
312                                 wpa_ssid_txt(wpa_s->current_ssid->ssid,
313                                              wpa_s->current_ssid->ssid_len));
314         }
315         pos += snprintf(pos, end - pos,
316                         "pairwise_cipher=%s\n"
317                         "group_cipher=%s\n"
318                         "key_mgmt=%s\n"
319                         "wpa_state=%s\n",
320                         wpa_cipher_txt(wpa_s->pairwise_cipher),
321                         wpa_cipher_txt(wpa_s->group_cipher),
322                         wpa_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->proto),
323                         wpa_state_txt(wpa_s->wpa_state));
324
325         res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose);
326         if (res >= 0)
327                 pos += res;
328
329         if (wpa_s->preauth_eapol) {
330                 pos += snprintf(pos, end - pos, "Pre-authentication "
331                                 "EAPOL state machines:\n");
332                 res = eapol_sm_get_status(wpa_s->preauth_eapol,
333                                           pos, end - pos, verbose);
334                 if (res >= 0)
335                         pos += res;
336         }
337
338         return pos - buf;
339 }
340
341
342 static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
343                                               void *sock_ctx)
344 {
345         struct wpa_supplicant *wpa_s = eloop_ctx;
346         char buf[256];
347         int res;
348         CTRL_IFACE_SOCK from;
349         socklen_t fromlen = sizeof(from);
350         char *reply;
351         const int reply_size = 2048;
352         int reply_len;
353         int new_attached = 0, ctrl_rsp = 0;
354
355         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
356                        (struct sockaddr *) &from, &fromlen);
357         if (res < 0) {
358                 perror("recvfrom(ctrl_iface)");
359                 return;
360         }
361         buf[res] = '\0';
362         if (strncmp(buf, "CTRL-RSP-", 9) == 0) {
363                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
364                                       (u8 *) buf, res);
365         } else {
366                 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res);
367         }
368
369         reply = malloc(reply_size);
370         if (reply == NULL) {
371                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
372                        fromlen);
373                 return;
374         }
375
376         memcpy(reply, "OK\n", 3);
377         reply_len = 3;
378
379         if (strcmp(buf, "PING") == 0) {
380                 memcpy(reply, "PONG\n", 5);
381                 reply_len = 5;
382         } else if (strcmp(buf, "MIB") == 0) {
383                 reply_len = wpa_get_mib(wpa_s, reply, reply_size);
384                 if (reply_len >= 0) {
385                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
386                                                reply_size - reply_len);
387                         if (res < 0)
388                                 reply_len = -1;
389                         else
390                                 reply_len += res;
391                 }
392         } else if (strncmp(buf, "STATUS", 6) == 0) {
393                 reply_len = wpa_supplicant_ctrl_iface_status(
394                         wpa_s, buf + 6, reply, reply_size);
395         } else if (strcmp(buf, "PMKSA") == 0) {
396                 reply_len = pmksa_cache_list(wpa_s, reply, reply_size);
397         } else if (strncmp(buf, "SET ", 4) == 0) {
398                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
399                         reply_len = -1;
400         } else if (strcmp(buf, "LOGON") == 0) {
401                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
402         } else if (strcmp(buf, "LOGOFF") == 0) {
403                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
404         } else if (strcmp(buf, "REASSOCIATE") == 0) {
405                 wpa_s->reassociate = 1;
406                 wpa_supplicant_req_scan(wpa_s, 0, 0);
407         } else if (strncmp(buf, "PREAUTH ", 8) == 0) {
408                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
409                         reply_len = -1;
410         } else if (strcmp(buf, "ATTACH") == 0) {
411                 if (wpa_supplicant_ctrl_iface_attach(wpa_s, &from, fromlen))
412                         reply_len = -1;
413                 else
414                         new_attached = 1;
415         } else if (strcmp(buf, "DETACH") == 0) {
416                 if (wpa_supplicant_ctrl_iface_detach(wpa_s, &from, fromlen))
417                         reply_len = -1;
418         } else if (strncmp(buf, "LEVEL ", 6) == 0) {
419                 if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen,
420                                                     buf + 6))
421                         reply_len = -1;
422         } else if (strncmp(buf, "CTRL-RSP-", 9) == 0) {
423                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(wpa_s, buf + 9))
424                         reply_len = -1;
425                 else
426                         ctrl_rsp = 1;
427         } else if (strcmp(buf, "RECONFIGURE") == 0) {
428                 if (wpa_supplicant_reload_configuration(wpa_s))
429                         reply_len = -1;
430         } else if (strcmp(buf, "TERMINATE") == 0) {
431                 eloop_terminate();
432         } else {
433                 memcpy(reply, "UNKNOWN COMMAND\n", 16);
434                 reply_len = 16;
435         }
436
437         if (reply_len < 0) {
438                 memcpy(reply, "FAIL\n", 5);
439                 reply_len = 5;
440         }
441         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
442         free(reply);
443
444         if (new_attached)
445                 eapol_sm_notify_ctrl_attached(wpa_s->eapol);
446         if (ctrl_rsp)
447                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
448 }
449
450
451 static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
452 {
453         char *buf;
454         size_t len;
455
456         if (wpa_s->conf->ctrl_interface == NULL)
457                 return NULL;
458
459         len = strlen(wpa_s->conf->ctrl_interface) + strlen(wpa_s->ifname) + 2;
460         buf = malloc(len);
461         if (buf == NULL)
462                 return NULL;
463
464         snprintf(buf, len, "%s/%s",
465                  wpa_s->conf->ctrl_interface, wpa_s->ifname);
466 #ifdef __CYGWIN__
467         {
468                 /* Windows/WinPcap uses interface names that are not suitable
469                  * as a file name - convert invalid chars to underscores */
470                 char *pos = buf;
471                 while (*pos) {
472                         if (*pos == '\\')
473                                 *pos = '_';
474                         pos++;
475                 }
476         }
477 #endif /* __CYGWIN__ */
478         return buf;
479 }
480
481
482 int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
483 {
484         CTRL_IFACE_SOCK addr;
485         int s = -1;
486         char *fname = NULL;
487
488         wpa_s->ctrl_sock = -1;
489
490         if (wpa_s->conf->ctrl_interface == NULL)
491                 return 0;
492
493 #ifdef CONFIG_CTRL_IFACE_UDP
494         s = socket(PF_INET, SOCK_DGRAM, 0);
495         if (s < 0) {
496                 perror("socket(PF_INET)");
497                 goto fail;
498         }
499
500         memset(&addr, 0, sizeof(addr));
501         addr.sin_family = AF_INET;
502         addr.sin_addr.s_addr = htonl((127 << 24) | 1);
503         addr.sin_port = htons(9877);
504         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
505                 perror("bind(AF_UNIX)");
506                 goto fail;
507         }
508 #else /* CONFIG_CTRL_IFACE_UDP */
509         if (mkdir(wpa_s->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
510                 if (errno == EEXIST) {
511                         wpa_printf(MSG_DEBUG, "Using existing control "
512                                    "interface directory.");
513                 } else {
514                         perror("mkdir[ctrl_interface]");
515                         goto fail;
516                 }
517         }
518
519         if (wpa_s->conf->ctrl_interface_gid_set &&
520             chown(wpa_s->conf->ctrl_interface, 0,
521                   wpa_s->conf->ctrl_interface_gid) < 0) {
522                 perror("chown[ctrl_interface]");
523                 return -1;
524         }
525
526         if (strlen(wpa_s->conf->ctrl_interface) + 1 + strlen(wpa_s->ifname) >=
527             sizeof(addr.sun_path))
528                 goto fail;
529
530         s = socket(PF_UNIX, SOCK_DGRAM, 0);
531         if (s < 0) {
532                 perror("socket(PF_UNIX)");
533                 goto fail;
534         }
535
536         memset(&addr, 0, sizeof(addr));
537         addr.sun_family = AF_UNIX;
538         fname = wpa_supplicant_ctrl_iface_path(wpa_s);
539         if (fname == NULL)
540                 goto fail;
541         strncpy(addr.sun_path, fname, sizeof(addr.sun_path));
542         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
543                 perror("bind(PF_UNIX)");
544                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
545                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
546                                    " allow connections - assuming it was left"
547                                    "over from forced program termination");
548                         if (unlink(fname) < 0) {
549                                 perror("unlink[ctrl_iface]");
550                                 wpa_printf(MSG_ERROR, "Could not unlink "
551                                            "existing ctrl_iface socket '%s'",
552                                            fname);
553                                 goto fail;
554                         }
555                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
556                             0) {
557                                 perror("bind(PF_UNIX)");
558                                 goto fail;
559                         }
560                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
561                                    "ctrl_iface socket '%s'", fname);
562                 } else {
563                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
564                                    "be in use - cannot override it");
565                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
566                                    "not used anymore", fname);
567                         free(fname);
568                         fname = NULL;
569                         goto fail;
570                 }
571         }
572
573         if (wpa_s->conf->ctrl_interface_gid_set &&
574             chown(fname, 0, wpa_s->conf->ctrl_interface_gid) < 0) {
575                 perror("chown[ctrl_interface/ifname]");
576                 goto fail;
577         }
578
579         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
580                 perror("chmod[ctrl_interface/ifname]");
581                 goto fail;
582         }
583         free(fname);
584 #endif /* CONFIG_CTRL_IFACE_UDP */
585
586         wpa_s->ctrl_sock = s;
587         eloop_register_read_sock(s, wpa_supplicant_ctrl_iface_receive, wpa_s,
588                                  NULL);
589
590         return 0;
591
592 fail:
593         if (s >= 0)
594                 close(s);
595         if (fname) {
596                 unlink(fname);
597                 free(fname);
598         }
599         return -1;
600 }
601
602
603 void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
604 {
605         struct wpa_ctrl_dst *dst, *prev;
606
607         if (wpa_s->ctrl_sock > -1) {
608                 char *fname;
609                 eloop_unregister_read_sock(wpa_s->ctrl_sock);
610                 if (wpa_s->ctrl_dst) {
611                         /*
612                          * Wait a second before closing the control socket if
613                          * there are any attached monitors in order to allow
614                          * them to receive any pending messages.
615                          */
616                         wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
617                                    "monitors to receive messages");
618                         sleep(1);
619                 }
620                 close(wpa_s->ctrl_sock);
621                 wpa_s->ctrl_sock = -1;
622                 fname = wpa_supplicant_ctrl_iface_path(wpa_s);
623                 if (fname)
624                         unlink(fname);
625                 free(fname);
626
627                 if (rmdir(wpa_s->conf->ctrl_interface) < 0) {
628                         if (errno == ENOTEMPTY) {
629                                 wpa_printf(MSG_DEBUG, "Control interface "
630                                            "directory not empty - leaving it "
631                                            "behind");
632                         } else {
633                                 perror("rmdir[ctrl_interface]");
634                         }
635                 }
636         }
637
638         dst = wpa_s->ctrl_dst;
639         while (dst) {
640                 prev = dst;
641                 dst = dst->next;
642                 free(prev);
643         }
644 }
645
646
647 void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
648                                     char *buf, size_t len)
649 {
650         struct wpa_ctrl_dst *dst, *next;
651         char levelstr[10];
652         int idx;
653 #ifdef CONFIG_CTRL_IFACE_UDP
654         char *sbuf;
655         int llen;
656
657         dst = wpa_s->ctrl_dst;
658         if (wpa_s->ctrl_sock < 0 || dst == NULL)
659                 return;
660
661         snprintf(levelstr, sizeof(levelstr), "<%d>", level);
662
663         llen = strlen(levelstr);
664         sbuf = malloc(llen + len);
665         if (sbuf == NULL)
666                 return;
667
668         memcpy(sbuf, levelstr, llen);
669         memcpy(sbuf + llen, buf, len);
670
671         idx = 0;
672         while (dst) {
673                 next = dst->next;
674                 if (level >= dst->debug_level) {
675                         wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
676                                    inet_ntoa(dst->addr.sin_addr),
677                                    ntohs(dst->addr.sin_port));
678                         if (sendto(wpa_s->ctrl_sock, sbuf, llen + len, 0,
679                                    (struct sockaddr *) &dst->addr,
680                                    sizeof(dst->addr)) < 0) {
681                                 fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
682                                         idx);
683                                 perror("sendto");
684                                 dst->errors++;
685                                 if (dst->errors > 10) {
686                                         wpa_supplicant_ctrl_iface_detach(
687                                                 wpa_s, &dst->addr,
688                                                 dst->addrlen);
689                                 }
690                         } else
691                                 dst->errors = 0;
692                 }
693                 idx++;
694                 dst = next;
695         }
696         free(sbuf);
697 #else /* CONFIG_CTRL_IFACE_UDP */
698         struct msghdr msg;
699         struct iovec io[2];
700
701         dst = wpa_s->ctrl_dst;
702         if (wpa_s->ctrl_sock < 0 || dst == NULL)
703                 return;
704
705         snprintf(levelstr, sizeof(levelstr), "<%d>", level);
706         io[0].iov_base = levelstr;
707         io[0].iov_len = strlen(levelstr);
708         io[1].iov_base = buf;
709         io[1].iov_len = len;
710         memset(&msg, 0, sizeof(msg));
711         msg.msg_iov = io;
712         msg.msg_iovlen = 2;
713
714         idx = 0;
715         while (dst) {
716                 next = dst->next;
717                 if (level >= dst->debug_level) {
718                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
719                                     (u8 *) dst->addr.sun_path, dst->addrlen);
720                         msg.msg_name = &dst->addr;
721                         msg.msg_namelen = dst->addrlen;
722                         if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) {
723                                 fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
724                                         idx);
725                                 perror("sendmsg");
726                                 dst->errors++;
727                                 if (dst->errors > 10) {
728                                         wpa_supplicant_ctrl_iface_detach(
729                                                 wpa_s, &dst->addr,
730                                                 dst->addrlen);
731                                 }
732                         } else
733                                 dst->errors = 0;
734                 }
735                 idx++;
736                 dst = next;
737         }
738 #endif /* CONFIG_CTRL_IFACE_UDP */
739 }