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

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

radauth support for rt2880

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