From 8697bf01a17333541da88f695c39e23c09c29b93 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Thu, 2 Sep 2004 16:10:25 +0000 Subject: [PATCH] wild stab at supporting PPP ('Linux cooked capture') packets.. --- nethogs.cpp | 14 ++++++++++-- nethogs.h | 5 ++++ packet.cpp | 66 +++++++++++++++++++++++++++++++++++------------------ packet.h | 3 ++- process.cpp | 19 +++++++-------- 5 files changed, 71 insertions(+), 36 deletions(-) diff --git a/nethogs.cpp b/nethogs.cpp index c7dc064..9b98d68 100644 --- a/nethogs.cpp +++ b/nethogs.cpp @@ -25,6 +25,7 @@ extern "C" { unsigned refreshdelay = 1; bool tracemode = false; bool needrefresh = true; +packet_type packettype = packet_ethernet; char * currentdevice = NULL; @@ -72,7 +73,7 @@ void process (u_char * args, const struct pcap_pkthdr * header, const u_char * m { curtime = header->ts; - Packet * packet = getPacket (header, m_packet); + Packet * packet = getPacket (header, m_packet, packettype); if (packet == NULL) return; @@ -121,10 +122,11 @@ static void versiondisplay(void) static void help(void) { - std::cerr << "usage: nethogs [-V] [-d] [device [device [device ...]]]\n"; + std::cerr << "usage: nethogs [-V] [-d seconds] [-t] [-p] [-f (eth|ppp))] [device [device [device ...]]]\n"; std::cerr << " -V : prints version.\n"; std::cerr << " -d : delay for update refresh rate in seconds. default is 1.\n"; std::cerr << " -t : tracemode.\n"; + std::cerr << " -f : format of packets on interface, default is eth.\n"; std::cerr << " -p : sniff in promiscious mode (not recommended).\n"; std::cerr << " device : device(s) to monitor. default is eth0\n"; } @@ -175,6 +177,14 @@ int main (int argc, char** argv) refreshdelay=atoi(*argv); } break; + case 'f': if (argv[1]) + { + argv++; + if (strcmp (*argv, "ppp") == 0) + packettype = packet_ppp; + else if (strcmp (*argv, "eth") == 0) + packettype = packet_ethernet; + } default : help(); exit(0); } diff --git a/nethogs.h b/nethogs.h index f480d79..a3bb593 100644 --- a/nethogs.h +++ b/nethogs.h @@ -93,4 +93,9 @@ private: short int sa_family; }; +enum packet_type { + packet_ethernet, + packet_ppp +}; + #endif diff --git a/packet.cpp b/packet.cpp index 099be7d..89742af 100644 --- a/packet.cpp +++ b/packet.cpp @@ -80,6 +80,21 @@ void getLocal (const char *device) typedef u_int32_t tcp_seq; +/* ppp header, i hope ;) */ +/* glanced from ethereal, it's 16 bytes, and the payload packet type is + * in the last 2 bytes... */ +struct ppp_header { + u_int16_t dummy1; + u_int16_t dummy2; + u_int16_t dummy3; + u_int16_t dummy4; + u_int16_t dummy5; + u_int16_t dummy6; + u_int16_t dummy7; + + u_int16_t packettype; +}; + /* TCP header */ // TODO take from elsewhere. struct tcp_hdr { @@ -109,17 +124,33 @@ struct tcp_hdr { u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ }; - /* Packet 'Constructor' - but returns NULL on failure */ -Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet) +Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, packet_type headertype) { - // const struct ethernet_hdr * ethernet = (struct ethernet_hdr *)packet; - 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!! */ - if (ethernet->ether_type == 0x0008) + int packettype; + int headersize; + + switch (headertype) { - const struct ip * ip = (struct ip *)(packet + sizeof(ether_header)); + 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; + case (packet_ppp): + { + const struct ppp_header * ppp = (struct ppp_header *)packet; + packettype = ppp->packettype; + headersize = sizeof (struct ether_header); + break; + }; break; + } + if (packettype == 0x0008) + { + const struct ip * ip = (struct ip *)(packet + headersize); if (ip->ip_p != 6) { #if DEBUG @@ -127,10 +158,10 @@ Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet) #endif return NULL; } - const struct tcp_hdr * tcp = (struct tcp_hdr *)(packet + sizeof(ether_header) + sizeof(struct ip)); + const struct tcp_hdr * tcp = (struct tcp_hdr *)(packet + headersize + sizeof(struct ip)); return new Packet (ip->ip_src, ntohs(tcp->th_sport), ip->ip_dst, ntohs(tcp->th_dport), header->len, header->ts); - } else if (ethernet->ether_type == 0xDD86) { - const struct ip6_hdr * ip6 = (struct ip6_hdr *)(packet + sizeof(ether_header)); + } else if (packettype == 0xDD86) { + const struct ip6_hdr * ip6 = (struct ip6_hdr *)(packet + headersize); if ((ip6->ip6_ctlun).ip6_un1.ip6_un1_nxt != 0x06) { // TODO maybe we need to skip over some headers? @@ -139,17 +170,14 @@ Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet) #endif return NULL; } - const struct tcp_hdr * tcp = (struct tcp_hdr *)(packet + sizeof(ether_header) + sizeof(ip6_hdr)); + const struct tcp_hdr * tcp = (struct tcp_hdr *)(packet + headersize + sizeof(ip6_hdr)); - // TODO make a Packet constructor that properly understands IPv6 - //return new Packet (*((in_addr*)(&(ip6->ip6_src))), ntohs(tcp->th_sport), - // *((in_addr*)(&(ip6->ip6_dst))), ntohs(tcp->th_dport), header->len, header->ts); return new Packet (ip6->ip6_src, ntohs(tcp->th_sport), ip6->ip6_dst, ntohs(tcp->th_dport), header->len, header->ts); } #if DEBUG - std::cerr << "Dropped non-ip packet of type " << ethernet->ether_type << std::endl; + std::cerr << "Dropped non-ip packet of type " << packettype << std::endl; #endif return NULL; } @@ -246,13 +274,9 @@ char * Packet::gethashstring () if (sa_family == AF_INET) { inet_ntop(sa_family, &sip, local_string, 49); inet_ntop(sa_family, &dip, remote_string, 49); - if (DEBUG) - fprintf(stderr, "Generating IPv4 string: "); } else { inet_ntop(sa_family, &sip6, local_string, 49); inet_ntop(sa_family, &dip6, remote_string, 49); - if (DEBUG) - fprintf(stderr, "Generating IPv6 string: "); } if (Outgoing()) { snprintf(retval, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", local_string, sport, remote_string, dport); @@ -261,8 +285,6 @@ char * Packet::gethashstring () } free (local_string); free (remote_string); - if (DEBUG) - std::cout << retval << std::endl; return retval; } diff --git a/packet.h b/packet.h index c70bdc6..4d412b3 100644 --- a/packet.h +++ b/packet.h @@ -7,6 +7,7 @@ #include #include #include +#include "nethogs.h" extern "C" { @@ -54,6 +55,6 @@ private: short int sa_family; }; -Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet); +Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, packet_type packettype); #endif diff --git a/process.cpp b/process.cpp index 6e85985..006b571 100644 --- a/process.cpp +++ b/process.cpp @@ -97,8 +97,6 @@ void addtoconninode (char * buffer) if (strlen(local_addr) > 8) { /* this is an IPv6-style row */ - if (DEBUG) - fprintf (stderr, "IPv6-style row\n"); /* Demangle what the kernel gives us */ sscanf(local_addr, "%08X%08X%08X%08X", @@ -112,15 +110,11 @@ void addtoconninode (char * buffer) && (in6_local.s6_addr32[2] == 0xFFFF0000)) { /* IPv4-compatible address */ - if (DEBUG) - fprintf (stderr, "IPv4-compatible address\n"); result_addr_local = *((struct in6_addr*) &(in6_local.s6_addr32[3])); result_addr_remote = *((struct in6_addr*) &(in6_remote.s6_addr32[3])); sa_family = AF_INET; } else { /* real IPv6 address */ - if (DEBUG) - fprintf (stderr, "IPv6 address\n"); inet_ntop(AF_INET6, &in6_local, addr6, sizeof(addr6)); INET6_getsock(addr6, (struct sockaddr *) &localaddr); inet_ntop(AF_INET6, &in6_remote, addr6, sizeof(addr6)); @@ -150,8 +144,8 @@ void addtoconninode (char * buffer) free (local_string); free (remote_string); - if (DEBUG) - fprintf (stderr, "Hashkey: %s\n", hashkey); + //if (DEBUG) + // fprintf (stderr, "Hashkey: %s\n", hashkey); conninode->add(hashkey, (void *)inode); @@ -403,7 +397,11 @@ Process * getProcess (unsigned long inode, char * devicename) prg_cache_load(); node = prg_cache_get(inode); if (node == NULL) + { + if (DEBUG) + std::cerr << "Unknown inode " << inode << ", assuming unknown." << endl; return unknownproc; + } } ProcList * current = processes; @@ -468,9 +466,8 @@ Process * getProcess (Connection * connection, char * devicename) if (inode == NULL) { delete reversepacket; -#if DEBUG - std::cerr << connection->refpacket->gethashstring() << " STILL not in table - adding to the unknown process\n"; -#endif + if (DEBUG) + std::cerr << connection->refpacket->gethashstring() << " STILL not in table - adding to the unknown process\n"; unknownproc->connections = new ConnList (connection, unknownproc->connections); return unknownproc; }