source: src/router/libutils/wl.c @ 13540

Last change on this file since 13540 was 13540, checked in by eko, 3 years ago

use prefix for all builds

  • Property svn:executable set to *
File size: 42.4 KB
Line 
1/*
2 * Wireless network adapter utilities
3 *
4 * Copyright 2001-2003, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 * $Id: wl.c,v 1.3 2005/11/11 09:26:19 seg Exp $
13 */
14#include <string.h>
15#include <unistd.h>
16
17#include <typedefs.h>
18#include <bcmutils.h>
19#include <wlutils.h>
20#include <shutils.h>
21#include <utils.h>
22#include <bcmnvram.h>
23#include <math.h>
24
25struct nvram_tuple router_defaults[] = {
26        {0, 0, 0}
27};
28
29/*
30 * DD-WRT addition (loaned from radauth)
31 */
32
33#ifndef HAVE_MADWIFI
34
35#ifdef HAVE_RT2880
36char *getRADev(char *prefix)
37{
38        char *ifname = NULL;
39
40        if (!strcmp(prefix, "wl0"))
41                ifname = "ra0";
42        if (!strcmp(prefix, "wl0.1"))
43                ifname = "ra1";
44        if (!strcmp(prefix, "wl0.2"))
45                ifname = "ra2";
46        if (!strcmp(prefix, "wl0.3"))
47                ifname = "ra3";
48        if (!strcmp(prefix, "wl0.4"))
49                ifname = "ra4";
50        if (!strcmp(prefix, "wl0.5"))
51                ifname = "ra5";
52        if (!strcmp(prefix, "wl0.6"))
53                ifname = "ra6";
54        if (!strcmp(prefix, "wl0.7"))
55                ifname = "ra7";
56        if (ifname)
57                return ifname;
58        else
59                return prefix;
60}
61
62int has_5ghz(char *prefix)
63{
64        if (strstr(nvram_nget("%s_bandlist", prefix), "a"))
65                return 1;
66
67        return 0;
68}
69
70int has_2ghz(char *prefix)
71{
72        if (strstr(nvram_nget("%s_bandlist", prefix), "b"))
73                return 1;
74
75        return 0;
76}
77
78int getchannels(unsigned int *list, char *ifname)
79{
80        list[0] = 1;
81        list[1] = 2;
82        list[2] = 3;
83        list[3] = 4;
84        list[4] = 5;
85        list[5] = 6;
86        list[6] = 7;
87        list[7] = 8;
88        list[8] = 9;
89        list[9] = 10;
90        list[10] = 11;
91        list[11] = 12;
92        list[12] = 13;
93#ifdef BUFFALO_JP
94        list[13] = 14;
95        return 14;
96#else
97        return 13;
98#endif
99}
100
101#include <sys/types.h>
102#include <sys/file.h>
103#include <sys/ioctl.h>
104#include <sys/socket.h>
105#include <stdio.h>
106#include <stdlib.h>
107#include <string.h>
108#include <stdint.h>
109#include <ctype.h>
110#include <getopt.h>
111#include <err.h>
112#include <linux/socket.h>
113#include <linux/if.h>
114
115#include "wireless.h"
116
117u_int ieee80211_mhz2ieee(u_int freq)
118{
119        if (freq == 2484)
120                return 14;
121        if (freq < 2484) {
122                int chan = (freq - (2407)) / 5;
123                if (chan < 0)
124                        chan += 256;
125                return chan;
126        }
127        if (freq < 2502)
128                return 14;
129        if (freq < 2512)
130                return 15;
131        if (freq < 4990 && freq > 4940)
132                return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
133        if (freq < 5000)
134                return 15 + ((freq - (2512)) / 20);
135
136        return (freq - (5000)) / 5;
137}
138
139unsigned int ieee80211_ieee2mhz(unsigned int chan)
140{
141        if (chan == 14)
142                return 2484;
143        if (chan < 14)
144                return ((2407) + chan * 5);
145        else if (chan < 27)
146                return ((2512) + ((chan - 15) * 20));
147        else {
148                if (chan > 212 && chan < 256) {
149                        //recalculate offset
150                        int newchan = chan - 256;
151                        int newfreq = (2407) + (newchan * 5);
152
153                        return newfreq;
154                } else
155                        return ((2512) + ((chan - 15) * 20));
156        }
157}
158
159int wifi_getchannel(char *ifname)
160{
161        struct iwreq wrq;
162        double freq;
163        int channel;
164
165        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
166        ioctl(getsocket(), SIOCGIWFREQ, &wrq);
167
168        int i;
169
170        freq = (float)wrq.u.freq.m;
171        if (freq < 1000.0f) {
172                return (int)freq;
173        }
174
175        freq = (double)wrq.u.freq.m;
176        for (i = 0; i < wrq.u.freq.e; i++)
177                freq *= 10.0;
178        freq /= 1000000.0;
179        cprintf("wifi channel %f\n", freq);
180        channel = ieee80211_mhz2ieee(freq);
181
182        return channel;
183}
184
185int wifi_getfreq(char *ifname)
186{
187        struct iwreq wrq;
188        double freq;
189
190        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
191        ioctl(getsocket(), SIOCGIWFREQ, &wrq);
192
193        int i;
194
195        freq = (float)wrq.u.freq.m;
196        if (freq < 1000.0f) {
197                return ieee80211_ieee2mhz((unsigned int)freq);
198        }
199        freq = (double)wrq.u.freq.m;
200        for (i = 0; i < wrq.u.freq.e; i++)
201                freq *= 10.0;
202        freq /= 1000000.0;
203        cprintf("wifi channel %f\n", freq);
204        return freq;
205}
206
207float wifi_getrate(char *ifname)
208{
209        struct iwreq wrq;
210
211        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
212        ioctl(getsocket(), SIOCGIWRATE, &wrq);
213        return wrq.u.bitrate.value;
214}
215
216int get_radiostate(char *ifname)
217{
218        char mode[32];
219
220        sprintf(mode, "%s_net_mode", ifname);
221        if (nvram_match(mode, "disabled"))
222                return 0;
223        struct ifreq ifr;
224        int skfd = getsocket();
225
226        strncpy(ifr.ifr_name, "ra0", sizeof(ifr.ifr_name));
227        if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
228                return -1;
229        }
230        if ((ifr.ifr_flags & IFF_UP)) {
231                return 1;
232        }
233        return 0;
234}
235
236static const char *ieee80211_ntoa(const uint8_t mac[6])
237{
238        static char a[18];
239        int i;
240
241        i = snprintf(a, sizeof(a), "%02x:%02x:%02x:%02x:%02x:%02x",
242                     mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
243        return (i < 17 ? NULL : a);
244}
245
246typedef union _MACHTTRANSMIT_SETTING {
247        struct {
248                unsigned short MCS:7;   // MCS
249                unsigned short BW:1;    //channel bandwidth 20MHz or 40 MHz
250                unsigned short ShortGI:1;
251                unsigned short STBC:2;  //SPACE
252                unsigned short rsv:3;
253                unsigned short MODE:2;  // Use definition MODE_xxx.
254        } field;
255        unsigned short word;
256} MACHTTRANSMIT_SETTING;
257
258typedef struct _RT_802_11_MAC_ENTRY {
259        unsigned char Addr[6];
260        unsigned char Aid;
261        unsigned char Psm;      // 0:PWR_ACTIVE, 1:PWR_SAVE
262        unsigned char MimoPs;   // 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled
263        char AvgRssi0;
264        char AvgRssi1;
265        char AvgRssi2;
266        unsigned int ConnectedTime;
267        MACHTTRANSMIT_SETTING TxRate;
268} RT_802_11_MAC_ENTRY;
269
270typedef struct _RT_802_11_MAC_TABLE {
271        unsigned long Num;
272        RT_802_11_MAC_ENTRY Entry[128]; //MAX_LEN_OF_MAC_TABLE = 32
273} RT_802_11_MAC_TABLE;
274
275typedef struct STAINFO {
276        char mac[6];
277        char rssi;
278        char noise;
279        char ifname[32];
280} STAINFO;
281
282int OidQueryInformation(unsigned long OidQueryCode, int socket_id,
283                        char *DeviceName, void *ptr, unsigned long PtrLength)
284{
285        struct iwreq wrq;
286
287        strcpy(wrq.ifr_name, DeviceName);
288        wrq.u.data.length = PtrLength;
289        wrq.u.data.pointer = (caddr_t) ptr;
290        wrq.u.data.flags = OidQueryCode;
291
292        return (ioctl(socket_id, (SIOCIWFIRSTPRIV + 0x0E), &wrq));
293}
294
295#include "stapriv.h"
296#include "oid.h"
297
298STAINFO *getRaStaInfo(char *ifname)
299{
300        char G_bRadio = 1;      //TRUE
301
302        int ConnectStatus = 0;
303        unsigned char BssidQuery[6];
304
305        if (!nvram_nmatch("sta", "%s_mode", ifname)
306            && !nvram_nmatch("apsta", "%s_mode", ifname)
307            && !nvram_nmatch("apstawet", "%s_mode", ifname)) {
308                return NULL;
309        }
310        char *ifn = "ra0";
311
312        if (nvram_nmatch("apsta", "%s_mode", ifname)
313            || nvram_nmatch("apstawet", "%s_mode", ifname))
314                ifn = "apcli0";
315
316        int s;
317
318        s = getsocket();
319        if (OidQueryInformation
320            (OID_GEN_MEDIA_CONNECT_STATUS, s, ifn, &ConnectStatus,
321             sizeof(ConnectStatus)) < 0) {
322                return NULL;
323        }
324        if (OidQueryInformation
325            (RT_OID_802_11_RADIO, s, ifn, &G_bRadio, sizeof(G_bRadio)) < 0) {
326                return NULL;
327        }
328        if (G_bRadio && ConnectStatus == 1) {
329                memset(&BssidQuery, 0x00, sizeof(BssidQuery));
330                OidQueryInformation(OID_802_11_BSSID, s, ifn, &BssidQuery,
331                                    sizeof(BssidQuery));
332                long RSSI;
333                int nNoiseDbm;
334                unsigned char lNoise;   // this value is (ULONG) in Ndis driver (NOTICE!!!)
335
336                OidQueryInformation(RT_OID_802_11_RSSI, s, ifn, &RSSI,
337                                    sizeof(RSSI));
338                OidQueryInformation(RT_OID_802_11_QUERY_NOISE_LEVEL, s, "ra0",
339                                    &lNoise, sizeof(lNoise));
340                nNoiseDbm = lNoise;
341                nNoiseDbm -= 143;
342
343                STAINFO *ret = malloc(sizeof(STAINFO));
344
345                memcpy(ret->mac, BssidQuery, 6);
346                strcpy(ret->ifname, ifn);
347                ret->rssi = RSSI;
348                ret->noise = nNoiseDbm;
349                return ret;
350        }
351        return NULL;
352
353}
354
355#define RTPRIV_IOCTL_GET_MAC_TABLE              (SIOCIWFIRSTPRIV + 0x0F)
356
357int getassoclist(char *ifname, unsigned char *list)
358{
359        struct iwreq iwr;
360        char type[32];
361        char netmode[32];
362        unsigned int *count = (unsigned int *)list;
363
364        RT_802_11_MAC_TABLE table = { 0 };
365        int s, i;
366
367        sprintf(type, "%s_mode", ifname);
368        sprintf(netmode, "%s_net_mode", ifname);
369        if (nvram_match(netmode, "disabled")) {
370                return 0;
371        }
372
373        int state = get_radiostate(ifname);
374        int ignore = 0;
375
376        if (state == 0 || state == -1) {
377                ignore = 1;
378        }
379        if (!ignore) {
380                s = getsocket();
381                if (s < 0) {
382                        ignore = 1;
383                }
384                (void)memset(&iwr, 0, sizeof(struct iwreq));
385                (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
386
387                iwr.u.data.pointer = (caddr_t) & table;
388                if (ioctl(s, RTPRIV_IOCTL_GET_MAC_TABLE, &iwr) < 0) {
389                        ignore = 1;
390                }
391        }
392
393        unsigned char *l = (unsigned char *)list;
394
395        count[0] = 0;
396        l += 4;
397        STAINFO *sta = getRaStaInfo(ifname);
398
399        if (sta != NULL) {
400                memcpy(l, sta->mac, 6);
401                l += 6;
402                count[0]++;
403                free(sta);
404        }
405        if (!ignore && table.Num < 128)
406                for (i = 0; i < table.Num; i++) {
407                        memcpy(l, &table.Entry[i].Addr, 6);
408                        if (l[0] == 0 && l[1] == 0 && l[2] == 0 && l[3] == 0
409                            && l[4] == 0 && l[5] == 0)
410                                break;
411                        l += 6;
412                        count[0]++;
413                }
414
415        return count[0];
416}
417
418int getRssi(char *ifname, unsigned char *mac)
419{
420        struct iwreq iwr;
421        char type[32];
422        char netmode[32];
423
424        RT_802_11_MAC_TABLE table = { 0 };
425        int s, i;
426
427        sprintf(type, "%s_mode", ifname);
428        sprintf(netmode, "%s_net_mode", ifname);
429        if (nvram_match(netmode, "disabled")) {
430                return 0;
431        }
432
433        int state = get_radiostate(ifname);
434        int ignore = 0;
435
436        if (state == 0 || state == -1) {
437                ignore = 1;
438        }
439        if (!ignore) {
440                s = getsocket();
441                if (s < 0) {
442                        ignore = 1;
443                }
444                (void)memset(&iwr, 0, sizeof(struct iwreq));
445                (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
446
447                iwr.u.data.pointer = (caddr_t) & table;
448                if (ioctl(s, RTPRIV_IOCTL_GET_MAC_TABLE, &iwr) < 0) {
449                        ignore = 1;
450                }
451        }
452
453        STAINFO *sta = getRaStaInfo(ifname);
454
455        if (sta != NULL) {
456                if (!memcmp(mac, sta->mac, 6)) {
457                        int retu = sta->rssi;
458
459                        free(sta);
460                        return -95 + retu;
461                }
462                free(sta);
463        }
464        if (!ignore && table.Num < 128)
465                for (i = 0; i < table.Num; i++) {
466                        if (!memcmp(mac, &table.Entry[i].Addr, 6)) {
467                                return -95 + table.Entry[i].AvgRssi0;
468                        }
469                }
470        return 0;
471}
472
473int getNoise(char *ifname, unsigned char *mac)
474{
475
476        return -95;
477
478}
479
480int getUptime(char *ifname, unsigned char *mac)
481{
482        return 0;
483}
484
485#else
486int getchannels(unsigned int *list, char *ifname)
487{
488        // int ret, num;
489        // num = (sizeof (*list) - 4) / 6; /* Maximum number of entries in the
490        // buffer */
491        // memcpy (list, &num, 4); /* First 4 bytes are the number of ent. */
492
493        // ret = wl_ioctl (name, WLC_GET_VALID_CHANNELS, list, 128);
494        // fprintf(stderr,"get channels\n");
495        char exec[64];
496
497        sprintf(exec, "wl -i %s channels", ifname);
498        FILE *in = popen(exec, "r");
499
500        int chan;
501        int count = 0;
502
503        while (!feof(in) && fscanf(in, "%d", &chan) == 1) {
504                list[count++] = chan;
505        }
506        pclose(in);
507#ifdef BUFFALO_JP
508        return count - 1;
509#else
510        return count;
511#endif
512}
513
514int has_5ghz(char *prefix)
515{
516        if (strstr(nvram_nget("%s_bandlist", prefix), "a"))
517                return 1;
518
519        return 0;
520}
521
522int has_2ghz(char *prefix)
523{
524        if (strstr(nvram_nget("%s_bandlist", prefix), "b"))
525                return 1;
526
527        return 0;
528}
529
530int wl_getbssid(char *wl, char *mac)
531{
532        int ret;
533        struct ether_addr ea;
534
535        wl_ioctl(wl, WLC_GET_BSSID, &ea, ETHER_ADDR_LEN);
536        ether_etoa(&ea, mac);
537        return 0;
538}
539
540int getassoclist(char *name, unsigned char *list)
541{
542        // int ap;
543        // if ((wl_ioctl(name, WLC_GET_AP, &ap, sizeof(ap)) < 0) || ap)
544        // {
545        int ret;
546        unsigned int num;
547
548        num = (sizeof(*list) - 4) / 6;  /* Maximum number of entries in the
549                                         * buffer */
550        memcpy(list, &num, 4);  /* First 4 bytes are the number of ent. */
551
552        ret = wl_ioctl(name, WLC_GET_ASSOCLIST, list, 8192);
553        unsigned int *count = (unsigned int *)list;
554
555        // }else
556        // {
557        // char buf[WLC_IOCTL_MAXLEN];
558        /*
559         * wl_bss_info_t *bss_info = (wl_bss_info_t *) buf;
560         * memset(buf,0,WLC_IOCTL_MAXLEN); if (wl_ioctl(name, WLC_GET_BSS_INFO,
561         * bss_info, WLC_IOCTL_MAXLEN)<0)return 0; struct maclist *l = (struct
562         * maclist*)list;
563         */
564        /*
565         * sta_info_t *sta_info = (sta_info_t *) buf;
566         * memset(buf,0,WLC_IOCTL_MAXLEN); if (wl_ioctl(name, WLC_GET_VAR,
567         * sta_info, WLC_IOCTL_MAXLEN)<0)return 0;
568         *
569         * struct maclist *l = (struct maclist*)list; l->count=1;
570         * memcpy(&l->ea,&sta_info->ea,6);
571         */
572        if (ret < 0)
573                return -1;
574        return count[0];
575}
576#endif
577
578int getwdslist(char *name, unsigned char *list)
579{
580        int ret, num;
581
582        num = (sizeof(*list) - 4) / 6;  /* Maximum number of entries in the
583                                         * buffer */
584        memcpy(list, &num, 4);  /* First 4 bytes are the number of ent. */
585
586        ret = wl_ioctl(name, WLC_GET_WDSLIST, list, 8192);
587
588        return (ret);
589}
590
591#ifndef HAVE_RT2880
592int getNoise(char *ifname, unsigned char *macname)
593{
594        unsigned int noise;
595
596        // rssi = 0;
597        // char buf[WLC_IOCTL_MAXLEN];
598        wl_ioctl(ifname, WLC_GET_PHY_NOISE, &noise, sizeof(noise));
599
600        /*
601         * wl_bss_info_t *bss_info = (wl_bss_info_t *) buf;
602         * memset(buf,0,WLC_IOCTL_MAXLEN);
603         *
604         * wl_ioctl(name, WLC_GET_BSS_INFO, bss_info, WLC_IOCTL_MAXLEN); if
605         * ((wl_ioctl(name, WLC_GET_AP, &ap, sizeof(ap)) < 0) || ap) { if
606         * (wl_ioctl(name, WLC_GET_PHY_NOISE, &noise, sizeof(noise)) < 0) noise =
607         * 0; } else { // somehow the structure doesn't fit here rssi = buf[82];
608         * noise = buf[84]; }
609         */
610        return noise;
611}
612
613int getUptime(char *ifname, unsigned char *mac)
614{
615        return 0;
616}
617
618#endif
619/*
620 * struct iw_statistics *wlcompat_get_wireless_stats(struct net_device *dev)
621 * { wl_bss_info_t *bss_info = (wl_bss_info_t *) buf; get_pktcnt_t pkt;
622 * unsigned int rssi, noise, ap;
623 *
624 * memset(&wstats, 0, sizeof(wstats)); memset(&pkt, 0, sizeof(pkt));
625 * memset(buf, 0, sizeof(buf)); bss_info->version = 0x2000; wl_ioctl(dev,
626 * WLC_GET_BSS_INFO, bss_info, WLC_IOCTL_MAXLEN); wl_ioctl(dev,
627 * WLC_GET_PKTCNTS, &pkt, sizeof(pkt));
628 *
629 * rssi = 0; if ((wl_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap)) < 0) || ap) { if
630 * (wl_ioctl(dev, WLC_GET_PHY_NOISE, &noise, sizeof(noise)) < 0) noise = 0; }
631 * else { // somehow the structure doesn't fit here rssi = buf[82]; noise =
632 * buf[84]; } rssi = (rssi == 0 ? 1 : rssi); wstats.qual.updated = 0x10; if
633 * (rssi <= 1) wstats.qual.updated |= 0x20; if (noise <= 1)
634 * wstats.qual.updated |= 0x40;
635 *
636 * if ((wstats.qual.updated & 0x60) == 0x60) return NULL;
637 *
638 * wstats.qual.level = rssi; wstats.qual.noise = noise; wstats.discard.misc =
639 * pkt.rx_bad_pkt; wstats.discard.retries = pkt.tx_bad_pkt;
640 *
641 * return &wstats; }
642 */
643#else
644#include <sys/types.h>
645#include <sys/file.h>
646#include <sys/ioctl.h>
647#include <sys/socket.h>
648#include <stdio.h>
649#include <stdlib.h>
650#include <string.h>
651#include <stdint.h>
652#include <ctype.h>
653#include <getopt.h>
654#include <err.h>
655
656#include "wireless.h"
657#undef WPA_OUI
658#undef WME_OUI
659#include "../madwifi.dev/madwifi.dev/net80211/ieee80211.h"
660#include "../madwifi.dev/madwifi.dev/net80211/ieee80211_crypto.h"
661#include "../madwifi.dev/madwifi.dev/net80211/ieee80211_ioctl.h"
662
663int getsocket(void)
664{
665        static int s = -1;
666
667        if (s < 0) {
668                s = socket(AF_INET, SOCK_DGRAM, 0);
669                if (s < 0)
670                        err(1, "socket(SOCK_DGRAM)");
671        }
672        return s;
673}
674
675/*
676 * Atheros
677 */
678
679#define IOCTL_ERR(x) [x - SIOCIWFIRSTPRIV] "ioctl[" #x "]"
680static int
681set80211priv(struct iwreq *iwr, const char *ifname, int op, void *data,
682             size_t len)
683{
684#define N(a)    (sizeof(a)/sizeof(a[0]))
685
686        memset(iwr, 0, sizeof(struct iwreq));
687        strncpy(iwr->ifr_name, ifname, IFNAMSIZ);
688        if (len < IFNAMSIZ) {
689                /*
690                 * Argument data fits inline; put it there.
691                 */
692                memcpy(iwr->u.name, data, len);
693        } else {
694                /*
695                 * Argument data too big for inline transfer; setup a
696                 * parameter block instead; the kernel will transfer
697                 * the data for the driver.
698                 */
699                iwr->u.data.pointer = data;
700                iwr->u.data.length = len;
701        }
702
703        if (ioctl(getsocket(), op, iwr) < 0) {
704                static const char *opnames[] = {
705                        IOCTL_ERR(IEEE80211_IOCTL_SETPARAM),
706                        IOCTL_ERR(IEEE80211_IOCTL_GETPARAM),
707                        IOCTL_ERR(IEEE80211_IOCTL_SETMODE),
708                        IOCTL_ERR(IEEE80211_IOCTL_GETMODE),
709                        IOCTL_ERR(IEEE80211_IOCTL_SETWMMPARAMS),
710                        IOCTL_ERR(IEEE80211_IOCTL_GETWMMPARAMS),
711                        IOCTL_ERR(IEEE80211_IOCTL_SETCHANLIST),
712                        IOCTL_ERR(IEEE80211_IOCTL_GETCHANLIST),
713                        IOCTL_ERR(IEEE80211_IOCTL_CHANSWITCH),
714                        IOCTL_ERR(IEEE80211_IOCTL_GETCHANINFO),
715                        IOCTL_ERR(IEEE80211_IOCTL_SETOPTIE),
716                        IOCTL_ERR(IEEE80211_IOCTL_GETOPTIE),
717                        IOCTL_ERR(IEEE80211_IOCTL_SETMLME),
718                        IOCTL_ERR(IEEE80211_IOCTL_SETKEY),
719                        IOCTL_ERR(IEEE80211_IOCTL_DELKEY),
720                        IOCTL_ERR(IEEE80211_IOCTL_ADDMAC),
721                        IOCTL_ERR(IEEE80211_IOCTL_DELMAC),
722                };
723                op -= SIOCIWFIRSTPRIV;
724                if (0 <= op && op < N(opnames))
725                        perror(opnames[op]);
726                else
727                        perror("ioctl[unknown???]");
728                return -1;
729        }
730        return 0;
731#undef N
732}
733
734int do80211priv(const char *ifname, int op, void *data, size_t len)
735{
736        struct iwreq iwr;
737
738        if (set80211priv(&iwr, ifname, op, data, len) < 0)
739                return -1;
740        if (len < IFNAMSIZ)
741                memcpy(data, iwr.u.name, len);
742        return iwr.u.data.length;
743}
744
745float wifi_getrate(char *ifname)
746{
747        struct iwreq wrq;
748
749        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
750        ioctl(getsocket(), SIOCGIWRATE, &wrq);
751        return wrq.u.bitrate.value;
752}
753
754/*
755 * For doing log10/exp10 without libm
756 */
757#define LOG10_MAGIC     1.25892541179
758
759int iw_mwatt2dbm(int in)
760{
761        /*
762         * Version without libm : slower
763         */
764        double fin = (double)in;
765        int res = 0;
766
767        /*
768         * Split integral and floating part to avoid accumulating rounding errors
769         */
770        while (fin > 10.0) {
771                res += 10;
772                fin /= 10.0;
773        }
774        while (fin > 1.000001) {        /* Eliminate rounding errors, take ceil */
775                res += 1;
776                fin /= LOG10_MAGIC;
777        }
778        return (res);
779}
780
781int isEMP(char *ifname)         //checks if its usually a emp card (no concrete detection possible)
782{
783        int vendor;
784        int product;
785        int devcount;
786        char readid[64];
787
788        strcpy(readid, ifname);
789        sscanf(readid, "ath%d", &devcount);
790        sprintf(readid, "/proc/sys/dev/wifi%d/idvendor", devcount);
791        FILE *in = fopen(readid, "rb");
792        vendor = 0;
793        if (in) {
794                fscanf(in, "%d", &vendor);
795                fclose(in);
796        }
797        sprintf(readid, "/proc/sys/dev/wifi%d/idproduct", devcount);
798        in = fopen(readid, "rb");
799        product = 0;
800        if (in) {
801                fscanf(in, "%d", &product);
802                fclose(in);
803        }
804        if (vendor == 0x168c && product == 0x2062)
805                return 1;
806        if (vendor == 0x168c && product == 0x2063)      //will include more suspicius cards.
807                return 1;
808        return 0;
809
810}
811
812int isXR36(char *ifname)        //checks if its usually a emp card (no concrete detection possible)
813{
814        int vendor;
815        int product;
816        int devcount;
817        char readid[64];
818
819        strcpy(readid, ifname);
820        sscanf(readid, "ath%d", &devcount);
821        sprintf(readid, "/proc/sys/dev/wifi%d/idvendor", devcount);
822        FILE *in = fopen(readid, "rb");
823        vendor = 0;
824        if (in) {
825                fscanf(in, "%d", &vendor);
826                fclose(in);
827        }
828        sprintf(readid, "/proc/sys/dev/wifi%d/idproduct", devcount);
829        in = fopen(readid, "rb");
830        product = 0;
831        if (in) {
832                fscanf(in, "%d", &product);
833                fclose(in);
834        }
835        if (vendor == 0x0777 && product == 0x3c03)      //XR3.3/XR3.6/XR3.7 share the same pci id's
836                return 1;
837        return 0;
838
839}
840
841int wifi_gettxpower(char *ifname)
842{
843        int poweroffset = 0;
844
845#ifdef HAVE_ALPHA
846        poweroffset = 10;
847#elif HAVE_EOC1650
848        poweroffset = 0;
849#elif HAVE_BWRG1000
850        poweroffset = 12;       //?? guess
851#elif HAVE_EAP3660
852        poweroffset = 8;
853#elif HAVE_EOC2610
854        poweroffset = 8;
855#elif HAVE_EOC5610
856        poweroffset = 0;        // does not need a offset, internally mapped
857#elif HAVE_NS2
858        poweroffset = 10;
859#elif HAVE_LC2
860        poweroffset = 10;
861#elif HAVE_BS2
862        poweroffset = 0;
863#elif HAVE_PICO2
864        poweroffset = 0;
865#elif HAVE_PICO2HP
866        poweroffset = 10;
867#elif HAVE_MS2
868        poweroffset = 10;
869#elif HAVE_BS2HP
870        poweroffset = 10;
871#elif HAVE_NS5
872        poweroffset = 5;
873#elif HAVE_PICO5
874        poweroffset = 5;
875#elif HAVE_DLM101
876        poweroffset = 5;
877#elif HAVE_NS3
878        poweroffset = 5;
879#elif HAVE_LC5
880        poweroffset = 5;
881#elif HAVE_BS5
882        poweroffset = 5;
883#elif HAVE_LS5
884        poweroffset = 5;
885#else
886
887        if (isEMP(ifname)) {
888                if (nvram_nmatch("2", "%s_cardtype", ifname))
889                        poweroffset = 8;
890                if (nvram_nmatch("3", "%s_cardtype", ifname))
891                        poweroffset = 8;
892                if (nvram_nmatch("5", "%s_cardtype", ifname))
893                        poweroffset = 8;
894                if (nvram_nmatch("6", "%s_cardtype", ifname))
895                        poweroffset = 7;
896                if (nvram_nmatch("7", "%s_cardtype", ifname))
897                        poweroffset = 10;
898        } else {
899                int vendor;
900                int devcount;
901                char readid[64];
902
903                strcpy(readid, ifname);
904                sscanf(readid, "ath%d", &devcount);
905                sprintf(readid, "/proc/sys/dev/wifi%d/poweroffset", devcount);
906                FILE *in = fopen(readid, "rb");
907
908                vendor = 0;
909                if (in) {
910                        vendor = atoi(fgets(readid, sizeof(readid), in));
911                        fclose(in);
912                }
913
914                poweroffset = vendor;
915                if (poweroffset < 0 || poweroffset > 20)
916                        poweroffset = 0;
917        }
918#endif
919#ifdef HAVE_MAKSAT
920        char *manpoweroffset;
921        manpoweroffset = nvram_nget("%s_poweroffset", ifname);
922        if (strlen(manpoweroffset)) {
923                poweroffset = atoi(manpoweroffset);
924        }
925#endif
926        struct iwreq wrq;
927
928        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
929        ioctl(getsocket(), SIOCGIWTXPOW, &wrq);
930        struct iw_param *txpower = &wrq.u.txpower;
931
932        if (txpower->disabled) {
933                return 0;
934        } else {
935                /*
936                 * Check for relative values
937                 */
938                if (txpower->flags & IW_TXPOW_RELATIVE) {
939                        return txpower->value + poweroffset;
940                } else {
941                        int dbm = 0;
942
943                        /*
944                         * Convert everything to dBm
945                         */
946                        if (txpower->flags & IW_TXPOW_MWATT)
947                                dbm = iw_mwatt2dbm(txpower->value);
948                        else
949                                dbm = txpower->value;
950                        return dbm + poweroffset;
951                }
952        }
953}
954
955int wifi_gettxpoweroffset(char *ifname)
956{
957        int poweroffset = 0;
958
959#ifdef HAVE_ALPHA
960        poweroffset = 10;
961#elif HAVE_EOC1650
962        poweroffset = 0;
963#elif HAVE_BWRG1000
964        poweroffset = 12;       //?? guess
965#elif HAVE_EAP3660
966        poweroffset = 8;
967#elif HAVE_EOC2610
968        poweroffset = 8;
969#elif HAVE_EOC5610
970        poweroffset = 0;
971#elif HAVE_NS2
972        poweroffset = 10;
973#elif HAVE_LC2
974        poweroffset = 10;
975#elif HAVE_BS2
976        poweroffset = 0;
977#elif HAVE_PICO2
978        poweroffset = 0;
979#elif HAVE_PICO2HP
980        poweroffset = 10;
981#elif HAVE_MS2
982        poweroffset = 10;
983#elif HAVE_BS2HP
984        poweroffset = 10;
985#elif HAVE_NS5
986        poweroffset = 5;
987#elif HAVE_PICO5
988        poweroffset = 5;
989#elif HAVE_NS3
990        poweroffset = 5;
991#elif HAVE_LC5
992        poweroffset = 5;
993#elif HAVE_DLM101
994        poweroffset = 5;
995#elif HAVE_BS5
996        poweroffset = 5;
997#elif HAVE_LS5
998        poweroffset = 5;
999#else
1000        if (isEMP(ifname)) {
1001                if (nvram_nmatch("2", "%s_cardtype", ifname))
1002                        return 8;
1003                if (nvram_nmatch("3", "%s_cardtype", ifname))
1004                        return 8;
1005                if (nvram_nmatch("5", "%s_cardtype", ifname))
1006                        return 8;
1007                if (nvram_nmatch("6", "%s_cardtype", ifname))
1008                        return 7;
1009                if (nvram_nmatch("7", "%s_cardtype", ifname))
1010                        return 10;
1011        }
1012        int vendor;
1013        int devcount;
1014        char readid[64];
1015
1016        strcpy(readid, ifname);
1017        sscanf(readid, "ath%d", &devcount);
1018        sprintf(readid, "/proc/sys/dev/wifi%d/poweroffset", devcount);
1019        FILE *in = fopen(readid, "rb");
1020
1021        vendor = 0;
1022        if (in) {
1023                vendor = atoi(fgets(readid, sizeof(readid), in));
1024                fclose(in);
1025        }
1026        poweroffset = vendor;
1027        if (poweroffset < 0 || poweroffset > 20)
1028                poweroffset = 0;
1029#endif
1030#ifdef HAVE_MAKSAT
1031        char *manpoweroffset;
1032        manpoweroffset = nvram_nget("%s_poweroffset", ifname);
1033        if (strlen(manpoweroffset)) {
1034                poweroffset = atoi(manpoweroffset);
1035        }
1036#endif
1037        return poweroffset;
1038}
1039
1040int get_wififreq(char *ifname, int freq)
1041{
1042#ifdef HAVE_NS3
1043        return -2000;
1044#endif
1045        if (isEMP(ifname)) {
1046                if (nvram_nmatch("4", "%s_cardtype", ifname))
1047                        return freq - 2400;
1048        }
1049        char *var = NULL;
1050        if (ifname) {
1051                char localvar[32];
1052                sprintf(localvar, "%s_offset", ifname);
1053                var = nvram_get(localvar);
1054        }
1055        if (var) {
1056                return freq + atoi(var);
1057        }
1058        int vendor;
1059        int devcount;
1060        char readid[64];
1061
1062        strcpy(readid, ifname);
1063        sscanf(readid, "ath%d", &devcount);
1064        sprintf(readid, "/proc/sys/dev/wifi%d/vendor", devcount);
1065        FILE *in = fopen(readid, "rb");
1066
1067        vendor = 0;
1068        if (in) {
1069                vendor = atoi(fgets(readid, sizeof(readid), in));
1070                fclose(in);
1071        }
1072        switch (vendor) {
1073        case 9:         // ubnt xr9
1074                if (freq < 2427 || freq > 2442)
1075                        return -1;
1076                return freq - (2427 - 907);
1077                break;
1078        case 4:         // ubnt sr9
1079                switch (freq)   // mmh weired order
1080                {
1081                case 2422:
1082                        return 922;
1083                        break;
1084                case 2423:
1085                        return 921;
1086                        break;
1087                case 2424:
1088                        return 920;
1089                        break;
1090                case 2425:
1091                        return 919;
1092                        break;
1093                case 2426:
1094                        return 918;
1095                        break;
1096                case 2427:
1097                        return 917;
1098                        break;
1099                case 2428:
1100                        return 916;
1101                        break;
1102                case 2429:
1103                        return 915;
1104                        break;
1105                case 2430:
1106                        return 914;
1107                        break;
1108                case 2431:
1109                        return 913;
1110                        break;
1111                case 2432:
1112                        return 912;
1113                        break;
1114                case 2433:
1115                        return 911;
1116                        break;
1117                case 2434:
1118                        return 910;
1119                        break;
1120                case 2435:
1121                        return 909;
1122                        break;
1123                case 2436:
1124                        return 908;
1125                        break;
1126                case 2437:
1127                        return 907;
1128                        break;
1129                }
1130                return -1;
1131        case 13:
1132                return freq - (5540 - 3540);    // xr3 general 3,5 ghz
1133        case 1328:
1134                return freq - (5540 - 2840);    // xr3 special 2.8 ghz
1135        case 1336:
1136                if (nvram_nmatch("2", "%s_cardtype", ifname))
1137                        return freq - (5765 - 3658);    // xr3 3.7 ghz
1138                else
1139                        return freq - (5540 - 3340);    // xr3 special 3.3/3.6 ghz
1140        case 7:
1141                if (freq < 2427 || freq > 2442)
1142                        return -1;
1143                return freq - (2427 - 763);     // xr7
1144        case 14:
1145                return freq - (5540 - 4516);    // xr4
1146                // case 24:
1147                // return -(5540-4540); //sr4
1148        default:
1149                return freq;
1150                break;
1151        }
1152        return freq;
1153}
1154
1155#ifdef WILLAM
1156#define OFFSET 0
1157#else
1158#define OFFSET 0
1159#endif
1160u_int ieee80211_mhz2ieee(u_int freq)
1161{
1162        if (freq == 2484 + OFFSET)
1163                return 14;
1164        if (freq < 2484 + OFFSET) {
1165                int chan = (freq - (2407 + OFFSET)) / 5;
1166                if (chan < 0)
1167                        chan += 256;
1168                return chan;
1169        }
1170        if (freq < 4990 && freq > 4940)
1171                return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
1172        if (freq < 5000)
1173                return 15 + ((freq - (2512 + OFFSET)) / 20);
1174
1175        return (freq - (5000 + OFFSET)) / 5;
1176}
1177
1178int wifi_getchannel(char *ifname)
1179{
1180        struct iwreq wrq;
1181        int channel;
1182
1183        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
1184        ioctl(getsocket(), SIOCGIWFREQ, &wrq);
1185
1186        int i;
1187
1188        double freq = (double)wrq.u.freq.m;
1189        for (i = 0; i < wrq.u.freq.e; i++)
1190                freq *= 10.0;
1191        freq /= 1000000.0;
1192        cprintf("wifi channel %f\n", freq);
1193        channel = ieee80211_mhz2ieee(freq);
1194
1195        return channel;
1196}
1197
1198int wifi_getfreq(char *ifname)
1199{
1200        struct iwreq wrq;
1201
1202        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
1203        ioctl(getsocket(), SIOCGIWFREQ, &wrq);
1204
1205        int i;
1206        double freq = (double)wrq.u.freq.m;
1207        for (i = 0; i < wrq.u.freq.e; i++)
1208                freq *= 10.0;
1209        freq /= 1000000.0;
1210        cprintf("wifi channel %f\n", freq);
1211        return freq;
1212}
1213
1214int get_radiostate(char *ifname)
1215{
1216        char mode[32];
1217
1218        sprintf(mode, "%s_net_mode", ifname);
1219        if (nvram_match(mode, "disabled"))
1220                return 0;
1221        struct ifreq ifr;
1222        int skfd = getsocket();
1223
1224        strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1225        if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
1226                return -1;
1227        }
1228        if ((ifr.ifr_flags & IFF_UP)) {
1229                return 1;
1230        }
1231        return 0;
1232}
1233
1234struct wifi_channels {
1235        int channel;
1236        int freq;
1237        int noise;
1238};
1239
1240static inline int iw_get_ext(int skfd,  /* Socket to the kernel */
1241                             const char *ifname,        /* Device name */
1242                             int request,       /* WE ID */
1243                             struct iwreq *pwrq)
1244{                               /* Fixed part of the
1245                                 * request */
1246        /*
1247         * Set device name
1248         */
1249        strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
1250        /*
1251         * Do the request
1252         */
1253        return (ioctl(skfd, request, pwrq));
1254}
1255
1256int isAssociated(char *ifname)
1257{
1258        struct iwreq wrq;
1259        int i;
1260
1261        if (iw_get_ext(getsocket(), ifname, SIOCGIWAP, &wrq) >= 0) {
1262                for (i = 0; i < 6; i++)
1263                        if (wrq.u.ap_addr.sa_data[i] != 0)
1264                                return 1;
1265        }
1266        return 0;
1267}
1268
1269int getAssocMAC(char *ifname, char *mac)
1270{
1271        struct iwreq wrq;
1272        int i;
1273        int ret = -1;
1274
1275        if (iw_get_ext(getsocket(), ifname, SIOCGIWAP, &wrq) >= 0) {
1276                for (i = 0; i < 6; i++)
1277                        if (wrq.u.ap_addr.sa_data[i] != 0)
1278                                ret = 0;
1279        }
1280        if (!ret) {
1281                for (i = 0; i < 6; i++)
1282                        mac[i] = wrq.u.ap_addr.sa_data[i];
1283
1284        }
1285        return ret;
1286}
1287
1288
1289int is_ar5008(char *prefix)
1290{
1291        char sys[64];
1292        int devnum;
1293        sscanf(prefix, "ath%d", &devnum)
1294
1295        sprintf(sys, "/proc/sys/dev/wifi%d/mimo", devnum);
1296       
1297        if (f_exists(sys))
1298                return 1;
1299               
1300        return 0;
1301}
1302
1303int has_athmask(int devnum, int mask)
1304{
1305        char sys[64];
1306        int modes;
1307
1308        sprintf(sys, "/proc/sys/dev/wifi%d/wirelessmodes", devnum);
1309        FILE *tmp = fopen(sys, "rb");
1310
1311        if (tmp == NULL)
1312                return 0;
1313        fscanf(tmp,"%d",&modes);
1314        fclose(tmp);
1315        if ((modes&mask) == mask)
1316        return 1;
1317        else
1318        return 0;
1319}
1320
1321
1322int has_5ghz(char *prefix)
1323{
1324        int devnum;
1325        sscanf(prefix, "ath%d", &devnum)
1326
1327        return has_athmask(devnum,0x1);
1328}
1329
1330int has_2ghz(char *prefix)
1331{
1332        int devnum;
1333        sscanf(prefix, "ath%d", &devnum)
1334
1335        return has_athmask(devnum,0x8);
1336}
1337
1338
1339
1340static struct wifi_channels *list_channelsext(const char *ifname, int allchans)
1341{
1342        struct ieee80211req_chaninfo chans;
1343        struct ieee80211req_chaninfo achans;
1344        const struct ieee80211_channel *c;
1345        int i;
1346
1347        // fprintf (stderr, "list channels for %s\n", ifname);
1348        if (do80211priv
1349            (ifname, IEEE80211_IOCTL_GETCHANINFO, &chans, sizeof(chans)) < 0) {
1350                fprintf(stderr, "unable to get channel information\n");
1351                return NULL;
1352        }
1353        if (!allchans) {
1354                uint8_t active[64];
1355
1356                if (do80211priv
1357                    (ifname, IEEE80211_IOCTL_GETCHANLIST, &active,
1358                     sizeof(active)) < 0) {
1359                        fprintf(stderr, "unable to get active channel list\n");
1360                        return NULL;
1361                }
1362                memset(&achans, 0, sizeof(achans));
1363                for (i = 0; i < chans.ic_nchans; i++) {
1364                        c = &chans.ic_chans[i];
1365                        if (isset(active, c->ic_ieee) || allchans)
1366                                achans.ic_chans[achans.ic_nchans++] = *c;
1367                }
1368        } else
1369                achans = chans;
1370
1371        // fprintf(stderr,"channel number %d\n", achans.ic_nchans);
1372        struct wifi_channels *list =
1373            (struct wifi_channels *)malloc(sizeof(struct wifi_channels) *
1374                                           (achans.ic_nchans + 1));
1375
1376        char wl_mode[16];
1377        char wl_turbo[16];
1378
1379        sprintf(wl_mode, "%s_net_mode", ifname);
1380        sprintf(wl_turbo, "%s_channelbw", ifname);
1381        int l = 0;
1382
1383        for (i = 0; i < achans.ic_nchans; i++) {
1384                // fprintf(stderr,"channel number %d of %d\n", i,achans.ic_nchans);
1385
1386                // filter out A channels if mode isnt A-Only or mixed
1387                if (IEEE80211_IS_CHAN_A(&achans.ic_chans[i])) {
1388#ifdef HAVE_WHRAG108
1389                        if (!strcmp(ifname, "ath1"))
1390                                continue;
1391#endif
1392#ifdef HAVE_TW6600
1393                        if (!strcmp(ifname, "ath1"))
1394                                continue;
1395#endif
1396                        if (nvram_invmatch(wl_mode, "a-only")
1397                            && nvram_invmatch(wl_mode, "mixed"))
1398                                continue;
1399                }
1400                // filter out B/G channels if mode isnt g-only, b-only or mixed
1401                if (IEEE80211_IS_CHAN_ANYG(&achans.ic_chans[i])
1402                    || IEEE80211_IS_CHAN_B(&achans.ic_chans[i])) {
1403#ifdef HAVE_WHRAG108
1404                        if (!strcmp(ifname, "ath0"))
1405                                continue;
1406#endif
1407#ifdef HAVE_TW6600
1408                        if (!strcmp(ifname, "ath0"))
1409                                continue;
1410#endif
1411                        if (nvram_invmatch(wl_mode, "g-only")
1412                            && nvram_invmatch(wl_mode, "mixed")
1413                            && nvram_invmatch(wl_mode, "b-only")
1414                            && nvram_invmatch(wl_mode, "bg-mixed"))
1415                                continue;
1416                }
1417                // filter out channels which are not supporting turbo mode if turbo
1418                // is enabled
1419                if (!IEEE80211_IS_CHAN_STURBO(&achans.ic_chans[i])
1420                    && !IEEE80211_IS_CHAN_DTURBO(&achans.ic_chans[i])) {
1421                        if (nvram_match(wl_turbo, "40"))
1422                                continue;
1423                }
1424                // filter out turbo channels if turbo mode is disabled
1425                /*
1426                 * if (IEEE80211_IS_CHAN_STURBO (&achans.ic_chans[i]) ||
1427                 * IEEE80211_IS_CHAN_DTURBO (&achans.ic_chans[i])) { if (nvram_match
1428                 * (wl_turbo, "0")) continue; }
1429                 */
1430                if (IEEE80211_IS_CHAN_STURBO(&achans.ic_chans[i])) {
1431                        if (!nvram_match(wl_turbo, "40"))
1432                                continue;
1433                }
1434
1435                list[l].channel = achans.ic_chans[i].ic_ieee;
1436                list[l].freq = achans.ic_chans[i].ic_freq;
1437                list[l].noise = -95;    // achans.ic_chans[i].ic_noise;
1438                l++;
1439        }
1440
1441        list[l].freq = -1;
1442        return list;
1443}
1444
1445struct wifi_channels *list_channels(char *devnr)
1446{
1447        return list_channelsext(devnr, 1);
1448        /*
1449         * char csign[64]; char channel[64]; char ppp[64]; char freq[64]; char
1450         * dum1[64]; char dum2[64]; char dum3[64]; char dum4[64];
1451         *
1452         * char cmd[64]; sprintf (cmd, "iwlist %s chan>/tmp/.channels", devnr);
1453         * system (cmd); FILE *in = fopen ("/tmp/.channels", "rb"); if (in ==
1454         * NULL) return NULL; fscanf (in, "%s %s %s %s %s %s %s %s", csign,
1455         * channel, ppp, freq, dum1, dum2, dum3, dum4); int ch = atoi (channel);
1456         * int i; struct wifi_channels *list = (struct wifi_channels *) malloc
1457         * (sizeof (struct wifi_channels) * (ch+1) ); for (i = 0; i < ch; i++) {
1458         * fscanf (in, "%s %s %s %s %s", csign, channel, ppp, freq, dum1); if
1459         * (!strcmp (csign, "Current")) break; list[i].channel = atoi (channel);
1460         * list[i].freq = strdup (freq); channelcount++; } fclose (in); return
1461         * list;
1462         */
1463}
1464
1465int getdevicecount(void)
1466{
1467        int count = getifcount("wifi");
1468
1469        if (count < 7 && count > 0)
1470                return count;
1471        return 0;
1472}
1473
1474int getRssi(char *ifname, unsigned char *mac)
1475{
1476        unsigned char *buf = malloc(24 * 1024);
1477
1478        memset(buf, 0, 1024 * 24);
1479        unsigned char *cp;
1480        int len;
1481        struct iwreq iwr;
1482        int s;
1483        char nb[32];
1484        sprintf(nb, "%s_bias", ifname);
1485
1486        s = socket(AF_INET, SOCK_DGRAM, 0);
1487        if (s < 0) {
1488                fprintf(stderr, "socket(SOCK_DRAGM)\n");
1489                free(buf);
1490                return 0;
1491        }
1492        (void)memset(&iwr, 0, sizeof(iwr));
1493        (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
1494        iwr.u.data.pointer = (void *)buf;
1495        iwr.u.data.length = 1024 * 24;
1496        if (ioctl(s, IEEE80211_IOCTL_STA_INFO, &iwr) < 0) {
1497                close(s);
1498                free(buf);
1499                fprintf(stderr, "stainfo error\n");
1500                return 0;
1501        }
1502        len = iwr.u.data.length;
1503        if (len < sizeof(struct ieee80211req_sta_info))
1504                return 0;
1505
1506        cp = buf;
1507        char maccmp[6];
1508
1509        memset(maccmp, 0, 6);
1510        do {
1511                struct ieee80211req_sta_info *si;
1512
1513                si = (struct ieee80211req_sta_info *)cp;
1514                if (!memcmp(&si->isi_macaddr[0], mac, 6)) {
1515                        close(s);
1516                        int rssi = si->isi_noise + si->isi_rssi;
1517
1518                        free(buf);
1519
1520                        return rssi + atoi(nvram_default_get(nb, "0"));
1521                }
1522                if (!memcmp(&si->isi_macaddr[0], mac, 6))
1523                        break;
1524                cp += si->isi_len;
1525                len -= si->isi_len;
1526        }
1527        while (len >= sizeof(struct ieee80211req_sta_info));
1528        close(s);
1529        free(buf);
1530        return 0;
1531}
1532
1533int getUptime(char *ifname, unsigned char *mac)
1534{
1535        unsigned char *buf = malloc(24 * 1024);
1536
1537        memset(buf, 0, 24 * 1024);
1538        unsigned char *cp;
1539        int len;
1540        struct iwreq iwr;
1541        int s;
1542
1543        s = socket(AF_INET, SOCK_DGRAM, 0);
1544        if (s < 0) {
1545                fprintf(stderr, "socket(SOCK_DRAGM)\n");
1546                free(buf);
1547                return 0;
1548        }
1549        (void)memset(&iwr, 0, sizeof(iwr));
1550        (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
1551        iwr.u.data.pointer = (void *)buf;
1552        iwr.u.data.length = 24 * 1024;
1553        if (ioctl(s, IEEE80211_IOCTL_STA_INFO, &iwr) < 0) {
1554                close(s);
1555                free(buf);
1556                return 0;
1557        }
1558        len = iwr.u.data.length;
1559        if (len < sizeof(struct ieee80211req_sta_info))
1560                return -1;
1561
1562        cp = buf;
1563        char maccmp[6];
1564
1565        memset(maccmp, 0, 6);
1566        do {
1567                struct ieee80211req_sta_info *si;
1568
1569                si = (struct ieee80211req_sta_info *)cp;
1570                if (!memcmp(&si->isi_macaddr[0], mac, 6)) {
1571                        close(s);
1572                        int uptime = si->isi_uptime;
1573
1574                        free(buf);
1575                        return uptime;
1576                }
1577                if (!memcmp(&si->isi_macaddr[0], mac, 6))
1578                        break;
1579                cp += si->isi_len;
1580                len -= si->isi_len;
1581        }
1582        while (len >= sizeof(struct ieee80211req_sta_info));
1583        close(s);
1584        free(buf);
1585        return 0;
1586}
1587
1588int getNoise(char *ifname, unsigned char *mac)
1589{
1590        unsigned char *buf = malloc(24 * 1024);
1591
1592        memset(buf, 0, 24 * 1024);
1593        unsigned char *cp;
1594        int len;
1595        struct iwreq iwr;
1596        int s;
1597        char nb[32];
1598        sprintf(nb, "%s_bias", ifname);
1599
1600        s = socket(AF_INET, SOCK_DGRAM, 0);
1601        if (s < 0) {
1602                fprintf(stderr, "socket(SOCK_DRAGM)\n");
1603                free(buf);
1604                return 0;
1605        }
1606        (void)memset(&iwr, 0, sizeof(iwr));
1607        (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
1608        iwr.u.data.pointer = (void *)buf;
1609        iwr.u.data.length = 24 * 1024;
1610        if (ioctl(s, IEEE80211_IOCTL_STA_INFO, &iwr) < 0) {
1611                close(s);
1612                free(buf);
1613                return 0;
1614        }
1615        len = iwr.u.data.length;
1616        if (len < sizeof(struct ieee80211req_sta_info))
1617                return -1;
1618
1619        cp = buf;
1620        char maccmp[6];
1621
1622        memset(maccmp, 0, 6);
1623        do {
1624                struct ieee80211req_sta_info *si;
1625
1626                si = (struct ieee80211req_sta_info *)cp;
1627                if (!memcmp(&si->isi_macaddr[0], mac, 6)) {
1628                        close(s);
1629                        int noise = si->isi_noise;
1630
1631                        free(buf);
1632                        return noise + atoi(nvram_default_get(nb, "0"));
1633                }
1634                if (!memcmp(&si->isi_macaddr[0], mac, 6))
1635                        break;
1636                cp += si->isi_len;
1637                len -= si->isi_len;
1638        }
1639        while (len >= sizeof(struct ieee80211req_sta_info));
1640        close(s);
1641        free(buf);
1642        return 0;
1643}
1644
1645int getassoclist(char *ifname, unsigned char *list)
1646{
1647        unsigned char *buf;
1648
1649        buf = malloc(24 * 1024);
1650        memset(buf, 0, 1024 * 24);
1651        unsigned char *cp;
1652        int len;
1653        struct iwreq iwr;
1654        int s;
1655        char type[32];
1656        char netmode[32];
1657        unsigned int *count = (unsigned int *)list;
1658
1659        sprintf(type, "%s_mode", ifname);
1660        sprintf(netmode, "%s_net_mode", ifname);
1661        if (nvram_match(netmode, "disabled")) {
1662                free(buf);
1663                return 0;
1664        }
1665        int mincount = 0;
1666
1667        if (nvram_match(type, "wdssta") || nvram_match(type, "sta")
1668            || nvram_match(type, "wet")) {
1669                int assoc = isAssociated(ifname);
1670
1671                if (!assoc) {
1672                        free(buf);
1673                        return 0;
1674                }
1675                char mac[6];
1676
1677                getAssocMAC(ifname, mac);
1678                memcpy(&list[4], mac, 6);
1679                count[0] = 1;
1680                mincount = 1;
1681        }
1682        s = socket(AF_INET, SOCK_DGRAM, 0);
1683        if (s < 0) {
1684                fprintf(stderr, "socket(SOCK_DRAGM)\n");
1685                free(buf);
1686                mincount = 1;
1687                return mincount;
1688        }
1689        (void)memset(&iwr, 0, sizeof(iwr));
1690        (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
1691        iwr.u.data.pointer = (void *)buf;
1692        iwr.u.data.length = 1024 * 24;
1693        if (ioctl(s, IEEE80211_IOCTL_STA_INFO, &iwr) < 0) {
1694                close(s);
1695                free(buf);
1696                return mincount;
1697        }
1698        len = iwr.u.data.length;
1699        if (len < sizeof(struct ieee80211req_sta_info)) {
1700                close(s);
1701                free(buf);
1702                return mincount;
1703        }
1704
1705        cp = buf;
1706        unsigned char *l = (unsigned char *)list;
1707
1708        count[0] = 0;
1709        l += 4;
1710        do {
1711                struct ieee80211req_sta_info *si;
1712
1713                si = (struct ieee80211req_sta_info *)cp;
1714                memcpy(l, &si->isi_macaddr[0], 6);
1715                if (l[0] == 0 && l[1] == 0 && l[2] == 0 && l[3] == 0
1716                    && l[4] == 0 && l[5] == 0)
1717                        break;
1718                l += 6;
1719                count[0]++;
1720                cp += si->isi_len;
1721                len -= si->isi_len;
1722        }
1723        while (len >= sizeof(struct ieee80211req_sta_info));
1724        close(s);
1725        free(buf);
1726
1727        return mincount > count[0] ? mincount : count[0];
1728}
1729
1730#endif
1731
1732#if !defined(HAVE_MADWIFI) && !defined(HAVE_RT2880)
1733
1734/*
1735 * int wl_probe (char *name) { int ret, val;
1736 *
1737 * if ((ret = wl_ioctl (name, WLC_GET_MAGIC, &val, sizeof (val)))) return
1738 * ret; if (val != WLC_IOCTL_MAGIC) return -1; if ((ret = wl_ioctl (name,
1739 * WLC_GET_VERSION, &val, sizeof (val)))) return ret; if (val >
1740 * WLC_IOCTL_VERSION) return -1;
1741 *
1742 * return ret; }
1743 */
1744// #ifndef HAVE_MSSID
1745int wl_set_val(char *name, char *var, void *val, int len)
1746{
1747        char buf[128];
1748        int buf_len;
1749
1750        /*
1751         * check for overflow
1752         */
1753        if ((buf_len = strlen(var)) + 1 + len > sizeof(buf))
1754                return -1;
1755
1756        strcpy(buf, var);
1757        buf_len += 1;
1758
1759        /*
1760         * append int value onto the end of the name string
1761         */
1762        memcpy(&buf[buf_len], val, len);
1763        buf_len += len;
1764
1765        return wl_ioctl(name, WLC_SET_VAR, buf, buf_len);
1766}
1767
1768int wl_get_val(char *name, char *var, void *val, int len)
1769{
1770        char buf[128];
1771        int ret;
1772
1773        /*
1774         * check for overflow
1775         */
1776        if (strlen(var) + 1 > sizeof(buf) || len > sizeof(buf))
1777                return -1;
1778
1779        strcpy(buf, var);
1780        if ((ret = wl_ioctl(name, WLC_GET_VAR, buf, sizeof(buf))))
1781                return ret;
1782
1783        memcpy(val, buf, len);
1784        return 0;
1785}
1786
1787int wl_set_int(char *name, char *var, int val)
1788{
1789        return wl_set_val(name, var, &val, sizeof(val));
1790}
1791
1792int wl_get_int(char *name, char *var, int *val)
1793{
1794        return wl_get_val(name, var, val, sizeof(*val));
1795}
1796
1797// #else
1798int
1799wl_iovar_getbuf(char *ifname, char *iovar, void *param, int paramlen,
1800                void *bufptr, int buflen)
1801{
1802        int err;
1803        uint namelen;
1804        uint iolen;
1805
1806        namelen = strlen(iovar) + 1;    /* length of iovar name plus null */
1807        iolen = namelen + paramlen;
1808
1809        /*
1810         * check for overflow
1811         */
1812        if (iolen > buflen)
1813                return (BCME_BUFTOOSHORT);
1814
1815        memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
1816        memcpy((int8 *) bufptr + namelen, param, paramlen);
1817
1818        err = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
1819
1820        return (err);
1821}
1822
1823int
1824wl_iovar_setbuf(char *ifname, char *iovar, void *param, int paramlen,
1825                void *bufptr, int buflen)
1826{
1827        uint namelen;
1828        uint iolen;
1829
1830        namelen = strlen(iovar) + 1;    /* length of iovar name plus null */
1831        iolen = namelen + paramlen;
1832
1833        /*
1834         * check for overflow
1835         */
1836        if (iolen > buflen)
1837                return (BCME_BUFTOOSHORT);
1838
1839        memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
1840        memcpy((int8 *) bufptr + namelen, param, paramlen);
1841
1842        return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
1843}
1844
1845int wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen)
1846{
1847        char smbuf[WLC_IOCTL_SMLEN];
1848
1849        return wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf,
1850                               sizeof(smbuf));
1851}
1852
1853int wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen)
1854{
1855        char smbuf[WLC_IOCTL_SMLEN];
1856        int ret;
1857
1858        /*
1859         * use the return buffer if it is bigger than what we have on the stack
1860         */
1861        if (buflen > sizeof(smbuf)) {
1862                ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen);
1863        } else {
1864                ret =
1865                    wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf,
1866                                    sizeof(smbuf));
1867                if (ret == 0)
1868                        memcpy(bufptr, smbuf, buflen);
1869        }
1870
1871        return ret;
1872}
1873
1874/*
1875 * set named driver variable to int value
1876 * calling example: wl_iovar_setint(ifname, "arate", rate)
1877 */
1878int wl_iovar_setint(char *ifname, char *iovar, int val)
1879{
1880        return wl_iovar_set(ifname, iovar, &val, sizeof(val));
1881}
1882
1883/*
1884 * get named driver variable to int value and return error indication
1885 * calling example: wl_iovar_getint(ifname, "arate", &rate)
1886 */
1887int wl_iovar_getint(char *ifname, char *iovar, int *val)
1888{
1889        return wl_iovar_get(ifname, iovar, val, sizeof(int));
1890}
1891
1892/*
1893 * format a bsscfg indexed iovar buffer
1894 */
1895static int
1896wl_bssiovar_mkbuf(char *iovar, int bssidx, void *param, int paramlen,
1897                  void *bufptr, int buflen, unsigned int *plen)
1898{
1899        char *prefix = "bsscfg:";
1900        int8 *p;
1901        uint prefixlen;
1902        uint namelen;
1903        uint iolen;
1904
1905        prefixlen = strlen(prefix);     /* length of bsscfg prefix */
1906        namelen = strlen(iovar) + 1;    /* length of iovar name + null */
1907        iolen = prefixlen + namelen + sizeof(int) + paramlen;
1908
1909        /*
1910         * check for overflow
1911         */
1912        if (buflen < 0 || iolen > (uint) buflen) {
1913                *plen = 0;
1914                return BCME_BUFTOOSHORT;
1915        }
1916
1917        p = (int8 *) bufptr;
1918
1919        /*
1920         * copy prefix, no null
1921         */
1922        memcpy(p, prefix, prefixlen);
1923        p += prefixlen;
1924
1925        /*
1926         * copy iovar name including null
1927         */
1928        memcpy(p, iovar, namelen);
1929        p += namelen;
1930
1931        /*
1932         * bss config index as first param
1933         */
1934        memcpy(p, &bssidx, sizeof(int32));
1935        p += sizeof(int32);
1936
1937        /*
1938         * parameter buffer follows
1939         */
1940        if (paramlen)
1941                memcpy(p, param, paramlen);
1942
1943        *plen = iolen;
1944        return 0;
1945}
1946
1947/*
1948 * set named & bss indexed driver variable to buffer value
1949 */
1950int
1951wl_bssiovar_setbuf(char *ifname, char *iovar, int bssidx, void *param,
1952                   int paramlen, void *bufptr, int buflen)
1953{
1954        int err;
1955        uint iolen;
1956
1957        err =
1958            wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen,
1959                              &iolen);
1960        if (err)
1961                return err;
1962
1963        return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
1964}
1965
1966/*
1967 * get named & bss indexed driver variable buffer value
1968 */
1969int
1970wl_bssiovar_getbuf(char *ifname, char *iovar, int bssidx, void *param,
1971                   int paramlen, void *bufptr, int buflen)
1972{
1973        int err;
1974        uint iolen;
1975
1976        err =
1977            wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen,
1978                              &iolen);
1979        if (err)
1980                return err;
1981
1982        return wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
1983}
1984
1985/*
1986 * set named & bss indexed driver variable to buffer value
1987 */
1988int
1989wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param,
1990                int paramlen)
1991{
1992        char smbuf[WLC_IOCTL_SMLEN];
1993
1994        return wl_bssiovar_setbuf(ifname, iovar, bssidx, param, paramlen, smbuf,
1995                                  sizeof(smbuf));
1996}
1997
1998/*
1999 * get named & bss indexed driver variable buffer value
2000 */
2001int
2002wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len)
2003{
2004        char smbuf[WLC_IOCTL_SMLEN];
2005        int err;
2006
2007        /*
2008         * use the return buffer if it is bigger than what we have on the stack
2009         */
2010        if (len > (int)sizeof(smbuf)) {
2011                err =
2012                    wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, outbuf,
2013                                       len);
2014        } else {
2015                memset(smbuf, 0, sizeof(smbuf));
2016                err =
2017                    wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, smbuf,
2018                                       sizeof(smbuf));
2019                if (err == 0)
2020                        memcpy(outbuf, smbuf, len);
2021        }
2022
2023        return err;
2024}
2025
2026/*
2027 * set named & bss indexed driver variable to int value
2028 */
2029int wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val)
2030{
2031        return wl_bssiovar_set(ifname, iovar, bssidx, &val, sizeof(int));
2032}
2033
2034/*
2035 * void wl_printlasterror(char *name) { char err_buf[WLC_IOCTL_SMLEN];
2036 * strcpy(err_buf, "bcmerrstr");
2037 *
2038 * fprintf(stderr, "Error: "); if ( wl_ioctl(name, WLC_GET_VAR, err_buf,
2039 * sizeof (err_buf)) != 0) fprintf(stderr, "Error getting the Errorstring
2040 * from driver\n"); else fprintf(stderr, err_buf); }
2041 */
2042
2043#endif
Note: See TracBrowser for help on using the repository browser.