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

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

adjustments for buffalo

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