Root/package/iwinfo/src/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
21#include "iwinfo.h"
22
23
24static char * format_bssid(unsigned char *mac)
25{
26    static char buf[18];
27
28    snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X",
29        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
30
31    return buf;
32}
33
34static char * format_ssid(char *ssid)
35{
36    static char buf[IWINFO_ESSID_MAX_SIZE+3];
37
38    if (ssid && ssid[0])
39        snprintf(buf, sizeof(buf), "\"%s\"", ssid);
40    else
41        snprintf(buf, sizeof(buf), "unknown");
42
43    return buf;
44}
45
46static char * format_channel(int ch)
47{
48    static char buf[8];
49
50    if (ch <= 0)
51        snprintf(buf, sizeof(buf), "unknown");
52    else
53        snprintf(buf, sizeof(buf), "%d", ch);
54
55    return buf;
56}
57
58static char * format_frequency(int freq)
59{
60    static char buf[10];
61
62    if (freq <= 0)
63        snprintf(buf, sizeof(buf), "unknown");
64    else
65        snprintf(buf, sizeof(buf), "%.3f GHz", ((float)freq / 1000.0));
66
67    return buf;
68}
69
70static char * format_txpower(int pwr)
71{
72    static char buf[10];
73
74    if (pwr < 0)
75        snprintf(buf, sizeof(buf), "unknown");
76    else
77        snprintf(buf, sizeof(buf), "%d dBm", pwr);
78
79    return buf;
80}
81
82static char * format_quality(int qual)
83{
84    static char buf[8];
85
86    if (qual < 0)
87        snprintf(buf, sizeof(buf), "unknown");
88    else
89        snprintf(buf, sizeof(buf), "%d", qual);
90
91    return buf;
92}
93
94static char * format_quality_max(int qmax)
95{
96    static char buf[8];
97
98    if (qmax < 0)
99        snprintf(buf, sizeof(buf), "unknown");
100    else
101        snprintf(buf, sizeof(buf), "%d", qmax);
102
103    return buf;
104}
105
106static char * format_signal(int sig)
107{
108    static char buf[10];
109
110    if (!sig)
111        snprintf(buf, sizeof(buf), "unknown");
112    else
113        snprintf(buf, sizeof(buf), "%d dBm", sig);
114
115    return buf;
116}
117
118static char * format_noise(int noise)
119{
120    static char buf[10];
121
122    if (!noise)
123        snprintf(buf, sizeof(buf), "unknown");
124    else
125        snprintf(buf, sizeof(buf), "%d dBm", noise);
126
127    return buf;
128}
129
130static char * format_rate(int rate)
131{
132    static char buf[14];
133
134    if (rate <= 0)
135        snprintf(buf, sizeof(buf), "unknown");
136    else
137        snprintf(buf, sizeof(buf), "%d.%d MBit/s",
138            rate / 1000, (rate % 1000) / 100);
139
140    return buf;
141}
142
143static char * format_enc_ciphers(int ciphers)
144{
145    static char str[128] = { 0 };
146    char *pos = str;
147
148    if (ciphers & IWINFO_CIPHER_WEP40)
149        pos += sprintf(pos, "WEP-40, ");
150
151    if (ciphers & IWINFO_CIPHER_WEP104)
152        pos += sprintf(pos, "WEP-104, ");
153
154    if (ciphers & IWINFO_CIPHER_TKIP)
155        pos += sprintf(pos, "TKIP, ");
156
157    if (ciphers & IWINFO_CIPHER_CCMP)
158        pos += sprintf(pos, "CCMP, ");
159
160    if (ciphers & IWINFO_CIPHER_WRAP)
161        pos += sprintf(pos, "WRAP, ");
162
163    if (ciphers & IWINFO_CIPHER_AESOCB)
164        pos += sprintf(pos, "AES-OCB, ");
165
166    if (ciphers & IWINFO_CIPHER_CKIP)
167        pos += sprintf(pos, "CKIP, ");
168
169    if (!ciphers || (ciphers & IWINFO_CIPHER_NONE))
170        pos += sprintf(pos, "NONE, ");
171
172    *(pos - 2) = 0;
173
174    return str;
175}
176
177static char * format_enc_suites(int suites)
178{
179    static char str[64] = { 0 };
180    char *pos = str;
181
182    if (suites & IWINFO_KMGMT_PSK)
183        pos += sprintf(pos, "PSK/");
184
185    if (suites & IWINFO_KMGMT_8021x)
186        pos += sprintf(pos, "802.1X/");
187
188    if (!suites || (suites & IWINFO_KMGMT_NONE))
189        pos += sprintf(pos, "NONE/");
190
191    *(pos - 1) = 0;
192
193    return str;
194}
195
196static char * format_encryption(struct iwinfo_crypto_entry *c)
197{
198    static char buf[512];
199
200    if (!c)
201    {
202        snprintf(buf, sizeof(buf), "unknown");
203    }
204    else if (c->enabled)
205    {
206        /* WEP */
207        if (c->auth_algs && !c->wpa_version)
208        {
209            if ((c->auth_algs & IWINFO_AUTH_OPEN) &&
210                (c->auth_algs & IWINFO_AUTH_SHARED))
211            {
212                snprintf(buf, sizeof(buf), "WEP Open/Shared (%s)",
213                    format_enc_ciphers(c->pair_ciphers));
214            }
215            else if (c->auth_algs & IWINFO_AUTH_OPEN)
216            {
217                snprintf(buf, sizeof(buf), "WEP Open System (%s)",
218                    format_enc_ciphers(c->pair_ciphers));
219            }
220            else if (c->auth_algs & IWINFO_AUTH_SHARED)
221            {
222                snprintf(buf, sizeof(buf), "WEP Shared Auth (%s)",
223                    format_enc_ciphers(c->pair_ciphers));
224            }
225        }
226
227        /* WPA */
228        else if (c->wpa_version)
229        {
230            switch (c->wpa_version) {
231                case 3:
232                    snprintf(buf, sizeof(buf), "mixed WPA/WPA2 %s (%s)",
233                        format_enc_suites(c->auth_suites),
234                        format_enc_ciphers(c->pair_ciphers | c->group_ciphers));
235                    break;
236
237                case 2:
238                    snprintf(buf, sizeof(buf), "WPA2 %s (%s)",
239                        format_enc_suites(c->auth_suites),
240                        format_enc_ciphers(c->pair_ciphers | c->group_ciphers));
241                    break;
242
243                case 1:
244                    snprintf(buf, sizeof(buf), "WPA %s (%s)",
245                        format_enc_suites(c->auth_suites),
246                        format_enc_ciphers(c->pair_ciphers | c->group_ciphers));
247                    break;
248            }
249        }
250        else
251        {
252            snprintf(buf, sizeof(buf), "none");
253        }
254    }
255    else
256    {
257        snprintf(buf, sizeof(buf), "none");
258    }
259
260    return buf;
261}
262
263static char * format_hwmodes(int modes)
264{
265    static char buf[12];
266
267    if (modes <= 0)
268        snprintf(buf, sizeof(buf), "unknown");
269    else
270        snprintf(buf, sizeof(buf), "802.11%s%s%s%s",
271            (modes & IWINFO_80211_A) ? "a" : "",
272            (modes & IWINFO_80211_B) ? "b" : "",
273            (modes & IWINFO_80211_G) ? "g" : "",
274            (modes & IWINFO_80211_N) ? "n" : "");
275
276    return buf;
277}
278
279static char * format_assocrate(struct iwinfo_rate_entry *r)
280{
281    static char buf[40];
282    char *p = buf;
283    int l = sizeof(buf);
284
285    if (r->rate <= 0)
286    {
287        snprintf(buf, sizeof(buf), "unknown");
288    }
289    else
290    {
291        p += snprintf(p, l, "%s", format_rate(r->rate));
292        l = sizeof(buf) - (p - buf);
293
294        if (r->mcs >= 0)
295        {
296            p += snprintf(p, l, ", MCS %d, %dMHz", r->mcs, 20 + r->is_40mhz*20);
297            l = sizeof(buf) - (p - buf);
298
299            if (r->is_short_gi)
300                p += snprintf(p, l, ", short GI");
301        }
302    }
303
304    return buf;
305}
306
307
308static const char * print_type(const struct iwinfo_ops *iw, const char *ifname)
309{
310    const char *type = iwinfo_type(ifname);
311    return type ? type : "unknown";
312}
313
314static char * print_hardware_id(const struct iwinfo_ops *iw, const char *ifname)
315{
316    static char buf[20];
317    struct iwinfo_hardware_id ids;
318
319    if (!iw->hardware_id(ifname, (char *)&ids))
320    {
321        snprintf(buf, sizeof(buf), "%04X:%04X %04X:%04X",
322            ids.vendor_id, ids.device_id,
323            ids.subsystem_vendor_id, ids.subsystem_device_id);
324    }
325    else
326    {
327        snprintf(buf, sizeof(buf), "unknown");
328    }
329
330    return buf;
331}
332
333static char * print_hardware_name(const struct iwinfo_ops *iw, const char *ifname)
334{
335    static char buf[128];
336
337    if (iw->hardware_name(ifname, buf))
338        snprintf(buf, sizeof(buf), "unknown");
339
340    return buf;
341}
342
343static char * print_txpower_offset(const struct iwinfo_ops *iw, const char *ifname)
344{
345    int off;
346    static char buf[12];
347
348    if (iw->txpower_offset(ifname, &off))
349        snprintf(buf, sizeof(buf), "unknown");
350    else if (off != 0)
351        snprintf(buf, sizeof(buf), "%d dB", off);
352    else
353        snprintf(buf, sizeof(buf), "none");
354
355    return buf;
356}
357
358static char * print_frequency_offset(const struct iwinfo_ops *iw, const char *ifname)
359{
360    int off;
361    static char buf[12];
362
363    if (iw->frequency_offset(ifname, &off))
364        snprintf(buf, sizeof(buf), "unknown");
365    else if (off != 0)
366        snprintf(buf, sizeof(buf), "%.3f GHz", ((float)off / 1000.0));
367    else
368        snprintf(buf, sizeof(buf), "none");
369
370    return buf;
371}
372
373static char * print_ssid(const struct iwinfo_ops *iw, const char *ifname)
374{
375    char buf[IWINFO_ESSID_MAX_SIZE+1] = { 0 };
376
377    if (iw->ssid(ifname, buf))
378        memset(buf, 0, sizeof(buf));
379
380    return format_ssid(buf);
381}
382
383static char * print_bssid(const struct iwinfo_ops *iw, const char *ifname)
384{
385    static char buf[18] = { 0 };
386
387    if (iw->bssid(ifname, buf))
388        snprintf(buf, sizeof(buf), "00:00:00:00:00:00");
389
390    return buf;
391}
392
393static char * print_mode(const struct iwinfo_ops *iw, const char *ifname)
394{
395    int mode;
396    static char buf[128];
397
398    if (iw->mode(ifname, &mode))
399        mode = IWINFO_OPMODE_UNKNOWN;
400
401    snprintf(buf, sizeof(buf), "%s", IWINFO_OPMODE_NAMES[mode]);
402
403    return buf;
404}
405
406static char * print_channel(const struct iwinfo_ops *iw, const char *ifname)
407{
408    int ch;
409    if (iw->channel(ifname, &ch))
410        ch = -1;
411
412    return format_channel(ch);
413}
414
415static char * print_frequency(const struct iwinfo_ops *iw, const char *ifname)
416{
417    int freq;
418    if (iw->frequency(ifname, &freq))
419        freq = -1;
420
421    return format_frequency(freq);
422}
423
424static char * print_txpower(const struct iwinfo_ops *iw, const char *ifname)
425{
426    int pwr, off;
427    if (iw->txpower_offset(ifname, &off))
428        off = 0;
429
430    if (iw->txpower(ifname, &pwr))
431        pwr = -1;
432    else
433        pwr += off;
434
435    return format_txpower(pwr);
436}
437
438static char * print_quality(const struct iwinfo_ops *iw, const char *ifname)
439{
440    int qual;
441    if (iw->quality(ifname, &qual))
442        qual = -1;
443
444    return format_quality(qual);
445}
446
447static char * print_quality_max(const struct iwinfo_ops *iw, const char *ifname)
448{
449    int qmax;
450    if (iw->quality_max(ifname, &qmax))
451        qmax = -1;
452
453    return format_quality_max(qmax);
454}
455
456static char * print_signal(const struct iwinfo_ops *iw, const char *ifname)
457{
458    int sig;
459    if (iw->signal(ifname, &sig))
460        sig = 0;
461
462    return format_signal(sig);
463}
464
465static char * print_noise(const struct iwinfo_ops *iw, const char *ifname)
466{
467    int noise;
468    if (iw->noise(ifname, &noise))
469        noise = 0;
470
471    return format_noise(noise);
472}
473
474static char * print_rate(const struct iwinfo_ops *iw, const char *ifname)
475{
476    int rate;
477    if (iw->bitrate(ifname, &rate))
478        rate = -1;
479
480    return format_rate(rate);
481}
482
483static char * print_encryption(const struct iwinfo_ops *iw, const char *ifname)
484{
485    struct iwinfo_crypto_entry c = { 0 };
486    if (iw->encryption(ifname, (char *)&c))
487        return format_encryption(NULL);
488
489    return format_encryption(&c);
490}
491
492static char * print_hwmodes(const struct iwinfo_ops *iw, const char *ifname)
493{
494    int modes;
495    if (iw->hwmodelist(ifname, &modes))
496        modes = -1;
497
498    return format_hwmodes(modes);
499}
500
501static char * print_mbssid_supp(const struct iwinfo_ops *iw, const char *ifname)
502{
503    int supp;
504    static char buf[4];
505
506    if (iw->mbssid_support(ifname, &supp))
507        snprintf(buf, sizeof(buf), "no");
508    else
509        snprintf(buf, sizeof(buf), "%s", supp ? "yes" : "no");
510
511    return buf;
512}
513
514
515static void print_info(const struct iwinfo_ops *iw, const char *ifname)
516{
517    printf("%-9s ESSID: %s\n",
518        ifname,
519        print_ssid(iw, ifname));
520    printf(" Access Point: %s\n",
521        print_bssid(iw, ifname));
522    printf(" Mode: %s Channel: %s (%s)\n",
523        print_mode(iw, ifname),
524        print_channel(iw, ifname),
525        print_frequency(iw, ifname));
526    printf(" Tx-Power: %s Link Quality: %s/%s\n",
527        print_txpower(iw, ifname),
528        print_quality(iw, ifname),
529        print_quality_max(iw, ifname));
530    printf(" Signal: %s Noise: %s\n",
531        print_signal(iw, ifname),
532        print_noise(iw, ifname));
533    printf(" Bit Rate: %s\n",
534        print_rate(iw, ifname));
535    printf(" Encryption: %s\n",
536        print_encryption(iw, ifname));
537    printf(" Type: %s HW Mode(s): %s\n",
538        print_type(iw, ifname),
539        print_hwmodes(iw, ifname));
540    printf(" Hardware: %s [%s]\n",
541        print_hardware_id(iw, ifname),
542        print_hardware_name(iw, ifname));
543    printf(" TX power offset: %s\n",
544        print_txpower_offset(iw, ifname));
545    printf(" Frequency offset: %s\n",
546        print_frequency_offset(iw, ifname));
547    printf(" Supports VAPs: %s\n",
548        print_mbssid_supp(iw, ifname));
549}
550
551
552static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname)
553{
554    int i, x, len;
555    char buf[IWINFO_BUFSIZE];
556    struct iwinfo_scanlist_entry *e;
557
558    if (iw->scanlist(ifname, buf, &len))
559    {
560        printf("Scanning not possible\n\n");
561        return;
562    }
563    else if (len <= 0)
564    {
565        printf("No scan results\n\n");
566        return;
567    }
568
569    for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_scanlist_entry), x++)
570    {
571        e = (struct iwinfo_scanlist_entry *) &buf[i];
572
573        printf("Cell %02d - Address: %s\n",
574            x,
575            format_bssid(e->mac));
576        printf(" ESSID: %s\n",
577            format_ssid(e->ssid));
578        printf(" Mode: %s Channel: %s\n",
579            IWINFO_OPMODE_NAMES[e->mode],
580            format_channel(e->channel));
581        printf(" Signal: %s Quality: %s/%s\n",
582            format_signal(e->signal - 0x100),
583            format_quality(e->quality),
584            format_quality_max(e->quality_max));
585        printf(" Encryption: %s\n\n",
586            format_encryption(&e->crypto));
587    }
588}
589
590
591static void print_txpwrlist(const struct iwinfo_ops *iw, const char *ifname)
592{
593    int len, pwr, off, i;
594    char buf[IWINFO_BUFSIZE];
595    struct iwinfo_txpwrlist_entry *e;
596
597    if (iw->txpwrlist(ifname, buf, &len) || len <= 0)
598    {
599        printf("No TX power information available\n");
600        return;
601    }
602
603    if (iw->txpower(ifname, &pwr))
604        pwr = -1;
605
606    if (iw->txpower_offset(ifname, &off))
607        off = 0;
608
609    for (i = 0; i < len; i += sizeof(struct iwinfo_txpwrlist_entry))
610    {
611        e = (struct iwinfo_txpwrlist_entry *) &buf[i];
612
613        printf("%s%3d dBm (%4d mW)\n",
614            (pwr == e->dbm) ? "*" : " ",
615            e->dbm + off,
616            iwinfo_dbm2mw(e->dbm + off));
617    }
618}
619
620
621static void print_freqlist(const struct iwinfo_ops *iw, const char *ifname)
622{
623    int i, len, ch;
624    char buf[IWINFO_BUFSIZE];
625    struct iwinfo_freqlist_entry *e;
626
627    if (iw->freqlist(ifname, buf, &len) || len <= 0)
628    {
629        printf("No frequency information available\n");
630        return;
631    }
632
633    if (iw->channel(ifname, &ch))
634        ch = -1;
635
636    for (i = 0; i < len; i += sizeof(struct iwinfo_freqlist_entry))
637    {
638        e = (struct iwinfo_freqlist_entry *) &buf[i];
639
640        printf("%s %s (Channel %s)%s\n",
641            (ch == e->channel) ? "*" : " ",
642            format_frequency(e->mhz),
643            format_channel(e->channel),
644            e->restricted ? " [restricted]" : "");
645    }
646}
647
648
649static void print_assoclist(const struct iwinfo_ops *iw, const char *ifname)
650{
651    int i, len;
652    char buf[IWINFO_BUFSIZE];
653    struct iwinfo_assoclist_entry *e;
654
655    if (iw->assoclist(ifname, buf, &len))
656    {
657        printf("No information available\n");
658        return;
659    }
660    else if (len <= 0)
661    {
662        printf("No station connected\n");
663        return;
664    }
665
666    for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry))
667    {
668        e = (struct iwinfo_assoclist_entry *) &buf[i];
669
670        printf("%s %s / %s (SNR %d) %d ms ago\n",
671            format_bssid(e->mac),
672            format_signal(e->signal),
673            format_noise(e->noise),
674            (e->signal - e->noise),
675            e->inactive);
676
677        printf(" RX: %-38s %8d Pkts.\n",
678            format_assocrate(&e->rx_rate),
679            e->rx_packets
680        );
681
682        printf(" TX: %-38s %8d Pkts.\n\n",
683            format_assocrate(&e->tx_rate),
684            e->tx_packets
685        );
686    }
687}
688
689
690static char * lookup_country(char *buf, int len, int iso3166)
691{
692    int i;
693    struct iwinfo_country_entry *c;
694
695    for (i = 0; i < len; i += sizeof(struct iwinfo_country_entry))
696    {
697        c = (struct iwinfo_country_entry *) &buf[i];
698
699        if (c->iso3166 == iso3166)
700            return c->ccode;
701    }
702
703    return NULL;
704}
705
706static void print_countrylist(const struct iwinfo_ops *iw, const char *ifname)
707{
708    int len;
709    char buf[IWINFO_BUFSIZE];
710    char *ccode;
711    char curcode[3];
712    const struct iwinfo_iso3166_label *l;
713
714    if (iw->countrylist(ifname, buf, &len))
715    {
716        printf("No country code information available\n");
717        return;
718    }
719
720    if (iw->country(ifname, curcode))
721        memset(curcode, 0, sizeof(curcode));
722
723    for (l = IWINFO_ISO3166_NAMES; l->iso3166; l++)
724    {
725        if ((ccode = lookup_country(buf, len, l->iso3166)) != NULL)
726        {
727            printf("%s %4s %c%c\n",
728                strncmp(ccode, curcode, 2) ? " " : "*",
729                ccode, (l->iso3166 / 256), (l->iso3166 % 256));
730        }
731    }
732}
733
734
735int main(int argc, char **argv)
736{
737    int i;
738    const struct iwinfo_ops *iw;
739
740    if (argc < 3)
741    {
742        fprintf(stderr,
743            "Usage:\n"
744            " iwinfo <device> info\n"
745            " iwinfo <device> scan\n"
746            " iwinfo <device> txpowerlist\n"
747            " iwinfo <device> freqlist\n"
748            " iwinfo <device> assoclist\n"
749            " iwinfo <device> countrylist\n"
750        );
751
752        return 1;
753    }
754
755    iw = iwinfo_backend(argv[1]);
756
757    if (!iw)
758    {
759        fprintf(stderr, "No such wireless device: %s\n", argv[1]);
760        return 1;
761    }
762
763    for (i = 2; i < argc; i++)
764    {
765        switch(argv[i][0])
766        {
767        case 'i':
768            print_info(iw, argv[1]);
769            break;
770
771        case 's':
772            print_scanlist(iw, argv[1]);
773            break;
774
775        case 't':
776            print_txpwrlist(iw, argv[1]);
777            break;
778
779        case 'f':
780            print_freqlist(iw, argv[1]);
781            break;
782
783        case 'a':
784            print_assoclist(iw, argv[1]);
785            break;
786
787        case 'c':
788            print_countrylist(iw, argv[1]);
789            break;
790
791        default:
792            fprintf(stderr, "Unknown command: %s\n", argv[i]);
793            return 1;
794        }
795    }
796
797    iwinfo_finish();
798
799    return 0;
800}
801

Archive Download this file



interactive