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

Last change on this file since 18045 was 18045, checked in by chris, 17 months ago

mac80211 changes

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