]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa_supplicant/ctrl_iface.c
This commit was generated by cvs2svn to compensate for changes in r147021,
[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 value='%s'",
252                    rsp, id, pos);
253
254         ssid = wpa_s->conf->ssid;
255         while (ssid) {
256                 if (id == ssid->id)
257                         break;
258                 ssid = ssid->next;
259         }
260
261         if (ssid == NULL) {
262                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
263                            "to update", id);
264                 return -1;
265         }
266
267         if (strcmp(rsp, "IDENTITY") == 0) {
268                 free(ssid->identity);
269                 ssid->identity = (u8 *) strdup(pos);
270                 ssid->identity_len = strlen(pos);
271                 ssid->pending_req_identity = 0;
272                 if (ssid == wpa_s->current_ssid)
273                         wpa_s->reassociate = 1;
274         } else if (strcmp(rsp, "PASSWORD") == 0) {
275                 free(ssid->password);
276                 ssid->password = (u8 *) strdup(pos);
277                 ssid->password_len = strlen(pos);
278                 ssid->pending_req_password = 0;
279                 if (ssid == wpa_s->current_ssid)
280                         wpa_s->reassociate = 1;
281         } else if (strcmp(rsp, "OTP") == 0) {
282                 free(ssid->otp);
283                 ssid->otp = (u8 *) strdup(pos);
284                 ssid->otp_len = strlen(pos);
285                 free(ssid->pending_req_otp);
286                 ssid->pending_req_otp = NULL;
287                 ssid->pending_req_otp_len = 0;
288         } else {
289                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
290                 return -1;
291         }
292
293         return 0;
294 }
295
296
297 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
298                                             const char *params,
299                                             char *buf, size_t buflen)
300 {
301         char *pos, *end;
302         int res, verbose;
303
304         verbose = strcmp(params, "-VERBOSE") == 0;
305         pos = buf;
306         end = buf + buflen;
307         pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n",
308                         MAC2STR(wpa_s->bssid));
309         if (wpa_s->current_ssid) {
310                 pos += snprintf(pos, end - pos, "ssid=%s\n",
311                                 wpa_ssid_txt(wpa_s->current_ssid->ssid,
312                                              wpa_s->current_ssid->ssid_len));
313         }
314         pos += snprintf(pos, end - pos,
315                         "pairwise_cipher=%s\n"
316                         "group_cipher=%s\n"
317                         "key_mgmt=%s\n"
318                         "wpa_state=%s\n",
319                         wpa_cipher_txt(wpa_s->pairwise_cipher),
320                         wpa_cipher_txt(wpa_s->group_cipher),
321                         wpa_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->proto),
322                         wpa_state_txt(wpa_s->wpa_state));
323
324         res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose);
325         if (res >= 0)
326                 pos += res;
327
328         if (wpa_s->preauth_eapol) {
329                 pos += snprintf(pos, end - pos, "Pre-authentication "
330                                 "EAPOL state machines:\n");
331                 res = eapol_sm_get_status(wpa_s->preauth_eapol,
332                                           pos, end - pos, verbose);
333                 if (res >= 0)
334                         pos += res;
335         }
336
337         return pos - buf;
338 }
339
340
341 static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
342                                               void *sock_ctx)
343 {
344         struct wpa_supplicant *wpa_s = eloop_ctx;
345         char buf[256];
346         int res;
347         CTRL_IFACE_SOCK from;
348         socklen_t fromlen = sizeof(from);
349         char *reply;
350         const int reply_size = 2048;
351         int reply_len;
352         int new_attached = 0, ctrl_rsp = 0;
353
354         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
355                        (struct sockaddr *) &from, &fromlen);
356         if (res < 0) {
357                 perror("recvfrom(ctrl_iface)");
358                 return;
359         }
360         buf[res] = '\0';
361         if (strncmp(buf, "CTRL-RSP-", 9) == 0) {
362                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
363                                       (u8 *) buf, res);
364         } else {
365                 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res);
366         }
367
368         reply = malloc(reply_size);
369         if (reply == NULL) {
370                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
371                        fromlen);
372                 return;
373         }
374
375         memcpy(reply, "OK\n", 3);
376         reply_len = 3;
377
378         if (strcmp(buf, "PING") == 0) {
379                 memcpy(reply, "PONG\n", 5);
380                 reply_len = 5;
381         } else if (strcmp(buf, "MIB") == 0) {
382                 reply_len = wpa_get_mib(wpa_s, reply, reply_size);
383                 if (reply_len >= 0) {
384                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
385                                                reply_size - reply_len);
386                         if (res < 0)
387                                 reply_len = -1;
388                         else
389                                 reply_len += res;
390                 }
391         } else if (strncmp(buf, "STATUS", 6) == 0) {
392                 reply_len = wpa_supplicant_ctrl_iface_status(
393                         wpa_s, buf + 6, reply, reply_size);
394         } else if (strcmp(buf, "PMKSA") == 0) {
395                 reply_len = pmksa_cache_list(wpa_s, reply, reply_size);
396         } else if (strncmp(buf, "SET ", 4) == 0) {
397                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
398                         reply_len = -1;
399         } else if (strcmp(buf, "LOGON") == 0) {
400                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
401         } else if (strcmp(buf, "LOGOFF") == 0) {
402                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
403         } else if (strcmp(buf, "REASSOCIATE") == 0) {
404                 wpa_s->reassociate = 1;
405                 wpa_supplicant_req_scan(wpa_s, 0, 0);
406         } else if (strncmp(buf, "PREAUTH ", 8) == 0) {
407                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
408                         reply_len = -1;
409         } else if (strcmp(buf, "ATTACH") == 0) {
410                 if (wpa_supplicant_ctrl_iface_attach(wpa_s, &from, fromlen))
411                         reply_len = -1;
412                 else
413                         new_attached = 1;
414         } else if (strcmp(buf, "DETACH") == 0) {
415                 if (wpa_supplicant_ctrl_iface_detach(wpa_s, &from, fromlen))
416                         reply_len = -1;
417         } else if (strncmp(buf, "LEVEL ", 6) == 0) {
418                 if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen,
419                                                     buf + 6))
420                         reply_len = -1;
421         } else if (strncmp(buf, "CTRL-RSP-", 9) == 0) {
422                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(wpa_s, buf + 9))
423                         reply_len = -1;
424                 else
425                         ctrl_rsp = 1;
426         } else if (strcmp(buf, "RECONFIGURE") == 0) {
427                 if (wpa_supplicant_reload_configuration(wpa_s))
428                         reply_len = -1;
429         } else if (strcmp(buf, "TERMINATE") == 0) {
430                 eloop_terminate();
431         } else {
432                 memcpy(reply, "UNKNOWN COMMAND\n", 16);
433                 reply_len = 16;
434         }
435
436         if (reply_len < 0) {
437                 memcpy(reply, "FAIL\n", 5);
438                 reply_len = 5;
439         }
440         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
441         free(reply);
442
443         if (new_attached)
444                 eapol_sm_notify_ctrl_attached(wpa_s->eapol);
445         if (ctrl_rsp)
446                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
447 }
448
449
450 static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
451 {
452         char *buf;
453         size_t len;
454
455         if (wpa_s->conf->ctrl_interface == NULL)
456                 return NULL;
457
458         len = strlen(wpa_s->conf->ctrl_interface) + strlen(wpa_s->ifname) + 2;
459         buf = malloc(len);
460         if (buf == NULL)
461                 return NULL;
462
463         snprintf(buf, len, "%s/%s",
464                  wpa_s->conf->ctrl_interface, wpa_s->ifname);
465 #ifdef __CYGWIN__
466         {
467                 /* Windows/WinPcap uses interface names that are not suitable
468                  * as a file name - convert invalid chars to underscores */
469                 char *pos = buf;
470                 while (*pos) {
471                         if (*pos == '\\')
472                                 *pos = '_';
473                         pos++;
474                 }
475         }
476 #endif /* __CYGWIN__ */
477         return buf;
478 }
479
480
481 int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
482 {
483         CTRL_IFACE_SOCK addr;
484         int s = -1;
485         char *fname = NULL;
486
487         wpa_s->ctrl_sock = -1;
488
489         if (wpa_s->conf->ctrl_interface == NULL)
490                 return 0;
491
492 #ifdef CONFIG_CTRL_IFACE_UDP
493         s = socket(PF_INET, SOCK_DGRAM, 0);
494         if (s < 0) {
495                 perror("socket(PF_INET)");
496                 goto fail;
497         }
498
499         memset(&addr, 0, sizeof(addr));
500         addr.sin_family = AF_INET;
501         addr.sin_addr.s_addr = htonl((127 << 24) | 1);
502         addr.sin_port = htons(9877);
503         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
504                 perror("bind(AF_UNIX)");
505                 goto fail;
506         }
507 #else /* CONFIG_CTRL_IFACE_UDP */
508         if (mkdir(wpa_s->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
509                 if (errno == EEXIST) {
510                         wpa_printf(MSG_DEBUG, "Using existing control "
511                                    "interface directory.");
512                 } else {
513                         perror("mkdir[ctrl_interface]");
514                         goto fail;
515                 }
516         }
517
518         if (wpa_s->conf->ctrl_interface_gid_set &&
519             chown(wpa_s->conf->ctrl_interface, 0,
520                   wpa_s->conf->ctrl_interface_gid) < 0) {
521                 perror("chown[ctrl_interface]");
522                 return -1;
523         }
524
525         if (strlen(wpa_s->conf->ctrl_interface) + 1 + strlen(wpa_s->ifname) >=
526             sizeof(addr.sun_path))
527                 goto fail;
528
529         s = socket(PF_UNIX, SOCK_DGRAM, 0);
530         if (s < 0) {
531                 perror("socket(PF_UNIX)");
532                 goto fail;
533         }
534
535         memset(&addr, 0, sizeof(addr));
536         addr.sun_family = AF_UNIX;
537         fname = wpa_supplicant_ctrl_iface_path(wpa_s);
538         if (fname == NULL)
539                 goto fail;
540         strncpy(addr.sun_path, fname, sizeof(addr.sun_path));
541         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
542                 perror("bind(PF_UNIX)");
543                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
544                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
545                                    " allow connections - assuming it was left"
546                                    "over from forced program termination");
547                         if (unlink(fname) < 0) {
548                                 perror("unlink[ctrl_iface]");
549                                 wpa_printf(MSG_ERROR, "Could not unlink "
550                                            "existing ctrl_iface socket '%s'",
551                                            fname);
552                                 goto fail;
553                         }
554                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
555                             0) {
556                                 perror("bind(PF_UNIX)");
557                                 goto fail;
558                         }
559                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
560                                    "ctrl_iface socket '%s'", fname);
561                 } else {
562                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
563                                    "be in use - cannot override it");
564                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
565                                    "not used anymore", fname);
566                         free(fname);
567                         fname = NULL;
568                         goto fail;
569                 }
570         }
571
572         if (wpa_s->conf->ctrl_interface_gid_set &&
573             chown(fname, 0, wpa_s->conf->ctrl_interface_gid) < 0) {
574                 perror("chown[ctrl_interface/ifname]");
575                 goto fail;
576         }
577
578         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
579                 perror("chmod[ctrl_interface/ifname]");
580                 goto fail;
581         }
582         free(fname);
583 #endif /* CONFIG_CTRL_IFACE_UDP */
584
585         wpa_s->ctrl_sock = s;
586         eloop_register_read_sock(s, wpa_supplicant_ctrl_iface_receive, wpa_s,
587                                  NULL);
588
589         return 0;
590
591 fail:
592         if (s >= 0)
593                 close(s);
594         if (fname) {
595                 unlink(fname);
596                 free(fname);
597         }
598         return -1;
599 }
600
601
602 void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
603 {
604         struct wpa_ctrl_dst *dst, *prev;
605
606         if (wpa_s->ctrl_sock > -1) {
607                 char *fname;
608                 eloop_unregister_read_sock(wpa_s->ctrl_sock);
609                 close(wpa_s->ctrl_sock);
610                 wpa_s->ctrl_sock = -1;
611                 fname = wpa_supplicant_ctrl_iface_path(wpa_s);
612                 if (fname)
613                         unlink(fname);
614                 free(fname);
615
616                 if (rmdir(wpa_s->conf->ctrl_interface) < 0) {
617                         if (errno == ENOTEMPTY) {
618                                 wpa_printf(MSG_DEBUG, "Control interface "
619                                            "directory not empty - leaving it "
620                                            "behind");
621                         } else {
622                                 perror("rmdir[ctrl_interface]");
623                         }
624                 }
625         }
626
627         dst = wpa_s->ctrl_dst;
628         while (dst) {
629                 prev = dst;
630                 dst = dst->next;
631                 free(prev);
632         }
633 }
634
635
636 void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
637                                     char *buf, size_t len)
638 {
639         struct wpa_ctrl_dst *dst, *next;
640         char levelstr[10];
641         int idx;
642 #ifdef CONFIG_CTRL_IFACE_UDP
643         char *sbuf;
644         int llen;
645
646         dst = wpa_s->ctrl_dst;
647         if (wpa_s->ctrl_sock < 0 || dst == NULL)
648                 return;
649
650         snprintf(levelstr, sizeof(levelstr), "<%d>", level);
651
652         llen = strlen(levelstr);
653         sbuf = malloc(llen + len);
654         if (sbuf == NULL)
655                 return;
656
657         memcpy(sbuf, levelstr, llen);
658         memcpy(sbuf + llen, buf, len);
659
660         idx = 0;
661         while (dst) {
662                 next = dst->next;
663                 if (level >= dst->debug_level) {
664                         wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
665                                    inet_ntoa(dst->addr.sin_addr),
666                                    ntohs(dst->addr.sin_port));
667                         if (sendto(wpa_s->ctrl_sock, sbuf, llen + len, 0,
668                                    (struct sockaddr *) &dst->addr,
669                                    sizeof(dst->addr)) < 0) {
670                                 fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
671                                         idx);
672                                 perror("sendto");
673                                 dst->errors++;
674                                 if (dst->errors > 10) {
675                                         wpa_supplicant_ctrl_iface_detach(
676                                                 wpa_s, &dst->addr,
677                                                 dst->addrlen);
678                                 }
679                         } else
680                                 dst->errors = 0;
681                 }
682                 idx++;
683                 dst = next;
684         }
685         free(sbuf);
686 #else /* CONFIG_CTRL_IFACE_UDP */
687         struct msghdr msg;
688         struct iovec io[2];
689
690         dst = wpa_s->ctrl_dst;
691         if (wpa_s->ctrl_sock < 0 || dst == NULL)
692                 return;
693
694         snprintf(levelstr, sizeof(levelstr), "<%d>", level);
695         io[0].iov_base = levelstr;
696         io[0].iov_len = strlen(levelstr);
697         io[1].iov_base = buf;
698         io[1].iov_len = len;
699         memset(&msg, 0, sizeof(msg));
700         msg.msg_iov = io;
701         msg.msg_iovlen = 2;
702
703         idx = 0;
704         while (dst) {
705                 next = dst->next;
706                 if (level >= dst->debug_level) {
707                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
708                                     (u8 *) dst->addr.sun_path, dst->addrlen);
709                         msg.msg_name = &dst->addr;
710                         msg.msg_namelen = dst->addrlen;
711                         if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) {
712                                 fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
713                                         idx);
714                                 perror("sendmsg");
715                                 dst->errors++;
716                                 if (dst->errors > 10) {
717                                         wpa_supplicant_ctrl_iface_detach(
718                                                 wpa_s, &dst->addr,
719                                                 dst->addrlen);
720                                 }
721                         } else
722                                 dst->errors = 0;
723                 }
724                 idx++;
725                 dst = next;
726         }
727 #endif /* CONFIG_CTRL_IFACE_UDP */
728 }