Commit 6197223f by pdw

Applied patch from Mats Erik Andersson <mats.andersson@gisladisker.se>

parent 6d594acb
......@@ -11,6 +11,19 @@
int compare(void* a, void* b) {
addr_pair* aa = (addr_pair*)a;
addr_pair* bb = (addr_pair*)b;
if (aa->af != bb->af)
return 0;
if (aa->af == AF_INET6) {
return (IN6_ARE_ADDR_EQUAL(&aa->src6, &bb->src6)
&& aa->src_port == bb->src_port
&& IN6_ARE_ADDR_EQUAL(&aa->dst6, &bb->dst6)
&& aa->dst_port == bb->dst_port
&& aa->protocol == bb->protocol);
}
/* AF_INET or unknown. */
return (aa->src.s_addr == bb->src.s_addr
&& aa->src_port == bb->src_port
&& aa->dst.s_addr == bb->dst.s_addr
......@@ -18,25 +31,42 @@ int compare(void* a, void* b) {
&& aa->protocol == bb->protocol);
}
static int __inline__ hash_uint32(uint32_t n) {
return ((n & 0x000000FF)
+ ((n & 0x0000FF00) >> 8)
+ ((n & 0x00FF0000) >> 16)
+ ((n & 0xFF000000) >> 24));
}
int hash(void* key) {
int hash;
long addr;
addr_pair* ap = (addr_pair*)key;
addr = (long)ap->src.s_addr;
hash = ((addr & 0x000000FF)
+ (addr & 0x0000FF00 >> 8)
+ (addr & 0x00FF0000 >> 16)
+ (addr & 0xFF000000 >> 24)
+ ap->src_port) % 0xFF;
addr = (long)ap->dst.s_addr;
hash = ( hash + (addr & 0x000000FF)
+ (addr & 0x0000FF00 >> 8)
+ (addr & 0x00FF0000 >> 16)
+ (addr & 0xFF000000 >> 24)
+ ap->dst_port) % 0xFF;
if (ap->af == AF_INET6) {
uint32_t* addr6 = ap->src6.s6_addr32;
hash = ( hash_uint32(addr6[0])
+ hash_uint32(addr6[1])
+ hash_uint32(addr6[2])
+ hash_uint32(addr6[3])
+ ap->src_port) % 0xFF;
addr6 = ap->dst6.s6_addr32;
hash = ( hash + hash_uint32(addr6[0])
+ hash_uint32(addr6[1])
+ hash_uint32(addr6[2])
+ hash_uint32(addr6[3])
+ ap->dst_port) % 0xFF;
} else {
in_addr_t addr = ap->src.s_addr;
hash = ( hash_uint32(addr)
+ ap->src_port) % 0xFF;
addr = ap->dst.s_addr;
hash = ( hash + hash_uint32(addr)
+ ap->dst_port) % 0xFF;
}
return hash;
}
......
......@@ -12,11 +12,18 @@
#include "hash.h"
typedef struct {
int af;
unsigned short int protocol;
unsigned short int src_port;
struct in_addr src;
union {
struct in_addr src;
struct in6_addr src6;
};
unsigned short int dst_port;
struct in_addr dst;
union {
struct in_addr dst;
struct in6_addr dst6;
};
} addr_pair;
typedef addr_pair key_type; /* index into hash table */
......
......@@ -18,12 +18,17 @@
#include <net/if.h>
#include <netinet/in.h>
#if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
#if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ \
|| ( defined __GNUC__ && ! defined __linux__ )
#include <sys/param.h>
#include <sys/sysctl.h>
#include <net/if_dl.h>
#endif
#ifdef USE_GETIFADDRS
#include <ifaddrs.h>
#endif
#include "iftop.h"
/*
......@@ -40,16 +45,20 @@
*/
int
get_addrs_ioctl(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr)
get_addrs_ioctl(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr, struct in6_addr *if_ip6_addr)
{
int s;
struct ifreq ifr = {};
int got_hw_addr = 0;
int got_ip_addr = 0;
int got_ip6_addr = 0;
#ifdef USE_GETIFADDRS
struct ifaddrs *ifa, *ifas;
#endif
/* -- */
s = socket(PF_INET, SOCK_DGRAM, 0); /* any sort of IP socket will do */
s = socket(AF_INET, SOCK_DGRAM, 0); /* any sort of IP socket will do */
if (s == -1) {
perror("socket");
......@@ -71,7 +80,8 @@ get_addrs_ioctl(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr)
got_hw_addr = 1;
}
#else
#if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
#if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ \
|| ( defined __GNUC__ && ! defined __linux__ )
{
int sysctlparam[6] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
size_t needed = 0;
......@@ -109,7 +119,45 @@ get_addrs_ioctl(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr)
#endif
/* Get the IP address of the interface */
#ifdef SIOCGIFADDR
#ifdef USE_GETIFADDRS
if (getifaddrs(&ifas) == -1) {
fprintf(stderr, "Unable to get IP address for interface: %s\n", interface);
perror("getifaddrs()");
}
else {
for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
if (got_ip_addr && got_ip6_addr)
break; /* Search is already complete. */
if (strcmp(ifa->ifa_name, interface))
continue; /* Not our interface. */
if ( (ifa->ifa_addr->sa_family != AF_INET)
&& (ifa->ifa_addr->sa_family != AF_INET6) )
continue; /* AF_PACKET is beyond our scope. */
if ( (ifa->ifa_addr->sa_family == AF_INET)
&& !got_ip_addr ) {
got_ip_addr = 2;
memcpy(if_ip_addr,
&(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr),
sizeof(*if_ip_addr));
continue;
}
/* Must be a IPv6 address at this point. */
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) ifa->ifa_addr;
if ( IN6_IS_ADDR_LINKLOCAL(&(sa6->sin6_addr))
|| IN6_IS_ADDR_SITELOCAL(&(sa6->sin6_addr)) )
continue;
/* A useful IPv6 address. */
memcpy(if_ip6_addr, &(sa6->sin6_addr), sizeof(*if_ip6_addr));
got_ip6_addr = 4;
}
freeifaddrs(ifas);
} /* getifaddrs() */
#elif defined(SIOCGIFADDR)
(*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET;
if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
fprintf(stderr, "Unable to get IP address for interface: %s\n", interface);
......@@ -125,5 +173,5 @@ get_addrs_ioctl(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr)
close(s);
return got_hw_addr + got_ip_addr;
return got_hw_addr + got_ip_addr + got_ip6_addr;
}
......@@ -36,6 +36,8 @@ char * config_directives[] = {
"log-scale",
"max-bandwidth",
"net-filter",
"net-filter6",
"link-local",
"port-display",
NULL
};
......
......@@ -11,8 +11,8 @@ iftop - display bandwidth usage on an interface by host
.SH SYNOPSIS
\fBiftop\fP \fB-h\fP |
[\fB-nNpbBP\fP] [\fB-i\fP \fIinterface\fP] [\fB-f\fP \fIfilter code\fP] [\fB-F\fP \fInet\fP/\fImask\fP]
[\fB-nNpblBP\fP] [\fB-i\fP \fIinterface\fP] [\fB-f\fP \fIfilter code\fP] [\fB-F\fP \fInet\fP/\fImask\fP]
[\fB-G\fP \fInet6\fP/\fImask6\fP]
.SH DESCRIPTION
\fBiftop\fP listens to network traffic on a named \fIinterface\fP, or on the
first interface it can find which looks like an external interface if none is
......@@ -65,6 +65,10 @@ the specified interface is also counted.
\fB-P\fP
Turn on port display.
.TP
\fB-l\fP
Display and count datagrams addressed to or from link-local IPv6 addresses.
The default is not to display that address category.
.TP
\fB-b\fP
Don't display bar graphs of traffic.
.TP
......@@ -79,12 +83,17 @@ Use \fIfilter code\fP to select the packets to count. Only IP packets are ever
counted, so the specified code is evaluated as \fB(\fP\fIfilter code\fP\fB) and ip\fP.
.TP
\fB-F\fP \fInet\fP/\fImask\fP
Specifies a network for traffic analysis. If specified, iftop will only
Specifies an IPv4 network for traffic analysis. If specified, iftop will only
include packets flowing in to or out of the given network, and packet direction
is determined relative to the network boundary, rather than to the interface.
You may specify \fImask\fP as a dotted quad, such as /255.255.255.0, or as a
single number specifying the number of bits set in the netmask, such as /24.
.TP
\fB-G\fP \fInet6\fP/\fImask6\fP
Specifies an IPv6 network for traffic analysis. The value of \fImask6\fP can be
given as a prefix length or as a numerical address string for more compound
bitmasking.
.TP
\fB-c\fP \fIconfig file\fP
Specifies an alternate config file. If not specified, iftop will use
\fB~/.iftoprc\fP if it exists. See below for a description of config files
......@@ -213,6 +222,9 @@ Puts the interface into promiscuous mode.
\fBport-display:\fP \fI(off|source-only|destination-only|on)\fP
Controls display of port numbers.
.TP
\fBlink-local:\fP \fI(yes|no)\fP
Determines displaying of link-local IPv6 addresses.
.TP
\fBhide-source:\fP \fI(yes|no)\fP
Hides source host names.
.TP
......@@ -240,6 +252,9 @@ Fixes the maximum for the bar graph scale to \fIbw\fP, e.g. "10M". Note that the
\fBnet-filter:\fP \fInet/mask\fP
Defines an IP network boundary for determining packet direction.
.TP
\fBnet-filter6:\fP \fInet6/mask6\fP
Defines an IPv6 network boundary for determining packet direction.
.TP
\fBscreen-filter:\fP \fIregexp\fP
Sets a regular expression to filter screen output.
......
......@@ -2,6 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in_systm.h>
......@@ -14,29 +15,36 @@
#define hash_table_size 256
int ns_hash_compare(void* a, void* b) {
struct in_addr* aa = (struct in_addr*)a;
struct in_addr* bb = (struct in_addr*)b;
return (aa->s_addr == bb->s_addr);
struct in6_addr* aa = (struct in6_addr*)a;
struct in6_addr* bb = (struct in6_addr*)b;
return IN6_ARE_ADDR_EQUAL(aa, bb);
}
static int __inline__ hash_uint32(uint32_t n) {
return ((n & 0x000000FF)
+ ((n & 0x0000FF00) >> 8)
+ ((n & 0x00FF0000) >> 16)
+ ((n & 0xFF000000) >> 24));
}
int ns_hash_hash(void* key) {
int hash;
long addr;
addr = (long)((struct in_addr*)key)->s_addr;
uint32_t* addr6 = ((struct in6_addr *) key)->s6_addr32;
hash = ((addr & 0x000000FF)
+ (addr & 0x0000FF00 >> 8)
+ (addr & 0x00FF0000 >> 16)
+ (addr & 0xFF000000 >> 24)) % 0xFF;
hash = ( hash_uint32(addr6[0])
+ hash_uint32(addr6[1])
+ hash_uint32(addr6[2])
+ hash_uint32(addr6[3])) % 0xFF;
return hash;
}
void* ns_hash_copy_key(void* orig) {
struct in_addr* copy;
struct in6_addr* copy;
copy = xmalloc(sizeof *copy);
*copy = *(struct in_addr*)orig;
memcpy(copy, orig, sizeof *copy);
return copy;
}
......
......@@ -30,7 +30,7 @@
options_t options;
char optstr[] = "+i:f:nNF:hpbBPm:c:";
char optstr[] = "+i:f:nNF:G:lhpbBPm:c:";
/* Global options. */
......@@ -118,6 +118,10 @@ void options_set_defaults() {
options.netfilter = 0;
inet_aton("10.0.1.0", &options.netfilternet);
inet_aton("255.255.255.0", &options.netfiltermask);
options.netfilter6 = 0;
inet_pton(AF_INET6, "fe80::", &options.netfilter6net); /* Link-local */
inet_pton(AF_INET6, "ffff::", &options.netfilter6mask);
options.link_local = 0;
options.dnsresolution = 1;
options.portresolution = 1;
#ifdef NEED_PROMISCUOUS_FOR_OUTGOING
......@@ -237,7 +241,8 @@ static void usage(FILE *fp) {
fprintf(fp,
"iftop: display bandwidth usage on an interface by host\n"
"\n"
"Synopsis: iftop -h | [-npbBP] [-i interface] [-f filter code] [-N net/mask]\n"
"Synopsis: iftop -h | [-npblBP] [-i interface] [-f filter code]\n"
" [-F net/mask] [-G net6/mask6]\n"
"\n"
" -h display this message\n"
" -n don't do hostname lookups\n"
......@@ -249,7 +254,9 @@ static void usage(FILE *fp) {
" -i interface listen on named interface\n"
" -f filter code use filter code to select packets to count\n"
" (default: none, but only IP packets are counted)\n"
" -F net/mask show traffic flows in/out of network\n"
" -F net/mask show traffic flows in/out of IPv4 network\n"
" -G net6/mask6 show traffic flows in/out of IPv6 network\n"
" -l display and count link-local IPv6 traffic (default: off)\n"
" -P show ports as well as hosts\n"
" -m limit sets the upper limit for the bandwidth scale\n"
" -c config file specifies an alternative configuration file\n"
......@@ -285,6 +292,10 @@ void options_read_args(int argc, char **argv) {
config_set_string("filter-code", optarg);
break;
case 'l':
config_set_string("link-local", "true");
break;
case 'p':
config_set_string("promiscuous", "true");
break;
......@@ -297,6 +308,10 @@ void options_read_args(int argc, char **argv) {
config_set_string("net-filter", optarg);
break;
case 'G':
config_set_string("net-filter6", optarg);
break;
case 'm':
config_set_string("max-bandwidth", optarg);
break;
......@@ -438,6 +453,8 @@ int options_config_get_net_filter() {
if(s) {
char* mask;
options.netfilter = 0;
mask = strchr(s, '/');
if (mask == NULL) {
fprintf(stderr, "Could not parse net/mask: %s\n", s);
......@@ -455,7 +472,7 @@ int options_config_get_net_filter() {
int n;
n = atoi(mask);
if (n > 32) {
fprintf(stderr, "Invalid netmask: %s\n", s);
fprintf(stderr, "Invalid netmask length: %s\n", mask);
}
else {
if(n == 32) {
......@@ -470,17 +487,86 @@ int options_config_get_net_filter() {
options.netfiltermask.s_addr = htonl(~mm);
}
}
options.netfilter = 1;
}
else if (inet_aton(mask, &options.netfiltermask) == 0) {
fprintf(stderr, "Invalid netmask: %s\n", s);
else {
if (inet_aton(mask, &options.netfiltermask) != 0)
options.netfilter = 1;
else {
fprintf(stderr, "Invalid netmask: %s\n", s);
return 0;
}
}
options.netfilternet.s_addr = options.netfilternet.s_addr & options.netfiltermask.s_addr;
options.netfilter = 1;
return 1;
}
return 0;
}
/*
* Read the net filter IPv6 option.
*/
int options_config_get_net_filter6() {
char* s;
int j;
s = config_get_string("net-filter6");
if(s) {
char* mask;
options.netfilter6 = 0;
mask = strchr(s, '/');
if (mask == NULL) {
fprintf(stderr, "Could not parse IPv6 net/prefix: %s\n", s);
return 0;
}
*mask = '\0';
mask++;
if (inet_pton(AF_INET6, s, &options.netfilter6net) == 0) {
fprintf(stderr, "Invalid IPv6 network address: %s\n", s);
return 0;
}
/* Accept prefix lengths and address expressions. */
if (mask[strspn(mask, "0123456789")] == '\0') {
/* Whole string is numeric */
unsigned int n;
n = atoi(mask);
if (n > 128 || n < 1) {
fprintf(stderr, "Invalid IPv6 prefix length: %s\n", mask);
}
else {
int bl, rem;
const uint32_t mm = 0xffffffff;
uint32_t part = mm;
bl = n / 32;
rem = n % 32;
part <<= 32 - rem;
for (j=0; j < bl; ++j)
options.netfilter6mask.s6_addr32[j] = htonl(mm);
if (rem > 0)
options.netfilter6mask.s6_addr32[bl] = htonl(part);
options.netfilter6 = 1;
}
}
else {
if (inet_pton(AF_INET6, mask, &options.netfilter6mask) != 0)
options.netfilter6 = 1;
else {
fprintf(stderr, "Invalid IPv6 netmask: %s\n", s);
return 0;
}
}
/* Prepare any comparison by masking the provided filtered net. */
for (j=0; j < 4; ++j)
options.netfilter6net.s6_addr32[j] &= options.netfilter6mask.s6_addr32[j];
return 1;
}
return 0;
}
void options_make() {
options_config_get_string("interface", &options.interface);
......@@ -499,5 +585,7 @@ void options_make() {
options_config_get_bw_rate("max-bandwidth", &options.max_bandwidth);
options_config_get_enum("port-display", showports_enumeration, (int*)&options.showports);
options_config_get_string("screen-filter", &options.screenfilter);
options_config_get_bool("link-local", &options.link_local);
options_config_get_net_filter();
options_config_get_net_filter6();
};
......@@ -78,6 +78,13 @@ typedef struct {
struct in_addr netfilternet;
struct in_addr netfiltermask;
int netfilter6;
struct in6_addr netfilter6net;
struct in6_addr netfilter6mask;
/* Account for link-local traffic. */
int link_local;
char *config_file;
int config_file_specified;
......
......@@ -25,7 +25,7 @@
#define RESOLVE_QUEUE_LENGTH 20
struct in_addr resolve_queue[RESOLVE_QUEUE_LENGTH];
struct in6_addr resolve_queue[RESOLVE_QUEUE_LENGTH];
pthread_cond_t resolver_queue_cond;
pthread_mutex_t resolver_queue_mutex;
......@@ -55,18 +55,48 @@ extern options_t options;
* as NetBSD break the RFC and implement it in a non-thread-safe fashion, so
* for the moment, the configure script won't try to use it.
*/
char *do_resolve(struct in_addr *addr) {
struct sockaddr_in sin = {0};
char *do_resolve(struct in6_addr *addr) {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
char buf[NI_MAXHOST]; /* 1025 */
int res;
sin.sin_family = AF_INET;
sin.sin_addr = *addr;
sin.sin_port = 0;
if (getnameinfo((struct sockaddr*)&sin, sizeof sin, buf, sizeof buf, NULL, 0, NI_NAMEREQD) == 0)
return xstrdup(buf);
else
return NULL;
int res, af;
uint32_t* probe;
memset(&sin, '\0', sizeof(sin));
memset(&sin6, '\0', sizeof(sin6));
/* If the upper three (network byte order) uint32-parts
* are null, then there ought to be an IPv4 address here.
* Any such IPv6 would have to be 'xxxx::'. Neglectable? */
probe = (uint32_t *) addr;
af = (probe[1] || probe[2] || probe[3]) ? AF_INET6 : AF_INET;
switch (af) {
case AF_INET:
sin.sin_family = af;
sin.sin_port = 0;
memcpy(&sin.sin_addr, addr, sizeof(sin.sin_addr));
if (getnameinfo((struct sockaddr*)&sin, sizeof sin,
buf, sizeof buf, NULL, 0, NI_NAMEREQD) == 0)
return xstrdup(buf);
else
return NULL;
break;
case AF_INET6:
sin6.sin6_family = af;
sin6.sin6_port = 0;
memcpy(&sin6.sin6_addr, addr, sizeof(sin6.sin6_addr));
if (getnameinfo((struct sockaddr*)&sin6, sizeof sin6,
buf, sizeof buf, NULL, 0, NI_NAMEREQD) == 0)
return xstrdup(buf);
else
return NULL;
break;
default:
return NULL;
}
}
#elif defined(USE_GETHOSTBYADDR_R)
......@@ -376,7 +406,7 @@ void resolver_worker(void* ptr) {
/* Keep resolving until the queue is empty */
while(head != tail) {
char * hostname;
struct in_addr addr = resolve_queue[tail];
struct in6_addr addr = resolve_queue[tail];
/* mutex always locked at this point */
......@@ -427,7 +457,7 @@ void resolver_initialise() {
}
void resolve(struct in_addr* addr, char* result, int buflen) {
void resolve(int af, struct in6_addr* addr, char* result, int buflen) {
char* hostname;
union {
char **ch_pp;
......@@ -443,12 +473,18 @@ void resolve(struct in_addr* addr, char* result, int buflen) {
/* Found => already resolved, or on the queue */
}
else {
hostname = strdup(inet_ntoa(*addr));
hostname = xmalloc(INET6_ADDRSTRLEN);
inet_ntop(af, addr, hostname, INET6_ADDRSTRLEN);
hash_insert(ns_hash, addr, hostname);
if(((head + 1) % RESOLVE_QUEUE_LENGTH) == tail) {
/* queue full */
}
else if((af == AF_INET6)
&& (IN6_IS_ADDR_LINKLOCAL(addr)
|| IN6_IS_ADDR_SITELOCAL(addr))) {
/* Link-local and site-local stay numerical. */
}
else {
resolve_queue[head] = *addr;
head = (head + 1) % RESOLVE_QUEUE_LENGTH;
......
......@@ -14,6 +14,6 @@
void resolver_initialise(void);
void resolve(struct in_addr* addr, char* result, int buflen);
void resolve(int af, struct in6_addr* addr, char* result, int buflen);
#endif /* __RESOLVER_H_ */
......@@ -53,11 +53,11 @@ void stringmap_delete_free(stringmap S) {
}
/* stringmap_insert:
* Insert into S an item having key k and value d. Returns an existing key
* or NULL if it was inserted.
* Insert into S an item having key k and value d. Returns a pointer to
* the existing item value, or NULL if a new item was created.
*/
item *stringmap_insert(stringmap S, const char *k, const item d) {
if (!S) return 0;
if (!S) return NULL;
if (S->key == NULL) {
S->key = xstrdup(k);
S->d = d;
......
......@@ -109,19 +109,19 @@ int screen_line_bandwidth_compare(host_pair_line* aa, host_pair_line* bb, int st
* Compare two screen lines based on hostname / IP. Fall over to compare by
* bandwidth.
*/
int screen_line_host_compare(struct in_addr* a, struct in_addr* b, host_pair_line* aa, host_pair_line* bb) {
int screen_line_host_compare(void* a, void* b, host_pair_line* aa, host_pair_line* bb) {
char hosta[HOSTNAME_LENGTH], hostb[HOSTNAME_LENGTH];
int r;
/* This isn't overly efficient because we resolve again before
display. */
if (options.dnsresolution) {
resolve(a, hosta, HOSTNAME_LENGTH);
resolve(b, hostb, HOSTNAME_LENGTH);
resolve(aa->ap.af, a, hosta, HOSTNAME_LENGTH);
resolve(bb->ap.af, b, hostb, HOSTNAME_LENGTH);
}
else {
strcpy(hosta, inet_ntoa(*a));
strcpy(hostb, inet_ntoa(*b));
inet_ntop(aa->ap.af, a, hosta, sizeof(hosta));
inet_ntop(bb->ap.af, b, hostb, sizeof(hostb));
}
r = strcmp(hosta, hostb);
......@@ -149,10 +149,10 @@ int screen_line_compare(void* a, void* b) {
return screen_line_bandwidth_compare(aa, bb, 2);
}
else if(options.sort == OPTION_SORT_SRC) {
return screen_line_host_compare(&(aa->ap.src), &(bb->ap.src), aa, bb);
return screen_line_host_compare(&(aa->ap.src6), &(bb->ap.src6), aa, bb);
}
else if(options.sort == OPTION_SORT_DEST) {
return screen_line_host_compare(&(aa->ap.dst), &(bb->ap.dst), aa, bb);
return screen_line_host_compare(&(aa->ap.dst6), &(bb->ap.dst6), aa, bb);
}
return 1;
......@@ -487,10 +487,10 @@ void analyse_data() {
/* Aggregate hosts, if required */
if(options.aggregate_src) {
ap.src.s_addr = 0;
memset(&ap.src6, '\0', sizeof(ap.src6));
}
if(options.aggregate_dest) {
ap.dst.s_addr = 0;
memset(&ap.dst6, '\0', sizeof(ap.dst6));
}
/* Aggregate ports, if required */
......@@ -535,7 +535,7 @@ void analyse_data() {
}
void sprint_host(char * line, struct in_addr* addr, unsigned int port, unsigned int protocol, int L) {
void sprint_host(char * line, int af, struct in6_addr* addr, unsigned int port, unsigned int protocol, int L) {
char hostname[HOSTNAME_LENGTH];
char service[HOSTNAME_LENGTH];
char* s_name;
......@@ -546,14 +546,15 @@ void sprint_host(char * line, struct in_addr* addr, unsigned int port, unsigned
ip_service skey;
int left;
if(addr->s_addr == 0) {
if(IN6_IS_ADDR_UNSPECIFIED(addr)) {
sprintf(hostname, " * ");
}
else {
if (options.dnsresolution)
resolve(addr, hostname, L);
resolve(af, addr, hostname, L);
else
strcpy(hostname, inet_ntoa(*addr));
inet_ntop(af, addr, hostname, sizeof(hostname));
}
left = strlen(hostname);
......@@ -637,8 +638,15 @@ void ui_print() {
L = HOSTNAME_LENGTH;
}
sprint_host(host1, &(screen_line->ap.src), screen_line->ap.src_port, screen_line->ap.protocol, L);
sprint_host(host2, &(screen_line->ap.dst), screen_line->ap.dst_port, screen_line->ap.protocol, L);
sprint_host(host1, screen_line->ap.af,
&(screen_line->ap.src6),