let ipkg fail when a package file to be installed is not found
[openwrt.git] / openwrt / package / wiviz / src / wiviz.c
1 /*
2 This file is part of Wi-viz (http://wiviz.natetrue.com).
3
4 Wi-viz is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License v2 as published by
6 the Free Software Foundation.
7
8 Wi-viz is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with Wi-viz; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16 */
17 #include <stdio.h>
18 #include <pcap.h>
19 #include <signal.h>
20
21 #define HOST_TIMEOUT 300
22
23 #include "wl_access.h"
24 #include "structs.h"
25 #include "channelhopper.h"
26
27 #ifdef WIN32
28 #define OFFLINE
29 #endif
30 #ifndef __cplusplus
31 #define __cdecl
32 #endif
33
34 #define nonzeromac(x) memcmp(x, "\0\0\0\0\0\0", 6)
35
36 void dealWithPacket(wiviz_cfg * cfg, struct pcap_pkthdr * header, const u_char * packet);
37 wiviz_host * gotHost(wiviz_cfg * cfg, u_char * mac, host_type type);
38 void fprint_mac(FILE * outf, u_char * mac, char * extra);
39 void print_mac(u_char * mac, char * extra);
40 void print_host(FILE * outf, wiviz_host * host);
41 void __cdecl signal_handler(int);
42 void readWL(wiviz_cfg * cfg);
43 void reloadConfig();
44
45 wiviz_cfg * global_cfg;
46
47 ////////////////////////////////////////////////////////////////////////////////
48 int main(int argc, char * * argv) {
49   pcap_t *handle;                        
50   char *dev;                                
51   char errbuf[PCAP_ERRBUF_SIZE]; 
52   int stop = 0;
53   int oldMonitor, newMonitor;
54   struct pcap_pkthdr header;          
55   const u_char *packet;                 
56   wiviz_cfg cfg;
57   int i;
58   int defaultHopSeq[] = { 1, 3, 6, 8, 11 };
59   
60   global_cfg = &cfg;
61   signal(SIGUSR1, &signal_handler);
62   signal(SIGUSR2, &signal_handler);
63
64   fprintf(stderr, "Wi-Viz infogathering daemon by Nathan True\n");
65   
66   memset(&cfg, 0, sizeof(wiviz_cfg));
67   cfg.numHosts = 0;
68   cfg.lastKeepAlive = time(NULL);
69   cfg.channelHopping = 0;
70   cfg.channelDwellTime = 1000;
71   cfg.channelHopSeqLen = 5;
72   memcpy(cfg.channelHopSeq, defaultHopSeq, sizeof(defaultHopSeq));
73
74   wl_ioctl(WL_DEVICE, WLC_GET_MAGIC, &i, 4);
75         if (i != WLC_IOCTL_MAGIC) {
76                 fprintf(stderr, "Wireless magic not correct, not querying wl for info\n");
77                 cfg.readFromWl = 0;
78         }
79         else {
80           cfg.readFromWl = 1;
81           wl_ioctl(WL_DEVICE, WLC_GET_MONITOR, &oldMonitor, 4);
82           newMonitor = 1;
83           wl_ioctl(WL_DEVICE, WLC_SET_MONITOR, &newMonitor, 4);
84         }
85
86   reloadConfig();
87
88 #ifndef OFFLINE
89   dev = "prism0";
90   handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
91 #else
92   dev = "c:\\cifsroot\\wdump2.pcap";
93   handle = pcap_open_offline(dev, errbuf);
94 #endif
95
96         if (cfg.readFromWl) {
97           readWL(&cfg);
98         }
99
100   if (!handle) {
101     fprintf(stderr, "Failure to open pcap!\nErr=%s\n", errbuf);
102     return -1;
103     }
104   while (!stop) {
105     packet = pcap_next(handle, &header);
106     if (!packet) break;
107     dealWithPacket(&cfg, &header, packet);
108     if (time(NULL) - cfg.lastKeepAlive > 30) stop = 1;
109     }
110
111   signal_handler(SIGUSR1);
112
113   if (cfg.channelHopperPID) kill(cfg.channelHopperPID, SIGKILL);
114
115   for (i = 0; i < MAX_HOSTS; i++) {
116     print_host(stderr, cfg.hosts + i);
117     if (cfg.hosts[i].occupied) printf("\n");
118     if (cfg.hosts[i].apInfo) free(cfg.hosts[i].apInfo);
119     if (cfg.hosts[i].staInfo) free(cfg.hosts[i].staInfo);
120     }
121
122   wl_ioctl(WL_DEVICE, WLC_SET_MONITOR, &oldMonitor, 4);
123
124   pcap_close(handle);
125   return 0;
126   }
127
128 ////////////////////////////////////////////////////////////////////////////////
129 void writeJavascript() { 
130   int i;
131   FILE * outf;
132   wiviz_host * h;
133
134   outf = fopen("/tmp/wiviz-pipe", "w");
135   if (!outf) {
136     fprintf(stderr, "Failure to open output file\n");
137     return;
138     }
139
140   global_cfg->lastKeepAlive = time(NULL);
141   
142   if(global_cfg->readFromWl) readWL(global_cfg);
143   
144   fprintf(outf, "top.hosts = new Array(\n");
145   for (i = 0; i < MAX_HOSTS; i++) {
146     h = global_cfg->hosts + i;
147     if (h->occupied == 0) continue;
148     if (time(NULL) - h->lastSeen > HOST_TIMEOUT) {
149       h->occupied = 0;
150       }
151     fprintf(outf, "  new Array(");
152     print_host(outf, h);
153     fprintf(outf, "),\n");
154     }
155   fprintf(outf, "new Array());\n");
156   fprintf(outf, "var cfg_string = 'channel-");
157   if (global_cfg->channelHopping) {
158     fprintf(outf, "hopping");
159     }
160   else {
161     fprintf(outf, "%i", global_cfg->curChannel);
162     }
163   fprintf(outf, "';\ntop.wiviz_callback(top.hosts, cfg_string);\n");
164   fclose(outf);
165   }
166
167 ////////////////////////////////////////////////////////////////////////////////
168 void reloadConfig() {
169   FILE * cnf;
170   wiviz_cfg * cfg = global_cfg;
171   char filebuffer[512];
172   char * fbptr, * p, * v, * vv;
173   int fblen, val;
174   int hopCfgChanged = 0;
175   int newHopSeq[12];
176   int newHopSeqLen = 0;
177
178   fprintf(stderr, "Loading config file\n");
179
180   cnf = fopen("/tmp/wiviz-cfg", "r");
181   if (!cnf) {
182     fprintf(stderr, "Wiviz: No config file (/tmp/wiviz-cfg) present, using defaults\n");
183     return;
184     }
185
186   fblen = fread(filebuffer, 1, 512, cnf);
187   fclose(cnf);
188   if (fblen >= 512) {
189     fprintf(stderr, "Error reading config file\n");
190     return;
191     }
192   filebuffer[fblen] = 0;
193   fprintf(stderr, "Read %i bytes from config file\n", fblen);
194
195   fbptr = filebuffer;
196
197   while (fbptr < filebuffer + fblen && *fbptr != 0) {
198     p = fbptr;
199     //Find end of parameter
200     for (; *fbptr != '=' && *fbptr != 0; fbptr++);
201     *fbptr = 0;
202     v = ++fbptr;
203     //Find end of value
204     for (; *fbptr != '&' && *fbptr != 0; fbptr++);
205     *(fbptr++) = 0;
206     fprintf(stderr, "Config: %s=%s\n", p, v);
207     //Apply configuration
208     if (!strcmp(p, "channelsel")) {
209       //Channel selector
210       cfg->channelHopping = 0;
211       if (!strcmp(v, "hop")) {
212         //Set channel hopping
213         cfg->channelHopping = 1;
214         hopCfgChanged = 1;
215         }
216       else if (!strcmp(v, "nochange")) {
217         //Don't change anything, read channel from wireless card
218         readWL(cfg);
219         }
220       else {
221         val = atoi(v);
222         if (val < 1 || val > 14) {
223           fprintf(stderr, "Channel setting in config file invalid (%i)\n", cfg->curChannel);
224         }
225         else {
226           cfg->curChannel = val;
227           if (cfg->readFromWl) {
228             if (wl_ioctl(WL_DEVICE, WLC_SET_CHANNEL, &cfg->curChannel, 4) < 0) {
229               fprintf(stderr, "Channel set to %i failed\n", cfg->curChannel);
230               }
231             }
232           else {
233             fprintf(stderr, "Can't set channel, no Broadcom wireless device present\n");
234             }
235           }
236         }
237       }
238     if (!strcmp(p, "hopdwell")) {
239       val = atoi(v);
240       if (val < 100) val = 100;
241       if (val > 30000) val = 30000;
242       if (cfg->channelDwellTime != val) hopCfgChanged = 1;
243       cfg->channelDwellTime = val;
244       }
245     if (!strcmp(p, "hopseq")) {
246       cfg->channelHopSeqLen = 0;
247       while (v < fbptr) {
248         for (vv = v; *vv != ',' && *vv != 0; vv++);
249         if (*vv == 0) {
250           cfg->channelHopSeq[cfg->channelHopSeqLen++] = atoi(v);
251           break;          
252           }
253         *vv = 0;
254         cfg->channelHopSeq[cfg->channelHopSeqLen++] = atoi(v);
255         v = vv + 1;
256         }
257       }
258     /*
259     if (!strcmp(p, "")) {
260       }
261     */
262     }
263   //Apply channel hopper settings
264   if (cfg->channelHopping == 0 && cfg->channelHopperPID) {
265     kill(cfg->channelHopperPID, SIGKILL);
266     cfg->channelHopperPID = 0;
267     }
268   if (cfg->channelHopping == 1 && hopCfgChanged) {
269     if (cfg->channelHopperPID) kill(cfg->channelHopperPID, SIGKILL);
270     if ((cfg->channelHopperPID = fork()) == 0) {
271       channelHopper(cfg);
272       }
273     }
274   }
275
276 ////////////////////////////////////////////////////////////////////////////////
277 void __cdecl signal_handler(int signum) {
278   if (signum == SIGUSR1) writeJavascript();
279   if (signum == SIGUSR2) reloadConfig();
280   }
281
282 ////////////////////////////////////////////////////////////////////////////////
283 void dealWithPacket(wiviz_cfg * cfg, struct pcap_pkthdr * header, const u_char * packet) {
284   ieee802_11_hdr * hWifi;
285   prism_hdr * hPrism;
286   wiviz_host * host;
287   wiviz_host * emergebss;
288   host_type type = typeUnknown;
289   int wfType;
290   int rssi = 0;
291   int to_ds, from_ds;
292   prism_did * i;
293   ieee_802_11_tag * e;
294   ieee_802_11_mgt_frame * m;
295   char * src = "\0\0\0\0\0\0";
296   char * dst = "\0\0\0\0\0\0";
297   char * bss = "\0\0\0\0\0\0";
298   char * ssid = "";
299   int channel = 0;
300   int adhocbeacon = 0;
301   u_char ssidlen = 0;
302   ap_enc_type encType = aetUnknown;
303
304   if (!packet) return;
305   if (header->len < sizeof(prism_hdr) + sizeof(ieee802_11_hdr)) return;
306   hPrism = (prism_hdr *) packet;
307   hWifi = (ieee802_11_hdr *) (packet + (hPrism->msg_length));
308
309   //Parse the prism DIDs
310   i = (prism_did *)((char *)hPrism + sizeof(prism_hdr));
311   while ((int)i < (int)hWifi) {
312     if (i->did == pdn_rssi) rssi = *(int *)(i+1);
313     i = (prism_did *) ((int)(i+1) + i->length);
314     }
315
316   //Establish the frame type
317   wfType = ((hWifi->frame_control & 0xF0) >> 4) + ((hWifi->frame_control & 0xC) << 2);
318   switch (wfType) {
319     case mgt_assocRequest:
320     case mgt_reassocRequest:
321     case mgt_probeRequest:
322       type = typeSta;
323       src=hWifi->addr2;
324       dst=hWifi->addr1;
325       break;
326     case mgt_assocResponse:
327     case mgt_reassocResponse:
328     case mgt_probeResponse:
329     case mgt_beacon:
330       src=hWifi->addr2;
331       dst=hWifi->addr1;
332       bss=hWifi->addr3;
333       type = typeAP;
334       break;
335     }
336   to_ds = hWifi->flags & IEEE80211_TO_DS;
337   from_ds = hWifi->flags & IEEE80211_FROM_DS;
338   if ((wfType & 0xF0) == 0x20 && (wfType & 0xF) < 4) {
339     //Data frame
340     src=hWifi->addr2;
341     dst=hWifi->addr1;
342     if (!from_ds) type = typeSta;
343       else type = typeAP;
344     if (!to_ds && !from_ds) bss = hWifi->addr3;
345     if (to_ds && !from_ds) bss = hWifi->addr1;
346     if (!to_ds && from_ds) bss = hWifi->addr2;
347     }
348   if (type == typeUnknown) return;
349
350   //Parse the 802.11 tags
351   if (wfType == mgt_probeResponse || wfType == mgt_beacon) {
352     m = (ieee_802_11_mgt_frame *) (hWifi + 1);
353     if (m->caps & MGT_CAPS_IBSS) {
354       type = typeSta;
355       adhocbeacon = 1;
356       }
357     if (m->caps & MGT_CAPS_WEP) encType = aetEncWEP;
358     else encType = aetUnencrypted;
359     e = (ieee_802_11_tag *) ((int) m + sizeof(ieee_802_11_mgt_frame));
360     while ((u_int)e < (u_int)packet + header->len) {
361       if (e->tag == tagSSID) {
362         ssidlen = e->length;
363         ssid = (char *)(e + 1);
364         }
365       if (e->tag == tagChannel) {
366         channel = *(char *)(e + 1);
367         }
368       if (e->tag == tagVendorSpecific) {
369         if (e->length >= 4 && memcmp(e + 1, "\x00\x50\xf2\x01", 4) == 0) {
370           //WPA encryption
371           encType = aetEncWPA;
372           }
373         }
374       e = (ieee_802_11_tag *) ((int)(e + 1) + e->length);
375       }
376     }
377   
378   //Look up the host in the hash table
379   host = gotHost(cfg, src, type);
380
381   //Add any info we received
382   if (host->RSSI) {
383     host->RSSI = host->RSSI * 9 / 10 + (-rssi * 10);
384     }
385   else {
386     host->RSSI = -rssi * 100;
387     }
388   if (type == typeSta) {
389     if (nonzeromac(bss)) {
390       memcpy(host->staInfo->connectedBSSID, bss, 6);
391       host->staInfo->state = ssAssociated;
392       emergebss = gotHost(cfg, bss, typeAP);
393       if (emergebss->RSSI == 0) emergebss->RSSI = 10000;
394       memcpy(emergebss->apInfo->bssid, bss, 6);
395       if (adhocbeacon) {
396         emergebss->type = typeAdhocHub;
397         if (ssidlen > 0 && ssidlen <= 32) {
398           memcpy(emergebss->apInfo->ssid, ssid, ssidlen);
399           emergebss->apInfo->ssidlen = ssidlen;
400           }
401         if (channel) emergebss->apInfo->channel = channel;
402         emergebss->apInfo->flags = hWifi->flags;
403         emergebss->RSSI = host->RSSI;
404         if (encType != aetUnknown) emergebss->apInfo->encryption = encType;
405         }
406       }
407     if (wfType == mgt_probeRequest && host->staInfo->state == ssUnknown) host->staInfo->state = ssUnassociated;
408     }
409   if (type == typeAP) {
410     if (nonzeromac(bss)) {
411       memcpy(host->apInfo->bssid, bss, 6);
412       }
413     if (ssidlen > 0 && ssidlen <= 32) {
414       memcpy(host->apInfo->ssid, ssid, ssidlen);
415       host->apInfo->ssidlen = ssidlen;
416       }
417     if (channel) host->apInfo->channel = channel;
418     host->apInfo->flags = hWifi->flags;
419     if (encType != aetUnknown) host->apInfo->encryption = encType;
420     }
421   }
422
423 ////////////////////////////////////////////////////////////////////////////////
424 void print_mac(u_char * mac, char * extra) {
425   fprint_mac(stdout, mac, extra);
426   }
427
428 ////////////////////////////////////////////////////////////////////////////////
429 void fprint_mac(FILE * outf, u_char * mac, char * extra) {
430   fprintf(outf, "%02X:%02X:%02X:%02X:%02X:%02X%s",
431       mac[0] & 0xFF,
432       mac[1] & 0xFF,
433       mac[2] & 0xFF,
434       mac[3] & 0xFF,
435       mac[4] & 0xFF,
436       mac[5] & 0xFF,
437       extra);
438   }
439
440 ////////////////////////////////////////////////////////////////////////////////
441 #define MAX_PROBES MAX_HOSTS/2
442 wiviz_host * gotHost(wiviz_cfg * cfg, u_char * mac, host_type type) {
443   int i = (mac[5] + (mac[4] << 8)) % MAX_HOSTS;
444   int c = 0;
445   wiviz_host * h = cfg->hosts + i;
446   while (h->occupied && memcmp(h->mac, mac, 6)) {
447     i++; h++; c++;
448     if (i >= MAX_HOSTS) {
449       i = 0;
450       h = cfg->hosts;
451       }
452     if (c > MAX_PROBES) break;
453     } 
454   if (!h->occupied) {
455     fprintf(stderr, "New host, ");
456     fprint_mac(stderr, mac, ", type=");
457     fprintf(stderr, "%s\n", (type==typeAP) ? "AP" : ((type==typeSta) ? "Sta" : "Unk"));
458     }
459   h->occupied = 1;
460   h->lastSeen = time(NULL);
461   h->type = type;
462   memcpy(h->mac, mac, 6);
463   if (h->type == typeAP && !h->apInfo) {
464     h->apInfo = (ap_info *) malloc(sizeof(ap_info));
465     memset(h->apInfo, 0, sizeof(ap_info));
466     }
467   if (h->type == typeSta && !h->staInfo) {
468     h->staInfo = (sta_info *) malloc(sizeof(sta_info));
469     memset(h->staInfo, 0, sizeof(sta_info));
470     }
471   return h;
472   }
473
474 ////////////////////////////////////////////////////////////////////////////////
475 void print_host(FILE * outf, wiviz_host * host) {
476   int i;
477
478   if (!host->occupied) return;
479   fprintf(outf, "'");
480   fprint_mac(outf, host->mac, "'");
481   fprintf(outf, ", -%i, '", host->RSSI / 100);
482   switch (host->type) {
483     case typeAP:  fprintf(outf, "ap"); break;
484     case typeSta: fprintf(outf, "sta"); break;
485     case typeAdhocHub: fprintf(outf, "adhoc"); break;
486     }
487   if (host->type == typeSta) {
488     switch(host->staInfo->state) {
489       case ssAssociated:
490         fprintf(outf, "-assoc-");
491         fprint_mac(outf, host->staInfo->connectedBSSID, "");
492         break;
493       case ssUnassociated:
494         fprintf(outf, "-unassoc");
495       }
496     }
497   if (host->type == typeAP || host->type == typeAdhocHub) {
498     fprintf(outf, "-channel-%i-ssid-", host->apInfo->channel & 0xFF);
499     for (i = 0; i < host->apInfo->ssidlen; i++) {
500       fprintf(outf, "\\x%02X", *((char *)host->apInfo->ssid + i) & 0xFF);
501         }
502     switch (host->apInfo->encryption) {
503       case aetUnknown: fprintf(outf, "-?enc-?alg"); break;
504       case aetUnencrypted: fprintf(outf, "-unenc-na"); break;
505       case aetEncUnknown: fprintf(outf, "-enc-unknown"); break;
506       case aetEncWEP: fprintf(outf, "-enc-wep"); break;
507       case aetEncWPA: fprintf(outf, "-enc-wpa"); break;
508       }
509     }
510   fprintf(outf, "', %i", time(0) - host->lastSeen);
511   }
512
513 ////////////////////////////////////////////////////////////////////////////////
514 #define MAX_STA_COUNT 64
515 void readWL(wiviz_cfg * cfg) {
516         int ap, i;
517         wiviz_host * host, * sta;
518         uchar mac[6];
519         wlc_ssid_t ssid; 
520         channel_info_t channel;
521         maclist_t * macs;
522   sta_rssi_t starssi;
523         
524         get_mac(WL_DEVICE, mac);
525         printf("AP mac: ");
526         print_mac(mac, "\n");
527         if (!nonzeromac(mac)) return;
528         wl_ioctl(WL_DEVICE, WLC_GET_AP, &ap, 4);
529         if (ap) {
530                 host = gotHost(cfg, mac, typeAP);
531                 wl_ioctl(WL_DEVICE, WLC_GET_BSSID, host->apInfo->bssid, 6);
532                 wl_ioctl(WL_DEVICE, WLC_GET_SSID, &ssid, sizeof(wlc_ssid_t));
533                 memcpy(host->apInfo->ssid, ssid.SSID, 32);
534                 host->apInfo->ssidlen = ssid.SSID_len;
535                 host->RSSI = 0;
536                 wl_ioctl(WL_DEVICE, WLC_GET_CHANNEL, &channel, sizeof(channel_info_t));
537                 host->apInfo->channel = channel.hw_channel;
538                 macs = (maclist_t *) malloc(4 + MAX_STA_COUNT * sizeof(ether_addr_t));
539                 macs->count = MAX_STA_COUNT;
540                 if (wl_ioctl(WL_DEVICE, WLC_GET_ASSOCLIST, macs, 4 + MAX_STA_COUNT * sizeof(ether_addr_t)) > -1) {
541                         for (i = 0; i < macs->count; i++) {
542                           sta = gotHost(cfg, (char *)&macs->ea[i], typeSta);
543         memcpy(starssi.mac, &macs->ea[i], 6);
544         starssi.RSSI = 3000;
545         starssi.zero_ex_forty_one = 0x41;
546                                 if (wl_ioctl(WL_DEVICE, WLC_GET_RSSI, &starssi, 12) < 0) printf("rssifail\n");
547                                 sta->RSSI = -starssi.RSSI * 100;
548                                 sta->staInfo->state = ssAssociated;
549                                 memcpy(sta->staInfo->connectedBSSID, host->apInfo->bssid, 6);
550                         }
551                 }
552         }
553         else {
554                 host = gotHost(cfg, mac, typeSta);
555                 host->RSSI = 0;
556                 if (wl_ioctl(WL_DEVICE, WLC_GET_BSSID, &host->staInfo->connectedBSSID, 6) < 0) {
557                   host->staInfo->state = ssUnassociated;
558                 }
559                 else {
560                   host->staInfo->state = ssAssociated;
561                 }
562         }
563   if (wl_ioctl(WL_DEVICE, WLC_GET_CHANNEL, &channel, sizeof(channel_info_t)) >= 0) {
564     cfg->curChannel = channel.hw_channel;
565     fprintf(stderr, "Current channel is %i\n", cfg->curChannel);
566     }
567 }
568
569
570
571
572