#include "integers.h"
-#if defined(HAVE_PCAP_H)
-# include <pcap.h>
-#elif defined(HAVE_PCAP_PCAP_H)
-# include <pcap/pcap.h>
-#else
-# error No pcap.h
-#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
-#include <net/bpf.h>
+/* include <net/bpf.h> -- this was added by the PFLOG patch but seems
+ * superfluous and breaks on Slackware */
+#if defined(HAVE_PCAP_H)
+# include <pcap.h>
+#elif defined(HAVE_PCAP_PCAP_H)
+# include <pcap/pcap.h>
+#else
+# error No pcap.h
+#endif
#include <pthread.h>
#include <curses.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
+#include <locale.h>
#include "iftop.h"
#include "addr_hash.h"
#include "resolver.h"
+#include "ui_common.h"
#include "ui.h"
+#include "tui.h"
#include "options.h"
#ifdef DLT_LINUX_SLL
#include "sll.h"
#include "ethertype.h"
#include "cfgfile.h"
#include "ppp.h"
+#include "addrs_ioctl.h"
#include <netinet/ip6.h>
/* ethernet address of interface. */
int have_hw_addr = 0;
-unsigned char if_hw_addr[6];
+char if_hw_addr[6];
/* IP address of interface */
int have_ip_addr = 0;
hash_type* history;
history_type history_totals;
time_t last_timestamp;
+time_t first_timestamp;
int history_pos = 0;
int history_len = 1;
pthread_mutex_t tick_mutex;
-/* Only need ethernet (plus optional 4 byte VLAN) and IP headers (48) + first 2 bytes of tcp/udp header */
+/* Only need ethernet (plus optional 4 byte VLAN) and IP headers (48) + first 2
+ * bytes of tcp/udp header */
/* Increase with a further 20 to account for IPv6 header length. */
-#define CAPTURE_LENGTH 92
+/* IEEE 802.11 radiotap throws in a variable length header plus 8 (radiotap
+ * header header) plus 34 (802.11 MAC) plus 40 (IPv6) = 78, plus whatever's in
+ * the radiotap payload */
+/*#define CAPTURE_LENGTH 92 */
+#define CAPTURE_LENGTH 256
void init_history() {
history = addr_hash_create();
t = time(NULL);
if(t - last_timestamp >= RESOLUTION) {
- //printf("TICKING\n");
analyse_data();
- ui_print();
+ if (options.no_curses) {
+ if (!options.timed_output || (options.timed_output && t - first_timestamp >= options.timed_output)) {
+ tui_print();
+ if (options.timed_output) {
+ finish(SIGINT);
+ }
+ }
+ }
+ else {
+ ui_print();
+ }
history_rotate();
last_timestamp = t;
}
else {
- ui_tick(print);
+ if (options.no_curses) {
+ tui_tick(print);
+ }
+ else {
+ ui_tick(print);
+ }
}
pthread_mutex_unlock(&tick_mutex);
return ret;
}
-int __inline__ ip_addr_match(struct in_addr addr) {
+static int __inline__ ip_addr_match(struct in_addr addr) {
return addr.s_addr == if_ip_addr.s_addr;
}
-int __inline__ ip6_addr_match(struct in6_addr *addr) {
+static int __inline__ ip6_addr_match(struct in6_addr *addr) {
return IN6_ARE_ADDR_EQUAL(addr, &if_ip6_addr);
}
int direction = 0; /* incoming */
history_type* ht;
union {
- history_type **ht_pp;
- void **void_pp;
+ history_type **ht_pp;
+ void **void_pp;
} u_ht = { &ht };
addr_pair ap;
unsigned int len = 0;
memset(&ap, '\0', sizeof(ap));
+ tick(0);
+
if( (IP_V(iptr) ==4 && options.netfilter == 0)
|| (IP_V(iptr) == 6 && options.netfilter6 == 0) ) {
/*
assign_addr_pair(&ap, iptr, 1);
direction = 0;
}
+ else if (IP_V(iptr) == 4 && IN_MULTICAST(iptr->ip_dst.s_addr)) {
+ assign_addr_pair(&ap, iptr, 1);
+ direction = 0;
+ }
+ else if (IP_V(iptr) == 6 && IN6_IS_ADDR_MULTICAST(&ip6tr->ip6_dst)) {
+ assign_addr_pair(&ap, iptr, 1);
+ direction = 0;
+ }
/*
* Cannot determine direction from hardware or IP levels. Therefore
* assume that it was a packet between two other machines, assign
direction = 0;
}
/* Drop other uncertain packages. */
+ else
+ return;
}
if(IP_V(iptr) == 4 && options.netfilter != 0) {
/* First reduce the participating addresses using the netfilter prefix.
* We need scratch pads to do this.
*/
- for (j=0; j < 4; ++j) {
- scribdst.s6_addr32[j] = ip6tr->ip6_dst.s6_addr32[j]
- & options.netfilter6mask.s6_addr32[j];
- scribsrc.s6_addr32[j] = ip6tr->ip6_src.s6_addr32[j]
- & options.netfilter6mask.s6_addr32[j];
+ for (j=0; j < 16; ++j) {
+ scribdst.s6_addr[j] = ip6tr->ip6_dst.s6_addr[j]
+ & options.netfilter6mask.s6_addr[j];
+ scribsrc.s6_addr[j] = ip6tr->ip6_src.s6_addr[j]
+ & options.netfilter6mask.s6_addr[j];
}
/* Now look for any hits. */
hdrlen = BPF_WORDALIGN(hdr->length);
length -= hdrlen;
packet += hdrlen;
- handle_ip_packet((struct ip*)packet, length);
+ handle_ip_packet((struct ip*)packet, -1);
}
#endif
+static void handle_null_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
+{
+ handle_ip_packet((struct ip*)(packet + 4), -1);
+}
+
static void handle_llc_packet(const struct llc* llc, int dir) {
struct ip* ip = (struct ip*)((void*)llc + sizeof(struct llc));
if(llc->ssap == LLCSAP_SNAP && llc->dsap == LLCSAP_SNAP
&& llc->llcui == LLC_UI) {
u_int32_t orgcode;
- register u_short et;
+ u_int16_t et;
orgcode = EXTRACT_24BITS(&llc->llc_orgcode[0]);
- et = EXTRACT_16BITS(&llc->llc_ethertype[0]);
+ et = (llc->llc_ethertype[0] << 8) + llc->llc_ethertype[1];
switch(orgcode) {
case OUI_ENCAP_ETHER:
case OUI_CISCO_90:
ether_type = ntohs(eptr->ether_type);
payload = packet + sizeof(struct ether_header);
- tick(0);
-
if(ether_type == ETHERTYPE_8021Q) {
- struct vlan_8021q_header* vptr;
- vptr = (struct vlan_8021q_header*)payload;
- ether_type = ntohs(vptr->ether_type);
+ struct vlan_8021q_header* vptr;
+ vptr = (struct vlan_8021q_header*)payload;
+ ether_type = ntohs(vptr->ether_type);
payload += sizeof(struct vlan_8021q_header);
}
dir = 1;
}
else if(have_hw_addr && memcmp(eptr->ether_dhost, if_hw_addr, 6) == 0 ) {
- /* packet entering this i/f */
- dir = 0;
- }
- else if (memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", eptr->ether_dhost, 6) == 0) {
- /* broadcast packet, count as incoming */
+ /* packet entering this i/f */
+ dir = 0;
+ }
+ else if (memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", eptr->ether_dhost, 6) == 0) {
+ /* broadcast packet, count as incoming */
dir = 0;
}
}
}
+#ifdef DLT_IEEE802_11_RADIO
+/*
+ * Packets with a bonus radiotap header.
+ * See http://www.gsp.com/cgi-bin/man.cgi?section=9&topic=ieee80211_radiotap
+ */
+static void handle_radiotap_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
+{
+ /* 802.11 MAC header is = 34 bytes (not sure if that's universally true) */
+ /* We could try harder to figure out hardware direction from the MAC header */
+ handle_ip_packet((struct ip*)(packet + ((struct radiotap_header *)packet)->it_len + 34),-1);
+}
+
+
+#endif
/* set_filter_code:
* Install some filter code. Returns NULL on success or an error message on
void packet_init() {
char errbuf[PCAP_ERRBUF_SIZE];
char *m;
- int s;
int i;
int dlt;
int result;
packet_handler = handle_pflog_packet;
}
#endif
- else if(dlt == DLT_RAW || dlt == DLT_NULL) {
+ else if(dlt == DLT_RAW) {
packet_handler = handle_raw_packet;
}
+ else if(dlt == DLT_NULL) {
+ packet_handler = handle_null_packet;
+ }
+#ifdef DLT_LOOP
+ else if(dlt == DLT_LOOP) {
+ packet_handler = handle_null_packet;
+ }
+#endif
+#ifdef DLT_IEEE802_11_RADIO
+ else if(dlt == DLT_IEEE802_11_RADIO) {
+ packet_handler = handle_radiotap_packet;
+ }
+#endif
else if(dlt == DLT_IEEE802) {
packet_handler = handle_tokenring_packet;
}
pthread_t thread;
struct sigaction sa = {};
+ setlocale(LC_ALL, "");
+
/* TODO: tidy this up */
/* read command line options and config file */
config_init();
init_history();
- ui_init();
+ if (options.no_curses) {
+ tui_init();
+ }
+ else {
+ ui_init();
+ }
pthread_create(&thread, NULL, (void*)&packet_loop, NULL);
- ui_loop();
+ /* Keep the starting time (used for timed termination) */
+ first_timestamp = time(NULL);
+
+ if (options.no_curses) {
+ if (options.timed_output) {
+ while(!foad) {
+ sleep(1);
+ }
+ }
+ else {
+ tui_loop();
+ }
+ }
+ else {
+ ui_loop();
+ }
pthread_cancel(thread);