4c91d12492cf767f45fa2662f50c0cda78544856
[oonf.git] / src-plugins / nl80211_listener / nl80211_listener.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2013, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #define _GNU_SOURCE
43
44 /* must be first because of a problem with linux/netlink.h */
45 #include <sys/socket.h>
46
47 /* and now the rest of the includes */
48 #include <linux/types.h>
49 #include <linux/netlink.h>
50 #include <linux/genetlink.h>
51 #include "nl80211.h"
52 #include <netlink/attr.h>
53 #include <netlink/msg.h>
54
55 #include "common/autobuf.h"
56 #include "common/avl.h"
57 #include "common/avl_comp.h"
58 #include "common/common_types.h"
59 #include "common/netaddr.h"
60 #include "common/netaddr_acl.h"
61 #include "common/string.h"
62
63 #include "config/cfg.h"
64 #include "config/cfg_schema.h"
65 #include "core/oonf_logging.h"
66 #include "core/oonf_plugins.h"
67 #include "core/oonf_subsystem.h"
68 #include "subsystems/oonf_class.h"
69 #include "subsystems/oonf_clock.h"
70 #include "subsystems/oonf_interface.h"
71 #include "subsystems/oonf_layer2.h"
72 #include "subsystems/oonf_timer.h"
73 #include "subsystems/os_system.h"
74
75 #include "nl80211_listener/nl80211_listener.h"
76
77 /* definitions */
78 struct _nl80211_config {
79   uint64_t interval;
80 };
81
82 enum query_type {
83   QUERY_FIRST = 0,
84   QUERY_STATION_DUMP = 0,
85   QUERY_SCAN_DUMP,
86
87   /* must be last */
88   QUERY_COUNT,
89 };
90
91 /* prototypes */
92 static int _init(void);
93 static void _cleanup(void);
94
95 static void _cb_config_changed(void);
96 static void _send_genl_getfamily(void);
97
98 static void _cb_nl_message(struct nlmsghdr *hdr);
99 static void _cb_nl_error(uint32_t seq, int error);
100 static void _cb_nl_timeout(void);
101 static void _cb_nl_done(uint32_t seq);
102
103 static void _cb_transmission_event(void *);
104
105 /* configuration */
106 static struct cfg_schema_entry _nl80211_entries[] = {
107   CFG_MAP_CLOCK_MIN(_nl80211_config, interval, "interval", "1.0",
108       "Interval between two linklayer information updates", 100),
109 };
110
111 static struct cfg_schema_section _nl80211_section = {
112   .type = OONF_PLUGIN_GET_NAME(),
113   .cb_delta_handler = _cb_config_changed,
114   .entries = _nl80211_entries,
115   .entry_count = ARRAYSIZE(_nl80211_entries),
116 };
117
118 static struct _nl80211_config _config;
119
120 /* plugin declaration */
121 struct oonf_subsystem nl80211_listener_subsystem = {
122   .name = OONF_PLUGIN_GET_NAME(),
123   .descr = "OONF nl80211 listener plugin",
124   .author = "Henning Rogge",
125
126   .cfg_section = &_nl80211_section,
127
128   .init = _init,
129   .cleanup = _cleanup,
130 };
131 DECLARE_OONF_PLUGIN(nl80211_listener_subsystem);
132
133 /* netlink specific data */
134 static struct os_system_netlink _netlink_handler = {
135   .cb_message = _cb_nl_message,
136   .cb_error = _cb_nl_error,
137   .cb_done = _cb_nl_done,
138   .cb_timeout = _cb_nl_timeout,
139 };
140
141 static struct nlmsghdr *_msgbuf;
142
143 static int _nl80211_id = -1;
144 static bool _nl80211_mc_set = false;
145
146 static char _last_queried_if[IF_NAMESIZE];
147 static enum query_type _next_query_type;
148
149 /* timer for generating netlink requests */
150 static struct oonf_timer_info _transmission_timer_info = {
151   .name = "nl80211 listener timer",
152   .callback = _cb_transmission_event,
153   .periodic = true,
154 };
155
156 struct oonf_timer_entry _transmission_timer = {
157   .info = &_transmission_timer_info
158 };
159
160 /**
161  * Constructor of plugin
162  * @return 0 if initialization was successful, -1 otherwise
163  */
164 static int
165 _init(void) {
166   _msgbuf = calloc(1, UIO_MAXIOV);
167   if (_msgbuf == NULL) {
168     OONF_WARN(LOG_NL80211, "Not enough memory for nl80211 memory buffer");
169     return -1;
170   }
171
172   if (os_system_netlink_add(&_netlink_handler, NETLINK_GENERIC)) {
173     free(_msgbuf);
174     return -1;
175   }
176
177   oonf_timer_add(&_transmission_timer_info);
178
179   memset(_last_queried_if, 0, sizeof(_last_queried_if));
180   _next_query_type = QUERY_STATION_DUMP;
181
182   _send_genl_getfamily();
183   return 0;
184 }
185
186 /**
187  * Destructor of plugin
188  */
189 static void
190 _cleanup(void) {
191   oonf_timer_stop(&_transmission_timer);
192   oonf_timer_remove(&_transmission_timer_info);
193   os_system_netlink_remove(&_netlink_handler);
194
195   free (_msgbuf);
196 }
197
198 /**
199  * Parse the netlink message result that contains the list of available
200  * generic netlink families of the kernel.
201  * @param hdr pointer to netlink message
202  */
203 static void
204 _parse_cmd_newfamily(struct nlmsghdr *hdr) {
205   static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
206     [CTRL_ATTR_FAMILY_ID]    = { .type = NLA_U16 },
207     [CTRL_ATTR_FAMILY_NAME]  = { .type = NLA_STRING, .maxlen = GENL_NAMSIZ },
208     [CTRL_ATTR_VERSION]      = { .type = NLA_U32 },
209     [CTRL_ATTR_HDRSIZE]      = { .type = NLA_U32 },
210     [CTRL_ATTR_MAXATTR]      = { .type = NLA_U32 },
211     [CTRL_ATTR_OPS]          = { .type = NLA_NESTED },
212     [CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED },
213   };
214   struct nlattr *attrs[CTRL_ATTR_MAX+1];
215   struct nlattr *mcgrp;
216   int iterator;
217
218   if (nlmsg_parse(hdr, sizeof(struct genlmsghdr),
219       attrs, CTRL_ATTR_MAX, ctrl_policy) < 0) {
220     OONF_WARN(LOG_NL80211, "Cannot parse netlink CTRL_CMD_NEWFAMILY message");
221     return;
222   }
223
224   if (attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
225     OONF_WARN(LOG_NL80211, "Missing Family ID in CTRL_CMD_NEWFAMILY");
226     return;
227   }
228   if (attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
229     OONF_WARN(LOG_NL80211, "Missing Family Name in CTRL_CMD_NEWFAMILY");
230     return;
231   }
232   if (strcmp(nla_get_string(attrs[CTRL_ATTR_FAMILY_NAME]), "nl80211") != 0) {
233     /* not interested in this one */
234     return;
235   }
236   _nl80211_id = nla_get_u32(attrs[CTRL_ATTR_FAMILY_ID]);
237
238   if (_nl80211_mc_set || !attrs[CTRL_ATTR_MCAST_GROUPS]) {
239     /* no multicast groups */
240     return;
241   }
242
243   nla_for_each_nested(mcgrp, attrs[CTRL_ATTR_MCAST_GROUPS], iterator) {
244     struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
245     uint32_t group;
246
247     nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX,
248         nla_data(mcgrp), nla_len(mcgrp), NULL);
249
250     if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] ||
251         !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
252       continue;
253
254     if (strcmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]), "mlme"))
255       continue;
256
257     group = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
258     OONF_DEBUG(LOG_NL80211, "Found multicast group %s: %d",
259         (char *)nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
260         group);
261
262     if (os_system_netlink_add_mc(&_netlink_handler, &group, 1)) {
263       OONF_WARN(LOG_NL80211,
264           "Could not activate multicast group %d for nl80211", group);
265     }
266     else {
267       _nl80211_mc_set = true;
268     }
269     break;
270   }
271 }
272
273 /**
274  * Parse result of station dump nl80211 command
275  * @param hdr pointer to netlink message
276  */
277 static void
278 _parse_cmd_new_station(struct nlmsghdr *hdr) {
279   static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
280     [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
281     [NL80211_STA_INFO_RX_BYTES]      = { .type = NLA_U32 },
282     [NL80211_STA_INFO_TX_BYTES]      = { .type = NLA_U32 },
283     [NL80211_STA_INFO_RX_PACKETS]    = { .type = NLA_U32 },
284     [NL80211_STA_INFO_TX_PACKETS]    = { .type = NLA_U32 },
285     [NL80211_STA_INFO_SIGNAL]        = { .type = NLA_U8 },
286     [NL80211_STA_INFO_RX_BITRATE]    = { .type = NLA_NESTED },
287     [NL80211_STA_INFO_TX_BITRATE]    = { .type = NLA_NESTED },
288     [NL80211_STA_INFO_LLID]          = { .type = NLA_U16 },
289     [NL80211_STA_INFO_PLID]          = { .type = NLA_U16 },
290     [NL80211_STA_INFO_PLINK_STATE]   = { .type = NLA_U8 },
291     [NL80211_STA_INFO_TX_RETRIES]    = { .type = NLA_U32 },
292     [NL80211_STA_INFO_TX_FAILED]     = { .type = NLA_U32 },
293   };
294   static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
295     [NL80211_RATE_INFO_BITRATE]      = { .type = NLA_U16 },
296     [NL80211_RATE_INFO_MCS]          = { .type = NLA_U8 },
297     [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
298     [NL80211_RATE_INFO_SHORT_GI]     = { .type = NLA_FLAG },
299   };
300
301   struct nlattr *tb[NL80211_ATTR_MAX + 1];
302   struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
303   struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
304
305   struct oonf_interface_data *if_data;
306   struct oonf_layer2_neighbor *neigh;
307   struct netaddr mac;
308   unsigned if_index;
309   char if_name[IF_NAMESIZE];
310
311 #ifdef OONF_LOG_DEBUG_INFO
312   struct netaddr_str buf1, buf2;
313 #endif
314
315   if (nlmsg_parse(hdr, sizeof(struct genlmsghdr),
316       tb, NL80211_ATTR_MAX, NULL) < 0) {
317     OONF_WARN(LOG_NL80211, "Cannot parse netlink NL80211_CMD_NEW_STATION message");
318     return;
319   }
320
321   if (!tb[NL80211_ATTR_STA_INFO]) {
322     OONF_WARN(LOG_NL80211, "Cannot find station info attribute");
323     return;
324   }
325   if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
326            tb[NL80211_ATTR_STA_INFO], stats_policy)) {
327     OONF_WARN(LOG_NL80211, "Cannot parse station info attribute");
328     return;
329   }
330
331   netaddr_from_binary(&mac, nla_data(tb[NL80211_ATTR_MAC]), 6, AF_MAC48);
332   if_index = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
333
334   if (if_indextoname(if_index, if_name) == NULL) {
335     return;
336   }
337
338   if_data = oonf_interface_get_data(if_name, NULL);
339   if (if_data == NULL || netaddr_get_address_family(&if_data->mac) == AF_UNSPEC) {
340     return;
341   }
342
343   OONF_DEBUG(LOG_NL80211, "Add neighbor %s for network %s",
344       netaddr_to_string(&buf1, &mac), netaddr_to_string(&buf2, &if_data->mac));
345
346   neigh = oonf_layer2_add_neighbor(&if_data->mac, &mac, if_index,
347       _config.interval + _config.interval / 4);
348   if (neigh == NULL) {
349     OONF_WARN(LOG_NL80211, "Not enough memory for new layer2 neighbor");
350     return;
351   }
352
353   /* make sure that the network is there */
354   oonf_layer2_add_network(&if_data->mac, if_index,
355         _config.interval + _config.interval / 4);
356
357   /* reset all existing data */
358   oonf_layer2_neighbor_clear(neigh);
359
360   /* insert new data */
361   if (sinfo[NL80211_STA_INFO_INACTIVE_TIME]) {
362     oonf_layer2_neighbor_set_last_seen(neigh,
363         oonf_clock_get_absolute(nla_get_u32(sinfo[NL80211_STA_INFO_INACTIVE_TIME])));
364   }
365   if (sinfo[NL80211_STA_INFO_RX_BYTES]) {
366     oonf_layer2_neighbor_set_rx_bytes(neigh,
367         nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]));
368   }
369   if (sinfo[NL80211_STA_INFO_RX_PACKETS]) {
370     oonf_layer2_neighbor_set_rx_packets(neigh,
371         nla_get_u32(sinfo[NL80211_STA_INFO_RX_PACKETS]));
372   }
373   if (sinfo[NL80211_STA_INFO_TX_BYTES]) {
374     oonf_layer2_neighbor_set_tx_bytes(neigh,
375         nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]));
376   }
377   if (sinfo[NL80211_STA_INFO_TX_PACKETS]) {
378     oonf_layer2_neighbor_set_tx_packets(neigh,
379         nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]));
380   }
381   if (sinfo[NL80211_STA_INFO_TX_RETRIES])  {
382     oonf_layer2_neighbor_set_tx_retries(neigh,
383         nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]));
384   }
385   if (sinfo[NL80211_STA_INFO_TX_FAILED]) {
386     oonf_layer2_neighbor_set_tx_fails(neigh,
387         nla_get_u32(sinfo[NL80211_STA_INFO_TX_FAILED]));
388   }
389   if (sinfo[NL80211_STA_INFO_SIGNAL])  {
390     oonf_layer2_neighbor_set_signal(neigh, (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]));
391   }
392   if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
393     if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
394              sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy) == 0) {
395       if (rinfo[NL80211_RATE_INFO_BITRATE]) {
396         uint64_t rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
397         oonf_layer2_neighbor_set_tx_bitrate(neigh, ((uint64_t)rate * 1024 * 1024) / 10);
398       }
399       /* TODO: do we need the rest of the data ? */
400 #if 0
401       if (rinfo[NL80211_RATE_INFO_MCS])
402         printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
403       if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
404         printf(" 40Mhz");
405       if (rinfo[NL80211_RATE_INFO_SHORT_GI])
406         printf(" short GI");
407 #endif
408     }
409   }
410   if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
411     if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
412              sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy) == 0) {
413       if (rinfo[NL80211_RATE_INFO_BITRATE]) {
414         uint64_t rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
415         oonf_layer2_neighbor_set_rx_bitrate(neigh, ((uint64_t)rate * 1024 * 1024) / 10);
416       }
417       /* TODO: do we need the rest of the data ? */
418 #if 0
419       if (rinfo[NL80211_RATE_INFO_MCS])
420         printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
421       if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
422         printf(" 40Mhz");
423       if (rinfo[NL80211_RATE_INFO_SHORT_GI])
424         printf(" short GI");
425 #endif
426     }
427   }
428
429   oonf_layer2_neighbor_commit(neigh);
430   return;
431 }
432
433 /**
434  * Parse result of station dump nl80211 command
435  * @param hdr pointer to netlink message
436  */
437 static void
438 _parse_cmd_del_station(struct nlmsghdr *hdr) {
439   struct nlattr *tb[NL80211_ATTR_MAX + 1];
440
441   struct oonf_interface_data *if_data;
442   struct oonf_layer2_neighbor *neigh;
443   struct netaddr mac;
444   unsigned if_index;
445   char if_name[IF_NAMESIZE];
446 #ifdef OONF_LOG_DEBUG_INFO
447   struct netaddr_str buf1, buf2;
448 #endif
449
450   if (nlmsg_parse(hdr, sizeof(struct genlmsghdr),
451       tb, NL80211_ATTR_MAX, NULL) < 0) {
452     OONF_WARN(LOG_NL80211, "Cannot parse netlink NL80211_CMD_NEW_STATION message");
453     return;
454   }
455
456   netaddr_from_binary(&mac, nla_data(tb[NL80211_ATTR_MAC]), 6, AF_MAC48);
457   if_index = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
458
459   if (if_indextoname(if_index, if_name) == NULL) {
460     return;
461   }
462   if_data = oonf_interface_get_data(if_name, NULL);
463   if (if_data == NULL || netaddr_get_address_family(&if_data->mac) == AF_UNSPEC) {
464     return;
465   }
466
467   OONF_DEBUG(LOG_NL80211, "Remove neighbor %s for network %s",
468       netaddr_to_string(&buf1, &mac), netaddr_to_string(&buf2, &if_data->mac));
469
470   neigh = oonf_layer2_get_neighbor(&if_data->mac, &mac);
471   if (neigh != NULL) {
472     oonf_layer2_remove_neighbor(neigh);
473   }
474 }
475
476 #define WLAN_CAPABILITY_ESS   (1<<0)
477 #define WLAN_CAPABILITY_IBSS    (1<<1)
478 #define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
479 #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
480 #define WLAN_CAPABILITY_PRIVACY   (1<<4)
481 #define WLAN_CAPABILITY_SHORT_PREAMBLE  (1<<5)
482 #define WLAN_CAPABILITY_PBCC    (1<<6)
483 #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
484 #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
485 #define WLAN_CAPABILITY_QOS   (1<<9)
486 #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
487 #define WLAN_CAPABILITY_APSD    (1<<11)
488 #define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
489
490 /**
491  * Parse the result of the passive scan of nl80211
492  * @param msg pointer to netlink message
493  */
494 static void
495 _parse_cmd_new_scan_result(struct nlmsghdr *msg) {
496   static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
497     [NL80211_BSS_TSF]             = { .type = NLA_U64 },
498     [NL80211_BSS_FREQUENCY]       = { .type = NLA_U32 },
499 //    [NL80211_BSS_BSSID] = { },
500     [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
501     [NL80211_BSS_CAPABILITY]      = { .type = NLA_U16 },
502 //    [NL80211_BSS_INFORMATION_ELEMENTS] = { },
503     [NL80211_BSS_SIGNAL_MBM]      = { .type = NLA_U32 },
504     [NL80211_BSS_SIGNAL_UNSPEC]   = { .type = NLA_U8 },
505     [NL80211_BSS_STATUS]          = { .type = NLA_U32 },
506     [NL80211_BSS_SEEN_MS_AGO]     = { .type = NLA_U32 },
507 //    [NL80211_BSS_BEACON_IES] = { },
508   };
509
510   struct nlattr *tb[NL80211_ATTR_MAX + 1];
511   struct nlattr *bss[NL80211_BSS_MAX + 1];
512
513   struct oonf_interface_data *if_data;
514   struct oonf_layer2_network *net;
515   struct netaddr mac;
516   unsigned if_index;
517   char if_name[IF_NAMESIZE];
518 #ifdef OONF_LOG_DEBUG_INFO
519   struct netaddr_str buf;
520 #endif
521
522   if (nlmsg_parse(msg, sizeof(struct genlmsghdr),
523       tb, NL80211_ATTR_MAX, NULL) < 0) {
524     OONF_WARN(LOG_NL80211, "Cannot parse netlink NL80211_CMD_NEW_SCAN_RESULT message");
525     return;
526   }
527
528   if (!tb[NL80211_ATTR_BSS]) {
529     OONF_WARN(LOG_NL80211, "bss info missing!\n");
530     return;
531   }
532   if (nla_parse_nested(bss, NL80211_BSS_MAX,
533            tb[NL80211_ATTR_BSS],
534            bss_policy)) {
535     OONF_WARN(LOG_NL80211, "failed to parse nested attributes!\n");
536     return;
537   }
538
539   if (!bss[NL80211_BSS_BSSID]) {
540     OONF_WARN(LOG_NL80211, "No BSSID found");
541     return;
542   }
543
544   if (!bss[NL80211_BSS_STATUS]) {
545     /* ignore different networks for the moment */
546     return;
547   }
548   netaddr_from_binary(&mac, nla_data(bss[NL80211_BSS_BSSID]), 6, AF_MAC48);
549   if_index = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
550
551   if (if_indextoname(if_index, if_name) == NULL) {
552     return;
553   }
554
555   if_data = oonf_interface_get_data(if_name, NULL);
556   if (if_data == NULL || netaddr_get_address_family(&if_data->mac) == AF_UNSPEC) {
557     return;
558   }
559
560   net = oonf_layer2_add_network(&if_data->mac, if_index,
561       _config.interval + _config.interval / 4);
562   if (net == NULL) {
563     OONF_WARN(LOG_NL80211, "Not enough memory for new layer2 network");
564     return;
565   }
566
567   OONF_DEBUG(LOG_NL80211, "Add network %s", netaddr_to_string(&buf, &if_data->mac));
568 #if 0
569   if (bss[NL80211_BSS_STATUS]) {
570     switch (nla_get_u32(bss[NL80211_BSS_STATUS])) {
571     case NL80211_BSS_STATUS_AUTHENTICATED:
572       printf(" -- authenticated");
573       break;
574     case NL80211_BSS_STATUS_ASSOCIATED:
575       printf(" -- associated");
576       break;
577     case NL80211_BSS_STATUS_IBSS_JOINED:
578       printf(" -- joined");
579       break;
580     default:
581       printf(" -- unknown status: %d",
582         nla_get_u32(bss[NL80211_BSS_STATUS]));
583       break;
584     }
585   }
586   printf("\n");
587
588   if (bss[NL80211_BSS_TSF]) {
589     unsigned long long tsf;
590     tsf = (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]);
591     printf("\tTSF: %llu usec (%llud, %.2lld:%.2llu:%.2llu)\n",
592       tsf, tsf/1000/1000/60/60/24, (tsf/1000/1000/60/60) % 24,
593       (tsf/1000/1000/60) % 60, (tsf/1000/1000) % 60);
594   }
595 #endif
596
597   if (bss[NL80211_BSS_FREQUENCY]) {
598     oonf_layer2_network_set_frequency(net,
599         nla_get_u32(bss[NL80211_BSS_FREQUENCY]) * 1000000ull);
600   }
601 #if 0
602   if (bss[NL80211_BSS_BEACON_INTERVAL])
603     printf("\tbeacon interval: %d\n",
604       nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]));
605   if (bss[NL80211_BSS_CAPABILITY]) {
606     __u16 capa = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
607     printf("\tcapability:");
608     if (capa & WLAN_CAPABILITY_ESS)
609       printf(" ESS");
610     if (capa & WLAN_CAPABILITY_IBSS)
611       printf(" IBSS");
612     if (capa & WLAN_CAPABILITY_PRIVACY)
613       printf(" Privacy");
614     if (capa & WLAN_CAPABILITY_SHORT_PREAMBLE)
615       printf(" ShortPreamble");
616     if (capa & WLAN_CAPABILITY_PBCC)
617       printf(" PBCC");
618     if (capa & WLAN_CAPABILITY_CHANNEL_AGILITY)
619       printf(" ChannelAgility");
620     if (capa & WLAN_CAPABILITY_SPECTRUM_MGMT)
621       printf(" SpectrumMgmt");
622     if (capa & WLAN_CAPABILITY_QOS)
623       printf(" QoS");
624     if (capa & WLAN_CAPABILITY_SHORT_SLOT_TIME)
625       printf(" ShortSlotTime");
626     if (capa & WLAN_CAPABILITY_APSD)
627       printf(" APSD");
628     if (capa & WLAN_CAPABILITY_DSSS_OFDM)
629       printf(" DSSS-OFDM");
630     printf(" (0x%.4x)\n", capa);
631   }
632   if (bss[NL80211_BSS_SIGNAL_MBM]) {
633     int s = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
634     printf("\tsignal: %d.%.2d dBm\n", s/100, s%100);
635   }
636   if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
637     unsigned char s = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
638     printf("\tsignal: %d/100\n", s);
639   }
640 #endif
641   if (bss[NL80211_BSS_SEEN_MS_AGO]) {
642     oonf_layer2_network_set_last_seen(net,
643         nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]));
644   }
645   if (bss[NL80211_BSS_INFORMATION_ELEMENTS] != NULL ||
646       bss[NL80211_BSS_BEACON_IES] != NULL) {
647     int len,i;
648     uint8_t *data;
649     uint8_t *rate1, *rate2;
650     uint8_t rate1_count, rate2_count;
651     uint64_t *rate;
652
653     rate1 = rate2 = NULL;
654
655     if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
656       len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
657       data = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
658     }
659     else {
660       len = nla_len(bss[NL80211_BSS_BEACON_IES]);
661       data = nla_data(bss[NL80211_BSS_BEACON_IES]);
662     }
663
664     /* collect pointers to data-rates */
665     rate1_count = 0;
666     rate2_count = 0;
667     while (len > 0) {
668       if (data[0] == 0) {
669         /* SSID */
670         char ssid[33];
671
672         memset(ssid, 0, sizeof(ssid));
673         memcpy(ssid, &data[2], data[1]);
674         oonf_layer2_network_set_ssid(net, ssid);
675       }
676       if (data[0] == 1) {
677         /* supported rates */
678         rate1 = &data[2];
679         rate1_count = data[1];
680       }
681       else if (data[0] == 50) {
682         /* extended supported rates */
683         rate2 = &data[2];
684         rate2_count = data[1];
685       }
686       len -= data[1] + 2;
687       data += data[1] + 2;
688     }
689
690     if (rate1_count + rate2_count > 0) {
691       rate = calloc(rate1_count + rate2_count, sizeof(uint64_t));
692       if (rate) {
693         len = 0;
694         for (i=0; i<rate1_count; i++) {
695           rate[len++] = (uint64_t)(rate1[i] & 0x7f) << 19;
696         }
697         for (i=0; i<rate2_count; i++) {
698           rate[len++] = (uint64_t)(rate2[i] & 0x7f) << 19;
699         }
700
701         oonf_layer2_network_set_supported_rates(net, rate, rate1_count + rate2_count);
702         free(rate);
703       }
704     }
705   }
706
707   oonf_layer2_network_commit(net);
708   return;
709 }
710
711 /**
712  * Parse an incoming netlink message from the kernel
713  * @param hdr pointer to netlink message
714  */
715 static void
716 _cb_nl_message(struct nlmsghdr *hdr) {
717   struct genlmsghdr *gen_hdr;
718
719   gen_hdr = NLMSG_DATA(hdr);
720   if (hdr->nlmsg_type == GENL_ID_CTRL && gen_hdr->cmd == CTRL_CMD_NEWFAMILY) {
721     _parse_cmd_newfamily(hdr);
722     return;
723   }
724
725   if (hdr->nlmsg_type == _nl80211_id) {
726     if (gen_hdr->cmd == NL80211_CMD_NEW_STATION) {
727       _parse_cmd_new_station(hdr);
728       return;
729     }
730     if (gen_hdr->cmd == NL80211_CMD_DEL_STATION) {
731       _parse_cmd_del_station(hdr);
732       return;
733     }
734     if (gen_hdr->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
735       _parse_cmd_new_scan_result(hdr);
736       return;
737     }
738   }
739
740   OONF_INFO(LOG_NL80211, "Unhandled incoming netlink message type %u cmd %u\n",
741       hdr->nlmsg_type, gen_hdr->cmd);
742 }
743
744 /**
745  * Request the list of generic netlink families from the kernel
746  */
747 static void
748 _send_genl_getfamily(void) {
749   struct genlmsghdr *hdr;
750
751   memset(_msgbuf, 0, UIO_MAXIOV);
752
753   /* generic netlink initialization */
754   hdr = NLMSG_DATA(_msgbuf);
755   _msgbuf->nlmsg_len = NLMSG_LENGTH(sizeof(*hdr));
756   _msgbuf->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
757
758   /* request nl80211 identifier */
759   _msgbuf->nlmsg_type = GENL_ID_CTRL;
760
761   hdr->cmd = CTRL_CMD_GETFAMILY;
762   hdr->version = 1;
763
764   os_system_netlink_send(&_netlink_handler, _msgbuf);
765 }
766
767 /**
768  * Request a station dump from nl80211
769  * @param if_idx interface index to be dumped
770  */
771 static void
772 _send_nl80211_get_station_dump(int if_idx) {
773   struct genlmsghdr *hdr;
774
775   memset(_msgbuf, 0, UIO_MAXIOV);
776
777   /* generic netlink initialization */
778   hdr = NLMSG_DATA(_msgbuf);
779   _msgbuf->nlmsg_len = NLMSG_LENGTH(sizeof(*hdr));
780   _msgbuf->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
781
782   /* get nl80211 station dump */
783   _msgbuf->nlmsg_type = _nl80211_id;
784   hdr->cmd = NL80211_CMD_GET_STATION;
785
786   /* add interface index to the request */
787   os_system_netlink_addreq(_msgbuf, NL80211_ATTR_IFINDEX, &if_idx, sizeof(if_idx));
788
789   os_system_netlink_send(&_netlink_handler, _msgbuf);
790 }
791
792 /**
793  * Request a passive scan dump from nl80211
794  * @param if_idx interface index to be dumped
795  */
796 static void
797 _send_nl80211_get_scan_dump(int if_idx) {
798   struct genlmsghdr *hdr;
799
800   memset(_msgbuf, 0, UIO_MAXIOV);
801
802   /* generic netlink initialization */
803   hdr = NLMSG_DATA(_msgbuf);
804   _msgbuf->nlmsg_len = NLMSG_LENGTH(sizeof(*hdr));
805   _msgbuf->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
806
807   /* get nl80211 station dump */
808   _msgbuf->nlmsg_type = _nl80211_id;
809   hdr->cmd = NL80211_CMD_GET_SCAN;
810
811   /* add interface index to the request */
812   os_system_netlink_addreq(_msgbuf, NL80211_ATTR_IFINDEX, &if_idx, sizeof(if_idx));
813
814   os_system_netlink_send(&_netlink_handler, _msgbuf);
815 }
816
817 /**
818  * Transmit the next netlink command to nl80211
819  * @param ptr unused
820  */
821 static void
822 _cb_transmission_event(void *ptr __attribute__((unused))) {
823   struct oonf_interface *interf;
824
825   if (_last_queried_if[0] == 0) {
826     /* get first interface */
827     interf = avl_first_element(&oonf_interface_tree, interf, _node);
828   }
829   else {
830     /* get next interface */
831     interf = avl_find_ge_element(&oonf_interface_tree, _last_queried_if, interf, _node);
832
833     if (interf != NULL && strcmp(_last_queried_if, interf->data.name) == 0) {
834       interf = avl_next_element_safe(&oonf_interface_tree, interf, _node);
835     }
836   }
837
838   if (!interf && _next_query_type < QUERY_COUNT-1) {
839     /* begin next query type */
840     _next_query_type++;
841     interf = avl_first_element(&oonf_interface_tree, interf, _node);
842   }
843
844   if (!interf) {
845     /* nothing to do anymore */
846     memset(_last_queried_if, 0, sizeof(_last_queried_if));
847     _next_query_type = QUERY_FIRST;
848     return;
849   }
850   else {
851     strscpy(_last_queried_if, interf->data.name, sizeof(_last_queried_if));
852   }
853
854   OONF_DEBUG(LOG_NL80211, "Send Query %d to NL80211 interface %s",
855       _next_query_type, interf->data.name);
856   if (_next_query_type == QUERY_STATION_DUMP) {
857     _send_nl80211_get_station_dump(interf->data.index);
858   }
859   else if (_next_query_type == QUERY_SCAN_DUMP){
860     _send_nl80211_get_scan_dump(interf->data.index);
861   }
862 }
863
864 static void
865 _cb_nl_error(uint32_t seq, int error) {
866   OONF_DEBUG(LOG_NL80211, "%u: Received error %d", seq, error);
867   _cb_transmission_event(NULL);
868 }
869
870 static void
871 _cb_nl_timeout(void) {
872   OONF_DEBUG(LOG_NL80211, "Received timeout");
873   _cb_transmission_event(NULL);
874 }
875
876 static void
877 _cb_nl_done(uint32_t seq) {
878   OONF_DEBUG(LOG_NL80211, "%u: Received done", seq);
879   _cb_transmission_event(NULL);
880 }
881
882 /**
883  * Update configuration of nl80211-listener plugin
884  */
885 static void
886 _cb_config_changed(void) {
887   if (cfg_schema_tobin(&_config, _nl80211_section.post,
888       _nl80211_entries, ARRAYSIZE(_nl80211_entries))) {
889     OONF_WARN(LOG_NL80211, "Could not convert %s config to bin",
890         OONF_PLUGIN_GET_NAME());
891     return;
892   }
893
894   /* half of them station dumps, half of them passive scans */
895   oonf_timer_start(&_transmission_timer, _config.interval);
896 }