diff --exclude='.git*' -Nur horst-2.0-rc1/capture.c horst-2008-07-13/capture.c
--- horst-2.0-rc1/capture.c	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/capture.c	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -31,6 +31,7 @@
 #include "capture.h"
 #include "util.h"
 
+extern fd_set fds;
 
 #ifdef PCAP
 
@@ -176,7 +177,7 @@
 }
 
 
-void
+static void
 set_receive_buffer(int fd, int sockbufsize)
 {
 	int ret;
@@ -206,6 +207,7 @@
 {
 	int ret;
 	int ifindex;
+	struct sockaddr_ll sall;
 
 	mon_ifname = devname;
 
@@ -216,7 +218,6 @@
 	/* bind only to one interface */
 	ifindex = device_index(mon_fd, devname);
 
-	struct sockaddr_ll sall;
 	sall.sll_ifindex = ifindex;
 	sall.sll_family = AF_PACKET;
 	sall.sll_protocol = htons(ETH_P_ALL);
@@ -229,14 +230,14 @@
 
 	set_receive_buffer(mon_fd, recv_buffer_size);
 
-	return (mon_fd >= 0);
+	return mon_fd;
 }
 
 
 inline int
-recv_packet(unsigned char* buffer, size_t bufsize)
+recv_packet(int fd, unsigned char* buffer, size_t bufsize)
 {
-	return recv(mon_fd, buffer, bufsize, MSG_DONTWAIT);
+	return recv(fd, buffer, bufsize, MSG_DONTWAIT);
 }
 
 
diff --exclude='.git*' -Nur horst-2.0-rc1/capture.h horst-2008-07-13/capture.h
--- horst-2.0-rc1/capture.h	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/capture.h	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -24,7 +24,7 @@
 open_packet_socket(char* devname, size_t bufsize, int recv_buffer_size);
 
 int
-recv_packet(unsigned char* buffer, size_t bufsize);
+recv_packet(int fd, unsigned char* buffer, size_t bufsize);
 
 void
 close_packet_socket(void);
diff --exclude='.git*' -Nur horst-2.0-rc1/ChangeLog horst-2008-07-13/ChangeLog
--- horst-2.0-rc1/ChangeLog	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/ChangeLog	2008-07-13 10:54:53.000000000 +0200
@@ -1,42 +1,44 @@
-2007-10-XX  Bruno Randolf (br1@einfach.org)
+2007-12-26 (2.0-rc1)  Bruno Randolf (br1@einfach.org)
 
 	* added radiotap header support and automatic detection of the header
-	  format used by the driver (prism2 or radiotap)
+	  format used by the driver (prism2 or radiotap).
 
 	* added IBSS split detection: warn when one ESSID (name) is announced
-	  with different BSSIDs in beacons from different nodes in IBSS mode
+	  with different BSSIDs in beacons from different nodes in IBSS mode.
+	  very useful for debugging IBSS problems.
 
-	* added ESSID window: list all known ESSIDs and all stations which
+	* new ESSID window: list all known ESSIDs and all stations which
 	  announce the ESSID in their beacons including the TSF timestamp for
-	  easier IBSS split analysis
+	  easier IBSS split analysis.
 
-	* added MAC Filter window, improved filtering in general
+	* new history window: display Signal/Noise/Rate graph
 
-	* display minimum and maximum SNR of each node
+	* new packet statistics window: display the percentage of different
+	  packet types and physical rates and other packet statistics.
 
-	* various smaller improvements, fixes and cleanups
+	* improved filtering framework: allow filtering by packet types,
+	  MAC addresses, BSSID.
 
-	* use non-blocking IO
+	* added duration calculation: "AirTime" to estimate the pyhsical usage
+	  of the channel.
 
-	* added Signal/Noise/Rate history graph
+	* optimized screen updates and buffering: to save CPU time and to avoid
+	  loosing packets. added -w and -d options for fine grained control
+	  of display update and sleep intervals. -b option to change the buffer
+	  size (it's quite large by default now).
 
-	* -t command line option to specify node timeout
+	* much more complete and improved 802.11 packet parsing.
 
-	* optimized screen updates - saves CPU time
+	* better node timeout handling, using linked lists. -t command line
+	  option to specify node timeout.
 
-	* packet statistics, AirTime, Usage, added "duration" calculation to
-          estimate the usage of the channel
+	* sort node list by SNR, age, BSSID or channel.
 
-	* better filter framework
+	* -o option to write packet infos into a text file.
 
-	* -w and -d options for fine grained control of update and sleep
-	  intervals, to adapt for slower CPUs
+	* initial (primitive) B.A.T.M.A.N support.
 
-	* improved packet parsing
-
-	* initial B.A.T.M.A.N support
-
-	* -o option to write packet infos into file
+	* various smaller improvements, fixes, cleanups and beautifications.
 
 2007-07-20  Sven-Ola aet gmx.de
 
diff --exclude='.git*' -Nur horst-2.0-rc1/display.c horst-2008-07-13/display.c
--- horst-2.0-rc1/display.c	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/display.c	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -102,14 +102,19 @@
 static void __attribute__ ((format (printf, 4, 5)))
 print_centered(WINDOW* win, int line, int cols, const char *fmt, ...)
 {
-	char buf[cols];
+	char* buf;
 	va_list ap;
 
+	buf = malloc(cols);
+	if (buf == NULL)
+		return;
+
 	va_start(ap, fmt);
 	vsnprintf(buf, cols, fmt, ap);
 	va_end(ap);
 
 	mvwprintw(win, line, cols / 2 - strlen(buf) / 2, buf);
+	free(buf);
 }
 
 
@@ -205,7 +210,7 @@
 
 #define MAC_COL 30
 
-void
+static void
 filter_input(int c)
 {
 	char buf[18];
@@ -342,11 +347,11 @@
 	struct node_info* n2 = list_entry(p2, struct node_info, list);
 
 	if (n1->channel < n2->channel)
-		return -1;
+		return 1;
 	else if (n1->channel == n2->channel)
 		return 0;
 	else
-		return 1;
+		return -1;
 }
 
 
@@ -356,11 +361,11 @@
 	struct node_info* n1 = list_entry(p1, struct node_info, list);
 	struct node_info* n2 = list_entry(p2, struct node_info, list);
 
-	return memcmp(n1->wlan_bssid, n2->wlan_bssid, MAC_LEN);
+	return -memcmp(n1->wlan_bssid, n2->wlan_bssid, MAC_LEN);
 }
 
 
-void
+static void
 sort_input(int c)
 {
 	switch(c) {
@@ -391,7 +396,7 @@
 
 
 void
-handle_user_input()
+handle_user_input(void)
 {
 	int key;
 
@@ -497,7 +502,7 @@
 #define CHECK_ETHER(_mac) MAC_NOT_EMPTY(_mac) ? '*' : ' '
 
 static void
-update_filter_win()
+update_filter_win(void)
 {
 	int l, i;
 
@@ -630,7 +635,7 @@
 
 
 static void
-update_show_win()
+update_show_win(void)
 {
 	if (show_win_current == 'e')
 		update_essid_win();
@@ -650,7 +655,8 @@
 static void
 update_status_win(struct packet_info* pkt, struct node_info* node)
 {
-	int sig, noi, max, rate, bps, bpsn, usen;
+	int sig, noi, rate, bps, bpsn, usen;
+	int max = 0;
 	float use;
 	int max_stat_bar = stat_height - 4;
 
@@ -754,7 +760,7 @@
 	else if (n->wlan_mode == WLAN_MODE_PROBE )
 		mvwprintw(list_win, line, COL_STA, "P");
 
-	mvwprintw(list_win, line, COL_ENC, n->wep ? "E" : "O");
+	mvwprintw(list_win, line, COL_ENC, n->wep ? "W" : "");
 
 	mvwprintw(list_win, line, COL_RATE, "%2d", p->rate/2);
 	mvwprintw(list_win, line, COL_SOURCE, "%s", ether_sprintf(p->wlan_src));
@@ -871,7 +877,7 @@
 			wprintw(show_win, " %016llx", node->tsf);
 			wprintw(show_win, " %2d", node->channel);
 			wprintw(show_win, " %2ddB", node->snr);
-			wprintw(show_win, " %s", node->wep ? "E" : "O");
+			wprintw(show_win, " %s", node->wep ? "W" : " ");
 			if (node->pkt_types & PKT_TYPE_IP)
 				wprintw(show_win, " %s", ip_sprintf(node->ip_src));
 			line++;
@@ -981,7 +987,7 @@
 }
 
 
-void
+static void
 update_dump_win(struct packet_info* pkt)
 {
 	if (!pkt) {
@@ -1036,7 +1042,7 @@
 
 		switch (pkt->wlan_type & IEEE80211_FCTL_FTYPE) {
 		case IEEE80211_FTYPE_DATA:
-			if ( current_packet.wlan_wep == 1)
+			if ( pkt->wlan_wep == 1)
 				wprintw(dump_win, "ENCRYPTED");
 			break;
 		case IEEE80211_FTYPE_CTL:
@@ -1049,7 +1055,7 @@
 			}
 			break;
 		case IEEE80211_FTYPE_MGMT:
-			switch (current_packet.wlan_type & IEEE80211_FCTL_STYPE) {
+			switch (pkt->wlan_type & IEEE80211_FCTL_STYPE) {
 			case IEEE80211_STYPE_BEACON:
 			case IEEE80211_STYPE_PROBE_RESP:
 				wprintw(dump_win, "'%s' %llx", pkt->wlan_essid,
diff --exclude='.git*' -Nur horst-2.0-rc1/display.h horst-2008-07-13/display.h
--- horst-2.0-rc1/display.h	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/display.h	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --exclude='.git*' -Nur horst-2.0-rc1/ieee80211_util.c horst-2008-07-13/ieee80211_util.c
--- horst-2.0-rc1/ieee80211_util.c	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/ieee80211_util.c	2008-07-13 10:54:53.000000000 +0200
@@ -18,13 +18,14 @@
 
 #include "ieee80211.h"
 #include "ieee80211_radiotap.h"
+#include "ieee80211_util.h"
 #include "main.h"
 #include "util.h"
 
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 u8*
-ieee80211_get_bssid(struct ieee80211_hdr *hdr, int len)
+ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len)
 {
 	__le16 fc;
 
@@ -99,7 +100,7 @@
 
 /* from mac80211/ieee80211_sta.c, modified */
 void
-ieee802_11_parse_elems(unsigned char *start, int len, struct packet_info *pkt)
+ieee802_11_parse_elems(unsigned char *start, size_t len, struct packet_info *pkt)
 {
 	int left = len;
 	unsigned char *pos = start;
diff --exclude='.git*' -Nur horst-2.0-rc1/ieee80211_util.h horst-2008-07-13/ieee80211_util.h
--- horst-2.0-rc1/ieee80211_util.h	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/ieee80211_util.h	2008-07-13 10:54:53.000000000 +0200
@@ -25,7 +25,7 @@
 ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);
 
 void
-ieee802_11_parse_elems(unsigned char *start, int len, struct packet_info *pkt);
+ieee802_11_parse_elems(unsigned char *start, size_t len, struct packet_info *pkt);
 
 int
 ieee80211_frame_duration(int phymode, size_t len,
diff --exclude='.git*' -Nur horst-2.0-rc1/listsort.c horst-2008-07-13/listsort.c
--- horst-2.0-rc1/listsort.c	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/listsort.c	2008-07-13 10:54:53.000000000 +0200
@@ -1,16 +1,24 @@
-
-#include "list.h"
-
-/*
- * sorting a linked list.
+/* horst - olsr scanning tool
  *
- * The algorithm used is Mergesort, because that works really well
- * on linked lists, without requiring the O(N) extra space it needs
- * when you do it on arrays.
+ * Copyright (C) 2005-2008  Bruno Randolf
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *
+ * This is based on work under the following license:
  *
- */
-
-/*
  * This file is copyright 2001 Simon Tatham.
  *
  * Permission is hereby granted, free of charge, to any person
@@ -35,29 +43,36 @@
  * SOFTWARE.
  */
 
+#include "list.h"
+#include "listsort.h"
 
 /*
- * This is the actual sort function. Notice that it returns the new
- * head of the list. (It has to, because the head will not
- * generally be the same element after the sort.) So unlike sorting
- * an array, where you can do
- *
- *     sort(myarray);
+ * sorting a linked list.
  *
- * you now have to do
+ * The algorithm used is Mergesort, because that works really well
+ * on linked lists, without requiring the O(N) extra space it needs
+ * when you do it on arrays.
  *
- *     list = listsort(mylist);
  */
-struct list_head*
-listsort(struct list_head *list,
+
+
+/*
+ * This is the actual sort function.
+ * It assumes head to be a pointer to the first list element, and not beeing a
+ * list element itself (as common in the linux linked list implementation).
+ * If the first element moves, head is adjusted accordingly.
+ */
+void
+listsort(struct list_head *head,
 	int(*cmp)(const struct list_head*, const struct list_head*))
 {
-	struct list_head *p, *q, *e, *tail, *oldhead;
+	struct list_head *list, *p, *q, *e, *tail, *oldhead;
 	int insize, nmerges, psize, qsize, i;
 
-	if (!list)
-		return NULL;
+	if (!head || head->next == head)
+		return;
 
+	list = head->next;
 	insize = 1;
 
 	while (1)
@@ -77,7 +92,7 @@
 			psize = 0;
 			for (i = 0; i < insize; i++) {
 				psize++;
-				q = (q->next == oldhead ? NULL : q->next);
+				q = (q->next == oldhead || q->next == head ? NULL : q->next);
 				if (!q)
 					break;
 			}
@@ -92,20 +107,20 @@
 				if (psize == 0) {
 					/* p is empty; e must come from q. */
 					e = q; q = q->next; qsize--;
-					if (q == oldhead) q = NULL;
+					if (q == oldhead || q == head) q = NULL;
 				} else if (qsize == 0 || !q) {
 					/* q is empty; e must come from p. */
 					e = p; p = p->next; psize--;
-					if (p == oldhead) p = NULL;
+					if (p == oldhead || p == head) p = NULL;
 				} else if (cmp(p,q) <= 0) {
 					/* First element of p is lower (or same);
 					 * e must come from p. */
 					e = p; p = p->next; psize--;
-					if (p == oldhead) p = NULL;
+					if (p == oldhead || p == head) p = NULL;
 				} else {
 					/* First element of q is lower; e must come from q. */
 					e = q; q = q->next; qsize--;
-					if (q == oldhead) q = NULL;
+					if (q == oldhead || q == head) q = NULL;
 				}
 				/* add the next element to the merged list */
 				if (tail)
@@ -124,13 +139,20 @@
 		list->prev = tail;
 
 		/* If we have done only one merge, we're finished. */
-		if (nmerges <= 1)   /* allow for nmerges==0, the empty list case */
-			return list;
+		if (nmerges <= 1) {  /* allow for nmerges==0, the empty list case */
+			/* adjust head */
+			head->next = list;
+			head->prev = list->prev;
+			list->prev->next = head;
+			list->prev = head;
+			return;
+		}
 		/* Otherwise repeat, merging lists twice the size */
 		insize *= 2;
 	}
 }
 
+
 #if 0
 /*
  * Small test rig with three test orders. The list length 13 is
@@ -150,9 +172,12 @@
 {
 	struct element *ea = list_entry(a, struct element, list);
 	struct element *eb = list_entry(b, struct element, list);
+	//printf("  cmp %d - %d\n", ea->i, eb->i);
 	return ea->i - eb->i;
 }
 
+#if 0
+/* old outdated test */
 int main(void) {
 	#define n 13
 	struct element k[n], *head, *p;
@@ -212,3 +237,42 @@
 	return 0;
 }
 #endif
+
+int main(void)
+{
+	struct list_head lh;
+	struct element e[5];
+	struct element* ep;
+
+	INIT_LIST_HEAD(&lh);
+
+	e[0].i = 5;
+	e[1].i = 2;
+	e[2].i = 1;
+	e[3].i = 3;
+	e[4].i = 4;
+
+	list_add_tail(&e[0].list, &lh);
+	list_add_tail(&e[1].list, &lh);
+	list_add_tail(&e[2].list, &lh);
+	list_add_tail(&e[3].list, &lh);
+	list_add_tail(&e[4].list, &lh);
+
+	list_for_each_entry(ep, &lh, list) {
+		printf("%d ", ep->i);
+	}
+	printf("\n");
+
+	listsort(&lh, &elem_cmp);
+
+	list_for_each_entry(ep, &lh, list) {
+		printf("%d ", ep->i);
+		//printf("  [%p next %p prev %p]\n", &ep->list, ep->list.next, ep->list.prev);
+		if (ep->list.next->prev != &ep->list)
+			printf("* reverse link error!\n");
+	}
+	printf("\n");
+
+	return 0;
+}
+#endif
diff --exclude='.git*' -Nur horst-2.0-rc1/listsort.h horst-2008-07-13/listsort.h
--- horst-2.0-rc1/listsort.h	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/listsort.h	2008-07-13 10:54:53.000000000 +0200
@@ -1,9 +1,28 @@
+/* horst - olsr scanning tool
+ *
+ * Copyright (C) 2005-2008  Bruno Randolf
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
 #ifndef _LISTSORT_H
 #define _LISTSORT_H
 
 struct list_head;
 
-struct list_head*
+void
 listsort(struct list_head *list,
 	int(*cmp)(const struct list_head*, const struct list_head*));
 
diff --exclude='.git*' -Nur horst-2.0-rc1/main.c horst-2008-07-13/main.c
--- horst-2.0-rc1/main.c	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/main.c	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,7 +25,11 @@
 #include <signal.h>
 #include <sys/time.h>
 #include <time.h>
+#include <errno.h>
 #include <err.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include "protocol_parser.h"
 #include "display.h"
@@ -36,17 +40,6 @@
 #include "ieee80211.h"
 #include "ieee80211_util.h"
 
-static void get_options(int argv, char** argc);
-static struct node_info* node_update(struct packet_info* pkt);
-static void check_ibss_split(struct packet_info* pkt, struct node_info* pkt_node);
-static int filter_packet(struct packet_info* pkt);
-static void update_history(struct packet_info* pkt);
-static void update_statistics(struct packet_info* pkt);
-static void write_to_file(struct packet_info* pkt);
-static inline void timeout_nodes(void);
-
-struct packet_info current_packet;
-
 struct list_head nodes;
 struct essid_meta_info essids;
 struct history hist;
@@ -59,6 +52,7 @@
 	.sleep_time		= SLEEP_TIME,
 	.filter_pkt		= 0xffffff,
 	.recv_buffer_size	= RECV_BUFFER_SIZE,
+	.port			= DEFAULT_PORT,
 };
 
 struct timeval the_time;
@@ -67,208 +61,18 @@
 static FILE* DF = NULL;
 static struct timeval last_nodetimeout;
 
+/*
+ * receive packet buffer
+ * size: max 80211 frame (2312) + space for prism2 header (144)
+ * or radiotap header (usually only 26) + some extra
+ */
+static unsigned char buffer[2312 + 200];
 
-int
-main(int argc, char** argv)
-{
-	unsigned char buffer[8192];
-	int len;
-	struct node_info* node;
-
-	get_options(argc, argv);
-
-	if (!conf.quiet)
-		printf("horst: using monitoring interface %s\n", conf.ifname);
-
-	signal(SIGINT, finish_all);
-
-	gettimeofday(&stats.stats_time, NULL);
-
-	mon = open_packet_socket(conf.ifname, sizeof(buffer), conf.recv_buffer_size);
-	if (mon < 0)
-		err(1, "couldn't open packet socket");
-
-	conf.arphrd = device_get_arptype();
-	if (conf.arphrd != ARPHRD_IEEE80211_PRISM &&
-	    conf.arphrd != ARPHRD_IEEE80211_RADIOTAP) {
-		printf("wrong monitor type. please use radiotap or prism2 headers\n");
-		exit(1);
-	}
-
-	if (conf.dumpfile != NULL) {
-		DF = fopen(conf.dumpfile, "w");
-		if (DF == NULL)
-			err(1, "couldn't open dump file");
-	}
-
-	INIT_LIST_HEAD(&essids.list);
-	INIT_LIST_HEAD(&nodes);
-
-	if (conf.rport)
-		net_init_socket(conf.rport);
-#if !DO_DEBUG
-	else {
-		init_display();
-	}
-#endif
-
-	while ((len = recv_packet(buffer, sizeof(buffer))))
-	{
-		handle_user_input();
-
-		if (conf.paused || len == -1) {
-			/*
-			 * no packet received or paused: just wait a few ms
-			 * if we wait too long here we will loose packets
-			 * if we don't sleep there will be 100% system load
-			 */
-			usleep(conf.sleep_time);
-			continue;
-		}
-#if DO_DEBUG
-		dump_packet(buffer, len);
-#endif
-		memset(&current_packet, 0, sizeof(current_packet));
-		if (!parse_packet(buffer, len)) {
-			DEBUG("parsing failed\n");
-			continue;
-		}
-
-		if (filter_packet(&current_packet))
-			continue;
-
-		gettimeofday(&the_time, NULL);
-
-		if (conf.dumpfile != NULL)
-			write_to_file(&current_packet);
-
-		node = node_update(&current_packet);
-
-		timeout_nodes();
-
-		update_history(&current_packet);
-		update_statistics(&current_packet);
-		check_ibss_split(&current_packet, node);
-
-		if (conf.rport) {
-			net_send_packet();
-			continue;
-		}
-#if !DO_DEBUG
-		update_display(&current_packet, node);
-#endif
-	}
-	/* will never */
-	return 0;
-}
-
-
-void
-get_options(int argc, char** argv)
-{
-	int c;
-	static int n;
-
-	while((c = getopt(argc, argv, "hqi:t:p:e:d:w:o:b:")) > 0) {
-		switch (c) {
-			case 'p':
-				conf.rport = atoi(optarg);
-				break;
-			case 'q':
-				conf.quiet = 1;
-				break;
-			case 'i':
-				conf.ifname = optarg;
-				break;
-			case 'o':
-				conf.dumpfile = optarg;
-				break;
-			case 't':
-				conf.node_timeout = atoi(optarg);
-				break;
-			case 'b':
-				conf.recv_buffer_size = atoi(optarg);
-				break;
-			case 's':
-				/* reserved for spectro meter */
-				break;
-			case 'd':
-				conf.display_interval = atoi(optarg);
-				break;
-			case 'w':
-				conf.sleep_time = atoi(optarg);
-				break;
-			case 'e':
-				if (n >= MAX_FILTERMAC)
-					break;
-				conf.do_macfilter = 1;
-				convert_string_to_mac(optarg, conf.filtermac[n]);
-				printf("%s\n", ether_sprintf(conf.filtermac[n]));
-				n++;
-				break;
-			case 'h':
-			default:
-				printf("usage: %s [-h] [-q] [-i interface] [-t sec] [-p port] [-e mac] [-d usec] [-w usec] [-o file]\n\n"
-					"Options (default value)\n"
-					"  -h\t\tthis help\n"
-					"  -q\t\tquiet [basically useless]\n"
-					"  -i <intf>\tinterface (wlan0)\n"
-					"  -t <sec>\tnode timeout (60)\n"
-					"  -p <port>\tuse port\n"
-					"  -e <mac>\tfilter all macs ecxept this\n"
-					"  -d <usec>\tdisplay update interval (100000 = 100ms = 10fps)\n"
-					"  -w <usec>\twait loop (1000 = 1ms)\n"
-					"  -o <filename>\twrite packet info into file\n"
-					"  -b <bytes>\treceive buffer size (6750000)\n"
-					"\n",
-					argv[0]);
-				exit(0);
-				break;
-		}
-	}
-}
-
-
-void
-free_lists(void)
-{
-	struct essid_info *e, *f;
-	struct node_info *ni, *mi;
-
-	/* free node list */
-	list_for_each_entry_safe(ni, mi, &nodes, list) {
-		DEBUG("free node %s\n", ether_sprintf(ni->last_pkt.wlan_src));
-		list_del(&ni->list);
-		free(ni);
-	}
-
-	/* free essids */
-	list_for_each_entry_safe(e, f, &essids.list, list) {
-		DEBUG("free essid '%s'\n", e->essid);
-		list_del(&e->list);
-		free(e);
-	}
-}
-
-
-void
-finish_all(int sig)
-{
-	free_lists();
-
-	close_packet_socket();
-	
-	if (DF != NULL)
-		fclose(DF);
-
-#if !DO_DEBUG
-	if (conf.rport)
-		net_finish();
-	else
-		finish_display(sig);
-#endif
-	exit(0);
-}
+/* for select */
+static fd_set read_fds;
+static fd_set write_fds;
+static fd_set excpt_fds;
+static struct timeval tv;
 
 
 static void
@@ -290,8 +94,9 @@
 	if (p->pkt_types & PKT_TYPE_OLSR)
 		n->olsr_count++;
 	if (p->wlan_bssid[0] != 0xff &&
-		! (p->wlan_bssid[0] == 0 && p->wlan_bssid[1] == 0 && p->wlan_bssid[2] == 0 &&
-		   p->wlan_bssid[3] == 0 && p->wlan_bssid[4] == 0 && p->wlan_bssid[5] == 0)) {
+	    !(p->wlan_bssid[0] == 0 && p->wlan_bssid[1] == 0 &&
+	      p->wlan_bssid[2] == 0 && p->wlan_bssid[3] == 0 &&
+	      p->wlan_bssid[4] == 0 && p->wlan_bssid[5] == 0)) {
 		memcpy(n->wlan_bssid, p->wlan_bssid, MAC_LEN);
 	}
 	if ((p->wlan_type & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
@@ -316,8 +121,9 @@
 {
 	struct node_info* n;
 
-	if (pkt->wlan_src[0] == 0 && pkt->wlan_src[1] == 0 && pkt->wlan_src[2] == 0 &&
-	    pkt->wlan_src[3] == 0 && pkt->wlan_src[4] == 0 && pkt->wlan_src[5] == 0) {
+	if (pkt->wlan_src[0] == 0 && pkt->wlan_src[1] == 0 &&
+	    pkt->wlan_src[2] == 0 && pkt->wlan_src[3] == 0 &&
+	    pkt->wlan_src[4] == 0 && pkt->wlan_src[5] == 0) {
 		return NULL;
 	}
 
@@ -364,8 +170,9 @@
 			n, ether_sprintf(n->last_pkt.wlan_src));
 		DEBUG(" bssid %s\n", ether_sprintf(n->wlan_bssid));
 
-		if (n->wlan_mode == WLAN_MODE_AP)
+		if (n->wlan_mode == WLAN_MODE_AP) {
 			continue;
+		}
 
 		if (last_bssid && memcmp(last_bssid, n->wlan_bssid, MAC_LEN) != 0) {
 			e->split = 1;
@@ -414,7 +221,7 @@
 
 	/* only check beacons (XXX: what about PROBE?) */
 	if (!((pkt->wlan_type & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
-	     (pkt->wlan_type & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)) {
+	      (pkt->wlan_type & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)) {
 		return;
 	}
 
@@ -442,8 +249,9 @@
 	}
 
 	/* if node had another essid before, remove it there */
-	if (pkt_node->essid != NULL && pkt_node->essid != e)
+	if (pkt_node->essid != NULL && pkt_node->essid != e) {
 		remove_node_from_essid(pkt_node);
+	}
 
 	/* new node */
 	if (pkt_node->essid == NULL) {
@@ -463,8 +271,9 @@
 {
 	int i;
 
-	if (conf.filter_off)
+	if (conf.filter_off) {
 		return 0;
+	}
 
 	if (!(pkt->pkt_types & conf.filter_pkt)) {
 		stats.filtered_packets++;
@@ -472,15 +281,16 @@
 	}
 
 	if (MAC_NOT_EMPTY(conf.filterbssid) &&
-	    memcmp(current_packet.wlan_bssid, conf.filterbssid, MAC_LEN) != 0) {
+	    memcmp(pkt->wlan_bssid, conf.filterbssid, MAC_LEN) != 0) {
 		stats.filtered_packets++;
 		return 1;
 	}
 
 	if (conf.do_macfilter) {
 		for (i = 0; i < MAX_FILTERMAC; i++) {
-			if (memcmp(current_packet.wlan_src, conf.filtermac[i], MAC_LEN) == 0)
+			if (memcmp(pkt->wlan_src, conf.filtermac[i], MAC_LEN) == 0) {
 				return 0;
+			}
 		}
 		stats.filtered_packets++;
 		return 1;
@@ -492,16 +302,18 @@
 static void
 update_history(struct packet_info* p)
 {
-	if (p->signal == 0)
+	if (p->signal == 0) {
 		return;
+	}
 
 	hist.signal[hist.index] = p->signal;
 	hist.noise[hist.index] = p->noise;
 	hist.rate[hist.index] = p->rate;
 	hist.type[hist.index] = p->wlan_type;
 	hist.index++;
-	if (hist.index == MAX_HISTORY)
+	if (hist.index == MAX_HISTORY) {
 		hist.index = 0;
+	}
 }
 
 
@@ -509,6 +321,11 @@
 update_statistics(struct packet_info* p)
 {
 	int duration;
+
+	if (p->rate == 0) {
+		return;
+	}
+
 	duration = ieee80211_frame_duration(p->phy_flags & PHY_FLAG_MODE_MASK,
 			p->len, p->rate * 5, p->phy_flags & PHY_FLAG_SHORTPRE);
 
@@ -539,7 +356,7 @@
 	fprintf(DF, "%s, ", ether_sprintf(pkt->wlan_bssid));
 	fprintf(DF, "%x, %d, %d, %d, %d, %d, ",
 		pkt->pkt_types, pkt->signal, pkt->noise, pkt->snr, pkt->len, pkt->rate);
-	fprintf(DF, "%016llx, ", pkt->wlan_tsf);
+	fprintf(DF, "%016llx, ", (unsigned long long)pkt->wlan_tsf);
 	fprintf(DF, "%s, %d, %d, %d, ",
 		pkt->wlan_essid, pkt->wlan_mode, pkt->wlan_channel, pkt->wlan_wep);
 	fprintf(DF, "%s, ", ip_sprintf(pkt->ip_src));
@@ -548,25 +365,260 @@
 }
 
 
-static inline void
+static void
 timeout_nodes(void)
 {
 	struct node_info *n, *m;
 
-	if ((the_time.tv_sec - last_nodetimeout.tv_sec) < conf.node_timeout )
+	if ((the_time.tv_sec - last_nodetimeout.tv_sec) < conf.node_timeout ) {
 		return;
+	}
 
 	list_for_each_entry_safe(n, m, &nodes, list) {
 		if (n->last_seen < (the_time.tv_sec - conf.node_timeout)) {
 			list_del(&n->list);
-			if (n->essid != NULL)
+			if (n->essid != NULL) {
 				remove_node_from_essid(n);
+			}
 			free(n);
 		}
 	}
 	last_nodetimeout = the_time;
 }
 
+
+static void
+handle_packet(struct packet_info* pkt)
+{
+	struct node_info* node;
+
+	if (conf.port && cli_fd != -1) {
+		net_send_packet(pkt);
+	}
+	if (conf.dumpfile != NULL) {
+		write_to_file(pkt);
+	}
+	if (conf.quiet || conf.paused) {
+		return;
+	}
+
+	/* in display mode */
+	if (filter_packet(pkt)) {
+		return;
+	}
+
+	node = node_update(pkt);
+	update_history(pkt);
+	update_statistics(pkt);
+	check_ibss_split(pkt, node);
+
+#if !DO_DEBUG
+	update_display(pkt, node);
+#endif
+}
+
+
+static void
+receive_packet(unsigned char* buffer, int len)
+{
+	struct packet_info current_packet;
+
+#if DO_DEBUG
+	dump_packet(buffer, len);
+#endif
+	memset(&current_packet, 0, sizeof(current_packet));
+
+	if (!conf.serveraddr) {
+		/* local capture */
+		if (!parse_packet(buffer, len, &current_packet)) {
+			DEBUG("parsing failed\n");
+			return;
+		}
+	}
+	else {
+		/* client mode - receiving pre-parsed from server */
+		if (!net_receive_packet(buffer, len, &current_packet)) {
+			DEBUG("receive failed\n");
+			return;
+		}
+	}
+
+	handle_packet(&current_packet);
+}
+
+
+static void
+receive_any(void)
+{
+	int ret, len, mfd;
+
+	FD_ZERO(&read_fds);
+	FD_ZERO(&write_fds);
+	FD_ZERO(&excpt_fds);
+
+	FD_SET(0, &read_fds);
+	FD_SET(mon, &read_fds);
+	if (srv_fd != -1) {
+		FD_SET(srv_fd, &read_fds);
+	}
+	tv.tv_sec = 0;
+	tv.tv_usec = conf.sleep_time;
+	mfd = max(mon, srv_fd) + 1;
+
+	ret = select(mfd, &read_fds, &write_fds, &excpt_fds, &tv);
+	if (ret == -1 && errno == EINTR) { /* interrupted */
+		return;
+	}
+	if (ret == 0) { /* timeout */
+		return;
+	}
+	if (ret < 0) {
+		err(1, "select()");
+	}
+
+	/* stdin */
+	if (FD_ISSET(0, &read_fds)) {
+		handle_user_input();
+	}
+
+	/* packet */
+	if (FD_ISSET(mon, &read_fds)) {
+		len = recv_packet(mon, buffer, sizeof(buffer));
+		receive_packet(buffer, len);
+	}
+
+	/* server */
+	if (srv_fd != -1 && FD_ISSET(srv_fd, &read_fds)) {
+		net_handle_server_conn();
+	}
+}
+
+
+static void
+sigpipe_handler(int sig)
+{
+	/* ignore signal here - we will handle it after write failed */
+}
+
+
+static void
+get_options(int argc, char** argv)
+{
+	int c;
+	static int n;
+
+	while((c = getopt(argc, argv, "hqi:t:p:e:d:w:o:b:c:")) > 0) {
+		switch (c) {
+		case 'p':
+			conf.port = optarg;
+			break;
+		case 'q':
+			conf.quiet = 1;
+			break;
+		case 'i':
+			conf.ifname = optarg;
+			break;
+		case 'o':
+			conf.dumpfile = optarg;
+			break;
+		case 't':
+			conf.node_timeout = atoi(optarg);
+			break;
+		case 'b':
+			conf.recv_buffer_size = atoi(optarg);
+			break;
+		case 's':
+			/* reserved for spectro meter */
+			break;
+		case 'd':
+			conf.display_interval = atoi(optarg);
+			break;
+		case 'w':
+			conf.sleep_time = atoi(optarg);
+			break;
+		case 'e':
+			if (n >= MAX_FILTERMAC)
+				break;
+			conf.do_macfilter = 1;
+			convert_string_to_mac(optarg, conf.filtermac[n]);
+			printf("%s\n", ether_sprintf(conf.filtermac[n]));
+			n++;
+			break;
+		case 'c':
+			conf.serveraddr = optarg;
+			break;
+		case 'h':
+		default:
+			printf("usage: %s [-h] [-q] [-i interface] [-t sec] [-p port] [-e mac] [-d usec] [-w usec] [-o file]\n\n"
+				"Options (default value)\n"
+				"  -h\t\tthis help\n"
+				"  -q\t\tquiet [basically useless]\n"
+				"  -i <intf>\tinterface (wlan0)\n"
+				"  -t <sec>\tnode timeout (60)\n"
+				"  -c <IP>\tconnect to server\n"
+				"  -p <port>\tuse port (4444)\n"
+				"  -e <mac>\tfilter all macs ecxept this\n"
+				"  -d <usec>\tdisplay update interval (100000 = 100ms = 10fps)\n"
+				"  -w <usec>\twait loop (1000 = 1ms)\n"
+				"  -o <filename>\twrite packet info into file\n"
+				"  -b <bytes>\treceive buffer size (6750000)\n"
+				"\n",
+				argv[0]);
+			exit(0);
+			break;
+		}
+	}
+}
+
+
+void
+free_lists(void)
+{
+	struct essid_info *e, *f;
+	struct node_info *ni, *mi;
+
+	/* free node list */
+	list_for_each_entry_safe(ni, mi, &nodes, list) {
+		DEBUG("free node %s\n", ether_sprintf(ni->last_pkt.wlan_src));
+		list_del(&ni->list);
+		free(ni);
+	}
+
+	/* free essids */
+	list_for_each_entry_safe(e, f, &essids.list, list) {
+		DEBUG("free essid '%s'\n", e->essid);
+		list_del(&e->list);
+		free(e);
+	}
+}
+
+
+void
+finish_all(int sig)
+{
+	free_lists();
+
+	if (!conf.serveraddr) {
+		close_packet_socket();
+	}
+
+	if (DF != NULL) {
+		fclose(DF);
+	}
+
+#if !DO_DEBUG
+	if (conf.port) {
+		net_finish();
+	}
+
+	if (!conf.quiet) {
+		finish_display(sig);
+	}
+#endif
+	exit(0);
+}
+
+
 #if 0
 void print_rate_duration_table(void)
 {
@@ -607,3 +659,59 @@
 	}
 }
 #endif
+
+
+int
+main(int argc, char** argv)
+{
+	INIT_LIST_HEAD(&essids.list);
+	INIT_LIST_HEAD(&nodes);
+
+	get_options(argc, argv);
+
+	signal(SIGINT, finish_all);
+	signal(SIGPIPE, sigpipe_handler);
+
+	gettimeofday(&stats.stats_time, NULL);
+
+	if (conf.serveraddr) {
+		mon = net_open_client_socket(conf.serveraddr, conf.port);
+	}
+	else {
+		mon = open_packet_socket(conf.ifname, sizeof(buffer), conf.recv_buffer_size);
+		if (mon < 0) {
+			err(1, "couldn't open packet socket");
+		}
+		conf.arphrd = device_get_arptype();
+		if (conf.arphrd != ARPHRD_IEEE80211_PRISM &&
+		conf.arphrd != ARPHRD_IEEE80211_RADIOTAP) {
+			printf("wrong monitor type. please use radiotap or prism2 headers\n");
+			exit(1);
+		}
+	}
+
+	if (conf.dumpfile != NULL) {
+		DF = fopen(conf.dumpfile, "w");
+		if (DF == NULL) {
+			err(1, "couldn't open dump file");
+		}
+	}
+
+	if (!conf.serveraddr && conf.port) {
+		net_init_server_socket(conf.port);
+	}
+#if !DO_DEBUG
+	if (!conf.quiet) {
+		init_display();
+	}
+#endif
+
+	for ( /* ever*/ ;;)
+	{
+		receive_any();
+		gettimeofday(&the_time, NULL);
+		timeout_nodes();
+	}
+	/* will never */
+	return 0;
+}
diff --exclude='.git*' -Nur horst-2.0-rc1/main.h horst-2008-07-13/main.h
--- horst-2.0-rc1/main.h	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/main.h	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -34,7 +34,7 @@
 #define MAX_ESSIDS		255
 #define MAX_BSSIDS		255
 #define MAX_HISTORY		255
-#define MAX_ESSID_LEN		255
+#define MAX_ESSID_LEN		32
 #define MAX_RATES		109	/* in 500kbps steps: 54 * 2 + 1 for array index */
 #define MAX_FSTYPE		0xff
 #define MAX_FILTERMAC		9
@@ -80,14 +80,14 @@
 #define PHY_FLAG_G		0x0040
 #define PHY_FLAG_MODE_MASK	0x00f0
 
-/* default config vlaues */
+/* default config values */
 #define INTERFACE_NAME		"wlan0"
 #define NODE_TIMEOUT		60	/* seconds */
 /* update display every 100ms - "10 frames per sec should be enough for everyone" ;) */
 #define DISPLAY_UPDATE_INTERVAL 100000	/* usec */
 #define SLEEP_TIME		1000	/* usec */
-#define RECV_BUFFER_SIZE	6750000 /* 54Mbps in byte */
-
+#define RECV_BUFFER_SIZE	6750000	/* 54Mbps in byte */
+#define DEFAULT_PORT		"4444"	/* string because of getaddrinfo() */
 
 #ifndef ARPHRD_IEEE80211_RADIOTAP
 #define ARPHRD_IEEE80211_RADIOTAP 803    /* IEEE 802.11 + radiotap header */
@@ -116,7 +116,7 @@
 	unsigned char		wlan_src[MAC_LEN];
 	unsigned char		wlan_dst[MAC_LEN];
 	unsigned char		wlan_bssid[MAC_LEN];
-	char			wlan_essid[255];
+	char			wlan_essid[MAX_ESSID_LEN];
 	u_int64_t		wlan_tsf;	/* timestamp from beacon */
 	int			wlan_mode;	/* AP, STA or IBSS */
 	unsigned char		wlan_channel;	/* channel from beacon, probe */
@@ -217,18 +217,19 @@
 
 struct config {
 	char*			ifname;
-	int			rport;
+	char*			port;
 	int			quiet;
 	int			node_timeout;
 	int			display_interval;
 	int			sleep_time;
 	char*			dumpfile;
 	int			recv_buffer_size;
+	char*			serveraddr;
 
 	unsigned char		filtermac[MAX_FILTERMAC][MAC_LEN];
 	unsigned char		filterbssid[MAC_LEN];
 	int			filter_pkt;
-	int			filter_off:1,
+	unsigned int		filter_off:1,
 				do_macfilter:1;
 
 	/* this isn't exactly config, but wtf... */
diff --exclude='.git*' -Nur horst-2.0-rc1/Makefile horst-2008-07-13/Makefile
--- horst-2.0-rc1/Makefile	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/Makefile	2008-07-13 10:54:53.000000000 +0200
@@ -21,7 +21,7 @@
 PCAP=0
 OBJS=protocol_parser.o main.o capture.o display.o network.o util.o ieee80211_util.o listsort.o
 LIBS=-lncurses
-CFLAGS+=-Wall -DDO_DEBUG=$(DEBUG) #-g
+CFLAGS+=-Wall -DDO_DEBUG=$(DEBUG) -g
 
 ifeq ($(PCAP),1)
 CFLAGS+=-DPCAP
diff --exclude='.git*' -Nur horst-2.0-rc1/network.c horst-2008-07-13/network.c
--- horst-2.0-rc1/network.c	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/network.c	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,77 +23,195 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
 #include <err.h>
 
 #include "main.h"
 #include "util.h"
+#include "network.h"
 
 extern struct config conf;
 
-struct sockaddr_in sock_in, cin;
-socklen_t cinlen;
-int srv_fd=0;
-int cli_fd=0;
-int i;
-fd_set rs;
-char line[256];
-int llen;
-struct timeval to={0,0};
-struct timeval tr={0,100};
-int on = 1;
+int srv_fd = -1;
+int cli_fd = -1;
+static int netmon_fd;
+
+struct net_packet_info {
+	/* general */
+	int			pkt_types;	/* bitmask of packet types in this pkt */
+	int			len;		/* packet length */
+
+	/* wlan phy (from radiotap) */
+	int			signal;		/* signal strength (usually dBm) */
+	int			noise;		/* noise level (usually dBm) */
+	int			snr;		/* signal to noise ratio */
+	int			rate;		/* physical rate */
+	int			phy_freq;	/* frequency (unused) */
+	int			phy_flags;	/* A, B, G, shortpre */
+
+	/* wlan mac */
+	int			wlan_type;	/* frame control field */
+	unsigned char		wlan_src[MAC_LEN];
+	unsigned char		wlan_dst[MAC_LEN];
+	unsigned char		wlan_bssid[MAC_LEN];
+	char			wlan_essid[MAX_ESSID_LEN];
+	u_int64_t		wlan_tsf;	/* timestamp from beacon */
+	int			wlan_mode;	/* AP, STA or IBSS */
+	unsigned char		wlan_channel;	/* channel from beacon, probe */
+	int			wlan_wep;	/* WEP on/off */
+
+	/* IP */
+	unsigned int		ip_src;
+	unsigned int		ip_dst;
+	int			olsr_type;
+	int			olsr_neigh;
+	int			olsr_tc;
+} __attribute__ ((packed));
 
 
 void
-net_init_socket(int rport)
+net_init_server_socket(char* rport)
 {
-	if (!conf.quiet)
-		printf("using remote port %d\n",rport);
+	struct sockaddr_in sock_in;
+	int reuse = 1;
 
-	sock_in.sin_family=AF_INET;
-	sock_in.sin_port=htons(rport);
-	sock_in.sin_addr.s_addr=htonl(INADDR_ANY);
+	printf("using server port %s\n", rport);
 
-	if ((srv_fd=socket(AF_INET,SOCK_STREAM,0)) < 0) {
+	sock_in.sin_family = AF_INET;
+	sock_in.sin_addr.s_addr = htonl(INADDR_ANY);
+	sock_in.sin_port = htons(atoi(rport));
+
+	if ((srv_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 		err(1, "socket");
 	}
-	if (setsockopt(srv_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
+
+	if (setsockopt(srv_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
 		err(1, "setsockopt SO_REUSEADDR");
 	}
+
 	if (bind(srv_fd, (struct sockaddr*)&sock_in, sizeof(sock_in)) < 0) {
 		err(1, "bind");
 	}
-	if (listen(srv_fd, 5) < 0) {
+
+	if (listen(srv_fd, 0) < 0) {
 		err(1, "listen");
 	}
 }
 
 
 int
-net_send_packet(void)
+net_send_packet(struct packet_info *pkt)
 {
-	struct node_info* n;
-	FD_ZERO(&rs);
-	FD_SET(srv_fd,&rs);
-	if (select(srv_fd+1,&rs,NULL,NULL,&to) && FD_ISSET(srv_fd,&rs))
-	{
-		cli_fd = accept(srv_fd,(struct sockaddr*)&cin,&cinlen);
-		if (!conf.quiet)
-			printf("horst: accepting client\n");
-		if (!cli_fd)
-			return -1;
-
-		// discard stuff which was sent to us e.g. by a http client
-		FD_ZERO(&rs);
-		FD_SET(cli_fd,&rs);
-		while (select(cli_fd+1,&rs,NULL,NULL,&tr) && FD_ISSET(cli_fd,&rs)) {
-			read(cli_fd,line,sizeof(line));
-			FD_ZERO(&rs);
-			FD_SET(cli_fd,&rs);
+	int ret;
+	struct net_packet_info np;
+
+	np.pkt_types	= pkt->pkt_types;
+	np.len		= pkt->len;
+	np.signal	= pkt->signal;
+	np.noise	= pkt->noise;
+	np.snr		= pkt->snr;
+	np.rate		= pkt->rate;
+	np.phy_freq	= pkt->phy_freq;
+	np.phy_flags	= pkt->phy_flags;
+	np.wlan_type	= pkt->wlan_type;
+	np.wlan_tsf	= pkt->wlan_tsf;
+	np.wlan_mode	= pkt->wlan_mode;
+	np.wlan_channel = pkt->wlan_channel;
+	np.wlan_wep	= pkt->wlan_wep;
+	np.ip_src	= pkt->ip_src;
+	np.ip_dst	= pkt->ip_dst;
+	np.olsr_type	= pkt->olsr_type;
+	np.olsr_neigh	= pkt->olsr_neigh;
+	np.olsr_tc	= pkt->olsr_tc;
+	memcpy(np.wlan_src, pkt->wlan_src, MAC_LEN);
+	memcpy(np.wlan_dst, pkt->wlan_dst, MAC_LEN);
+	memcpy(np.wlan_bssid, pkt->wlan_bssid, MAC_LEN);
+	memcpy(np.wlan_essid, pkt->wlan_essid, MAX_ESSID_LEN);
+
+	ret = write(cli_fd, &np, sizeof(np));
+	if (ret == -1) {
+		if (errno == EPIPE) {
+			printf("client has closed\n");
+			close(cli_fd);
+			cli_fd = -1;
+		}
+		else {
+			perror("write");
 		}
+	}
+	return 0;
+}
+
+
+/*
+ * return 0 - error
+ *	  1 - ok
+ */
+int
+net_receive_packet(unsigned char *buffer, int len, struct packet_info *pkt)
+{
+	struct net_packet_info *np;
+
+	if (len < sizeof(struct net_packet_info)) {
+		return 0;
+	}
+
+	np = (struct net_packet_info *)buffer;
+
+	if (np->rate == 0) {
+		return 0;
+	}
+
+	pkt->pkt_types	= np->pkt_types;
+	pkt->len	= np->len;
+	pkt->signal	= np->signal;
+	pkt->noise	= np->noise;
+	pkt->snr	= np->snr;
+	pkt->rate	= np->rate;
+	pkt->phy_freq	= np->phy_freq;
+	pkt->phy_flags	= np->phy_flags;
+	pkt->wlan_type	= np->wlan_type;
+	pkt->wlan_tsf	= np->wlan_tsf;
+	pkt->wlan_mode	= np->wlan_mode;
+	pkt->wlan_channel = np->wlan_channel;
+	pkt->wlan_wep	= np->wlan_wep;
+	pkt->ip_src	= np->ip_src;
+	pkt->ip_dst	= np->ip_dst;
+	pkt->olsr_type	= np->olsr_type;
+	pkt->olsr_neigh	= np->olsr_neigh;
+	pkt->olsr_tc	= np->olsr_tc;
+	memcpy(pkt->wlan_src, np->wlan_src, MAC_LEN);
+	memcpy(pkt->wlan_dst, np->wlan_dst, MAC_LEN);
+	memcpy(pkt->wlan_bssid, np->wlan_bssid, MAC_LEN);
+	memcpy(pkt->wlan_essid, np->wlan_essid, MAX_ESSID_LEN);
+
+	return 1;
+}
+
+
+int net_handle_server_conn( void )
+{
+	struct sockaddr_in cin;
+	socklen_t cinlen;
+
+	if (cli_fd != -1) {
+		printf("can only handle one client\n");
+		return -1;
+	}
+
+	cli_fd = accept(srv_fd, (struct sockaddr*)&cin, &cinlen);
 
+	printf("horst: accepting client\n");
+
+	//read(cli_fd,line,sizeof(line));
+	return 0;
+}
+
+#if 0
 		// satisfy http clients (wget)
 		static const char hdr[]="HTTP/1.0 200 ok\r\nContent-Type: text/plain\r\n\r\n";
-		write (cli_fd,hdr,sizeof(hdr));
+ 		write (cli_fd,hdr,sizeof(hdr));
 		list_for_each_entry(n, &nodes, list) {
 			char src_eth[18];
 			strcpy(src_eth,ether_sprintf(n->last_pkt.wlan_src));
@@ -110,13 +228,68 @@
 				n->tsf);
 			write(cli_fd,line,llen);
 		}
-		close(cli_fd);
+#endif
+
+
+int
+net_open_client_socket(char* serveraddr, char* rport)
+{
+	struct addrinfo saddr;
+	struct addrinfo *result, *rp;
+	int ret;
+
+	printf("connecting to server %s port %s\n", serveraddr, rport);
+
+	/* Obtain address(es) matching host/port */
+	memset(&saddr, 0, sizeof(struct addrinfo));
+	saddr.ai_family = AF_INET;
+	saddr.ai_socktype = SOCK_STREAM;
+	saddr.ai_flags = 0;
+	saddr.ai_protocol = 0;
+
+	ret = getaddrinfo(serveraddr, rport, &saddr, &result);
+	if (ret != 0) {
+		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
+		exit(EXIT_FAILURE);
 	}
-	return 0;
+
+	/* getaddrinfo() returns a list of address structures.
+	   Try each address until we successfully connect. */
+	for (rp = result; rp != NULL; rp = rp->ai_next) {
+		netmon_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+		if (netmon_fd == -1) {
+			continue;
+		}
+
+		if (connect(netmon_fd, rp->ai_addr, rp->ai_addrlen) != -1) {
+			break; /* Success */
+		}
+
+		close(netmon_fd);
+	}
+
+	if (rp == NULL) {
+		/* No address succeeded */
+		freeaddrinfo(result);
+		err(1, "could not connect");
+	}
+
+	freeaddrinfo(result);
+
+	printf("connected\n");
+	return netmon_fd;
 }
 
 
 void
 net_finish(void) {
-	close(srv_fd);
+	if (srv_fd != -1) {
+		close(srv_fd);
+	}
+	if (cli_fd != -1) {
+		close(cli_fd);
+	}
+	if (netmon_fd) {
+		close(netmon_fd);
+	}
 }
diff --exclude='.git*' -Nur horst-2.0-rc1/network.h horst-2008-07-13/network.h
--- horst-2.0-rc1/network.h	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/network.h	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -20,11 +20,24 @@
 #ifndef _PROTOCOL_NETWORK_H_
 #define _PROTOCOL_NETWORK_H_
 
+struct packet_info;
+
+extern int srv_fd;
+extern int cli_fd;
+
+void
+net_init_server_socket(char* rport);
+
+int net_handle_server_conn(void);
+
+int
+net_send_packet(struct packet_info *pkt);
+
 int
-net_init_socket(int rport);
+net_receive_packet(unsigned char* buffer, int len, struct packet_info *pkt);
 
 int
-net_send_packet(void);
+net_open_client_socket(char* server, char* rport);
 
 void
 net_finish(void);
diff --exclude='.git*' -Nur horst-2.0-rc1/protocol_parser.c horst-2008-07-13/protocol_parser.c
--- horst-2.0-rc1/protocol_parser.c	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/protocol_parser.c	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -35,27 +35,27 @@
 #include "main.h"
 #include "util.h"
 
-static int parse_prism_header(unsigned char** buf, int len);
-static int parse_radiotap_header(unsigned char** buf, int len);
-static int parse_80211_header(unsigned char** buf, int len);
-static int inline parse_llc(unsigned char** buf, int len);
-static int parse_ip_header(unsigned char** buf, int len);
-static int parse_udp_header(unsigned char** buf, int len);
-static int parse_olsr_packet(unsigned char** buf, int len);
-static int parse_batman_packet(unsigned char** buf, int len);
+static int parse_prism_header(unsigned char** buf, int len, struct packet_info* current_packet);
+static int parse_radiotap_header(unsigned char** buf, int len, struct packet_info* current_packet);
+static int parse_80211_header(unsigned char** buf, int len, struct packet_info* current_packet);
+static int parse_llc(unsigned char** buf, int len, struct packet_info* current_packet);
+static int parse_ip_header(unsigned char** buf, int len, struct packet_info* current_packet);
+static int parse_udp_header(unsigned char** buf, int len, struct packet_info* current_packet);
+static int parse_olsr_packet(unsigned char** buf, int len, struct packet_info* current_packet);
+static int parse_batman_packet(unsigned char** buf, int len, struct packet_info* current_packet);
 
 
 /* return 1 if we parsed enough = min ieee header */
 int
-parse_packet(unsigned char* buf, int len)
+parse_packet(unsigned char* buf, int len, struct packet_info* current_packet)
 {
 	if (conf.arphrd == ARPHRD_IEEE80211_PRISM) {
-		len = parse_prism_header(&buf, len);
+		len = parse_prism_header(&buf, len, current_packet);
 		if (len <= 0)
 			return 0;
 	}
 	else if (conf.arphrd == ARPHRD_IEEE80211_RADIOTAP) {
-		len = parse_radiotap_header(&buf, len);
+		len = parse_radiotap_header(&buf, len, current_packet);
 		if (len <= 0)
 			return 0;
 	}
@@ -64,22 +64,22 @@
 	    conf.arphrd == ARPHRD_IEEE80211_PRISM ||
 	    conf.arphrd == ARPHRD_IEEE80211_RADIOTAP) {
 		DEBUG("before parse 80211 len: %d\n", len);
-		len = parse_80211_header(&buf, len);
+		len = parse_80211_header(&buf, len, current_packet);
 		if (len < 0) /* couldnt parse */
 			return 0;
 		else if (len == 0)
 			return 1;
 	}
 
-	len = parse_llc(&buf, len);
+	len = parse_llc(&buf, len, current_packet);
 	if (len <= 0)
 		return 1;
 
-	len = parse_ip_header(&buf, len);
+	len = parse_ip_header(&buf, len, current_packet);
 	if (len <= 0)
 		return 1;
 
-	len = parse_udp_header(&buf, len);
+	len = parse_udp_header(&buf, len, current_packet);
 	if (len <= 0)
 		return 1;
 
@@ -88,7 +88,7 @@
 
 
 static int
-parse_prism_header(unsigned char** buf, int len)
+parse_prism_header(unsigned char** buf, int len, struct packet_info* current_packet)
 {
 	wlan_ng_prism2_header* ph;
 
@@ -106,53 +106,53 @@
 	*/
 	if (((int)ph->noise.data) < 0) {
 		/* new madwifi */
-		current_packet.signal = ph->signal.data;
-		current_packet.noise = ph->noise.data;
-		current_packet.snr = ph->rssi.data;
+		current_packet->signal = ph->signal.data;
+		current_packet->noise = ph->noise.data;
+		current_packet->snr = ph->rssi.data;
 	}
 	else if (((int)ph->rssi.data) < 0) {
 		/* broadcom hack */
-		current_packet.signal = ph->rssi.data;
-		current_packet.noise = -95;
-		current_packet.snr = 95 + ph->rssi.data;
+		current_packet->signal = ph->rssi.data;
+		current_packet->noise = -95;
+		current_packet->snr = 95 + ph->rssi.data;
 	}
 	else {
 		/* assume hostap */
-		current_packet.signal = ph->signal.data;
-		current_packet.noise = ph->noise.data;
-		current_packet.snr = ph->signal.data - ph->noise.data; //XXX rssi?
+		current_packet->signal = ph->signal.data;
+		current_packet->noise = ph->noise.data;
+		current_packet->snr = ph->signal.data - ph->noise.data; //XXX rssi?
 	}
 
-	current_packet.rate = ph->rate.data;
+	current_packet->rate = ph->rate.data;
 
 	/* just in case...*/
-	if (current_packet.snr < 0)
-		current_packet.snr = -current_packet.snr;
-	if (current_packet.snr > 99)
-		current_packet.snr = 99;
-	if (current_packet.rate == 0 || current_packet.rate > 108) {
+	if (current_packet->snr < 0)
+		current_packet->snr = -current_packet->snr;
+	if (current_packet->snr > 99)
+		current_packet->snr = 99;
+	if (current_packet->rate == 0 || current_packet->rate > 108) {
 		/* assume min rate, guess mode from channel */
 		DEBUG("*** fixing wrong rate\n");
 		if (ph->channel.data > 14)
-			current_packet.rate = 12; /* 6 * 2 */
+			current_packet->rate = 12; /* 6 * 2 */
 		else
-			current_packet.rate = 2; /* 1 * 2 */
+			current_packet->rate = 2; /* 1 * 2 */
 	}
 
 	/* guess phy mode */
 	if (ph->channel.data > 14)
-		current_packet.phy_flags |= PHY_FLAG_A;
+		current_packet->phy_flags |= PHY_FLAG_A;
 	else
-		current_packet.phy_flags |= PHY_FLAG_G;
+		current_packet->phy_flags |= PHY_FLAG_G;
 	/* always assume shortpre */
-	current_packet.phy_flags |= PHY_FLAG_SHORTPRE;
+	current_packet->phy_flags |= PHY_FLAG_SHORTPRE;
 
 	DEBUG("devname: %s\n", ph->devname);
-	DEBUG("signal: %d -> %d\n", ph->signal.data, current_packet.signal);
-	DEBUG("noise: %d -> %d\n", ph->noise.data, current_packet.noise);
+	DEBUG("signal: %d -> %d\n", ph->signal.data, current_packet->signal);
+	DEBUG("noise: %d -> %d\n", ph->noise.data, current_packet->noise);
 	DEBUG("rate: %d\n", ph->rate.data);
 	DEBUG("rssi: %d\n", ph->rssi.data);
-	DEBUG("*** SNR %d\n", current_packet.snr);
+	DEBUG("*** SNR %d\n", current_packet->snr);
 
 	*buf = *buf + sizeof(wlan_ng_prism2_header);
 	return len - sizeof(wlan_ng_prism2_header);
@@ -160,7 +160,7 @@
 
 
 static int
-parse_radiotap_header(unsigned char** buf, int len)
+parse_radiotap_header(unsigned char** buf, int len, struct packet_info* current_packet)
 {
 	struct ieee80211_radiotap_header* rh;
 	__le32 present; /* the present bitmap */
@@ -178,6 +178,7 @@
 	b = *buf + sizeof(struct ieee80211_radiotap_header);
 	present = rh->it_present;
 
+	DEBUG("radiotap header len: %d\n", rh->it_len);
 	DEBUG("%08x\n", present);
 
 	/* check for header extension - ignore for now, just advance current position */
@@ -222,29 +223,29 @@
 				/* we are only interrested in these: */
 				case IEEE80211_RADIOTAP_RATE:
 					DEBUG("[rate %0x]", *b);
-					current_packet.rate = (*b);
+					current_packet->rate = (*b);
 					b++;
 					break;
 				case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
 					DEBUG("[sig %0x]", *b);
-					current_packet.signal = *(char*)b;
+					current_packet->signal = *(char*)b;
 					b++;
 					break;
 				case IEEE80211_RADIOTAP_DBM_ANTNOISE:
 					DEBUG("[noi %0x]", *b);
-					current_packet.noise = *(char*)b;
+					current_packet->noise = *(char*)b;
 					b++;
 					break;
 				case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
 					DEBUG("[snr %0x]", *b);
-					current_packet.snr = *b;
+					current_packet->snr = *b;
 					b++;
 					break;
 				case IEEE80211_RADIOTAP_FLAGS:
 					/* short preamble */
 					DEBUG("[flags %0x", *b);
 					if (*b & IEEE80211_RADIOTAP_F_SHORTPRE) {
-						current_packet.phy_flags |= PHY_FLAG_SHORTPRE;
+						current_packet->phy_flags |= PHY_FLAG_SHORTPRE;
 						DEBUG(" shortpre");
 					}
 					DEBUG("]");
@@ -252,19 +253,19 @@
 					break;
 				case IEEE80211_RADIOTAP_CHANNEL:
 					/* channel & channel type */
-					current_packet.phy_freq = *(u_int16_t*)b;
-					DEBUG("[chan %d ", current_packet.phy_freq);
+					current_packet->phy_freq = *(u_int16_t*)b;
+					DEBUG("[chan %d ", current_packet->phy_freq);
 					b = b + 2;
 					if (*(u_int16_t*)b & IEEE80211_CHAN_A) {
-						current_packet.phy_flags |= PHY_FLAG_A;
+						current_packet->phy_flags |= PHY_FLAG_A;
 						DEBUG("A]");
 					}
 					else if (*(u_int16_t*)b & IEEE80211_CHAN_G) {
-						current_packet.phy_flags |= PHY_FLAG_G;
+						current_packet->phy_flags |= PHY_FLAG_G;
 						DEBUG("G]");
 					}
 					else if (*(u_int16_t*)b & IEEE80211_CHAN_B) {
-						current_packet.phy_flags |= PHY_FLAG_B;
+						current_packet->phy_flags |= PHY_FLAG_B;
 						DEBUG("B]");
 					}
 					b = b + 2;
@@ -278,25 +279,27 @@
 	DEBUG("\n");
 
 	/* sanitize */
-	if (current_packet.snr > 99)
-		current_packet.snr = 99;
-	if (current_packet.rate == 0 || current_packet.rate > 108) {
+	if (!(present & (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)))
+		current_packet->snr = current_packet->signal - current_packet->noise;
+	if (current_packet->snr > 99)
+		current_packet->snr = 99;
+	if (current_packet->rate == 0 || current_packet->rate > 108) {
 		/* assume min rate for mode */
 		DEBUG("*** fixing wrong rate\n");
-		if (current_packet.phy_flags & PHY_FLAG_A)
-			current_packet.rate = 12; /* 6 * 2 */
-		else if (current_packet.phy_flags & PHY_FLAG_B)
-			current_packet.rate = 2; /* 1 * 2 */
-		else if (current_packet.phy_flags & PHY_FLAG_G)
-			current_packet.rate = 12; /* 6 * 2 */
+		if (current_packet->phy_flags & PHY_FLAG_A)
+			current_packet->rate = 12; /* 6 * 2 */
+		else if (current_packet->phy_flags & PHY_FLAG_B)
+			current_packet->rate = 2; /* 1 * 2 */
+		else if (current_packet->phy_flags & PHY_FLAG_G)
+			current_packet->rate = 12; /* 6 * 2 */
 		else
-			current_packet.rate = 2;
+			current_packet->rate = 2;
 	}
 
-	DEBUG("\nrate: %d\n", current_packet.rate);
-	DEBUG("signal: %d\n", current_packet.signal);
-	DEBUG("noise: %d\n", current_packet.noise);
-	DEBUG("snr: %d\n", current_packet.snr);
+	DEBUG("\nrate: %d\n", current_packet->rate);
+	DEBUG("signal: %d\n", current_packet->signal);
+	DEBUG("noise: %d\n", current_packet->noise);
+	DEBUG("snr: %d\n", current_packet->snr);
 
 	*buf = *buf + rh->it_len;
 	return len - rh->it_len;
@@ -304,7 +307,7 @@
 
 
 static int
-parse_80211_header(unsigned char** buf, int len)
+parse_80211_header(unsigned char** buf, int len, struct packet_info* current_packet)
 {
 	struct ieee80211_hdr* wh;
 	struct ieee80211_mgmt* whm;
@@ -322,8 +325,8 @@
 	if (len < hdrlen)
 		return -1;
 
-	current_packet.len = len;
-	current_packet.wlan_type = (wh->frame_control & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE));
+	current_packet->len = len;
+	current_packet->wlan_type = (wh->frame_control & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE));
 
 	DEBUG("wlan_type %x - type %x - stype %x\n", wh->frame_control, wh->frame_control & IEEE80211_FCTL_FTYPE, wh->frame_control & IEEE80211_FCTL_STYPE );
 
@@ -331,12 +334,12 @@
 
 	bssid = ieee80211_get_bssid(wh, len);
 
-	switch (current_packet.wlan_type & IEEE80211_FCTL_FTYPE) {
+	switch (current_packet->wlan_type & IEEE80211_FCTL_FTYPE) {
 	case IEEE80211_FTYPE_DATA:
-		current_packet.pkt_types = PKT_TYPE_DATA;
-		switch (current_packet.wlan_type & IEEE80211_FCTL_STYPE) {
+		current_packet->pkt_types = PKT_TYPE_DATA;
+		switch (current_packet->wlan_type & IEEE80211_FCTL_STYPE) {
 		case IEEE80211_STYPE_NULLFUNC:
-			current_packet.pkt_types |= PKT_TYPE_NULL;
+			current_packet->pkt_types |= PKT_TYPE_NULL;
 			break;
 		}
 		sa = ieee80211_get_SA(wh);
@@ -344,32 +347,32 @@
 		/* AP, STA or IBSS */
 		if ((wh->frame_control & IEEE80211_FCTL_FROMDS) == 0 &&
 		(wh->frame_control & IEEE80211_FCTL_TODS) == 0)
-			current_packet.wlan_mode = WLAN_MODE_IBSS;
+			current_packet->wlan_mode = WLAN_MODE_IBSS;
 		else if (wh->frame_control & IEEE80211_FCTL_FROMDS)
-			current_packet.wlan_mode = WLAN_MODE_AP;
+			current_packet->wlan_mode = WLAN_MODE_AP;
 		else if (wh->frame_control & IEEE80211_FCTL_TODS)
-			current_packet.wlan_mode = WLAN_MODE_STA;
+			current_packet->wlan_mode = WLAN_MODE_STA;
 		/* WEP */
 		if (wh->frame_control & IEEE80211_FCTL_PROTECTED)
-			current_packet.wlan_wep = 1;
+			current_packet->wlan_wep = 1;
 		break;
 
 	case IEEE80211_FTYPE_CTL:
-		current_packet.pkt_types = PKT_TYPE_CTRL;
-		switch (current_packet.wlan_type & IEEE80211_FCTL_STYPE) {
+		current_packet->pkt_types = PKT_TYPE_CTRL;
+		switch (current_packet->wlan_type & IEEE80211_FCTL_STYPE) {
 		case IEEE80211_STYPE_RTS:
-			current_packet.pkt_types |= PKT_TYPE_RTS;
+			current_packet->pkt_types |= PKT_TYPE_RTS;
 			sa = wh->addr2;
 			da = wh->addr1;
 			break;
 
 		case IEEE80211_STYPE_CTS:
-			current_packet.pkt_types |= PKT_TYPE_CTS;
+			current_packet->pkt_types |= PKT_TYPE_CTS;
 			da = wh->addr1;
 			break;
 
 		case IEEE80211_STYPE_ACK:
-			current_packet.pkt_types |= PKT_TYPE_ACK;
+			current_packet->pkt_types |= PKT_TYPE_ACK;
 			da = wh->addr1;
 			break;
 
@@ -389,48 +392,48 @@
 		break;
 
 	case IEEE80211_FTYPE_MGMT:
-		current_packet.pkt_types = PKT_TYPE_MGMT;
+		current_packet->pkt_types = PKT_TYPE_MGMT;
 		whm = (struct ieee80211_mgmt*)*buf;
 		sa = whm->sa;
 		da = whm->da;
 
-		switch (current_packet.wlan_type & IEEE80211_FCTL_STYPE) {
+		switch (current_packet->wlan_type & IEEE80211_FCTL_STYPE) {
 		case IEEE80211_STYPE_BEACON:
-			current_packet.pkt_types |= PKT_TYPE_BEACON;
-			current_packet.wlan_tsf = whm->u.beacon.timestamp;
+			current_packet->pkt_types |= PKT_TYPE_BEACON;
+			current_packet->wlan_tsf = whm->u.beacon.timestamp;
 			ieee802_11_parse_elems(whm->u.beacon.variable,
-				len - sizeof(struct ieee80211_mgmt) - 4 /* FCS */, &current_packet);
-			DEBUG("ESSID %s \n", current_packet.wlan_essid );
-			DEBUG("CHAN %d \n", current_packet.wlan_channel );
+				len - sizeof(struct ieee80211_mgmt) - 4 /* FCS */, current_packet);
+			DEBUG("ESSID %s \n", current_packet->wlan_essid );
+			DEBUG("CHAN %d \n", current_packet->wlan_channel );
 			if (whm->u.beacon.capab_info & WLAN_CAPABILITY_IBSS)
-				current_packet.wlan_mode = WLAN_MODE_IBSS;
+				current_packet->wlan_mode = WLAN_MODE_IBSS;
 			else if (whm->u.beacon.capab_info & WLAN_CAPABILITY_ESS)
-				current_packet.wlan_mode = WLAN_MODE_AP;
+				current_packet->wlan_mode = WLAN_MODE_AP;
 			if (whm->u.beacon.capab_info & WLAN_CAPABILITY_PRIVACY)
-				current_packet.wlan_wep = 1;
+				current_packet->wlan_wep = 1;
 			break;
 
 		case IEEE80211_STYPE_PROBE_RESP:
-			current_packet.pkt_types |= PKT_TYPE_PROBE;
-			current_packet.wlan_tsf = whm->u.beacon.timestamp;
+			current_packet->pkt_types |= PKT_TYPE_PROBE;
+			current_packet->wlan_tsf = whm->u.beacon.timestamp;
 			ieee802_11_parse_elems(whm->u.beacon.variable,
-				len - sizeof(struct ieee80211_mgmt) - 4 /* FCS */, &current_packet);
-			DEBUG("ESSID %s \n", current_packet.wlan_essid );
-			DEBUG("CHAN %d \n", current_packet.wlan_channel );
+				len - sizeof(struct ieee80211_mgmt) - 4 /* FCS */, current_packet);
+			DEBUG("ESSID %s \n", current_packet->wlan_essid );
+			DEBUG("CHAN %d \n", current_packet->wlan_channel );
 			if (whm->u.beacon.capab_info & WLAN_CAPABILITY_IBSS)
-				current_packet.wlan_mode = WLAN_MODE_IBSS;
+				current_packet->wlan_mode = WLAN_MODE_IBSS;
 			else if (whm->u.beacon.capab_info & WLAN_CAPABILITY_ESS)
-				current_packet.wlan_mode = WLAN_MODE_AP;
+				current_packet->wlan_mode = WLAN_MODE_AP;
 			if (whm->u.beacon.capab_info & WLAN_CAPABILITY_PRIVACY)
-				current_packet.wlan_wep = 1;
+				current_packet->wlan_wep = 1;
 			break;
 
 		case IEEE80211_STYPE_PROBE_REQ:
-			current_packet.pkt_types |= PKT_TYPE_PROBE;
+			current_packet->pkt_types |= PKT_TYPE_PROBE;
 			ieee802_11_parse_elems(whm->u.probe_req.variable,
 				len - 24 - 4 /* FCS */,
-				&current_packet);
-			current_packet.wlan_mode |= WLAN_MODE_PROBE;
+				current_packet);
+			current_packet->wlan_mode |= WLAN_MODE_PROBE;
 			break;
 
 		case IEEE80211_STYPE_ASSOC_REQ:
@@ -438,33 +441,33 @@
 		case IEEE80211_STYPE_REASSOC_REQ:
 		case IEEE80211_STYPE_REASSOC_RESP:
 		case IEEE80211_STYPE_DISASSOC:
-			current_packet.pkt_types |= PKT_TYPE_ASSOC;
+			current_packet->pkt_types |= PKT_TYPE_ASSOC;
 			break;
 
 		case IEEE80211_STYPE_AUTH:
 		case IEEE80211_STYPE_DEAUTH:
-			current_packet.pkt_types |= PKT_TYPE_AUTH;
+			current_packet->pkt_types |= PKT_TYPE_AUTH;
 			break;
 		}
 		break;
 	}
 
 	if (sa != NULL) {
-		memcpy(current_packet.wlan_src, sa, MAC_LEN);
+		memcpy(current_packet->wlan_src, sa, MAC_LEN);
 		DEBUG("SA    %s\n", ether_sprintf(sa));
 	}
 	if (da != NULL) {
-		memcpy(current_packet.wlan_dst, da, MAC_LEN);
+		memcpy(current_packet->wlan_dst, da, MAC_LEN);
 		DEBUG("DA    %s\n", ether_sprintf(da));
 	}
 	if (bssid!=NULL) {
-		memcpy(current_packet.wlan_bssid, bssid, MAC_LEN);
+		memcpy(current_packet->wlan_bssid, bssid, MAC_LEN);
 		DEBUG("BSSID %s\n", ether_sprintf(bssid));
 	}
 
 	/* only data frames contain more info, otherwise stop parsing */
-	if ((current_packet.wlan_type & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
-	     current_packet.wlan_wep != 1) {
+	if ((current_packet->wlan_type & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+	     current_packet->wlan_wep != 1) {
 		*buf = *buf + hdrlen;
 		return len - hdrlen;
 	}
@@ -472,8 +475,8 @@
 }
 
 
-static inline int
-parse_llc(unsigned char ** buf, int len)
+static int
+parse_llc(unsigned char ** buf, int len, struct packet_info* current_packet)
 {
 	DEBUG("* parse LLC\n");
 
@@ -486,7 +489,7 @@
 		return -1;
 	(*buf)++;
 	if (**buf == 0x06) { /* ARP */
-		current_packet.pkt_types |= PKT_TYPE_ARP;
+		current_packet->pkt_types |= PKT_TYPE_ARP;
 		return 0;
 	}
 	if (**buf != 0x00)  /* not IP */
@@ -500,7 +503,7 @@
 
 
 static int
-parse_ip_header(unsigned char** buf, int len)
+parse_ip_header(unsigned char** buf, int len, struct packet_info* current_packet)
 {
 	struct iphdr* ih;
 
@@ -513,16 +516,16 @@
 
 	DEBUG("*** IP SRC: %s\n", ip_sprintf(ih->saddr));
 	DEBUG("*** IP DST: %s\n", ip_sprintf(ih->daddr));
-	current_packet.ip_src = ih->saddr;
-	current_packet.ip_dst = ih->daddr;
-	current_packet.pkt_types |= PKT_TYPE_IP;
+	current_packet->ip_src = ih->saddr;
+	current_packet->ip_dst = ih->daddr;
+	current_packet->pkt_types |= PKT_TYPE_IP;
 
 	DEBUG("IP proto: %d\n", ih->protocol);
 	switch (ih->protocol) {
-	case IPPROTO_UDP: current_packet.pkt_types |= PKT_TYPE_UDP; break;
+	case IPPROTO_UDP: current_packet->pkt_types |= PKT_TYPE_UDP; break;
 	/* all others set the type and return. no more parsing */
-	case IPPROTO_ICMP: current_packet.pkt_types |= PKT_TYPE_ICMP; return 0;
-	case IPPROTO_TCP: current_packet.pkt_types |= PKT_TYPE_TCP; return 0;
+	case IPPROTO_ICMP: current_packet->pkt_types |= PKT_TYPE_ICMP; return 0;
+	case IPPROTO_TCP: current_packet->pkt_types |= PKT_TYPE_TCP; return 0;
 	}
 
 
@@ -532,7 +535,7 @@
 
 
 static int
-parse_udp_header(unsigned char** buf, int len)
+parse_udp_header(unsigned char** buf, int len, struct packet_info* current_packet)
 {
 	struct udphdr* uh;
 
@@ -547,21 +550,20 @@
 	len = len - 8;
 
 	if (ntohs(uh->dest) == 698) /* OLSR */
-		return parse_olsr_packet(buf, len);
+		return parse_olsr_packet(buf, len, current_packet);
 
 	if (ntohs(uh->dest) == BAT_PORT) /* batman */
-		return parse_batman_packet(buf, len);
+		return parse_batman_packet(buf, len, current_packet);
 
 	return 0;
 }
 
 
 static int
-parse_olsr_packet(unsigned char** buf, int len)
+parse_olsr_packet(unsigned char** buf, int len, struct packet_info* current_packet)
 {
 	struct olsr* oh;
-	int number;
-	int i;
+	int number, i, msgtype;
 
 	if (len < sizeof(struct olsr))
 		return -1;
@@ -569,26 +571,26 @@
 	oh = (struct olsr*)*buf;
 
 	// TODO: more than one olsr messages can be in one packet
-	int msgtype = oh->olsr_msg[0].olsr_msgtype;
+	msgtype = oh->olsr_msg[0].olsr_msgtype;
 
 	DEBUG("OLSR msgtype: %d\n*** ", msgtype);
 
-	current_packet.pkt_types |= PKT_TYPE_OLSR;
-	current_packet.olsr_type = msgtype;
+	current_packet->pkt_types |= PKT_TYPE_OLSR;
+	current_packet->olsr_type = msgtype;
 
 	if (msgtype == LQ_HELLO_MESSAGE || msgtype == LQ_TC_MESSAGE )
-		current_packet.pkt_types |= PKT_TYPE_OLSR_LQ;
+		current_packet->pkt_types |= PKT_TYPE_OLSR_LQ;
 
 	if (msgtype == HELLO_MESSAGE) {
 		number = (ntohs(oh->olsr_msg[0].olsr_msgsize) - 12) / sizeof(struct hellomsg);
 		DEBUG("HELLO %d\n", number);
-		current_packet.olsr_neigh = number;
+		current_packet->olsr_neigh = number;
 	}
 
 	if (msgtype == LQ_HELLO_MESSAGE) {
 		number = (ntohs(oh->olsr_msg[0].olsr_msgsize) - 16) / 12;
 		DEBUG("LQ_HELLO %d (%d)\n", number, (ntohs(oh->olsr_msg[0].olsr_msgsize) - 16));
-		current_packet.olsr_neigh = number;
+		current_packet->olsr_neigh = number;
 	}
 #if 0
 /*	XXX: tc messages are relayed. so we would have to find the originating node (IP)
@@ -597,13 +599,13 @@
 	if (msgtype == TC_MESSAGE) {
 		number = (ntohs(oh->olsr_msg[0].olsr_msgsize)-12) / sizeof(struct tcmsg);
 		DEBUG("TC %d\n", number);
-		current_packet.olsr_tc = number;
+		current_packet->olsr_tc = number;
 	}
 
 	if (msgtype == LQ_TC_MESSAGE) {
 		number = (ntohs(oh->olsr_msg[0].olsr_msgsize)-16) / 8;
 		DEBUG("LQ_TC %d (%d)\n", number, (ntohs(oh->olsr_msg[0].olsr_msgsize)-16));
-		current_packet.olsr_tc = number;
+		current_packet->olsr_tc = number;
 	}
 #endif
 	if (msgtype == HNA_MESSAGE) {
@@ -618,7 +620,7 @@
 			DEBUG("HNA %s", ip_sprintf(hna->addr));
 			DEBUG("/%s\n", ip_sprintf(hna->netmask));
 			if (hna->addr == 0 && hna->netmask == 0)
-				current_packet.pkt_types |= PKT_TYPE_OLSR_GW;
+				current_packet->pkt_types |= PKT_TYPE_OLSR_GW;
 		}
 	}
 	/* done for good */
@@ -627,9 +629,9 @@
 
 
 static int
-parse_batman_packet(unsigned char** buf, int len)
+parse_batman_packet(unsigned char** buf, int len, struct packet_info* current_packet)
 {
-	current_packet.pkt_types |= PKT_TYPE_BATMAN;
+	current_packet->pkt_types |= PKT_TYPE_BATMAN;
 
 	return 0;
 }
diff --exclude='.git*' -Nur horst-2.0-rc1/protocol_parser.h horst-2008-07-13/protocol_parser.h
--- horst-2.0-rc1/protocol_parser.h	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/protocol_parser.h	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -20,7 +20,9 @@
 #ifndef _PROTOCOL_PARSER_H_
 #define _PROTOCOL_PARSER_H_
 
+struct packet_info;
+
 int
-parse_packet(unsigned char* buf, int len);
+parse_packet(unsigned char* buf, int len, struct packet_info* current_packet);
 
 #endif
diff --exclude='.git*' -Nur horst-2.0-rc1/TODO horst-2008-07-13/TODO
--- horst-2.0-rc1/TODO	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/TODO	2008-07-13 10:54:53.000000000 +0200
@@ -13,6 +13,13 @@
 feature requests:
 -----------------
 
+ * FCS errors checken
+ * ACKs
+ * retries
+ * batman layer 2 ethertype 0x0842
+
+---
+
 > WEITERE OPTIONEN, (braucht ein tmp. eingabe-feld, zb. im header)
 > evt. als [IP:], dann untermenue:
 > - [k: keep] eintrag nach time-out in der anzeige halten, markiert m."?".
diff --exclude='.git*' -Nur horst-2.0-rc1/util.c horst-2008-07-13/util.c
--- horst-2.0-rc1/util.c	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/util.c	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -30,7 +30,7 @@
 };
 
 /* a list of packet type names for easier indexing with padding */
-struct pkt_names mgmt_names[] = {
+static struct pkt_names mgmt_names[] = {
 	{ 'a', "ASOCRQ" },		/* IEEE80211_STYPE_ASSOC_REQ	0x0000 */
 	{ 'A', "ASOCRP" },		/* IEEE80211_STYPE_ASSOC_RESP	0x0010 */
 	{ 'a', "REASRQ" },		/* IEEE80211_STYPE_REASSOC_REQ	0x0020 */
@@ -46,7 +46,7 @@
 	{ 'T', "ACTION" },		/* IEEE80211_STYPE_ACTION	0x00D0 */
 };
 
-struct pkt_names ctrl_names[] = {
+static struct pkt_names ctrl_names[] = {
 	{ 's', "PSPOLL" },		/* IEEE80211_STYPE_PSPOLL	0x00A0 */
 	{ 'R', "RTS" },			/* IEEE80211_STYPE_RTS		0x00B0 */
 	{ 'C', "CTS" },			/* IEEE80211_STYPE_CTS		0x00C0 */
@@ -55,7 +55,7 @@
 	{ 'f', "CFENDK" },		/* IEEE80211_STYPE_CFENDACK	0x00F0 */
 };
 
-struct pkt_names data_names[] = {
+static struct pkt_names data_names[] = {
 	{ 'D', "DATA" },		/* IEEE80211_STYPE_DATA			0x0000 */
 	{ 'F', "DCFACK" },		/* IEEE80211_STYPE_DATA_CFACK		0x0010 */
 	{ 'F', "DCFPLL" },		/* IEEE80211_STYPE_DATA_CFPOLL		0x0020 */
@@ -79,7 +79,7 @@
 #define CTRL_NAME_INDEX(_i) ((((_i) & IEEE80211_FCTL_STYPE)>>4)-10)
 
 
-inline int
+int
 normalize(float oval, int max_val, int max) {
 	int val;
 	val= (oval / max_val) * max;
diff --exclude='.git*' -Nur horst-2.0-rc1/util.h horst-2008-07-13/util.h
--- horst-2.0-rc1/util.h	2007-12-26 11:22:20.000000000 +0100
+++ horst-2008-07-13/util.h	2008-07-13 10:54:53.000000000 +0200
@@ -1,6 +1,6 @@
 /* horst - olsr scanning tool
  *
- * Copyright (C) 2005-2007  Bruno Randolf
+ * Copyright (C) 2005-2008  Bruno Randolf
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -40,7 +40,7 @@
 void
 convert_string_to_mac(const char* string, unsigned char* mac);
 
-inline int
+int
 normalize(float val, int max_val, int max);
 
 #define normalize_db(_val, _max) \
@@ -58,6 +58,8 @@
 #define MAC_NOT_EMPTY(_mac) (_mac[0] || _mac[1] || _mac[2] || _mac[3] || _mac[4] || _mac[5])
 #define MAC_EMPTY(_mac) (!_mac[0] && !_mac[1] && !_mac[2] && !_mac[3] && !_mac[4] && !_mac[5])
 
-#define TOGGLE_BIT(_x, _m) (_x) = (_x) & (_m) ? (_x) & ~(_m) : (_x) | (_m)
+#define TOGGLE_BIT(_x, _m) (_x) ^= (_m)
+
+#define max(x,y) ((x) > (y) ? (x) : (y))
 
 #endif
