iwinfo: Fix incorrect buffer allocation in nl80211_get_ifcomb_cb()
[project/iwinfo.git] / iwinfo_nl80211.c
1 /*
2  * iwinfo - Wireless Information Library - NL80211 Backend
3  *
4  *   Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
5  *
6  * The iwinfo library is free software: you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License version 2
8  * as published by the Free Software Foundation.
9  *
10  * The iwinfo library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with the iwinfo library. If not, see http://www.gnu.org/licenses/.
17  *
18  * The signal handling code is derived from the official madwifi tools,
19  * wlanconfig.c in particular. The encryption property handling was
20  * inspired by the hostapd madwifi driver.
21  *
22  * Parts of this code are derived from the Linux iw utility.
23  */
24
25 #include <limits.h>
26 #include <glob.h>
27 #include <fnmatch.h>
28 #include "iwinfo_nl80211.h"
29
30 #define min(x, y) ((x) < (y)) ? (x) : (y)
31
32 static struct nl80211_state *nls = NULL;
33
34 static void nl80211_close(void)
35 {
36         if (nls)
37         {
38                 if (nls->nlctrl)
39                         genl_family_put(nls->nlctrl);
40
41                 if (nls->nl80211)
42                         genl_family_put(nls->nl80211);
43
44                 if (nls->nl_sock)
45                         nl_socket_free(nls->nl_sock);
46
47                 if (nls->nl_cache)
48                         nl_cache_free(nls->nl_cache);
49
50                 free(nls);
51                 nls = NULL;
52         }
53 }
54
55 static int nl80211_init(void)
56 {
57         int err, fd;
58
59         if (!nls)
60         {
61                 nls = malloc(sizeof(struct nl80211_state));
62                 if (!nls) {
63                         err = -ENOMEM;
64                         goto err;
65                 }
66
67                 memset(nls, 0, sizeof(*nls));
68
69                 nls->nl_sock = nl_socket_alloc();
70                 if (!nls->nl_sock) {
71                         err = -ENOMEM;
72                         goto err;
73                 }
74
75                 if (genl_connect(nls->nl_sock)) {
76                         err = -ENOLINK;
77                         goto err;
78                 }
79
80                 fd = nl_socket_get_fd(nls->nl_sock);
81                 if (fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) < 0) {
82                         err = -EINVAL;
83                         goto err;
84                 }
85
86                 if (genl_ctrl_alloc_cache(nls->nl_sock, &nls->nl_cache)) {
87                         err = -ENOMEM;
88                         goto err;
89                 }
90
91                 nls->nl80211 = genl_ctrl_search_by_name(nls->nl_cache, "nl80211");
92                 if (!nls->nl80211) {
93                         err = -ENOENT;
94                         goto err;
95                 }
96
97                 nls->nlctrl = genl_ctrl_search_by_name(nls->nl_cache, "nlctrl");
98                 if (!nls->nlctrl) {
99                         err = -ENOENT;
100                         goto err;
101                 }
102         }
103
104         return 0;
105
106
107 err:
108         nl80211_close();
109         return err;
110 }
111
112 static int nl80211_readint(const char *path)
113 {
114         int fd;
115         int rv = -1;
116         char buffer[16];
117
118         if ((fd = open(path, O_RDONLY)) > -1)
119         {
120                 if (read(fd, buffer, sizeof(buffer)) > 0)
121                         rv = atoi(buffer);
122
123                 close(fd);
124         }
125
126         return rv;
127 }
128
129 static int nl80211_readstr(const char *path, char *buffer, int length)
130 {
131         int fd;
132         int rv = -1;
133
134         if ((fd = open(path, O_RDONLY)) > -1)
135         {
136                 if ((rv = read(fd, buffer, length - 1)) > 0)
137                 {
138                         if (buffer[rv - 1] == '\n')
139                                 rv--;
140
141                         buffer[rv] = 0;
142                 }
143
144                 close(fd);
145         }
146
147         return rv;
148 }
149
150
151 static int nl80211_msg_error(struct sockaddr_nl *nla,
152         struct nlmsgerr *err, void *arg)
153 {
154         int *ret = arg;
155         *ret = err->error;
156         return NL_STOP;
157 }
158
159 static int nl80211_msg_finish(struct nl_msg *msg, void *arg)
160 {
161         int *ret = arg;
162         *ret = 0;
163         return NL_SKIP;
164 }
165
166 static int nl80211_msg_ack(struct nl_msg *msg, void *arg)
167 {
168         int *ret = arg;
169         *ret = 0;
170         return NL_STOP;
171 }
172
173 static int nl80211_msg_response(struct nl_msg *msg, void *arg)
174 {
175         return NL_SKIP;
176 }
177
178 static void nl80211_free(struct nl80211_msg_conveyor *cv)
179 {
180         if (cv)
181         {
182                 if (cv->cb)
183                         nl_cb_put(cv->cb);
184
185                 if (cv->msg)
186                         nlmsg_free(cv->msg);
187
188                 cv->cb  = NULL;
189                 cv->msg = NULL;
190         }
191 }
192
193 static struct nl80211_msg_conveyor * nl80211_new(struct genl_family *family,
194                                                  int cmd, int flags)
195 {
196         static struct nl80211_msg_conveyor cv;
197
198         struct nl_msg *req = NULL;
199         struct nl_cb *cb = NULL;
200
201         req = nlmsg_alloc();
202         if (!req)
203                 goto err;
204
205         cb = nl_cb_alloc(NL_CB_DEFAULT);
206         if (!cb)
207                 goto err;
208
209         genlmsg_put(req, 0, 0, genl_family_get_id(family), 0, flags, cmd, 0);
210
211         cv.msg = req;
212         cv.cb  = cb;
213
214         return &cv;
215
216 err:
217 nla_put_failure:
218         if (cb)
219                 nl_cb_put(cb);
220
221         if (req)
222                 nlmsg_free(req);
223
224         return NULL;
225 }
226
227 static struct nl80211_msg_conveyor * nl80211_ctl(int cmd, int flags)
228 {
229         if (nl80211_init() < 0)
230                 return NULL;
231
232         return nl80211_new(nls->nlctrl, cmd, flags);
233 }
234
235 static int nl80211_phy_idx_from_uci_path(struct uci_section *s)
236 {
237         const char *opt;
238         char buf[128];
239         int idx = -1;
240         glob_t gl;
241
242         opt = uci_lookup_option_string(uci_ctx, s, "path");
243         if (!opt)
244                 return -1;
245
246         snprintf(buf, sizeof(buf), "/sys/devices/%s/ieee80211/*/index", opt);  /**/
247         if (glob(buf, 0, NULL, &gl))
248                 return -1;
249
250         if (gl.gl_pathc > 0)
251                 idx = nl80211_readint(gl.gl_pathv[0]);
252
253         globfree(&gl);
254
255         return idx;
256 }
257
258 static int nl80211_phy_idx_from_uci_macaddr(struct uci_section *s)
259 {
260         const char *opt;
261         char buf[128];
262         int i, idx = -1;
263         glob_t gl;
264
265         opt = uci_lookup_option_string(uci_ctx, s, "macaddr");
266         if (!opt)
267                 return -1;
268
269         snprintf(buf, sizeof(buf), "/sys/class/ieee80211/*", opt);      /**/
270         if (glob(buf, 0, NULL, &gl))
271                 return -1;
272
273         for (i = 0; i < gl.gl_pathc; i++)
274         {
275                 snprintf(buf, sizeof(buf), "%s/macaddress", gl.gl_pathv[i]);
276                 if (nl80211_readstr(buf, buf, sizeof(buf)) <= 0)
277                         continue;
278
279                 if (fnmatch(opt, buf, FNM_CASEFOLD))
280                         continue;
281
282                 snprintf(buf, sizeof(buf), "%s/index", gl.gl_pathv[i]);
283                 if ((idx = nl80211_readint(buf)) > -1)
284                         break;
285         }
286
287         globfree(&gl);
288
289         return idx;
290 }
291
292 static int nl80211_phy_idx_from_uci_phy(struct uci_section *s)
293 {
294         const char *opt;
295         char buf[128];
296
297         opt = uci_lookup_option_string(uci_ctx, s, "phy");
298         if (!opt)
299                 return -1;
300
301         snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/index", opt);
302         return nl80211_readint(buf);
303 }
304
305 static int nl80211_phy_idx_from_uci(const char *name)
306 {
307         struct uci_section *s;
308         int idx = -1;
309
310         s = iwinfo_uci_get_radio(name, "mac80211");
311         if (!s)
312                 goto free;
313
314         idx = nl80211_phy_idx_from_uci_path(s);
315
316         if (idx < 0)
317                 idx = nl80211_phy_idx_from_uci_macaddr(s);
318
319         if (idx < 0)
320                 idx = nl80211_phy_idx_from_uci_phy(s);
321
322 free:
323         iwinfo_uci_free();
324         return idx;
325 }
326
327 static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname,
328                                                  int cmd, int flags)
329 {
330         int ifidx = -1, phyidx = -1;
331         struct nl80211_msg_conveyor *cv;
332
333         if (ifname == NULL)
334                 return NULL;
335
336         if (nl80211_init() < 0)
337                 return NULL;
338
339         if (!strncmp(ifname, "phy", 3))
340                 phyidx = atoi(&ifname[3]);
341         else if (!strncmp(ifname, "radio", 5))
342                 phyidx = nl80211_phy_idx_from_uci(ifname);
343         else if (!strncmp(ifname, "mon.", 4))
344                 ifidx = if_nametoindex(&ifname[4]);
345         else
346                 ifidx = if_nametoindex(ifname);
347
348         /* Valid ifidx must be greater than 0 */
349         if ((ifidx <= 0) && (phyidx < 0))
350                 return NULL;
351
352         cv = nl80211_new(nls->nl80211, cmd, flags);
353         if (!cv)
354                 return NULL;
355
356         if (ifidx > -1)
357                 NLA_PUT_U32(cv->msg, NL80211_ATTR_IFINDEX, ifidx);
358
359         if (phyidx > -1)
360                 NLA_PUT_U32(cv->msg, NL80211_ATTR_WIPHY, phyidx);
361
362         return cv;
363
364 nla_put_failure:
365         nl80211_free(cv);
366         return NULL;
367 }
368
369 static struct nl80211_msg_conveyor * nl80211_send(
370         struct nl80211_msg_conveyor *cv,
371         int (*cb_func)(struct nl_msg *, void *), void *cb_arg
372 ) {
373         static struct nl80211_msg_conveyor rcv;
374         int err = 1;
375
376         if (cb_func)
377                 nl_cb_set(cv->cb, NL_CB_VALID, NL_CB_CUSTOM, cb_func, cb_arg);
378         else
379                 nl_cb_set(cv->cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_msg_response, &rcv);
380
381         if (nl_send_auto_complete(nls->nl_sock, cv->msg) < 0)
382                 goto err;
383
384         nl_cb_err(cv->cb,               NL_CB_CUSTOM, nl80211_msg_error,  &err);
385         nl_cb_set(cv->cb, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_msg_finish, &err);
386         nl_cb_set(cv->cb, NL_CB_ACK,    NL_CB_CUSTOM, nl80211_msg_ack,    &err);
387
388         while (err > 0)
389                 nl_recvmsgs(nls->nl_sock, cv->cb);
390
391         return &rcv;
392
393 err:
394         nl_cb_put(cv->cb);
395         nlmsg_free(cv->msg);
396
397         return NULL;
398 }
399
400 static struct nlattr ** nl80211_parse(struct nl_msg *msg)
401 {
402         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
403         static struct nlattr *attr[NL80211_ATTR_MAX + 1];
404
405         nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
406                   genlmsg_attrlen(gnlh, 0), NULL);
407
408         return attr;
409 }
410
411
412 static int nl80211_subscribe_cb(struct nl_msg *msg, void *arg)
413 {
414         struct nl80211_group_conveyor *cv = arg;
415
416         struct nlattr **attr = nl80211_parse(msg);
417         struct nlattr *mgrpinfo[CTRL_ATTR_MCAST_GRP_MAX + 1];
418         struct nlattr *mgrp;
419         int mgrpidx;
420
421         if (!attr[CTRL_ATTR_MCAST_GROUPS])
422                 return NL_SKIP;
423
424         nla_for_each_nested(mgrp, attr[CTRL_ATTR_MCAST_GROUPS], mgrpidx)
425         {
426                 nla_parse(mgrpinfo, CTRL_ATTR_MCAST_GRP_MAX,
427                           nla_data(mgrp), nla_len(mgrp), NULL);
428
429                 if (mgrpinfo[CTRL_ATTR_MCAST_GRP_ID] &&
430                     mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME] &&
431                     !strncmp(nla_data(mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME]),
432                              cv->name, nla_len(mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME])))
433                 {
434                         cv->id = nla_get_u32(mgrpinfo[CTRL_ATTR_MCAST_GRP_ID]);
435                         break;
436                 }
437         }
438
439         return NL_SKIP;
440 }
441
442 static int nl80211_subscribe(const char *family, const char *group)
443 {
444         struct nl80211_group_conveyor cv = { .name = group, .id = -ENOENT };
445         struct nl80211_msg_conveyor *req;
446
447         req = nl80211_ctl(CTRL_CMD_GETFAMILY, 0);
448         if (req)
449         {
450                 NLA_PUT_STRING(req->msg, CTRL_ATTR_FAMILY_NAME, family);
451                 nl80211_send(req, nl80211_subscribe_cb, &cv);
452
453 nla_put_failure:
454                 nl80211_free(req);
455         }
456
457         return nl_socket_add_membership(nls->nl_sock, cv.id);
458 }
459
460
461 static int nl80211_wait_cb(struct nl_msg *msg, void *arg)
462 {
463         struct nl80211_event_conveyor *cv = arg;
464         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
465
466         if (gnlh->cmd == cv->wait)
467                 cv->recv = gnlh->cmd;
468
469         return NL_SKIP;
470 }
471
472 static int nl80211_wait_seq_check(struct nl_msg *msg, void *arg)
473 {
474         return NL_OK;
475 }
476
477 static int nl80211_wait(const char *family, const char *group, int cmd)
478 {
479         struct nl80211_event_conveyor cv = { .wait = cmd };
480         struct nl_cb *cb;
481
482         if (nl80211_subscribe(family, group))
483                 return -ENOENT;
484
485         cb = nl_cb_alloc(NL_CB_DEFAULT);
486
487         if (!cb)
488                 return -ENOMEM;
489
490         nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nl80211_wait_seq_check, NULL);
491         nl_cb_set(cb, NL_CB_VALID,     NL_CB_CUSTOM, nl80211_wait_cb,        &cv );
492
493         while (!cv.recv)
494                 nl_recvmsgs(nls->nl_sock, cb);
495
496         nl_cb_put(cb);
497
498         return 0;
499 }
500
501
502 static int nl80211_freq2channel(int freq)
503 {
504         if (freq == 2484)
505                 return 14;
506         else if (freq < 2484)
507                 return (freq - 2407) / 5;
508         else if (freq >= 4910 && freq <= 4980)
509                 return (freq - 4000) / 5;
510         else
511                 return (freq - 5000) / 5;
512 }
513
514 static int nl80211_channel2freq(int channel, const char *band)
515 {
516         if (!band || band[0] != 'a')
517         {
518                 if (channel == 14)
519                         return 2484;
520                 else if (channel < 14)
521                         return (channel * 5) + 2407;
522         }
523         else
524         {
525                 if (channel >= 182 && channel <= 196)
526                         return (channel * 5) + 4000;
527                 else
528                         return (channel * 5) + 5000;
529         }
530
531         return 0;
532 }
533
534 static char * nl80211_getval(const char *ifname, const char *buf, const char *key)
535 {
536         int i, len;
537         char lkey[64] = { 0 };
538         const char *ln = buf;
539         static char lval[256] = { 0 };
540
541         int matched_if = ifname ? 0 : 1;
542
543
544         for( i = 0, len = strlen(buf); i < len; i++ )
545         {
546                 if (!lkey[0] && (buf[i] == ' ' || buf[i] == '\t'))
547                 {
548                         ln++;
549                 }
550                 else if (!lkey[0] && (buf[i] == '='))
551                 {
552                         if ((&buf[i] - ln) > 0)
553                                 memcpy(lkey, ln, min(sizeof(lkey) - 1, &buf[i] - ln));
554                 }
555                 else if (buf[i] == '\n')
556                 {
557                         if (lkey[0])
558                         {
559                                 memcpy(lval, ln + strlen(lkey) + 1,
560                                         min(sizeof(lval) - 1, &buf[i] - ln - strlen(lkey) - 1));
561
562                                 if ((ifname != NULL) &&
563                                     (!strcmp(lkey, "interface") || !strcmp(lkey, "bss")) )
564                                 {
565                                         matched_if = !strcmp(lval, ifname);
566                                 }
567                                 else if (matched_if && !strcmp(lkey, key))
568                                 {
569                                         return lval;
570                                 }
571                         }
572
573                         ln = &buf[i+1];
574                         memset(lkey, 0, sizeof(lkey));
575                         memset(lval, 0, sizeof(lval));
576                 }
577         }
578
579         return NULL;
580 }
581
582 static int nl80211_ifname2phy_cb(struct nl_msg *msg, void *arg)
583 {
584         char *buf = arg;
585         struct nlattr **attr = nl80211_parse(msg);
586
587         if (attr[NL80211_ATTR_WIPHY_NAME])
588                 memcpy(buf, nla_data(attr[NL80211_ATTR_WIPHY_NAME]),
589                        nla_len(attr[NL80211_ATTR_WIPHY_NAME]));
590         else
591                 buf[0] = 0;
592
593         return NL_SKIP;
594 }
595
596 static char * nl80211_ifname2phy(const char *ifname)
597 {
598         static char phy[32] = { 0 };
599         struct nl80211_msg_conveyor *req;
600
601         memset(phy, 0, sizeof(phy));
602
603         req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
604         if (req)
605         {
606                 nl80211_send(req, nl80211_ifname2phy_cb, phy);
607                 nl80211_free(req);
608         }
609
610         return phy[0] ? phy : NULL;
611 }
612
613 static char * nl80211_phy2ifname(const char *ifname)
614 {
615         int fd, ifidx = -1, cifidx = -1, phyidx = -1;
616         char buffer[64];
617         static char nif[IFNAMSIZ] = { 0 };
618
619         DIR *d;
620         struct dirent *e;
621
622         /* Only accept phy name of the form phy%d or radio%d */
623         if (!ifname)
624                 return NULL;
625         else if (!strncmp(ifname, "phy", 3))
626                 phyidx = atoi(&ifname[3]);
627         else if (!strncmp(ifname, "radio", 5))
628                 phyidx = nl80211_phy_idx_from_uci(ifname);
629         else
630                 return NULL;
631
632         memset(nif, 0, sizeof(nif));
633
634         if (phyidx > -1)
635         {
636                 if ((d = opendir("/sys/class/net")) != NULL)
637                 {
638                         while ((e = readdir(d)) != NULL)
639                         {
640                                 snprintf(buffer, sizeof(buffer),
641                                          "/sys/class/net/%s/phy80211/index", e->d_name);
642
643                                 if (nl80211_readint(buffer) == phyidx)
644                                 {
645                                         snprintf(buffer, sizeof(buffer),
646                                                  "/sys/class/net/%s/ifindex", e->d_name);
647
648                                         if ((cifidx = nl80211_readint(buffer)) >= 0 &&
649                                             ((ifidx < 0) || (cifidx < ifidx)))
650                                         {
651                                                 ifidx = cifidx;
652                                                 strncpy(nif, e->d_name, sizeof(nif));
653                                         }
654                                 }
655                         }
656
657                         closedir(d);
658                 }
659         }
660
661         return nif[0] ? nif : NULL;
662 }
663
664 static int nl80211_get_mode_cb(struct nl_msg *msg, void *arg)
665 {
666         int *mode = arg;
667         struct nlattr **tb = nl80211_parse(msg);
668         const int ifmodes[NL80211_IFTYPE_MAX + 1] = {
669                 IWINFO_OPMODE_UNKNOWN,          /* unspecified */
670                 IWINFO_OPMODE_ADHOC,            /* IBSS */
671                 IWINFO_OPMODE_CLIENT,           /* managed */
672                 IWINFO_OPMODE_MASTER,           /* AP */
673                 IWINFO_OPMODE_AP_VLAN,          /* AP/VLAN */
674                 IWINFO_OPMODE_WDS,                      /* WDS */
675                 IWINFO_OPMODE_MONITOR,          /* monitor */
676                 IWINFO_OPMODE_MESHPOINT,        /* mesh point */
677                 IWINFO_OPMODE_P2P_CLIENT,       /* P2P-client */
678                 IWINFO_OPMODE_P2P_GO,           /* P2P-GO */
679         };
680
681         if (tb[NL80211_ATTR_IFTYPE])
682                 *mode = ifmodes[nla_get_u32(tb[NL80211_ATTR_IFTYPE])];
683
684         return NL_SKIP;
685 }
686
687
688 static int nl80211_get_mode(const char *ifname, int *buf)
689 {
690         char *res;
691         struct nl80211_msg_conveyor *req;
692
693         res = nl80211_phy2ifname(ifname);
694         req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_INTERFACE, 0);
695         *buf = IWINFO_OPMODE_UNKNOWN;
696
697         if (req)
698         {
699                 nl80211_send(req, nl80211_get_mode_cb, buf);
700                 nl80211_free(req);
701         }
702
703         return (*buf == IWINFO_OPMODE_UNKNOWN) ? -1 : 0;
704 }
705
706 static char * nl80211_hostapd_info(const char *ifname)
707 {
708         int mode;
709         char *phy;
710         char path[32] = { 0 };
711         static char buf[4096] = { 0 };
712         FILE *conf;
713
714         if (nl80211_get_mode(ifname, &mode))
715                 return NULL;
716
717         if ((mode == IWINFO_OPMODE_MASTER || mode == IWINFO_OPMODE_AP_VLAN) &&
718             (phy = nl80211_ifname2phy(ifname)) != NULL)
719         {
720                 snprintf(path, sizeof(path), "/var/run/hostapd-%s.conf", phy);
721
722                 if ((conf = fopen(path, "r")) != NULL)
723                 {
724                         fread(buf, sizeof(buf) - 1, 1, conf);
725                         fclose(conf);
726
727                         return buf;
728                 }
729         }
730
731         return NULL;
732 }
733
734 static inline int nl80211_wpactl_recv(int sock, char *buf, int blen)
735 {
736         fd_set rfds;
737         struct timeval tv = { 2, 0 };
738
739         FD_ZERO(&rfds);
740         FD_SET(sock, &rfds);
741
742         memset(buf, 0, blen);
743
744
745         if (select(sock + 1, &rfds, NULL, NULL, &tv) < 0)
746                 return -1;
747
748         if (!FD_ISSET(sock, &rfds))
749                 return -1;
750
751         return recv(sock, buf, blen, 0);
752 }
753
754 static char * nl80211_wpactl_info(const char *ifname, const char *cmd,
755                                                                    const char *event)
756 {
757         int numtry = 0;
758         int sock = -1;
759         char *rv = NULL;
760         size_t remote_length, local_length;
761         static char buffer[10240] = { 0 };
762
763         struct sockaddr_un local = { 0 };
764         struct sockaddr_un remote = { 0 };
765
766
767         sock = socket(PF_UNIX, SOCK_DGRAM, 0);
768         if (sock < 0)
769                 return NULL;
770
771         remote.sun_family = AF_UNIX;
772         remote_length = sizeof(remote.sun_family) + sprintf(remote.sun_path,
773                 "/var/run/wpa_supplicant-%s/%s", ifname, ifname);
774
775         if (fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC) < 0)
776                 goto out;
777
778         if (connect(sock, (struct sockaddr *) &remote, remote_length))
779         {
780                 remote_length = sizeof(remote.sun_family) + sprintf(remote.sun_path,
781                         "/var/run/wpa_supplicant/%s", ifname);
782
783                 if (connect(sock, (struct sockaddr *) &remote, remote_length))
784                         goto out;
785         }
786
787         local.sun_family = AF_UNIX;
788         local_length = sizeof(local.sun_family) +
789                 sprintf(local.sun_path, "/var/run/iwinfo-%s-%d", ifname, getpid());
790
791         if (bind(sock, (struct sockaddr *) &local, local_length))
792                 goto out;
793
794
795         if (event)
796         {
797                 send(sock, "ATTACH", 6, 0);
798
799                 if (nl80211_wpactl_recv(sock, buffer, sizeof(buffer)-1) <= 0)
800                         goto out;
801         }
802
803
804         send(sock, cmd, strlen(cmd), 0);
805
806         /* we might have to scan up to 72 channels / 256ms per channel */
807         /* this makes up to 18.5s hence 10 tries */
808         while( numtry++ < 10 )
809         {
810                 char *bracket;
811
812                 /* make sure there is a terminating nul byte */
813                 if (nl80211_wpactl_recv(sock, buffer, sizeof(buffer)-1) <= 0)
814                 {
815                         if (event)
816                                 continue;
817
818                         break;
819                 }
820
821                 if ((!event && buffer[0] != '<') || (event && strstr(buffer, event)))
822                         break;
823
824                 /* there may be more than max(numtry) BSS-ADDED events */
825                 /* ignore them similar to wpa_cli */
826                 if (buffer[0] == '<' &&
827                                 (bracket=strchr(buffer,'>')) != NULL &&
828                                 strncmp(bracket+1,"CTRL-EVENT-BSS-ADDED",20) == 0)
829                         numtry--;
830         }
831
832         rv = buffer;
833
834 out:
835         close(sock);
836
837         if (local.sun_family)
838                 unlink(local.sun_path);
839
840         return rv;
841 }
842
843 static char * nl80211_ifadd(const char *ifname)
844 {
845         int phyidx;
846         char *rv = NULL, path[PATH_MAX];
847         static char nif[IFNAMSIZ] = { 0 };
848         struct nl80211_msg_conveyor *req, *res;
849         FILE *sysfs;
850
851         req = nl80211_msg(ifname, NL80211_CMD_NEW_INTERFACE, 0);
852         if (req)
853         {
854                 snprintf(nif, sizeof(nif), "tmp.%s", ifname);
855
856                 NLA_PUT_STRING(req->msg, NL80211_ATTR_IFNAME, nif);
857                 NLA_PUT_U32(req->msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_STATION);
858
859                 nl80211_send(req, NULL, NULL);
860
861                 snprintf(path, sizeof(path) - 1,
862                          "/proc/sys/net/ipv6/conf/%s/disable_ipv6", nif);
863
864                 if ((sysfs = fopen(path, "w")) != NULL)
865                 {
866                         fwrite("0\n", 1, 2, sysfs);
867                         fclose(sysfs);
868                 }
869
870                 rv = nif;
871
872         nla_put_failure:
873                 nl80211_free(req);
874         }
875
876         return rv;
877 }
878
879 static void nl80211_ifdel(const char *ifname)
880 {
881         struct nl80211_msg_conveyor *req;
882
883         req = nl80211_msg(ifname, NL80211_CMD_DEL_INTERFACE, 0);
884         if (req)
885         {
886                 NLA_PUT_STRING(req->msg, NL80211_ATTR_IFNAME, ifname);
887
888                 nl80211_send(req, NULL, NULL);
889
890         nla_put_failure:
891                 nl80211_free(req);
892         }
893 }
894
895 static void nl80211_hostapd_hup(const char *ifname)
896 {
897         int fd, pid = 0;
898         char buf[32];
899         char *phy = nl80211_ifname2phy(ifname);
900
901         if (phy)
902         {
903                 snprintf(buf, sizeof(buf), "/var/run/wifi-%s.pid", phy);
904                 if ((fd = open(buf, O_RDONLY)) > 0)
905                 {
906                         if (read(fd, buf, sizeof(buf)) > 0)
907                                 pid = atoi(buf);
908
909                         close(fd);
910                 }
911
912                 if (pid > 0)
913                         kill(pid, 1);
914         }
915 }
916
917
918 static int nl80211_probe(const char *ifname)
919 {
920         return !!nl80211_ifname2phy(ifname);
921 }
922
923 struct nl80211_ssid_bssid {
924         unsigned char *ssid;
925         unsigned char bssid[7];
926 };
927
928 static int nl80211_get_ssid_bssid_cb(struct nl_msg *msg, void *arg)
929 {
930         int ielen;
931         unsigned char *ie;
932         struct nl80211_ssid_bssid *sb = arg;
933         struct nlattr **tb = nl80211_parse(msg);
934         struct nlattr *bss[NL80211_BSS_MAX + 1];
935
936         static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
937                 [NL80211_BSS_INFORMATION_ELEMENTS] = {                 },
938                 [NL80211_BSS_STATUS]               = { .type = NLA_U32 },
939         };
940
941         if (!tb[NL80211_ATTR_BSS] ||
942             nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
943                              bss_policy) ||
944             !bss[NL80211_BSS_BSSID] ||
945             !bss[NL80211_BSS_STATUS] ||
946             !bss[NL80211_BSS_INFORMATION_ELEMENTS])
947         {
948                 return NL_SKIP;
949         }
950
951         switch (nla_get_u32(bss[NL80211_BSS_STATUS]))
952         {
953         case NL80211_BSS_STATUS_ASSOCIATED:
954         case NL80211_BSS_STATUS_AUTHENTICATED:
955         case NL80211_BSS_STATUS_IBSS_JOINED:
956
957                 if (sb->ssid)
958                 {
959                         ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
960                         ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
961
962                         while (ielen >= 2 && ielen >= ie[1])
963                         {
964                                 if (ie[0] == 0)
965                                 {
966                                         memcpy(sb->ssid, ie + 2, min(ie[1], IWINFO_ESSID_MAX_SIZE));
967                                         return NL_SKIP;
968                                 }
969
970                                 ielen -= ie[1] + 2;
971                                 ie += ie[1] + 2;
972                         }
973                 }
974                 else
975                 {
976                         sb->bssid[0] = 1;
977                         memcpy(sb->bssid + 1, nla_data(bss[NL80211_BSS_BSSID]), 6);
978                         return NL_SKIP;
979                 }
980
981         default:
982                 return NL_SKIP;
983         }
984 }
985
986 static int nl80211_get_ssid(const char *ifname, char *buf)
987 {
988         char *res;
989         struct nl80211_msg_conveyor *req;
990         struct nl80211_ssid_bssid sb;
991
992         /* try to find ssid from scan dump results */
993         res = nl80211_phy2ifname(ifname);
994         req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
995
996         sb.ssid = buf;
997         *buf = 0;
998
999         if (req)
1000         {
1001                 nl80211_send(req, nl80211_get_ssid_bssid_cb, &sb);
1002                 nl80211_free(req);
1003         }
1004
1005         /* failed, try to find from hostapd info */
1006         if ((*buf == 0) &&
1007             (res = nl80211_hostapd_info(ifname)) &&
1008             (res = nl80211_getval(ifname, res, "ssid")))
1009         {
1010                 memcpy(buf, res, strlen(res));
1011         }
1012
1013         return (*buf == 0) ? -1 : 0;
1014 }
1015
1016 static int nl80211_get_bssid(const char *ifname, char *buf)
1017 {
1018         char *res;
1019         struct nl80211_msg_conveyor *req;
1020         struct nl80211_ssid_bssid sb;
1021
1022         /* try to find bssid from scan dump results */
1023         res = nl80211_phy2ifname(ifname);
1024         req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
1025
1026         sb.ssid = NULL;
1027         sb.bssid[0] = 0;
1028
1029         if (req)
1030         {
1031                 nl80211_send(req, nl80211_get_ssid_bssid_cb, &sb);
1032                 nl80211_free(req);
1033         }
1034
1035         /* failed, try to find mac from hostapd info */
1036         if ((sb.bssid[0] == 0) &&
1037             (res = nl80211_hostapd_info(ifname)) &&
1038             (res = nl80211_getval(ifname, res, "bssid")))
1039         {
1040                 sb.bssid[0] = 1;
1041                 sb.bssid[1] = strtol(&res[0],  NULL, 16);
1042                 sb.bssid[2] = strtol(&res[3],  NULL, 16);
1043                 sb.bssid[3] = strtol(&res[6],  NULL, 16);
1044                 sb.bssid[4] = strtol(&res[9],  NULL, 16);
1045                 sb.bssid[5] = strtol(&res[12], NULL, 16);
1046                 sb.bssid[6] = strtol(&res[15], NULL, 16);
1047         }
1048
1049         if (sb.bssid[0])
1050         {
1051                 sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
1052                         sb.bssid[1], sb.bssid[2], sb.bssid[3],
1053                         sb.bssid[4], sb.bssid[5], sb.bssid[6]);
1054
1055                 return 0;
1056         }
1057
1058         return -1;
1059 }
1060
1061
1062 static int nl80211_get_frequency_scan_cb(struct nl_msg *msg, void *arg)
1063 {
1064         int *freq = arg;
1065         struct nlattr **attr = nl80211_parse(msg);
1066         struct nlattr *binfo[NL80211_BSS_MAX + 1];
1067
1068         static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
1069                 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
1070                 [NL80211_BSS_STATUS]    = { .type = NLA_U32 },
1071         };
1072
1073         if (attr[NL80211_ATTR_BSS] &&
1074             !nla_parse_nested(binfo, NL80211_BSS_MAX,
1075                               attr[NL80211_ATTR_BSS], bss_policy))
1076         {
1077                 if (binfo[NL80211_BSS_STATUS] && binfo[NL80211_BSS_FREQUENCY])
1078                         *freq = nla_get_u32(binfo[NL80211_BSS_FREQUENCY]);
1079         }
1080
1081         return NL_SKIP;
1082 }
1083
1084 static int nl80211_get_frequency_info_cb(struct nl_msg *msg, void *arg)
1085 {
1086         int *freq = arg;
1087         struct nlattr **tb = nl80211_parse(msg);
1088
1089         if (tb[NL80211_ATTR_WIPHY_FREQ])
1090                 *freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
1091
1092         return NL_SKIP;
1093 }
1094
1095 static int nl80211_get_frequency(const char *ifname, int *buf)
1096 {
1097         int chn;
1098         char *res, *channel;
1099         struct nl80211_msg_conveyor *req;
1100
1101         /* try to find frequency from interface info */
1102         res = nl80211_phy2ifname(ifname);
1103         req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_INTERFACE, 0);
1104         *buf = 0;
1105
1106         if (req)
1107         {
1108                 nl80211_send(req, nl80211_get_frequency_info_cb, buf);
1109                 nl80211_free(req);
1110         }
1111
1112         /* failed, try to find frequency from hostapd info */
1113         if ((*buf == 0) &&
1114             (res = nl80211_hostapd_info(ifname)) &&
1115             (channel = nl80211_getval(NULL, res, "channel")))
1116         {
1117                 chn = atoi(channel);
1118                 *buf = nl80211_channel2freq(chn, nl80211_getval(NULL, res, "hw_mode"));
1119         }
1120         else
1121         {
1122                 /* failed, try to find frequency from scan results */
1123                 if (*buf == 0)
1124                 {
1125                         res = nl80211_phy2ifname(ifname);
1126                         req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_SCAN,
1127                                           NLM_F_DUMP);
1128
1129                         if (req)
1130                         {
1131                                 nl80211_send(req, nl80211_get_frequency_scan_cb, buf);
1132                                 nl80211_free(req);
1133                         }
1134                 }
1135         }
1136
1137         return (*buf == 0) ? -1 : 0;
1138 }
1139
1140 static int nl80211_get_channel(const char *ifname, int *buf)
1141 {
1142         if (!nl80211_get_frequency(ifname, buf))
1143         {
1144                 *buf = nl80211_freq2channel(*buf);
1145                 return 0;
1146         }
1147
1148         return -1;
1149 }
1150
1151
1152 static int nl80211_get_txpower(const char *ifname, int *buf)
1153 {
1154 #if 0
1155         char *res;
1156         char path[PATH_MAX];
1157
1158         res = nl80211_ifname2phy(ifname);
1159         snprintf(path, sizeof(path), "/sys/kernel/debug/ieee80211/%s/power",
1160                  res ? res : ifname);
1161
1162         if ((*buf = nl80211_readint(path)) > -1)
1163                 return 0;
1164 #endif
1165
1166         return wext_ops.txpower(ifname, buf);
1167 }
1168
1169
1170 static int nl80211_fill_signal_cb(struct nl_msg *msg, void *arg)
1171 {
1172         int8_t dbm;
1173         int16_t mbit;
1174         struct nl80211_rssi_rate *rr = arg;
1175         struct nlattr **attr = nl80211_parse(msg);
1176         struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
1177         struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
1178
1179         static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
1180                 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32    },
1181                 [NL80211_STA_INFO_RX_BYTES]      = { .type = NLA_U32    },
1182                 [NL80211_STA_INFO_TX_BYTES]      = { .type = NLA_U32    },
1183                 [NL80211_STA_INFO_RX_PACKETS]    = { .type = NLA_U32    },
1184                 [NL80211_STA_INFO_TX_PACKETS]    = { .type = NLA_U32    },
1185                 [NL80211_STA_INFO_SIGNAL]        = { .type = NLA_U8     },
1186                 [NL80211_STA_INFO_TX_BITRATE]    = { .type = NLA_NESTED },
1187                 [NL80211_STA_INFO_LLID]          = { .type = NLA_U16    },
1188                 [NL80211_STA_INFO_PLID]          = { .type = NLA_U16    },
1189                 [NL80211_STA_INFO_PLINK_STATE]   = { .type = NLA_U8     },
1190         };
1191
1192         static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
1193                 [NL80211_RATE_INFO_BITRATE]      = { .type = NLA_U16  },
1194                 [NL80211_RATE_INFO_MCS]          = { .type = NLA_U8   },
1195                 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
1196                 [NL80211_RATE_INFO_SHORT_GI]     = { .type = NLA_FLAG },
1197         };
1198
1199         if (attr[NL80211_ATTR_STA_INFO])
1200         {
1201                 if (!nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
1202                                       attr[NL80211_ATTR_STA_INFO], stats_policy))
1203                 {
1204                         if (sinfo[NL80211_STA_INFO_SIGNAL])
1205                         {
1206                                 dbm = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
1207                                 rr->rssi = rr->rssi ? (int8_t)((rr->rssi + dbm) / 2) : dbm;
1208                         }
1209
1210                         if (sinfo[NL80211_STA_INFO_TX_BITRATE])
1211                         {
1212                                 if (!nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
1213                                                       sinfo[NL80211_STA_INFO_TX_BITRATE],
1214                                                       rate_policy))
1215                                 {
1216                                         if (rinfo[NL80211_RATE_INFO_BITRATE])
1217                                         {
1218                                                 mbit = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
1219                                                 rr->rate = rr->rate
1220                                                         ? (int16_t)((rr->rate + mbit) / 2) : mbit;
1221                                         }
1222                                 }
1223                         }
1224                 }
1225         }
1226
1227         return NL_SKIP;
1228 }
1229
1230 static void nl80211_fill_signal(const char *ifname, struct nl80211_rssi_rate *r)
1231 {
1232         DIR *d;
1233         struct dirent *de;
1234         struct nl80211_msg_conveyor *req;
1235
1236         r->rssi = 0;
1237         r->rate = 0;
1238
1239         if ((d = opendir("/sys/class/net")) != NULL)
1240         {
1241                 while ((de = readdir(d)) != NULL)
1242                 {
1243                         if (!strncmp(de->d_name, ifname, strlen(ifname)) &&
1244                             (!de->d_name[strlen(ifname)] ||
1245                              !strncmp(&de->d_name[strlen(ifname)], ".sta", 4)))
1246                         {
1247                                 req = nl80211_msg(de->d_name, NL80211_CMD_GET_STATION,
1248                                                   NLM_F_DUMP);
1249
1250                                 if (req)
1251                                 {
1252                                         nl80211_send(req, nl80211_fill_signal_cb, r);
1253                                         nl80211_free(req);
1254                                 }
1255                         }
1256                 }
1257
1258                 closedir(d);
1259         }
1260 }
1261
1262 static int nl80211_get_bitrate(const char *ifname, int *buf)
1263 {
1264         struct nl80211_rssi_rate rr;
1265
1266         nl80211_fill_signal(ifname, &rr);
1267
1268         if (rr.rate)
1269         {
1270                 *buf = (rr.rate * 100);
1271                 return 0;
1272         }
1273
1274         return -1;
1275 }
1276
1277 static int nl80211_get_signal(const char *ifname, int *buf)
1278 {
1279         struct nl80211_rssi_rate rr;
1280
1281         nl80211_fill_signal(ifname, &rr);
1282
1283         if (rr.rssi)
1284         {
1285                 *buf = rr.rssi;
1286                 return 0;
1287         }
1288
1289         return -1;
1290 }
1291
1292 static int nl80211_get_noise_cb(struct nl_msg *msg, void *arg)
1293 {
1294         int8_t *noise = arg;
1295         struct nlattr **tb = nl80211_parse(msg);
1296         struct nlattr *si[NL80211_SURVEY_INFO_MAX + 1];
1297
1298         static struct nla_policy sp[NL80211_SURVEY_INFO_MAX + 1] = {
1299                 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
1300                 [NL80211_SURVEY_INFO_NOISE]     = { .type = NLA_U8  },
1301         };
1302
1303         if (!tb[NL80211_ATTR_SURVEY_INFO])
1304                 return NL_SKIP;
1305
1306         if (nla_parse_nested(si, NL80211_SURVEY_INFO_MAX,
1307                              tb[NL80211_ATTR_SURVEY_INFO], sp))
1308                 return NL_SKIP;
1309
1310         if (!si[NL80211_SURVEY_INFO_NOISE])
1311                 return NL_SKIP;
1312
1313         if (!*noise || si[NL80211_SURVEY_INFO_IN_USE])
1314                 *noise = (int8_t)nla_get_u8(si[NL80211_SURVEY_INFO_NOISE]);
1315
1316         return NL_SKIP;
1317 }
1318
1319
1320 static int nl80211_get_noise(const char *ifname, int *buf)
1321 {
1322         int8_t noise;
1323         struct nl80211_msg_conveyor *req;
1324
1325         req = nl80211_msg(ifname, NL80211_CMD_GET_SURVEY, NLM_F_DUMP);
1326         if (req)
1327         {
1328                 noise = 0;
1329
1330                 nl80211_send(req, nl80211_get_noise_cb, &noise);
1331                 nl80211_free(req);
1332
1333                 if (noise)
1334                 {
1335                         *buf = noise;
1336                         return 0;
1337                 }
1338         }
1339
1340         return -1;
1341 }
1342
1343 static int nl80211_get_quality(const char *ifname, int *buf)
1344 {
1345         int signal;
1346
1347         if (!nl80211_get_signal(ifname, &signal))
1348         {
1349                 /* A positive signal level is usually just a quality
1350                  * value, pass through as-is */
1351                 if (signal >= 0)
1352                 {
1353                         *buf = signal;
1354                 }
1355
1356                 /* The cfg80211 wext compat layer assumes a signal range
1357                  * of -110 dBm to -40 dBm, the quality value is derived
1358                  * by adding 110 to the signal level */
1359                 else
1360                 {
1361                         if (signal < -110)
1362                                 signal = -110;
1363                         else if (signal > -40)
1364                                 signal = -40;
1365
1366                         *buf = (signal + 110);
1367                 }
1368
1369                 return 0;
1370         }
1371
1372         return -1;
1373 }
1374
1375 static int nl80211_get_quality_max(const char *ifname, int *buf)
1376 {
1377         /* The cfg80211 wext compat layer assumes a maximum
1378          * quality of 70 */
1379         *buf = 70;
1380
1381         return 0;
1382 }
1383
1384 static int nl80211_get_encryption(const char *ifname, char *buf)
1385 {
1386         int i;
1387         char k[9];
1388         char *val, *res;
1389         struct iwinfo_crypto_entry *c = (struct iwinfo_crypto_entry *)buf;
1390
1391         /* WPA supplicant */
1392         if ((res = nl80211_wpactl_info(ifname, "STATUS", NULL)) &&
1393             (val = nl80211_getval(NULL, res, "pairwise_cipher")))
1394         {
1395                 /* WEP */
1396                 if (strstr(val, "WEP"))
1397                 {
1398                         if (strstr(val, "WEP-40"))
1399                                 c->pair_ciphers |= IWINFO_CIPHER_WEP40;
1400
1401                         else if (strstr(val, "WEP-104"))
1402                                 c->pair_ciphers |= IWINFO_CIPHER_WEP104;
1403
1404                         c->enabled       = 1;
1405                         c->group_ciphers = c->pair_ciphers;
1406
1407                         c->auth_suites |= IWINFO_KMGMT_NONE;
1408                         c->auth_algs   |= IWINFO_AUTH_OPEN; /* XXX: assumption */
1409                 }
1410
1411                 /* WPA */
1412                 else
1413                 {
1414                         if (strstr(val, "TKIP"))
1415                                 c->pair_ciphers |= IWINFO_CIPHER_TKIP;
1416
1417                         else if (strstr(val, "CCMP"))
1418                                 c->pair_ciphers |= IWINFO_CIPHER_CCMP;
1419
1420                         else if (strstr(val, "NONE"))
1421                                 c->pair_ciphers |= IWINFO_CIPHER_NONE;
1422
1423                         else if (strstr(val, "WEP-40"))
1424                                 c->pair_ciphers |= IWINFO_CIPHER_WEP40;
1425
1426                         else if (strstr(val, "WEP-104"))
1427                                 c->pair_ciphers |= IWINFO_CIPHER_WEP104;
1428
1429
1430                         if ((val = nl80211_getval(NULL, res, "group_cipher")))
1431                         {
1432                                 if (strstr(val, "TKIP"))
1433                                         c->group_ciphers |= IWINFO_CIPHER_TKIP;
1434
1435                                 else if (strstr(val, "CCMP"))
1436                                         c->group_ciphers |= IWINFO_CIPHER_CCMP;
1437
1438                                 else if (strstr(val, "NONE"))
1439                                         c->group_ciphers |= IWINFO_CIPHER_NONE;
1440
1441                                 else if (strstr(val, "WEP-40"))
1442                                         c->group_ciphers |= IWINFO_CIPHER_WEP40;
1443
1444                                 else if (strstr(val, "WEP-104"))
1445                                         c->group_ciphers |= IWINFO_CIPHER_WEP104;
1446                         }
1447
1448
1449                         if ((val = nl80211_getval(NULL, res, "key_mgmt")))
1450                         {
1451                                 if (strstr(val, "WPA2"))
1452                                         c->wpa_version = 2;
1453
1454                                 else if (strstr(val, "WPA"))
1455                                         c->wpa_version = 1;
1456
1457
1458                                 if (strstr(val, "PSK"))
1459                                         c->auth_suites |= IWINFO_KMGMT_PSK;
1460
1461                                 else if (strstr(val, "EAP") || strstr(val, "802.1X"))
1462                                         c->auth_suites |= IWINFO_KMGMT_8021x;
1463
1464                                 else if (strstr(val, "NONE"))
1465                                         c->auth_suites |= IWINFO_KMGMT_NONE;
1466                         }
1467
1468                         c->enabled = (c->wpa_version && c->auth_suites) ? 1 : 0;
1469                 }
1470
1471                 return 0;
1472         }
1473
1474         /* Hostapd */
1475         else if ((res = nl80211_hostapd_info(ifname)))
1476         {
1477                 if ((val = nl80211_getval(ifname, res, "wpa")) != NULL)
1478                         c->wpa_version = atoi(val);
1479
1480                 val = nl80211_getval(ifname, res, "wpa_key_mgmt");
1481
1482                 if (!val || strstr(val, "PSK"))
1483                         c->auth_suites |= IWINFO_KMGMT_PSK;
1484
1485                 if (val && strstr(val, "EAP"))
1486                         c->auth_suites |= IWINFO_KMGMT_8021x;
1487
1488                 if (val && strstr(val, "NONE"))
1489                         c->auth_suites |= IWINFO_KMGMT_NONE;
1490
1491                 if ((val = nl80211_getval(ifname, res, "wpa_pairwise")) != NULL)
1492                 {
1493                         if (strstr(val, "TKIP"))
1494                                 c->pair_ciphers |= IWINFO_CIPHER_TKIP;
1495
1496                         if (strstr(val, "CCMP"))
1497                                 c->pair_ciphers |= IWINFO_CIPHER_CCMP;
1498
1499                         if (strstr(val, "NONE"))
1500                                 c->pair_ciphers |= IWINFO_CIPHER_NONE;
1501                 }
1502
1503                 if ((val = nl80211_getval(ifname, res, "auth_algs")) != NULL)
1504                 {
1505                         switch(atoi(val)) {
1506                                 case 1:
1507                                         c->auth_algs |= IWINFO_AUTH_OPEN;
1508                                         break;
1509
1510                                 case 2:
1511                                         c->auth_algs |= IWINFO_AUTH_SHARED;
1512                                         break;
1513
1514                                 case 3:
1515                                         c->auth_algs |= IWINFO_AUTH_OPEN;
1516                                         c->auth_algs |= IWINFO_AUTH_SHARED;
1517                                         break;
1518
1519                                 default:
1520                                         break;
1521                         }
1522
1523                         for (i = 0; i < 4; i++)
1524                         {
1525                                 snprintf(k, sizeof(k), "wep_key%d", i);
1526
1527                                 if ((val = nl80211_getval(ifname, res, k)))
1528                                 {
1529                                         if ((strlen(val) == 5) || (strlen(val) == 10))
1530                                                 c->pair_ciphers |= IWINFO_CIPHER_WEP40;
1531
1532                                         else if ((strlen(val) == 13) || (strlen(val) == 26))
1533                                                 c->pair_ciphers |= IWINFO_CIPHER_WEP104;
1534                                 }
1535                         }
1536                 }
1537
1538                 c->group_ciphers = c->pair_ciphers;
1539                 c->enabled = (c->wpa_version || c->pair_ciphers) ? 1 : 0;
1540
1541                 return 0;
1542         }
1543
1544         return -1;
1545 }
1546
1547 static int nl80211_get_phyname(const char *ifname, char *buf)
1548 {
1549         const char *name;
1550
1551         name = nl80211_ifname2phy(ifname);
1552
1553         if (name)
1554         {
1555                 strcpy(buf, name);
1556                 return 0;
1557         }
1558         else if ((name = nl80211_phy2ifname(ifname)) != NULL)
1559         {
1560                 name = nl80211_ifname2phy(name);
1561
1562                 if (name)
1563                 {
1564                         strcpy(buf, ifname);
1565                         return 0;
1566                 }
1567         }
1568
1569         return -1;
1570 }
1571
1572
1573 static int nl80211_get_assoclist_cb(struct nl_msg *msg, void *arg)
1574 {
1575         struct nl80211_array_buf *arr = arg;
1576         struct iwinfo_assoclist_entry *e = arr->buf;
1577         struct nlattr **attr = nl80211_parse(msg);
1578         struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
1579         struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
1580
1581         static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
1582                 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32    },
1583                 [NL80211_STA_INFO_RX_PACKETS]    = { .type = NLA_U32    },
1584                 [NL80211_STA_INFO_TX_PACKETS]    = { .type = NLA_U32    },
1585                 [NL80211_STA_INFO_RX_BITRATE]    = { .type = NLA_NESTED },
1586                 [NL80211_STA_INFO_TX_BITRATE]    = { .type = NLA_NESTED },
1587                 [NL80211_STA_INFO_SIGNAL]        = { .type = NLA_U8     },
1588         };
1589
1590         static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
1591                 [NL80211_RATE_INFO_BITRATE]      = { .type = NLA_U16    },
1592                 [NL80211_RATE_INFO_MCS]          = { .type = NLA_U8     },
1593                 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG   },
1594                 [NL80211_RATE_INFO_SHORT_GI]     = { .type = NLA_FLAG   },
1595         };
1596
1597         /* advance to end of array */
1598         e += arr->count;
1599         memset(e, 0, sizeof(*e));
1600
1601         if (attr[NL80211_ATTR_MAC])
1602                 memcpy(e->mac, nla_data(attr[NL80211_ATTR_MAC]), 6);
1603
1604         if (attr[NL80211_ATTR_STA_INFO] &&
1605             !nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
1606                               attr[NL80211_ATTR_STA_INFO], stats_policy))
1607         {
1608                 if (sinfo[NL80211_STA_INFO_SIGNAL])
1609                         e->signal = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
1610
1611                 if (sinfo[NL80211_STA_INFO_INACTIVE_TIME])
1612                         e->inactive = nla_get_u32(sinfo[NL80211_STA_INFO_INACTIVE_TIME]);
1613
1614                 if (sinfo[NL80211_STA_INFO_RX_PACKETS])
1615                         e->rx_packets = nla_get_u32(sinfo[NL80211_STA_INFO_RX_PACKETS]);
1616
1617                 if (sinfo[NL80211_STA_INFO_TX_PACKETS])
1618                         e->tx_packets = nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]);
1619
1620                 if (sinfo[NL80211_STA_INFO_RX_BITRATE] &&
1621                     !nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
1622                                       sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy))
1623                 {
1624                         if (rinfo[NL80211_RATE_INFO_BITRATE])
1625                                 e->rx_rate.rate =
1626                                         nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100;
1627
1628                         if (rinfo[NL80211_RATE_INFO_MCS])
1629                                 e->rx_rate.mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
1630
1631                         if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
1632                                 e->rx_rate.is_40mhz = 1;
1633
1634                         if (rinfo[NL80211_RATE_INFO_SHORT_GI])
1635                                 e->rx_rate.is_short_gi = 1;
1636                 }
1637
1638                 if (sinfo[NL80211_STA_INFO_TX_BITRATE] &&
1639                     !nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
1640                                       sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy))
1641                 {
1642                         if (rinfo[NL80211_RATE_INFO_BITRATE])
1643                                 e->tx_rate.rate =
1644                                         nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100;
1645
1646                         if (rinfo[NL80211_RATE_INFO_MCS])
1647                                 e->tx_rate.mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
1648
1649                         if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
1650                                 e->tx_rate.is_40mhz = 1;
1651
1652                         if (rinfo[NL80211_RATE_INFO_SHORT_GI])
1653                                 e->tx_rate.is_short_gi = 1;
1654                 }
1655         }
1656
1657         e->noise = 0; /* filled in by caller */
1658         arr->count++;
1659
1660         return NL_SKIP;
1661 }
1662
1663 static int nl80211_get_assoclist(const char *ifname, char *buf, int *len)
1664 {
1665         DIR *d;
1666         int i, noise = 0;
1667         struct dirent *de;
1668         struct nl80211_msg_conveyor *req;
1669         struct nl80211_array_buf arr = { .buf = buf, .count = 0 };
1670         struct iwinfo_assoclist_entry *e;
1671
1672         if ((d = opendir("/sys/class/net")) != NULL)
1673         {
1674                 while ((de = readdir(d)) != NULL)
1675                 {
1676                         if (!strncmp(de->d_name, ifname, strlen(ifname)) &&
1677                             (!de->d_name[strlen(ifname)] ||
1678                              !strncmp(&de->d_name[strlen(ifname)], ".sta", 4)))
1679                         {
1680                                 req = nl80211_msg(de->d_name, NL80211_CMD_GET_STATION,
1681                                                   NLM_F_DUMP);
1682
1683                                 if (req)
1684                                 {
1685                                         nl80211_send(req, nl80211_get_assoclist_cb, &arr);
1686                                         nl80211_free(req);
1687                                 }
1688                         }
1689                 }
1690
1691                 closedir(d);
1692
1693                 if (!nl80211_get_noise(ifname, &noise))
1694                         for (i = 0, e = arr.buf; i < arr.count; i++, e++)
1695                                 e->noise = noise;
1696
1697                 *len = (arr.count * sizeof(struct iwinfo_assoclist_entry));
1698                 return 0;
1699         }
1700
1701         return -1;
1702 }
1703
1704 static int nl80211_get_txpwrlist_cb(struct nl_msg *msg, void *arg)
1705 {
1706         int *dbm_max = arg;
1707         int ch_cur, ch_cmp, bands_remain, freqs_remain;
1708
1709         struct nlattr **attr = nl80211_parse(msg);
1710         struct nlattr *bands[NL80211_BAND_ATTR_MAX + 1];
1711         struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
1712         struct nlattr *band, *freq;
1713
1714         static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
1715                 [NL80211_FREQUENCY_ATTR_FREQ]         = { .type = NLA_U32  },
1716                 [NL80211_FREQUENCY_ATTR_DISABLED]     = { .type = NLA_FLAG },
1717                 [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
1718                 [NL80211_FREQUENCY_ATTR_NO_IBSS]      = { .type = NLA_FLAG },
1719                 [NL80211_FREQUENCY_ATTR_RADAR]        = { .type = NLA_FLAG },
1720                 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32  },
1721         };
1722
1723         ch_cur = *dbm_max; /* value int* is initialized with channel by caller */
1724         *dbm_max = -1;
1725
1726         nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain)
1727         {
1728                 nla_parse(bands, NL80211_BAND_ATTR_MAX, nla_data(band),
1729                           nla_len(band), NULL);
1730
1731                 nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS], freqs_remain)
1732                 {
1733                         nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX,
1734                                   nla_data(freq), nla_len(freq), freq_policy);
1735
1736                         ch_cmp = nl80211_freq2channel(nla_get_u32(
1737                                 freqs[NL80211_FREQUENCY_ATTR_FREQ]));
1738
1739                         if ((!ch_cur || (ch_cmp == ch_cur)) &&
1740                             freqs[NL80211_FREQUENCY_ATTR_MAX_TX_POWER])
1741                         {
1742                                 *dbm_max = (int)(0.01 * nla_get_u32(
1743                                         freqs[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]));
1744
1745                                 break;
1746                         }
1747                 }
1748         }
1749
1750         return NL_SKIP;
1751 }
1752
1753 static int nl80211_get_txpwrlist(const char *ifname, char *buf, int *len)
1754 {
1755         int ch_cur;
1756         int dbm_max = -1, dbm_cur, dbm_cnt;
1757         struct nl80211_msg_conveyor *req;
1758         struct iwinfo_txpwrlist_entry entry;
1759
1760         if (nl80211_get_channel(ifname, &ch_cur))
1761                 ch_cur = 0;
1762
1763         req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
1764         if (req)
1765         {
1766                 /* initialize the value pointer with channel for callback */
1767                 dbm_max = ch_cur;
1768
1769                 nl80211_send(req, nl80211_get_txpwrlist_cb, &dbm_max);
1770                 nl80211_free(req);
1771         }
1772
1773         if (dbm_max > 0)
1774         {
1775                 for (dbm_cur = 0, dbm_cnt = 0;
1776                      dbm_cur < dbm_max;
1777                      dbm_cur++, dbm_cnt++)
1778                 {
1779                         entry.dbm = dbm_cur;
1780                         entry.mw  = iwinfo_dbm2mw(dbm_cur);
1781
1782                         memcpy(&buf[dbm_cnt * sizeof(entry)], &entry, sizeof(entry));
1783                 }
1784
1785                 entry.dbm = dbm_max;
1786                 entry.mw  = iwinfo_dbm2mw(dbm_max);
1787
1788                 memcpy(&buf[dbm_cnt * sizeof(entry)], &entry, sizeof(entry));
1789                 dbm_cnt++;
1790
1791                 *len = dbm_cnt * sizeof(entry);
1792                 return 0;
1793         }
1794
1795         return -1;
1796 }
1797
1798 static void nl80211_get_scancrypto(const char *spec,
1799         struct iwinfo_crypto_entry *c)
1800 {
1801         if (strstr(spec, "WPA") || strstr(spec, "WEP"))
1802         {
1803                 c->enabled = 1;
1804
1805                 if (strstr(spec, "WPA2-") && strstr(spec, "WPA-"))
1806                         c->wpa_version = 3;
1807
1808                 else if (strstr(spec, "WPA2"))
1809                         c->wpa_version = 2;
1810
1811                 else if (strstr(spec, "WPA"))
1812                         c->wpa_version = 1;
1813
1814                 else if (strstr(spec, "WEP"))
1815                         c->auth_algs = IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED;
1816
1817
1818                 if (strstr(spec, "PSK"))
1819                         c->auth_suites |= IWINFO_KMGMT_PSK;
1820
1821                 if (strstr(spec, "802.1X") || strstr(spec, "EAP"))
1822                         c->auth_suites |= IWINFO_KMGMT_8021x;
1823
1824                 if (strstr(spec, "WPA-NONE"))
1825                         c->auth_suites |= IWINFO_KMGMT_NONE;
1826
1827
1828                 if (strstr(spec, "TKIP"))
1829                         c->pair_ciphers |= IWINFO_CIPHER_TKIP;
1830
1831                 if (strstr(spec, "CCMP"))
1832                         c->pair_ciphers |= IWINFO_CIPHER_CCMP;
1833
1834                 if (strstr(spec, "WEP-40"))
1835                         c->pair_ciphers |= IWINFO_CIPHER_WEP40;
1836
1837                 if (strstr(spec, "WEP-104"))
1838                         c->pair_ciphers |= IWINFO_CIPHER_WEP104;
1839
1840                 c->group_ciphers = c->pair_ciphers;
1841         }
1842         else
1843         {
1844                 c->enabled = 0;
1845         }
1846 }
1847
1848
1849 struct nl80211_scanlist {
1850         struct iwinfo_scanlist_entry *e;
1851         int len;
1852 };
1853
1854
1855 static void nl80211_get_scanlist_ie(struct nlattr **bss,
1856                                     struct iwinfo_scanlist_entry *e)
1857 {
1858         int ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
1859         unsigned char *ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
1860         static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 };
1861         int len;
1862
1863         while (ielen >= 2 && ielen >= ie[1])
1864         {
1865                 switch (ie[0])
1866                 {
1867                 case 0: /* SSID */
1868                         len = min(ie[1], IWINFO_ESSID_MAX_SIZE);
1869                         memcpy(e->ssid, ie + 2, len);
1870                         e->ssid[len] = 0;
1871                         break;
1872
1873                 case 48: /* RSN */
1874                         iwinfo_parse_rsn(&e->crypto, ie + 2, ie[1],
1875                                          IWINFO_CIPHER_CCMP, IWINFO_KMGMT_8021x);
1876                         break;
1877
1878                 case 221: /* Vendor */
1879                         if (ie[1] >= 4 && !memcmp(ie + 2, ms_oui, 3) && ie[5] == 1)
1880                                 iwinfo_parse_rsn(&e->crypto, ie + 6, ie[1] - 4,
1881                                                  IWINFO_CIPHER_TKIP, IWINFO_KMGMT_PSK);
1882                         break;
1883                 }
1884
1885                 ielen -= ie[1] + 2;
1886                 ie += ie[1] + 2;
1887         }
1888 }
1889
1890 static int nl80211_get_scanlist_cb(struct nl_msg *msg, void *arg)
1891 {
1892         int8_t rssi;
1893         uint16_t caps;
1894
1895         struct nl80211_scanlist *sl = arg;
1896         struct nlattr **tb = nl80211_parse(msg);
1897         struct nlattr *bss[NL80211_BSS_MAX + 1];
1898
1899         static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
1900                 [NL80211_BSS_TSF]                  = { .type = NLA_U64 },
1901                 [NL80211_BSS_FREQUENCY]            = { .type = NLA_U32 },
1902                 [NL80211_BSS_BSSID]                = {                 },
1903                 [NL80211_BSS_BEACON_INTERVAL]      = { .type = NLA_U16 },
1904                 [NL80211_BSS_CAPABILITY]           = { .type = NLA_U16 },
1905                 [NL80211_BSS_INFORMATION_ELEMENTS] = {                 },
1906                 [NL80211_BSS_SIGNAL_MBM]           = { .type = NLA_U32 },
1907                 [NL80211_BSS_SIGNAL_UNSPEC]        = { .type = NLA_U8  },
1908                 [NL80211_BSS_STATUS]               = { .type = NLA_U32 },
1909                 [NL80211_BSS_SEEN_MS_AGO]          = { .type = NLA_U32 },
1910                 [NL80211_BSS_BEACON_IES]           = {                 },
1911         };
1912
1913         if (!tb[NL80211_ATTR_BSS] ||
1914                 nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
1915                                  bss_policy) ||
1916                 !bss[NL80211_BSS_BSSID])
1917         {
1918                 return NL_SKIP;
1919         }
1920
1921         if (bss[NL80211_BSS_CAPABILITY])
1922                 caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
1923         else
1924                 caps = 0;
1925
1926         memset(sl->e, 0, sizeof(*sl->e));
1927         memcpy(sl->e->mac, nla_data(bss[NL80211_BSS_BSSID]), 6);
1928
1929         if (caps & (1<<1))
1930                 sl->e->mode = IWINFO_OPMODE_ADHOC;
1931         else if (caps & (1<<0))
1932                 sl->e->mode = IWINFO_OPMODE_MASTER;
1933         else
1934                 sl->e->mode = IWINFO_OPMODE_MESHPOINT;
1935
1936         if (caps & (1<<4))
1937                 sl->e->crypto.enabled = 1;
1938
1939         if (bss[NL80211_BSS_FREQUENCY])
1940                 sl->e->channel = nl80211_freq2channel(nla_get_u32(
1941                         bss[NL80211_BSS_FREQUENCY]));
1942
1943         if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
1944                 nl80211_get_scanlist_ie(bss, sl->e);
1945
1946         if (bss[NL80211_BSS_SIGNAL_MBM])
1947         {
1948                 sl->e->signal =
1949                         (uint8_t)((int32_t)nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]) / 100);
1950
1951                 rssi = sl->e->signal - 0x100;
1952
1953                 if (rssi < -110)
1954                         rssi = -110;
1955                 else if (rssi > -40)
1956                         rssi = -40;
1957
1958                 sl->e->quality = (rssi + 110);
1959                 sl->e->quality_max = 70;
1960         }
1961
1962         if (sl->e->crypto.enabled && !sl->e->crypto.wpa_version)
1963         {
1964                 sl->e->crypto.auth_algs    = IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED;
1965                 sl->e->crypto.pair_ciphers = IWINFO_CIPHER_WEP40 | IWINFO_CIPHER_WEP104;
1966         }
1967
1968         sl->e++;
1969         sl->len++;
1970
1971         return NL_SKIP;
1972 }
1973
1974 static int nl80211_get_scanlist_nl(const char *ifname, char *buf, int *len)
1975 {
1976         struct nl80211_msg_conveyor *req;
1977         struct nl80211_scanlist sl = { .e = (struct iwinfo_scanlist_entry *)buf };
1978
1979         req = nl80211_msg(ifname, NL80211_CMD_TRIGGER_SCAN, 0);
1980         if (req)
1981         {
1982                 nl80211_send(req, NULL, NULL);
1983                 nl80211_free(req);
1984         }
1985
1986         nl80211_wait("nl80211", "scan", NL80211_CMD_NEW_SCAN_RESULTS);
1987
1988         req = nl80211_msg(ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
1989         if (req)
1990         {
1991                 nl80211_send(req, nl80211_get_scanlist_cb, &sl);
1992                 nl80211_free(req);
1993         }
1994
1995         *len = sl.len * sizeof(struct iwinfo_scanlist_entry);
1996         return *len ? 0 : -1;
1997 }
1998
1999 static int wpasupp_ssid_decode(const char *in, char *out, int outlen)
2000 {
2001 #define hex(x) \
2002         (((x) >= 'a') ? ((x) - 'a' + 10) : \
2003                 (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0')))
2004
2005         int len = 0;
2006
2007         while (*in)
2008         {
2009                 if (len + 1 >= outlen)
2010                         break;
2011
2012                 switch (*in)
2013                 {
2014                 case '\\':
2015                         in++;
2016                         switch (*in)
2017                         {
2018                         case 'n':
2019                                 out[len++] = '\n'; in++;
2020                                 break;
2021
2022                         case 'r':
2023                                 out[len++] = '\r'; in++;
2024                                 break;
2025
2026                         case 't':
2027                                 out[len++] = '\t'; in++;
2028                                 break;
2029
2030                         case 'e':
2031                                 out[len++] = '\e'; in++;
2032                                 break;
2033
2034                         case 'x':
2035                                 if (isxdigit(*(in+1)) && isxdigit(*(in+2)))
2036                                         out[len++] = hex(*(in+1)) * 16 + hex(*(in+2));
2037                                 in += 3;
2038                                 break;
2039
2040                         default:
2041                                 out[len++] = *in++;
2042                                 break;
2043                         }
2044                         break;
2045
2046                 default:
2047                         out[len++] = *in++;
2048                         break;
2049                 }
2050         }
2051
2052         if (outlen > len)
2053                 out[len] = '\0';
2054
2055         return len;
2056 }
2057
2058 static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
2059 {
2060         int freq, rssi, qmax, count, mode;
2061         char *res;
2062         char ssid[129] = { 0 };
2063         char bssid[18] = { 0 };
2064         char cipher[256] = { 0 };
2065
2066         /* Got a radioX pseudo interface, find some interface on it or create one */
2067         if (!strncmp(ifname, "radio", 5))
2068         {
2069                 /* Reuse existing interface */
2070                 if ((res = nl80211_phy2ifname(ifname)) != NULL)
2071                 {
2072                         return nl80211_get_scanlist(res, buf, len);
2073                 }
2074
2075                 /* Need to spawn a temporary iface for scanning */
2076                 else if ((res = nl80211_ifadd(ifname)) != NULL)
2077                 {
2078                         count = nl80211_get_scanlist(res, buf, len);
2079                         nl80211_ifdel(res);
2080                         return count;
2081                 }
2082         }
2083
2084         struct iwinfo_scanlist_entry *e = (struct iwinfo_scanlist_entry *)buf;
2085
2086         /* WPA supplicant */
2087         if ((res = nl80211_wpactl_info(ifname, "SCAN", "CTRL-EVENT-SCAN-RESULTS")))
2088         {
2089                 if ((res = nl80211_wpactl_info(ifname, "SCAN_RESULTS", NULL)))
2090                 {
2091                         nl80211_get_quality_max(ifname, &qmax);
2092
2093                         count = -1;
2094
2095                         do {
2096                                 if (res[0] == '<')
2097                                 {
2098                                         /* skip log lines */
2099                                         goto nextline;
2100                                 }
2101                                 if (count < 0)
2102                                 {
2103                                         /* skip header line */
2104                                         count++;
2105                                         goto nextline;
2106                                 }
2107                                 if (sscanf(res, "%17s %d %d %255s%*[ \t]%128[^\n]\n",
2108                                               bssid, &freq, &rssi, cipher, ssid) < 5)
2109                                 {
2110                                         /* skip malformed lines */
2111                                         goto nextline;
2112                                 }
2113                                 /* BSSID */
2114                                 e->mac[0] = strtol(&bssid[0],  NULL, 16);
2115                                 e->mac[1] = strtol(&bssid[3],  NULL, 16);
2116                                 e->mac[2] = strtol(&bssid[6],  NULL, 16);
2117                                 e->mac[3] = strtol(&bssid[9],  NULL, 16);
2118                                 e->mac[4] = strtol(&bssid[12], NULL, 16);
2119                                 e->mac[5] = strtol(&bssid[15], NULL, 16);
2120
2121                                 /* SSID */
2122                                 wpasupp_ssid_decode(ssid, e->ssid, sizeof(e->ssid));
2123
2124                                 /* Mode (assume master) */
2125                                 if (strstr(cipher,"[MESH]"))
2126                                         e->mode = IWINFO_OPMODE_MESHPOINT;
2127                                 else
2128                                         e->mode = IWINFO_OPMODE_MASTER;
2129
2130                                 /* Channel */
2131                                 e->channel = nl80211_freq2channel(freq);
2132
2133                                 /* Signal */
2134                                 e->signal = rssi;
2135
2136                                 /* Quality */
2137                                 if (rssi < 0)
2138                                 {
2139                                         /* The cfg80211 wext compat layer assumes a signal range
2140                                          * of -110 dBm to -40 dBm, the quality value is derived
2141                                          * by adding 110 to the signal level */
2142                                         if (rssi < -110)
2143                                                 rssi = -110;
2144                                         else if (rssi > -40)
2145                                                 rssi = -40;
2146
2147                                         e->quality = (rssi + 110);
2148                                 }
2149                                 else
2150                                 {
2151                                         e->quality = rssi;
2152                                 }
2153
2154                                 /* Max. Quality */
2155                                 e->quality_max = qmax;
2156
2157                                 /* Crypto */
2158                                 nl80211_get_scancrypto(cipher, &e->crypto);
2159
2160                                 count++;
2161                                 e++;
2162
2163                                 memset(ssid, 0, sizeof(ssid));
2164                                 memset(bssid, 0, sizeof(bssid));
2165                                 memset(cipher, 0, sizeof(cipher));
2166
2167                         nextline:
2168                                 /* advance to next line */
2169                                 while( *res && *res++ != '\n' );
2170                         }
2171                         while( *res );
2172
2173                         *len = count * sizeof(struct iwinfo_scanlist_entry);
2174                         return 0;
2175                 }
2176         }
2177
2178         /* station / ad-hoc / monitor scan */
2179         else if (!nl80211_get_mode(ifname, &mode) &&
2180                  (mode == IWINFO_OPMODE_ADHOC ||
2181                   mode == IWINFO_OPMODE_MASTER ||
2182                   mode == IWINFO_OPMODE_CLIENT ||
2183                   mode == IWINFO_OPMODE_MONITOR) &&
2184                  iwinfo_ifup(ifname))
2185         {
2186                 return nl80211_get_scanlist_nl(ifname, buf, len);
2187         }
2188
2189         /* AP scan */
2190         else
2191         {
2192                 /* Got a temp interface, don't create yet another one */
2193                 if (!strncmp(ifname, "tmp.", 4))
2194                 {
2195                         if (!iwinfo_ifup(ifname))
2196                                 return -1;
2197
2198                         nl80211_get_scanlist_nl(ifname, buf, len);
2199                         iwinfo_ifdown(ifname);
2200                         return 0;
2201                 }
2202
2203                 /* Spawn a new scan interface */
2204                 else
2205                 {
2206                         if (!(res = nl80211_ifadd(ifname)))
2207                                 goto out;
2208
2209                         iwinfo_ifmac(res);
2210
2211                         /* if we can take the new interface up, the driver supports an
2212                          * additional interface and there's no need to tear down the ap */
2213                         if (iwinfo_ifup(res))
2214                         {
2215                                 nl80211_get_scanlist_nl(res, buf, len);
2216                                 iwinfo_ifdown(res);
2217                         }
2218
2219                         /* driver cannot create secondary interface, take down ap
2220                          * during scan */
2221                         else if (iwinfo_ifdown(ifname) && iwinfo_ifup(res))
2222                         {
2223                                 nl80211_get_scanlist_nl(res, buf, len);
2224                                 iwinfo_ifdown(res);
2225                                 iwinfo_ifup(ifname);
2226                                 nl80211_hostapd_hup(ifname);
2227                         }
2228
2229                 out:
2230                         nl80211_ifdel(res);
2231                         return 0;
2232                 }
2233         }
2234
2235         return -1;
2236 }
2237
2238 static int nl80211_get_freqlist_cb(struct nl_msg *msg, void *arg)
2239 {
2240         int bands_remain, freqs_remain;
2241
2242         struct nl80211_array_buf *arr = arg;
2243         struct iwinfo_freqlist_entry *e = arr->buf;
2244
2245         struct nlattr **attr = nl80211_parse(msg);
2246         struct nlattr *bands[NL80211_BAND_ATTR_MAX + 1];
2247         struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
2248         struct nlattr *band, *freq;
2249
2250         static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
2251                 [NL80211_FREQUENCY_ATTR_FREQ]         = { .type = NLA_U32  },
2252                 [NL80211_FREQUENCY_ATTR_DISABLED]     = { .type = NLA_FLAG },
2253                 [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
2254                 [NL80211_FREQUENCY_ATTR_NO_IBSS]      = { .type = NLA_FLAG },
2255                 [NL80211_FREQUENCY_ATTR_RADAR]        = { .type = NLA_FLAG },
2256                 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32  },
2257         };
2258
2259         nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain)
2260         {
2261                 nla_parse(bands, NL80211_BAND_ATTR_MAX,
2262                           nla_data(band), nla_len(band), NULL);
2263
2264                 nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS], freqs_remain)
2265                 {
2266                         nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX,
2267                                   nla_data(freq), nla_len(freq), NULL);
2268
2269                         if (!freqs[NL80211_FREQUENCY_ATTR_FREQ] ||
2270                             freqs[NL80211_FREQUENCY_ATTR_DISABLED])
2271                                 continue;
2272
2273                         e->mhz = nla_get_u32(freqs[NL80211_FREQUENCY_ATTR_FREQ]);
2274                         e->channel = nl80211_freq2channel(e->mhz);
2275
2276                         e->restricted = (
2277                                 freqs[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] ||
2278                                 freqs[NL80211_FREQUENCY_ATTR_NO_IBSS]      ||
2279                                 freqs[NL80211_FREQUENCY_ATTR_RADAR]
2280                         ) ? 1 : 0;
2281
2282                         e++;
2283                         arr->count++;
2284                 }
2285         }
2286
2287         return NL_SKIP;
2288 }
2289
2290 static int nl80211_get_freqlist(const char *ifname, char *buf, int *len)
2291 {
2292         struct nl80211_msg_conveyor *req;
2293         struct nl80211_array_buf arr = { .buf = buf, .count = 0 };
2294
2295         req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
2296         if (req)
2297         {
2298                 nl80211_send(req, nl80211_get_freqlist_cb, &arr);
2299                 nl80211_free(req);
2300         }
2301
2302         if (arr.count > 0)
2303         {
2304                 *len = arr.count * sizeof(struct iwinfo_freqlist_entry);
2305                 return 0;
2306         }
2307
2308         return -1;
2309 }
2310
2311 static int nl80211_get_country_cb(struct nl_msg *msg, void *arg)
2312 {
2313         char *buf = arg;
2314         struct nlattr **attr = nl80211_parse(msg);
2315
2316         if (attr[NL80211_ATTR_REG_ALPHA2])
2317                 memcpy(buf, nla_data(attr[NL80211_ATTR_REG_ALPHA2]), 2);
2318         else
2319                 buf[0] = 0;
2320
2321         return NL_SKIP;
2322 }
2323
2324 static int nl80211_get_country(const char *ifname, char *buf)
2325 {
2326         int rv = -1;
2327         struct nl80211_msg_conveyor *req;
2328
2329         req = nl80211_msg(ifname, NL80211_CMD_GET_REG, 0);
2330         if (req)
2331         {
2332                 nl80211_send(req, nl80211_get_country_cb, buf);
2333                 nl80211_free(req);
2334
2335                 if (buf[0])
2336                         rv = 0;
2337         }
2338
2339         return rv;
2340 }
2341
2342 static int nl80211_get_countrylist(const char *ifname, char *buf, int *len)
2343 {
2344         int i, count;
2345         struct iwinfo_country_entry *e = (struct iwinfo_country_entry *)buf;
2346         const struct iwinfo_iso3166_label *l;
2347
2348         for (l = IWINFO_ISO3166_NAMES, count = 0; l->iso3166; l++, e++, count++)
2349         {
2350                 e->iso3166 = l->iso3166;
2351                 e->ccode[0] = (l->iso3166 / 256);
2352                 e->ccode[1] = (l->iso3166 % 256);
2353         }
2354
2355         *len = (count * sizeof(struct iwinfo_country_entry));
2356         return 0;
2357 }
2358
2359 static int nl80211_get_hwmodelist_cb(struct nl_msg *msg, void *arg)
2360 {
2361         int *modes = arg;
2362         int bands_remain, freqs_remain;
2363         uint16_t caps = 0;
2364         uint32_t vht_caps = 0;
2365         struct nlattr **attr = nl80211_parse(msg);
2366         struct nlattr *bands[NL80211_BAND_ATTR_MAX + 1];
2367         struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
2368         struct nlattr *band, *freq;
2369
2370         *modes = 0;
2371
2372         if (attr[NL80211_ATTR_WIPHY_BANDS])
2373         {
2374                 nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain)
2375                 {
2376                         nla_parse(bands, NL80211_BAND_ATTR_MAX,
2377                                   nla_data(band), nla_len(band), NULL);
2378
2379                         if (bands[NL80211_BAND_ATTR_HT_CAPA])
2380                                 caps = nla_get_u16(bands[NL80211_BAND_ATTR_HT_CAPA]);
2381
2382                         /* Treat any nonzero capability as 11n */
2383                         if (caps > 0)
2384                                 *modes |= IWINFO_80211_N;
2385
2386                         if (bands[NL80211_BAND_ATTR_VHT_CAPA])
2387                                 vht_caps = nla_get_u32(bands[NL80211_BAND_ATTR_VHT_CAPA]);
2388
2389                         /* Treat any nonzero capability as 11ac */
2390                         if (vht_caps > 0)
2391                                 *modes |= IWINFO_80211_AC;
2392
2393                         nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS],
2394                                             freqs_remain)
2395                         {
2396                                 nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX,
2397                                           nla_data(freq), nla_len(freq), NULL);
2398
2399                                 if (!freqs[NL80211_FREQUENCY_ATTR_FREQ])
2400                                         continue;
2401
2402                                 if (nla_get_u32(freqs[NL80211_FREQUENCY_ATTR_FREQ]) < 2485)
2403                                 {
2404                                         *modes |= IWINFO_80211_B;
2405                                         *modes |= IWINFO_80211_G;
2406                                 }
2407                                 else if (!(*modes & IWINFO_80211_AC))
2408                                 {
2409                                         *modes |= IWINFO_80211_A;
2410                                 }
2411                         }
2412                 }
2413         }
2414
2415         return NL_SKIP;
2416 }
2417
2418 static int nl80211_get_hwmodelist(const char *ifname, int *buf)
2419 {
2420         struct nl80211_msg_conveyor *req;
2421
2422         req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
2423         if (req)
2424         {
2425                 nl80211_send(req, nl80211_get_hwmodelist_cb, buf);
2426                 nl80211_free(req);
2427         }
2428
2429         return *buf ? 0 : -1;
2430 }
2431
2432 static int nl80211_get_ifcomb_cb(struct nl_msg *msg, void *arg)
2433 {
2434         struct nlattr **attr = nl80211_parse(msg);
2435         struct nlattr *comb;
2436         int *ret = arg;
2437         int comb_rem, limit_rem, mode_rem;
2438
2439         *ret = 0;
2440         if (!attr[NL80211_ATTR_INTERFACE_COMBINATIONS])
2441                 return NL_SKIP;
2442
2443         nla_for_each_nested(comb, attr[NL80211_ATTR_INTERFACE_COMBINATIONS], comb_rem)
2444         {
2445                 static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
2446                         [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
2447                         [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
2448                 };
2449                 struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB+1];
2450                 static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
2451                         [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
2452                         [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
2453                 };
2454                 struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT+1];
2455                 struct nlattr *limit;
2456
2457                 nla_parse_nested(tb_comb, NUM_NL80211_IFACE_COMB, comb, iface_combination_policy);
2458
2459                 if (!tb_comb[NL80211_IFACE_COMB_LIMITS])
2460                         continue;
2461
2462                 nla_for_each_nested(limit, tb_comb[NL80211_IFACE_COMB_LIMITS], limit_rem)
2463                 {
2464                         struct nlattr *mode;
2465
2466                         nla_parse_nested(tb_limit, NUM_NL80211_IFACE_LIMIT, limit, iface_limit_policy);
2467
2468                         if (!tb_limit[NL80211_IFACE_LIMIT_TYPES] ||
2469                             !tb_limit[NL80211_IFACE_LIMIT_MAX])
2470                                 continue;
2471
2472                         if (nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX]) < 2)
2473                                 continue;
2474
2475                         nla_for_each_nested(mode, tb_limit[NL80211_IFACE_LIMIT_TYPES], mode_rem) {
2476                                 if (nla_type(mode) == NL80211_IFTYPE_AP)
2477                                         *ret = 1;
2478                         }
2479                 }
2480         }
2481
2482         return NL_SKIP;
2483 }
2484
2485 static int nl80211_get_mbssid_support(const char *ifname, int *buf)
2486 {
2487         struct nl80211_msg_conveyor *req;
2488
2489         req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
2490         if (!req)
2491                 return -1;
2492
2493         nl80211_send(req, nl80211_get_ifcomb_cb, buf);
2494         nl80211_free(req);
2495         return 0;
2496 }
2497
2498 static int nl80211_get_hardware_id(const char *ifname, char *buf)
2499 {
2500         int rv;
2501         char *res;
2502
2503         /* Got a radioX pseudo interface, find some interface on it or create one */
2504         if (!strncmp(ifname, "radio", 5))
2505         {
2506                 /* Reuse existing interface */
2507                 if ((res = nl80211_phy2ifname(ifname)) != NULL)
2508                 {
2509                         rv = wext_ops.hardware_id(res, buf);
2510                 }
2511
2512                 /* Need to spawn a temporary iface for finding IDs */
2513                 else if ((res = nl80211_ifadd(ifname)) != NULL)
2514                 {
2515                         rv = wext_ops.hardware_id(res, buf);
2516                         nl80211_ifdel(res);
2517                 }
2518         }
2519         else
2520         {
2521                 rv = wext_ops.hardware_id(ifname, buf);
2522         }
2523
2524         /* Failed to obtain hardware IDs, search board config */
2525         if (rv)
2526         {
2527                 rv = iwinfo_hardware_id_from_mtd((struct iwinfo_hardware_id *)buf);
2528         }
2529
2530         return rv;
2531 }
2532
2533 static const struct iwinfo_hardware_entry *
2534 nl80211_get_hardware_entry(const char *ifname)
2535 {
2536         struct iwinfo_hardware_id id;
2537
2538         if (nl80211_get_hardware_id(ifname, (char *)&id))
2539                 return NULL;
2540
2541         return iwinfo_hardware(&id);
2542 }
2543
2544 static int nl80211_get_hardware_name(const char *ifname, char *buf)
2545 {
2546         const struct iwinfo_hardware_entry *hw;
2547
2548         if (!(hw = nl80211_get_hardware_entry(ifname)))
2549                 sprintf(buf, "Generic MAC80211");
2550         else
2551                 sprintf(buf, "%s %s", hw->vendor_name, hw->device_name);
2552
2553         return 0;
2554 }
2555
2556 static int nl80211_get_txpower_offset(const char *ifname, int *buf)
2557 {
2558         const struct iwinfo_hardware_entry *hw;
2559
2560         if (!(hw = nl80211_get_hardware_entry(ifname)))
2561                 return -1;
2562
2563         *buf = hw->txpower_offset;
2564         return 0;
2565 }
2566
2567 static int nl80211_get_frequency_offset(const char *ifname, int *buf)
2568 {
2569         const struct iwinfo_hardware_entry *hw;
2570
2571         if (!(hw = nl80211_get_hardware_entry(ifname)))
2572                 return -1;
2573
2574         *buf = hw->frequency_offset;
2575         return 0;
2576 }
2577
2578 static int nl80211_lookup_phyname(const char *section, char *buf)
2579 {
2580         int idx;
2581
2582         if ((idx = nl80211_phy_idx_from_uci(section)) < 0)
2583                 return -1;
2584
2585         sprintf(buf, "phy%d", idx);
2586         return 0;
2587 }
2588
2589 const struct iwinfo_ops nl80211_ops = {
2590         .name             = "nl80211",
2591         .probe            = nl80211_probe,
2592         .channel          = nl80211_get_channel,
2593         .frequency        = nl80211_get_frequency,
2594         .frequency_offset = nl80211_get_frequency_offset,
2595         .txpower          = nl80211_get_txpower,
2596         .txpower_offset   = nl80211_get_txpower_offset,
2597         .bitrate          = nl80211_get_bitrate,
2598         .signal           = nl80211_get_signal,
2599         .noise            = nl80211_get_noise,
2600         .quality          = nl80211_get_quality,
2601         .quality_max      = nl80211_get_quality_max,
2602         .mbssid_support   = nl80211_get_mbssid_support,
2603         .hwmodelist       = nl80211_get_hwmodelist,
2604         .mode             = nl80211_get_mode,
2605         .ssid             = nl80211_get_ssid,
2606         .bssid            = nl80211_get_bssid,
2607         .country          = nl80211_get_country,
2608         .hardware_id      = nl80211_get_hardware_id,
2609         .hardware_name    = nl80211_get_hardware_name,
2610         .encryption       = nl80211_get_encryption,
2611         .phyname          = nl80211_get_phyname,
2612         .assoclist        = nl80211_get_assoclist,
2613         .txpwrlist        = nl80211_get_txpwrlist,
2614         .scanlist         = nl80211_get_scanlist,
2615         .freqlist         = nl80211_get_freqlist,
2616         .countrylist      = nl80211_get_countrylist,
2617         .lookup_phy       = nl80211_lookup_phyname,
2618         .close            = nl80211_close
2619 };