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

Last change on this file since 13532 was 13532, checked in by BrainSlayer, 3 years ago

detect capable modes from hardware

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