2db292bf9d3f1b4c9bf909e4577e818bd45be83b
[metze/wireshark/wip.git] / caputils / ws80211_utils.c
1 /*
2  * ws80211 utilities
3  * Copyright 2012, Pontus Fuchs <pontus.fuchs@gmail.com>
4
5 Parts of this file was copied from iw:
6
7 Copyright (c) 2007, 2008        Johannes Berg
8 Copyright (c) 2007              Andy Lutomirski
9 Copyright (c) 2007              Mike Kershaw
10 Copyright (c) 2008-2009         Luis R. Rodriguez
11
12 Permission to use, copy, modify, and/or distribute this software for any
13 purpose with or without fee is hereby granted, provided that the above
14 copyright notice and this permission notice appear in all copies.
15
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 */
24
25 #include "config.h"
26
27 #include <stdio.h>
28
29 #include <glib.h>
30 #include <glib/gstdio.h>
31
32 #include "ws80211_utils.h"
33 #include "wsutil/ws_diag_control.h"
34
35 #if defined(HAVE_LIBNL) && defined(HAVE_NL80211)
36 #include <string.h>
37 #include <errno.h>
38 #include <unistd.h>
39
40 #include <net/if.h>
41 #include <sys/ioctl.h>
42
43 DIAG_OFF(pedantic)
44 #include <netlink/genl/genl.h>
45 DIAG_ON(pedantic)
46 #include <netlink/genl/family.h>
47 #include <netlink/genl/ctrl.h>
48 DIAG_OFF(pedantic)
49 #include <netlink/msg.h>
50 DIAG_ON(pedantic)
51 #include <netlink/attr.h>
52
53 #include <linux/nl80211.h>
54
55 #ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
56 static int ws80211_get_protocol_features(int* features);
57 #endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
58
59 /* libnl 1.x compatibility code */
60 #ifdef HAVE_LIBNL1
61 #define nl_sock nl_handle
62 static inline struct nl_handle *nl_socket_alloc(void)
63 {
64         return nl_handle_alloc();
65 }
66
67 static inline void nl_socket_free(struct nl_sock *h)
68 {
69         nl_handle_destroy(h);
70 }
71 #endif /* HAVE_LIBNL1 */
72
73 struct nl80211_state {
74         struct nl_sock *nl_sock;
75         int nl80211_id;
76         int have_split_wiphy;
77 };
78
79 static struct nl80211_state nl_state;
80
81 int ws80211_init(void)
82 {
83         int err;
84 #ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
85         int features = 0;
86 #endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
87
88         struct nl80211_state *state = &nl_state;
89
90         state->nl_sock = nl_socket_alloc();
91         if (!state->nl_sock) {
92                 fprintf(stderr, "Failed to allocate netlink socket.\n");
93                 return -ENOMEM;
94         }
95
96         if (genl_connect(state->nl_sock)) {
97                 fprintf(stderr, "Failed to connect to generic netlink.\n");
98                 err = -ENOLINK;
99                 goto out_handle_destroy;
100         }
101
102         state->nl80211_id = genl_ctrl_resolve(state->nl_sock, "nl80211");
103         if (state->nl80211_id < 0) {
104                 fprintf(stderr, "nl80211 not found.\n");
105                 err = -ENOENT;
106                 goto out_handle_destroy;
107         }
108 #ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
109         ws80211_get_protocol_features(&features);
110         if (features & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
111                 state->have_split_wiphy = TRUE;
112 #endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
113
114         return 0;
115
116  out_handle_destroy:
117         nl_socket_free(state->nl_sock);
118         state->nl_sock = 0;
119         return err;
120 }
121
122 static int error_handler(struct sockaddr_nl *nla _U_, struct nlmsgerr *err,
123                          void *arg)
124 {
125         int *ret = (int *)arg;
126         *ret = err->error;
127         return NL_STOP;
128 }
129
130 static int finish_handler(struct nl_msg *msg _U_, void *arg)
131 {
132         int *ret = (int *)arg;
133         *ret = 0;
134         return NL_SKIP;
135 }
136
137 static int ack_handler(struct nl_msg *msg _U_, void *arg)
138 {
139         int *ret = (int *)arg;
140         *ret = 0;
141         return NL_STOP;
142 }
143
144 static int nl80211_do_cmd(struct nl_msg *msg, struct nl_cb *cb)
145 {
146         volatile int err;
147
148         if (!nl_state.nl_sock)
149                 return -ENOLINK;
150
151         err = nl_send_auto_complete(nl_state.nl_sock, msg);
152         if (err < 0)
153                 goto out;
154
155         err = 1;
156
157         nl_cb_err(cb, NL_CB_CUSTOM, error_handler, (void *)&err);
158         nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, (void *)&err);
159         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, (void *)&err);
160
161         while (err > 0)
162                 nl_recvmsgs(nl_state.nl_sock, cb);
163  out:
164         nl_cb_put(cb);
165
166         return err;
167 }
168
169 struct nliface_cookie
170 {
171         char *ifname;
172         GArray *interfaces;
173 };
174
175 static struct ws80211_interface *
176         get_interface_by_name(GArray *interfaces,
177                               char* ifname)
178 {
179         unsigned int i;
180         struct ws80211_interface *iface;
181
182         for (i = 0; i < interfaces->len; i++) {
183                 iface = g_array_index(interfaces, struct ws80211_interface *, i);
184                 if (!strcmp(iface->ifname, ifname))
185                         return iface;
186         }
187         return NULL;
188 }
189
190 /*
191  * And now for a steaming heap of suck.
192  *
193  * The nla_for_each_nested() macro defined by at least some versions of the
194  * Linux kernel's headers doesn't do the casting required when compiling
195  * with a C++ compiler or with -Wc++-compat, so we get warnings, and those
196  * warnings are fatal when we compile this file.
197  *
198  * So we replace it with our own version, which does the requisite cast.
199  */
200
201 /**
202  * nla_for_each_nested - iterate over nested attributes
203  * @pos: loop counter, set to current attribute
204  * @nla: attribute containing the nested attributes
205  * @rem: initialized to len, holds bytes currently remaining in stream
206  */
207 #undef nla_for_each_nested
208 #define nla_for_each_nested(pos, nla, rem) \
209         nla_for_each_attr(pos, (struct nlattr *)nla_data(nla), nla_len(nla), rem)
210
211 #ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
212 static int get_features_handler(struct nl_msg *msg, void *arg)
213 {
214         int *feat = (int*) arg;
215         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
216         struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
217
218         nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
219                   genlmsg_attrlen(gnlh, 0), NULL);
220
221         if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES])
222                 *feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]);
223
224         return NL_SKIP;
225 }
226
227 static int ws80211_get_protocol_features(int* features)
228 {
229         struct nl_msg *msg;
230         struct nl_cb *cb;
231         int ret;
232
233         msg = nlmsg_alloc();
234         if (!msg) {
235                 fprintf(stderr, "failed to allocate netlink message\n");
236                 return 2;
237         }
238
239         cb = nl_cb_alloc(NL_CB_DEFAULT);
240
241         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0, 0,
242                     NL80211_CMD_GET_PROTOCOL_FEATURES, 0);
243
244         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_features_handler, features);
245
246         ret = nl80211_do_cmd(msg, cb);
247         nlmsg_free(msg);
248         return ret;
249 }
250 #endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
251
252 #ifdef NL80211_BAND_ATTR_HT_CAPA
253 static void parse_band_ht_capa(struct ws80211_interface *iface,
254                                struct nlattr *tb)
255 {
256         gboolean ht40;
257
258         if (!tb) return;
259
260         iface->channel_types |= 1 << WS80211_CHAN_HT20;
261         ht40 = !!(nla_get_u16(tb) & 0x02);
262         if (ht40) {
263                 iface->channel_types |= 1 << WS80211_CHAN_HT40MINUS;
264                 iface->channel_types |= 1 << WS80211_CHAN_HT40PLUS;
265         }
266 }
267 #endif /* NL80211_BAND_ATTR_HT_CAPA */
268
269 static void parse_supported_iftypes(struct ws80211_interface *iface,
270                                     struct nlattr *tb)
271 {
272         struct nlattr *nl_mode;
273         int rem_mode;
274
275         if (!tb) return;
276
277         nla_for_each_nested(nl_mode, tb, rem_mode) {
278                 if (nla_type(nl_mode) == NL80211_IFTYPE_MONITOR)
279                         iface->cap_monitor = 1;
280         }
281 }
282
283 static void parse_band_freqs(struct ws80211_interface *iface,
284                              struct nlattr *tb)
285 {
286         struct nlattr *nl_freq;
287         struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
288         static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
289                 {NLA_UNSPEC, 0, 0},             /* __NL80211_FREQUENCY_ATTR_INVALID */
290                 {NLA_U32, 0, 0},                /* NL80211_FREQUENCY_ATTR_FREQ */
291                 {NLA_FLAG, 0, 0},               /* NL80211_FREQUENCY_ATTR_DISABLED */
292                 {NLA_FLAG, 0, 0},               /* NL80211_FREQUENCY_ATTR_PASSIVE_SCAN */
293                 {NLA_FLAG, 0, 0},               /* NL80211_FREQUENCY_ATTR_NO_IBSS */
294                 {NLA_FLAG, 0, 0},               /* NL80211_FREQUENCY_ATTR_RADAR */
295                 {NLA_U32, 0, 0}                 /* NL80211_FREQUENCY_ATTR_MAX_TX_POWER */
296         };
297         int rem_freq;
298
299         if (!tb) return;
300
301         nla_for_each_nested(nl_freq, tb, rem_freq) {
302                 uint32_t freq;
303                 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
304                           (struct nlattr *)nla_data(nl_freq),
305                           nla_len(nl_freq), freq_policy);
306                 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
307                         continue;
308                 if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
309                         continue;
310
311                 freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
312                 g_array_append_val(iface->frequencies, freq);
313         }
314 }
315
316 static void parse_wiphy_bands(struct ws80211_interface *iface,
317                              struct nlattr *tb)
318 {
319         struct nlattr *nl_band;
320         struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
321         int bandidx = 1;
322         int rem_band;
323
324         if (!tb) return;
325
326         nla_for_each_nested(nl_band, tb, rem_band) {
327                 bandidx++;
328
329                 nla_parse(tb_band, NL80211_BAND_ATTR_MAX,
330                           (struct nlattr *)nla_data(nl_band),
331                           nla_len(nl_band), NULL);
332
333 #ifdef NL80211_BAND_ATTR_HT_CAPA
334                 parse_band_ht_capa(iface, tb_band[NL80211_BAND_ATTR_HT_CAPA]);
335 #endif /* NL80211_BAND_ATTR_HT_CAPA */
336                 parse_band_freqs(iface, tb_band[NL80211_BAND_ATTR_FREQS]);
337         }
338 }
339
340 static void parse_supported_commands(struct ws80211_interface *iface,
341                                      struct nlattr *tb)
342 {
343         /* Can frequency be set? Only newer versions of cfg80211 supports this */
344 #ifdef HAVE_NL80211_CMD_SET_CHANNEL
345         int cmd;
346         struct nlattr *nl_cmd;
347
348         if (!tb) return;
349
350         nla_for_each_nested(nl_cmd, tb, cmd) {
351                 if(nla_get_u32(nl_cmd) == NL80211_CMD_SET_CHANNEL)
352                         iface->can_set_freq = TRUE;
353         }
354 #else
355         iface->can_set_freq = TRUE;
356 #endif
357 }
358
359 static int get_phys_handler(struct nl_msg *msg, void *arg)
360 {
361         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
362         struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
363
364         struct nliface_cookie *cookie = (struct nliface_cookie *)arg;
365
366         struct ws80211_interface *iface;
367         char* ifname;
368         int added = 0;
369
370         nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
371                   genlmsg_attrlen(gnlh, 0), NULL);
372
373         if (!tb_msg[NL80211_ATTR_WIPHY_NAME])
374                 return NL_SKIP;
375
376         ifname = g_strdup_printf("%s.mon", nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]));
377         iface = get_interface_by_name(cookie->interfaces, ifname);
378
379         if (!iface) {
380                 iface = (struct ws80211_interface *)g_malloc0(sizeof(*iface));
381                 if (!iface) {
382                         g_free(ifname);
383                         return NL_SKIP;
384                 }
385                 added = 1;
386                 iface->ifname = ifname;
387                 iface->frequencies = g_array_new(FALSE, FALSE, sizeof(uint32_t));
388                 iface->channel_types = 1 << WS80211_CHAN_NO_HT;
389         } else {
390                 g_free(ifname);
391         }
392
393         parse_supported_iftypes(iface, tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES]);
394         parse_wiphy_bands(iface, tb_msg[NL80211_ATTR_WIPHY_BANDS]);
395         parse_supported_commands(iface, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]);
396
397         if (added)
398                 g_array_append_val(cookie->interfaces, iface);
399
400         return NL_SKIP;
401 }
402
403 static int ws80211_get_phys(GArray *interfaces)
404 {
405         struct nliface_cookie cookie;
406         struct nl_msg *msg;
407         struct nl_cb *cb;
408         int ret;
409         msg = nlmsg_alloc();
410         if (!msg) {
411                 fprintf(stderr, "failed to allocate netlink message\n");
412                 return 2;
413         }
414
415         cb = nl_cb_alloc(NL_CB_DEFAULT);
416
417         cookie.interfaces = interfaces;
418
419         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
420                     NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
421
422 #ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
423         if (nl_state.have_split_wiphy) {
424                 NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
425         }
426 #endif /* #ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP */
427         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_phys_handler, &cookie);
428
429         ret = nl80211_do_cmd(msg, cb);
430         nlmsg_free(msg);
431         return ret;
432
433 #ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
434 nla_put_failure:
435         nlmsg_free(msg);
436         fprintf(stderr, "building message failed\n");
437         return -1;
438 #endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
439 }
440
441 static int get_freq_wext(const char *ifname)
442 {
443         int fd;
444         int ret = -1;
445         /* Ugly hack to avoid including wireless.h */
446         struct {
447                 char name1[IFNAMSIZ];
448                 __s32 m;
449                 __s16 e;
450                 __u8 i;
451                 __u8 flags;
452         } wrq;
453
454         fd = socket(AF_INET, SOCK_DGRAM, 0);
455         if (fd == -1)
456                 return -1;
457
458         g_strlcpy(wrq.name1, ifname, IFNAMSIZ);
459         /* SIOCGIWFREQ */
460         if (ioctl(fd, 0x8B05, &wrq) == 0) {
461                 if (wrq.e == 6)
462                         ret = wrq.m;
463         }
464         close(fd);
465         return ret;
466 }
467
468 struct __iface_info
469 {
470         struct ws80211_iface_info *pub;
471         int type;
472         int phyidx;
473 };
474
475 static int get_iface_info_handler(struct nl_msg *msg, void *arg)
476 {
477         struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
478         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
479         struct __iface_info *iface_info = (struct __iface_info *)arg;
480
481         nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
482                   genlmsg_attrlen(gnlh, 0), NULL);
483
484         if (tb_msg[NL80211_ATTR_IFTYPE]) {
485                 iface_info->type = nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]);
486         }
487         if (tb_msg[NL80211_ATTR_WIPHY]) {
488                 iface_info->phyidx = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]);
489         }
490
491         if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
492                 iface_info->pub->current_freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]);
493                 iface_info->pub->current_chan_type = WS80211_CHAN_NO_HT;
494
495                 if (tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
496                         switch (nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
497
498                         case NL80211_CHAN_NO_HT:
499                                 iface_info->pub->current_chan_type = WS80211_CHAN_NO_HT;
500                                 break;
501
502                         case NL80211_CHAN_HT20:
503                                 iface_info->pub->current_chan_type = WS80211_CHAN_HT20;
504                                 break;
505
506                         case NL80211_CHAN_HT40MINUS:
507                                 iface_info->pub->current_chan_type = WS80211_CHAN_HT40MINUS;
508                                 break;
509
510                         case NL80211_CHAN_HT40PLUS:
511                                 iface_info->pub->current_chan_type = WS80211_CHAN_HT40PLUS;
512                                 break;
513                         }
514                 }
515
516         }
517         return NL_SKIP;
518 }
519
520
521 static int __ws80211_get_iface_info(const char *name, struct __iface_info *iface_info)
522 {
523         int devidx;
524         struct nl_msg *msg;
525         struct nl_cb *cb;
526         msg = nlmsg_alloc();
527         if (!msg) {
528                 fprintf(stderr, "failed to allocate netlink message\n");
529                 return 2;
530         }
531
532         cb = nl_cb_alloc(NL_CB_DEFAULT);
533
534         devidx = if_nametoindex(name);
535
536         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
537                     0, NL80211_CMD_GET_INTERFACE, 0);
538         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
539
540         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_iface_info_handler, iface_info);
541
542         if (nl80211_do_cmd(msg, cb)) {
543                 nlmsg_free(msg);
544                 return -1;
545         }
546
547         /* Old kernels can't get the current freq via netlink. Try WEXT too :( */
548         if (iface_info->pub->current_freq == -1)
549                 iface_info->pub->current_freq = get_freq_wext(name);
550         nlmsg_free(msg);
551         return 0;
552
553 nla_put_failure:
554         nlmsg_free(msg);
555         fprintf(stderr, "building message failed\n");
556         return -1;
557 }
558
559 int ws80211_get_iface_info(const char *name, struct ws80211_iface_info *iface_info)
560 {
561         struct __iface_info __iface_info;
562
563         memset(iface_info, 0, sizeof(*iface_info));
564         __iface_info.pub = iface_info;
565         __iface_info.type = -1;
566         __iface_info.phyidx= -1;
567         __iface_info.pub->current_freq = -1;
568         __iface_info.pub->current_chan_type = WS80211_CHAN_NO_HT;
569
570         return __ws80211_get_iface_info(name, &__iface_info);
571 }
572
573 static int ws80211_keep_only_monitor(GArray *interfaces)
574 {
575         unsigned int j;
576         struct ws80211_interface *iface;
577 restart:
578         for (j = 0; j < interfaces->len; j++) {
579                 iface = g_array_index(interfaces, struct ws80211_interface *, j);
580                 if (!iface->cap_monitor) {
581                         g_array_remove_index(interfaces, j);
582                         g_array_free(iface->frequencies, TRUE);
583                         g_free(iface->ifname);
584                         g_free(iface);
585                         goto restart;
586                 }
587         }
588         return 0;
589 }
590
591 static int ws80211_populate_devices(GArray *interfaces)
592 {
593         FILE *fh;
594         char line[200];
595         char *t;
596         gchar *t2;
597         char *ret;
598         int i;
599         unsigned int j;
600
601         struct ws80211_iface_info pub = {-1, WS80211_CHAN_NO_HT, WS80211_FCS_ALL};
602         struct __iface_info iface_info;
603         struct ws80211_interface *iface;
604
605         /* Get a list of phy's that can handle monitor mode */
606         ws80211_get_phys(interfaces);
607         ws80211_keep_only_monitor(interfaces);
608
609         fh = g_fopen("/proc/net/dev", "r");
610         if(!fh) {
611                 fprintf(stderr, "Cannot open /proc/net/dev");
612                 return -ENOENT;
613         }
614
615         /* Skip the first two lines */
616         for (i = 0; i < 2; i++) {
617                 ret = fgets(line, sizeof(line), fh);
618                 if (ret == NULL) {
619                         fprintf(stderr, "Error parsing /proc/net/dev");
620                         fclose(fh);
621                         return -1;
622                 }
623         }
624
625         /* Update names of user created monitor interfaces */
626         while(fgets(line, sizeof(line), fh)) {
627                 t = index(line, ':');
628                 if (!t)
629                         continue;
630                 *t = 0;
631                 t = line;
632                 while (*t && *t == ' ')
633                         t++;
634                 memset(&iface_info, 0, sizeof(iface_info));
635                 iface_info.pub = &pub;
636                 __ws80211_get_iface_info(t, &iface_info);
637
638                 if (iface_info.type == NL80211_IFTYPE_MONITOR) {
639                         for (j = 0; j < interfaces->len; j++) {
640                                 iface = g_array_index(interfaces, struct ws80211_interface *, j);
641                                 t2 = g_strdup_printf("phy%d.mon", iface_info.phyidx);
642                                 if (t2) {
643                                         if (!strcmp(t2, iface->ifname)) {
644                                                 g_free(iface->ifname);
645                                                 iface->ifname = g_strdup(t);
646                                         }
647                                         g_free(t2);
648                                 }
649                         }
650                 }
651         }
652         fclose(fh);
653         return 0;
654 }
655
656 static int ws80211_iface_up(const char *ifname)
657 {
658         int sock;
659         struct ifreq ifreq;
660
661         sock = socket(AF_PACKET, SOCK_RAW, 0);
662         if (sock == -1)
663                 return -1;
664
665         g_strlcpy(ifreq.ifr_name, ifname, sizeof(ifreq.ifr_name));
666
667         if (ioctl(sock, SIOCGIFFLAGS, &ifreq))
668                 goto out_err;
669
670         ifreq.ifr_flags |= IFF_UP;
671
672         if (ioctl(sock, SIOCSIFFLAGS, &ifreq))
673                 goto out_err;
674
675         close(sock);
676         return 0;
677
678 out_err:
679         close(sock);
680         return -1;
681 }
682
683 static int ws80211_create_on_demand_interface(const char *name)
684 {
685         int devidx, phyidx, err;
686         struct nl_msg *msg;
687         struct nl_cb *cb;
688
689         devidx = if_nametoindex(name);
690         if (devidx)
691                 return ws80211_iface_up(name);
692
693         if (sscanf(name, "phy%d.mon", &phyidx) != 1)
694                 return -EINVAL;
695
696         cb = nl_cb_alloc(NL_CB_DEFAULT);
697         msg = nlmsg_alloc();
698         if (!msg) {
699                 fprintf(stderr, "failed to allocate netlink message\n");
700                 return 2;
701         }
702
703         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
704                     0, NL80211_CMD_NEW_INTERFACE, 0);
705         NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, phyidx);
706
707         NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, name);
708         NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
709
710         err = nl80211_do_cmd(msg, cb);
711         if (err)
712                 return err;
713         return ws80211_iface_up(name);
714
715 nla_put_failure:
716         fprintf(stderr, "building message failed\n");
717         return 2;
718 }
719
720 int ws80211_set_freq(const char *name, int freq, int chan_type)
721 {
722         int devidx, err;
723         struct nl_msg *msg;
724         struct nl_cb *cb;
725
726         err = ws80211_create_on_demand_interface(name);
727         if (err)
728                 return err;
729
730         msg = nlmsg_alloc();
731         if (!msg) {
732                 fprintf(stderr, "failed to allocate netlink message\n");
733                 return 2;
734         }
735
736         cb = nl_cb_alloc(NL_CB_DEFAULT);
737
738         devidx = if_nametoindex(name);
739
740 #ifdef HAVE_NL80211_CMD_SET_CHANNEL
741         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
742                     0, NL80211_CMD_SET_CHANNEL, 0);
743 #else
744         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
745                     0, NL80211_CMD_SET_WIPHY, 0);
746 #endif
747
748         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
749         NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
750
751         switch (chan_type) {
752
753 #ifdef NL80211_BAND_ATTR_HT_CAPA
754         case WS80211_CHAN_NO_HT:
755                 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_NO_HT);
756                 break;
757
758         case WS80211_CHAN_HT20:
759                 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT20);
760                 break;
761
762         case WS80211_CHAN_HT40MINUS:
763                 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT40MINUS);
764                 break;
765
766         case WS80211_CHAN_HT40PLUS:
767                 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT40PLUS);
768                 break;
769 #endif
770
771         default:
772                 break;
773         }
774         err = nl80211_do_cmd(msg, cb);
775         return err;
776
777 nla_put_failure:
778         fprintf(stderr, "building message failed\n");
779         return 2;
780
781 }
782
783 GArray* ws80211_find_interfaces(void)
784 {
785         GArray *interfaces;
786
787         if (!nl_state.nl_sock)
788                 return NULL;
789
790         interfaces = g_array_new(FALSE, FALSE, sizeof(struct ws80211_interface *));
791         if (!interfaces)
792                 return NULL;
793
794         if (ws80211_populate_devices(interfaces)) {
795                 ws80211_free_interfaces(interfaces);
796                 return NULL;
797         }
798         return interfaces;
799 }
800
801 int
802 ws80211_str_to_chan_type(const gchar *s)
803 {
804         int ret = -1;
805         if (!s)
806                 return -1;
807
808         if (!strcmp(s, CHAN_NO_HT))
809                 ret = WS80211_CHAN_NO_HT;
810         if (!strcmp(s, CHAN_HT20))
811                 ret = WS80211_CHAN_HT20;
812         if (!strcmp(s, CHAN_HT40MINUS))
813                 ret = WS80211_CHAN_HT40MINUS;
814         if (!strcmp(s, CHAN_HT40PLUS))
815                 ret = WS80211_CHAN_HT40PLUS;
816         return ret;
817 }
818
819 const gchar
820 *ws80211_chan_type_to_str(int type)
821 {
822         switch (type) {
823         case WS80211_CHAN_NO_HT:
824                 return CHAN_NO_HT;
825         case WS80211_CHAN_HT20:
826                 return CHAN_HT20;
827         case WS80211_CHAN_HT40MINUS:
828                 return CHAN_HT40MINUS;
829         case WS80211_CHAN_HT40PLUS:
830                 return CHAN_HT40PLUS;
831         }
832         return NULL;
833 }
834
835 gboolean ws80211_has_fcs_filter(void)
836 {
837         return FALSE;
838 }
839
840 int ws80211_set_fcs_validation(const char *name _U_, enum ws80211_fcs_validation fcs_validation _U_)
841 {
842         return -1;
843 }
844
845 const char *network_manager_path = "/usr/sbin/NetworkManager"; /* Is this correct? */
846 const char *ws80211_get_helper_path(void) {
847         if (g_file_test(network_manager_path, G_FILE_TEST_IS_EXECUTABLE)) {
848                 return network_manager_path;
849         }
850         return NULL;
851 }
852
853 #elif defined(HAVE_AIRPCAP)
854
855 #include <wsutil/unicode-utils.h>
856
857 #include "airpcap.h"
858 #include "airpcap_loader.h"
859
860 int ws80211_init(void)
861 {
862         if (airpcap_get_dll_state() == AIRPCAP_DLL_OK) {
863                 return 0;
864         }
865         return -1;
866 }
867
868 static const char *airpcap_dev_prefix_ = "\\\\.\\";
869
870 GArray* ws80211_find_interfaces(void)
871 {
872         GArray *interfaces;
873         GList *airpcap_if_list, *cur_if;
874         int err;
875         gchar *err_str = NULL;
876
877         interfaces = g_array_new(FALSE, FALSE, sizeof(struct ws80211_interface *));
878         if (!interfaces)
879                 return NULL;
880
881         airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
882
883         if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
884                 g_free(err_str);
885                 g_array_free(interfaces, TRUE);
886                 return NULL;
887         }
888
889         for (cur_if = airpcap_if_list; cur_if; cur_if = g_list_next(cur_if)) {
890                 struct ws80211_interface *iface;
891                 airpcap_if_info_t *airpcap_if_info = (airpcap_if_info_t *) cur_if->data;
892                 char *ifname;
893                 guint32 chan;
894                 guint32 i;
895
896                 if (!airpcap_if_info) continue;
897                 ifname = airpcap_if_info->name;
898                 if (strlen(ifname) > 4 && g_str_has_prefix(ifname, airpcap_dev_prefix_)) ifname += 4;
899
900                 iface = (struct ws80211_interface *)g_malloc0(sizeof(*iface));
901                 iface->ifname = g_strdup(ifname);
902                 iface->can_set_freq = TRUE;
903                 iface->frequencies = g_array_new(FALSE, FALSE, sizeof(guint32));
904
905                 iface->channel_types = 1 << WS80211_CHAN_NO_HT;
906                 /*
907                  * AirPcap stores per-channel capabilities. We should probably
908                  * do the same. */
909                 for (i = 0; i < airpcap_if_info->numSupportedChannels; i++) {
910                         if (airpcap_if_info->pSupportedChannels[i].Flags & FLAG_CAN_BE_HIGH) {
911                                 iface->channel_types |= 1 << WS80211_CHAN_HT40MINUS;
912                                 iface->channel_types |= 1 << WS80211_CHAN_HT40PLUS;
913                                 break;
914                         }
915                 }
916
917                 iface->cap_monitor = 1;
918
919                 for (chan = 0; chan < airpcap_if_info->numSupportedChannels; chan++) {
920                         g_array_append_val(iface->frequencies, airpcap_if_info->pSupportedChannels[chan].Frequency);
921                 }
922
923                 g_array_append_val(interfaces, iface);
924         }
925
926         return interfaces;
927 }
928
929 int ws80211_get_iface_info(const char *name, struct ws80211_iface_info *iface_info)
930 {
931         GList *airpcap_if_list;
932         int err;
933         gchar *err_str = NULL;
934         airpcap_if_info_t *airpcap_if_info;
935
936         if (!iface_info) return -1;
937
938         airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
939
940         if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
941                 g_free(err_str);
942                 return -1;
943         }
944
945         airpcap_if_info = get_airpcap_if_from_name(airpcap_if_list, name);
946
947         if (!airpcap_if_info) {
948                 free_airpcap_interface_list(airpcap_if_list);
949                 return -1;
950         }
951
952         memset(iface_info, 0, sizeof(*iface_info));
953         iface_info->current_freq = airpcap_if_info->channelInfo.Frequency;
954         switch (airpcap_if_info->channelInfo.ExtChannel) {
955                 case 0:
956                         iface_info->current_chan_type = WS80211_CHAN_NO_HT;
957                         break;
958                 case -1:
959                         iface_info->current_chan_type = WS80211_CHAN_HT40MINUS;
960                         break;
961                 case 1:
962                         iface_info->current_chan_type = WS80211_CHAN_HT40PLUS;
963                         break;
964                 default:
965                         return -1;
966         }
967
968         switch (airpcap_if_info->CrcValidationOn) {
969                 case AIRPCAP_VT_ACCEPT_CORRECT_FRAMES:
970                         iface_info->current_fcs_validation = WS80211_FCS_VALID;
971                         break;
972                 case AIRPCAP_VT_ACCEPT_CORRUPT_FRAMES:
973                         iface_info->current_fcs_validation = WS80211_FCS_INVALID;
974                         break;
975                 default:
976                         iface_info->current_fcs_validation = WS80211_FCS_ALL;
977                         break;
978         }
979
980         return 0;
981 }
982
983 int ws80211_set_freq(const char *name, int freq, int chan_type)
984 {
985         GList *airpcap_if_list;
986         int err;
987         gchar *err_str = NULL;
988         airpcap_if_info_t *airpcap_if_info;
989         gchar err_buf[AIRPCAP_ERRBUF_SIZE];
990         PAirpcapHandle adapter;
991         int ret_val = -1;
992
993         airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
994
995         if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
996                 g_free(err_str);
997                 return ret_val;
998         }
999
1000         airpcap_if_info = get_airpcap_if_from_name(airpcap_if_list, name);
1001
1002         if (!airpcap_if_info) {
1003                 free_airpcap_interface_list(airpcap_if_list);
1004                 return ret_val;
1005         }
1006
1007         adapter = airpcap_if_open(airpcap_if_info->name, err_buf);
1008         if (adapter) {
1009                 airpcap_if_info->channelInfo.Frequency = freq;
1010                 switch (chan_type) {
1011                         case WS80211_CHAN_HT40MINUS:
1012                                 airpcap_if_info->channelInfo.ExtChannel = -1;
1013                                 break;
1014                         case WS80211_CHAN_HT40PLUS:
1015                                 airpcap_if_info->channelInfo.ExtChannel = 1;
1016                                 break;
1017                         default:
1018                                 airpcap_if_info->channelInfo.ExtChannel = 0;
1019                                 break;
1020                 }
1021
1022                 if (airpcap_if_set_device_channel_ex(adapter, airpcap_if_info->channelInfo)) {
1023                         ret_val = 0;
1024                 }
1025                 airpcap_if_close(adapter);
1026         }
1027
1028         free_airpcap_interface_list(airpcap_if_list);
1029         return ret_val;
1030 }
1031
1032 int ws80211_str_to_chan_type(const gchar *s _U_)
1033 {
1034         return -1;
1035 }
1036
1037 const gchar *ws80211_chan_type_to_str(int type _U_)
1038 {
1039         return NULL;
1040 }
1041
1042 gboolean ws80211_has_fcs_filter(void)
1043 {
1044         return TRUE;
1045 }
1046
1047 int ws80211_set_fcs_validation(const char *name, enum ws80211_fcs_validation fcs_validation)
1048 {
1049         GList *airpcap_if_list;
1050         int err;
1051         gchar *err_str = NULL;
1052         airpcap_if_info_t *airpcap_if_info;
1053         gchar err_buf[AIRPCAP_ERRBUF_SIZE];
1054         PAirpcapHandle adapter;
1055         int ret_val = -1;
1056
1057         airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
1058
1059         if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
1060                 g_free(err_str);
1061                 return ret_val;
1062         }
1063
1064         airpcap_if_info = get_airpcap_if_from_name(airpcap_if_list, name);
1065
1066         if (!airpcap_if_info) {
1067                 free_airpcap_interface_list(airpcap_if_list);
1068                 return ret_val;
1069         }
1070
1071         adapter = airpcap_if_open(airpcap_if_info->name, err_buf);
1072         if (adapter) {
1073                 AirpcapValidationType val_type = AIRPCAP_VT_ACCEPT_EVERYTHING;
1074                 switch (fcs_validation) {
1075                         case WS80211_FCS_VALID:
1076                                 val_type = AIRPCAP_VT_ACCEPT_CORRECT_FRAMES;
1077                                 break;
1078                         case WS80211_FCS_INVALID:
1079                                 val_type = AIRPCAP_VT_ACCEPT_CORRUPT_FRAMES;
1080                                 break;
1081                         default:
1082                                 break;
1083                 }
1084
1085                 if (airpcap_if_set_fcs_validation(adapter, val_type)) {
1086                         /* Appears to be necessary for this to take effect. */
1087                         airpcap_if_store_cur_config_as_adapter_default(adapter);
1088                         ret_val = 0;
1089                 }
1090                 airpcap_if_close(adapter);
1091         }
1092
1093         free_airpcap_interface_list(airpcap_if_list);
1094         return ret_val;
1095 }
1096
1097 static char *airpcap_conf_path = NULL;
1098 const char *ws80211_get_helper_path(void)
1099 {
1100         HKEY h_key = NULL;
1101
1102         if (!airpcap_conf_path && RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\AirPcap"), 0, KEY_QUERY_VALUE|KEY_WOW64_32KEY, &h_key) == ERROR_SUCCESS) {
1103                 DWORD reg_ret;
1104                 TCHAR airpcap_dir_utf16[MAX_PATH];
1105                 DWORD ad_size = sizeof(airpcap_dir_utf16)/sizeof(TCHAR);
1106
1107                 reg_ret = RegQueryValueEx(h_key, NULL, NULL, NULL,
1108                                 (LPBYTE) &airpcap_dir_utf16, &ad_size);
1109
1110                 if (reg_ret == ERROR_SUCCESS) {
1111                         airpcap_dir_utf16[ad_size-1] = L'\0';
1112                         g_free(airpcap_conf_path);
1113                         airpcap_conf_path = g_strdup_printf("%s\\AirpcapConf.exe", utf_16to8(airpcap_dir_utf16));
1114
1115                         if (!g_file_test(airpcap_conf_path, G_FILE_TEST_IS_EXECUTABLE)) {
1116                                 g_free(airpcap_conf_path);
1117                                 airpcap_conf_path = NULL;
1118                         }
1119                 }
1120         }
1121
1122         return airpcap_conf_path;
1123 }
1124
1125 #else /* Everyone else. */
1126 int ws80211_init(void)
1127 {
1128         return -1;
1129 }
1130
1131 GArray* ws80211_find_interfaces(void)
1132 {
1133         return NULL;
1134 }
1135
1136 int ws80211_get_iface_info(const char *name _U_, struct ws80211_iface_info *iface_info _U_)
1137 {
1138         return -1;
1139 }
1140
1141 int ws80211_set_freq(const char *name _U_, int freq _U_, int _U_ chan_type)
1142 {
1143         return -1;
1144 }
1145
1146 int ws80211_str_to_chan_type(const gchar *s _U_)
1147 {
1148         return -1;
1149 }
1150
1151 const gchar *ws80211_chan_type_to_str(int type _U_)
1152 {
1153         return NULL;
1154 }
1155
1156 gboolean ws80211_has_fcs_filter(void)
1157 {
1158         return FALSE;
1159 }
1160
1161 int ws80211_set_fcs_validation(const char *name _U_, enum ws80211_fcs_validation fcs_validation _U_)
1162 {
1163         return -1;
1164 }
1165
1166 const char *ws80211_get_helper_path(void) {
1167         return NULL;
1168 }
1169
1170 #endif /* HAVE_LIBNL && HAVE_NL80211 */
1171
1172 /* Common to everyone */
1173
1174 void ws80211_free_interfaces(GArray *interfaces)
1175 {
1176         struct ws80211_interface *iface;
1177
1178         if (!interfaces)
1179                 return;
1180
1181         while (interfaces->len) {
1182                 iface = g_array_index(interfaces, struct ws80211_interface *, 0);
1183                 g_array_remove_index(interfaces, 0);
1184                 g_array_free(iface->frequencies, TRUE);
1185                 g_free(iface->ifname);
1186                 g_free(iface);
1187         }
1188         g_array_free(interfaces, TRUE);
1189 }
1190
1191 /*
1192  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1193  *
1194  * Local variables:
1195  * c-basic-offset: 8
1196  * tab-width: 8
1197  * indent-tabs-mode: t
1198  * End:
1199  *
1200  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1201  * :indentSize=8:tabSize=8:noTabs=false:
1202  */