source: src/router/services/tools/site_survey_madwifi.c @ 32590

Last change on this file since 32590 was 32590, checked in by brainslayer, 3 weeks ago

format code

File size: 8.0 KB
Line 
1/*
2 * site_survey_madwifi.c
3 *
4 * Copyright (C) 2006 Sebastian Gottschall <gottschall@dd-wrt.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 *
20 * $Id:
21 */
22
23#include <sys/types.h>
24#include <sys/file.h>
25#include <sys/ioctl.h>
26#include <sys/socket.h>
27
28#include <unistd.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <stdint.h>
33#include <ctype.h>
34#include <getopt.h>
35#include <err.h>
36#include <shutils.h>
37#include <wlutils.h>
38#include <utils.h>
39
40#include <typedefs.h>
41#include <bcmnvram.h>
42
43#ifndef __UCLIBC__
44/* Convenience types.  */
45typedef unsigned char __u_char;
46typedef unsigned short int __u_short;
47typedef unsigned int __u_int;
48typedef unsigned long int __u_long;
49
50/* Fixed-size types, underlying types depend on word size and compiler.  */
51typedef signed char __int8_t;
52typedef unsigned char __uint8_t;
53typedef signed short int __int16_t;
54typedef unsigned short int __uint16_t;
55typedef signed int __int32_t;
56typedef unsigned int __uint32_t;
57#endif
58
59#include "wireless_copy.h"
60#include "net80211/ieee80211.h"
61#include "net80211/ieee80211_crypto.h"
62#include "net80211/ieee80211_ioctl.h"
63
64static int copy_essid(char buf[], size_t bufsize, const u_int8_t *essid, size_t essid_len)
65{
66        const u_int8_t *p;
67        int maxlen;
68        int i;
69
70        if (essid_len > bufsize)
71                maxlen = bufsize;
72        else
73                maxlen = essid_len;
74        /*
75         * determine printable or not
76         */
77        for (i = 0, p = essid; i < maxlen; i++, p++) {
78                if (*p < ' ' || *p > 0x7e)
79                        break;
80        }
81        if (i != maxlen) {      /* not printable, print as hex */
82                if (bufsize < 3)
83                        return 0;
84#if 0
85                strlcpy(buf, "0x", bufsize);
86#else
87                strncpy(buf, "0x", bufsize);
88#endif
89                bufsize -= 2;
90                p = essid;
91                for (i = 0; i < maxlen && bufsize >= 2; i++) {
92                        sprintf(&buf[2 + 2 * i], "%02x", *p++);
93                        bufsize -= 2;
94                }
95                maxlen = 2 + 2 * i;
96        } else {                /* printable, truncate as needed */
97                memcpy(buf, essid, maxlen);
98        }
99        if (maxlen != essid_len)
100                memcpy(buf + maxlen - 3, "...", 3);
101        return maxlen;
102}
103
104#define sys_restart() kill(1, SIGHUP)
105
106static int write_site_survey(void);
107static int open_site_survey(void);
108
109static struct site_survey_list *site_survey_lists;
110
111#define LE_READ_4(p)                                    \
112        ((u_int32_t)                                    \
113         ((((const u_int8_t *)(p))[0]      ) |          \
114          (((const u_int8_t *)(p))[1] <<  8) |          \
115          (((const u_int8_t *)(p))[2] << 16) |          \
116          (((const u_int8_t *)(p))[3] << 24)))
117
118static __inline int iswpaoui(const unsigned char *frm)
119{
120        return frm[1] > 3 && LE_READ_4(frm + 2) == ((WPA_OUI_TYPE << 24) | WPA_OUI);
121}
122
123static __inline int isrsnoui(const unsigned char *frm)
124{
125        return frm[1] > 3 && LE_READ_4(frm + 2) == ((WPA_OUI_TYPE << 24) | RSN_OUI);
126}
127
128static __inline int iswmeoui(const unsigned char *frm)
129{
130        return frm[1] > 3 && LE_READ_4(frm + 2) == ((WME_OUI_TYPE << 24) | WME_OUI);
131}
132
133static __inline int isatherosoui(const unsigned char *frm)
134{
135        return frm[1] > 3 && LE_READ_4(frm + 2) == ((ATH_OUI_TYPE << 24) | ATH_OUI);
136}
137
138static int __inline ismtikoui(const unsigned char *frm)
139{
140        return frm[1] > 3 && LE_READ_4(frm + 2) == MTIK_OUI;
141}
142
143static int fillenc(char *encinfo, unsigned char *vp, int ielen)
144{
145        int r = 0;
146        bzero(encinfo, 128);
147        while (ielen > 0) {
148                switch (vp[0]) {
149                case IEEE80211_ELEMID_VENDOR:
150                        if (iswpaoui(vp))
151                                strcat(encinfo, "WPA ");
152                        if (isrsnoui(vp))
153                                strcat(encinfo, "WPA2 ");
154                        else if (iswmeoui(vp))
155                                strcat(encinfo, "WME ");
156                        else if (isatherosoui(vp))
157                                strcat(encinfo, "ATH ");
158                        else if (ismtikoui(vp))
159                                strcat(encinfo, "MTIK ");
160                        break;
161                case IEEE80211_ELEMID_RSN:
162                        strcat(encinfo, "WPA2 ");
163                        break;
164                default:
165                        break;
166                }
167                ielen -= 2 + vp[1];
168                vp += 2 + vp[1];
169        }
170        if (strlen(encinfo) > 0)
171                encinfo[strlen(encinfo) - 1] = 0;
172        return r;
173}
174
175static const char *ieee80211_ntoa(const uint8_t mac[IEEE80211_ADDR_LEN])
176{
177        static char a[18];
178        int i;
179
180        i = snprintf(a, sizeof(a), "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
181        return (i < 17 ? NULL : a);
182}
183
184int site_survey_main_11n(int argc, char *argv[]);
185
186int site_survey_main(int argc, char *argv[])
187{
188        char *name = nvram_safe_get("wl0_ifname");
189        unsigned char mac[20];
190        int i = 0;
191        char *dev = name;
192
193        unlink(SITE_SURVEY_DB);
194        int ap = 0, oldap = 0;
195
196        char ssid[31];
197        unsigned char *cp;
198        int len;
199        char *sta = nvram_safe_get("wifi_display");
200#ifdef HAVE_ATH9K
201#ifndef HAVE_NOWIFI
202        if (is_ath9k(sta)) {
203                extern int site_survey_main_mac802211(int argc, char *argv[]);
204                return site_survey_main_mac802211(argc, argv);
205        }
206#endif
207#endif
208#ifdef HAVE_MADWIFI_MIMO
209#ifndef HAVE_NOWIFI
210        if (is_ar5008(sta)) {
211                return site_survey_main_11n(argc, argv);
212        }
213#endif
214#endif
215        unsigned char *buf = malloc(24 * 1024);
216        if (!buf)
217                return -1;
218        site_survey_lists = calloc(sizeof(struct site_survey_list) * SITE_SURVEY_NUM, 1);
219        bzero(buf, 24 * 1024);
220        eval("iwlist", sta, "scan");
221        len = do80211priv(sta, IEEE80211_IOCTL_SCAN_RESULTS, buf, 24 * 1024);
222        if (len == -1) {
223                fprintf(stderr, "unable to get scan results");
224                free(buf);
225                free(site_survey_lists);
226                return -1;
227        }
228        if (len < sizeof(struct ieee80211req_scan_result)) {
229                free(buf);
230                free(site_survey_lists);
231                return -1;
232        }
233        cp = buf;
234        do {
235                struct ieee80211req_scan_result *sr;
236                unsigned char *vp;
237                char ssid[14];
238
239                sr = (struct ieee80211req_scan_result *)cp;
240                vp = (u_int8_t *)(sr + 1);
241                bzero(ssid, sizeof(ssid));
242                strncpy(site_survey_lists[i].SSID, vp, sr->isr_ssid_len);
243                strcpy(site_survey_lists[i].BSSID, ieee80211_ntoa(sr->isr_bssid));
244                site_survey_lists[i].channel = ieee80211_mhz2ieee(sr->isr_freq);
245                site_survey_lists[i].frequency = sr->isr_freq;
246                int noise = 256;
247
248                noise -= (int)sr->isr_noise;
249                site_survey_lists[i].phy_noise = -noise;
250                if (sr->isr_noise == 0) {
251                        site_survey_lists[i].phy_noise = -95;
252                }
253                site_survey_lists[i].RSSI = (int)site_survey_lists[i].phy_noise + (int)sr->isr_rssi;
254                site_survey_lists[i].capability = sr->isr_capinfo;
255                // site_survey_lists[i].athcaps = sr->isr_athflags;
256                site_survey_lists[i].rate_count = sr->isr_nrates;
257                int n11 = fillenc(site_survey_lists[i].ENCINFO,
258                                  (unsigned char *)(vp + sr->isr_ssid_len),
259                                  sr->isr_ie_len);
260                if (n11)
261                        site_survey_lists[i].rate_count = n11;
262                cp += sr->isr_len, len -= sr->isr_len;
263                i++;
264        }
265        while (len >= sizeof(struct ieee80211req_scan_result));
266        free(buf);
267        write_site_survey();
268        open_site_survey();
269        for (i = 0; i < SITE_SURVEY_NUM && site_survey_lists[i].BSSID[0]
270             && site_survey_lists[i].channel != 0; i++) {
271                if (site_survey_lists[i].SSID[0] == 0) {
272                        strcpy(site_survey_lists[i].SSID, "hidden");
273                }
274
275                fprintf(stderr,
276                        "[%2d] SSID[%20s] BSSID[%s] channel[%2d] frequency[%4d] rssi[%d] noise[%d] beacon[%d] cap[%x] dtim[%d] rate[%d] enc[%s]\n",
277                        i, site_survey_lists[i].SSID,
278                        site_survey_lists[i].BSSID,
279                        site_survey_lists[i].channel,
280                        site_survey_lists[i].frequency,
281                        site_survey_lists[i].RSSI,
282                        site_survey_lists[i].phy_noise,
283                        site_survey_lists[i].beacon_period, site_survey_lists[i].capability, site_survey_lists[i].dtim_period, site_survey_lists[i].rate_count, site_survey_lists[i].ENCINFO);
284        }
285
286        free(site_survey_lists);
287        return 0;
288}
289
290static int write_site_survey(void)
291{
292        FILE *fp;
293
294        if ((fp = fopen(SITE_SURVEY_DB, "w"))) {
295                fwrite(&site_survey_lists[0], sizeof(struct site_survey_list) * SITE_SURVEY_NUM, 1, fp);
296                fclose(fp);
297                return 0;
298        }
299        return 1;
300}
301
302static int open_site_survey(void)
303{
304        FILE *fp;
305
306        bzero(site_survey_lists, sizeof(site_survey_lists));
307
308        if ((fp = fopen(SITE_SURVEY_DB, "r"))) {
309                fread(&site_survey_lists[0], sizeof(struct site_survey_list) * SITE_SURVEY_NUM, 1, fp);
310                fclose(fp);
311                return 1;
312        }
313        return 0;
314}
Note: See TracBrowser for help on using the repository browser.