diff --git a/nethogs.h b/nethogs.h index 2b38d5e..5cffe48 100644 --- a/nethogs.h +++ b/nethogs.h @@ -19,7 +19,7 @@ #define NEEDROOT 1 #endif -#define DEBUG 0 +#define DEBUG 1 #define PROGNAME_WIDTH 27 diff --git a/packet.cpp b/packet.cpp index 95ceb8a..3f4b194 100644 --- a/packet.cpp +++ b/packet.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include // #include "inet6.c" @@ -38,12 +40,12 @@ void getLocal (const char *device) typedef u_int32_t tcp_seq; -/* ethernet header */ -struct ethernet_hdr { +/* ethernet header (now unused) */ +/*struct ethernet_hdr { u_char ether_dhost[ETHER_ADDR_LEN]; u_char ether_shost[ETHER_ADDR_LEN]; - u_short ether_type; /* IP? */ -}; + u_short ether_type; +};*/ /* IP header */ struct ip_hdr @@ -104,26 +106,42 @@ Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet) { //const struct ethernet_hdr * ethernet = (struct ethernet_hdr *)packet; const struct ether_header * ethernet = (struct ether_header *)packet; - if (ethernet->ether_type != 8) + /* 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) { + //const struct ip_hdr * ip = (struct ip_hdr *)(packet + sizeof(ether_header)); + const struct ip * ip = (struct ip *)(packet + sizeof(ether_header)); + if (ip->ip_p != 6) + { #if DEBUG - std::cerr << "Dropped non-ip packet of type " << ethernet->ether_type << std::endl; + std::cerr << "Dropped non-tcp IPv4 packet of type " << (int)(ip->ip_p) << std::endl; #endif - return NULL; + return NULL; + } + const struct tcp_hdr * tcp = (struct tcp_hdr *)(packet + sizeof(ether_header) + sizeof(ip_hdr)); + 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)); + if ((ip6->ip6_ctlun).ip6_un1.ip6_un1_nxt != 0x06) + { + // TODO maybe we need to skip over some headers? +#if DEBUG + std::cerr << "Dropped non-tcp IPv6 header of type " << (int)((ip6->ip6_ctlun).ip6_un1.ip6_un1_nxt) << std::endl; +#endif + return NULL; + } + const struct tcp_hdr * tcp = (struct tcp_hdr *)(packet + sizeof(ether_header) + 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); } - const struct ip_hdr * ip = (struct ip_hdr *)(packet + sizeof(ethernet_hdr)); - if (ip->ip_p != 6) - { #if DEBUG - std::cerr << "Dropped non-tcp packet of type " << (int)(ip->ip_p) << std::endl; + std::cerr << "Dropped non-ip packet of type " << ethernet->ether_type << std::endl; #endif - return NULL; - } - - const struct tcp_hdr * tcp = (struct tcp_hdr *)(packet + sizeof(ethernet_hdr) + sizeof(ip_hdr)); - - return new Packet (ip->ip_src, ntohs(tcp->th_sport), ip->ip_dst, ntohs(tcp->th_dport), header->len, header->ts); + 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) @@ -181,16 +199,18 @@ bool Packet::Outgoing () { char * Packet::gethashstring () { // TODO this needs to be bigger to support ipv6?! + char * tempretval = (char *) malloc (92 * sizeof(char)); char * retval = (char *) malloc (92 * sizeof(char)); if (Outgoing()) { - snprintf(retval, 92 * sizeof(char), "%s:%d-", inet_ntoa(sip), sport); - snprintf(retval, 92 * sizeof(char), "%s%s:%d", retval, inet_ntoa(dip), dport); + snprintf(tempretval, 92 * sizeof(char), "%s:%d-", inet_ntoa(sip), sport); + snprintf(retval, 92 * sizeof(char), "%s%s:%d", tempretval, inet_ntoa(dip), dport); } else { - snprintf(retval, 92 * sizeof(char), "%s:%d-", inet_ntoa(dip), dport); - snprintf(retval, 92 * sizeof(char), "%s%s:%d", retval, inet_ntoa(sip), sport); + snprintf(tempretval, 92 * sizeof(char), "%s:%d-", inet_ntoa(dip), dport); + snprintf(retval, 92 * sizeof(char), "%s%s:%d", tempretval, inet_ntoa(sip), sport); } //if (DEBUG) //cout << "hasshtring: " << retval << endl; + free (tempretval); return retval; } diff --git a/process.cpp b/process.cpp index 8110d56..53149a3 100644 --- a/process.cpp +++ b/process.cpp @@ -68,6 +68,9 @@ HashTable * conninode = new HashTable (256); * 10: 020310AC:1770 9DD8A9C3:A525 01 00000000:00000000 00:00000000 00000000 0 0 2119 1 c0f4f0c0 206 40 10 3 -1 * 11: 020310AC:0404 936B2ECF:0747 01 00000000:00000000 00:00000000 00000000 1000 0 2109 1 c0f4fc00 368 40 20 2 -1 * + * and of the form: + * 2: 0000000000000000FFFF0000020310AC:0016 0000000000000000FFFF00009DD8A9C3:A526 01 00000000:00000000 02:000A7214 00000000 0 0 2525 2 c732eca0 201 40 1 2 -1 + * */ // TODO check what happens to the 'content' field of the hash void addtoconninode (char * buffer) @@ -76,7 +79,8 @@ void addtoconninode (char * buffer) int local_port, rem_port; struct sockaddr_in6 localaddr, remaddr; char addr6[INET6_ADDRSTRLEN]; - struct in6_addr in6; + struct in6_addr in6_local; + struct in6_addr in6_remote; extern struct aftype inet6_aftype; // the following line leaks memory. unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long)); @@ -86,22 +90,43 @@ 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", - &in6.s6_addr32[0], &in6.s6_addr32[1], - &in6.s6_addr32[2], &in6.s6_addr32[3]); - inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); - INET6_getsock(addr6, (struct sockaddr *) &localaddr); + &in6_local.s6_addr32[0], &in6_local.s6_addr32[1], + &in6_local.s6_addr32[2], &in6_local.s6_addr32[3]); sscanf(rem_addr, "%08X%08X%08X%08X", - &in6.s6_addr32[0], &in6.s6_addr32[1], - &in6.s6_addr32[2], &in6.s6_addr32[3]); - inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); - INET6_getsock(addr6, (struct sockaddr *) &remaddr); - localaddr.sin6_family = AF_INET6; - remaddr.sin6_family = AF_INET6; + &in6_remote.s6_addr32[0], &in6_remote.s6_addr32[1], + &in6_remote.s6_addr32[2], &in6_remote.s6_addr32[3]); + + if ((in6_local.s6_addr32[0] == 0x0) && (in6_local.s6_addr32[1] == 0x0) + && (in6_local.s6_addr32[2] == 0xFFFF0000)) + { + /* IPv4-compatible address */ + if (DEBUG) + fprintf (stderr, "IPv4-compatible address\n"); + ((struct sockaddr_in *)&localaddr)->sin_addr.s_addr = in6_local.s6_addr32[3]; + ((struct sockaddr_in *)&remaddr)->sin_addr.s_addr = in6_remote.s6_addr32[3]; + ((struct sockaddr *) &localaddr)->sa_family = AF_INET; + ((struct sockaddr *) &remaddr)->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)); + INET6_getsock(addr6, (struct sockaddr *) &remaddr); + localaddr.sin6_family = AF_INET6; + remaddr.sin6_family = AF_INET6; + } } else { + /* this is an IPv4-style row */ sscanf(local_addr, "%X", &((struct sockaddr_in *)&localaddr)->sin_addr.s_addr); sscanf(rem_addr, "%X", &((struct sockaddr_in *)&remaddr)->sin_addr.s_addr); ((struct sockaddr *) &localaddr)->sa_family = AF_INET; @@ -109,216 +134,22 @@ void addtoconninode (char * buffer) } /* Construct hash key and add inode to conninode table */ + char * temphashkey = (char *) malloc (92 * sizeof(char)); char * hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - conninode->add(hashkey, (void *)inode); - // TODO maybe also add this inode for our other local addresses with that destination - - return; + /* TODO make this support the ipv6 addresses properly */ + snprintf(temphashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); + snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", temphashkey, inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); + free (temphashkey); - /* - * OLD CODE BELOW - dead now. - * - * - if (strcmp(inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), "172.16.3.1") == 0) - { - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", "195.169.216.157", local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - conninode->add(hashkey, (void *)inode); - } - if (strcmp(inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), "172.16.3.1") == 0) - { - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, "195.169.216.157", rem_port); - conninode->add(hashkey, (void *)inode); - } - if (strcmp(inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), "195.169.216.157") == 0) - { - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", "172.16.3.1", local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - conninode->add(hashkey, (void *)inode); + if (DEBUG) + fprintf (stderr, "Hashkey: %s\n", hashkey); - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, "172.16.3.1", local_port); - conninode->add(hashkey, (void *)inode); - } - if (strcmp(inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), "195.169.216.157") == 0) - { - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, "172.16.3.1", rem_port); - conninode->add(hashkey, (void *)inode); - - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", "172.16.3.1", rem_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - conninode->add(hashkey, (void *)inode); - } - */ -} - -/* - * parses a /proc/net/tcp6-line of the form: - * sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode - * 2: 0000000000000000FFFF0000020310AC:0016 0000000000000000FFFF00009DD8A9C3:A526 01 00000000:00000000 02:000A7214 00000000 0 0 2525 2 c732eca0 201 40 1 2 -1 - * - * For now, we only support 0000000000000000FFFF0000-addresses. - */ -void addtoconninodev6 (char * buffer) -{ - char rem_addr[128], local_addr[128]; - int local_port, rem_port; - struct sockaddr_in6 localaddr, remaddr; - char addr6[INET6_ADDRSTRLEN]; - struct in6_addr in6; - extern struct aftype inet6_aftype; - // the following line leaks memory. - unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long)); - // TODO check it matched - sscanf(buffer, "%*d: 0000000000000000FFFF0000%64[0-9A-Fa-f]:%X 0000000000000000FFFF0000%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 (strlen(local_addr) > 8) - { - /* Demangle what the kernel gives us */ - sscanf(local_addr, "%08X%08X%08X%08X", - &in6.s6_addr32[0], &in6.s6_addr32[1], - &in6.s6_addr32[2], &in6.s6_addr32[3]); - inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); - INET6_getsock(addr6, (struct sockaddr *) &localaddr); - sscanf(rem_addr, "%08X%08X%08X%08X", - &in6.s6_addr32[0], &in6.s6_addr32[1], - &in6.s6_addr32[2], &in6.s6_addr32[3]); - inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); - INET6_getsock(addr6, (struct sockaddr *) &remaddr); - localaddr.sin6_family = AF_INET6; - remaddr.sin6_family = AF_INET6; - } - else - { - sscanf(local_addr, "%X", &((struct sockaddr_in *)&localaddr)->sin_addr.s_addr); - sscanf(rem_addr, "%X", &((struct sockaddr_in *)&remaddr)->sin_addr.s_addr); - ((struct sockaddr *) &localaddr)->sa_family = AF_INET; - ((struct sockaddr *) &remaddr)->sa_family = AF_INET; - } - - /* Construct hash key and add inode to conninode table */ - char * hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); conninode->add(hashkey, (void *)inode); // TODO maybe also add this inode for our other local addresses with that destination } -/* -void addtoconninodev6 (char * buffer) -{ - char rem_addr[128], local_addr[128]; - int local_port, rem_port; - struct sockaddr_in6 localaddr, remaddr; - char addr6[INET6_ADDRSTRLEN]; - struct in6_addr in6; - extern struct aftype inet6_aftype; - // the following line leaks memory. - unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long)); - // TODO check it matched - sscanf(buffer, "%*d: 0000000000000000FFFF0000%64[0-9A-Fa-f]:%X 0000000000000000FFFF0000%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 (strlen(local_addr) > 8) - { - // Demangle what the kernel gives us - sscanf(local_addr, "%08X%08X%08X%08X", - &in6.s6_addr32[0], &in6.s6_addr32[1], - &in6.s6_addr32[2], &in6.s6_addr32[3]); - inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); - INET6_getsock(addr6, (struct sockaddr *) &localaddr); - sscanf(rem_addr, "%08X%08X%08X%08X", - &in6.s6_addr32[0], &in6.s6_addr32[1], - &in6.s6_addr32[2], &in6.s6_addr32[3]); - inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); - INET6_getsock(addr6, (struct sockaddr *) &remaddr); - localaddr.sin6_family = AF_INET6; - remaddr.sin6_family = AF_INET6; - } - else - { - sscanf(local_addr, "%X", &((struct sockaddr_in *)&localaddr)->sin_addr.s_addr); - sscanf(rem_addr, "%X", &((struct sockaddr_in *)&remaddr)->sin_addr.s_addr); - ((struct sockaddr *) &localaddr)->sa_family = AF_INET; - ((struct sockaddr *) &remaddr)->sa_family = AF_INET; - } - - char * hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - conninode->add(hashkey, (void *)inode); - - // also add the reverse. - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - conninode->add(hashkey, (void *)inode); - - // also add the aliases :S - if (strcmp(inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), "172.16.3.1") == 0) - { - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", "195.169.216.157", local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - conninode->add(hashkey, (void *)inode); - - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, "195.169.216.157", local_port); - conninode->add(hashkey, (void *)inode); - } - if (strcmp(inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), "172.16.3.1") == 0) - { - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, "195.169.216.157", rem_port); - conninode->add(hashkey, (void *)inode); - - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", "195.169.216.157", rem_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - conninode->add(hashkey, (void *)inode); - } - if (strcmp(inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), "195.169.216.157") == 0) - { - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", "172.16.3.1", local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - conninode->add(hashkey, (void *)inode); - - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), rem_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, "172.16.3.1", local_port); - conninode->add(hashkey, (void *)inode); - } - if (strcmp(inet_ntoa(((struct sockaddr_in *)&remaddr)->sin_addr), "195.169.216.157") == 0) - { - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, "172.16.3.1", rem_port); - conninode->add(hashkey, (void *)inode); - - hashkey = (char *) malloc (92 * sizeof(char)); - snprintf(hashkey, 92 * sizeof(char), "%s:%d-", "172.16.3.1", rem_port); - snprintf(hashkey, 92 * sizeof(char), "%s%s:%d", hashkey, inet_ntoa(((struct sockaddr_in *)&localaddr)->sin_addr), local_port); - conninode->add(hashkey, (void *)inode); - } -} -*/ - void refreshconninode () { delete conninode; @@ -326,6 +157,9 @@ void refreshconninode () char buffer[8192]; FILE * procinfo = fopen ("/proc/net/tcp", "r"); + + + // TODO use helper function if (procinfo) { fgets(buffer, sizeof(buffer), procinfo); @@ -347,7 +181,7 @@ void refreshconninode () fgets(buffer, sizeof(buffer), procinfo); do { if (fgets(buffer, sizeof(buffer), procinfo)) - addtoconninodev6(buffer); + addtoconninode(buffer); } while (!feof(procinfo)); fclose (procinfo); }