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

Last change on this file since 31570 was 31570, checked in by brainslayer, 4 months ago

do not show up center freqs if not available

  • Property svn:executable set to *
File size: 60.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 <syslog.h>
24#include <fcntl.h>
25//#include <math.h>
26#ifdef HAVE_ATH9K
27#include <glob.h>
28#endif
29
30/*
31 * DD-WRT addition (loaned from radauth)
32 */
33
34int ieee80211_mhz2ieee(int freq)
35{
36        if (freq == 2484)
37                return 14;
38        if (freq == 2407)
39                return 0;
40        if (freq < 2484 && freq > 2407)
41                return (freq - 2407) / 5;
42        if (freq < 2412) {
43                return ((freq - 2407) / 5) + 256;
44        }
45        if (freq > 2484 && freq < 4000)
46                return (freq - 2414) / 5;
47        if (freq < 4990 && freq > 4940)
48                return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
49        // 5000 will become  channel 200
50        if (freq >= 4800 && freq < 5005)
51                return (freq - 4000) / 5;
52        if (freq < 5000)
53                return 15 + ((freq - 2512) / 20);
54        if (freq == 58320)
55                return 1;
56        if (freq == 60480)
57                return 2;
58        if (freq == 62640)
59                return 3;
60        if (freq == 64800)
61                return 4;
62
63        return (freq - 5000) / 5;
64}
65
66#ifndef HAVE_MADWIFI
67
68unsigned int ieee80211_ieee2mhz(unsigned int chan)
69{
70        if (chan == 14)
71                return 2484;
72        if (chan < 14)
73                return ((2407) + chan * 5);
74        else if (chan < 27)
75                return ((2512) + ((chan - 15) * 20));
76        else
77                return ((5000) + (chan * 5));
78}
79
80#if defined(HAVE_RT2880) || defined(HAVE_RT61)
81char *getRADev(char *prefix)
82{
83        char *ifname = NULL;
84
85        if (!strcmp(prefix, "wl0"))
86                ifname = "ra0";
87        if (!strcmp(prefix, "wl0.1"))
88                ifname = "ra1";
89        if (!strcmp(prefix, "wl0.2"))
90                ifname = "ra2";
91        if (!strcmp(prefix, "wl0.3"))
92                ifname = "ra3";
93        if (!strcmp(prefix, "wl0.4"))
94                ifname = "ra4";
95        if (!strcmp(prefix, "wl0.5"))
96                ifname = "ra5";
97        if (!strcmp(prefix, "wl0.6"))
98                ifname = "ra6";
99        if (!strcmp(prefix, "wl0.7"))
100                ifname = "ra7";
101
102        if (!strcmp(prefix, "wl1"))
103                ifname = "ba0";
104        if (!strcmp(prefix, "wl1.1"))
105                ifname = "ba1";
106        if (!strcmp(prefix, "wl1.2"))
107                ifname = "ba2";
108        if (!strcmp(prefix, "wl1.3"))
109                ifname = "ba3";
110        if (!strcmp(prefix, "wl1.4"))
111                ifname = "ba4";
112        if (!strcmp(prefix, "wl1.5"))
113                ifname = "ba5";
114        if (!strcmp(prefix, "wl1.6"))
115                ifname = "ba6";
116        if (!strcmp(prefix, "wl1.7"))
117                ifname = "ba7";
118
119        if (ifname)
120                return ifname;
121        else
122                return prefix;
123}
124
125int has_5ghz(char *prefix)
126{
127        if (!strcmp(prefix, "wl0"))
128                return 0;
129        return 1;
130}
131
132int has_2ghz(char *prefix)
133{
134        if (!strcmp(prefix, "wl0"))
135                return 1;
136        return 0;
137}
138
139int getchannels(unsigned int *list, char *ifname)
140{
141        if (!strcmp(ifname, "ra0")) {
142                list[0] = 1;
143                list[1] = 2;
144                list[2] = 3;
145                list[3] = 4;
146                list[4] = 5;
147                list[5] = 6;
148                list[6] = 7;
149                list[7] = 8;
150                list[8] = 9;
151                list[9] = 10;
152                list[10] = 11;
153                list[11] = 12;
154                list[12] = 13;
155                list[13] = 14;
156#ifdef HAVE_BUFFALO
157                // temporal solution, needs to be done right
158                if (nvram_match("region", "EU"))
159                        return 11;
160                else if (nvram_match("region", "RU"))
161                        return 11;
162                else if (nvram_match("region", "US"))
163                        return 11;
164                else if (nvram_match("region", "JP"))
165                        return 13;
166                else
167                        return 11;
168#else
169                return 14;
170#endif
171        } else {
172                int i;
173                int cnt = 0;
174#ifdef HAVE_BUFFALO
175                if (nvram_match("region", "EU")) {
176                        for (i = 0; i < 4; i++)
177                                list[cnt++] = 36 + (i * 4);
178                } else if (nvram_match("region", "RU")) {
179                        for (i = 0; i < 4; i++)
180                                list[cnt++] = 36 + (i * 4);
181                } else if (nvram_match("region", "US")) {
182                        for (i = 0; i < 4; i++)
183                                list[cnt++] = 36 + (i * 4);
184                        for (i = 0; i < 5; i++)
185                                list[cnt++] = 149 + (i * 4);
186                } else if (nvram_match("region", "JP")) {
187                        for (i = 0; i < 8; i++)
188                                list[cnt++] = 36 + (i * 4);
189                        for (i = 0; i < 11; i++)
190                                list[cnt++] = 100 + (i * 4);
191                } else {
192                        for (i = 0; i < 4; i++)
193                                list[cnt++] = 36 + (i * 4);
194                }
195
196#else
197                for (i = 0; i < 8; i++)
198                        list[cnt++] = 36 + (i * 4);
199
200                for (i = 0; i < 11; i++)
201                        list[cnt++] = 100 + (i * 4);
202
203                for (i = 0; i < 7; i++)
204                        list[cnt++] = 149 + (i * 4);
205#endif
206                return cnt;
207        }
208}
209
210#include <sys/types.h>
211#include <sys/file.h>
212#include <sys/ioctl.h>
213#include <sys/socket.h>
214#include <stdio.h>
215#include <stdlib.h>
216#include <string.h>
217#include <stdint.h>
218#include <ctype.h>
219#include <getopt.h>
220#include <err.h>
221#include <linux/socket.h>
222#include <linux/if.h>
223#define __user
224#include "wireless.h"
225
226static int wrqfreq_to_int(struct iwreq *wrq)
227{
228        int freq, i;
229        freq = wrq->u.freq.m;
230        if (freq < 1000) {
231                return freq;
232        }
233        int divisor = 1000000;
234        int e = wrq->u.freq.e;
235        for (i = 0; i < e; i++)
236                divisor /= 10;
237        if (divisor)
238                freq /= divisor;
239        return freq;
240}
241
242struct wifi_interface *wifi_getfreq(char *ifname)
243{
244        struct iwreq wrq;
245        int freq;
246
247        (void)memset(&wrq, 0, sizeof(struct iwreq));
248        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
249        ioctl(getsocket(), SIOCGIWFREQ, &wrq);
250        closesocket();
251        freq = wrq.u.freq.m;
252        struct wifi_interface *interface = (struct wifi_interface *)malloc(sizeof(struct wifi_interface));
253        if (freq < 1000) {
254                interface->freq = ieee80211_ieee2mhz(freq);
255                return interface;
256        }
257        interface->freq = wrqfreq_to_int(&wrq);
258        return interface;
259}
260
261int wifi_getchannel(char *ifname)
262{
263        struct wifi_interface *interface = wifi_getfreq(ifname);
264        int channel = ieee80211_mhz2ieee(interface->freq);
265        free(interface);
266        return channel;
267}
268
269long long wifi_getrate(char *ifname)
270{
271        struct iwreq wrq;
272
273        (void)memset(&wrq, 0, sizeof(struct iwreq));
274        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
275        ioctl(getsocket(), SIOCGIWRATE, &wrq);
276        closesocket();
277        return wrq.u.bitrate.value;
278}
279
280int get_radiostate(char *ifname)
281{
282        if (nvram_nmatch("disabled", "%s_net_mode", ifname))
283                return 0;
284        if (!strcmp(ifname, "wl0"))
285                ifname = "ra0";
286        if (!strcmp(ifname, "wl1"))
287                ifname = "ba0";
288        struct ifreq ifr;
289        int skfd = getsocket();
290
291        strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
292        if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
293                closesocket();
294                return -1;
295        }
296        if ((ifr.ifr_flags & IFF_UP)) {
297                closesocket();
298                return 1;
299        }
300        closesocket();
301        return 0;
302}
303
304static const char *ieee80211_ntoa(const uint8_t mac[6])
305{
306        static char a[18];
307        int i;
308
309        i = snprintf(a, sizeof(a), "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
310        return (i < 17 ? NULL : a);
311}
312
313typedef union _MACHTTRANSMIT_SETTING {
314        struct {
315                unsigned short MCS:7;   // MCS
316                unsigned short BW:1;    //channel bandwidth 20MHz or 40 MHz
317                unsigned short ShortGI:1;
318                unsigned short STBC:2;  //SPACE
319                unsigned short rsv:3;
320                unsigned short MODE:2;  // Use definition MODE_xxx.
321        } field;
322        unsigned short word;
323} MACHTTRANSMIT_SETTING;
324
325typedef struct _RT_802_11_MAC_ENTRY {
326        unsigned char ApIdx;
327        unsigned char Addr[6];
328        unsigned char Aid;
329        unsigned char Psm;      // 0:PWR_ACTIVE, 1:PWR_SAVE
330        unsigned char MimoPs;   // 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled
331        char AvgRssi0;
332        char AvgRssi1;
333        char AvgRssi2;
334        unsigned int ConnectedTime;
335        MACHTTRANSMIT_SETTING TxRate;
336//#ifdef RTMP_RBUS_SUPPORT
337        unsigned int LastRxRate;
338        int StreamSnr[3];
339        int SoundingRespSnr[3];
340//#endif // RTMP_RBUS_SUPPORT //
341} RT_802_11_MAC_ENTRY;
342
343typedef struct _RT_802_11_MAC_TABLE {
344        unsigned long Num;
345        RT_802_11_MAC_ENTRY Entry[128]; //MAX_LEN_OF_MAC_TABLE = 32
346} RT_802_11_MAC_TABLE;
347
348typedef struct STAINFO {
349        char mac[6];
350        char rssi;
351        char noise;
352        char ifname[32];
353} STAINFO;
354
355int OidQueryInformation(unsigned long OidQueryCode, int socket_id, char *DeviceName, void *ptr, unsigned long PtrLength)
356{
357        struct iwreq wrq;
358
359        strcpy(wrq.ifr_name, DeviceName);
360        wrq.u.data.length = PtrLength;
361        wrq.u.data.pointer = (caddr_t) ptr;
362        wrq.u.data.flags = OidQueryCode;
363
364        return (ioctl(socket_id, (SIOCIWFIRSTPRIV + 0x0E), &wrq));
365}
366
367#include "stapriv.h"
368#include "oid.h"
369
370STAINFO *getRaStaInfo(char *ifname)
371{
372        char G_bRadio = 1;      //TRUE
373
374        int ConnectStatus = 0;
375        unsigned char BssidQuery[6];
376
377        if (!nvram_nmatch("sta", "%s_mode", ifname)
378            && !nvram_nmatch("apsta", "%s_mode", ifname)
379            && !nvram_nmatch("apstawet", "%s_mode", ifname)) {
380                return NULL;
381        }
382        char *ifn = "ra0";
383        if (!strcmp(ifname, "wl1"))
384                ifn = "ba0";
385
386        if (nvram_nmatch("apsta", "%s_mode", ifname)
387            || nvram_nmatch("apstawet", "%s_mode", ifname)) {
388                ifn = "apcli0";
389                if (!strcmp(ifname, "wl1"))
390                        ifn = "apcli1";
391        }
392
393        int s;
394
395        s = getsocket();
396        if (OidQueryInformation(OID_GEN_MEDIA_CONNECT_STATUS, s, ifn, &ConnectStatus, sizeof(ConnectStatus)) < 0) {
397                return NULL;
398        }
399        if (OidQueryInformation(RT_OID_802_11_RADIO, s, ifn, &G_bRadio, sizeof(G_bRadio)) < 0) {
400                return NULL;
401        }
402        if (G_bRadio && ConnectStatus == 1) {
403                memset(&BssidQuery, 0x00, sizeof(BssidQuery));
404                OidQueryInformation(OID_802_11_BSSID, s, ifn, &BssidQuery, sizeof(BssidQuery));
405                long RSSI;
406                int nNoiseDbm;
407                unsigned char lNoise;   // this value is (ULONG) in Ndis driver (NOTICE!!!)
408
409                OidQueryInformation(RT_OID_802_11_RSSI, s, ifn, &RSSI, sizeof(RSSI));
410                OidQueryInformation(RT_OID_802_11_QUERY_NOISE_LEVEL, s, ifn, &lNoise, sizeof(lNoise));
411                nNoiseDbm = lNoise;
412                nNoiseDbm -= 143;
413
414                STAINFO *ret = safe_malloc(sizeof(STAINFO));
415
416                memcpy(ret->mac, BssidQuery, 6);
417                strcpy(ret->ifname, ifn);
418                ret->rssi = RSSI;
419                ret->noise = -nNoiseDbm;
420                return ret;
421        }
422        return NULL;
423
424}
425
426#define RTPRIV_IOCTL_GET_MAC_TABLE              (SIOCIWFIRSTPRIV + 0x0F)
427
428int getassoclist(char *ifname, unsigned char *list)
429{
430        struct iwreq iwr;
431        unsigned int *count = (unsigned int *)list;
432
433        RT_802_11_MAC_TABLE table = { 0 };
434        int s, i;
435
436        if (nvram_nmatch("disabled", "%s_net_mode", ifname)) {
437                return 0;
438        }
439
440        int state = get_radiostate(ifname);
441        int ignore = 0;
442
443        if (state == 0 || state == -1) {
444                ignore = 1;
445        }
446        if (!ignore) {
447                s = getsocket();
448                if (s < 0) {
449                        ignore = 1;
450                }
451                (void)memset(&iwr, 0, sizeof(struct iwreq));
452                (void)strncpy(iwr.ifr_name, getRADev(ifname), sizeof(iwr.ifr_name));
453
454                iwr.u.data.pointer = (caddr_t) & table;
455                if (ioctl(s, RTPRIV_IOCTL_GET_MAC_TABLE, &iwr) < 0) {
456                        ignore = 1;
457                }
458        }
459
460        unsigned char *l = (unsigned char *)list;
461
462        count[0] = 0;
463        l += 4;
464        STAINFO *sta = getRaStaInfo(ifname);
465
466        if (sta != NULL) {
467                memcpy(l, sta->mac, 6);
468                l += 6;
469                count[0]++;
470                free(sta);
471        }
472        if (!ignore && table.Num < 128)
473                for (i = 0; i < table.Num; i++) {
474                        memcpy(l, &table.Entry[i].Addr, 6);
475                        if (l[0] == 0 && l[1] == 0 && l[2] == 0 && l[3] == 0 && l[4] == 0 && l[5] == 0)
476                                break;
477                        l += 6;
478                        count[0]++;
479                }
480
481        return count[0];
482}
483
484int getRssi(char *ifname, unsigned char *mac)
485{
486        struct iwreq iwr;
487
488        RT_802_11_MAC_TABLE table = { 0 };
489        int s, i;
490
491        if (nvram_nmatch("disabled", "%s_net_mode", ifname)) {
492                return 0;
493        }
494
495        int state = get_radiostate(ifname);
496        int ignore = 0;
497
498        if (state == 0 || state == -1) {
499                ignore = 1;
500        }
501        if (!ignore) {
502                s = getsocket();
503                if (s < 0) {
504                        ignore = 1;
505                }
506                (void)memset(&iwr, 0, sizeof(struct iwreq));
507                (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
508
509                iwr.u.data.pointer = (caddr_t) & table;
510                if (ioctl(s, RTPRIV_IOCTL_GET_MAC_TABLE, &iwr) < 0) {
511                        ignore = 1;
512                }
513        }
514
515        STAINFO *sta = getRaStaInfo(ifname);
516
517        if (sta != NULL) {
518                if (!memcmp(mac, sta->mac, 6)) {
519                        int retu = sta->rssi;
520
521                        free(sta);
522                        return -95 + retu;
523                }
524                free(sta);
525        }
526        if (!ignore && table.Num < 128)
527                for (i = 0; i < table.Num; i++) {
528                        if (!memcmp(mac, &table.Entry[i].Addr, 6)) {
529                                return -95 + table.Entry[i].AvgRssi0;
530                        }
531                }
532        return 0;
533}
534
535int getNoise(char *ifname, unsigned char *mac)
536{
537
538        return -95;
539
540}
541
542int getUptime(char *ifname, unsigned char *mac)
543{
544        return 0;
545}
546
547void radio_off(int idx)
548{
549        switch (idx) {
550        case -1:
551                idx = 1;
552        case 0:
553                if (!nvram_match("wl0_net_mode", "disabled")) {
554                        eval("iwpriv", "ra0", "set", "RadioOn=0");
555                        eval("iwpriv", "ra0", "set", "WlanLed=0");
556                }
557        case 1:
558                if (!nvram_match("wl1_net_mode", "disabled") && idx == 1) {
559                        eval("iwpriv", "ba0", "set", "RadioOn=0");
560                        eval("iwpriv", "ba0", "set", "WlanLed=0");
561                }
562
563        }
564        led_control(LED_WLAN0, LED_OFF);
565}
566
567void radio_on(int idx)
568{
569        switch (idx) {
570        case -1:
571                idx = 1;
572        case 0:
573                if (!nvram_match("wl0_net_mode", "disabled")) {
574                        eval("iwpriv", "ra0", "set", "RadioOn=1");
575                        eval("iwpriv", "ra0", "set", "WlanLed=1");
576                }
577        case 1:
578                if (!nvram_match("wl1_net_mode", "disabled") && idx == 1) {
579                        eval("iwpriv", "ba0", "set", "RadioOn=1");
580                        eval("iwpriv", "ba0", "set", "WlanLed=1");
581                }
582
583        }
584        led_control(LED_WLAN0, LED_ON);
585}
586
587#else
588#ifdef WL_CHANSPEC_BW_8080
589
590static const uint8 wf_chspec_bw_mhz[] = { 5, 10, 20, 40, 80, 160, 160 };
591
592#define WF_NUM_BW \
593        (sizeof(wf_chspec_bw_mhz)/sizeof(uint8))
594
595/* 40MHz channels in 5GHz band */
596static const uint8 wf_5g_40m_chans[] = { 38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159 };
597
598#define WF_NUM_5G_40M_CHANS \
599        (sizeof(wf_5g_40m_chans)/sizeof(uint8))
600
601/* 80MHz channels in 5GHz band */
602static const uint8 wf_5g_80m_chans[] = { 42, 58, 106, 122, 138, 155 };
603
604#define WF_NUM_5G_80M_CHANS \
605        (sizeof(wf_5g_80m_chans)/sizeof(uint8))
606
607/* 160MHz channels in 5GHz band */
608static const uint8 wf_5g_160m_chans[] = { 50, 114 };
609
610#define WF_NUM_5G_160M_CHANS \
611        (sizeof(wf_5g_160m_chans)/sizeof(uint8))
612
613static uint8 center_chan_to_edge(uint bw)
614{
615        /* edge channels separated by BW - 10MHz on each side
616         * delta from cf to edge is half of that,
617         * MHz to channel num conversion is 5MHz/channel
618         */
619        return (uint8) (((bw - 20) / 2) / 5);
620}
621
622static uint8 channel_low_edge(uint center_ch, uint bw)
623{
624        return (uint8) (center_ch - center_chan_to_edge(bw));
625}
626
627/* return control channel given center channel and side band */
628static uint8 channel_to_ctl_chan(uint center_ch, uint bw, uint sb)
629{
630        return (uint8) (channel_low_edge(center_ch, bw) + sb * 4);
631}
632
633/* convert bandwidth from chanspec to MHz */
634static uint bw_chspec_to_mhz(chanspec_t chspec)
635{
636        uint bw;
637
638        bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT;
639        return (bw >= WF_NUM_BW ? 0 : wf_chspec_bw_mhz[bw]);
640}
641
642uint8 wf_chspec_ctlchan(chanspec_t chspec)
643{
644        uint center_chan;
645        uint bw_mhz;
646        uint sb;
647
648        /* Is there a sideband ? */
649        if (CHSPEC_IS20(chspec)) {
650                return CHSPEC_CHANNEL(chspec);
651        } else {
652                sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
653
654                if (CHSPEC_IS8080(chspec)) {
655                        bw_mhz = 80;
656
657                        if (sb < 4) {
658                                center_chan = CHSPEC_CHAN1(chspec);
659                        } else {
660                                center_chan = CHSPEC_CHAN2(chspec);
661                                sb -= 4;
662                        }
663
664                        /* convert from channel index to channel number */
665                        center_chan = wf_5g_80m_chans[center_chan];
666                } else {
667                        bw_mhz = bw_chspec_to_mhz(chspec);
668                        center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT;
669                }
670
671                return (channel_to_ctl_chan(center_chan, bw_mhz, sb));
672        }
673}
674
675static int getcenterchannel(chanspec_t chspec)
676{
677        const char *band;
678        uint ctl_chan;
679
680        /* ctl channel */
681        return wf_chspec_ctlchan(chspec);
682}
683
684#else
685
686#ifndef CHSPEC_IS40
687#define WL_CHANSPEC_CTL_SB_MASK         0x0300
688#define WL_CHANSPEC_CTL_SB_LOWER        0x0100
689#define WL_CHANSPEC_CTL_SB_UPPER        0x0200
690
691#define WL_CHANSPEC_BW_MASK             0x0C00
692#define WL_CHANSPEC_BW_40               0x0C00
693
694#define CHSPEC_CHANNEL(chspec)  ((uint8)(chspec & 0xff))
695
696#define CHSPEC_IS40(chspec)     (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
697#define CHSPEC_SB_UPPER(chspec) ((chspec & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
698#define CHSPEC_SB_LOWER(chspec) ((chspec & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
699#endif
700
701static int getcenterchannel(chanspec_t chspec)
702{
703        const char *band;
704        uint ctl_chan;
705        int channel;
706        channel = CHSPEC_CHANNEL(chspec);
707        /* check for non-default band spec */
708
709        if (CHSPEC_IS40(chspec)) {
710                if (CHSPEC_SB_UPPER(chspec)) {
711                        channel += 2;
712                } else {
713                        channel -= 2;
714                }
715        }
716        return channel;
717}
718#endif
719#ifdef HAVE_80211AC
720int has_beamforming(char *prefix)
721{
722        wlc_rev_info_t rev;
723        int c = 0;
724        if (!strcmp(prefix, "wl0"))
725                c = 0;
726        else if (!strcmp(prefix, "wl1"))
727                c = 1;
728        else if (!strcmp(prefix, "wl2"))
729                c = 2;
730
731        char *name = get_wl_instance_name(c);
732        wl_ioctl(name, WLC_GET_REVINFO, &rev, sizeof(rev));
733
734        if (rev.corerev < 40)
735                return 0;       /* TxBF unsupported */
736
737        return 1;
738
739}
740#endif
741
742int getchannels(unsigned int *retlist, char *ifname)
743{
744#ifdef HAVE_80211AC
745        char buf[WLC_IOCTL_MAXLEN];
746        int buflen;
747        int ret;
748        int count = 0;
749        int i;
750        chanspec_t c = 0, *chanspec;
751
752        char abbrev[WLC_CNTRY_BUF_SZ] = "";     /* default.. current locale */
753        wl_uint32_list_t *list;
754
755        memset(buf, 0, WLC_IOCTL_MAXLEN);
756        strcpy(buf, "chanspecs");
757        buflen = strlen(buf) + 1;
758
759        chanspec = (chanspec_t *) (buf + buflen);
760        *chanspec = c;
761        buflen += (sizeof(chanspec_t));
762
763        strncpy(buf + buflen, abbrev, WLC_CNTRY_BUF_SZ);
764
765        buflen += WLC_CNTRY_BUF_SZ;
766
767        list = (wl_uint32_list_t *) (buf + buflen);
768        list->count = WL_NUMCHANSPECS;
769        buflen += sizeof(uint32) * (WL_NUMCHANSPECS + 1);
770
771        if ((ret = wl_ioctl(ifname, WLC_GET_VAR, &buf[0], buflen)))
772                if (ret < 0)
773                        return 0;
774
775        int wl = get_wl_instance(ifname);
776
777        list = (wl_uint32_list_t *) buf;
778
779        int mask = 0;
780        int bw = atoi(nvram_nget("wl%d_nbw", wl));
781        if (!bw)
782                bw = 20;
783
784        int spec = 0;
785#ifdef WL_CHANSPEC_BW_8080
786        if (nvram_nmatch("8080", "wl%d_nbw", wl))
787                mask = WL_CHANSPEC_BW_8080;
788        else if (nvram_nmatch("160", "wl%d_nbw", wl))
789                mask = WL_CHANSPEC_BW_160;
790        else if (nvram_nmatch("80", "wl%d_nbw", wl))
791                mask = WL_CHANSPEC_BW_80;
792        else
793#endif
794        if (nvram_nmatch("40", "wl%d_nbw", wl))
795                mask = WL_CHANSPEC_BW_40;
796        else if (nvram_nmatch("20", "wl%d_nbw", wl))
797                mask = WL_CHANSPEC_BW_20;
798        else if (nvram_nmatch("0", "wl%d_nbw", wl))
799                mask = WL_CHANSPEC_BW_20;
800        else if (nvram_nmatch("10", "wl%d_nbw", wl))
801                mask = WL_CHANSPEC_BW_10;
802#ifdef WL_CHANSPEC_BW_5
803        else if (nvram_nmatch("5", "wl%d_nbw", wl))
804                mask = WL_CHANSPEC_BW_5;
805#endif
806
807        if (bw > 20) {
808#ifdef WL_CHANSPEC_CTL_SB_UU
809                if (bw == 80) {
810                        if (nvram_nmatch("lower", "wl%d_nctrlsb", wl) || nvram_nmatch("upper", "wl%d_nctrlsb", wl))
811                                nvram_nset("ll", "wl%d_nctrlsb", wl);
812                }
813                if (nvram_nmatch("uu", "wl%d_nctrlsb", wl))
814                        spec = WL_CHANSPEC_CTL_SB_UU;
815                else if (nvram_nmatch("ul", "wl%d_nctrlsb", wl))
816                        spec = WL_CHANSPEC_CTL_SB_UL;
817                else if (nvram_nmatch("lu", "wl%d_nctrlsb", wl))
818                        spec = WL_CHANSPEC_CTL_SB_LU;
819                else if (nvram_nmatch("ll", "wl%d_nctrlsb", wl))
820                        spec = WL_CHANSPEC_CTL_SB_LL;
821#endif
822                if (bw == 40) {
823                        if (nvram_nmatch("uu", "wl%d_nctrlsb", wl) || nvram_nmatch("ul", "wl%d_nctrlsb", wl) || nvram_nmatch("lu", "wl%d_nctrlsb", wl) || nvram_nmatch("ll", "wl%d_nctrlsb", wl))
824                                nvram_nset("lower", "wl%d_nctrlsb", wl);
825                }
826                if (nvram_nmatch("lower", "wl%d_nctrlsb", wl))
827                        spec = WL_CHANSPEC_CTL_SB_LOWER;
828                else if (nvram_nmatch("upper", "wl%d_nctrlsb", wl))
829                        spec = WL_CHANSPEC_CTL_SB_UPPER;
830        }
831
832        for (i = 0; i < list->count; i++) {
833
834                c = list->element[i];
835                int cspec = c & 0x700;
836                int cbw = c & 0x3800;
837                //        fprintf(stderr,"wl%d: %X spec %d, cbw %d\n",wl,c,cbw,cspec);
838                if ((cbw == mask) && (cspec == spec)) {
839                        //        fprintf(stderr,"take wl%d: %X spec %d, cbw %d\n",wl,c,cbw,cspec);
840
841                        int channel = getcenterchannel(c);
842
843                        int a;
844                        int inlist = 0;
845                        for (a = 0; a < count; a++)
846                                if (retlist[a] == channel) {
847                                        inlist = 1;
848                                        break;
849                                }
850                        if (!inlist) {
851                                retlist[count++] = channel;
852                        }
853                }
854        }
855        int a;
856        // sort
857        for (a = 0; a < count; a++) {
858                for (i = 0; i < count - 1; i++) {
859                        if (retlist[i + 1] < retlist[i]) {
860                                int cc = retlist[i + 1];
861                                retlist[i + 1] = retlist[i];
862                                retlist[i] = cc;
863                        }
864                }
865        }
866
867        return count;
868
869#else                           //HAVE_80211AC
870
871        // int ret, num;
872        // num = (sizeof (*list) - 4) / 6; /* Maximum number of entries in the
873        // buffer */
874        // memcpy (list, &num, 4); /* First 4 bytes are the number of ent. */
875
876        // ret = wl_ioctl (name, WLC_GET_VALID_CHANNELS, list, 128);
877        // fprintf(stderr,"get channels\n");
878        char exec[64];
879
880        sprintf(exec, "wl -i %s channels", ifname);
881        FILE *in = popen(exec, "r");
882
883        int chan;
884        int count = 0;
885
886        while (!feof(in) && fscanf(in, "%d", &chan) == 1) {
887                retlist[count++] = chan;
888        }
889        pclose(in);
890#ifdef BUFFALO_JP
891        return count - 1;
892#else
893        return count;
894#endif
895
896#endif
897}
898
899#ifdef TEST
900
901void main(int argc, char *argv[])
902{
903        char buf[1024];
904        getchannels(buf, "eth1");
905}
906#endif
907int has_5ghz(char *prefix)
908{
909#ifdef HAVE_QTN
910        if (!strcmp(prefix, "wl1"))
911                return 1;
912#endif
913        if (strstr(nvram_nget("%s_bandlist", prefix), "a"))
914                return 1;
915
916        return 0;
917}
918
919int has_2ghz(char *prefix)
920{
921        if (strstr(nvram_nget("%s_bandlist", prefix), "b"))
922                return 1;
923
924        return 0;
925}
926
927int wifi_getchannel(char *ifn)
928{
929        channel_info_t ci;
930        char name[32];
931        sprintf(name, "%s_ifname", ifn);
932        char *ifname = nvram_safe_get(name);
933
934        memset(&ci, 0, sizeof(ci));
935        wl_ioctl(ifname, WLC_GET_CHANNEL, &ci, sizeof(ci));
936        if (ci.scan_channel > 0) {
937                return ci.scan_channel;
938        } else if (ci.hw_channel > 0) {
939                return ci.hw_channel;
940        } else
941                return -1;
942}
943
944int wl_getbssid(char *wl, char *mac)
945{
946        int ret;
947        struct ether_addr ea;
948
949        wl_ioctl(wl, WLC_GET_BSSID, &ea, ETHER_ADDR_LEN);
950        ether_etoa(&ea, mac);
951        return 0;
952}
953
954int getassoclist(char *name, unsigned char *list)
955{
956#ifdef HAVE_QTN
957        if (has_qtn(name))
958                return getassoclist_qtn(name, list);
959#endif
960
961        // int ap;
962        // if ((wl_ioctl(name, WLC_GET_AP, &ap, sizeof(ap)) < 0) || ap)
963        // {
964        int ret;
965        unsigned int num;
966
967        num = (sizeof(*list) - 4) / 6;  /* Maximum number of entries in the
968                                         * buffer */
969        memcpy(list, &num, 4);  /* First 4 bytes are the number of ent. */
970
971        ret = wl_ioctl(name, WLC_GET_ASSOCLIST, list, 8192);
972        unsigned int *count = (unsigned int *)list;
973
974        // }else
975        // {
976        // char buf[WLC_IOCTL_MAXLEN];
977        /*
978         * wl_bss_info_t *bss_info = (wl_bss_info_t *) buf;
979         * memset(buf,0,WLC_IOCTL_MAXLEN); if (wl_ioctl(name, WLC_GET_BSS_INFO,
980         * bss_info, WLC_IOCTL_MAXLEN)<0)return 0; struct maclist *l = (struct
981         * maclist*)list;
982         */
983        /*
984         * sta_info_t *sta_info = (sta_info_t *) buf;
985         * memset(buf,0,WLC_IOCTL_MAXLEN); if (wl_ioctl(name, WLC_GET_VAR,
986         * sta_info, WLC_IOCTL_MAXLEN)<0)return 0;
987         *
988         * struct maclist *l = (struct maclist*)list; l->count=1;
989         * memcpy(&l->ea,&sta_info->ea,6);
990         */
991        if (ret < 0)
992                return -1;
993        return count[0];
994}
995#endif
996
997int getwdslist(char *name, unsigned char *list)
998{
999        int ret, num;
1000
1001        num = (sizeof(*list) - 4) / 6;  /* Maximum number of entries in the
1002                                         * buffer */
1003        memcpy(list, &num, 4);  /* First 4 bytes are the number of ent. */
1004
1005        ret = wl_ioctl(name, WLC_GET_WDSLIST, list, 8192);
1006
1007        return (ret);
1008}
1009
1010#if !defined(HAVE_RT2880) && !defined(HAVE_RT61)
1011int getNoise(char *ifname, unsigned char *macname)
1012{
1013        unsigned int noise;
1014
1015        // rssi = 0;
1016        // char buf[WLC_IOCTL_MAXLEN];
1017        wl_ioctl(ifname, WLC_GET_PHY_NOISE, &noise, sizeof(noise));
1018
1019        /*
1020         * wl_bss_info_t *bss_info = (wl_bss_info_t *) buf;
1021         * memset(buf,0,WLC_IOCTL_MAXLEN);
1022         *
1023         * wl_ioctl(name, WLC_GET_BSS_INFO, bss_info, WLC_IOCTL_MAXLEN); if
1024         * ((wl_ioctl(name, WLC_GET_AP, &ap, sizeof(ap)) < 0) || ap) { if
1025         * (wl_ioctl(name, WLC_GET_PHY_NOISE, &noise, sizeof(noise)) < 0) noise =
1026         * 0; } else { // somehow the structure doesn't fit here rssi = buf[82];
1027         * noise = buf[84]; }
1028         */
1029        return noise;
1030}
1031
1032int getUptime(char *ifname, unsigned char *mac)
1033{
1034        return 0;
1035}
1036
1037#endif
1038
1039#else
1040#include <sys/types.h>
1041#include <sys/file.h>
1042#include <sys/ioctl.h>
1043#include <sys/socket.h>
1044#include <stdio.h>
1045#include <stdlib.h>
1046#include <string.h>
1047#include <stdint.h>
1048#include <ctype.h>
1049#include <getopt.h>
1050#include <err.h>
1051
1052#include "wireless.h"
1053#undef WPA_OUI
1054#undef WME_OUI
1055#include "../madwifi.dev/madwifi.dev/net80211/ieee80211.h"
1056#include "../madwifi.dev/madwifi.dev/net80211/ieee80211_crypto.h"
1057#include "../madwifi.dev/madwifi.dev/net80211/ieee80211_ioctl.h"
1058
1059static int wrqfreq_to_int(struct iwreq *wrq)
1060{
1061        int freq, i;
1062        freq = wrq->u.freq.m;
1063        if (freq < 1000) {
1064                return freq;
1065        }
1066        int divisor = 1000000;
1067        int e = wrq->u.freq.e;
1068        for (i = 0; i < e; i++)
1069                divisor /= 10;
1070        if (divisor)
1071                freq /= divisor;
1072        return freq;
1073}
1074
1075/*
1076 * Atheros
1077 */
1078
1079#define IOCTL_ERR(x) [x - SIOCIWFIRSTPRIV] "ioctl[" #x "]"
1080static int set80211priv(struct iwreq *iwr, const char *ifname, int op, void *data, size_t len)
1081{
1082#define N(a)    (sizeof(a)/sizeof(a[0]))
1083
1084        memset(iwr, 0, sizeof(struct iwreq));
1085        strncpy(iwr->ifr_name, ifname, IFNAMSIZ);
1086        if (len < IFNAMSIZ) {
1087                /*
1088                 * Argument data fits inline; put it there.
1089                 */
1090                memcpy(iwr->u.name, data, len);
1091        } else {
1092                /*
1093                 * Argument data too big for inline transfer; setup a
1094                 * parameter block instead; the kernel will transfer
1095                 * the data for the driver.
1096                 */
1097                iwr->u.data.pointer = data;
1098                iwr->u.data.length = len;
1099        }
1100
1101        if (ioctl(getsocket(), op, iwr) < 0) {
1102                static const char *opnames[] = {
1103                        IOCTL_ERR(IEEE80211_IOCTL_SETPARAM),
1104                        IOCTL_ERR(IEEE80211_IOCTL_GETPARAM),
1105                        IOCTL_ERR(IEEE80211_IOCTL_SETMODE),
1106                        IOCTL_ERR(IEEE80211_IOCTL_GETMODE),
1107                        IOCTL_ERR(IEEE80211_IOCTL_SETWMMPARAMS),
1108                        IOCTL_ERR(IEEE80211_IOCTL_GETWMMPARAMS),
1109                        IOCTL_ERR(IEEE80211_IOCTL_SETCHANLIST),
1110                        IOCTL_ERR(IEEE80211_IOCTL_GETCHANLIST),
1111                        IOCTL_ERR(IEEE80211_IOCTL_CHANSWITCH),
1112                        IOCTL_ERR(IEEE80211_IOCTL_GETCHANINFO),
1113                        IOCTL_ERR(IEEE80211_IOCTL_SETOPTIE),
1114                        IOCTL_ERR(IEEE80211_IOCTL_GETOPTIE),
1115                        IOCTL_ERR(IEEE80211_IOCTL_SETMLME),
1116                        IOCTL_ERR(IEEE80211_IOCTL_SETKEY),
1117                        IOCTL_ERR(IEEE80211_IOCTL_DELKEY),
1118                        IOCTL_ERR(IEEE80211_IOCTL_ADDMAC),
1119                        IOCTL_ERR(IEEE80211_IOCTL_DELMAC),
1120                };
1121                op -= SIOCIWFIRSTPRIV;
1122                if (0 <= op && op < N(opnames))
1123                        perror(opnames[op]);
1124                else
1125                        perror("ioctl[unknown???]");
1126                return -1;
1127        }
1128        return 0;
1129#undef N
1130}
1131
1132int do80211priv(const char *ifname, int op, void *data, size_t len)
1133{
1134        struct iwreq iwr;
1135
1136        if (set80211priv(&iwr, ifname, op, data, len) < 0)
1137                return -1;
1138        if (len < IFNAMSIZ)
1139                memcpy(data, iwr.u.name, len);
1140        return iwr.u.data.length;
1141}
1142
1143#define KILO    1000
1144
1145long long wifi_getrate(char *ifname)
1146{
1147#if defined(HAVE_ATH9K) && !defined(HAVE_MVEBU)
1148        if (is_ath9k(ifname)) {
1149                char physical[32];
1150                strncpy(physical, ifname, 4);
1151                if (nvram_nmatch("b-only", "%s_net_mode", physical))
1152                        return 11000 * KILO;
1153                if (nvram_nmatch("g-only", "%s_net_mode", physical))
1154                        return 54000 * KILO;
1155                if (nvram_nmatch("a-only", "%s_net_mode", physical))
1156                        return 54000 * KILO;
1157                if (nvram_nmatch("bg-mixed", "%s_net_mode", physical))
1158                        return 54000 * KILO;
1159                struct wifi_interface *interface = mac80211_get_interface(ifname);
1160                if (!interface)
1161                        return -1;
1162                long long rate;
1163                int sgi = has_shortgi(physical);
1164                int vhtmcs = -1;
1165                //fprintf(stderr,"sgi %d, width %d\n",sgi, interface->width);
1166                if (nvram_nmatch("mixed", "%s_net_mode", physical) ||   //
1167                    nvram_nmatch("ac-only", "%s_net_mode", physical) || //
1168                    nvram_nmatch("1", "%s_turbo_qam", physical) ||      //
1169                    nvram_nmatch("acn-mixed", "%s_net_mode", physical)) //
1170                        vhtmcs = mac80211_get_maxvhtmcs(physical);
1171                int mcs = mac80211_get_maxmcs(physical);
1172                int novht = 0;
1173#ifdef HAVE_ATH10K
1174                if (is_ath10k(ifname) && has_2ghz(physical))
1175                        novht = nvram_nmatch("0", "%s_turbo_qam", physical);
1176#endif
1177                sgi = sgi ? nvram_nmatch("1", "%s_shortgi", physical) : 0;
1178                switch (interface->width) {
1179                case 2:
1180                        rate = 54000;
1181                        break;
1182                case 5:
1183                        rate = 54000 / 4;
1184                        break;
1185                case 10:
1186                        rate = 54000 / 2;
1187                        break;
1188                case 20:
1189                case 40:
1190                case 80:
1191                case 160:
1192                        rate = VHTTxRate(mcs, novht ? -1 : vhtmcs, sgi, interface->width);
1193                        break;
1194                case 8080:
1195                        rate = VHTTxRate(mcs, novht ? -1 : vhtmcs, sgi, 160);
1196                        break;
1197                default:
1198                        rate = 54000;
1199                }
1200                free(interface);
1201                return rate * KILO;
1202        } else
1203#endif
1204        {
1205
1206                struct iwreq wrq;
1207
1208                (void)memset(&wrq, 0, sizeof(struct iwreq));
1209                strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
1210                ioctl(getsocket(), SIOCGIWRATE, &wrq);
1211                return wrq.u.bitrate.value;
1212        }
1213}
1214
1215/*
1216 * For doing log10/exp10 without libm
1217 */
1218#define LOG10_MAGIC     1.25892541179
1219
1220int iw_mwatt2dbm(int in)
1221{
1222        /*
1223         * Version without libm : slower
1224         */
1225        double fin = (double)in;
1226        int res = 0;
1227
1228        /*
1229         * Split integral and floating part to avoid accumulating rounding errors
1230         */
1231        while (fin > 10.0) {
1232                res += 10;
1233                fin /= 10.0;
1234        }
1235        while (fin > 1.000001) {        /* Eliminate rounding errors, take ceil */
1236                res += 1;
1237                fin /= LOG10_MAGIC;
1238        }
1239        return (res);
1240}
1241
1242static int checkid(char *ifname, int vendorid, int productid)   //checks if its usually a emp card (no concrete detection possible)
1243{
1244#ifdef HAVE_MVEBU
1245        return 0;
1246#endif
1247        int vendor;
1248        int product;
1249        int devcount;
1250        char readid[64];
1251
1252        strcpy(readid, ifname);
1253        sscanf(readid, "ath%d", &devcount);
1254        sprintf(readid, "/proc/sys/dev/wifi%d/idvendor", devcount);
1255        FILE *in = fopen(readid, "rb");
1256        vendor = 0;
1257        if (in) {
1258                fscanf(in, "%d", &vendor);
1259                fclose(in);
1260        }
1261        sprintf(readid, "/proc/sys/dev/wifi%d/idproduct", devcount);
1262        in = fopen(readid, "rb");
1263        product = 0;
1264        if (in) {
1265                fscanf(in, "%d", &product);
1266                fclose(in);
1267        }
1268        if (vendor == vendorid && product == productid) //XR3.3/XR3.6/XR3.7 share the same pci id's
1269                return 1;
1270        return 0;
1271
1272}
1273
1274int isEMP(char *ifname)         //checks if its usually a emp card (no concrete detection possible)
1275{
1276        if (checkid(ifname, 0x168c, 0x2062))
1277                return 1;
1278        if (checkid(ifname, 0x168c, 0x2063))    //will include more suspicius cards.
1279                return 1;
1280        return 0;
1281
1282}
1283
1284int isXR36(char *ifname)        //checks if its usually a emp card (no concrete detection possible)
1285{
1286        return checkid(ifname, 0x0777, 0x3c03);
1287}
1288
1289int isFXXN_PRO(char *ifname)    //checks if its usualla a DBII Networks FxxN-PRO card (no correct detection possible)
1290{
1291        char cproduct[30];
1292        char cvendor[30];
1293        char readid[64];
1294        int devcount;
1295
1296        strcpy(readid, ifname);
1297        sscanf(readid, "ath%d", &devcount);
1298        sprintf(readid, "/sys/class/ieee80211/phy%d/device/subsystem_vendor", devcount);
1299        FILE *in = fopen(readid, "rb");
1300        if (in) {
1301                fscanf(in, "%s\n", cvendor);
1302                fclose(in);
1303        }
1304        sprintf(readid, "/sys/class/ieee80211/phy%d/device/subsystem_device", devcount);
1305        in = fopen(readid, "rb");
1306        if (in) {
1307                fscanf(in, "%s\n", cproduct);
1308                fclose(in);
1309        }
1310
1311        if (!strcmp(cvendor, "0x168c") && !strcmp(cproduct, "0x2096")) {        //F36N-PRO / F64N-PRO shares the same id's
1312                return 1;
1313        } else if (!strcmp(cvendor, "0xdb11") && !strcmp(cproduct, "0x0f50")) { // F50N-PRO
1314                return 2;
1315        }
1316        return 0;
1317}
1318
1319int isSR71E(char *ifname)
1320{
1321
1322        char cproduct[30];
1323        char cvendor[30];
1324        char readid[64];
1325        int devcount;
1326
1327        strcpy(readid, ifname);
1328        sscanf(readid, "ath%d", &devcount);
1329        sprintf(readid, "/sys/class/ieee80211/phy%d/device/subsystem_vendor", devcount);
1330        FILE *in = fopen(readid, "rb");
1331        if (in) {
1332                fscanf(in, "%s\n", cvendor);
1333                fclose(in);
1334        }
1335        sprintf(readid, "/sys/class/ieee80211/phy%d/device/subsystem_device", devcount);
1336        in = fopen(readid, "rb");
1337        if (in) {
1338                fscanf(in, "%s\n", cproduct);
1339                fclose(in);
1340        }
1341
1342        if (!strcmp(cvendor, "0x0777") && !strcmp(cproduct, "0x4e05")) {        // SR71-E
1343                return 1;
1344        }
1345        if (!strcmp(cvendor, "0x0777") && !strcmp(cproduct, "0x4082")) {        // SR71
1346                return 1;
1347        }
1348        if (!strcmp(cvendor, "0x168c") && !strcmp(cproduct, "0x2082")) {        // SR71-A
1349                return 1;
1350        }
1351        if (!strcmp(cvendor, "0x0777") && !strcmp(cproduct, "0x4005")) {        // SR71-15
1352                return 1;
1353        }
1354        if (!strcmp(cvendor, "0x0777") && !strcmp(cproduct, "0x4002")) {        // SR71-12
1355                return 1;
1356        }
1357        return 0;
1358
1359}
1360
1361int isDL4600(char *ifname)
1362{
1363        int vendor;
1364        int product;
1365        int devcount;
1366        char readid[64];
1367
1368        strcpy(readid, ifname);
1369        sscanf(readid, "ath%d", &devcount);
1370        sprintf(readid, "/proc/sys/dev/wifi%d/idvendor", devcount);
1371        FILE *in = fopen(readid, "rb");
1372        vendor = 0;
1373        if (in) {
1374                fscanf(in, "%d", &vendor);
1375                fclose(in);
1376        }
1377        sprintf(readid, "/proc/sys/dev/wifi%d/idproduct", devcount);
1378        in = fopen(readid, "rb");
1379        product = 0;
1380        if (in) {
1381                fscanf(in, "%d", &product);
1382                fclose(in);
1383        }
1384        if (vendor == 0x1C14 && product == 0x19)
1385                return 1;
1386        return 0;
1387}
1388
1389int wifi_gettxpower(char *ifname)
1390{
1391        int poweroffset = wifi_gettxpoweroffset(ifname);
1392        struct iwreq wrq;
1393
1394        (void)memset(&wrq, 0, sizeof(struct iwreq));
1395
1396        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
1397
1398        ioctl(getsocket(), SIOCGIWTXPOW, &wrq);
1399        closesocket();
1400        struct iw_param *txpower = &wrq.u.txpower;
1401
1402        if (txpower->disabled) {
1403                return 0;
1404        } else {
1405                /*
1406                 * Check for relative values
1407                 */
1408                if (txpower->flags & IW_TXPOW_RELATIVE) {
1409                        return txpower->value + poweroffset;
1410                } else {
1411                        int dbm = 0;
1412
1413                        /*
1414                         * Convert everything to dBm
1415                         */
1416                        if (txpower->flags & IW_TXPOW_MWATT)
1417                                dbm = iw_mwatt2dbm(txpower->value);
1418                        else
1419                                dbm = txpower->value;
1420                        return dbm + poweroffset;
1421                }
1422        }
1423}
1424
1425int wifi_gettxpoweroffset(char *ifname)
1426{
1427        int poweroffset = 0;
1428
1429#ifdef HAVE_ALPHA
1430        poweroffset = 10;
1431#elif HAVE_EOC1650
1432        poweroffset = 0;
1433#elif HAVE_BWRG1000
1434        poweroffset = 12;       //?? guess
1435#elif HAVE_EAP3660
1436        poweroffset = 8;
1437#elif HAVE_EOC2610
1438        poweroffset = 8;
1439#elif HAVE_ECB3500
1440        poweroffset = 8;
1441#elif HAVE_EOC5610
1442        poweroffset = 0;
1443#elif HAVE_NS2
1444        poweroffset = 10;
1445#elif HAVE_LC2
1446        poweroffset = 10;
1447#elif HAVE_BS2
1448        poweroffset = 0;
1449#elif HAVE_PICO2
1450        poweroffset = 0;
1451#elif HAVE_PICO2HP
1452        poweroffset = 10;
1453#elif HAVE_MS2
1454        poweroffset = 10;
1455#elif HAVE_BS2HP
1456        poweroffset = 10;
1457#elif HAVE_NS5
1458        poweroffset = 5;
1459#elif HAVE_PICO5
1460        poweroffset = 5;
1461#elif HAVE_NS3
1462        poweroffset = 5;
1463#elif HAVE_LC5
1464        poweroffset = 5;
1465#elif HAVE_DLM101
1466        poweroffset = 5;
1467#elif HAVE_BS5
1468        poweroffset = 5;
1469#elif HAVE_LS5
1470        poweroffset = 5;
1471#else
1472        if (isEMP(ifname)) {
1473                if (nvram_nmatch("2", "%s_cardtype", ifname))
1474                        return 8;
1475                if (nvram_nmatch("3", "%s_cardtype", ifname))
1476                        return 8;
1477                if (nvram_nmatch("5", "%s_cardtype", ifname))
1478                        return 8;
1479                if (nvram_nmatch("6", "%s_cardtype", ifname))
1480                        return 7;
1481                if (nvram_nmatch("7", "%s_cardtype", ifname))
1482                        return 10;
1483        }
1484
1485        if (isDL4600(ifname))
1486                return 10;
1487
1488#ifdef HAVE_ATH9K
1489        if (isFXXN_PRO(ifname))
1490                return 5;
1491        else if (isSR71E(ifname))
1492                return 7;
1493#endif
1494        int vendor;
1495        int devcount;
1496        char readid[64];
1497
1498        strcpy(readid, ifname);
1499        sscanf(readid, "ath%d", &devcount);
1500        sprintf(readid, "/proc/sys/dev/wifi%d/poweroffset", devcount);
1501        FILE *in = fopen(readid, "rb");
1502
1503        vendor = 0;
1504        if (in) {
1505                vendor = atoi(fgets(readid, sizeof(readid), in));
1506                fclose(in);
1507        }
1508        poweroffset = vendor;
1509        if (poweroffset < 0 || poweroffset > 20)
1510                poweroffset = 0;
1511#endif
1512        char *manpoweroffset;
1513        manpoweroffset = nvram_nget("%s_poweroffset", ifname);
1514        if (strlen(manpoweroffset)) {
1515                poweroffset = atoi(manpoweroffset);
1516        }
1517        return poweroffset;
1518}
1519
1520int get_wififreq(char *ifname, int freq)
1521{
1522#ifdef HAVE_NS3
1523        return -2000;
1524#endif
1525
1526        if (isEMP(ifname)) {
1527                if (nvram_nmatch("4", "%s_cardtype", ifname))
1528                        return freq - 2400;
1529        }
1530
1531        if (isDL4600(ifname))
1532                return freq - 705;
1533
1534#ifdef HAVE_ATH9K
1535        if (isFXXN_PRO(ifname) == 1) {
1536                if (nvram_nmatch("1", "%s_cardtype", ifname)) {
1537                        if (freq < 5180 || freq > 5580)
1538                                return -1;
1539                        return freq - 1830;
1540                }
1541                if (nvram_nmatch("2", "%s_cardtype", ifname)) {
1542                        if (freq < 5180 || freq > 5730)
1543                                return -1;
1544                        return freq + 720;
1545                }
1546        }
1547#endif
1548
1549        char *var = NULL;
1550        if (ifname) {
1551                char localvar[32];
1552                sprintf(localvar, "%s_offset", ifname);
1553                var = nvram_get(localvar);
1554        }
1555        if (var) {
1556                return freq + atoi(var);
1557        }
1558        int vendor;
1559        int devcount;
1560        char readid[64];
1561
1562        strcpy(readid, ifname);
1563        sscanf(readid, "ath%d", &devcount);
1564        sprintf(readid, "/proc/sys/dev/wifi%d/vendor", devcount);
1565        FILE *in = fopen(readid, "rb");
1566
1567        vendor = 0;
1568        if (in) {
1569                vendor = atoi(fgets(readid, sizeof(readid), in));
1570                fclose(in);
1571        }
1572        switch (vendor) {
1573        case 9:         // ubnt xr9
1574                if (freq < 2427 || freq > 2442)
1575                        return -1;
1576                return freq - (2427 - 907);
1577                break;
1578        case 4:         // ubnt sr9
1579                if (freq < 2422 || freq > 2437)
1580                        return -1;
1581                return (2422 + 922) - freq;
1582                break;
1583        case 13:
1584                return freq - (5540 - 3540);    // xr3 general 3,5 ghz
1585        case 1328:
1586                return freq - (5540 - 2840);    // xr3 special 2.8 ghz
1587        case 1336:
1588                if (nvram_nmatch("2", "%s_cardtype", ifname))
1589                        return freq - (5765 - 3658);    // xr3 3.7 ghz
1590                else
1591                        return freq - (5540 - 3340);    // xr3 special 3.3/3.6 ghz
1592        case 7:
1593                if (freq < 2427 || freq > 2442)
1594                        return -1;
1595                return freq - (2427 - 763);     // xr7
1596        case 14:
1597                return freq - (5540 - 4516);    // xr4
1598                // case 24:
1599                // return -(5540-4540); //sr4
1600        case 23:                // reserved for XR2.3 until spec is known
1601        case 26:                // reserved for XR2.6 until spec is known
1602
1603        default:
1604                return freq;
1605                break;
1606        }
1607        return freq;
1608}
1609
1610struct wifi_interface *wifi_getfreq(char *ifname)
1611{
1612        struct iwreq wrq;
1613
1614#ifdef HAVE_ATH9K
1615        if (has_ad(ifname)) {
1616                struct wifi_interface *interface = (struct wifi_interface *)malloc(sizeof(struct wifi_interface));
1617                memset(interface, 0, sizeof(struct wifi_interface));
1618                interface->freq = atoi(nvram_safe_get("ath2_channel"));
1619                interface->center1 = -1;
1620                interface->center2 = -1;
1621                return interface;
1622        }
1623        if (is_ath9k(ifname)) {
1624                return mac80211_get_interface(ifname);
1625        }
1626#endif
1627
1628        (void)memset(&wrq, 0, sizeof(struct iwreq));
1629        strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
1630        ioctl(getsocket(), SIOCGIWFREQ, &wrq);
1631        closesocket();
1632        struct wifi_interface *interface = (struct wifi_interface *)malloc(sizeof(struct wifi_interface));
1633        memset(interface, 0, sizeof(struct wifi_interface));
1634        interface->freq = wrqfreq_to_int(&wrq);
1635        interface->center1 = -1;
1636        interface->center2 = -1;
1637        return interface;
1638}
1639
1640int wifi_getchannel(char *ifname)
1641{
1642        struct wifi_interface *interface = wifi_getfreq(ifname);
1643        if (!interface)
1644                return 0;
1645        int channel = ieee80211_mhz2ieee(interface->freq);
1646        free(interface);
1647        return channel;
1648}
1649
1650int get_radiostate(char *ifname)
1651{
1652        if (nvram_nmatch("disabled", "%s_net_mode", ifname))
1653                return 0;
1654        if (!has_ad(ifname)) {
1655#ifdef HAVE_ATH9K
1656                if (is_ath9k(ifname)) {
1657                        char debugstring[64];
1658                        FILE *fp;
1659                        int idx;
1660                        char state[11];
1661
1662                        sprintf(debugstring, "/sys/kernel/debug/ieee80211/phy%d/ath9k/diag", get_ath9k_phy_ifname(ifname));
1663                        fp = fopen(debugstring, "r");
1664                        if (fp) {
1665                                fread(state, sizeof(state) - 1, 1, fp);
1666                                fclose(fp);
1667                                state[10] = '\0';
1668                                if (!strncmp(state, "0x00000003", 10))
1669                                        return 0;
1670                        }
1671                }
1672#endif
1673        }
1674        struct ifreq ifr;
1675        int skfd = getsocket();
1676
1677        strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1678        if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
1679                closesocket();
1680                return -1;
1681        }
1682        closesocket();
1683        if ((ifr.ifr_flags & IFF_UP)) {
1684                return 1;
1685        }
1686        return 0;
1687}
1688
1689static inline int iw_get_ext(int skfd,  /* Socket to the kernel */
1690                             const char *ifname,        /* Device name */
1691                             int request,       /* WE ID */
1692                             struct iwreq *pwrq)
1693{                               /* Fixed part of the
1694                                 * request */
1695        /*
1696         * Set device name
1697         */
1698        strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
1699        /*
1700         * Do the request
1701         */
1702        return (ioctl(skfd, request, pwrq));
1703}
1704
1705int isAssociated(char *ifname)
1706{
1707        struct iwreq wrq;
1708        int i;
1709
1710        if (iw_get_ext(getsocket(), ifname, SIOCGIWAP, &wrq) >= 0) {
1711                for (i = 0; i < 6; i++)
1712                        if (wrq.u.ap_addr.sa_data[i] != 0) {
1713                                closesocket();
1714                                return 1;
1715                        }
1716        }
1717        closesocket();
1718        return 0;
1719}
1720
1721int getAssocMAC(char *ifname, char *mac)
1722{
1723        struct iwreq wrq;
1724        int i;
1725        int ret = -1;
1726
1727        if (iw_get_ext(getsocket(), ifname, SIOCGIWAP, &wrq) >= 0) {
1728                for (i = 0; i < 6; i++)
1729                        if (wrq.u.ap_addr.sa_data[i] != 0)
1730                                ret = 0;
1731        }
1732        if (!ret) {
1733                for (i = 0; i < 6; i++)
1734                        mac[i] = wrq.u.ap_addr.sa_data[i];
1735
1736        }
1737        closesocket();
1738        return ret;
1739}
1740
1741#ifdef HAVE_ATH9K
1742
1743void radio_on_off_ath9k(int idx, int on)
1744{
1745        char debugstring[64];
1746        int fp;
1747        char secmode[16];
1748        char tpt[8];
1749
1750        sprintf(debugstring, "/sys/kernel/debug/ieee80211/phy%d/ath9k/diag", get_ath9k_phy_idx(idx));
1751        fp = open(debugstring, O_WRONLY);
1752        if (fp) {
1753                if (on)
1754                        write(fp, "0", strlen("0"));
1755                else
1756                        write(fp, "3", strlen("3"));
1757                fprintf(stderr, "ath9k radio %d: phy%d ath%d\n", on, get_ath9k_phy_idx(idx), idx);
1758                close(fp);
1759        }
1760        // LED
1761#ifdef HAVE_WZRHPAG300NH
1762        if (idx == 0)
1763                sprintf(debugstring, "/sys/class/leds/wireless_generic_1/trigger");
1764        else
1765                sprintf(debugstring, "/sys/class/leds/wireless_generic_21/trigger");
1766#else
1767        sprintf(debugstring, "/sys/class/leds/ath9k-phy%d/trigger", get_ath9k_phy_idx(idx));
1768#endif
1769        fp = open(debugstring, O_WRONLY);
1770        if (fp) {
1771                if (on) {
1772                        sprintf(tpt, "phy%dtpt", get_ath9k_phy_idx(idx));
1773                        write(fp, tpt, strlen(tpt));
1774                        sprintf(secmode, "ath%d_akm", idx);
1775                        if (nvram_get(secmode) && !nvram_match(secmode, "disabled")) {
1776                                // needs refinements
1777                                if (idx == 0)
1778                                        led_control(LED_SEC0, LED_ON);
1779                                else if (idx == 1)
1780                                        led_control(LED_SEC1, LED_ON);
1781                        }
1782                } else {
1783                        write(fp, "none", strlen("none"));
1784#ifdef HAVE_WZRHPAG300NH
1785                        if (idx == 0) {
1786                                led_control(LED_SEC0, LED_OFF);
1787                        } else if (idx == 1) {
1788                                led_control(LED_SEC1, LED_OFF);
1789                        }
1790#endif
1791                }
1792                close(fp);
1793        }
1794}
1795
1796#endif
1797
1798int is_ar5008(char *prefix)
1799{
1800        char sys[64];
1801        int devnum;
1802        sscanf(prefix, "ath%d", &devnum);
1803
1804        sprintf(sys, "/proc/sys/dev/wifi%d/mimo", devnum);
1805
1806        if (f_exists(sys))
1807                return 1;
1808
1809        return 0;
1810}
1811
1812int is_ath11n(char *prefix)
1813{
1814#ifdef HAVE_ATH9K
1815        if (is_ath9k(prefix))
1816                return 1;
1817#endif
1818#ifdef HAVE_MADWIFI_MIMO
1819        if (is_ar5008(prefix))
1820                return 1;
1821#endif
1822        return 0;
1823}
1824
1825int has_athmask(int devnum, int mask)
1826{
1827        char sys[64];
1828        int modes;
1829
1830        sprintf(sys, "/proc/sys/dev/wifi%d/wirelessmodes", devnum);
1831        FILE *tmp = fopen(sys, "rb");
1832
1833        if (tmp == NULL)
1834                return 0;
1835        fscanf(tmp, "%d", &modes);
1836        fclose(tmp);
1837        if ((modes & mask) == mask)
1838                return 1;
1839        else
1840                return 0;
1841}
1842
1843static struct wifi_channels *list_channelsext(const char *ifname, int allchans)
1844{
1845        struct ieee80211req_chaninfo chans;
1846        struct ieee80211req_chaninfo achans;
1847        const struct ieee80211_channel *c;
1848        int i;
1849
1850        // fprintf (stderr, "list channels for %s\n", ifname);
1851        if (do80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO, &chans, sizeof(chans)) < 0) {
1852                fprintf(stderr, "unable to get channel information\n");
1853                return NULL;
1854        }
1855        if (!allchans) {
1856                uint8_t active[64];
1857                if (do80211priv(ifname, IEEE80211_IOCTL_GETCHANLIST, &active, sizeof(active)) < 0) {
1858                        fprintf(stderr, "unable to get active channel list\n");
1859                        return NULL;
1860                }
1861                memset(&achans, 0, sizeof(achans));
1862                for (i = 0; i < chans.ic_nchans; i++) {
1863                        c = &chans.ic_chans[i];
1864                        if (isset(active, c->ic_ieee) || allchans)
1865                                achans.ic_chans[achans.ic_nchans++] = *c;
1866                }
1867        } else
1868                achans = chans;
1869
1870        // fprintf(stderr,"channel number %d\n", achans.ic_nchans);
1871        struct wifi_channels *list = (struct wifi_channels *)calloc(sizeof(struct wifi_channels) * (achans.ic_nchans + 1), 1);
1872
1873        char wl_mode[16];
1874        char wl_turbo[16];
1875
1876        sprintf(wl_mode, "%s_net_mode", ifname);
1877        sprintf(wl_turbo, "%s_channelbw", ifname);
1878        int l = 0;
1879
1880        for (i = 0; i < achans.ic_nchans; i++) {
1881                // fprintf(stderr,"channel number %d of %d\n", i,achans.ic_nchans);
1882
1883                // filter out A channels if mode isnt A-Only or mixed
1884                if (IEEE80211_IS_CHAN_A(&achans.ic_chans[i])) {
1885#ifdef HAVE_WHRAG108
1886                        if (!strcmp(ifname, "ath1"))
1887                                continue;
1888#endif
1889#ifdef HAVE_TW6600
1890                        if (!strcmp(ifname, "ath1"))
1891                                continue;
1892#endif
1893                        if (nvram_invmatch(wl_mode, "a-only")
1894                            && nvram_invmatch(wl_mode, "mixed"))
1895                                continue;
1896                }
1897                // filter out B/G channels if mode isnt g-only, b-only or mixed
1898                if (IEEE80211_IS_CHAN_ANYG(&achans.ic_chans[i])
1899                    || IEEE80211_IS_CHAN_B(&achans.ic_chans[i])) {
1900#ifdef HAVE_WHRAG108
1901                        if (!strcmp(ifname, "ath0"))
1902                                continue;
1903#endif
1904#ifdef HAVE_TW6600
1905                        if (!strcmp(ifname, "ath0"))
1906                                continue;
1907#endif
1908                        if (nvram_invmatch(wl_mode, "g-only")
1909                            && nvram_invmatch(wl_mode, "mixed")
1910                            && nvram_invmatch(wl_mode, "b-only")
1911                            && nvram_invmatch(wl_mode, "bg-mixed"))
1912                                continue;
1913                }
1914                // filter out channels which are not supporting turbo mode if turbo
1915                // is enabled
1916                if (!IEEE80211_IS_CHAN_STURBO(&achans.ic_chans[i])
1917                    && !IEEE80211_IS_CHAN_DTURBO(&achans.ic_chans[i])) {
1918                        if (nvram_matchi(wl_turbo, 40))
1919                                continue;
1920                }
1921                // filter out turbo channels if turbo mode is disabled
1922                /*
1923                 * if (IEEE80211_IS_CHAN_STURBO (&achans.ic_chans[i]) ||
1924                 * IEEE80211_IS_CHAN_DTURBO (&achans.ic_chans[i])) { if (nvram_match
1925                 * (wl_turbo, "0")) continue; }
1926                 */
1927                if (IEEE80211_IS_CHAN_STURBO(&achans.ic_chans[i])) {
1928                        if (!nvram_matchi(wl_turbo, 40))
1929                                continue;
1930                }
1931
1932                list[l].channel = achans.ic_chans[i].ic_ieee;
1933                list[l].freq = achans.ic_chans[i].ic_freq;
1934                list[l].noise = -95;    // achans.ic_chans[i].ic_noise;
1935                l++;
1936        }
1937
1938        list[l].freq = -1;
1939        return list;
1940}
1941
1942struct wifi_channels *list_channels(char *devnr)
1943{
1944
1945        return list_channelsext(devnr, 1);
1946        /*
1947         * char csign[64]; char channel[64]; char ppp[64]; char freq[64]; char
1948         * dum1[64]; char dum2[64]; char dum3[64]; char dum4[64];
1949         *
1950         * char cmd[64]; sprintf (cmd, "iwlist %s chan>/tmp/.channels", devnr);
1951         * system (cmd); FILE *in = fopen ("/tmp/.channels", "rb"); if (in ==
1952         * NULL) return NULL; fscanf (in, "%s %s %s %s %s %s %s %s", csign,
1953         * channel, ppp, freq, dum1, dum2, dum3, dum4); int ch = atoi (channel);
1954         * int i; struct wifi_channels *list = (struct wifi_channels *) safe_malloc
1955         * (sizeof (struct wifi_channels) * (ch+1) ); for (i = 0; i < ch; i++) {
1956         * fscanf (in, "%s %s %s %s %s", csign, channel, ppp, freq, dum1); if
1957         * (!strcmp (csign, "Current")) break; list[i].channel = atoi (channel);
1958         * list[i].freq = strdup (freq); channelcount++; } fclose (in); return
1959         * list;
1960         */
1961}
1962
1963int getRssi(char *ifname, unsigned char *mac)
1964{
1965#ifdef HAVE_ATH9K
1966        if (is_ath9k(ifname)) {
1967                return getRssi_ath9k(ifname, mac);
1968        }
1969#endif
1970#ifdef HAVE_MADWIFI_MIMO
1971        if (is_ar5008(ifname)) {
1972                return getRssi_11n(ifname, mac);
1973        }
1974#endif
1975        unsigned char *buf = calloc(24 * 1024, 1);
1976
1977        unsigned char *cp;
1978        int len;
1979        struct iwreq iwr;
1980        int s;
1981        char nb[32];
1982        sprintf(nb, "%s_bias", ifname);
1983
1984        s = socket(AF_INET, SOCK_DGRAM, 0);
1985        if (s < 0) {
1986                fprintf(stderr, "socket(SOCK_DRAGM)\n");
1987                free(buf);
1988                return 0;
1989        }
1990        (void)memset(&iwr, 0, sizeof(iwr));
1991        (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
1992        iwr.u.data.pointer = (void *)buf;
1993        iwr.u.data.length = 1024 * 24;
1994        if (ioctl(s, IEEE80211_IOCTL_STA_INFO, &iwr) < 0) {
1995                close(s);
1996                free(buf);
1997                return 0;
1998        }
1999        len = iwr.u.data.length;
2000        if (len < sizeof(struct ieee80211req_sta_info)) {
2001                close(s);
2002                free(buf);
2003                return 0;
2004        }
2005
2006        cp = buf;
2007        char maccmp[6];
2008
2009        memset(maccmp, 0, 6);
2010        do {
2011                struct ieee80211req_sta_info *si;
2012
2013                si = (struct ieee80211req_sta_info *)cp;
2014                if (!memcmp(&si->isi_macaddr[0], mac, 6)) {
2015                        close(s);
2016                        int rssi = si->isi_noise + si->isi_rssi;
2017
2018                        free(buf);
2019
2020                        return rssi + nvram_default_geti(nb, 0);
2021                }
2022                if (!memcmp(&si->isi_macaddr[0], mac, 6))
2023                        break;
2024                cp += si->isi_len;
2025                len -= si->isi_len;
2026        }
2027        while (len >= sizeof(struct ieee80211req_sta_info));
2028        close(s);
2029        free(buf);
2030        return 0;
2031}
2032
2033int getUptime(char *ifname, unsigned char *mac)
2034{
2035#ifdef HAVE_ATH9K
2036        if (is_ath9k(ifname)) {
2037                return getUptime_ath9k(ifname, mac);
2038        }
2039#endif
2040#ifdef HAVE_MADWIFI_MIMO
2041        if (is_ar5008(ifname)) {
2042                return getUptime_11n(ifname, mac);
2043        }
2044#endif
2045        unsigned char *buf = calloc(24 * 1024, 1);
2046
2047        unsigned char *cp;
2048        int len;
2049        struct iwreq iwr;
2050        int s;
2051
2052        s = socket(AF_INET, SOCK_DGRAM, 0);
2053        if (s < 0) {
2054                fprintf(stderr, "socket(SOCK_DRAGM)\n");
2055                free(buf);
2056                return 0;
2057        }
2058        (void)memset(&iwr, 0, sizeof(iwr));
2059        (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
2060        iwr.u.data.pointer = (void *)buf;
2061        iwr.u.data.length = 24 * 1024;
2062        if (ioctl(s, IEEE80211_IOCTL_STA_INFO, &iwr) < 0) {
2063                close(s);
2064                free(buf);
2065                return 0;
2066        }
2067        len = iwr.u.data.length;
2068        if (len < sizeof(struct ieee80211req_sta_info)) {
2069                close(s);
2070                free(buf);
2071                return -1;
2072        }
2073
2074        cp = buf;
2075        char maccmp[6];
2076
2077        memset(maccmp, 0, 6);
2078        do {
2079                struct ieee80211req_sta_info *si;
2080
2081                si = (struct ieee80211req_sta_info *)cp;
2082                if (!memcmp(&si->isi_macaddr[0], mac, 6)) {
2083                        close(s);
2084                        int uptime = 0; //si->isi_uptime;
2085
2086                        free(buf);
2087                        return uptime;
2088                }
2089                if (!memcmp(&si->isi_macaddr[0], mac, 6))
2090                        break;
2091                cp += si->isi_len;
2092                len -= si->isi_len;
2093        }
2094        while (len >= sizeof(struct ieee80211req_sta_info));
2095        close(s);
2096        free(buf);
2097        return 0;
2098}
2099
2100int getNoise(char *ifname, unsigned char *mac)
2101{
2102#ifdef HAVE_ATH9K
2103        if (is_ath9k(ifname)) {
2104                return getNoise_ath9k(ifname, mac);
2105        }
2106#endif
2107#ifdef HAVE_MADWIFI_MIMO
2108        if (is_ar5008(ifname)) {
2109                return getNoise_11n(ifname, mac);
2110        }
2111#endif
2112        unsigned char *buf = calloc(24 * 1024, 1);
2113
2114        unsigned char *cp;
2115        int len;
2116        struct iwreq iwr;
2117        int s;
2118        char nb[32];
2119        sprintf(nb, "%s_bias", ifname);
2120
2121        s = socket(AF_INET, SOCK_DGRAM, 0);
2122        if (s < 0) {
2123                fprintf(stderr, "socket(SOCK_DRAGM)\n");
2124                free(buf);
2125                return 0;
2126        }
2127        (void)memset(&iwr, 0, sizeof(iwr));
2128        (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
2129        iwr.u.data.pointer = (void *)buf;
2130        iwr.u.data.length = 24 * 1024;
2131        if (ioctl(s, IEEE80211_IOCTL_STA_INFO, &iwr) < 0) {
2132                close(s);
2133                free(buf);
2134                return 0;
2135        }
2136        len = iwr.u.data.length;
2137        if (len < sizeof(struct ieee80211req_sta_info)) {
2138                close(s);
2139                free(buf);
2140                return -1;
2141        }
2142
2143        cp = buf;
2144        char maccmp[6];
2145
2146        memset(maccmp, 0, 6);
2147        do {
2148                struct ieee80211req_sta_info *si;
2149
2150                si = (struct ieee80211req_sta_info *)cp;
2151                if (!memcmp(&si->isi_macaddr[0], mac, 6)) {
2152                        close(s);
2153                        int noise = si->isi_noise;
2154
2155                        free(buf);
2156                        return noise + nvram_default_geti(nb, 0);
2157                }
2158                if (!memcmp(&si->isi_macaddr[0], mac, 6))
2159                        break;
2160                cp += si->isi_len;
2161                len -= si->isi_len;
2162        }
2163        while (len >= sizeof(struct ieee80211req_sta_info));
2164        close(s);
2165        free(buf);
2166        return 0;
2167}
2168
2169int getassoclist(char *ifname, unsigned char *list)
2170{
2171#ifdef HAVE_ATH9K
2172        if (is_ath9k(ifname)) {
2173                return getassoclist_ath9k(ifname, list);
2174        }
2175#endif
2176#ifdef HAVE_MADWIFI_MIMO
2177        if (is_ar5008(ifname)) {
2178                return getassoclist_11n(ifname, list);
2179        }
2180#endif
2181        unsigned char *buf;
2182
2183        buf = calloc(24 * 1024, 1);
2184        unsigned char *cp;
2185        int len;
2186        struct iwreq iwr;
2187        int s;
2188        unsigned int *count = (unsigned int *)list;
2189
2190        if (nvram_nmatch("disabled", "%s_net_mode", ifname)) {
2191                free(buf);
2192                return 0;
2193        }
2194        int mincount = 0;
2195
2196        if (nvram_nmatch("wdssta", "%s_mode", ifname)
2197            || nvram_nmatch("sta", "%s_mode", ifname)
2198            || nvram_nmatch("wet", "%s_mode", ifname)) {
2199                int assoc = isAssociated(ifname);
2200
2201                if (!assoc) {
2202                        free(buf);
2203                        return 0;
2204                }
2205                char mac[6];
2206
2207                getAssocMAC(ifname, mac);
2208                memcpy(&list[4], mac, 6);
2209                count[0] = 1;
2210                mincount = 1;
2211        }
2212        s = socket(AF_INET, SOCK_DGRAM, 0);
2213        if (s < 0) {
2214                fprintf(stderr, "socket(SOCK_DRAGM)\n");
2215                free(buf);
2216                mincount = 1;
2217                return mincount;
2218        }
2219        (void)memset(&iwr, 0, sizeof(iwr));
2220        (void)strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
2221        iwr.u.data.pointer = (void *)buf;
2222        iwr.u.data.length = 1024 * 24;
2223        if (ioctl(s, IEEE80211_IOCTL_STA_INFO, &iwr) < 0) {
2224                close(s);
2225                free(buf);
2226                return mincount;
2227        }
2228        len = iwr.u.data.length;
2229        if (len < sizeof(struct ieee80211req_sta_info)) {
2230                close(s);
2231                free(buf);
2232                return mincount;
2233        }
2234
2235        cp = buf;
2236        unsigned char *l = (unsigned char *)list;
2237
2238        count[0] = 0;
2239        l += 4;
2240        do {
2241                struct ieee80211req_sta_info *si;
2242
2243                si = (struct ieee80211req_sta_info *)cp;
2244                memcpy(l, &si->isi_macaddr[0], 6);
2245                if (l[0] == 0 && l[1] == 0 && l[2] == 0 && l[3] == 0 && l[4] == 0 && l[5] == 0)
2246                        break;
2247                l += 6;
2248                count[0]++;
2249                cp += si->isi_len;
2250                len -= si->isi_len;
2251        }
2252        while (len >= sizeof(struct ieee80211req_sta_info));
2253        close(s);
2254        free(buf);
2255
2256        return mincount > count[0] ? mincount : count[0];
2257}
2258
2259void radio_off(int idx)
2260{
2261#ifdef HAVE_ATH9K
2262#ifdef HAVE_MADWIFI_MIMO
2263        if (nvram_match("mimo_driver", "ath9k"))
2264#endif
2265        {
2266                if (idx == -1) {
2267                        int cc = getdevicecount();
2268                        int i;
2269                        for (i = 0; i < cc; i++) {
2270                                radio_on_off_ath9k(i, 0);
2271                        }
2272                        led_control(LED_WLAN0, LED_OFF);
2273                        led_control(LED_WLAN1, LED_OFF);
2274                } else {
2275                        radio_on_off_ath9k(idx, 0);
2276                        if (idx == 0)
2277                                led_control(LED_WLAN0, LED_OFF);
2278                        if (idx == 1)
2279                                led_control(LED_WLAN1, LED_OFF);
2280                }
2281        }
2282#endif
2283        if (idx != -1) {
2284#ifdef HAVE_MVEBU
2285
2286#else
2287                writevaproc("1", "/proc/sys/dev/wifi%d/silent", idx);
2288                writevaproc("1", "/proc/sys/dev/wifi%d/ledon", idx);    // switch off led
2289#endif
2290                if (idx == 0)
2291                        led_control(LED_WLAN0, LED_OFF);
2292                if (idx == 1)
2293                        led_control(LED_WLAN1, LED_OFF);
2294        } else {
2295                int cc = getdevicecount();
2296                int i;
2297                for (i = 0; i < cc; i++) {
2298#ifdef HAVE_MVEBU
2299
2300#else
2301                        writevaproc("1", "/proc/sys/dev/wifi%d/silent", i);
2302                        writevaproc("1", "/proc/sys/dev/wifi%d/ledon", i);      // switch off led
2303#endif
2304                }
2305                led_control(LED_WLAN0, LED_OFF);
2306                led_control(LED_WLAN1, LED_OFF);
2307        }
2308#ifdef HAVE_ATH9K
2309#endif
2310}
2311
2312void radio_on(int idx)
2313{
2314#ifdef HAVE_ATH9K
2315#ifdef HAVE_MADWIFI_MIMO
2316        if (nvram_match("mimo_driver", "ath9k"))
2317#endif
2318        {
2319                if (idx == -1) {
2320                        int cc = getdevicecount();
2321                        int i;
2322                        for (i = 0; i < cc; i++) {
2323                                radio_on_off_ath9k(i, 1);
2324                        }
2325                        led_control(LED_WLAN0, LED_ON);
2326                        led_control(LED_WLAN1, LED_ON);
2327                } else {
2328                        radio_on_off_ath9k(idx, 1);
2329                        if (idx == 0)
2330                                led_control(LED_WLAN0, LED_ON);
2331                        if (idx == 1)
2332                                led_control(LED_WLAN1, LED_ON);
2333                }
2334        }
2335#endif
2336        if (idx != -1) {
2337#ifdef HAVE_MVEBU
2338
2339#else
2340                writevaproc("0", "/proc/sys/dev/wifi%d/silent", idx);
2341#endif
2342                if (idx == 0)
2343                        led_control(LED_WLAN0, LED_ON);
2344                if (idx == 1)
2345                        led_control(LED_WLAN1, LED_ON);
2346        } else {
2347                int cc = getdevicecount();
2348                int i;
2349                for (i = 0; i < cc; i++) {
2350                        writevaproc("0", "/proc/sys/dev/wifi%d/silent", i);
2351                }
2352                led_control(LED_WLAN0, LED_ON);
2353                led_control(LED_WLAN1, LED_ON);
2354        }
2355}
2356
2357int gettxantenna(char *ifname)
2358{
2359#ifdef HAVE_ATH9K
2360        if (is_ath9k(ifname)) {
2361#ifdef HAVE_CARLSONWIRELESS
2362                if (!registered_has_cap(20))
2363                        return (1);
2364#endif
2365                return (mac80211_get_avail_tx_antenna(get_ath9k_phy_ifname(ifname)));
2366        } else
2367#endif
2368                return (7);
2369}
2370
2371int getrxantenna(char *ifname)
2372{
2373#ifdef HAVE_ATH9K
2374        if (is_ath9k(ifname)) {
2375#ifdef HAVE_CARLSONWIRELESS
2376                if (!registered_has_cap(20))
2377                        return (1);
2378#endif
2379                return (mac80211_get_avail_rx_antenna(get_ath9k_phy_ifname(ifname)));
2380        } else
2381#endif
2382                return (7);
2383}
2384
2385#endif
2386
2387#if !defined(HAVE_MADWIFI) && !defined(HAVE_RT2880) && !defined(HAVE_RT61)
2388
2389void radio_off(int idx)
2390{
2391        if (pidof("nas") > 0 || pidof("wrt-radauth") > 0) {
2392                eval("stopservice", "nas", "-f");
2393        }
2394        if (idx != -1) {
2395                fprintf(stderr, "radio_off(%d) interface: %s\n", idx, get_wl_instance_name(idx));
2396                eval("wl", "-i", get_wl_instance_name(idx), "radio", "off");
2397                if (idx == 0)
2398                        led_control(LED_WLAN0, LED_OFF);
2399                if (idx == 1)
2400                        led_control(LED_WLAN1, LED_OFF);
2401                if (idx == 2)
2402                        led_control(LED_WLAN2, LED_OFF);
2403
2404        } else {
2405
2406                int cc = get_wl_instances();
2407                int ii;
2408
2409                for (ii = 0; ii < cc; ii++) {
2410                        eval("wl", "-i", get_wl_instance_name(ii), "radio", "off");
2411                }
2412                led_control(LED_WLAN0, LED_OFF);
2413                led_control(LED_WLAN1, LED_OFF);
2414                led_control(LED_WLAN2, LED_OFF);
2415        }
2416        //fix ticket 2991
2417        eval("startservice", "nas", "-f");
2418
2419}
2420
2421void radio_on(int idx)
2422{
2423        if (pidof("nas") > 0 || pidof("wrt-radauth") > 0) {
2424                eval("stopservice", "nas", "-f");
2425        }
2426        if (idx != -1) {
2427
2428                if (!nvram_nmatch("disabled", "wl%d_net_mode", idx)) {
2429                        fprintf(stderr, "radio_on(%d) interface: %s \n", idx, get_wl_instance_name(idx));
2430                        eval("wl", "-i", get_wl_instance_name(idx), "radio", "off");
2431                        eval("wl", "-i", get_wl_instance_name(idx), "radio", "on");
2432                }
2433
2434                if (idx == 0)
2435                        led_control(LED_WLAN0, LED_ON);
2436                if (idx == 1)
2437                        led_control(LED_WLAN1, LED_ON);
2438                if (idx == 2)
2439                        led_control(LED_WLAN2, LED_ON);
2440
2441        } else {
2442                int cc = get_wl_instances();
2443                int ii;
2444                for (ii = 0; ii < cc; ii++) {
2445                        if (!nvram_nmatch("disabled", "wl%d_net_mode", ii)) {
2446                                eval("wl", "-i", get_wl_instance_name(ii), "radio", "off");
2447                                eval("wl", "-i", get_wl_instance_name(ii), "radio", "on");
2448                        }
2449                }
2450                led_control(LED_WLAN0, LED_ON);
2451                led_control(LED_WLAN1, LED_ON);
2452                led_control(LED_WLAN2, LED_ON);
2453        }
2454        eval("startservice", "nas", "-f");
2455        eval("startservice", "guest_nas", "-f");
2456}
2457
2458/*
2459 * int wl_probe (char *name) { int ret, val;
2460 *
2461 * if ((ret = wl_ioctl (name, WLC_GET_MAGIC, &val, sizeof (val)))) return
2462 * ret; if (val != WLC_IOCTL_MAGIC) return -1; if ((ret = wl_ioctl (name,
2463 * WLC_GET_VERSION, &val, sizeof (val)))) return ret; if (val >
2464 * WLC_IOCTL_VERSION) return -1;
2465 *
2466 * return ret; }
2467 */
2468// #ifndef HAVE_MSSID
2469int wl_set_val(char *name, char *var, void *val, int len)
2470{
2471        char buf[128];
2472        int buf_len;
2473
2474        /*
2475         * check for overflow
2476         */
2477        if ((buf_len = strlen(var)) + 1 + len > sizeof(buf))
2478                return -1;
2479
2480        strcpy(buf, var);
2481        buf_len += 1;
2482
2483        /*
2484         * append int value onto the end of the name string
2485         */
2486        memcpy(&buf[buf_len], val, len);
2487        buf_len += len;
2488
2489        return wl_ioctl(name, WLC_SET_VAR, buf, buf_len);
2490}
2491
2492int wl_get_val(char *name, char *var, void *val, int len)
2493{
2494        char buf[128];
2495        int ret;
2496
2497        /*
2498         * check for overflow
2499         */
2500        if (strlen(var) + 1 > sizeof(buf) || len > sizeof(buf))
2501                return -1;
2502
2503        strcpy(buf, var);
2504        if ((ret = wl_ioctl(name, WLC_GET_VAR, buf, sizeof(buf))))
2505                return ret;
2506
2507        memcpy(val, buf, len);
2508        return 0;
2509}
2510
2511int wl_set_int(char *name, char *var, int val)
2512{
2513        return wl_set_val(name, var, &val, sizeof(val));
2514}
2515
2516int wl_get_int(char *name, char *var, int *val)
2517{
2518        return wl_get_val(name, var, val, sizeof(*val));
2519}
2520
2521int wl_iovar_getbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen)
2522{
2523        int err;
2524        uint namelen;
2525        uint iolen;
2526
2527        namelen = strlen(iovar) + 1;    /* length of iovar name plus null */
2528        iolen = namelen + paramlen;
2529
2530        /* check for overflow */
2531        if (iolen > buflen)
2532                return (BCME_BUFTOOSHORT);
2533
2534        memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
2535        memcpy((int8 *) bufptr + namelen, param, paramlen);
2536
2537        err = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
2538
2539        return (err);
2540}
2541
2542// #else
2543int wl_iovar_setbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen)
2544{
2545        uint namelen;
2546        uint iolen;
2547
2548        namelen = strlen(iovar) + 1;    /* length of iovar name plus null */
2549        iolen = namelen + paramlen;
2550
2551        /* check for overflow */
2552        if (iolen > buflen)
2553                return (BCME_BUFTOOSHORT);
2554
2555        memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
2556        memcpy((int8 *) bufptr + namelen, param, paramlen);
2557
2558        return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
2559}
2560
2561int wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen)
2562{
2563        char smbuf[WLC_IOCTL_SMLEN];
2564
2565        return wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf, sizeof(smbuf));
2566}
2567
2568int wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen)
2569{
2570        char smbuf[WLC_IOCTL_SMLEN];
2571        int ret;
2572
2573        /* use the return buffer if it is bigger than what we have on the stack */
2574        if (buflen > sizeof(smbuf)) {
2575                ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen);
2576        } else {
2577                ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf, sizeof(smbuf));
2578                if (ret == 0)
2579                        memcpy(bufptr, smbuf, buflen);
2580        }
2581
2582        return ret;
2583}
2584
2585/*
2586 * set named driver variable to int value
2587 * calling example: wl_iovar_setint(ifname, "arate", rate)
2588 */
2589int wl_iovar_setint(char *ifname, char *iovar, int val)
2590{
2591        return wl_iovar_set(ifname, iovar, &val, sizeof(val));
2592}
2593
2594/*
2595 * get named driver variable to int value and return error indication
2596 * calling example: wl_iovar_getint(ifname, "arate", &rate)
2597 */
2598int wl_iovar_getint(char *ifname, char *iovar, int *val)
2599{
2600        return wl_iovar_get(ifname, iovar, val, sizeof(int));
2601}
2602
2603/*
2604 * format a bsscfg indexed iovar buffer
2605 */
2606static int wl_bssiovar_mkbuf(char *iovar, int bssidx, void *param, int paramlen, void *bufptr, int buflen, unsigned int *plen)
2607{
2608        char *prefix = "bsscfg:";
2609        int8 *p;
2610        uint prefixlen;
2611        uint namelen;
2612        uint iolen;
2613
2614        prefixlen = strlen(prefix);     /* length of bsscfg prefix */
2615        namelen = strlen(iovar) + 1;    /* length of iovar name + null */
2616        iolen = prefixlen + namelen + sizeof(int) + paramlen;
2617
2618        /*
2619         * check for overflow
2620         */
2621        if (buflen < 0 || iolen > (uint) buflen) {
2622                *plen = 0;
2623                return BCME_BUFTOOSHORT;
2624        }
2625
2626        p = (int8 *) bufptr;
2627
2628        /*
2629         * copy prefix, no null
2630         */
2631        memcpy(p, prefix, prefixlen);
2632        p += prefixlen;
2633
2634        /*
2635         * copy iovar name including null
2636         */
2637        memcpy(p, iovar, namelen);
2638        p += namelen;
2639
2640        /*
2641         * bss config index as first param
2642         */
2643        memcpy(p, &bssidx, sizeof(int32));
2644        p += sizeof(int32);
2645
2646        /*
2647         * parameter buffer follows
2648         */
2649        if (paramlen)
2650                memcpy(p, param, paramlen);
2651
2652        *plen = iolen;
2653        return 0;
2654}
2655
2656/*
2657 * set named & bss indexed driver variable to buffer value
2658 */
2659int wl_bssiovar_setbuf(char *ifname, char *iovar, int bssidx, void *param, int paramlen, void *bufptr, int buflen)
2660{
2661        int err;
2662        uint iolen;
2663
2664        err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
2665        if (err)
2666                return err;
2667
2668        return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
2669}
2670
2671/*
2672 * get named & bss indexed driver variable buffer value
2673 */
2674int wl_bssiovar_getbuf(char *ifname, char *iovar, int bssidx, void *param, int paramlen, void *bufptr, int buflen)
2675{
2676        int err;
2677        uint iolen;
2678
2679        err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
2680        if (err)
2681                return err;
2682
2683        return wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
2684}
2685
2686/*
2687 * set named & bss indexed driver variable to buffer value
2688 */
2689int wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen)
2690{
2691        char smbuf[WLC_IOCTL_SMLEN];
2692
2693        return wl_bssiovar_setbuf(ifname, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf));
2694}
2695
2696/*
2697 * get named & bss indexed driver variable buffer value
2698 */
2699int wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len)
2700{
2701        char smbuf[WLC_IOCTL_SMLEN];
2702        int err;
2703
2704        /*
2705         * use the return buffer if it is bigger than what we have on the stack
2706         */
2707        if (len > (int)sizeof(smbuf)) {
2708                err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, outbuf, len);
2709        } else {
2710                memset(smbuf, 0, sizeof(smbuf));
2711                err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf));
2712                if (err == 0)
2713                        memcpy(outbuf, smbuf, len);
2714        }
2715
2716        return err;
2717}
2718
2719/*
2720 * set named & bss indexed driver variable to int value
2721 */
2722int wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val)
2723{
2724        return wl_bssiovar_set(ifname, iovar, bssidx, &val, sizeof(int));
2725}
2726
2727/*
2728 * void wl_printlasterror(char *name) { char err_buf[WLC_IOCTL_SMLEN];
2729 * strcpy(err_buf, "bcmerrstr");
2730 *
2731 * fprintf(stderr, "Error: "); if ( wl_ioctl(name, WLC_GET_VAR, err_buf,
2732 * sizeof (err_buf)) != 0) fprintf(stderr, "Error getting the Errorstring
2733 * from driver\n"); else fprintf(stderr, err_buf); }
2734 */
2735
2736int get_maxbssid(char *name)
2737{
2738        char cap[WLC_IOCTL_SMLEN];
2739        char caps[WLC_IOCTL_MEDLEN];
2740        char *next;
2741        if (wl_iovar_get(name, "cap", (void *)caps, sizeof(caps)))
2742                return 4;       //minimum is default
2743        foreach(cap, caps, next) {
2744                if (!strcmp(cap, "mbss16")) {
2745                        return 16;
2746                }
2747                if (!strcmp(cap, "mbss8")) {
2748                        return 8;
2749                }
2750                if (!strcmp(cap, "mbss4")) {
2751                        return 4;
2752                }
2753        }
2754        return 4;
2755}
2756
2757#endif
Note: See TracBrowser for help on using the repository browser.