• 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_WRAP)
203                         blobmsg_add_string(&buf, NULL, "wrap");
204 
205                 if (ciph & IWINFO_CIPHER_AESOCB)
206                         blobmsg_add_string(&buf, NULL, "aes-ocb");
207 
208                 if (ciph & IWINFO_CIPHER_CKIP)
209                         blobmsg_add_string(&buf, NULL, "ckip");
210 
211                 if (!ciph || (ciph & IWINFO_CIPHER_NONE))
212                         blobmsg_add_string(&buf, NULL, "none");
213 
214                 blobmsg_close_array(&buf, d);
215         }
216 
217         blobmsg_close_table(&buf, c);
218 }
219 
220 static void
221 rpc_iwinfo_call_encryption(const char *name)
222 {
223         struct iwinfo_crypto_entry crypto = { 0 };
224 
225         if (!iw->encryption(ifname, (char *)&crypto))
226                 rpc_iwinfo_add_encryption(name, &crypto);
227 }
228 
229 static void
230 rpc_iwinfo_call_htmodes(const char *name)
231 {
232         int modes;
233         void *c;
234 
235         if (!iw->htmodelist(ifname, &modes))
236         {
237                 c = blobmsg_open_array(&buf, name);
238 
239                 if (modes & IWINFO_HTMODE_HT20)
240                         blobmsg_add_string(&buf, NULL, "HT20");
241 
242                 if (modes & IWINFO_HTMODE_HT40)
243                         blobmsg_add_string(&buf, NULL, "HT40");
244 
245                 if (modes & IWINFO_HTMODE_VHT20)
246                         blobmsg_add_string(&buf, NULL, "VHT20");
247 
248                 if (modes & IWINFO_HTMODE_VHT40)
249                         blobmsg_add_string(&buf, NULL, "VHT40");
250 
251                 if (modes & IWINFO_HTMODE_VHT80)
252                         blobmsg_add_string(&buf, NULL, "VHT80");
253 
254                 if (modes & IWINFO_HTMODE_VHT80_80)
255                         blobmsg_add_string(&buf, NULL, "VHT80+80");
256 
257                 if (modes & IWINFO_HTMODE_VHT160)
258                         blobmsg_add_string(&buf, NULL, "VHT160");
259 
260                 blobmsg_close_array(&buf, c);
261         }
262 }
263 
264 static void
265 rpc_iwinfo_call_hwmodes(const char *name)
266 {
267         int modes;
268         void *c;
269 
270         if (!iw->hwmodelist(ifname, &modes))
271         {
272                 c = blobmsg_open_array(&buf, name);
273 
274                 if (modes & IWINFO_80211_AC)
275                         blobmsg_add_string(&buf, NULL, "ac");
276 
277                 if (modes & IWINFO_80211_A)
278                         blobmsg_add_string(&buf, NULL, "a");
279 
280                 if (modes & IWINFO_80211_B)
281                         blobmsg_add_string(&buf, NULL, "b");
282 
283                 if (modes & IWINFO_80211_G)
284                         blobmsg_add_string(&buf, NULL, "g");
285 
286                 if (modes & IWINFO_80211_N)
287                         blobmsg_add_string(&buf, NULL, "n");
288 
289                 blobmsg_close_array(&buf, c);
290         }
291 }
292 
293 static void rpc_iwinfo_call_hw_ht_mode()
294 {
295         const char *hwmode_str;
296         const char *htmode_str;
297         int32_t htmode = 0;
298 
299         if (iw->htmode(ifname, &htmode))
300                 return;
301 
302         switch (htmode) {
303                 case IWINFO_HTMODE_HT20:
304                         htmode_str = "HT20";
305                         hwmode_str = "n";
306                         break;
307                 case IWINFO_HTMODE_HT40:
308                         htmode_str = "HT40";
309                         hwmode_str = "n";
310                         break;
311                 case IWINFO_HTMODE_VHT80:
312                         htmode_str = "VHT80";
313                         hwmode_str = "ac";
314                         break;
315                 case IWINFO_HTMODE_VHT80_80:
316                         htmode_str = "VHT80+80";
317                         hwmode_str = "ac";
318                         break;
319                 case IWINFO_HTMODE_VHT160:
320                         htmode_str = "VHT160";
321                         hwmode_str = "ac";
322                         break;
323                 case IWINFO_HTMODE_NOHT:
324                         htmode_str = "20";
325                         hwmode_str = "a/g";
326                         break;
327                 default:
328                         htmode_str = hwmode_str = "unknown";
329                         break;
330         }
331         blobmsg_add_string(&buf, "hwmode", hwmode_str);
332         blobmsg_add_string(&buf, "htmode", htmode_str);
333 }
334 
335 static void
336 rpc_iwinfo_call_str(const char *name, int (*func)(const char *, char *))
337 {
338         char rv[IWINFO_BUFSIZE] = { 0 };
339 
340         if (!func(ifname, rv))
341                 blobmsg_add_string(&buf, name, rv);
342 }
343 
344 static int
345 rpc_iwinfo_info(struct ubus_context *ctx, struct ubus_object *obj,
346                 struct ubus_request_data *req, const char *method,
347                 struct blob_attr *msg)
348 {
349         int rv;
350         void *c;
351 
352         rv = rpc_iwinfo_open(msg);
353 
354         if (rv)
355                 return rv;
356 
357         blob_buf_init(&buf, 0);
358 
359         rpc_iwinfo_call_str("phy", iw->phyname);
360 
361         rpc_iwinfo_call_str("ssid", iw->ssid);
362         rpc_iwinfo_call_str("bssid", iw->bssid);
363         rpc_iwinfo_call_str("country", iw->country);
364 
365         rpc_iwinfo_call_int("mode", iw->mode, IWINFO_OPMODE_NAMES);
366         rpc_iwinfo_call_int("channel", iw->channel, NULL);
367 
368         rpc_iwinfo_call_int("frequency", iw->frequency, NULL);
369         rpc_iwinfo_call_int("frequency_offset", iw->frequency_offset, NULL);
370 
371         rpc_iwinfo_call_int("txpower", iw->txpower, NULL);
372         rpc_iwinfo_call_int("txpower_offset", iw->txpower_offset, NULL);
373 
374         rpc_iwinfo_call_int("quality", iw->quality, NULL);
375         rpc_iwinfo_call_int("quality_max", iw->quality_max, NULL);
376 
377         rpc_iwinfo_call_int("signal", iw->signal, NULL);
378         rpc_iwinfo_call_int("noise", iw->noise, NULL);
379 
380         rpc_iwinfo_call_int("bitrate", iw->bitrate, NULL);
381 
382         rpc_iwinfo_call_encryption("encryption");
383         rpc_iwinfo_call_htmodes("htmodes");
384         rpc_iwinfo_call_hwmodes("hwmodes");
385 
386         rpc_iwinfo_call_hw_ht_mode();
387 
388         c = blobmsg_open_table(&buf, "hardware");
389         rpc_iwinfo_call_hardware_id("id");
390         rpc_iwinfo_call_str("name", iw->hardware_name);
391         blobmsg_close_table(&buf, c);
392 
393         ubus_send_reply(ctx, req, buf.head);
394 
395         rpc_iwinfo_close();
396 
397         return UBUS_STATUS_OK;
398 }
399 
400 static int
401 rpc_iwinfo_scan(struct ubus_context *ctx, struct ubus_object *obj,
402                 struct ubus_request_data *req, const char *method,
403                 struct blob_attr *msg)
404 {
405         int i, rv, len;
406         void *c, *d;
407         char mac[18];
408         char res[IWINFO_BUFSIZE];
409         struct iwinfo_scanlist_entry *e;
410 
411         rv = rpc_iwinfo_open(msg);
412 
413         if (rv)
414                 return rv;
415 
416         blob_buf_init(&buf, 0);
417 
418         c = blobmsg_open_array(&buf, "results");
419 
420         if (!iw->scanlist(ifname, res, &len) && (len > 0))
421         {
422                 for (i = 0; i < len; i += sizeof(struct iwinfo_scanlist_entry))
423                 {
424                         e = (struct iwinfo_scanlist_entry *)&res[i];
425                         d = blobmsg_open_table(&buf, NULL);
426 
427                         if (e->ssid[0])
428                                 blobmsg_add_string(&buf, "ssid", (const char *)e->ssid);
429 
430                         snprintf(mac, sizeof(mac), "%02X:%02X:%02X:%02X:%02X:%02X",
431                                          e->mac[0], e->mac[1], e->mac[2],
432                                          e->mac[3], e->mac[4], e->mac[5]);
433 
434                         blobmsg_add_string(&buf, "bssid", mac);
435 
436                         blobmsg_add_string(&buf, "mode", IWINFO_OPMODE_NAMES[e->mode]);
437 
438                         blobmsg_add_u32(&buf, "channel", e->channel);
439                         blobmsg_add_u32(&buf, "signal", (uint32_t)(e->signal - 0x100));
440 
441                         blobmsg_add_u32(&buf, "quality", e->quality);
442                         blobmsg_add_u32(&buf, "quality_max", e->quality_max);
443 
444                         rpc_iwinfo_add_encryption("encryption", &e->crypto);
445 
446                         blobmsg_close_table(&buf, d);
447                 }
448         }
449 
450         blobmsg_close_array(&buf, c);
451 
452         ubus_send_reply(ctx, req, buf.head);
453 
454         rpc_iwinfo_close();
455 
456         return UBUS_STATUS_OK;
457 }
458 
459 static void
460 rpc_iwinfo_add_rateinfo(struct iwinfo_rate_entry *r)
461 {
462         blobmsg_add_u8(&buf, "ht", r->is_ht);
463         blobmsg_add_u8(&buf, "vht", r->is_vht);
464         blobmsg_add_u32(&buf, "mhz", r->mhz);
465         blobmsg_add_u32(&buf, "rate", r->rate);
466 
467         if (r->is_ht) {
468                 blobmsg_add_u32(&buf, "mcs", r->mcs);
469                 blobmsg_add_u8(&buf, "40mhz", r->is_40mhz);
470                 blobmsg_add_u8(&buf, "short_gi", r->is_short_gi);
471         }
472         else if (r->is_vht) {
473                 blobmsg_add_u32(&buf, "mcs", r->mcs);
474                 blobmsg_add_u32(&buf, "nss", r->nss);
475                 blobmsg_add_u8(&buf, "short_gi", r->is_short_gi);
476         }
477 }
478 
479 static int
480 rpc_iwinfo_assoclist(struct ubus_context *ctx, struct ubus_object *obj,
481                      struct ubus_request_data *req, const char *method,
482                      struct blob_attr *msg)
483 {
484         int i, rv, len;
485         char mac[18];
486         char res[IWINFO_BUFSIZE];
487         struct iwinfo_assoclist_entry *a;
488         struct ether_addr *macaddr = NULL;
489         void *c, *d, *e;
490         struct blob_attr *tb[__RPC_A_MAX];
491         bool found = false;
492 
493         blobmsg_parse(rpc_assoclist_policy, __RPC_A_MAX, tb,
494                       blob_data(msg), blob_len(msg));
495 
496         rv = __rpc_iwinfo_open(tb[RPC_A_DEVICE]);
497         if (rv)
498                 return rv;
499 
500         if (tb[RPC_A_MACADDR])
501                 macaddr = ether_aton(blobmsg_data(tb[RPC_A_MACADDR]));
502 
503         blob_buf_init(&buf, 0);
504 
505         if (!macaddr)
506                 c = blobmsg_open_array(&buf, "results");
507 
508         if (!iw->assoclist(ifname, res, &len) && (len > 0))
509         {
510                 for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry))
511                 {
512                         a = (struct iwinfo_assoclist_entry *)&res[i];
513 
514                         if (!macaddr)
515                                 d = blobmsg_open_table(&buf, NULL);
516                         else if (memcmp(macaddr, a->mac, ETH_ALEN) != 0)
517                                 continue;
518 
519                         snprintf(mac, sizeof(mac), "%02X:%02X:%02X:%02X:%02X:%02X",
520                                          a->mac[0], a->mac[1], a->mac[2],
521                                          a->mac[3], a->mac[4], a->mac[5]);
522 
523                         blobmsg_add_string(&buf, "mac", mac);
524                         blobmsg_add_u32(&buf, "signal", a->signal);
525                         blobmsg_add_u32(&buf, "signal_avg", a->signal_avg);
526                         blobmsg_add_u32(&buf, "noise", a->noise);
527                         blobmsg_add_u32(&buf, "inactive", a->inactive);
528                         blobmsg_add_u32(&buf, "connected_time", a->connected_time);
529                         blobmsg_add_u32(&buf, "thr", a->thr);
530                         blobmsg_add_u8(&buf, "authorized", a->is_authorized);
531                         blobmsg_add_u8(&buf, "authenticated", a->is_authenticated);
532                         blobmsg_add_string(&buf, "preamble", a->is_preamble_short ? "short" : "long");
533                         blobmsg_add_u8(&buf, "wme", a->is_wme);
534                         blobmsg_add_u8(&buf, "mfp", a->is_mfp);
535                         blobmsg_add_u8(&buf, "tdls", a->is_tdls);
536 
537                         blobmsg_add_u16(&buf, "mesh llid", a->llid);
538                         blobmsg_add_u16(&buf, "mesh plid", a->plid);
539                         blobmsg_add_string(&buf, "mesh plink", a->plink_state);
540                         blobmsg_add_string(&buf, "mesh local PS", a->local_ps);
541                         blobmsg_add_string(&buf, "mesh peer PS", a->peer_ps);
542                         blobmsg_add_string(&buf, "mesh non-peer PS", a->nonpeer_ps);
543 
544                         e = blobmsg_open_table(&buf, "rx");
545                         blobmsg_add_u64(&buf, "drop_misc", a->rx_drop_misc);
546                         blobmsg_add_u32(&buf, "packets", a->rx_packets);
547                         blobmsg_add_u32(&buf, "bytes", a->rx_bytes);
548                         rpc_iwinfo_add_rateinfo(&a->rx_rate);
549                         blobmsg_close_table(&buf, e);
550 
551                         e = blobmsg_open_table(&buf, "tx");
552                         blobmsg_add_u32(&buf, "failed", a->tx_failed);
553                         blobmsg_add_u32(&buf, "retries", a->tx_retries);
554                         blobmsg_add_u32(&buf, "packets", a->tx_packets);
555                         blobmsg_add_u32(&buf, "bytes", a->tx_bytes);
556                         rpc_iwinfo_add_rateinfo(&a->tx_rate);
557                         blobmsg_close_table(&buf, e);
558 
559                         found = true;
560                         if (!macaddr)
561                                 blobmsg_close_table(&buf, d);
562                         else
563                                 break;
564                 }
565         }
566 
567         if (!macaddr)
568                 blobmsg_close_array(&buf, c);
569         else if (!found)
570                 return UBUS_STATUS_NOT_FOUND;
571 
572         ubus_send_reply(ctx, req, buf.head);
573 
574         rpc_iwinfo_close();
575 
576         return UBUS_STATUS_OK;
577 }
578 
579 static int
580 rpc_iwinfo_survey(struct ubus_context *ctx, struct ubus_object *obj,
581                     struct ubus_request_data *req, const char *method,
582                     struct blob_attr *msg)
583 {
584         char res[IWINFO_BUFSIZE];
585         struct iwinfo_survey_entry *e;
586         void *c, *d;
587         int i, rv, len;
588 
589         blob_buf_init(&buf, 0);
590 
591         rv = rpc_iwinfo_open(msg);
592 
593         c = blobmsg_open_array(&buf, "results");
594 
595         if (rv || iw->survey(ifname, res, &len) || len < 0)
596                 return UBUS_STATUS_OK;
597 
598         for (i = 0; i < len; i += sizeof(struct iwinfo_survey_entry)) {
599                 e = (struct iwinfo_survey_entry *)&res[i];
600 
601                 d = blobmsg_open_table(&buf, NULL);
602                 blobmsg_add_u32(&buf, "mhz", e->mhz);
603                 blobmsg_add_u32(&buf, "noise", e->noise);
604                 blobmsg_add_u64(&buf, "active_time", e->active_time);
605                 blobmsg_add_u64(&buf, "busy_time", e->busy_time);
606                 blobmsg_add_u64(&buf, "busy_time_ext", e->busy_time_ext);
607                 blobmsg_add_u64(&buf, "rx_time", e->rxtime);
608                 blobmsg_add_u64(&buf, "tx_time", e->txtime);
609                 blobmsg_close_table(&buf, d);
610         }
611 
612         blobmsg_close_array(&buf, c);
613         ubus_send_reply(ctx, req, buf.head);
614         rpc_iwinfo_close();
615         return UBUS_STATUS_OK;
616 }
617 
618 static int
619 rpc_iwinfo_freqlist(struct ubus_context *ctx, struct ubus_object *obj,
620                     struct ubus_request_data *req, const char *method,
621                     struct blob_attr *msg)
622 {
623         int i, rv, len, ch;
624         char res[IWINFO_BUFSIZE];
625         struct iwinfo_freqlist_entry *f;
626         void *c, *d;
627 
628         rv = rpc_iwinfo_open(msg);
629 
630         if (rv)
631                 return rv;
632 
633         blob_buf_init(&buf, 0);
634 
635         c = blobmsg_open_array(&buf, "results");
636 
637         if (!iw->freqlist(ifname, res, &len) && (len > 0))
638         {
639                 if (iw->channel(ifname, &ch))
640                         ch = -1;
641 
642                 for (i = 0; i < len; i += sizeof(struct iwinfo_freqlist_entry))
643                 {
644                         f = (struct iwinfo_freqlist_entry *)&res[i];
645                         d = blobmsg_open_table(&buf, NULL);
646 
647                         blobmsg_add_u32(&buf, "channel", f->channel);
648                         blobmsg_add_u32(&buf, "mhz", f->mhz);
649                         blobmsg_add_u8(&buf, "restricted", f->restricted);
650 
651                         if (ch > -1)
652                                 blobmsg_add_u8(&buf, "active", f->channel == ch);
653 
654                         blobmsg_close_table(&buf, d);
655                 }
656         }
657 
658         blobmsg_close_array(&buf, c);
659 
660         ubus_send_reply(ctx, req, buf.head);
661 
662         rpc_iwinfo_close();
663 
664         return UBUS_STATUS_OK;
665 }
666 
667 static int
668 rpc_iwinfo_txpowerlist(struct ubus_context *ctx, struct ubus_object *obj,
669                        struct ubus_request_data *req, const char *method,
670                        struct blob_attr *msg)
671 {
672         int i, rv, len, pwr, off;
673         char res[IWINFO_BUFSIZE];
674         struct iwinfo_txpwrlist_entry *t;
675         void *c, *d;
676 
677         rv = rpc_iwinfo_open(msg);
678 
679         if (rv)
680                 return rv;
681 
682         blob_buf_init(&buf, 0);
683 
684         c = blobmsg_open_array(&buf, "results");
685 
686         if (!iw->txpwrlist(ifname, res, &len) && (len > 0))
687         {
688                 if (iw->txpower(ifname, &pwr))
689                         pwr = -1;
690 
691                 if (iw->txpower_offset(ifname, &off))
692                         off = 0;
693 
694                 for (i = 0; i < len; i += sizeof(struct iwinfo_txpwrlist_entry))
695                 {
696                         t = (struct iwinfo_txpwrlist_entry *)&res[i];
697                         d = blobmsg_open_table(&buf, NULL);
698 
699                         blobmsg_add_u32(&buf, "dbm", t->dbm + off);
700                         blobmsg_add_u32(&buf, "mw", iwinfo_dbm2mw(t->dbm + off));
701 
702                         if (pwr > -1)
703                                 blobmsg_add_u8(&buf, "active", t->dbm == pwr);
704 
705                         blobmsg_close_table(&buf, d);
706                 }
707         }
708 
709         blobmsg_close_array(&buf, c);
710 
711         ubus_send_reply(ctx, req, buf.head);
712 
713         rpc_iwinfo_close();
714 
715         return UBUS_STATUS_OK;
716 }
717 
718 static const char *
719 rpc_iwinfo_lookup_country(char *buf, int len, int iso3166)
720 {
721         int i;
722         static char ccode[5];
723         struct iwinfo_country_entry *c;
724 
725         for (i = 0; i < len; i += sizeof(struct iwinfo_country_entry))
726         {
727                 c = (struct iwinfo_country_entry *)&buf[i];
728 
729                 if (c->iso3166 == iso3166)
730                 {
731                         snprintf(ccode, sizeof(ccode), "%s", c->ccode);
732                         return ccode;
733                 }
734         }
735 
736         return NULL;
737 }
738 
739 static int
740 rpc_iwinfo_countrylist(struct ubus_context *ctx, struct ubus_object *obj,
741                        struct ubus_request_data *req, const char *method,
742                        struct blob_attr *msg)
743 {
744         int rv, len;
745         char cur[3];
746         char iso3166[3];
747         char res[IWINFO_BUFSIZE] = {0};
748         const char *ccode;
749         const struct iwinfo_iso3166_label *l;
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->countrylist(ifname, res, &len) && (len > 0))
762         {
763                 if (iw->country(ifname, cur))
764                         memset(cur, 0, sizeof(cur));
765 
766                 for (l = IWINFO_ISO3166_NAMES; l->iso3166; l++)
767                 {
768                         ccode = rpc_iwinfo_lookup_country(res, len, l->iso3166);
769 
770                         if (!ccode)
771                                 continue;
772 
773                         d = blobmsg_open_table(&buf, NULL);
774 
775                         blobmsg_add_string(&buf, "code", ccode);
776                         blobmsg_add_string(&buf, "country", (const char *)l->name);
777 
778                         snprintf(iso3166, sizeof(iso3166), "%c%c",
779                                  (l->iso3166 / 256), (l->iso3166 % 256));
780 
781                         blobmsg_add_string(&buf, "iso3166", iso3166);
782 
783                         if (cur[0])
784                                 blobmsg_add_u8(&buf, "active", !strncmp(ccode, cur, 2));
785 
786                         blobmsg_close_table(&buf, d);
787                 }
788         }
789 
790         blobmsg_close_array(&buf, c);
791 
792         ubus_send_reply(ctx, req, buf.head);
793 
794         rpc_iwinfo_close();
795 
796         return UBUS_STATUS_OK;
797 }
798 
799 static int
800 rpc_iwinfo_phyname(struct ubus_context *ctx, struct ubus_object *obj,
801                    struct ubus_request_data *req, const char *method,
802                    struct blob_attr *msg)
803 {
804         int i;
805         bool found = false;
806         char res[IWINFO_BUFSIZE];
807         const struct iwinfo_ops *ops;
808         struct blob_attr *tb[__RPC_U_MAX];
809         const char *backends[] = {
810                 "nl80211",
811                 "madwifi",
812                 "wl"
813         };
814 
815         blobmsg_parse(rpc_uci_policy, __RPC_U_MAX, tb,
816                       blob_data(msg), blob_len(msg));
817 
818         if (!tb[RPC_U_SECTION])
819                 return UBUS_STATUS_INVALID_ARGUMENT;
820 
821         for (i = 0; i < ARRAY_SIZE(backends); i++)
822         {
823                 ops = iwinfo_backend_by_name(backends[i]);
824 
825                 if (!ops || !ops->lookup_phy)
826                         continue;
827 
828                 if (!ops->lookup_phy(blobmsg_get_string(tb[RPC_U_SECTION]), res))
829                 {
830                         found = true;
831                         break;
832                 }
833         }
834 
835         if (found)
836         {
837                 blob_buf_init(&buf, 0);
838                 blobmsg_add_string(&buf, "phyname", res);
839 
840                 ubus_send_reply(ctx, req, buf.head);
841         }
842 
843         rpc_iwinfo_close();
844 
845         return found ? UBUS_STATUS_OK : UBUS_STATUS_NOT_FOUND;
846 }
847 
848 static int
849 rpc_iwinfo_devices(struct ubus_context *ctx, struct ubus_object *obj,
850                    struct ubus_request_data *req, const char *method,
851                    struct blob_attr *msg)
852 {
853         void *c;
854         struct dirent *e;
855         DIR *d;
856 
857         d = opendir("/sys/class/net");
858 
859         if (!d)
860                 return UBUS_STATUS_UNKNOWN_ERROR;
861 
862         blob_buf_init(&buf, 0);
863 
864         c = blobmsg_open_array(&buf, "devices");
865 
866         while ((e = readdir(d)) != NULL)
867         {
868                 if (e->d_type != DT_LNK)
869                         continue;
870 
871                 if (iwinfo_type(e->d_name))
872                         blobmsg_add_string(&buf, NULL, e->d_name);
873         }
874 
875         blobmsg_close_array(&buf, c);
876 
877         closedir(d);
878 
879         ubus_send_reply(ctx, req, buf.head);
880 
881         rpc_iwinfo_close();
882 
883         return UBUS_STATUS_OK;
884 }
885 
886 
887 static int
888 rpc_iwinfo_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx)
889 {
890         static const struct ubus_method iwinfo_methods[] = {
891                 UBUS_METHOD_NOARG("devices", rpc_iwinfo_devices),
892                 UBUS_METHOD("info",        rpc_iwinfo_info,        rpc_device_policy),
893                 UBUS_METHOD("scan",        rpc_iwinfo_scan,        rpc_device_policy),
894                 UBUS_METHOD("assoclist",   rpc_iwinfo_assoclist,   rpc_assoclist_policy),
895                 UBUS_METHOD("freqlist",    rpc_iwinfo_freqlist,    rpc_device_policy),
896                 UBUS_METHOD("txpowerlist", rpc_iwinfo_txpowerlist, rpc_device_policy),
897                 UBUS_METHOD("countrylist", rpc_iwinfo_countrylist, rpc_device_policy),
898                 UBUS_METHOD("survey",      rpc_iwinfo_survey,      rpc_device_policy),
899                 UBUS_METHOD("phyname",     rpc_iwinfo_phyname,     rpc_uci_policy),
900         };
901 
902         static struct ubus_object_type iwinfo_type =
903                 UBUS_OBJECT_TYPE("luci-rpc-iwinfo", iwinfo_methods);
904 
905         static struct ubus_object obj = {
906                 .name = "iwinfo",
907                 .type = &iwinfo_type,
908                 .methods = iwinfo_methods,
909                 .n_methods = ARRAY_SIZE(iwinfo_methods),
910         };
911 
912         return ubus_add_object(ctx, &obj);
913 }
914 
915 struct rpc_plugin rpc_plugin = {
916         .init = rpc_iwinfo_api_init
917 };
918 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt