1 /*-
2  * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/ioctl.h>
29 #include <sys/select.h>
30 #include <sys/time.h>
31 #include <net/if.h>
32 #include <net/if_media.h>
33 #include <net/bpf.h>
34 #include <net80211/ieee80211_ioctl.h>
35 #include <net80211/ieee80211.h>
36 #include <net/ethernet.h>
37 #include <net80211/ieee80211_radiotap.h>
38 #include <sys/endian.h>
39 #include <fcntl.h>
40 #include <errno.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <curses.h>
45 #include <signal.h>
46 #include <unistd.h>
47 #include <assert.h>
48 
49 //int hopfreq = 3*1000; // ms
50 int hopfreq = 500; // ms
51 int sig_reset = 1*1000; // ms
52 
53 
54 int ioctl_s = -1;
55 int bpf_s = -1;
56 
57 struct chan_info {
58 	int locked;
59 	int chan;
60 	struct ieee80211req ireq;
61 	struct timeval last_hop;
62 } chaninfo;
63 
64 
65 #define CRYPT_NONE		0
66 #define CRYPT_WEP		1
67 #define CRYPT_WPA1		2
68 #define CRYPT_WPA		3
69 #define CRYPT_WPA1_TKIP		4
70 #define CRYPT_WPA1_TKIP_PSK	5
71 #define CRYPT_WPA1_CCMP		6
72 #define CRYPT_WPA1_CCMP_PSK	7
73 #define CRYPT_80211i		8
74 #define CRYPT_80211i_TKIP	9
75 #define CRYPT_80211i_TKIP_PSK	10
76 
77 struct node_info {
78 	unsigned char mac[6];
79 	int signal;
80 	int noise;
81 	int max;
82 	unsigned char ssid[256];
83 	int chan;
84 	int wep;
85 	int pos;
86 	int ap;
87 
88 	struct timeval seen;
89 
90 	struct node_info* prev;
91 	struct node_info* next;
92 } *nodes = 0;
93 
94 void clean_crap() {
95 	struct node_info* next;
96 
97 	if (ioctl_s != -1)
98 		close(ioctl_s);
99 	if (bpf_s != -1)
100 		close(bpf_s);
101 
102 	while (nodes) {
103 		next = nodes->next;
104 		free(nodes);
105 		nodes = next;
106 	}
107 }
108 
109 char* mac2str(unsigned char* mac) {
110         static char ret[6*3];
111 
112         sprintf(ret, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
113                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
114 
115         return ret;
116 }
117 
118 char* wep2str(int w) {
119 	char* wep = 0;
120 	static char res[14];
121 
122 	switch (w) {
123 	case CRYPT_NONE:
124 		wep = "";
125 		break;
126 
127 	case CRYPT_WEP:
128 		wep = "WEP";
129 		break;
130 
131 	case CRYPT_WPA1:
132 		wep = "WPA1";
133 		break;
134 
135 	case CRYPT_WPA:
136 		wep = "WPA?";
137 		break;
138 
139 	case CRYPT_WPA1_TKIP:
140 		wep = "WPA1-TKIP";
141 		break;
142 
143 	case CRYPT_WPA1_TKIP_PSK:
144 		wep = "WPA1-TKIP-PSK";
145 		break;
146 
147 	case CRYPT_WPA1_CCMP:
148 		wep = "WPA1-CCMP";
149 		break;
150 
151 	case CRYPT_WPA1_CCMP_PSK:
152 		wep = "WPA1-CCMP-PSK";
153 		break;
154 
155 	case CRYPT_80211i:
156 		wep = "i";
157 		break;
158 
159 	case CRYPT_80211i_TKIP:
160 		wep = "11i-TKIP";
161 		break;
162 
163 	case CRYPT_80211i_TKIP_PSK:
164 		wep = "11i-TKIP-PSK";
165 		break;
166 
167 	default:
168 		wep = "FIXME!";
169 		break;
170 	}
171 
172 	memset(res, ' ', sizeof(res));
173 	assert(strlen(wep) < sizeof(res));
174 	memcpy(res, wep, strlen(wep));
175 	res[sizeof(res)-1] = 0;
176 	return res;
177 }
178 
179 char* ssid2str(struct node_info* node) {
180 	static char res[24];
181 
182 	memset(res, ' ', sizeof(res));
183 	res[0] = '[';
184 	strcpy(&res[sizeof(res)-2], "]");
185 
186 	if (node->ap) {
187 		int left = sizeof(res) - 3;
188 
189 		if (strlen(node->ssid) < left)
190 			left = strlen(node->ssid);
191 		memcpy(&res[1], node->ssid, left);
192 	}
193 	else {
194 		memcpy(&res[1], "<client>", 8);
195 	}
196 	return res;
197 }
198 
199 void save_state() {
200 	FILE* f;
201 	struct node_info* node = nodes;
202 
203 	f = fopen("stumbler.log", "w");
204 	if (!f) {
205 		perror("fopen()");
206 		exit(1);
207 	}
208 
209 	while (node) {
210 		struct tm* t;
211 		char tim[16];
212 
213 		t = localtime( (time_t*) &node->seen.tv_sec);
214 		if (!t) {
215 			perror("localtime()");
216 			exit(1);
217 		}
218 		tim[0] = 0;
219 		strftime(tim, sizeof(tim), "%H:%M:%S", t);
220 
221 		fprintf(f, "%s %s %s %2d %s 0x%.2x\n", tim,
222 			mac2str(node->mac), wep2str(node->wep),
223 			node->chan, ssid2str(node), node->max);
224 
225 		node = node->next;
226 	}
227 
228 	fclose(f);
229 }
230 
231 void cleanup(int x) {
232 	endwin();
233 	clean_crap();
234 	exit(0);
235 }
236 
237 void die(int p, char* msg) {
238 	endwin();
239 	if (p)
240 		perror(msg);
241 	else
242 		printf("%s\n", msg);
243 	clean_crap();
244 	exit(1);
245 }
246 
247 void display_chan() {
248 	int x, y;
249 	char tmp[3];
250 
251 	x = COLS - 2;
252 	y = LINES - 1;
253 
254 	snprintf(tmp, sizeof(tmp), "%.2d", chaninfo.chan);
255 	mvaddstr(y, x, tmp);
256 	refresh();
257 }
258 
259 void set_chan(int c) {
260         chaninfo.ireq.i_val = c;
261 
262         if (ioctl(ioctl_s, SIOCS80211, &chaninfo.ireq) == -1)
263                 die(1, "ioctl(SIOCS80211) [chan]");
264 
265 	chaninfo.chan = c;
266 
267 	if (gettimeofday(&chaninfo.last_hop, NULL) == -1)
268 		die(1, "gettimeofday()");
269 
270 	display_chan();
271 }
272 
273 void setup_if(char *dev) {
274         struct ifreq ifr;
275         unsigned int flags;
276 
277         // set chan
278         memset(&chaninfo.ireq, 0, sizeof(chaninfo.ireq));
279         strcpy(chaninfo.ireq.i_name, dev);
280         chaninfo.ireq.i_type = IEEE80211_IOC_CHANNEL;
281 
282         set_chan(1);
283 
284         // set iface up and promisc
285         memset(&ifr, 0, sizeof(ifr));
286         strcpy(ifr.ifr_name, dev);
287         if (ioctl(ioctl_s, SIOCGIFFLAGS, &ifr) == -1)
288                 die(1, "ioctl(SIOCGIFFLAGS)");
289 
290         flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
291         flags |= IFF_UP | IFF_PPROMISC;
292 
293         memset(&ifr, 0, sizeof(ifr));
294         strcpy(ifr.ifr_name, dev);
295         ifr.ifr_flags = flags & 0xffff;
296         ifr.ifr_flagshigh = flags >> 16;
297         if (ioctl(ioctl_s, SIOCSIFFLAGS, &ifr) == -1)
298                 die(1, "ioctl(SIOCSIFFLAGS)");
299 }
300 
301 void open_bpf(char *dev, int dlt) {
302         int i;
303         char buf[64];
304         int fd = -1;
305         struct ifreq ifr;
306 
307         for(i = 0;i < 16; i++) {
308                 sprintf(buf, "/dev/bpf%d", i);
309 
310                 fd = open(buf, O_RDWR);
311                 if(fd < 0) {
312                         if(errno != EBUSY)
313 				die(1,"can't open /dev/bpf");
314                         continue;
315                 }
316                 else
317                         break;
318         }
319 
320         if(fd < 0)
321                 die(1, "can't open /dev/bpf");
322 
323         strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1);
324         ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0;
325 
326         if(ioctl(fd, BIOCSETIF, &ifr) < 0)
327                 die(1, "ioctl(BIOCSETIF)");
328 
329         if (ioctl(fd, BIOCSDLT, &dlt) < 0)
330                 die(1, "ioctl(BIOCSDLT)");
331 
332         i = 1;
333         if(ioctl(fd, BIOCIMMEDIATE, &i) < 0)
334                 die(1, "ioctl(BIOCIMMEDIATE)");
335 
336 	bpf_s = fd;
337 }
338 
339 void user_input() {
340 	static char chan[3];
341 	static int pos = 0;
342 	int c;
343 
344 	c = getch();
345 
346 	switch (c) {
347 		case 'w':
348 			save_state();
349 			break;
350 
351 		case 'q':
352 			cleanup(0);
353 			break;
354 
355 		case 'c':
356 			chaninfo.locked = !chaninfo.locked;
357 			break;
358 
359 		case ERR:
360 			die(0, "getch()");
361 			break;
362 
363 		case '0':
364 		case '1':
365 		case '2':
366 		case '3':
367 		case '4':
368 		case '5':
369 		case '6':
370 		case '7':
371 		case '8':
372 		case '9':
373 			chan[pos++] = c;
374 			if (pos == 2) {
375 				int ch = atoi(chan);
376 				if (ch <= 11 && ch >= 1) {
377 					set_chan(atoi(chan));
378 					chaninfo.locked = 1;
379 				}
380 				pos = 0;
381 			}
382 			break;
383 
384 		default:
385 			pos = 0;
386 			break;
387 	}
388 }
389 
390 void display_node(struct node_info* node) {
391 	int x = 0;
392 	int y = 0;
393 	int i;
394 	char chan[3];
395 	char* ssid = 0;
396 	int sig, max, left, noise;
397 	char* wep = 0;
398 
399 	y = node->pos;
400 	if (y == -1) // offscreen
401 		return;
402 
403 	assert(y < LINES);
404 
405 	// MAC
406 	mvaddstr(y, x, mac2str(node->mac));
407 	x += 6*3;
408 
409 	// WEP
410 	wep = wep2str(node->wep);
411 	assert(wep);
412 	mvaddstr(y, x, wep);
413 	x += strlen(wep);
414 	x++;
415 
416 	// CHAN
417 	sprintf(chan, "%.2d", node->chan);
418 	mvaddstr(y, x, chan);
419 	x += 3;
420 
421 	// ssid
422 	ssid = ssid2str(node);
423 	assert(ssid);
424 	mvaddstr(y, x, ssid);
425 	x += strlen(ssid);
426 	x++;
427 
428 	left = COLS - x - 1;
429 
430 	sig = (int)  ( ((double)node->signal)*left/100.0 );
431 	noise=(int)  ( ((double)node->noise)*left/100.0 );
432 	max = (int)  ( ((double)node->max)*left/100.0 );
433 
434 	// SIGNAL BAR
435 	for (i = 0; i < noise; i++)
436 		mvaddch(y, x++, 'N');
437 
438 	for (; i < sig; i++)
439 		mvaddch(y,x++, 'X');
440 
441 	for (; i < max; i++)
442 		mvaddch(y,x++, ' ');
443 	mvaddch(y,x++, '|');
444 
445 	for (; x < COLS-1; x++)
446 		mvaddch(y, x, ' ');
447 
448 	assert (x <= COLS);
449 }
450 
451 void update_node(struct node_info* data) {
452 	struct node_info* node;
453 	int sort = 0;
454 
455 	assert(data->signal <= 100);
456 
457 	node = nodes;
458 
459 	// first time [virgin]
460 	if (!node) {
461 		node = (struct node_info*) malloc(sizeof(struct node_info));
462 		if (!node)
463 			die(1, "malloc()");
464 
465 		memset(node, 0, sizeof(*node));
466 		memcpy(node->mac, data->mac, 6);
467 		nodes = node;
468 	}
469 
470 	while (node) {
471 		// found it
472 		if (memcmp(node->mac, data->mac, 6) == 0)
473 			break;
474 
475 		// end of chain
476 		if (!node->next) {
477 			node->next = (struct node_info*)
478 				      malloc(sizeof(struct node_info));
479 			if (!node->next)
480 				die(1, "malloc()");
481 
482 			memset(node->next, 0, sizeof(*node->next));
483 			memcpy(node->next->mac, data->mac, 6);
484 			node->next->prev = node;
485 			node->next->pos = node->pos+1;
486 
487 			node = node->next;
488 			if (node->pos == LINES)
489 				sort = 1;
490 			break;
491 		}
492 
493 		node = node->next;
494 	}
495 	assert(node);
496 
497 	// too many nodes for screen
498 	if (sort) {
499 		struct node_info* ni = nodes;
500 
501 		while (ni) {
502 			if (ni->pos != -1)
503 				ni->pos--;
504 
505 			display_node(ni);
506 			ni = ni->next;
507 		}
508 	}
509 
510 	node->signal = data->signal;
511 	if (data->signal > node->max)
512 		node->max = data->signal;
513 
514 	if (gettimeofday(&node->seen, NULL) == -1)
515 		die(1, "gettimeofday()");
516 
517 	if (data->ssid[0] != 0)
518 		strcpy(node->ssid, data->ssid);
519 	if (data->chan != -1)
520 		node->chan = data->chan;
521 	if (data->wep != -1) {
522 		// XXX LAME --- won't detect if AP changes WEP mode in
523 		// beacons...
524 		if (node->wep != CRYPT_WEP &&
525 		    node->wep != CRYPT_NONE &&
526 		    data->wep == CRYPT_WEP) {
527 		}
528 		else
529 			node->wep = data->wep;
530 	}
531 	if (data->ap != -1)
532 		node->ap = data->ap;
533 
534 	display_node(node);
535 	refresh();
536 }
537 
538 void get_beacon_info(unsigned char* data, int rd,
539 		     struct node_info* node) {
540 
541 	int blen = 8 + 2 + 2;
542 
543 	strcpy(node->ssid, "<hidden>");
544 	node->chan = 0;
545 	node->wep = CRYPT_NONE;
546 
547 	assert(rd >= blen);
548 
549 	if (IEEE80211_BEACON_CAPABILITY(data) & IEEE80211_CAPINFO_PRIVACY)
550 		node->wep = CRYPT_WEP;
551 
552 	data += blen;
553 	rd -= blen;
554 
555 	while (rd > 2) {
556                 int eid, elen;
557 
558                 eid = *data;
559                 data++;
560                 elen = *data;
561                 data++;
562                 rd -= 2;
563 
564 		// short!
565                 if (rd < elen) {
566                         return;
567                 }
568 
569                 // ssid
570                 if (eid == 0) {
571 			if (elen == 1 && data[0] == 0) {
572 			// hidden
573 			}
574 			else {
575                         	memcpy(node->ssid, data, elen);
576                         	node->ssid[elen] = 0;
577 			}
578                 }
579                 // chan
580                 else if(eid == 3) {
581 			// weird chan!
582                         if( elen != 1)
583 				goto next;
584 
585                         node->chan = *data;
586                 }
587 		// WPA
588 		else if (eid == 221 && node->wep == CRYPT_WEP) {
589 			struct ieee80211_ie_wpa* wpa;
590 
591 			wpa = (struct ieee80211_ie_wpa*) data;
592 			if (elen < 6)
593 				goto next;
594 
595 			if (!memcmp(wpa->wpa_oui, "\x00\x50\xf2", 3)) {
596 			//	node->wep = CRYPT_WPA;
597 			}
598 			else
599 				goto next;
600 
601 			if (wpa->wpa_type == WPA_OUI_TYPE &&
602 			    le16toh(wpa->wpa_version) == WPA_VERSION) {
603 			    	int cipher, auth;
604 				unsigned char* ptr;
605 
606 				node->wep = CRYPT_WPA1;
607 
608 				if (elen < 12)
609 					goto next;
610 
611 				cipher = ((unsigned char*) wpa->wpa_mcipher)[3];
612 
613 				ptr = (unsigned char*)wpa + 12 +
614 				      4 * le16toh(wpa->wpa_uciphercnt);
615 
616 				if (elen < (ptr - data + 6))
617 					goto next;
618 
619 				if ( *((unsigned short*) ptr) == 0)
620 					goto next;
621 
622 				ptr += 2 + 3;
623 				auth = *ptr;
624 
625 				if (cipher == WPA_CSE_TKIP) {
626 					node->wep = CRYPT_WPA1_TKIP;
627 
628 					if (auth == WPA_ASE_8021X_PSK)
629 						node->wep = CRYPT_WPA1_TKIP_PSK;
630 				}
631 
632 				if (cipher == WPA_CSE_CCMP) {
633 					node->wep = CRYPT_WPA1_CCMP;
634 
635 					if (auth == WPA_ASE_8021X_PSK)
636 						node->wep = CRYPT_WPA1_CCMP_PSK;
637 				}
638 			}
639 		}
640 		else if (eid == 48 && node->wep == CRYPT_WEP) {
641 			unsigned char* ptr;
642 
643 			// XXX no bounds checking
644 			ptr = data;
645 
646 			if (ptr[0] == 1 && ptr[1] == 0) {
647 				unsigned short* count;
648 				int cipher = 0;
649 
650 				ptr += 2;
651 				node->wep = CRYPT_80211i;
652 
653 				if (!memcmp(ptr, "\x00\x0f\xac\x02", 4)) {
654 					node->wep = CRYPT_80211i_TKIP;
655 					cipher = 1;
656 				}
657 
658 				ptr += 4;
659 				count = (unsigned short*) ptr;
660 				ptr +=2 + *count*4;
661 
662 				count = (unsigned short*) ptr;
663 				if (*count) {
664 					ptr += 2;
665 
666 					if (!memcmp(ptr,"\x00\x0f\xac\x02", 4)) {
667 						if (cipher)
668 							node->wep = CRYPT_80211i_TKIP_PSK;
669 					}
670 				}
671 			}
672 		}
673 
674 next:
675                 data += elen;
676                 rd -= elen;
677 	}
678 }
679 
680 int get_packet_info(struct ieee80211_frame* wh,
681 		     unsigned char* body, int bodylen,
682 		     struct node_info* node) {
683 
684 	int type, stype;
685 
686 	node->chan = chaninfo.chan;
687 	node->wep = -1;
688 	node->ssid[0] = 0;
689 	node->ap = -1;
690 
691 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
692 
693 	if (type == IEEE80211_FC0_TYPE_CTL)
694 		return 0;
695 #if 0
696 	if (wh->i_addr2[0] != 0) {
697 		mvprintw(30,30,"%s %x",mac2str(wh->i_addr2), wh->i_fc[0]);
698 	}
699 #endif
700 
701 	stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
702 
703 	if (type == IEEE80211_FC0_TYPE_MGT &&
704 	    stype == IEEE80211_FC0_SUBTYPE_BEACON) {
705 		get_beacon_info(body, bodylen, node);
706 		node->ap = 1;
707 	}
708 
709 	else if (type == IEEE80211_FC0_TYPE_DATA &&
710 	    stype == IEEE80211_FC0_SUBTYPE_DATA) {
711 
712 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
713 			unsigned char* iv;
714 
715 			node->wep = CRYPT_WEP;
716 
717 			iv = body;
718 			iv += 3;
719 
720 			// extended IV?
721 			if (*iv & (1 << 1)) {
722 #if 0
723 				node->wep = CRYPT_WPA;
724 				mvprintw(20,20, "shei");
725 				exit(1);
726 #endif
727 			}
728 		}
729 
730 		if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
731 			node->ap = 1;
732 		else
733 			node->ap = 0;
734 	}
735 
736 	memcpy(node->mac, wh->i_addr2, 6);
737 	return 1;
738 }
739 
740 void radiotap(unsigned char* data, int rd) {
741 	struct ieee80211_radiotap_header* rth;
742 	struct ieee80211_frame* wh;
743 	char* body;
744 	struct node_info node;
745 	int8_t signal_dbm, noise_dbm;
746 	uint8_t signal_db, noise_db;
747 	int dbm = 0;
748 	int signal = 0;
749 	int i;
750 
751 	rd -= 4; // 802.11 CRC
752 
753 	// radiotap
754 	rth = (struct ieee80211_radiotap_header*) data;
755 
756 	// 802.11
757 	wh = (struct ieee80211_frame*)
758 	     ((char*)rth + rth->it_len);
759         rd -= rth->it_len;
760 
761 	assert (rd >= 0);
762 
763 	// body
764 	body = (char*) wh + sizeof(*wh);
765 	rd -= sizeof(*wh);
766 
767 	if (!get_packet_info(wh, body, rd, &node))
768 		return;
769 
770 	// signal and noise
771 	body = (char*) rth + sizeof(*rth);
772 	signal_dbm = noise_dbm = signal_db = noise_db = 0;
773 
774 	for (i = IEEE80211_RADIOTAP_TSFT; i <= IEEE80211_RADIOTAP_EXT; i++) {
775 		if (!(rth->it_present & (1 << i)))
776 			continue;
777 
778 		switch (i) {
779 		case IEEE80211_RADIOTAP_TSFT:
780 			body += sizeof(uint64_t);
781 			break;
782 
783 		case IEEE80211_RADIOTAP_FLAGS:
784 		case IEEE80211_RADIOTAP_RATE:
785 			body += sizeof(uint8_t);
786 			break;
787 
788 		case IEEE80211_RADIOTAP_CHANNEL:
789 			body += sizeof(uint16_t)*2;
790 			break;
791 
792 		case IEEE80211_RADIOTAP_FHSS:
793 			body += sizeof(uint16_t);
794 			break;
795 
796 		case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
797 			signal_dbm = *body;
798 			body++;
799 			dbm = 1;
800 			break;
801 
802 		case IEEE80211_RADIOTAP_DBM_ANTNOISE:
803 			noise_dbm = *body;
804 			body++;
805 			break;
806 
807 		case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
808 			signal_db = *((unsigned char*)body);
809 			body++;
810 			break;
811 
812 		case IEEE80211_RADIOTAP_DB_ANTNOISE:
813 			noise_db = *((unsigned char*)body);
814 			body++;
815 			break;
816 
817 		case IEEE80211_RADIOTAP_EXT:
818 			abort();
819 			break;
820 		}
821 	}
822 	if (dbm) {
823 		signal = signal_dbm - noise_dbm;
824 	}
825 	else {
826 		signal = signal_db - noise_db;
827 	}
828 	if (signal < 0)
829 		signal = 0;
830 
831 	node.signal = signal;
832 #if 0
833 	if (node.signal > 100 || node.signal < 0) {
834 		mvprintw(25,25, "sig=%d", node.signal);
835 	}
836 #else
837 	assert (node.signal <= 100 && node.signal >= 0);
838 #endif
839 
840 	update_node(&node);
841 }
842 
843 void bpf_input() {
844 	static unsigned char buf[4096];
845 	int rd;
846 	struct bpf_hdr* bpfh;
847 	unsigned char* data;
848 
849 	rd = read(bpf_s, buf, sizeof(buf));
850 	if (rd == -1)
851 		die(1,"read()");
852 
853 	bpfh = (struct bpf_hdr*) buf;
854 	rd -= bpfh->bh_hdrlen;
855 
856 	if (rd != bpfh->bh_caplen) {
857 		assert( rd > bpfh->bh_caplen);
858 		rd = bpfh->bh_caplen;
859 	}
860 
861 	data = (unsigned char*) bpfh + bpfh->bh_hdrlen;
862 	radiotap(data, rd);
863 }
864 
865 unsigned long elapsed_ms(struct timeval* now, struct timeval* prev) {
866 	unsigned long elapsed = 0;
867 
868 	if (now->tv_sec > prev->tv_sec)
869 		elapsed = 1000*1000 - prev->tv_usec +
870 			  now->tv_usec;
871 	else {
872 		assert(now->tv_sec == prev->tv_sec);
873 		elapsed = now->tv_usec - prev->tv_usec;
874 	}
875 	elapsed /= 1000; //ms
876 
877 	elapsed += (now->tv_sec - prev->tv_sec)*1000;
878 	return elapsed;
879 }
880 
881 void chanhop(struct timeval* tv) {
882 	unsigned long elapsed = 0;
883 
884 	if (gettimeofday(tv, NULL) == -1)
885 		die(1, "gettimeofday()");
886 
887 
888 	elapsed = elapsed_ms(tv, &chaninfo.last_hop);
889 
890 	// need to chan hop
891 	if (elapsed >= hopfreq) {
892 		int c;
893 
894 		c = chaninfo.chan + 1;
895 
896 		if (c > 11)
897 			c = 1;
898 
899 		set_chan(c);
900 
901 		elapsed = hopfreq;
902 	}
903 	// how much can we sleep?
904 	else {
905 		elapsed = hopfreq - elapsed;
906 	}
907 
908 	// ok calculate sleeping time...
909 	tv->tv_sec = elapsed/1000;
910 	tv->tv_usec = (elapsed - tv->tv_sec*1000)*1000;
911 }
912 
913 void check_seen(struct timeval* tv) {
914 	unsigned long elapsed  = 0;
915 	struct timeval now;
916 	int need_refresh = 0;
917 	unsigned long min_wait = 0;
918 	unsigned long will_wait;
919 
920 	will_wait = tv->tv_sec*1000+tv->tv_usec/1000;
921 	min_wait = will_wait;
922 
923 	struct node_info* node = nodes;
924 
925 	if (gettimeofday(&now, NULL) == -1)
926 		die(1, "gettimeofday()");
927 
928 	while(node) {
929 		if (node->signal) {
930 			elapsed = elapsed_ms(&now, &node->seen);
931 
932 			// node is dead...
933 			if (elapsed >= sig_reset) {
934 				node->signal = 0;
935 				display_node(node);
936 				need_refresh = 1;
937 			}
938 
939 			// need to check soon possibly...
940 			else {
941 				unsigned long left;
942 
943 				left = sig_reset - elapsed;
944 				if (left < min_wait)
945 					left = min_wait;
946 			}
947 		}
948 		node = node->next;
949 	}
950 
951 	if (need_refresh)
952 		refresh();
953 
954 	// need to sleep for less...
955 	if (min_wait < will_wait) {
956 		tv->tv_sec = min_wait/1000;
957 		tv->tv_usec = (min_wait - tv->tv_sec*1000)*1000;
958 	}
959 }
960 
961 void own(char* ifname) {
962 	int rd;
963 	fd_set fds;
964 	struct timeval tv;
965 	int dlt = DLT_IEEE802_11_RADIO;
966 
967 	hopfreq = 1000;
968 
969 	setup_if(ifname);
970 	open_bpf(ifname, dlt);
971 
972 	while(1) {
973 		// XXX innefficient all of this...
974 		if (!chaninfo.locked)
975 			chanhop(&tv);
976 		else {
977 			tv.tv_sec = 1;
978 			tv.tv_usec = 0;
979 		}
980 
981 		// especially this...
982 		check_seen(&tv);
983 
984 		FD_ZERO(&fds);
985 		FD_SET(0, &fds);
986 		FD_SET(bpf_s, &fds);
987 
988 		rd = select(bpf_s+1, &fds,NULL , NULL, &tv);
989 		if (rd == -1)
990 			die(1, "select()");
991 		if (FD_ISSET(0, &fds))
992 			user_input();
993 		if (FD_ISSET(bpf_s, &fds))
994 			bpf_input();
995 	}
996 }
997 
998 void init_globals() {
999 	ioctl_s = socket(PF_INET, SOCK_DGRAM, 0);
1000 	if (ioctl_s == -1) {
1001 		perror("socket()");
1002 		exit(1);
1003 	}
1004 
1005 	chaninfo.locked = 0;
1006 	chaninfo.chan = 0;
1007 }
1008 
1009 int main(int argc, char *argv[]) {
1010 
1011 
1012 	if (argc < 2) {
1013 		printf("Usage: %s <iface>\n", argv[0]);
1014 		exit(1);
1015 	}
1016 
1017 	init_globals();
1018 
1019 	initscr(); cbreak(); noecho();
1020 
1021 	nonl();
1022 	intrflush(stdscr, FALSE);
1023 	keypad(stdscr, TRUE);
1024 
1025 	curs_set(0);
1026 
1027 	clear();
1028 	refresh();
1029 
1030 	signal(SIGINT, cleanup);
1031 	signal(SIGTERM, cleanup);
1032 
1033 	own(argv[1]);
1034 
1035 	cleanup(0);
1036 	exit(0);
1037 }
1038