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

Last change on this file since 10769 was 10769, checked in by BrainSlayer, 5 years ago

it was just included in a comment, but thanks DC for taking care of this

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