• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/rpcd/iwinfo.c

  1 /*
  2  * rpcd - UBUS RPC server
  3  *
  4  *   Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
  5  *
  6  * Permission to use, copy, modify, and/or distribute this software for any
  7  * purpose with or without fee is hereby granted, provided that the above
  8  * copyright notice and this permission notice appear in all copies.
  9  *
 10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 17  */
 18 
 19 #include <sys/types.h>
 20 #include <dirent.h>
 21 #include <libubus.h>
 22 #include <iwinfo.h>
 23 #include <iwinfo/utils.h>
 24 #include <net/ethernet.h>
 25 
 26 #ifdef linux
 27 #include <netinet/ether.h>
 28 #endif
 29 
 30 #include <rpcd/plugin.h>
 31 
 32 
 33 static struct blob_buf buf;
 34 static const struct iwinfo_ops *iw;
 35 static const char *ifname;
 36 
 37 enum {
 38         RPC_D_DEVICE,
 39         __RPC_D_MAX,
 40 };
 41 
 42 static const struct blobmsg_policy rpc_device_policy[__RPC_D_MAX] = {
 43         [RPC_D_DEVICE] = { .name = "device", .type = BLOBMSG_TYPE_STRING },
 44 };
 45 
 46 enum {
 47         RPC_A_DEVICE,
 48         RPC_A_MACADDR,
 49         __RPC_A_MAX,
 50 };
 51 
 52 static const struct blobmsg_policy rpc_assoclist_policy[__RPC_A_MAX] = {
 53         [RPC_A_DEVICE] = { .name = "device", .type = BLOBMSG_TYPE_STRING },
 54         [RPC_A_MACADDR] = { .name = "mac", .type = BLOBMSG_TYPE_STRING },
 55 };
 56 
 57 enum {
 58         RPC_U_SECTION,
 59         __RPC_U_MAX
 60 };
 61 
 62 static const struct blobmsg_policy rpc_uci_policy[__RPC_U_MAX] = {
 63         [RPC_U_SECTION] = { .name = "section", .type = BLOBMSG_TYPE_STRING },
 64 };
 65 
 66 static int
 67 __rpc_iwinfo_open(struct blob_attr *device)
 68 {
 69         if (!device)
 70                 return UBUS_STATUS_INVALID_ARGUMENT;
 71 
 72         ifname = blobmsg_data(device);
 73         iw = iwinfo_backend(ifname);
 74 
 75         return iw ? UBUS_STATUS_OK : UBUS_STATUS_NOT_FOUND;
 76 }
 77 
 78 static int
 79 rpc_iwinfo_open(struct blob_attr *msg)
 80 {
 81         static struct blob_attr *tb[__RPC_D_MAX];
 82 
 83         blobmsg_parse(rpc_device_policy, __RPC_D_MAX, tb,
 84                       blob_data(msg), blob_len(msg));
 85 
 86         return __rpc_iwinfo_open(tb[RPC_D_DEVICE]);
 87 }
 88 
 89 static void
 90 rpc_iwinfo_close(void)
 91 {
 92         iw = NULL;
 93         ifname = NULL;
 94         iwinfo_finish();
 95 }
 96 
 97 static void
 98 rpc_iwinfo_call_int(const char *name, int (*func)(const char *, int *),
 99                     const char **map)
100 {
101         int rv;
102 
103         if (!func(ifname, &rv))
104         {
105                 if (!map)
106                         blobmsg_add_u32(&buf, name, rv);
107                 else
108                         blobmsg_add_string(&buf, name, map[rv]);
109         }
110 }
111 
112 static void
113 rpc_iwinfo_call_hardware_id(const char *name)
114 {
115         struct iwinfo_hardware_id ids;
116         void *c;
117 
118         if (!iw->hardware_id(ifname, (char *)&ids))
119         {
120                 c = blobmsg_open_array(&buf, name);
121 
122                 blobmsg_add_u32(&buf, NULL, ids.vendor_id);
123                 blobmsg_add_u32(&buf, NULL, ids.device_id);
124                 blobmsg_add_u32(&buf, NULL, ids.subsystem_vendor_id);
125                 blobmsg_add_u32(&buf, NULL, ids.subsystem_device_id);
126 
127                 blobmsg_close_array(&buf, c);
128         }
129 }
130 
131 static void
132 rpc_iwinfo_add_encryption(const char *name, struct iwinfo_crypto_entry *e)
133 {
134         int ciph, wpa_version;
135         void *c, *d;
136 
137         c = blobmsg_open_table(&buf, name);
138 
139         blobmsg_add_u8(&buf, "enabled", e->enabled);
140 
141         if (e->enabled)
142         {
143                 if (!e->wpa_version)
144                 {
145                         d = blobmsg_open_array(&buf, "wep");
146 
147                         if (e->auth_algs & IWINFO_AUTH_OPEN)
148                                 blobmsg_add_string(&buf, NULL, "open");
149 
150                         if (e->auth_algs & IWINFO_AUTH_SHARED)
151                                 blobmsg_add_string(&buf, NULL, "shared");
152 
153                         blobmsg_close_array(&buf, d);
154                 }
155                 else
156                 {
157                         d = blobmsg_open_array(&buf, "wpa");
158 
159                         for (wpa_version = 1; wpa_version <= 3; wpa_version++)
160                                 if (e->wpa_version & (1 << (wpa_version - 1)))
161                                         blobmsg_add_u32(&buf, NULL, wpa_version);
162 
163                         blobmsg_close_array(&buf, d);
164 
165 
166                         d = blobmsg_open_array(&buf, "authentication");
167 
168                         if (e->auth_suites & IWINFO_KMGMT_PSK)
169                                 blobmsg_add_string(&buf, NULL, "psk");
170 
171                         if (e->auth_suites & IWINFO_KMGMT_8021x)
172                                 blobmsg_add_string(&buf, NULL, "802.1x");
173 
174                         if (e->auth_suites & IWINFO_KMGMT_SAE)
175                                 blobmsg_add_string(&buf, NULL, "sae");
176 
177                         if (e->auth_suites & IWINFO_KMGMT_OWE)
178                                 blobmsg_add_string(&buf, NULL, "owe");
179 
180                         if (!e->auth_suites ||
181                                 (e->auth_suites & IWINFO_KMGMT_NONE))
182                                 blobmsg_add_string(&buf, NULL, "none");
183 
184                         blobmsg_close_array(&buf, d);
185                 }
186 
187                 d = blobmsg_open_array(&buf, "ciphers");
188                 ciph = e->pair_ciphers | e->group_ciphers;
189 
190                 if (ciph & IWINFO_CIPHER_WEP40)
191                         blobmsg_add_string(&buf, NULL, "wep-40");
192 
193                 if (ciph & IWINFO_CIPHER_WEP104)
194                         blobmsg_add_string(&buf, NULL, "wep-104");
195 
196                 if (ciph & IWINFO_CIPHER_TKIP)
197                         blobmsg_add_string(&buf, NULL, "tkip");
198 
199                 if (ciph & IWINFO_CIPHER_CCMP)
200                         blobmsg_add_string(&buf, NULL, "ccmp");
201 
202                 if (ciph & IWINFO_CIPHER_GCMP)
203                         blobmsg_add_string(&buf, NULL, "gcmp");
204 
205                 if (ciph & IWINFO_CIPHER_WRAP)
206                         blobmsg_add_string(&buf, NULL, "wrap");
207 
208                 if (ciph & IWINFO_CIPHER_AESOCB)
209                         blobmsg_add_string(&buf, NULL, "aes-ocb");
210 
211                 if (ciph & IWINFO_CIPHER_CKIP)
212                         blobmsg_add_string(&buf, NULL, "ckip");
213 
214                 if (!ciph || (ciph & IWINFO_CIPHER_NONE))
215                         blobmsg_add_string(&buf, NULL, "none");
216 
217                 blobmsg_close_array(&buf, d);
218         }
219 
220         blobmsg_close_table(&buf, c);
221 }
222 
223 static void
224 rpc_iwinfo_call_encryption(const char *name)
225 {
226         struct iwinfo_crypto_entry crypto = { 0 };
227 
228         if (!iw->encryption(ifname, (char *)&crypto))
229                 rpc_iwinfo_add_encryption(name, &crypto);
230 }
231 
232 static void
233 rpc_iwinfo_call_htmodes(const char *name)
234 {
235         int modes;
236         void *c;
237 
238         if (!iw->htmodelist(ifname, &modes))
239         {
240                 c = blobmsg_open_array(&buf, name);
241 
242                 if (modes & IWINFO_HTMODE_HT20)
243                         blobmsg_add_string(&buf, NULL, "HT20");
244 
245                 if (modes & IWINFO_HTMODE_HT40)
246                         blobmsg_add_string(&buf, NULL, "HT40");
247 
248                 if (modes & IWINFO_HTMODE_VHT20)
249                         blobmsg_add_string(&buf, NULL, "VHT20");
250 
251                 if (modes & IWINFO_HTMODE_VHT40)
252                         blobmsg_add_string(&buf, NULL, "VHT40");
253 
254                 if (modes & IWINFO_HTMODE_VHT80)
255                         blobmsg_add_string(&buf, NULL, "VHT80");
256 
257                 if (modes & IWINFO_HTMODE_VHT80_80)
258                         blobmsg_add_string(&buf, NULL, "VHT80+80");
259 
260                 if (modes & IWINFO_HTMODE_VHT160)
261                         blobmsg_add_string(&buf, NULL, "VHT160");
262 
263                 if (modes & IWINFO_HTMODE_HE20)
264                         blobmsg_add_string(&buf, NULL, "HE20");
265 
266                 if (modes & IWINFO_HTMODE_HE40)
267                         blobmsg_add_string(&buf, NULL, "HE40");
268 
269                 if (modes & IWINFO_HTMODE_HE80)
270                         blobmsg_add_string(&buf, NULL, "HE80");
271 
272                 if (modes & IWINFO_HTMODE_HE80_80)
273                         blobmsg_add_string(&buf, NULL, "HE80+80");
274 
275                 if (modes & IWINFO_HTMODE_HE160)
276                         blobmsg_add_string(&buf, NULL, "HE160");
277 
278                 blobmsg_close_array(&buf, c);
279         }
280 }
281 
282 static void
283 rpc_iwinfo_call_hwmodes(const char *name)
284 {
285         int modes;
286         void *c;
287 
288         if (!iw->hwmodelist(ifname, &modes))
289         {
290                 c = blobmsg_open_array(&buf, name);
291 
292                 if (modes & IWINFO_80211_AD)
293                         blobmsg_add_string(&buf, NULL, "ad");
294 
295                 if (modes & IWINFO_80211_AC)
296                         blobmsg_add_string(&buf, NULL, "ac");
297 
298                 if (modes & IWINFO_80211_AX)
299                         blobmsg_add_string(&buf, NULL, "ax");
300 
301                 if (modes & IWINFO_80211_A)
302                         blobmsg_add_string(&buf, NULL, "a");
303 
304                 if (modes & IWINFO_80211_B)
305                         blobmsg_add_string(&buf, NULL, "b");
306 
307                 if (modes & IWINFO_80211_G)
308                         blobmsg_add_string(&buf, NULL, "g");
309 
310                 if (modes & IWINFO_80211_N)
311                         blobmsg_add_string(&buf, NULL, "n");
312 
313                 blobmsg_close_array(&buf, c);
314         }
315 }
316 
317 static void rpc_iwinfo_call_hw_ht_mode()
318 {
319         const char *hwmode_str;
320         const char *htmode_str;
321         int32_t htmode = 0;
322         int modes;
323 
324         if (!iw->hwmodelist(ifname, &modes) && (modes == IWINFO_80211_AD)) {
325                 blobmsg_add_string(&buf, "hwmode", "ad");
326                 return;
327         }
328 
329         if (iw->htmode(ifname, &htmode))
330                 return;
331 
332         switch (htmode) {
333                 case IWINFO_HTMODE_HT20:
334                         htmode_str = "HT20";
335                         hwmode_str = "n";
336                         break;
337                 case IWINFO_HTMODE_HT40:
338                         htmode_str = "HT40";
339                         hwmode_str = "n";
340                         break;
341                 case IWINFO_HTMODE_VHT80:
342                         htmode_str = "VHT80";
343                         hwmode_str = "ac";
344                         break;
345                 case IWINFO_HTMODE_VHT80_80:
346                         htmode_str = "VHT80+80";
347                         hwmode_str = "ac";
348                         break;
349                 case IWINFO_HTMODE_VHT160:
350                         htmode_str = "VHT160";
351                         hwmode_str = "ac";
352                         break;
353                 case IWINFO_HTMODE_HE20:
354                         htmode_str = "HE20";
355                         hwmode_str = "ax";
356                         break;
357                 case IWINFO_HTMODE_HE40:
358                         htmode_str = "HE40";
359                         hwmode_str = "ax";
360                         break;
361                 case IWINFO_HTMODE_HE80:
362                         htmode_str = "HE80";
363                         hwmode_str = "ax";
364                         break;
365                 case IWINFO_HTMODE_HE80_80:
366                         htmode_str = "HE80+80";
367                         hwmode_str = "ax";
368                         break;
369                 case IWINFO_HTMODE_HE160:
370                         htmode_str = "HE160";
371                         hwmode_str = "ax";
372                         break;
373                 case IWINFO_HTMODE_NOHT:
374                         htmode_str = "20";
375                         hwmode_str = "a/g";
376                         break;
377                 default:
378                         htmode_str = hwmode_str = "unknown";
379                         break;
380         }
381         blobmsg_add_string(&buf, "hwmode", hwmode_str);
382         blobmsg_add_string(&buf, "htmode", htmode_str);
383 }
384 
385 static void
386 rpc_iwinfo_call_str(const char *name, int (*func)(const char *, char *))
387 {
388         char rv[IWINFO_BUFSIZE] = { 0 };
389 
390         if (!func(ifname, rv))
391                 blobmsg_add_string(&buf, name, rv);
392 }
393 
394 static int
395 rpc_iwinfo_info(struct ubus_context *ctx, struct ubus_object *obj,
396                 struct ubus_request_data *req, const char *method,
397                 struct blob_attr *msg)
398 {
399         int rv;
400         void *c;
401 
402         rv = rpc_iwinfo_open(msg);
403 
404         if (rv)
405                 return rv;
406 
407         blob_buf_init(&buf, 0);
408 
409         rpc_iwinfo_call_str("phy", iw->phyname);
410 
411         rpc_iwinfo_call_str("ssid", iw->ssid);
412         rpc_iwinfo_call_str("bssid", iw->bssid);
413         rpc_iwinfo_call_str("country", iw->country);
414 
415         rpc_iwinfo_call_int("mode", iw->mode, IWINFO_OPMODE_NAMES);
416         rpc_iwinfo_call_int("channel", iw->channel, NULL);
417         rpc_iwinfo_call_int("center_chan1", iw->center_chan1, NULL);
418         rpc_iwinfo_call_int("center_chan2", iw->center_chan2, NULL);
419 
420         rpc_iwinfo_call_int("frequency", iw->frequency, NULL);
421         rpc_iwinfo_call_int("frequency_offset", iw->frequency_offset, NULL);
422 
423         rpc_iwinfo_call_int("txpower", iw->txpower, NULL);
424         rpc_iwinfo_call_int("txpower_offset", iw->txpower_offset, NULL);
425 
426         rpc_iwinfo_call_int("quality", iw->quality, NULL);
427         rpc_iwinfo_call_int("quality_max", iw->quality_max, NULL);
428 
429         rpc_iwinfo_call_int("signal", iw->signal, NULL);
430         rpc_iwinfo_call_int("noise", iw->noise, NULL);
431 
432         rpc_iwinfo_call_int("bitrate", iw->bitrate, NULL);
433 
434         rpc_iwinfo_call_encryption("encryption");
435         rpc_iwinfo_call_htmodes("htmodes");
436         rpc_iwinfo_call_hwmodes("hwmodes");
437 
438         rpc_iwinfo_call_hw_ht_mode();
439 
440         c = blobmsg_open_table(&buf, "hardware");
441         rpc_iwinfo_call_hardware_id("id");
442         rpc_iwinfo_call_str("name", iw->hardware_name);
443         blobmsg_close_table(&buf, c);
444 
445         ubus_send_reply(ctx, req, buf.head);
446 
447         rpc_iwinfo_close();
448 
449         return UBUS_STATUS_OK;
450 }
451 
452 static int
453 rpc_iwinfo_scan(struct ubus_context *ctx, struct ubus_object *obj,
454                 struct ubus_request_data *req, const char *method,
455                 struct blob_attr *msg)
456 {
457         int i, rv, len;
458         void *c, *d, *t;
459         char mac[18];
460         char res[IWINFO_BUFSIZE];
461         struct iwinfo_scanlist_entry *e;
462 
463         rv = rpc_iwinfo_open(msg);
464 
465         if (rv)
466                 return rv;
467 
468         blob_buf_init(&buf, 0);
469 
470         c = blobmsg_open_array(&buf, "results");
471 
472         if (!iw->scanlist(ifname, res, &len) && (len > 0))
473         {
474                 for (i = 0; i < len; i += sizeof(struct iwinfo_scanlist_entry))
475                 {
476                         e = (struct iwinfo_scanlist_entry *)&res[i];
477                         d = blobmsg_open_table(&buf, NULL);
478 
479                         if (e->ssid[0])
480                                 blobmsg_add_string(&buf, "ssid", (const char *)e->ssid);
481 
482                         snprintf(mac, sizeof(mac), "%02X:%02X:%02X:%02X:%02X:%02X",
483                                          e->mac[0], e->mac[1], e->mac[2],
484                                          e->mac[3], e->mac[4], e->mac[5]);
485 
486                         blobmsg_add_string(&buf, "bssid", mac);
487 
488                         blobmsg_add_string(&buf, "mode", IWINFO_OPMODE_NAMES[e->mode]);
489 
490                         blobmsg_add_u32(&buf, "channel", e->channel);
491                         blobmsg_add_u32(&buf, "signal", (uint32_t)(e->signal - 0x100));
492 
493                         blobmsg_add_u32(&buf, "quality", e->quality);
494                         blobmsg_add_u32(&buf, "quality_max", e->quality_max);
495 
496                         if (e->ht_chan_info.primary_chan) {
497                                 t = blobmsg_open_table(&buf, "ht_operation");
498                                 blobmsg_add_u32(&buf, "primary_channel", e->ht_chan_info.primary_chan);
499                                 blobmsg_add_string(&buf, "secondary_channel_offset", ht_secondary_offset[e->ht_chan_info.secondary_chan_off]);
500                                 blobmsg_add_u32(&buf, "channel_width", ht_chan_width[e->ht_chan_info.chan_width]);
501                                 blobmsg_close_table(&buf, t);
502                         }
503 
504                         if (e->vht_chan_info.center_chan_1) {
505                                 t = blobmsg_open_table(&buf, "vht_operation");
506                                 blobmsg_add_u32(&buf, "channel_width", vht_chan_width[e->vht_chan_info.chan_width]);
507                                 blobmsg_add_u32(&buf, "center_freq_1", e->vht_chan_info.center_chan_1);
508                                 blobmsg_add_u32(&buf, "center_freq_2", e->vht_chan_info.center_chan_2);
509                                 blobmsg_close_table(&buf, t);
510                         }
511 
512                         rpc_iwinfo_add_encryption("encryption", &e->crypto);
513 
514                         blobmsg_close_table(&buf, d);
515                 }
516         }
517 
518         blobmsg_close_array(&buf, c);
519 
520         ubus_send_reply(ctx, req, buf.head);
521 
522         rpc_iwinfo_close();
523 
524         return UBUS_STATUS_OK;
525 }
526 
527 static void
528 rpc_iwinfo_add_rateinfo(struct iwinfo_rate_entry *r)
529 {
530         blobmsg_add_u8(&buf, "ht", r->is_ht);
531         blobmsg_add_u8(&buf, "vht", r->is_vht);
532         blobmsg_add_u8(&buf, "he", r->is_he);
533         blobmsg_add_u32(&buf, "mhz", r->mhz);
534         blobmsg_add_u32(&buf, "rate", r->rate);
535 
536         if (r->is_ht) {
537                 blobmsg_add_u32(&buf, "mcs", r->mcs);
538                 blobmsg_add_u8(&buf, "40mhz", r->is_40mhz);
539                 blobmsg_add_u8(&buf, "short_gi", r->is_short_gi);
540         }
541         else if (r->is_vht) {
542                 blobmsg_add_u32(&buf, "mcs", r->mcs);
543                 blobmsg_add_u32(&buf, "nss", r->nss);
544                 blobmsg_add_u8(&buf, "short_gi", r->is_short_gi);
545         }
546         else if (r->is_he) {
547                 blobmsg_add_u32(&buf, "mcs", r->mcs);
548                 blobmsg_add_u32(&buf, "nss", r->nss);
549                 blobmsg_add_u32(&buf, "he_gi", r->he_gi);
550                 blobmsg_add_u32(&buf, "he_dcm", r->he_dcm);
551         }
552 }
553 
554 static int
555 rpc_iwinfo_assoclist(struct ubus_context *ctx, struct ubus_object *obj,
556                      struct ubus_request_data *req, const char *method,
557                      struct blob_attr *msg)
558 {
559         int i, rv, len;
560         char mac[18];
561         char res[IWINFO_BUFSIZE];
562         struct iwinfo_assoclist_entry *a;
563         struct ether_addr *macaddr = NULL;
564         void *c, *d, *e;
565         struct blob_attr *tb[__RPC_A_MAX];
566         bool found = false;
567 
568         blobmsg_parse(rpc_assoclist_policy, __RPC_A_MAX, tb,
569                       blob_data(msg), blob_len(msg));
570 
571         rv = __rpc_iwinfo_open(tb[RPC_A_DEVICE]);
572         if (rv)
573                 return rv;
574 
575         if (tb[RPC_A_MACADDR])
576                 macaddr = ether_aton(blobmsg_data(tb[RPC_A_MACADDR]));
577 
578         blob_buf_init(&buf, 0);
579 
580         if (!macaddr)
581                 c = blobmsg_open_array(&buf, "results");
582 
583         if (!iw->assoclist(ifname, res, &len) && (len > 0))
584         {
585                 for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry))
586                 {
587                         a = (struct iwinfo_assoclist_entry *)&res[i];
588 
589                         if (!macaddr)
590                                 d = blobmsg_open_table(&buf, NULL);
591                         else if (memcmp(macaddr, a->mac, ETH_ALEN) != 0)
592                                 continue;
593 
594                         snprintf(mac, sizeof(mac), "%02X:%02X:%02X:%02X:%02X:%02X",
595                                          a->mac[0], a->mac[1], a->mac[2],
596                                          a->mac[3], a->mac[4], a->mac[5]);
597 
598                         blobmsg_add_string(&buf, "mac", mac);
599                         blobmsg_add_u32(&buf, "signal", a->signal);
600                         blobmsg_add_u32(&buf, "signal_avg", a->signal_avg);
601                         blobmsg_add_u32(&buf, "noise", a->noise);
602                         blobmsg_add_u32(&buf, "inactive", a->inactive);
603                         blobmsg_add_u32(&buf, "connected_time", a->connected_time);
604                         blobmsg_add_u32(&buf, "thr", a->thr);
605                         blobmsg_add_u8(&buf, "authorized", a->is_authorized);
606                         blobmsg_add_u8(&buf, "authenticated", a->is_authenticated);
607                         blobmsg_add_string(&buf, "preamble", a->is_preamble_short ? "short" : "long");
608                         blobmsg_add_u8(&buf, "wme", a->is_wme);
609                         blobmsg_add_u8(&buf, "mfp", a->is_mfp);
610                         blobmsg_add_u8(&buf, "tdls", a->is_tdls);
611 
612                         blobmsg_add_u16(&buf, "mesh llid", a->llid);
613                         blobmsg_add_u16(&buf, "mesh plid", a->plid);
614                         blobmsg_add_string(&buf, "mesh plink", a->plink_state);
615                         blobmsg_add_string(&buf, "mesh local PS", a->local_ps);
616                         blobmsg_add_string(&buf, "mesh peer PS", a->peer_ps);
617                         blobmsg_add_string(&buf, "mesh non-peer PS", a->nonpeer_ps);
618 
619                         e = blobmsg_open_table(&buf, "rx");
620                         blobmsg_add_u64(&buf, "drop_misc", a->rx_drop_misc);
621                         blobmsg_add_u32(&buf, "packets", a->rx_packets);
622                         blobmsg_add_u32(&buf, "bytes", a->rx_bytes);
623                         rpc_iwinfo_add_rateinfo(&a->rx_rate);
624                         blobmsg_close_table(&buf, e);
625 
626                         e = blobmsg_open_table(&buf, "tx");
627                         blobmsg_add_u32(&buf, "failed", a->tx_failed);
628                         blobmsg_add_u32(&buf, "retries", a->tx_retries);
629                         blobmsg_add_u32(&buf, "packets", a->tx_packets);
630                         blobmsg_add_u32(&buf, "bytes", a->tx_bytes);
631                         rpc_iwinfo_add_rateinfo(&a->tx_rate);
632                         blobmsg_close_table(&buf, e);
633 
634                         found = true;
635                         if (!macaddr)
636                                 blobmsg_close_table(&buf, d);
637                         else
638                                 break;
639                 }
640         }
641 
642         if (!macaddr)
643                 blobmsg_close_array(&buf, c);
644         else if (!found)
645                 return UBUS_STATUS_NOT_FOUND;
646 
647         ubus_send_reply(ctx, req, buf.head);
648 
649         rpc_iwinfo_close();
650 
651         return UBUS_STATUS_OK;
652 }
653 
654 static int
655 rpc_iwinfo_survey(struct ubus_context *ctx, struct ubus_object *obj,
656                     struct ubus_request_data *req, const char *method,
657                     struct blob_attr *msg)
658 {
659         char res[IWINFO_BUFSIZE];
660         struct iwinfo_survey_entry *e;
661         void *c, *d;
662         int i, rv, len;
663 
664         blob_buf_init(&buf, 0);
665 
666         rv = rpc_iwinfo_open(msg);
667 
668         c = blobmsg_open_array(&buf, "results");
669 
670         if (rv || iw->survey(ifname, res, &len) || len < 0)
671                 return UBUS_STATUS_OK;
672 
673         for (i = 0; i < len; i += sizeof(struct iwinfo_survey_entry)) {
674                 e = (struct iwinfo_survey_entry *)&res[i];
675 
676                 d = blobmsg_open_table(&buf, NULL);
677                 blobmsg_add_u32(&buf, "mhz", e->mhz);
678                 blobmsg_add_u32(&buf, "noise", e->noise);
679                 blobmsg_add_u64(&buf, "active_time", e->active_time);
680                 blobmsg_add_u64(&buf, "busy_time", e->busy_time);
681                 blobmsg_add_u64(&buf, "busy_time_ext", e->busy_time_ext);
682                 blobmsg_add_u64(&buf, "rx_time", e->rxtime);
683                 blobmsg_add_u64(&buf, "tx_time", e->txtime);
684                 blobmsg_close_table(&buf, d);
685         }
686 
687         blobmsg_close_array(&buf, c);
688         ubus_send_reply(ctx, req, buf.head);
689         rpc_iwinfo_close();
690         return UBUS_STATUS_OK;
691 }
692 
693 static int
694 rpc_iwinfo_freqlist(struct ubus_context *ctx, struct ubus_object *obj,
695                     struct ubus_request_data *req, const char *method,
696                     struct blob_attr *msg)
697 {
698         int i, rv, len, ch;
699         char res[IWINFO_BUFSIZE];
700         struct iwinfo_freqlist_entry *f;
701         void *c, *d;
702 
703         rv = rpc_iwinfo_open(msg);
704 
705         if (rv)
706                 return rv;
707 
708         blob_buf_init(&buf, 0);
709 
710         c = blobmsg_open_array(&buf, "results");
711 
712         if (!iw->freqlist(ifname, res, &len) && (len > 0))
713         {
714                 if (iw->channel(ifname, &ch))
715                         ch = -1;
716 
717                 for (i = 0; i < len; i += sizeof(struct iwinfo_freqlist_entry))
718                 {
719                         f = (struct iwinfo_freqlist_entry *)&res[i];
720                         d = blobmsg_open_table(&buf, NULL);
721 
722                         blobmsg_add_u32(&buf, "channel", f->channel);
723                         blobmsg_add_u32(&buf, "mhz", f->mhz);
724                         blobmsg_add_u8(&buf, "restricted", f->restricted);
725 
726                         if (ch > -1)
727                                 blobmsg_add_u8(&buf, "active", f->channel == ch);
728 
729                         blobmsg_close_table(&buf, d);
730                 }
731         }
732 
733         blobmsg_close_array(&buf, c);
734 
735         ubus_send_reply(ctx, req, buf.head);
736 
737         rpc_iwinfo_close();
738 
739         return UBUS_STATUS_OK;
740 }
741 
742 static int
743 rpc_iwinfo_txpowerlist(struct ubus_context *ctx, struct ubus_object *obj,
744                        struct ubus_request_data *req, const char *method,
745                        struct blob_attr *msg)
746 {
747         int i, rv, len, pwr, off;
748         char res[IWINFO_BUFSIZE];
749         struct iwinfo_txpwrlist_entry *t;
750         void *c, *d;
751 
752         rv = rpc_iwinfo_open(msg);
753 
754         if (rv)
755                 return rv;
756 
757         blob_buf_init(&buf, 0);
758 
759         c = blobmsg_open_array(&buf, "results");
760 
761         if (!iw->txpwrlist(ifname, res, &len) && (len > 0))
762         {
763                 if (iw->txpower(ifname, &pwr))
764                         pwr = -1;
765 
766                 if (iw->txpower_offset(ifname, &off))
767                         off = 0;
768 
769                 for (i = 0; i < len; i += sizeof(struct iwinfo_txpwrlist_entry))
770                 {
771                         t = (struct iwinfo_txpwrlist_entry *)&res[i];
772                         d = blobmsg_open_table(&buf, NULL);
773 
774                         blobmsg_add_u32(&buf, "dbm", t->dbm + off);
775                         blobmsg_add_u32(&buf, "mw", iwinfo_dbm2mw(t->dbm + off));
776 
777                         if (pwr > -1)
778                                 blobmsg_add_u8(&buf, "active", t->dbm == pwr);
779 
780                         blobmsg_close_table(&buf, d);
781                 }
782         }
783 
784         blobmsg_close_array(&buf, c);
785 
786         ubus_send_reply(ctx, req, buf.head);
787 
788         rpc_iwinfo_close();
789 
790         return UBUS_STATUS_OK;
791 }
792 
793 static const char *
794 rpc_iwinfo_lookup_country(char *buf, int len, int iso3166)
795 {
796         int i;
797         static char ccode[5];
798         struct iwinfo_country_entry *c;
799 
800         for (i = 0; i < len; i += sizeof(struct iwinfo_country_entry))
801         {
802                 c = (struct iwinfo_country_entry *)&buf[i];
803 
804                 if (c->iso3166 == iso3166)
805                 {
806                         snprintf(ccode, sizeof(ccode), "%s", c->ccode);
807                         return ccode;
808                 }
809         }
810 
811         return NULL;
812 }
813 
814 static int
815 rpc_iwinfo_countrylist(struct ubus_context *ctx, struct ubus_object *obj,
816                        struct ubus_request_data *req, const char *method,
817                        struct blob_attr *msg)
818 {
819         int rv, len;
820         char cur[3];
821         char iso3166[3];
822         char res[IWINFO_BUFSIZE] = {0};
823         const char *ccode;
824         const struct iwinfo_iso3166_label *l;
825         void *c, *d;
826 
827         rv = rpc_iwinfo_open(msg);
828 
829         if (rv)
830                 return rv;
831 
832         blob_buf_init(&buf, 0);
833 
834         c = blobmsg_open_array(&buf, "results");
835 
836         if (!iw->countrylist(ifname, res, &len) && (len > 0))
837         {
838                 if (iw->country(ifname, cur))
839                         memset(cur, 0, sizeof(cur));
840 
841                 for (l = IWINFO_ISO3166_NAMES; l->iso3166; l++)
842                 {
843                         ccode = rpc_iwinfo_lookup_country(res, len, l->iso3166);
844 
845                         if (!ccode)
846                                 continue;
847 
848                         d = blobmsg_open_table(&buf, NULL);
849 
850                         blobmsg_add_string(&buf, "code", ccode);
851                         blobmsg_add_string(&buf, "country", (const char *)l->name);
852 
853                         snprintf(iso3166, sizeof(iso3166), "%c%c",
854                                  (l->iso3166 / 256), (l->iso3166 % 256));
855 
856                         blobmsg_add_string(&buf, "iso3166", iso3166);
857 
858                         if (cur[0])
859                                 blobmsg_add_u8(&buf, "active", !strncmp(ccode, cur, 2));
860 
861                         blobmsg_close_table(&buf, d);
862                 }
863         }
864 
865         blobmsg_close_array(&buf, c);
866 
867         ubus_send_reply(ctx, req, buf.head);
868 
869         rpc_iwinfo_close();
870 
871         return UBUS_STATUS_OK;
872 }
873 
874 static int
875 rpc_iwinfo_phyname(struct ubus_context *ctx, struct ubus_object *obj,
876                    struct ubus_request_data *req, const char *method,
877                    struct blob_attr *msg)
878 {
879         int i;
880         bool found = false;
881         char res[IWINFO_BUFSIZE];
882         const struct iwinfo_ops *ops;
883         struct blob_attr *tb[__RPC_U_MAX];
884         const char *backends[] = {
885                 "nl80211",
886                 "madwifi",
887                 "wl"
888         };
889 
890         blobmsg_parse(rpc_uci_policy, __RPC_U_MAX, tb,
891                       blob_data(msg), blob_len(msg));
892 
893         if (!tb[RPC_U_SECTION])
894                 return UBUS_STATUS_INVALID_ARGUMENT;
895 
896         for (i = 0; i < ARRAY_SIZE(backends); i++)
897         {
898                 ops = iwinfo_backend_by_name(backends[i]);
899 
900                 if (!ops || !ops->lookup_phy)
901                         continue;
902 
903                 if (!ops->lookup_phy(blobmsg_get_string(tb[RPC_U_SECTION]), res))
904                 {
905                         found = true;
906                         break;
907                 }
908         }
909 
910         if (found)
911         {
912                 blob_buf_init(&buf, 0);
913                 blobmsg_add_string(&buf, "phyname", res);
914 
915                 ubus_send_reply(ctx, req, buf.head);
916         }
917 
918         rpc_iwinfo_close();
919 
920         return found ? UBUS_STATUS_OK : UBUS_STATUS_NOT_FOUND;
921 }
922 
923 static int
924 rpc_iwinfo_devices(struct ubus_context *ctx, struct ubus_object *obj,
925                    struct ubus_request_data *req, const char *method,
926                    struct blob_attr *msg)
927 {
928         void *c;
929         struct dirent *e;
930         DIR *d;
931 
932         d = opendir("/sys/class/net");
933 
934         if (!d)
935                 return UBUS_STATUS_UNKNOWN_ERROR;
936 
937         blob_buf_init(&buf, 0);
938 
939         c = blobmsg_open_array(&buf, "devices");
940 
941         while ((e = readdir(d)) != NULL)
942         {
943                 if (e->d_type != DT_LNK)
944                         continue;
945 
946                 if (iwinfo_type(e->d_name))
947                         blobmsg_add_string(&buf, NULL, e->d_name);
948         }
949 
950         blobmsg_close_array(&buf, c);
951 
952         closedir(d);
953 
954         ubus_send_reply(ctx, req, buf.head);
955 
956         rpc_iwinfo_close();
957 
958         return UBUS_STATUS_OK;
959 }
960 
961 
962 static int
963 rpc_iwinfo_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx)
964 {
965         static const struct ubus_method iwinfo_methods[] = {
966                 UBUS_METHOD_NOARG("devices", rpc_iwinfo_devices),
967                 UBUS_METHOD("info",        rpc_iwinfo_info,        rpc_device_policy),
968                 UBUS_METHOD("scan",        rpc_iwinfo_scan,        rpc_device_policy),
969                 UBUS_METHOD("assoclist",   rpc_iwinfo_assoclist,   rpc_assoclist_policy),
970                 UBUS_METHOD("freqlist",    rpc_iwinfo_freqlist,    rpc_device_policy),
971                 UBUS_METHOD("txpowerlist", rpc_iwinfo_txpowerlist, rpc_device_policy),
972                 UBUS_METHOD("countrylist", rpc_iwinfo_countrylist, rpc_device_policy),
973                 UBUS_METHOD("survey",      rpc_iwinfo_survey,      rpc_device_policy),
974                 UBUS_METHOD("phyname",     rpc_iwinfo_phyname,     rpc_uci_policy),
975         };
976 
977         static struct ubus_object_type iwinfo_type =
978                 UBUS_OBJECT_TYPE("luci-rpc-iwinfo", iwinfo_methods);
979 
980         static struct ubus_object obj = {
981                 .name = "iwinfo",
982                 .type = &iwinfo_type,
983                 .methods = iwinfo_methods,
984                 .n_methods = ARRAY_SIZE(iwinfo_methods),
985         };
986 
987         return ubus_add_object(ctx, &obj);
988 }
989 
990 struct rpc_plugin rpc_plugin = {
991         .init = rpc_iwinfo_api_init
992 };
993 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt