Support for SCU/SCP Role Selection and Asynchronous Operations Window Negotiation
[metze/wireshark/wip.git] / ws80211_utils.c
1 /*
2  * ws80211 utilities
3  * Copyright 2012, Pontus Fuchs <pontus.fuchs@gmail.com>
4
5 $Id$
6
7 Parts of this file was copied from iw:
8
9 Copyright (c) 2007, 2008        Johannes Berg
10 Copyright (c) 2007              Andy Lutomirski
11 Copyright (c) 2007              Mike Kershaw
12 Copyright (c) 2008-2009         Luis R. Rodriguez
13
14 Permission to use, copy, modify, and/or distribute this software for any
15 purpose with or without fee is hereby granted, provided that the above
16 copyright notice and this permission notice appear in all copies.
17
18 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 */
26
27 #include <config.h>
28
29 #include <stdio.h>
30
31 #include <glib.h>
32 #include <glib/gstdio.h>
33
34 #include "ws80211_utils.h"
35
36 #if defined(HAVE_LIBNL) && defined(HAVE_NL80211)
37 #include <strings.h>
38 #include <errno.h>
39 #include <unistd.h>
40
41 #include <net/if.h>
42 #include <sys/ioctl.h>
43
44 #include <netlink/genl/genl.h>
45 #include <netlink/genl/family.h>
46 #include <netlink/genl/ctrl.h>
47 #include <netlink/msg.h>
48 #include <netlink/attr.h>
49
50 #include <linux/nl80211.h>
51
52 /* libnl 1.x compatibility code */
53 #ifdef HAVE_LIBNL1
54 #define nl_sock nl_handle
55 static inline struct nl_handle *nl_socket_alloc(void)
56 {
57         return nl_handle_alloc();
58 }
59
60 static inline void nl_socket_free(struct nl_sock *h)
61 {
62         nl_handle_destroy(h);
63 }
64 #endif /* HAVE_LIBNL1 */
65
66 struct nl80211_state {
67         struct nl_sock *nl_sock;
68         int nl80211_id;
69 };
70
71 static struct nl80211_state nl_state;
72
73 int ws80211_init(void)
74 {
75         int err;
76
77         struct nl80211_state *state = &nl_state;
78
79         state->nl_sock = nl_socket_alloc();
80         if (!state->nl_sock) {
81                 fprintf(stderr, "Failed to allocate netlink socket.\n");
82                 return -ENOMEM;
83         }
84
85         if (genl_connect(state->nl_sock)) {
86                 fprintf(stderr, "Failed to connect to generic netlink.\n");
87                 err = -ENOLINK;
88                 goto out_handle_destroy;
89         }
90
91         state->nl80211_id = genl_ctrl_resolve(state->nl_sock, "nl80211");
92         if (state->nl80211_id < 0) {
93                 fprintf(stderr, "nl80211 not found.\n");
94                 err = -ENOENT;
95                 goto out_handle_destroy;
96         }
97
98         return 0;
99
100  out_handle_destroy:
101         nl_socket_free(state->nl_sock);
102         state->nl_sock = 0;
103         return err;
104 }
105
106 static int error_handler(struct sockaddr_nl *nla _U_, struct nlmsgerr *err,
107                          void *arg)
108 {
109         int *ret = arg;
110         *ret = err->error;
111         return NL_STOP;
112 }
113
114 static int finish_handler(struct nl_msg *msg _U_, void *arg)
115 {
116         int *ret = arg;
117         *ret = 0;
118         return NL_SKIP;
119 }
120
121 static int ack_handler(struct nl_msg *msg _U_, void *arg)
122 {
123         int *ret = arg;
124         *ret = 0;
125         return NL_STOP;
126 }
127
128 static int nl80211_do_cmd(struct nl_msg *msg, struct nl_cb *cb)
129 {
130         int err;
131
132         if (!nl_state.nl_sock)
133                 return -ENOLINK;
134
135         err = nl_send_auto_complete(nl_state.nl_sock, msg);
136         if (err < 0)
137                 goto out;
138
139         err = 1;
140
141         nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
142         nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
143         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
144
145         while (err > 0)
146                 nl_recvmsgs(nl_state.nl_sock, cb);
147  out:
148         nl_cb_put(cb);
149
150         return err;
151 }
152
153 struct nliface_cookie
154 {
155         char *ifname;
156         GArray *interfaces;
157 };
158
159 static int get_phys_handler(struct nl_msg *msg, void *arg)
160 {
161         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
162         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
163
164         struct nliface_cookie *cookie = arg;
165
166         struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
167
168         struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
169         static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
170                 [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
171                 [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
172                 [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
173                 [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
174                 [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
175                 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
176         };
177
178         struct nlattr *nl_band;
179         struct nlattr *nl_freq;
180         struct nlattr *nl_mode;
181         int bandidx = 1;
182         int rem_band, rem_freq, rem_mode;
183         struct ws80211_interface *iface;
184         int cap_monitor = 0;
185
186         nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
187                   genlmsg_attrlen(gnlh, 0), NULL);
188
189         if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
190                 return NL_SKIP;
191
192         if (tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES]) {
193                 nla_for_each_nested(nl_mode, tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES], rem_mode) {
194                         if (nla_type(nl_mode) == NL80211_IFTYPE_MONITOR)
195                                 cap_monitor = 1;
196                 }
197         }
198         if (!cap_monitor)
199                 return NL_SKIP;
200
201         iface = g_malloc0(sizeof(*iface));
202         if (!iface)
203                 return NL_SKIP;
204
205         iface->frequencies = g_array_new(FALSE, FALSE, sizeof(int));
206         iface->channel_types = 1 << WS80211_CHAN_NO_HT;
207
208         if (tb_msg[NL80211_ATTR_WIPHY_NAME]) {
209                 iface->ifname = g_strdup_printf("%s.mon",
210                 nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]));
211         }
212
213         nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {
214                 bandidx++;
215
216                 nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
217                           nla_len(nl_band), NULL);
218
219 #ifdef NL80211_BAND_ATTR_HT_CAPA
220                 if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) {
221                         gboolean ht40;
222                         iface->channel_types |= 1 << WS80211_CHAN_HT20;
223                         ht40 = !!(nla_get_u16(tb_band[NL80211_BAND_ATTR_HT_CAPA]) & 0x02);
224                         if (ht40) {
225                                 iface->channel_types |= 1 << WS80211_CHAN_HT40MINUS;
226                                 iface->channel_types |= 1 << WS80211_CHAN_HT40PLUS;
227                         }
228                 }
229 #endif /* NL80211_BAND_ATTR_HT_CAPA */
230
231                 nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
232                         uint32_t freq;
233                         nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
234                                   nla_len(nl_freq), freq_policy);
235                         if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
236                                 continue;
237                         if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
238                                 continue;
239
240                         freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
241                         g_array_append_val(iface->frequencies, freq);
242                 }
243         }
244
245         /* Can frequency be set? Only newer versions of cfg80211 supports this */
246 #ifdef HAVE_NL80211_CMD_SET_CHANNEL
247         if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) {
248                 int cmd;
249                 struct nlattr *nl_cmd;
250                 nla_for_each_nested(nl_cmd, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS], cmd) {
251                         if(nla_get_u32(nl_cmd) == NL80211_CMD_SET_CHANNEL)
252                                 iface->can_set_freq = TRUE;
253                 }
254         }
255 #else
256         iface->can_set_freq = TRUE;
257 #endif
258         g_array_append_val(cookie->interfaces, iface);
259
260         return NL_SKIP;
261 }
262
263
264 static int ws80211_get_phys(GArray *interfaces)
265 {
266         struct nliface_cookie cookie;
267         struct nl_msg *msg;
268         struct nl_cb *cb;
269         msg = nlmsg_alloc();
270         if (!msg) {
271                 fprintf(stderr, "failed to allocate netlink message\n");
272                 return 2;
273         }
274
275         cb = nl_cb_alloc(NL_CB_DEFAULT);
276
277         cookie.interfaces = interfaces;
278
279         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
280                     NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
281
282         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_phys_handler, &cookie);
283
284         return nl80211_do_cmd(msg, cb);
285
286 }
287
288 static int get_freq_wext(const char *ifname)
289 {
290         int fd;
291         int ret = -1;
292         /* Ugly hack to avoid incuding wireless.h */
293         struct {
294                 char name1[IFNAMSIZ];
295                 __s32 m;
296                 __s16 e;
297                 __u8 i;
298                 __u8 flags;
299         } wrq;
300
301         fd = socket(AF_INET, SOCK_DGRAM, 0);
302         if (fd == -1)
303                 return -1;
304
305         g_strlcpy(wrq.name1, ifname, IFNAMSIZ);
306         /* SIOCGIWFREQ */
307         if (ioctl(fd, 0x8B05, &wrq) == 0) {
308                 if (wrq.e == 6)
309                         ret = wrq.m;
310         }
311         close(fd);
312         return ret;
313 }
314
315 struct __iface_info
316 {
317         struct ws80211_iface_info *pub;
318         int type;
319         int phyidx;
320 };
321
322 static int get_iface_info_handler(struct nl_msg *msg, void *arg)
323 {
324         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
325         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
326         struct __iface_info *iface_info = arg;
327
328         nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
329                   genlmsg_attrlen(gnlh, 0), NULL);
330
331         if (tb_msg[NL80211_ATTR_IFTYPE]) {
332                 iface_info->type = nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]);
333         }
334         if (tb_msg[NL80211_ATTR_WIPHY]) {
335                 iface_info->phyidx = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]);
336         }
337
338         if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
339                 iface_info->pub->current_freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]);
340                 iface_info->pub->current_chan_type = NL80211_CHAN_NO_HT;
341
342                 if (tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
343                         iface_info->pub->current_chan_type =  nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
344
345         }
346         return NL_SKIP;
347 }
348
349
350 static int __ws80211_get_iface_info(const char *name, struct __iface_info *iface_info)
351 {
352         int devidx;
353         struct nl_msg *msg;
354         struct nl_cb *cb;
355         msg = nlmsg_alloc();
356         if (!msg) {
357                 fprintf(stderr, "failed to allocate netlink message\n");
358                 return 2;
359         }
360
361         cb = nl_cb_alloc(NL_CB_DEFAULT);
362
363         devidx = if_nametoindex(name);
364
365         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
366                     0, NL80211_CMD_GET_INTERFACE, 0);
367         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
368
369         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_iface_info_handler, iface_info);
370
371         if (nl80211_do_cmd(msg, cb))
372                 return -1;
373
374         /* Old kernels cant get the current freq via netlink. Try WEXT too :( */
375         if (iface_info->pub->current_freq == -1)
376                 iface_info->pub->current_freq = get_freq_wext(name);
377         return 0;
378
379 nla_put_failure:
380         fprintf(stderr, "building message failed\n");
381         return -1;
382 }
383
384 int ws80211_get_iface_info(const char *name, struct ws80211_iface_info *iface_info)
385 {
386         struct __iface_info __iface_info;
387
388         memset(iface_info, 0, sizeof(*iface_info));
389         __iface_info.pub = iface_info;
390         __iface_info.type = -1;
391         __iface_info.phyidx= -1;
392         __iface_info.pub->current_freq = -1;
393         __iface_info.pub->current_chan_type = -1;
394
395         return __ws80211_get_iface_info(name, &__iface_info);
396 }
397
398 static int ws80211_populate_devices(GArray *interfaces)
399 {
400         FILE *fh;
401         char line[200];
402         char *t;
403         gchar *t2;
404         char *ret;
405         int i;
406         unsigned int j;
407
408         struct ws80211_iface_info pub;
409         struct __iface_info iface_info;
410         struct ws80211_interface *iface;
411
412         /* Get a list of phy's that can handle monitor mode */
413         ws80211_get_phys(interfaces);
414
415         fh = g_fopen("/proc/net/dev", "r");
416         if(!fh) {
417                 fprintf(stderr, "Cannot open /proc/net/dev");
418                 return -ENOENT;
419         }
420
421         /* Skip the first two lines */
422         for (i = 0; i < 2; i++) {
423                 ret = fgets(line, sizeof(line), fh);
424                 if (ret == NULL) {
425                         fprintf(stderr, "Error parsing /proc/net/dev");
426                         fclose(fh);
427                         return -1;
428                 }
429         }
430
431         /* Update names of user created monitor interfaces */
432         while(fgets(line, sizeof(line), fh)) {
433                 t = index(line, ':');
434                 if (!t)
435                         continue;
436                 *t = 0;
437                 t = line;
438                 while (*t && *t == ' ')
439                         t++;
440                 memset(&iface_info, 0, sizeof(iface_info));
441                 iface_info.pub = &pub;
442                 __ws80211_get_iface_info(t, &iface_info);
443
444                 if (iface_info.type == NL80211_IFTYPE_MONITOR) {
445                         for (j = 0; j < interfaces->len; j++) {
446                                 iface = g_array_index(interfaces, struct ws80211_interface *, j);
447                                 t2 = g_strdup_printf("phy%d.mon", iface_info.phyidx);
448                                 if (t2) {
449                                         if (!strcmp(t2, iface->ifname)) {
450                                                 g_free(iface->ifname);
451                                                 iface->ifname = g_strdup(t);
452                                         }
453                                         g_free(t2);
454                                 }
455                         }
456                 }
457         }
458         fclose(fh);
459         return 0;
460 }
461
462 static int ws80211_iface_up(const char *ifname)
463 {
464         int sock;
465         struct ifreq ifreq;
466
467         sock = socket(AF_PACKET, SOCK_RAW, 0);
468         if (sock == -1)
469                 return -1;
470
471         g_strlcpy(ifreq.ifr_name, ifname, sizeof(ifreq.ifr_name));
472
473         if (ioctl(sock, SIOCGIFFLAGS, &ifreq))
474                 goto out_err;
475
476         ifreq.ifr_flags |= IFF_UP;
477
478         if (ioctl(sock, SIOCSIFFLAGS, &ifreq))
479                 goto out_err;
480
481         close(sock);
482         return 0;
483
484 out_err:
485         close(sock);
486         return -1;
487 }
488
489 static int ws80211_create_on_demand_interface(const char *name)
490 {
491         int devidx, phyidx, err;
492         struct nl_msg *msg;
493         struct nl_cb *cb;
494
495         devidx = if_nametoindex(name);
496         if (devidx)
497                 return ws80211_iface_up(name);
498
499         if (sscanf(name, "phy%d.mon", &phyidx) != 1)
500                 return -EINVAL;
501
502         cb = nl_cb_alloc(NL_CB_DEFAULT);
503         msg = nlmsg_alloc();
504         if (!msg) {
505                 fprintf(stderr, "failed to allocate netlink message\n");
506                 return 2;
507         }
508
509         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
510                     0, NL80211_CMD_NEW_INTERFACE, 0);
511         NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, phyidx);
512
513         NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, name);
514         NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
515
516         err = nl80211_do_cmd(msg, cb);
517         if (err)
518                 return err;
519         return ws80211_iface_up(name);
520
521 nla_put_failure:
522         fprintf(stderr, "building message failed\n");
523         return 2;
524 }
525
526 int ws80211_set_freq(const char *name, int freq, int chan_type)
527 {
528         int devidx, err;
529         struct nl_msg *msg;
530         struct nl_cb *cb;
531
532         err = ws80211_create_on_demand_interface(name);
533         if (err)
534                 return err;
535
536         msg = nlmsg_alloc();
537         if (!msg) {
538                 fprintf(stderr, "failed to allocate netlink message\n");
539                 return 2;
540         }
541
542         cb = nl_cb_alloc(NL_CB_DEFAULT);
543
544         devidx = if_nametoindex(name);
545
546 #ifdef HAVE_NL80211_CMD_SET_CHANNEL
547         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
548                     0, NL80211_CMD_SET_CHANNEL, 0);
549 #else
550         genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
551                     0, NL80211_CMD_SET_WIPHY, 0);
552 #endif
553
554         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
555         NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
556
557         switch (chan_type) {
558
559 #ifdef NL80211_BAND_ATTR_HT_CAPA
560         case WS80211_CHAN_NO_HT:
561                 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_NO_HT);
562                 break;
563
564         case WS80211_CHAN_HT20:
565                 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT20);
566                 break;
567
568         case WS80211_CHAN_HT40MINUS:
569                 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT40MINUS);
570                 break;
571
572         case WS80211_CHAN_HT40PLUS:
573                 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT40PLUS);
574                 break;
575 #endif
576
577         default:
578                 break;
579         }
580         err = nl80211_do_cmd(msg, cb);
581         return err;
582
583 nla_put_failure:
584         fprintf(stderr, "building message failed\n");
585         return 2;
586
587 }
588
589 void ws80211_free_interfaces(GArray *interfaces)
590 {
591         struct ws80211_interface *iface;
592
593         if (!interfaces)
594                 return;
595
596         while (interfaces->len) {
597                 iface = g_array_index(interfaces, struct ws80211_interface *, 0);
598                 g_array_remove_index(interfaces, 0);
599                 g_array_free(iface->frequencies, TRUE);
600                 g_free(iface->ifname);
601                 g_free(iface);
602         }
603         g_array_free(interfaces, TRUE);
604 }
605
606 GArray* ws80211_find_interfaces(void)
607 {
608         GArray *interfaces;
609
610         if (!nl_state.nl_sock)
611                 return NULL;
612
613         interfaces = g_array_new(FALSE, FALSE, sizeof(struct ws80211_interface *));
614         if (!interfaces)
615                 return NULL;
616
617         if (ws80211_populate_devices(interfaces)) {
618                 ws80211_free_interfaces(interfaces);
619                 return NULL;
620         }
621         return interfaces;
622 }
623
624 int ws80211_frequency_to_channel(int freq)
625 {
626         if (freq == 2484)
627                 return 14;
628
629         if (freq < 2484)
630                 return (freq - 2407) / 5;
631
632         return freq / 5 - 1000;
633 }
634
635 int
636 ws80211_str_to_chan_type(const gchar *s)
637 {
638         int ret = -1;
639         if (!s)
640                 return -1;
641
642         if (!strcmp(s, CHAN_NO_HT))
643                 ret = WS80211_CHAN_NO_HT;
644         if (!strcmp(s, CHAN_HT20))
645                 ret = WS80211_CHAN_HT20;
646         if (!strcmp(s, CHAN_HT40MINUS))
647                 ret = WS80211_CHAN_HT40MINUS;
648         if (!strcmp(s, CHAN_HT40PLUS))
649                 ret = WS80211_CHAN_HT40PLUS;
650         return ret;
651 }
652
653 const gchar
654 *ws80211_chan_type_to_str(int type)
655 {
656         switch (type) {
657         case WS80211_CHAN_NO_HT:
658                 return CHAN_NO_HT;
659         case WS80211_CHAN_HT20:
660                 return CHAN_HT20;
661         case WS80211_CHAN_HT40MINUS:
662                 return CHAN_HT40MINUS;
663         case WS80211_CHAN_HT40PLUS:
664                 return CHAN_HT40PLUS;
665         }
666         return NULL;
667 }
668
669 #else /* HAVE_LIBNL */
670 int ws80211_init(void)
671 {
672         return -1;
673 }
674
675 GArray* ws80211_find_interfaces(void)
676 {
677         return NULL;
678 }
679
680 int ws80211_get_iface_info(const char *name _U_, struct ws80211_iface_info *iface_info _U_)
681 {
682         return -1;
683 }
684
685 void ws80211_free_interfaces(GArray *interfaces _U_)
686 {
687 };
688
689 int ws80211_frequency_to_channel(int freq _U_)
690 {
691         return -1;
692 }
693
694 int ws80211_set_freq(const char *name _U_, int freq _U_, int chan_type _U_)
695 {
696         return -1;
697 }
698
699 int ws80211_str_to_chan_type(const gchar *s _U_)
700 {
701         return -1;
702 }
703
704 const gchar *ws80211_chan_type_to_str(int type _U_)
705 {
706         return NULL;
707 }
708 #endif /* HAVE_LIBNL && HAVE_NL80211 */