source: src/router/shared/wl.c @ 9830

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

formating

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