Fix mismatched function call
[platform/core/connectivity/wifi-mesh-manager.git] / src / mesh-netlink.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <glib.h>
20
21 #include <errno.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <net/if.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29
30 #include <netlink/genl/genl.h>
31 #include <netlink/genl/family.h>
32 #include <netlink/genl/ctrl.h>
33 #include <netlink/msg.h>
34 #include <netlink/attr.h>
35 #include <netlink/netlink.h>
36
37 #include "mesh.h"
38 #include "mesh-log.h"
39 #include "mesh-util.h"
40 #include "mesh-netlink.h"
41 #include "mesh-request.h"
42
43 #include "nl80211.h"
44
45 #define MESH_PARAM_HWMP_ROOTMODE  "mesh_hwmp_rootmode"
46 #define MESH_PARAM_GATE_ANNOUNCE  "mesh_gate_announcements"
47 #define MAX_MAC_ADDR_LEN  18
48 #define ETH_ALEN          6
49
50 #define BIT(x) (1ULL<<(x))
51
52 typedef enum {
53         MESH_NL_CALLBACK_FINISHED = 0,
54         MESH_NL_CALLBACK_TRYING,
55 } mesh_nl_callback_state_e;
56
57 typedef struct {
58         int nl80211_id;
59         int callback_state;
60         guint event_source;
61
62         struct nl_sock *nl_socket;
63         struct nl_msg *msg;
64         struct nl_cb *cb;
65         struct nl_cb *s_cb;
66
67         bool error_occured;
68         GList **station_list;
69         GList **mpath_list;
70 } mesh_nl_state;
71
72 typedef struct {
73         const char *group;
74         int id;
75 } multicast_group_id_args;
76
77 enum plink_state {
78         LISTEN,
79         OPN_SNT,
80         OPN_RCVD,
81         CNF_RCVD,
82         ESTAB,
83         HOLDING,
84         BLOCKED
85 };
86
87 /* For event handler */
88 static mesh_nl_state *event_state = NULL;
89
90 static int __initialize_nl80211(mesh_nl_state *state)
91 {
92         int err = MESHD_ERROR_NONE;
93
94         state->nl_socket = nl_socket_alloc();
95         if (!state->nl_socket) {
96                 MESH_LOGE("Failed to allocate netlink socket.");
97                 return MESHD_ERROR_OUT_OF_MEMORY;
98         }
99
100         if (genl_connect(state->nl_socket)) {
101                 MESH_LOGE("Failed to connect to generic netlink.");
102                 err = MESHD_ERROR_OPERATION_FAILED;
103                 goto DESTROY;
104         }
105
106         nl_socket_set_buffer_size(state->nl_socket, 8192, 8192);
107
108         state->nl80211_id = genl_ctrl_resolve(state->nl_socket, "nl80211");
109         if (state->nl80211_id < 0) {
110                 MESH_LOGE("nl80211 not found.");
111                 err = MESHD_ERROR_NO_DATA;
112                 goto DESTROY;
113         }
114
115         return 0;
116
117 DESTROY:
118         nl_socket_free(state->nl_socket);
119         return err;
120 }
121
122 static void __clean_nl80211(mesh_nl_state *state)
123 {
124         if (!state)
125                 return;
126
127         if (state->nl_socket) {
128                 nl_socket_free(state->nl_socket);
129                 state->nl_socket = NULL;
130                 state->nl80211_id = -1;
131         }
132 }
133
134 static int __get_device_index_from_string(const char* if_name, int *index)
135 {
136         int device_index = 0;
137
138         if (NULL == if_name) {
139                 MESH_LOGE("Invalid parameter");
140                 return MESHD_ERROR_INVALID_PARAMETER;
141         }
142
143         device_index = if_nametoindex(if_name);
144         if (device_index == 0) {
145                 MESH_LOGE("No interface index found [%s]", if_name);
146                 return MESHD_ERROR_NO_DATA;
147         }
148         *index = device_index;
149
150         return MESHD_ERROR_NONE;
151 }
152
153 static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
154 {
155         mesh_nl_state *state = (mesh_nl_state *)arg;
156         char buf[256] = { 0, };
157
158         NOTUSED(nla);
159
160         state->callback_state = MESH_NL_CALLBACK_FINISHED;
161         state->error_occured = TRUE;
162         strerror_r(err->error, buf, 255);
163
164         MESH_LOGD("error_handler");
165         MESH_LOGE("    %s (%d)", buf, err->error);
166
167         return NL_STOP;
168 }
169
170 static int finish_handler(struct nl_msg *msg, void *arg)
171 {
172         mesh_nl_state *state = (mesh_nl_state *)arg;
173
174         state->callback_state = MESH_NL_CALLBACK_FINISHED;
175
176         MESH_LOGD("finish_handler");
177         NOTUSED(msg);
178
179         return NL_SKIP;
180 }
181
182 static int ack_handler(struct nl_msg *msg, void *arg)
183 {
184         mesh_nl_state *state = (mesh_nl_state *)arg;
185
186         state->callback_state = MESH_NL_CALLBACK_FINISHED;
187
188         MESH_LOGD("ack_handler");
189         NOTUSED(msg);
190
191         return NL_STOP;
192 }
193
194 static int ack_simple_handler(struct nl_msg *msg, void *arg)
195 {
196         int *ret = arg;
197
198         (void) msg;
199         *ret = 0;
200
201         MESH_LOGD("ack_simple_handler");
202
203         return NL_STOP;
204 }
205
206 static int family_handler(struct nl_msg *msg, void *arg)
207 {
208         multicast_group_id_args *group = (multicast_group_id_args *)arg;
209         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
210         struct nlattr *tb[CTRL_ATTR_MAX + 1];
211         struct nlattr *mcast_group;
212         int rem_mcast_group;
213
214         MESH_LOGD("family_handler");
215
216         nla_parse(tb, CTRL_ATTR_MAX,
217                         genlmsg_attrdata(gnlh, 0),
218                         genlmsg_attrlen(gnlh, 0), NULL);
219         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
220                 return NL_SKIP;
221         }
222
223         nla_for_each_nested(mcast_group, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcast_group) {
224                 struct nlattr *tb_mcast_group[CTRL_ATTR_MCAST_GRP_MAX + 1];
225
226                 nla_parse(tb_mcast_group, CTRL_ATTR_MCAST_GRP_MAX,
227                                 nla_data(mcast_group), nla_len(mcast_group), NULL);
228
229                 if (!tb_mcast_group[CTRL_ATTR_MCAST_GRP_NAME] ||
230                                 !tb_mcast_group[CTRL_ATTR_MCAST_GRP_ID])
231                         continue;
232
233                 if (strncmp(nla_data(tb_mcast_group[CTRL_ATTR_MCAST_GRP_NAME]),
234                                 group->group,
235                                 nla_len(tb_mcast_group[CTRL_ATTR_MCAST_GRP_NAME])))
236                         continue;
237
238                 group->id = nla_get_u32(tb_mcast_group[CTRL_ATTR_MCAST_GRP_ID]);
239                 MESH_LOGD("mcast group id [%d]", group->id);
240                 break;
241         }
242
243         return NL_SKIP;
244 }
245
246 static int __nl_get_multicast_id(struct nl_sock *sock, const char *family, const char *group)
247 {
248         struct nl_msg *msg;
249         struct nl_cb *cb;
250         int ret, ctrlid;
251         multicast_group_id_args group_args = {
252                 .group = group,
253                 .id = -ENOENT,
254         };
255
256         msg = nlmsg_alloc();
257         if (!msg)
258                 return -ENOMEM;
259
260         cb = nl_cb_alloc(NL_CB_DEFAULT);
261         if (!cb) {
262                 ret = -ENOMEM;
263                 goto FAILURE;
264         }
265
266         ctrlid = genl_ctrl_resolve(sock, "nlctrl");
267
268         genlmsg_put(msg, 0, 0, ctrlid, 0,
269                     0, CTRL_CMD_GETFAMILY, 0);
270
271         ret = -ENOBUFS;
272         NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
273
274         ret = nl_send_auto(sock, msg);
275         if (ret < 0) {
276                 MESH_LOGE("Failed to nl_send_auto");
277                 goto out;
278         }
279
280         ret = 1;
281         nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
282         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_simple_handler, &ret);
283         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, family_handler, &group_args);
284
285         while (ret > 0)
286                 nl_recvmsgs(sock, cb);
287
288         if (ret == 0)
289                 ret = group_args.id;
290
291         MESH_LOGD("mcid : [%d]", ret);
292
293  nla_put_failure:
294  out:
295         nl_cb_put(cb);
296
297  FAILURE:
298         nlmsg_free(msg);
299         return ret;
300 }
301
302 static int __prepare_listen_events(mesh_nl_state *state)
303 {
304         int mcid, ret;
305
306         /* Configuration multicast group */
307         mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "config");
308         if (mcid < 0) {
309                 MESH_LOGE("Failed to get nl80211 config");
310                 return mcid;
311         }
312         MESH_LOGD("Mesh multicast id (config): [%d]", mcid);
313
314         ret = nl_socket_add_membership(state->nl_socket, mcid);
315         if (ret) {
316                 MESH_LOGE("Failed to nl_socket_add_membership");
317                 return ret;
318         }
319
320         /* Scan multicast group */
321         mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "scan");
322         if (mcid >= 0) {
323                 ret = nl_socket_add_membership(state->nl_socket, mcid);
324                 if (ret) {
325                         MESH_LOGE("Failed to nl_socket_add_membership");
326                         return ret;
327                 }
328         }
329         MESH_LOGD("Mesh multicast id (scan): [%d]", mcid);
330
331         /* Regulatory multicast group */
332         mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "regulatory");
333         if (mcid >= 0) {
334                 ret = nl_socket_add_membership(state->nl_socket, mcid);
335                 if (ret) {
336                         MESH_LOGE("Failed to nl_socket_add_membership");
337                         return ret;
338                 }
339         }
340         MESH_LOGD("Mesh multicast id (regulatory): [%d]", mcid);
341
342         /* MLME multicast group */
343         mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "mlme");
344         if (mcid >= 0) {
345                 ret = nl_socket_add_membership(state->nl_socket, mcid);
346                 if (ret) {
347                         MESH_LOGE("Failed to nl_socket_add_membership");
348                         return ret;
349                 }
350         }
351         MESH_LOGD("Mesh multicast id (mlme): [%d]", mcid);
352
353         mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "vendor");
354         if (mcid >= 0) {
355                 ret = nl_socket_add_membership(state->nl_socket, mcid);
356                 if (ret) {
357                         MESH_LOGE("Failed to nl_socket_add_membership");
358                         return ret;
359                 }
360         }
361         MESH_LOGD("Mesh multicast id (vendor): [%d]", mcid);
362
363         return 0;
364 }
365
366 static mesh_nl_state *_create_mesh_nl_state()
367 {
368         mesh_nl_state *state = g_new0(mesh_nl_state, 1);
369
370         state->nl80211_id = -1;
371         state->callback_state = MESH_NL_CALLBACK_TRYING;
372         state->error_occured = FALSE;
373
374         return state;
375 }
376
377 static void _delete_mesh_nl_state(mesh_nl_state **state)
378 {
379         if (NULL == state || NULL == *state)
380                 return;
381
382         g_free(*state);
383         *state = NULL;
384 }
385
386 static int valid_handler(struct nl_msg *msg, void *arg)
387 {
388         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
389         mesh_nl_state *state = (mesh_nl_state *)arg;
390         MESH_LOGD("valid_handler");
391
392         if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED) {
393                 MESH_LOGD("   Got NL80211_CMD_SCAN_ABORTED.");
394                 state->callback_state = MESH_NL_CALLBACK_FINISHED;
395
396                 /* Notify scan done status */
397                 mesh_notify_scan_done();
398         } else if (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
399                 MESH_LOGD("   Got NL80211_CMD_NEW_SCAN_RESULTS.");
400                 state->callback_state = MESH_NL_CALLBACK_FINISHED;
401
402                 /* Notify scan done status */
403                 mesh_notify_scan_done();
404         } else {
405                 MESH_LOGD("   Got [%d]", gnlh->cmd);
406         }
407
408         return NL_SKIP;
409 }
410
411 static int no_seq_check(struct nl_msg *msg, void *arg) {
412         NOTUSED(msg);
413         NOTUSED(arg);
414
415         return NL_OK;
416 }
417
418 static void __clean_netlink_message(mesh_nl_state *state)
419 {
420         if (!state)
421                 return;
422
423         if (state->cb)
424                 nl_cb_put(state->cb);
425         if (state->s_cb)
426                 nl_cb_put(state->s_cb);
427         if (state->msg)
428                 nlmsg_free(state->msg);
429
430         state->cb = NULL;
431         state->s_cb = NULL;
432         state->msg = NULL;
433
434         MESH_LOGD("message and callback cleaned");
435 }
436
437 static int __initialize_netlink_message(mesh_nl_state *state)
438 {
439         int err = MESHD_ERROR_NONE;
440
441         if (NULL == state) {
442                 MESH_LOGE("Invalid parameter !");
443                 return MESHD_ERROR_INVALID_PARAMETER;
444         }
445
446         /* Create netlink message */
447         state->msg = nlmsg_alloc();
448         if (NULL == state->msg) {
449                 MESH_LOGE("Failed to allocate netlink message");
450                 return MESHD_ERROR_OUT_OF_MEMORY;
451         }
452
453         /* NL_CB_DEFAULT */
454         state->cb = nl_cb_alloc(NL_CB_DEFAULT);
455         state->s_cb = nl_cb_alloc(NL_CB_DEFAULT);
456         if (!state->cb) {
457                 MESH_LOGE("Failed to allocate netlink callback");
458                 err = MESHD_ERROR_OUT_OF_MEMORY;
459                 goto DESTROY;
460         }
461
462         /* Set socket callback */
463         nl_socket_set_cb(state->nl_socket, state->s_cb);
464
465         /* Set callbacks */
466         nl_cb_err(state->cb, NL_CB_CUSTOM, error_handler, state);
467         nl_cb_set(state->cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, state);
468         nl_cb_set(state->cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, state);
469         nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, state);
470
471         MESH_LOGD("netlink socket initialized");
472
473         return MESHD_ERROR_NONE;
474
475 DESTROY:
476         __clean_netlink_message(state);
477
478         return err;
479 }
480
481 static gboolean _on_socket_event_io_received(GIOChannel *source,
482                 GIOCondition condition, gpointer data)
483 {
484         mesh_nl_state *state = (mesh_nl_state *)data;
485         int test = 0;
486
487         NOTUSED(source);
488         NOTUSED(condition);
489
490         MESH_LOGD("[Event] I/O received");
491
492         while (nl_recvmsgs_report(state->nl_socket, state->cb) > 0) {
493                 MESH_LOGD("  count [%02d]", ++test);
494         }
495
496         /* Do not remove I/O source */
497         return TRUE;
498 }
499
500 static void _on_remove_event_io_handler()
501 {
502         if(event_state) {
503                 g_source_remove(event_state->event_source);
504
505                 __clean_netlink_message(event_state);
506                 __clean_nl80211(event_state);
507                 _delete_mesh_nl_state(&event_state);
508         }
509 }
510
511 static void mac_addr_n2a(char *mac_addr, unsigned char *arg)
512 {
513         snprintf(mac_addr, MAX_MAC_ADDR_LEN+1,
514                         "%02X:%02X:%02X:%02X:%02X:%02X",
515                         arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
516 }
517
518 static char *get_chain_signal(struct nlattr *attr_list)
519 {
520         struct nlattr *attr;
521         static char buf[64];
522         char *cur = buf;
523         int i = 0, rem;
524         const char *prefix;
525
526         if (!attr_list)
527                 return (char *)"";
528
529         nla_for_each_nested(attr, attr_list, rem) {
530                 if (i++ > 0)
531                         prefix = ", ";
532                 else
533                         prefix = "[";
534
535                 cur += snprintf(cur, sizeof(buf) - (cur - buf), "%s%d", prefix,
536                                 (int8_t) nla_get_u8(attr));
537         }
538
539         if (i)
540                 snprintf(cur, sizeof(buf) - (cur - buf), "] ");
541
542         return buf;
543 }
544
545 static int parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen)
546 {
547         int rate = 0;
548         char *pos = buf;
549         struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
550         static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
551                 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
552                 [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
553                 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
554                 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
555                 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
556         };
557
558         if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, bitrate_attr, rate_policy)) {
559                 snprintf(buf, buflen, "failed to parse nested rate attributes!");
560                 return 0;
561         }
562
563         if (rinfo[NL80211_RATE_INFO_BITRATE32])
564                 rate = nla_get_u32(rinfo[NL80211_RATE_INFO_BITRATE32]);
565         else if (rinfo[NL80211_RATE_INFO_BITRATE])
566                 rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
567         if (rate > 0)
568                 pos += snprintf(pos, buflen - (pos - buf),
569                                 "%d.%d MBit/s", rate / 10, rate % 10);
570
571         if (rinfo[NL80211_RATE_INFO_MCS])
572                 pos += snprintf(pos, buflen - (pos - buf),
573                                 " MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
574         if (rinfo[NL80211_RATE_INFO_VHT_MCS])
575                 pos += snprintf(pos, buflen - (pos - buf),
576                                 " VHT-MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_MCS]));
577         if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
578                 pos += snprintf(pos, buflen - (pos - buf), " 40MHz");
579         if (rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
580                 pos += snprintf(pos, buflen - (pos - buf), " 80MHz");
581         if (rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
582                 pos += snprintf(pos, buflen - (pos - buf), " 80P80MHz");
583         if (rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
584                 pos += snprintf(pos, buflen - (pos - buf), " 160MHz");
585         if (rinfo[NL80211_RATE_INFO_SHORT_GI])
586                 pos += snprintf(pos, buflen - (pos - buf), " short GI");
587         if (rinfo[NL80211_RATE_INFO_VHT_NSS])
588                 pos += snprintf(pos, buflen - (pos - buf),
589                                 " VHT-NSS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]));
590
591         return rate;
592 }
593
594 static void parse_bss_param(struct nlattr *bss_param_attr, mesh_station_info_s *station_info)
595 {
596         struct nlattr *bss_param_info[NL80211_STA_BSS_PARAM_MAX + 1], *info;
597         static struct nla_policy bss_poilcy[NL80211_STA_BSS_PARAM_MAX + 1] = {
598                 [NL80211_STA_BSS_PARAM_CTS_PROT] = { .type = NLA_FLAG },
599                 [NL80211_STA_BSS_PARAM_SHORT_PREAMBLE] = { .type = NLA_FLAG },
600                 [NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME] = { .type = NLA_FLAG },
601                 [NL80211_STA_BSS_PARAM_DTIM_PERIOD] = { .type = NLA_U8 },
602                 [NL80211_STA_BSS_PARAM_BEACON_INTERVAL] = { .type = NLA_U16 },
603         };
604
605         if (nla_parse_nested(bss_param_info, NL80211_STA_BSS_PARAM_MAX, bss_param_attr, bss_poilcy)) {
606                 MESH_LOGE("failed to parse nested bss param attributes!");
607         }
608
609         info = bss_param_info[NL80211_STA_BSS_PARAM_DTIM_PERIOD];
610         if (info) {
611                 station_info->dtim_period = nla_get_u8(info);
612                 MESH_LOGD("    DTIM period:\t%u", station_info->dtim_period);
613         }
614         info = bss_param_info[NL80211_STA_BSS_PARAM_BEACON_INTERVAL];
615         if (info) {
616                 station_info->beacon_interval = nla_get_u16(info);
617                 MESH_LOGD("    beacon interval:%u", station_info->beacon_interval);
618         }
619         info = bss_param_info[NL80211_STA_BSS_PARAM_CTS_PROT];
620         if (info) {
621                 MESH_LOGD("    CTS protection:");
622                 if (nla_get_u16(info)) {
623                         MESH_LOGD("    yes");
624                         station_info->cts_protection = TRUE;
625                 } else {
626                         MESH_LOGD("    no");
627                         station_info->cts_protection = FALSE;
628                 }
629         }
630         info = bss_param_info[NL80211_STA_BSS_PARAM_SHORT_PREAMBLE];
631         if (info) {
632                 MESH_LOGD("    short preamble:");
633                 if (nla_get_u16(info)) {
634                         MESH_LOGD("    yes");
635                         station_info->short_preamble = TRUE;
636                 } else {
637                         MESH_LOGD("    no");
638                         station_info->short_preamble = FALSE;
639                 }
640         }
641         info = bss_param_info[NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME];
642         if (info) {
643                 MESH_LOGD("    short slot time:");
644                 if (nla_get_u16(info)) {
645                         MESH_LOGD("    yes");
646                         station_info->short_slot_time = TRUE;
647                 } else {
648                         MESH_LOGD("    no");
649                         station_info->short_slot_time = FALSE;
650                 }
651         }
652 }
653
654 static void print_power_mode(struct nlattr *a)
655 {
656         enum nl80211_mesh_power_mode pm = nla_get_u32(a);
657
658         switch (pm) {
659         case NL80211_MESH_POWER_ACTIVE:
660                 MESH_LOGD("ACTIVE");
661                 break;
662         case NL80211_MESH_POWER_LIGHT_SLEEP:
663                 MESH_LOGD("LIGHT SLEEP");
664                 break;
665         case NL80211_MESH_POWER_DEEP_SLEEP:
666                 MESH_LOGD("DEEP SLEEP");
667                 break;
668         default:
669                 MESH_LOGD("UNKNOWN");
670                 break;
671         }
672 }
673
674 static int _on_receive_station_info(struct nl_msg *msg, void *arg)
675 {
676         struct nlattr *tb[NL80211_ATTR_MAX + 1];
677         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
678         struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
679         struct nl80211_sta_flag_update *sta_flags;
680         static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
681                 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
682                 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
683                 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
684                 [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
685                 [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
686                 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
687                 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
688                 [NL80211_STA_INFO_BEACON_RX] = { .type = NLA_U64},
689                 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
690                 [NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
691                 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
692                 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
693                 [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
694                 [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
695                 [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
696                 [NL80211_STA_INFO_TX_RETRIES] = { .type = NLA_U32 },
697                 [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
698                 [NL80211_STA_INFO_BEACON_LOSS] = { .type = NLA_U32},
699                 [NL80211_STA_INFO_RX_DROP_MISC] = { .type = NLA_U64},
700                 [NL80211_STA_INFO_STA_FLAGS] =
701                         { .minlen = sizeof(struct nl80211_sta_flag_update) },
702                 [NL80211_STA_INFO_LOCAL_PM] = { .type = NLA_U32},
703                 [NL80211_STA_INFO_PEER_PM] = { .type = NLA_U32},
704                 [NL80211_STA_INFO_NONPEER_PM] = { .type = NLA_U32},
705                 [NL80211_STA_INFO_CHAIN_SIGNAL] = { .type = NLA_NESTED },
706                 [NL80211_STA_INFO_CHAIN_SIGNAL_AVG] = { .type = NLA_NESTED },
707                 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
708                 [NL80211_STA_INFO_BSS_PARAM] = { .type = NLA_NESTED },
709                 [NL80211_STA_INFO_RX_DURATION] = { .type = NLA_U64 },
710         };
711         char mac_addr[20], state_name[10], dev[20];
712         char *chain;
713         mesh_nl_state *state = (mesh_nl_state *)arg;
714         mesh_station_info_s *station_info = NULL;
715
716         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
717                         genlmsg_attrlen(gnlh, 0), NULL);
718
719         /*
720          * TODO: validate the interface and mac address!
721          * Otherwise, there's a race condition as soon as
722          * the kernel starts sending station notifications.
723          */
724
725         if (!tb[NL80211_ATTR_STA_INFO]) {
726                 MESH_LOGE("missing station stats !");
727                 return NL_SKIP;
728         }
729         if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
730                                 tb[NL80211_ATTR_STA_INFO],
731                                 stats_policy)) {
732                 MESH_LOGE("failed to parse nested attributes!");
733                 return NL_SKIP;
734         }
735
736         station_info = g_try_new0(mesh_station_info_s, 1);
737         if (NULL == station_info) {
738                 MESH_LOGE("Failed to allocate station info !");
739                 return NL_SKIP;
740         }
741
742         mac_addr_n2a(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
743         if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
744         MESH_LOGD("Station %s (on %s)", mac_addr, dev);
745         station_info->bssid = g_strdup(mac_addr);
746
747         if (sinfo[NL80211_STA_INFO_INACTIVE_TIME]) {
748                 station_info->inactive_time =
749                         nla_get_u32(sinfo[NL80211_STA_INFO_INACTIVE_TIME]);
750                 MESH_LOGE("    inactive time:\t%u ms", station_info->inactive_time);
751         }
752
753         if (sinfo[NL80211_STA_INFO_RX_BYTES64]) {
754                 station_info->rx_bytes =
755                         (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
756                 MESH_LOGE("    rx bytes:\t%llu", station_info->rx_bytes);
757         }
758         else if (sinfo[NL80211_STA_INFO_RX_BYTES]) {
759                 station_info->rx_bytes =
760                                 nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
761                 MESH_LOGD("    rx bytes:\t%u", station_info->rx_bytes);
762         }
763         if (sinfo[NL80211_STA_INFO_RX_PACKETS]) {
764                 station_info->rx_packets =
765                                 nla_get_u32(sinfo[NL80211_STA_INFO_RX_PACKETS]);
766                 MESH_LOGD("    rx packets:\t%u", station_info->rx_packets);
767         }
768
769         if (sinfo[NL80211_STA_INFO_TX_BYTES64]) {
770                 station_info->tx_bytes =
771                                 (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
772                 MESH_LOGD("    tx bytes:\t%llu", station_info->rx_packets);
773         }
774         else if (sinfo[NL80211_STA_INFO_TX_BYTES]) {
775                 station_info->tx_bytes =
776                                 nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
777                 MESH_LOGD("    tx bytes:\t%u", station_info->tx_bytes);
778         }
779         if (sinfo[NL80211_STA_INFO_TX_PACKETS]) {
780                 station_info->tx_packets =
781                                 nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]);
782                 MESH_LOGD("    tx packets:\t%u", station_info->tx_packets);
783         }
784         if (sinfo[NL80211_STA_INFO_TX_RETRIES]) {
785                 station_info->tx_retries =
786                                 nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
787                 MESH_LOGD("    tx retries:\t%u", station_info->tx_retries);
788         }
789         if (sinfo[NL80211_STA_INFO_TX_FAILED]) {
790                 station_info->tx_failed =
791                                 nla_get_u32(sinfo[NL80211_STA_INFO_TX_FAILED]);
792                 MESH_LOGD("    tx failed:\t%u", station_info->tx_failed);
793         }
794         if (sinfo[NL80211_STA_INFO_BEACON_LOSS]) {
795                 station_info->beacon_loss =
796                                 nla_get_u32(sinfo[NL80211_STA_INFO_BEACON_LOSS]);
797                 MESH_LOGD("    beacon loss:\t%u", station_info->beacon_loss);
798         }
799         if (sinfo[NL80211_STA_INFO_BEACON_RX]) {
800                 station_info->beacon_rx =
801                                 (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_BEACON_RX]);
802                 MESH_LOGD("    beacon rx:\t%llu", station_info->beacon_rx);
803         }
804         if (sinfo[NL80211_STA_INFO_RX_DROP_MISC]) {
805                 station_info->rx_drop_misc =
806                         (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_RX_DROP_MISC]);
807                 MESH_LOGD("    rx drop misc:\t%llu", station_info->rx_drop_misc);
808         }
809
810         chain = get_chain_signal(sinfo[NL80211_STA_INFO_CHAIN_SIGNAL]);
811         if (sinfo[NL80211_STA_INFO_SIGNAL]) {
812                 station_info->rssi =
813                                 (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
814                 MESH_LOGD("    signal:  \t%d %sdBm", station_info->rssi, chain);
815         }
816
817         chain = get_chain_signal(sinfo[NL80211_STA_INFO_CHAIN_SIGNAL_AVG]);
818         if (sinfo[NL80211_STA_INFO_SIGNAL_AVG]) {
819                 station_info->rssi_avg =
820                                 (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
821                 MESH_LOGD("    signal avg:\t%d %sdBm", station_info->rssi_avg, chain);
822         }
823
824         if (sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]) {
825                 station_info->beacon_signal_avg =
826                                 nla_get_u8(sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]);
827                 MESH_LOGD("    beacon signal avg:\t%d dBm", station_info->beacon_signal_avg);
828         }
829         if (sinfo[NL80211_STA_INFO_T_OFFSET]) {
830                 station_info->t_offset =
831                         (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_T_OFFSET]);
832                 MESH_LOGD("    Toffset:\t%llu us", station_info->t_offset);
833         }
834
835         if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
836                 char buf[100];
837                 station_info->tx_bitrate =
838                         parse_bitrate(sinfo[NL80211_STA_INFO_TX_BITRATE], buf, sizeof(buf));
839                 MESH_LOGD("    tx bitrate:\t%s", buf);
840         }
841
842         if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
843                 char buf[100];
844                 station_info->rx_bitrate =
845                         parse_bitrate(sinfo[NL80211_STA_INFO_RX_BITRATE], buf, sizeof(buf));
846                 MESH_LOGD("    rx bitrate:\t%s", buf);
847         }
848
849         if (sinfo[NL80211_STA_INFO_RX_DURATION]) {
850                 station_info->rx_duration =
851                         (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_RX_DURATION]);
852                 MESH_LOGD("    rx duration:\t%lld us", station_info->rx_duration);
853         }
854
855         if (sinfo[NL80211_STA_INFO_LLID]) {
856                 station_info->llid = nla_get_u16(sinfo[NL80211_STA_INFO_LLID]);
857                 MESH_LOGD("    mesh llid:\t%d", station_info->llid);
858         }
859         if (sinfo[NL80211_STA_INFO_PLID]) {
860                 station_info->llid = nla_get_u16(sinfo[NL80211_STA_INFO_PLID]);
861                 MESH_LOGD("    mesh plid:\t%d", station_info->plid);
862         }
863         if (sinfo[NL80211_STA_INFO_PLINK_STATE]) {
864                 station_info->mesh_plink =
865                                 nla_get_u8(sinfo[NL80211_STA_INFO_PLINK_STATE]);
866                 switch (station_info->mesh_plink) {
867                 case LISTEN:
868                         strcpy(state_name, "LISTEN");
869                         break;
870                 case OPN_SNT:
871                         strcpy(state_name, "OPN_SNT");
872                         break;
873                 case OPN_RCVD:
874                         strcpy(state_name, "OPN_RCVD");
875                         break;
876                 case CNF_RCVD:
877                         strcpy(state_name, "CNF_RCVD");
878                         break;
879                 case ESTAB:
880                         strcpy(state_name, "ESTAB");
881                         break;
882                 case HOLDING:
883                         strcpy(state_name, "HOLDING");
884                         break;
885                 case BLOCKED:
886                         strcpy(state_name, "BLOCKED");
887                         break;
888                 default:
889                         strcpy(state_name, "UNKNOWN");
890                         break;
891                 }
892                 MESH_LOGD("    mesh plink:\t%s", state_name);
893         }
894         if (sinfo[NL80211_STA_INFO_LOCAL_PM]) {
895                 station_info->local_ps_mode =
896                                 nla_get_u32(sinfo[NL80211_STA_INFO_LOCAL_PM]);
897                 MESH_LOGD("    mesh local PS mode:\t");
898                 print_power_mode(sinfo[NL80211_STA_INFO_LOCAL_PM]);
899         }
900         if (sinfo[NL80211_STA_INFO_PEER_PM]) {
901                 station_info->peer_ps_mode =
902                                 nla_get_u32(sinfo[NL80211_STA_INFO_PEER_PM]);
903                 MESH_LOGD("    mesh peer PS mode:\t");
904                 print_power_mode(sinfo[NL80211_STA_INFO_PEER_PM]);
905         }
906         if (sinfo[NL80211_STA_INFO_NONPEER_PM]) {
907                 station_info->non_peer_ps_mode =
908                                 nla_get_u32(sinfo[NL80211_STA_INFO_NONPEER_PM]);
909                 MESH_LOGD("    mesh non-peer PS mode:\t");
910                 print_power_mode(sinfo[NL80211_STA_INFO_NONPEER_PM]);
911         }
912
913         if (sinfo[NL80211_STA_INFO_STA_FLAGS]) {
914                 sta_flags = (struct nl80211_sta_flag_update *)
915                             nla_data(sinfo[NL80211_STA_INFO_STA_FLAGS]);
916
917                 if (sta_flags->mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
918                         MESH_LOGD("    authorized:");
919                         if (sta_flags->set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
920                                 MESH_LOGD("        yes");
921                                 station_info->authorized = TRUE;
922                         } else {
923                                 MESH_LOGD("        no");
924                                 station_info->authorized = FALSE;
925                         }
926                 }
927
928                 if (sta_flags->mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
929                         MESH_LOGD("    authenticated:");
930                         if (sta_flags->set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
931                                 MESH_LOGD("        yes");
932                                 station_info->authenticated = TRUE;
933                         } else {
934                                 MESH_LOGD("        no");
935                                 station_info->authenticated = FALSE;
936                         }
937                 }
938
939                 if (sta_flags->mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
940                         MESH_LOGD("    associated:");
941                         if (sta_flags->set & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
942                                 MESH_LOGD("        yes");
943                                 station_info->associated = TRUE;
944                         } else {
945                                 MESH_LOGD("        no");
946                                 station_info->associated = FALSE;
947                         }
948                 }
949
950                 if (sta_flags->mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
951                         MESH_LOGD("    preamble:");
952                         if (sta_flags->set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
953                                 MESH_LOGD("        short");
954                                 station_info->preamble = TRUE;
955                         } else {
956                                 MESH_LOGD("        long");
957                                 station_info->preamble = FALSE;
958                         }
959                 }
960
961                 if (sta_flags->mask & BIT(NL80211_STA_FLAG_WME)) {
962                         MESH_LOGD("    WMM/WME:");
963                         if (sta_flags->set & BIT(NL80211_STA_FLAG_WME)) {
964                                 MESH_LOGD("        yes");
965                                 station_info->wme = TRUE;
966                         } else {
967                                 MESH_LOGD("        no");
968                                 station_info->wme = FALSE;
969                         }
970                 }
971
972                 if (sta_flags->mask & BIT(NL80211_STA_FLAG_MFP)) {
973                         MESH_LOGD("    MFP:");
974                         if (sta_flags->set & BIT(NL80211_STA_FLAG_MFP)) {
975                                 MESH_LOGD("        yes");
976                                 station_info->mfp = TRUE;
977                         } else {
978                                 MESH_LOGD("        no");
979                                 station_info->mfp = FALSE;
980                         }
981                 }
982
983                 if (sta_flags->mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
984                         MESH_LOGD("    TDLS peer:");
985                         if (sta_flags->set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
986                                 MESH_LOGD("        yes");
987                                 station_info->tdls_peer = TRUE;
988                         } else {
989                                 MESH_LOGD("        no");
990                                 station_info->tdls_peer = FALSE;
991                         }
992                 }
993         }
994
995         if (sinfo[NL80211_STA_INFO_BSS_PARAM])
996                 parse_bss_param(sinfo[NL80211_STA_INFO_BSS_PARAM], station_info);
997         if (sinfo[NL80211_STA_INFO_CONNECTED_TIME]) {
998                 station_info->connected_time =
999                                 nla_get_u32(sinfo[NL80211_STA_INFO_CONNECTED_TIME]);
1000                 MESH_LOGD("    connected time:\t%u seconds", station_info->connected_time);
1001         }
1002
1003         MESH_LOGD("");
1004         *(state->station_list) = g_list_prepend(*(state->station_list), station_info);
1005
1006         return NL_SKIP;
1007 }
1008
1009 static int _on_receive_mpath_info(struct nl_msg *msg, void *arg)
1010 {
1011         struct nlattr *tb[NL80211_ATTR_MAX + 1];
1012         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1013         struct nlattr *pinfo[NL80211_MPATH_INFO_MAX + 1];
1014         char dst[20], next_hop[20], dev[20];
1015         static struct nla_policy mpath_policy[NL80211_MPATH_INFO_MAX + 1] = {
1016                 [NL80211_MPATH_INFO_FRAME_QLEN] = { .type = NLA_U32 },
1017                 [NL80211_MPATH_INFO_SN] = { .type = NLA_U32 },
1018                 [NL80211_MPATH_INFO_METRIC] = { .type = NLA_U32 },
1019                 [NL80211_MPATH_INFO_EXPTIME] = { .type = NLA_U32 },
1020                 [NL80211_MPATH_INFO_DISCOVERY_TIMEOUT] = { .type = NLA_U32 },
1021                 [NL80211_MPATH_INFO_DISCOVERY_RETRIES] = { .type = NLA_U8 },
1022                 [NL80211_MPATH_INFO_FLAGS] = { .type = NLA_U8 },
1023         };
1024
1025         mesh_nl_state *state = (mesh_nl_state *)arg;
1026         mesh_mpath_info_s *mpath_info = NULL;
1027
1028         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1029                 genlmsg_attrlen(gnlh, 0), NULL);
1030
1031         /*
1032          * TODO: validate the interface and mac address!
1033          * Otherwise, there's a race condition as soon as
1034          * the kernel starts sending mpath notifications.
1035          */
1036
1037         if (!tb[NL80211_ATTR_MPATH_INFO]) {
1038                 MESH_LOGE("missing mesh path info!");
1039                 return NL_SKIP;
1040         }
1041         if (nla_parse_nested(pinfo, NL80211_MPATH_INFO_MAX,
1042                         tb[NL80211_ATTR_MPATH_INFO],
1043                         mpath_policy)) {
1044                 MESH_LOGE("failed to parse nested attributes!");
1045                 return NL_SKIP;
1046         }
1047
1048         mpath_info = g_try_new0(mesh_mpath_info_s, 1);
1049         if (NULL == mpath_info) {
1050                 MESH_LOGE("Failed to allocate mesh path info !");
1051                 return NL_SKIP;
1052         }
1053
1054         mac_addr_n2a(dst, nla_data(tb[NL80211_ATTR_MAC]));
1055         mpath_info->dest_addr = g_strdup(dst);
1056         MESH_LOGD("Destination Address : %s", mpath_info->dest_addr);
1057
1058         mac_addr_n2a(next_hop, nla_data(tb[NL80211_ATTR_MPATH_NEXT_HOP]));
1059         mpath_info->next_hop = g_strdup(next_hop);
1060         MESH_LOGD("Next hop Address : %s", mpath_info->next_hop);
1061
1062         if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
1063         mpath_info->interface = g_strdup(dev);
1064         MESH_LOGD("Interface : %s", mpath_info->interface);
1065
1066         if (pinfo[NL80211_MPATH_INFO_SN]) {
1067                 mpath_info->sn = nla_get_u32(pinfo[NL80211_MPATH_INFO_SN]);
1068                 MESH_LOGD("SN : %u", mpath_info->sn);
1069         }
1070         if (pinfo[NL80211_MPATH_INFO_METRIC]) {
1071                 mpath_info->metric = nla_get_u32(pinfo[NL80211_MPATH_INFO_METRIC]);
1072                 MESH_LOGD("Metric : %u", mpath_info->metric);
1073         }
1074         if (pinfo[NL80211_MPATH_INFO_FRAME_QLEN]) {
1075                 mpath_info->qlen = nla_get_u32(pinfo[NL80211_MPATH_INFO_FRAME_QLEN]);
1076                 MESH_LOGD("QLEN : %u", mpath_info->qlen);
1077         }
1078         if (pinfo[NL80211_MPATH_INFO_EXPTIME]) {
1079                 mpath_info->exptime = nla_get_u32(pinfo[NL80211_MPATH_INFO_EXPTIME]);
1080                 MESH_LOGD("ExpTime : %u", mpath_info->exptime);
1081         }
1082         if (pinfo[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT]) {
1083                 mpath_info->discovery_timeout =
1084                                 nla_get_u32(pinfo[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT]);
1085                 MESH_LOGD("Discovery Timeout : %u", mpath_info->discovery_timeout);
1086         }
1087         if (pinfo[NL80211_MPATH_INFO_DISCOVERY_RETRIES]) {
1088                 mpath_info->discovery_retries =
1089                                 nla_get_u8(pinfo[NL80211_MPATH_INFO_DISCOVERY_RETRIES]);
1090                 MESH_LOGD("Discovery Retries : %u", mpath_info->discovery_retries);
1091         }
1092         if (pinfo[NL80211_MPATH_INFO_FLAGS]) {
1093                 mpath_info->flags = nla_get_u8(pinfo[NL80211_MPATH_INFO_FLAGS]);
1094                 MESH_LOGD("Flags : 0x%x", mpath_info->flags);
1095         }
1096
1097         MESH_LOGD("");
1098         *(state->mpath_list) = g_list_prepend(*(state->mpath_list), mpath_info);
1099
1100         return NL_SKIP;
1101 }
1102
1103 static int _on_receive_mesh_event(struct nl_msg *msg, void *arg)
1104 {
1105         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1106         struct nlattr *tb[NL80211_ATTR_MAX + 1];
1107         char ifname[16] = { 0, };
1108         char macbuf[6*3];
1109
1110         NOTUSED(arg);
1111
1112         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
1113
1114         if (tb[NL80211_ATTR_IFINDEX]) {
1115                 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname);
1116                 MESH_LOGD("%s: ", ifname);
1117         }
1118
1119         switch (gnlh->cmd) {
1120         case NL80211_CMD_NEW_STATION:
1121                 mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1122                 MESH_LOGD("[%s] new station [%s]", ifname, macbuf);
1123                 break;
1124         case NL80211_CMD_DEL_STATION:
1125                 mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1126                 MESH_LOGD("[%s] del station [%s]", ifname, macbuf);
1127                 break;
1128         case NL80211_CMD_NEW_MPATH:
1129                 mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1130                 MESH_LOGD("[%s] new mpath [%s]", ifname, macbuf);
1131
1132                 mesh_notify_station_joined((const char*)macbuf);
1133                 break;
1134         case NL80211_CMD_DEL_MPATH:
1135                 mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1136                 MESH_LOGD("[%s] del mpath [%s]", ifname, macbuf);
1137
1138                 mesh_notify_station_left((const char*)macbuf);
1139                 break;
1140         default:
1141                 MESH_LOGD("event [%d] is not handled", gnlh->cmd);
1142                 break;
1143         }
1144
1145         return NL_SKIP;
1146 }
1147
1148 static int _send_nl_set_mesh_parameter(const char* mesh_if_name,
1149                 const char* param_name, unsigned int value)
1150 {
1151         mesh_nl_state state = {
1152                 .nl80211_id = -1,
1153                 .callback_state = MESH_NL_CALLBACK_TRYING,
1154                 .event_source = 0,
1155                 .nl_socket = NULL,
1156                 .msg = NULL,
1157                 .cb = NULL,
1158                 .s_cb = NULL,
1159                 .error_occured = FALSE,
1160         };
1161         struct nlattr *container;
1162
1163         int err = MESHD_ERROR_NONE;
1164         int device_index = 0;
1165         int ret;
1166         int test = 0;
1167
1168         ret = __initialize_nl80211(&state);
1169         if (MESHD_ERROR_NONE != ret) {
1170                 MESH_LOGE("Failed to initialize nl80211");
1171                 return ret;
1172         }
1173
1174         ret = __initialize_netlink_message(&state);
1175         if (MESHD_ERROR_NONE != ret) {
1176                 MESH_LOGE("Failed to initialize netlink message");
1177                 goto DESTROY;
1178         }
1179
1180         /* Set command into message */
1181         genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
1182                     0, NL80211_CMD_SET_MESH_PARAMS, 0);
1183
1184         /* Add attributes into message */
1185         ret = __get_device_index_from_string(mesh_if_name, &device_index);
1186         if (MESHD_ERROR_NONE != ret) {
1187                 MESH_LOGE("Failed to get mesh device index");
1188                 err = ret;
1189                 goto DESTROY;
1190         }
1191         NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
1192
1193         container = nla_nest_start(state.msg, NL80211_ATTR_MESH_PARAMS);
1194         if (!container) {
1195                 MESH_LOGE("Failed to initialize netlink message");
1196                 goto DESTROY;
1197         }
1198
1199         /* Logic need to be changed if additional parameter is required */
1200         if (g_strcmp0(MESH_PARAM_HWMP_ROOTMODE, param_name) == 0) {
1201                 MESH_LOGD("  [mesh_hwmp_rootmode] : [%d]", value);
1202                 NLA_PUT_U8(state.msg, NL80211_MESHCONF_HWMP_ROOTMODE,
1203                                 (uint8_t)value);
1204         } else if (g_strcmp0(MESH_PARAM_GATE_ANNOUNCE, param_name) == 0) {
1205                 MESH_LOGD("  [mesh_gate_announcements] : [%d]", value);
1206                 NLA_PUT_U8(state.msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
1207                                 (uint8_t)value);
1208         } else {
1209                 MESH_LOGE("Parameter [%s] is not required !", param_name);
1210                 nla_nest_end(state.msg, container);
1211                 goto DESTROY;
1212         }
1213         nla_nest_end(state.msg, container);
1214
1215         /* Send message into kernel */
1216         ret = nl_send_auto(state.nl_socket, state.msg);
1217         if (ret < 0) {
1218                 MESH_LOGE("Failed to nl_send_auto() [%s](%d)",
1219                                 nl_geterror(ret), ret);
1220                 err = MESHD_ERROR_OPERATION_FAILED;
1221                 goto DESTROY;
1222         }
1223
1224         /* sync response */
1225         state.callback_state = MESH_NL_CALLBACK_TRYING;
1226         while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
1227                 MESH_LOGD("  count [%02d]", ++test);
1228                 nl_recvmsgs(state.nl_socket, state.cb);
1229         }
1230
1231 DESTROY:
1232         __clean_netlink_message(&state);
1233         __clean_nl80211(&state);
1234
1235         return err;
1236
1237 nla_put_failure:
1238         MESH_LOGE("Failed to message build");
1239         __clean_netlink_message(&state);
1240         __clean_nl80211(&state);
1241
1242         return MESHD_ERROR_OPERATION_FAILED;
1243 }
1244
1245 static int _send_nl_get_station_info(const char* if_name, GList **station_list)
1246 {
1247         mesh_nl_state state = {
1248                 .nl80211_id = -1,
1249                 .callback_state = MESH_NL_CALLBACK_TRYING,
1250                 .event_source = 0,
1251                 .nl_socket = NULL,
1252                 .msg = NULL,
1253                 .cb = NULL,
1254                 .s_cb = NULL,
1255                 .station_list = station_list
1256         };
1257         int err = MESHD_ERROR_NONE;
1258         int device_index = 0;
1259         int ret;
1260         int test = 0;
1261
1262         ret = __initialize_nl80211(&state);
1263         if (MESHD_ERROR_NONE != ret) {
1264                 MESH_LOGE("Failed to initialize nl80211");
1265                 return ret;
1266         }
1267
1268         ret = __initialize_netlink_message(&state);
1269         if (MESHD_ERROR_NONE != ret) {
1270                 MESH_LOGE("Failed to initialize netlink message");
1271                 goto DESTROY;
1272         }
1273
1274         /* Set command into message */
1275         genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
1276                     NLM_F_DUMP, NL80211_CMD_GET_STATION, 0);
1277
1278         /* Add attributes into message */
1279         MESH_LOGD("Dump station list with interface [%s]", if_name);
1280         ret = __get_device_index_from_string(if_name, &device_index);
1281         if (MESHD_ERROR_NONE != ret) {
1282                 MESH_LOGE("Failed to get mesh interface device index");
1283                 err = ret;
1284                 goto DESTROY;
1285         }
1286         NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
1287
1288         /* Register valid callback to dump result */
1289         nl_cb_set(state.cb, NL_CB_VALID, NL_CB_CUSTOM,
1290                         _on_receive_station_info, &state);
1291
1292         /* Send message into kernel */
1293         ret = nl_send_auto(state.nl_socket, state.msg);
1294         if (ret < 0) {
1295                 MESH_LOGE("Failed to nl_send_auto() [%s](%d)",
1296                                 nl_geterror(ret), ret);
1297                 err = MESHD_ERROR_OPERATION_FAILED;
1298                 goto DESTROY;
1299         }
1300
1301         /* sync response */
1302         state.callback_state = MESH_NL_CALLBACK_TRYING;
1303         while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
1304                 MESH_LOGD("  count [%02d]", ++test);
1305                 nl_recvmsgs(state.nl_socket, state.cb);
1306         }
1307         MESH_LOGD("Finished");
1308
1309 DESTROY:
1310         __clean_netlink_message(&state);
1311         __clean_nl80211(&state);
1312
1313         return err;
1314
1315 nla_put_failure:
1316         MESH_LOGE("Failed to message build");
1317         __clean_netlink_message(&state);
1318         __clean_nl80211(&state);
1319
1320         return MESHD_ERROR_OPERATION_FAILED;
1321 }
1322
1323 static int _send_nl_del_station_info(const char* if_name, char* peer)
1324 {
1325         mesh_nl_state state = {
1326                 .nl80211_id = -1,
1327                 .callback_state = MESH_NL_CALLBACK_FINISHED,
1328                 .event_source = 0,
1329                 .nl_socket = NULL,
1330                 .msg = NULL,
1331                 .cb = NULL,
1332                 .s_cb = NULL,
1333                 .station_list = NULL,
1334         };
1335         int err = MESHD_ERROR_NONE;
1336         int device_index = 0;
1337         int ret;
1338
1339         ret = __initialize_nl80211(&state);
1340         if (MESHD_ERROR_NONE != ret) {
1341                 MESH_LOGE("Failed to initialize nl80211");
1342                 return ret;
1343         }
1344
1345         ret = __initialize_netlink_message(&state);
1346         if (MESHD_ERROR_NONE != ret) {
1347                 MESH_LOGE("Failed to initialize netlink message");
1348                 goto DESTROY;
1349         }
1350
1351         /* Set command into message */
1352         genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
1353                     NLM_F_DUMP, NL80211_CMD_DEL_STATION, 0);
1354
1355         /* Add attributes into message */
1356         MESH_LOGD("Delete a station [%s] with interface [%s]", peer, if_name);
1357         ret = __get_device_index_from_string(if_name, &device_index);
1358         if (MESHD_ERROR_NONE != ret) {
1359                 MESH_LOGE("Failed to get mesh interface device index");
1360                 err = ret;
1361                 goto DESTROY;
1362         }
1363         NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
1364         NLA_PUT(state.msg, NL80211_ATTR_MAC, ETH_ALEN, peer);
1365
1366         /* Send message into kernel */
1367         ret = nl_send_auto(state.nl_socket, state.msg);
1368         if (ret < 0) {
1369                 MESH_LOGE("Failed to nl_send_auto() [%s](%d)",
1370                                 nl_geterror(ret), ret);
1371                 err = MESHD_ERROR_OPERATION_FAILED;
1372                 goto DESTROY;
1373         }
1374
1375 DESTROY:
1376         __clean_netlink_message(&state);
1377         __clean_nl80211(&state);
1378
1379         return err;
1380
1381 nla_put_failure:
1382         MESH_LOGE("Failed to message build");
1383         __clean_netlink_message(&state);
1384         __clean_nl80211(&state);
1385
1386         return MESHD_ERROR_OPERATION_FAILED;
1387 }
1388
1389 static int _send_nl_get_mpath_info(const char* if_name, GList **mpath_list)
1390 {
1391         mesh_nl_state state = {
1392                 .nl80211_id = -1,
1393                 .callback_state = MESH_NL_CALLBACK_TRYING,
1394                 .event_source = 0,
1395                 .nl_socket = NULL,
1396                 .msg = NULL,
1397                 .cb = NULL,
1398                 .s_cb = NULL,
1399                 .mpath_list = mpath_list
1400         };
1401         int err = MESHD_ERROR_NONE;
1402         int device_index = 0;
1403         int ret;
1404         int test = 0;
1405
1406         ret = __initialize_nl80211(&state);
1407         if (MESHD_ERROR_NONE != ret) {
1408                 MESH_LOGE("Failed to initialize nl80211");
1409                 return ret;
1410         }
1411
1412         ret = __initialize_netlink_message(&state);
1413         if (MESHD_ERROR_NONE != ret) {
1414                 MESH_LOGE("Failed to initialize netlink message");
1415                 goto DESTROY;
1416         }
1417
1418         /* Set command into message */
1419         genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
1420                     NLM_F_DUMP, NL80211_CMD_GET_MPATH, 0);
1421
1422         /* Add attributes into message */
1423         MESH_LOGD("Dump station list with interface [%s]", if_name);
1424         ret = __get_device_index_from_string(if_name, &device_index);
1425         if (MESHD_ERROR_NONE != ret) {
1426                 MESH_LOGE("Failed to get mesh interface device index");
1427                 err = ret;
1428                 goto DESTROY;
1429         }
1430         NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
1431
1432         /* Register valid callback to dump result */
1433         nl_cb_set(state.cb, NL_CB_VALID, NL_CB_CUSTOM,
1434                         _on_receive_mpath_info, &state);
1435
1436         /* Send message into kernel */
1437         ret = nl_send_auto(state.nl_socket, state.msg);
1438         if (ret < 0) {
1439                 MESH_LOGE("Failed to nl_send_auto() [%s](%d)",
1440                                 nl_geterror(ret), ret);
1441                 err = MESHD_ERROR_OPERATION_FAILED;
1442                 goto DESTROY;
1443         }
1444
1445         /* sync response */
1446         state.callback_state = MESH_NL_CALLBACK_TRYING;
1447         while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
1448                 MESH_LOGD("  count [%02d]", ++test);
1449                 nl_recvmsgs(state.nl_socket, state.cb);
1450         }
1451         MESH_LOGD("Finished");
1452
1453 DESTROY:
1454         __clean_netlink_message(&state);
1455         __clean_nl80211(&state);
1456
1457         return err;
1458
1459 nla_put_failure:
1460         MESH_LOGE("Failed to message build");
1461         __clean_netlink_message(&state);
1462         __clean_nl80211(&state);
1463
1464         return MESHD_ERROR_OPERATION_FAILED;
1465 }
1466
1467 static int _send_nl_register_event_handler()
1468 {
1469         int err = MESHD_ERROR_NONE;
1470         int ret;
1471         GIOChannel *recv_channel = NULL;
1472
1473         if (event_state) {
1474                 MESH_LOGE("Already event handler registered !");
1475                 return MESHD_ERROR_IN_PROGRESS;
1476         }
1477
1478         event_state = _create_mesh_nl_state("");
1479
1480         ret = __initialize_nl80211(event_state);
1481         if (MESHD_ERROR_NONE != ret) {
1482                 MESH_LOGE("Failed to initialize nl80211");
1483                 return ret;
1484         }
1485
1486         /* Subscribe multicast group should be proceed before scanning */
1487         ret = __prepare_listen_events(event_state);
1488         if (ret) {
1489                 MESH_LOGE("__prepare_listen_events : [%d]", ret);
1490                 goto DESTROY;
1491         }
1492
1493         ret = __initialize_netlink_message(event_state);
1494         if (MESHD_ERROR_NONE != ret) {
1495                 MESH_LOGE("Failed to initialize netlink message");
1496                 goto DESTROY;
1497         }
1498
1499         /* Set command into message */
1500         genlmsg_put(event_state->msg, 0, 0, event_state->nl80211_id, 0, 0, 0, 0);
1501
1502         /* Set callbacks for event handler */
1503         nl_cb_set(event_state->cb, NL_CB_VALID, NL_CB_CUSTOM,
1504                         _on_receive_mesh_event, event_state);
1505         // No sequence checking for multicast messages.
1506         nl_cb_set(event_state->cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
1507
1508         MESH_LOGD("Register event handler");
1509
1510         /* Change socket type to non-blocking */
1511         ret = nl_socket_set_nonblocking(event_state->nl_socket);
1512         if (ret < 0) {
1513                 MESH_LOGE("Failed to non-blocking socket [%s](%d)", nl_geterror(ret), ret);
1514         }
1515
1516         /* Register I/O callback to wait asynchronously */
1517         if (FALSE == event_state->error_occured) {
1518                 recv_channel = g_io_channel_unix_new(nl_socket_get_fd(event_state->nl_socket));
1519                 event_state->event_source = g_io_add_watch(recv_channel,
1520                                 (G_IO_IN | G_IO_ERR), _on_socket_event_io_received, event_state);
1521                 g_io_channel_unref(recv_channel);
1522         } else {
1523                 MESH_LOGE("Error responded. Failed to register event callback !!");
1524                 goto DESTROY;
1525         }
1526
1527         /* Resource should be free on I/O callback */
1528         return MESHD_ERROR_NONE;
1529
1530 DESTROY:
1531         __clean_netlink_message(event_state);
1532         __clean_nl80211(event_state);
1533         _delete_mesh_nl_state(&event_state);
1534
1535         return err;
1536 }
1537
1538 int mesh_netlink_set_mesh_parameter(const char* mesh_if_name,
1539                 const char* param_name, unsigned int value)
1540 {
1541         int ret = MESHD_ERROR_NONE;
1542
1543         if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
1544                 MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
1545                 return MESHD_ERROR_INVALID_PARAMETER;
1546         }
1547
1548         MESH_LOGD("Set mesh[%s] param [%s] value [%d]",
1549                         mesh_if_name, param_name, value);
1550         ret = _send_nl_set_mesh_parameter(mesh_if_name, param_name, value);
1551
1552         return ret;
1553 }
1554
1555 int mesh_netlink_get_station_info(const char* mesh_if_name, GList **station_list)
1556 {
1557         int ret = MESHD_ERROR_NONE;
1558
1559         if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
1560                 MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
1561                 return MESHD_ERROR_INVALID_PARAMETER;
1562         }
1563         if (NULL == station_list) {
1564                 MESH_LOGE("Invalid parameter [%p]", station_list);
1565                 return MESHD_ERROR_INVALID_PARAMETER;
1566         }
1567
1568         MESH_LOGD("Get connected stations");
1569         ret = _send_nl_get_station_info(mesh_if_name, station_list);
1570
1571         return ret;
1572 }
1573
1574 int mesh_netlink_del_station_info(const char* mesh_if_name, char *peer)
1575 {
1576         int ret = MESHD_ERROR_NONE;
1577
1578         if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
1579                 MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
1580                 return MESHD_ERROR_INVALID_PARAMETER;
1581         }
1582         if (NULL == peer) {
1583                 MESH_LOGE("Invalid parameter [%p]", peer);
1584                 return MESHD_ERROR_INVALID_PARAMETER;
1585         }
1586
1587         MESH_LOGD("Del connected station : [%s]", peer);
1588         ret = _send_nl_del_station_info(mesh_if_name, peer);
1589
1590         return ret;
1591 }
1592
1593 int mesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list)
1594 {
1595         int ret = MESHD_ERROR_NONE;
1596
1597         if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
1598                 MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
1599                 return MESHD_ERROR_INVALID_PARAMETER;
1600         }
1601         if (NULL == mpath_list) {
1602                 MESH_LOGE("Invalid parameter [%p]", mpath_list);
1603                 return MESHD_ERROR_INVALID_PARAMETER;
1604         }
1605
1606         MESH_LOGD("Get current mpath info");
1607         ret = _send_nl_get_mpath_info(mesh_if_name, mpath_list);
1608
1609         return ret;
1610 }
1611
1612 int mesh_netlink_register_event_handler()
1613 {
1614         int ret = MESHD_ERROR_NONE;
1615
1616         MESH_LOGD("Register mesh event handler");
1617         ret = _send_nl_register_event_handler();
1618
1619         return ret;
1620 }
1621
1622 int mesh_netlink_unregister_event_handler()
1623 {
1624         int ret = MESHD_ERROR_NONE;
1625
1626         MESH_LOGD("Unregister mesh event handler");
1627
1628         _on_remove_event_io_handler();
1629
1630         return ret;
1631 }