devices: add device id for Realtek RTL8188CU and RTL8188FTV
[project/iwinfo.git] / iwinfo_cli.c
1 /*
2 * iwinfo - Wireless Information Library - Command line frontend
3 *
4 * Copyright (C) 2011 Jo-Philipp Wich <xm@subsignal.org>
5 *
6 * The iwinfo library is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
9 *
10 * The iwinfo library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with the iwinfo library. If not, see http://www.gnu.org/licenses/.
17 */
18
19 #include <stdio.h>
20 #include <glob.h>
21
22 #include "iwinfo.h"
23
24
25 static char * format_bssid(unsigned char *mac)
26 {
27 static char buf[18];
28
29 snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X",
30 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
31
32 return buf;
33 }
34
35 static char * format_ssid(char *ssid)
36 {
37 static char buf[IWINFO_ESSID_MAX_SIZE+3];
38
39 if (ssid && ssid[0])
40 snprintf(buf, sizeof(buf), "\"%s\"", ssid);
41 else
42 snprintf(buf, sizeof(buf), "unknown");
43
44 return buf;
45 }
46
47 static const char *format_band(int band)
48 {
49 const char *name;
50
51 name = iwinfo_band_name(band);
52 if (name)
53 return name;
54
55 return "unknown";
56 }
57
58 static char * format_channel(int ch)
59 {
60 static char buf[16];
61
62 if (ch <= 0)
63 snprintf(buf, sizeof(buf), "unknown");
64 else
65 snprintf(buf, sizeof(buf), "%d", ch);
66
67 return buf;
68 }
69
70 static char * format_frequency(int freq)
71 {
72 static char buf[11];
73
74 if (freq <= 0)
75 snprintf(buf, sizeof(buf), "unknown");
76 else
77 snprintf(buf, sizeof(buf), "%.3f GHz", ((float)freq / 1000.0));
78
79 return buf;
80 }
81
82 static char * format_freqflags(uint32_t flags)
83 {
84 static char str[512] = "[";
85 char *pos = str + 1;
86 int i;
87
88 if (!flags)
89 return "";
90
91 for (i = 0; i < IWINFO_FREQ_FLAG_COUNT; i++)
92 if (flags & (1 << i))
93 pos += sprintf(pos, "%s, ", IWINFO_FREQ_FLAG_NAMES[i]);
94
95 *(pos - 2) = ']';
96 *(pos - 1) = 0;
97
98 return str;
99 }
100
101 static char * format_txpower(int pwr)
102 {
103 static char buf[16];
104
105 if (pwr < 0)
106 snprintf(buf, sizeof(buf), "unknown");
107 else
108 snprintf(buf, sizeof(buf), "%d dBm", pwr);
109
110 return buf;
111 }
112
113 static char * format_quality(int qual)
114 {
115 static char buf[16];
116
117 if (qual < 0)
118 snprintf(buf, sizeof(buf), "unknown");
119 else
120 snprintf(buf, sizeof(buf), "%d", qual);
121
122 return buf;
123 }
124
125 static char * format_quality_max(int qmax)
126 {
127 static char buf[16];
128
129 if (qmax < 0)
130 snprintf(buf, sizeof(buf), "unknown");
131 else
132 snprintf(buf, sizeof(buf), "%d", qmax);
133
134 return buf;
135 }
136
137 static char * format_signal(int sig)
138 {
139 static char buf[10];
140
141 if (!sig)
142 snprintf(buf, sizeof(buf), "unknown");
143 else
144 snprintf(buf, sizeof(buf), "%d dBm", sig);
145
146 return buf;
147 }
148
149 static char * format_noise(int noise)
150 {
151 static char buf[10];
152
153 if (!noise)
154 snprintf(buf, sizeof(buf), "unknown");
155 else
156 snprintf(buf, sizeof(buf), "%d dBm", noise);
157
158 return buf;
159 }
160
161 static char * format_rate(int rate)
162 {
163 static char buf[18];
164
165 if (rate <= 0)
166 snprintf(buf, sizeof(buf), "unknown");
167 else
168 snprintf(buf, sizeof(buf), "%d.%d MBit/s",
169 rate / 1000, (rate % 1000) / 100);
170
171 return buf;
172 }
173
174 static char * format_enc_ciphers(int ciphers)
175 {
176 static char str[128] = { 0 };
177 char *pos = str;
178 int i;
179
180 for (i = 0; i < IWINFO_CIPHER_COUNT; i++)
181 if (ciphers & (1 << i))
182 pos += sprintf(pos, "%s, ", IWINFO_CIPHER_NAMES[i]);
183
184 *(pos - 2) = 0;
185
186 return str;
187 }
188
189 static char * format_enc_suites(int suites)
190 {
191 static char str[64] = { 0 };
192 char *pos = str;
193 int i;
194
195 for (i = 0; i < IWINFO_KMGMT_COUNT; i++)
196 if (suites & (1 << i))
197 pos += sprintf(pos, "%s/", IWINFO_KMGMT_NAMES[i]);
198
199 *(pos - 1) = 0;
200
201 return str;
202 }
203
204 static char * format_encryption(struct iwinfo_crypto_entry *c)
205 {
206 static char buf[512];
207 char *pos = buf;
208 int i, n;
209
210 if (!c)
211 {
212 snprintf(buf, sizeof(buf), "unknown");
213 }
214 else if (c->enabled)
215 {
216 /* WEP */
217 if (c->auth_algs && !c->wpa_version)
218 {
219 if ((c->auth_algs & IWINFO_AUTH_OPEN) &&
220 (c->auth_algs & IWINFO_AUTH_SHARED))
221 {
222 snprintf(buf, sizeof(buf), "WEP Open/Shared (%s)",
223 format_enc_ciphers(c->pair_ciphers));
224 }
225 else if (c->auth_algs & IWINFO_AUTH_OPEN)
226 {
227 snprintf(buf, sizeof(buf), "WEP Open System (%s)",
228 format_enc_ciphers(c->pair_ciphers));
229 }
230 else if (c->auth_algs & IWINFO_AUTH_SHARED)
231 {
232 snprintf(buf, sizeof(buf), "WEP Shared Auth (%s)",
233 format_enc_ciphers(c->pair_ciphers));
234 }
235 }
236
237 /* WPA */
238 else if (c->wpa_version)
239 {
240 for (i = 0, n = 0; i < 3; i++)
241 if (c->wpa_version & (1 << i))
242 n++;
243
244 if (n > 1)
245 pos += sprintf(pos, "mixed ");
246
247 for (i = 0; i < 3; i++)
248 if (c->wpa_version & (1 << i))
249 {
250 if (i)
251 pos += sprintf(pos, "WPA%d/", i + 1);
252 else
253 pos += sprintf(pos, "WPA/");
254 }
255
256 pos--;
257
258 sprintf(pos, " %s (%s)",
259 format_enc_suites(c->auth_suites),
260 format_enc_ciphers(c->pair_ciphers | c->group_ciphers));
261 }
262 else
263 {
264 snprintf(buf, sizeof(buf), "none");
265 }
266 }
267 else
268 {
269 snprintf(buf, sizeof(buf), "none");
270 }
271
272 return buf;
273 }
274
275 static char * format_hwmodes(int modes)
276 {
277 static char buf[32] = "802.11";
278
279 if (iwinfo_format_hwmodes(modes, buf + 6, sizeof(buf) - 6) < 1)
280 snprintf(buf, sizeof(buf), "unknown");
281
282 return buf;
283 }
284
285 static char * format_assocrate(struct iwinfo_rate_entry *r)
286 {
287 static char buf[80];
288 char *p = buf;
289 int l = sizeof(buf);
290
291 if (r->rate <= 0)
292 {
293 snprintf(buf, sizeof(buf), "unknown");
294 }
295 else
296 {
297 p += snprintf(p, l, "%s", format_rate(r->rate));
298 l = sizeof(buf) - (p - buf);
299
300 if (r->is_ht)
301 {
302 p += snprintf(p, l, ", MCS %d, %dMHz", r->mcs, r->mhz);
303 l = sizeof(buf) - (p - buf);
304 }
305 else if (r->is_vht)
306 {
307 p += snprintf(p, l, ", VHT-MCS %d, %dMHz", r->mcs, r->mhz);
308 l = sizeof(buf) - (p - buf);
309
310 if (r->nss)
311 {
312 p += snprintf(p, l, ", VHT-NSS %d", r->nss);
313 l = sizeof(buf) - (p - buf);
314 }
315 }
316 else if (r->is_he)
317 {
318 p += snprintf(p, l, ", HE-MCS %d, %dMHz", r->mcs, r->mhz);
319 l = sizeof(buf) - (p - buf);
320
321 p += snprintf(p, l, ", HE-NSS %d", r->nss);
322 l = sizeof(buf) - (p - buf);
323
324 p += snprintf(p, l, ", HE-GI %d", r->he_gi);
325 l = sizeof(buf) - (p - buf);
326
327 p += snprintf(p, l, ", HE-DCM %d", r->he_dcm);
328 l = sizeof(buf) - (p - buf);
329 }
330 }
331
332 return buf;
333 }
334
335 static const char* format_chan_width(bool vht, uint8_t width)
336 {
337 if (!vht && width < ARRAY_SIZE(ht_chan_width))
338 switch (ht_chan_width[width]) {
339 case 20: return "20 MHz";
340 case 2040: return "40 MHz or higher";
341 }
342
343 if (vht && width < ARRAY_SIZE(vht_chan_width))
344 switch (vht_chan_width[width]) {
345 case 40: return "20 or 40 MHz";
346 case 80: return "80 MHz";
347 case 8080: return "80+80 MHz";
348 case 160: return "160 MHz";
349 }
350
351 return "unknown";
352 }
353
354
355 static const char * print_type(const struct iwinfo_ops *iw, const char *ifname)
356 {
357 const char *type = iwinfo_type(ifname);
358 return type ? type : "unknown";
359 }
360
361 static char * print_hardware_id(const struct iwinfo_ops *iw, const char *ifname)
362 {
363 static char buf[20];
364 struct iwinfo_hardware_id ids;
365
366 if (!iw->hardware_id(ifname, (char *)&ids))
367 {
368 if (strlen(ids.compatible) > 0)
369 snprintf(buf, sizeof(buf), "embedded");
370 else if (ids.vendor_id == 0 && ids.device_id == 0 &&
371 ids.subsystem_vendor_id != 0 && ids.subsystem_device_id != 0)
372 snprintf(buf, sizeof(buf), "USB %04X:%04X",
373 ids.subsystem_vendor_id, ids.subsystem_device_id);
374 else
375 snprintf(buf, sizeof(buf), "%04X:%04X %04X:%04X",
376 ids.vendor_id, ids.device_id,
377 ids.subsystem_vendor_id, ids.subsystem_device_id);
378 }
379 else
380 {
381 snprintf(buf, sizeof(buf), "unknown");
382 }
383
384 return buf;
385 }
386
387 static char * print_hardware_name(const struct iwinfo_ops *iw, const char *ifname)
388 {
389 static char buf[128];
390
391 if (iw->hardware_name(ifname, buf))
392 snprintf(buf, sizeof(buf), "unknown");
393
394 return buf;
395 }
396
397 static char * print_txpower_offset(const struct iwinfo_ops *iw, const char *ifname)
398 {
399 int off;
400 static char buf[12];
401
402 if (iw->txpower_offset(ifname, &off))
403 snprintf(buf, sizeof(buf), "unknown");
404 else if (off != 0)
405 snprintf(buf, sizeof(buf), "%d dB", off);
406 else
407 snprintf(buf, sizeof(buf), "none");
408
409 return buf;
410 }
411
412 static char * print_frequency_offset(const struct iwinfo_ops *iw, const char *ifname)
413 {
414 int off;
415 static char buf[12];
416
417 if (iw->frequency_offset(ifname, &off))
418 snprintf(buf, sizeof(buf), "unknown");
419 else if (off != 0)
420 snprintf(buf, sizeof(buf), "%.3f GHz", ((float)off / 1000.0));
421 else
422 snprintf(buf, sizeof(buf), "none");
423
424 return buf;
425 }
426
427 static char * print_ssid(const struct iwinfo_ops *iw, const char *ifname)
428 {
429 char buf[IWINFO_ESSID_MAX_SIZE+1] = { 0 };
430
431 if (iw->ssid(ifname, buf))
432 memset(buf, 0, sizeof(buf));
433
434 return format_ssid(buf);
435 }
436
437 static char * print_bssid(const struct iwinfo_ops *iw, const char *ifname)
438 {
439 static char buf[18] = { 0 };
440
441 if (iw->bssid(ifname, buf))
442 snprintf(buf, sizeof(buf), "00:00:00:00:00:00");
443
444 return buf;
445 }
446
447 static char * print_mode(const struct iwinfo_ops *iw, const char *ifname)
448 {
449 int mode;
450 static char buf[128];
451
452 if (iw->mode(ifname, &mode))
453 mode = IWINFO_OPMODE_UNKNOWN;
454
455 snprintf(buf, sizeof(buf), "%s", IWINFO_OPMODE_NAMES[mode]);
456
457 return buf;
458 }
459
460 static char * print_channel(const struct iwinfo_ops *iw, const char *ifname)
461 {
462 int ch;
463 if (iw->channel(ifname, &ch))
464 ch = -1;
465
466 return format_channel(ch);
467 }
468
469 static char * print_center_chan1(const struct iwinfo_ops *iw, const char *ifname)
470 {
471 int ch;
472 if (iw->center_chan1(ifname, &ch))
473 ch = -1;
474
475 return format_channel(ch);
476 }
477
478 static char * print_center_chan2(const struct iwinfo_ops *iw, const char *ifname)
479 {
480 int ch;
481 if (iw->center_chan2(ifname, &ch))
482 ch = -1;
483
484 return format_channel(ch);
485 }
486
487 static char * print_frequency(const struct iwinfo_ops *iw, const char *ifname)
488 {
489 int freq;
490 if (iw->frequency(ifname, &freq))
491 freq = -1;
492
493 return format_frequency(freq);
494 }
495
496 static char * print_txpower(const struct iwinfo_ops *iw, const char *ifname)
497 {
498 int pwr, off;
499 if (iw->txpower_offset(ifname, &off))
500 off = 0;
501
502 if (iw->txpower(ifname, &pwr))
503 pwr = -1;
504 else
505 pwr += off;
506
507 return format_txpower(pwr);
508 }
509
510 static char * print_quality(const struct iwinfo_ops *iw, const char *ifname)
511 {
512 int qual;
513 if (iw->quality(ifname, &qual))
514 qual = -1;
515
516 return format_quality(qual);
517 }
518
519 static char * print_quality_max(const struct iwinfo_ops *iw, const char *ifname)
520 {
521 int qmax;
522 if (iw->quality_max(ifname, &qmax))
523 qmax = -1;
524
525 return format_quality_max(qmax);
526 }
527
528 static char * print_signal(const struct iwinfo_ops *iw, const char *ifname)
529 {
530 int sig;
531 if (iw->signal(ifname, &sig))
532 sig = 0;
533
534 return format_signal(sig);
535 }
536
537 static char * print_noise(const struct iwinfo_ops *iw, const char *ifname)
538 {
539 int noise;
540 if (iw->noise(ifname, &noise))
541 noise = 0;
542
543 return format_noise(noise);
544 }
545
546 static char * print_rate(const struct iwinfo_ops *iw, const char *ifname)
547 {
548 int rate;
549 if (iw->bitrate(ifname, &rate))
550 rate = -1;
551
552 return format_rate(rate);
553 }
554
555 static char * print_encryption(const struct iwinfo_ops *iw, const char *ifname)
556 {
557 struct iwinfo_crypto_entry c = { 0 };
558 if (iw->encryption(ifname, (char *)&c))
559 return format_encryption(NULL);
560
561 return format_encryption(&c);
562 }
563
564 static char * print_hwmodes(const struct iwinfo_ops *iw, const char *ifname)
565 {
566 int modes;
567 if (iw->hwmodelist(ifname, &modes))
568 modes = -1;
569
570 return format_hwmodes(modes);
571 }
572
573 static const char *print_htmode(const struct iwinfo_ops *iw, const char *ifname)
574 {
575 int mode;
576 const char *name;
577 if (iw->htmode(ifname, &mode))
578 mode = -1;
579
580 name = iwinfo_htmode_name(mode);
581 if (name)
582 return name;
583
584 return "unknown";
585 }
586
587 static char * print_mbssid_supp(const struct iwinfo_ops *iw, const char *ifname)
588 {
589 int supp;
590 static char buf[4];
591
592 if (iw->mbssid_support(ifname, &supp))
593 snprintf(buf, sizeof(buf), "no");
594 else
595 snprintf(buf, sizeof(buf), "%s", supp ? "yes" : "no");
596
597 return buf;
598 }
599
600 static char * print_phyname(const struct iwinfo_ops *iw, const char *ifname)
601 {
602 static char buf[32];
603
604 if (!iw->phyname(ifname, buf))
605 return buf;
606
607 return "?";
608 }
609
610
611 static void print_info(const struct iwinfo_ops *iw, const char *ifname)
612 {
613 printf("%-9s ESSID: %s\n",
614 ifname,
615 print_ssid(iw, ifname));
616 printf(" Access Point: %s\n",
617 print_bssid(iw, ifname));
618 printf(" Mode: %s Channel: %s (%s) HT Mode: %s\n",
619 print_mode(iw, ifname),
620 print_channel(iw, ifname),
621 print_frequency(iw, ifname),
622 print_htmode(iw, ifname));
623 if (iw->center_chan1 != NULL) {
624 printf(" Center Channel 1: %s",
625 print_center_chan1(iw, ifname));
626 printf(" 2: %s\n", print_center_chan2(iw, ifname));
627 }
628 printf(" Tx-Power: %s Link Quality: %s/%s\n",
629 print_txpower(iw, ifname),
630 print_quality(iw, ifname),
631 print_quality_max(iw, ifname));
632 printf(" Signal: %s Noise: %s\n",
633 print_signal(iw, ifname),
634 print_noise(iw, ifname));
635 printf(" Bit Rate: %s\n",
636 print_rate(iw, ifname));
637 printf(" Encryption: %s\n",
638 print_encryption(iw, ifname));
639 printf(" Type: %s HW Mode(s): %s\n",
640 print_type(iw, ifname),
641 print_hwmodes(iw, ifname));
642 printf(" Hardware: %s [%s]\n",
643 print_hardware_id(iw, ifname),
644 print_hardware_name(iw, ifname));
645 printf(" TX power offset: %s\n",
646 print_txpower_offset(iw, ifname));
647 printf(" Frequency offset: %s\n",
648 print_frequency_offset(iw, ifname));
649 printf(" Supports VAPs: %s PHY name: %s\n",
650 print_mbssid_supp(iw, ifname),
651 print_phyname(iw, ifname));
652 }
653
654
655 static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname)
656 {
657 int i, x, len;
658 char buf[IWINFO_BUFSIZE];
659 struct iwinfo_scanlist_entry *e;
660
661 if (iw->scanlist(ifname, buf, &len))
662 {
663 printf("Scanning not possible\n\n");
664 return;
665 }
666 else if (len <= 0)
667 {
668 printf("No scan results\n\n");
669 return;
670 }
671
672 for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_scanlist_entry), x++)
673 {
674 e = (struct iwinfo_scanlist_entry *) &buf[i];
675
676 printf("Cell %02d - Address: %s\n",
677 x,
678 format_bssid(e->mac));
679 printf(" ESSID: %s\n",
680 format_ssid(e->ssid));
681 printf(" Mode: %s Frequency: %s Band: %s Channel: %s\n",
682 IWINFO_OPMODE_NAMES[e->mode],
683 format_frequency(e->mhz),
684 format_band(e->band),
685 format_channel(e->channel));
686 printf(" Signal: %s Quality: %s/%s\n",
687 format_signal(e->signal - 0x100),
688 format_quality(e->quality),
689 format_quality_max(e->quality_max));
690 printf(" Encryption: %s\n",
691 format_encryption(&e->crypto));
692 printf(" HT Operation:\n");
693 printf(" Primary Channel: %d\n",
694 e->ht_chan_info.primary_chan);
695 printf(" Secondary Channel Offset: %s\n",
696 ht_secondary_offset[e->ht_chan_info.secondary_chan_off]);
697 printf(" Channel Width: %s\n",
698 format_chan_width(false, e->ht_chan_info.chan_width));
699
700 if (e->vht_chan_info.center_chan_1) {
701 printf(" VHT Operation:\n");
702 printf(" Center Frequency 1: %d\n",
703 e->vht_chan_info.center_chan_1);
704 printf(" Center Frequency 2: %d\n",
705 e->vht_chan_info.center_chan_2);
706 printf(" Channel Width: %s\n",
707 format_chan_width(true, e->vht_chan_info.chan_width));
708 }
709
710 printf("\n");
711 }
712 }
713
714
715 static void print_txpwrlist(const struct iwinfo_ops *iw, const char *ifname)
716 {
717 int len, pwr, off, i;
718 char buf[IWINFO_BUFSIZE];
719 struct iwinfo_txpwrlist_entry *e;
720
721 if (iw->txpwrlist(ifname, buf, &len) || len <= 0)
722 {
723 printf("No TX power information available\n");
724 return;
725 }
726
727 if (iw->txpower(ifname, &pwr))
728 pwr = -1;
729
730 if (iw->txpower_offset(ifname, &off))
731 off = 0;
732
733 for (i = 0; i < len; i += sizeof(struct iwinfo_txpwrlist_entry))
734 {
735 e = (struct iwinfo_txpwrlist_entry *) &buf[i];
736
737 printf("%s%3d dBm (%4d mW)\n",
738 (pwr == e->dbm) ? "*" : " ",
739 e->dbm + off,
740 iwinfo_dbm2mw(e->dbm + off));
741 }
742 }
743
744
745 static void print_freqlist(const struct iwinfo_ops *iw, const char *ifname)
746 {
747 int i, len, freq;
748 char buf[IWINFO_BUFSIZE];
749 struct iwinfo_freqlist_entry *e;
750
751 if (iw->freqlist(ifname, buf, &len) || len <= 0)
752 {
753 printf("No frequency information available\n");
754 return;
755 }
756
757 if (iw->frequency(ifname, &freq))
758 freq = -1;
759
760 for (i = 0; i < len; i += sizeof(struct iwinfo_freqlist_entry))
761 {
762 e = (struct iwinfo_freqlist_entry *) &buf[i];
763
764 printf("%s %s (Band: %s, Channel %s) %s\n",
765 (freq == e->mhz) ? "*" : " ",
766 format_frequency(e->mhz),
767 format_band(e->band),
768 format_channel(e->channel),
769 format_freqflags(e->flags));
770 }
771 }
772
773
774 static void print_assoclist(const struct iwinfo_ops *iw, const char *ifname)
775 {
776 int i, len;
777 char buf[IWINFO_BUFSIZE];
778 struct iwinfo_assoclist_entry *e;
779
780 if (iw->assoclist(ifname, buf, &len))
781 {
782 printf("No information available\n");
783 return;
784 }
785 else if (len <= 0)
786 {
787 printf("No station connected\n");
788 return;
789 }
790
791 for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry))
792 {
793 e = (struct iwinfo_assoclist_entry *) &buf[i];
794
795 printf("%s %s / %s (SNR %d) %d ms ago\n",
796 format_bssid(e->mac),
797 format_signal(e->signal),
798 format_noise(e->noise),
799 (e->signal - e->noise),
800 e->inactive);
801
802 printf(" RX: %-38s %8d Pkts.\n",
803 format_assocrate(&e->rx_rate),
804 e->rx_packets
805 );
806
807 printf(" TX: %-38s %8d Pkts.\n",
808 format_assocrate(&e->tx_rate),
809 e->tx_packets
810 );
811
812 printf(" expected throughput: %s\n\n",
813 format_rate(e->thr));
814 }
815 }
816
817
818 static char * lookup_country(char *buf, int len, int iso3166)
819 {
820 int i;
821 struct iwinfo_country_entry *c;
822
823 for (i = 0; i < len; i += sizeof(struct iwinfo_country_entry))
824 {
825 c = (struct iwinfo_country_entry *) &buf[i];
826
827 if (c->iso3166 == iso3166)
828 return c->ccode;
829 }
830
831 return NULL;
832 }
833
834 static void print_countrylist(const struct iwinfo_ops *iw, const char *ifname)
835 {
836 int len;
837 char buf[IWINFO_BUFSIZE];
838 char *ccode;
839 char curcode[3];
840 const struct iwinfo_iso3166_label *l;
841
842 if (iw->countrylist(ifname, buf, &len))
843 {
844 printf("No country code information available\n");
845 return;
846 }
847
848 if (iw->country(ifname, curcode))
849 memset(curcode, 0, sizeof(curcode));
850
851 for (l = IWINFO_ISO3166_NAMES; l->iso3166; l++)
852 {
853 if ((ccode = lookup_country(buf, len, l->iso3166)) != NULL)
854 {
855 printf("%s %4s %c%c\n",
856 strncmp(ccode, curcode, 2) ? " " : "*",
857 ccode, (l->iso3166 / 256), (l->iso3166 % 256));
858 }
859 }
860 }
861
862 static void print_htmodelist(const struct iwinfo_ops *iw, const char *ifname)
863 {
864 int i, htmodes = 0;
865
866 if (iw->htmodelist(ifname, &htmodes))
867 {
868 printf("No HT mode information available\n");
869 return;
870 }
871
872 for (i = 0; i < IWINFO_HTMODE_COUNT; i++)
873 if (htmodes & (1 << i))
874 printf("%s ", IWINFO_HTMODE_NAMES[i]);
875
876 printf("\n");
877 }
878
879 static void lookup_phy(const struct iwinfo_ops *iw, const char *section)
880 {
881 char buf[IWINFO_BUFSIZE];
882
883 if (!iw->lookup_phy)
884 {
885 fprintf(stderr, "Not supported\n");
886 return;
887 }
888
889 if (iw->lookup_phy(section, buf))
890 {
891 fprintf(stderr, "Phy not found\n");
892 return;
893 }
894
895 printf("%s\n", buf);
896 }
897
898
899 static void lookup_path(const struct iwinfo_ops *iw, const char *phy)
900 {
901 const char *path;
902
903 if (!iw->phy_path || iw->phy_path(phy, &path) || !path)
904 return;
905
906 printf("%s\n", path);
907 }
908
909 int main(int argc, char **argv)
910 {
911 int i, rv = 0;
912 char *p;
913 const struct iwinfo_ops *iw;
914 glob_t globbuf;
915
916 if (argc > 1 && argc < 3)
917 {
918 fprintf(stderr,
919 "Usage:\n"
920 " iwinfo <device> info\n"
921 " iwinfo <device> scan\n"
922 " iwinfo <device> txpowerlist\n"
923 " iwinfo <device> freqlist\n"
924 " iwinfo <device> assoclist\n"
925 " iwinfo <device> countrylist\n"
926 " iwinfo <device> htmodelist\n"
927 " iwinfo <backend> phyname <section>\n"
928 );
929
930 return 1;
931 }
932
933 if (argc == 1)
934 {
935 glob("/sys/class/net/*", 0, NULL, &globbuf);
936
937 for (i = 0; i < globbuf.gl_pathc; i++)
938 {
939 p = strrchr(globbuf.gl_pathv[i], '/');
940
941 if (!p)
942 continue;
943
944 iw = iwinfo_backend(++p);
945
946 if (!iw)
947 continue;
948
949 print_info(iw, p);
950 printf("\n");
951 }
952
953 globfree(&globbuf);
954 return 0;
955 }
956
957 if (argc > 3)
958 {
959 iw = iwinfo_backend_by_name(argv[1]);
960
961 if (!iw)
962 {
963 fprintf(stderr, "No such wireless backend: %s\n", argv[1]);
964 rv = 1;
965 }
966 else
967 {
968 if (!strcmp(argv[2], "path")) {
969 lookup_path(iw, argv[3]);
970 return 0;
971 }
972 switch (argv[2][0])
973 {
974 case 'p':
975 lookup_phy(iw, argv[3]);
976 break;
977
978 default:
979 fprintf(stderr, "Unknown command: %s\n", argv[2]);
980 rv = 1;
981 }
982 }
983 }
984 else
985 {
986 iw = iwinfo_backend(argv[1]);
987
988 if (!iw)
989 {
990 fprintf(stderr, "No such wireless device: %s\n", argv[1]);
991 rv = 1;
992 }
993 else
994 {
995 for (i = 2; i < argc; i++)
996 {
997 switch(argv[i][0])
998 {
999 case 'i':
1000 print_info(iw, argv[1]);
1001 break;
1002
1003 case 's':
1004 print_scanlist(iw, argv[1]);
1005 break;
1006
1007 case 't':
1008 print_txpwrlist(iw, argv[1]);
1009 break;
1010
1011 case 'f':
1012 print_freqlist(iw, argv[1]);
1013 break;
1014
1015 case 'a':
1016 print_assoclist(iw, argv[1]);
1017 break;
1018
1019 case 'c':
1020 print_countrylist(iw, argv[1]);
1021 break;
1022
1023 case 'h':
1024 print_htmodelist(iw, argv[1]);
1025 break;
1026
1027 default:
1028 fprintf(stderr, "Unknown command: %s\n", argv[i]);
1029 rv = 1;
1030 }
1031 }
1032 }
1033 }
1034
1035 iwinfo_finish();
1036
1037 return rv;
1038 }