diff --git a/Makefile b/Makefile index 55a90ed..f5cfe65 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ man8 := $(DESTDIR)/usr/share/man/man8/ all: nethogs CFLAGS=-g -OBJS=structs.o packet.o connection.o process.o hashtbl.o refresh.o +OBJS=structs.o packet.o connection.o process.o hashtbl.o refresh.o decpcap.o GCC=g++ .PHONY: tgz @@ -40,6 +40,8 @@ connection.o: connection.cpp connection.h nethogs.h $(GCC) $(CFLAGS) -c connection.cpp hashtbl.o: hashtbl.cpp hashtbl.h nethogs.h $(GCC) $(CFLAGS) -c hashtbl.cpp +decpcap.o: decpcap.c decpcap.h + gcc $(CFLAGS) -c decpcap.c .PHONY: clean clean: diff --git a/nethogs.cpp b/nethogs.cpp index c5a76d1..5c83b5d 100644 --- a/nethogs.cpp +++ b/nethogs.cpp @@ -11,10 +11,14 @@ #include #include +#include +#include +#include + #include extern "C" { - #include + #include "decpcap.h" } #include "packet.h" @@ -25,7 +29,8 @@ extern "C" { unsigned refreshdelay = 1; bool tracemode = false; bool needrefresh = true; -packet_type packettype = packet_ethernet; +//packet_type packettype = packet_ethernet; +dp_link_type linktype = dp_link_ethernet; char * currentdevice = NULL; @@ -69,7 +74,8 @@ bool local_addr::contains(const struct in6_addr & n_addr) { return next->contains(n_addr); } -void process (u_char * args, const struct pcap_pkthdr * header, const u_char * m_packet) +/* deprecated by process_tcp + * void process (u_char * args, const struct pcap_pkthdr * header, const u_char * m_packet) { curtime = header->ts; @@ -81,11 +87,11 @@ void process (u_char * args, const struct pcap_pkthdr * header, const u_char * m if (connection != NULL) { - /* add packet to the connection */ connection->add(packet); } else { - /* else: unknown connection, create new */ connection = new Connection (packet); + if (DEBUG) + std::cerr << "Getting process by connection\n"; Process * process = getProcess(connection, currentdevice); } @@ -94,6 +100,79 @@ void process (u_char * args, const struct pcap_pkthdr * header, const u_char * m do_refresh(); needrefresh = false; } +}*/ + +struct dpargs { + int sa_family; + in_addr ip_src; + in_addr ip_dst; + in6_addr ip6_src; + in6_addr ip6_dst; +}; + +int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_packet) { + struct dpargs * args = (struct dpargs *) userdata; + struct tcphdr * tcp = (struct tcphdr *) m_packet; + + curtime = header->ts; + + /* TODO get info from userdata, then call getPacket */ + Packet * packet; + switch (args->sa_family) + { + case (AF_INET): + //packet = new Packet (args->ip_src, ntohs(tcp->th_sport), args->ip_dst, ntohs(tcp->th_dport), header->len, header->ts); + packet = new Packet (args->ip_src, ntohs(tcp->source), args->ip_dst, ntohs(tcp->dest), header->len, header->ts); + break; + case (AF_INET6): + packet = new Packet (args->ip6_src, ntohs(tcp->source), args->ip6_dst, ntohs(tcp->dest), header->len, header->ts); + break; + } + + Connection * connection = findConnection(packet); + + if (connection != NULL) + { + /* add packet to the connection */ + connection->add(packet); + } else { + /* else: unknown connection, create new */ + connection = new Connection (packet); + if (DEBUG) + std::cerr << "Getting process by connection\n"; + Process * process = getProcess(connection, currentdevice); + } + + if (needrefresh) + { + do_refresh(); + needrefresh = false; + } + + /* we're done now. */ + return true; +} + +int process_ip (u_char * userdata, const dp_header * header, const u_char * m_packet) { + struct dpargs * args = (struct dpargs *) userdata; + struct ip * ip = (struct ip *) m_packet; + args->sa_family = AF_INET; + args->ip_src = ip->ip_src; + args->ip_dst = ip->ip_dst; + + /* we're not done yet - also parse tcp :) */ + return false; +} + +int process_ip6 (u_char * userdata, const dp_header * header, const u_char * m_packet) { + struct dpargs * args = (struct dpargs *) userdata; + const struct ip6_hdr * ip6 = (struct ip6_hdr *) m_packet; + args->sa_family = AF_INET6; + args->ip6_src = ip6->ip6_src; + args->ip6_dst = ip6->ip6_dst; + + /* we're not done yet - also parse tcp :) */ + return false; } void quit_cb (int i) @@ -143,10 +222,10 @@ public: class handle { public: - handle (pcap_t * m_handle, char * m_devicename = NULL, handle * m_next = NULL) { + handle (dp_handle * m_handle, char * m_devicename = NULL, handle * m_next = NULL) { content = m_handle; next = m_next; devicename = m_devicename; } - pcap_t * content; + dp_handle * content; char * devicename; handle * next; }; @@ -154,6 +233,7 @@ public: int main (int argc, char** argv) { device * devices = NULL; + //dp_link_type linktype = dp_link_ethernet; int promisc = 0; for (argv++; *argv; argv++) @@ -181,9 +261,9 @@ int main (int argc, char** argv) { argv++; if (strcmp (*argv, "ppp") == 0) - packettype = packet_ppp; + linktype = dp_link_ppp; else if (strcmp (*argv, "eth") == 0) - packettype = packet_ethernet; + linktype = dp_link_ethernet; } break; default : help(); @@ -224,7 +304,10 @@ int main (int argc, char** argv) caption->append(" "); } - pcap_t * newhandle = pcap_open_live(current_dev->name, BUFSIZ, promisc, 100, errbuf); + dp_handle * newhandle = dp_open_live(current_dev->name, linktype, BUFSIZ, promisc, 100, errbuf); + dp_addcb (newhandle, dp_packet_ip, process_ip); + dp_addcb (newhandle, dp_packet_ip6, process_ip6); + dp_addcb (newhandle, dp_packet_tcp, process_tcp); if (newhandle != NULL) { /* The following code solves sf.net bug 1019381, but is only available @@ -249,8 +332,12 @@ int main (int argc, char** argv) handle * current_handle = handles; while (current_handle != NULL) { + struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs)); + userdata->sa_family = AF_UNSPEC; currentdevice = current_handle->devicename; - pcap_dispatch (current_handle->content, -1, process, NULL); + /* TODO maybe userdata needs be reset every now and then? */ + dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs)); + /* dp_dispatch handles deletion of the userdata */ current_handle = current_handle->next; } diff --git a/nethogs.h b/nethogs.h index 0c44c3e..e5ffc3c 100644 --- a/nethogs.h +++ b/nethogs.h @@ -99,9 +99,4 @@ private: short int sa_family; }; -enum packet_type { - packet_ethernet, - packet_ppp -}; - #endif diff --git a/packet.cpp b/packet.cpp index 74805fc..ed7f9b3 100644 --- a/packet.cpp +++ b/packet.cpp @@ -125,6 +125,7 @@ struct tcp_hdr { u_short th_urp; /* urgent pointer */ }; /* Packet 'Constructor' - but returns NULL on failure */ +/* deprecated by decpcap Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, packet_type headertype) { int packettype; @@ -135,8 +136,6 @@ Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, pa case (packet_ethernet): { const struct ether_header * ethernet = (struct ether_header *)packet; - /* this is the opposite endianness from http://www.iana.org/assignments/ethernet-numbers - * TODO probably have to look at network/host byte order and endianness!! */ packettype = ethernet->ether_type; headersize = sizeof (struct ether_header); }; break; @@ -180,6 +179,7 @@ Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, pa #endif return NULL; } +*/ Packet::Packet (in_addr m_sip, unsigned short m_sport, in_addr m_dip, unsigned short m_dport, bpf_u_int32 m_len, timeval m_time, direction m_dir) { diff --git a/packet.h b/packet.h index 4d412b3..58f15bb 100644 --- a/packet.h +++ b/packet.h @@ -55,6 +55,6 @@ private: short int sa_family; }; -Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, packet_type packettype); +//Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, packet_type packettype); #endif diff --git a/process.cpp b/process.cpp index c4b4c83..5221e02 100644 --- a/process.cpp +++ b/process.cpp @@ -91,9 +91,20 @@ void addtoconninode (char * buffer) unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long)); // TODO check it matched - sscanf(buffer, "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*lX:%*lX %*X:%*lX %*lX %*d %*d %ld %*512s\n", + int matches = sscanf(buffer, "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*lX:%*lX %*X:%*lX %*lX %*d %*d %ld %*512s\n", local_addr, &local_port, rem_addr, &rem_port, inode); + if (matches != 5) { + fprintf(stderr,"Unexpected buffer: '%s'\n",buffer); + exit(0); + } + /*if (*inode == 0) { + // This sometimes happens due to what I think is a bug in the + // kernel. See http://lkml.org/lkml/2004/9/10/193. + fprintf(stderr,"Inode zero: '%s'\n",buffer); + exit(0); + }*/ + if (strlen(local_addr) > 8) { /* this is an IPv6-style row */ @@ -396,7 +407,9 @@ void do_refresh() } /* returns the process from proclist with matching pid - * if none, creates it */ + * if the inode is not associated with any PID, return the unknown process + * if the process is not yet in the proclist, add it + */ Process * getProcess (unsigned long inode, char * devicename) { struct prg_node * node = prg_cache_get(inode); @@ -409,7 +422,7 @@ Process * getProcess (unsigned long inode, char * devicename) if (node == NULL) { if (DEBUG) - std::cerr << "Unknown inode " << inode << ", assuming unknown." << endl; + std::cerr << "inode " << inode << " STILL not in inode-to-program-mapping." << endl; return unknownproc; } } @@ -477,7 +490,7 @@ Process * getProcess (Connection * connection, char * devicename) { delete reversepacket; if (DEBUG) - std::cerr << connection->refpacket->gethashstring() << " STILL not in table - adding to the unknown process\n"; + std::cerr << connection->refpacket->gethashstring() << " STILL not in connection-to-inode table - adding to the unknown process\n"; unknownproc->connections = new ConnList (connection, unknownproc->connections); return unknownproc; }