/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* acct.c: traffic accounting
*
verbosef(" local network mask: %s", addr_to_str(&localmask));
}
-static int
-addr_is_local(const struct addr * const a)
-{
- if (a->family == IPv4) {
- if (using_localnet4) {
- if (addr_inside(a, &localnet4, &localmask4))
- return 1;
- } else {
- if (addr_equal(a, &localip4))
- return 1;
- }
- } else {
- assert(a->family == IPv6);
- if (using_localnet6) {
- if (addr_inside(a, &localnet6, &localmask6))
- return 1;
- } else {
- if (addr_equal(a, &localip6))
- return 1;
- }
+static int addr_is_local(const struct addr * const a,
+ const struct local_ips *local_ips) {
+ if (is_localip(a, local_ips))
+ return 1;
+ if (a->family == IPv4 && using_localnet4) {
+ if (addr_inside(a, &localnet4, &localmask4))
+ return 1;
+ } else if (a->family == IPv6 && using_localnet6) {
+ if (addr_inside(a, &localnet6, &localmask6))
+ return 1;
}
return 0;
}
/* Account for the given packet summary. */
-void
-acct_for(const struct pktsummary * const sm)
-{
- struct bucket *hs = NULL, *hd = NULL;
- struct bucket *ps, *pd;
+void acct_for(const struct pktsummary * const sm,
+ const struct local_ips * const local_ips) {
+ struct bucket *hs = NULL; // Source host.
+ struct bucket *hd = NULL; // Dest host.
int dir_in, dir_out;
#if 0 /* WANT_CHATTY? */
acct_total_bytes += sm->len;
/* Graphs. */
- dir_out = addr_is_local(&(sm->src));
- dir_in = addr_is_local(&(sm->dst));
+ dir_out = addr_is_local(&sm->src, local_ips);
+ dir_in = addr_is_local(&sm->dst, local_ips);
/* Traffic staying within the network isn't counted. */
- if (dir_in == 1 && dir_out == 1)
- dir_in = dir_out = 0;
-
- if (dir_out) {
+ if (dir_out && !dir_in) {
daylog_acct((uint64_t)sm->len, GRAPH_OUT);
graph_acct((uint64_t)sm->len, GRAPH_OUT);
}
- if (dir_in) {
+ if (dir_in && !dir_out) {
daylog_acct((uint64_t)sm->len, GRAPH_IN);
graph_acct((uint64_t)sm->len, GRAPH_IN);
}
/* Hosts. */
hosts_db_reduce();
- if (!opt_want_local_only || addr_is_local(&sm->src)) {
+ if (!opt_want_local_only || dir_out) {
hs = host_get(&(sm->src));
hs->out += sm->len;
hs->total += sm->len;
memcpy(hs->u.host.mac_addr, sm->src_mac, sizeof(sm->src_mac));
- hs->u.host.lastseen = now;
+ hs->u.host.last_seen_mono = now_mono();
}
- if (!opt_want_local_only || addr_is_local(&sm->dst)) {
+ if (!opt_want_local_only || dir_in) {
hd = host_get(&(sm->dst));
hd->in += sm->len;
hd->total += sm->len;
/* Protocols. */
if (sm->proto != IPPROTO_INVALID) {
if (hs) {
- ps = host_get_ip_proto(hs, sm->proto);
+ struct bucket *ps = host_get_ip_proto(hs, sm->proto);
ps->out += sm->len;
ps->total += sm->len;
}
if (hd) {
- pd = host_get_ip_proto(hd, sm->proto);
+ struct bucket *pd = host_get_ip_proto(hd, sm->proto);
pd->in += sm->len;
pd->total += sm->len;
}
/* Ports. */
switch (sm->proto) {
case IPPROTO_TCP:
+ // Local ports on host.
if ((sm->src_port <= opt_highest_port) && hs) {
- ps = host_get_port_tcp(hs, sm->src_port);
+ struct bucket *ps = host_get_port_tcp(hs, sm->src_port);
ps->out += sm->len;
ps->total += sm->len;
}
if ((sm->dst_port <= opt_highest_port) && hd) {
- pd = host_get_port_tcp(hd, sm->dst_port);
+ struct bucket *pd = host_get_port_tcp(hd, sm->dst_port);
pd->in += sm->len;
pd->total += sm->len;
if (sm->tcp_flags == TH_SYN)
pd->u.port_tcp.syn++;
}
+
+ // Remote ports.
+ if ((sm->src_port <= opt_highest_port) && hd) {
+ struct bucket *pdr = host_get_port_tcp_remote(hd, sm->src_port);
+ pdr->out += sm->len;
+ pdr->total += sm->len;
+ }
+ if ((sm->dst_port <= opt_highest_port) && hs) {
+ struct bucket *psr = host_get_port_tcp_remote(hs, sm->dst_port);
+ psr->in += sm->len;
+ psr->total += sm->len;
+ if (sm->tcp_flags == TH_SYN)
+ psr->u.port_tcp.syn++;
+ }
break;
case IPPROTO_UDP:
+ // Local ports on host.
if ((sm->src_port <= opt_highest_port) && hs) {
- ps = host_get_port_udp(hs, sm->src_port);
+ struct bucket *ps = host_get_port_udp(hs, sm->src_port);
ps->out += sm->len;
ps->total += sm->len;
}
if ((sm->dst_port <= opt_highest_port) && hd) {
- pd = host_get_port_udp(hd, sm->dst_port);
+ struct bucket *pd = host_get_port_udp(hd, sm->dst_port);
pd->in += sm->len;
pd->total += sm->len;
}
- break;
- case IPPROTO_ICMP:
- case IPPROTO_ICMPV6:
- case IPPROTO_AH:
- case IPPROTO_ESP:
- case IPPROTO_OSPF:
- /* known protocol, don't complain about it */
+ // Remote ports.
+ if ((sm->src_port <= opt_highest_port) && hd) {
+ struct bucket *pdr = host_get_port_udp_remote(hd, sm->src_port);
+ pdr->out += sm->len;
+ pdr->total += sm->len;
+ }
+ if ((sm->dst_port <= opt_highest_port) && hs) {
+ struct bucket *psr = host_get_port_udp_remote(hs, sm->dst_port);
+ psr->in += sm->len;
+ psr->total += sm->len;
+ }
break;
- default:
- verbosef("unknown IP proto (%04x)", sm->proto);
+ case IPPROTO_INVALID:
+ /* proto decoding failed, don't complain in accounting */
+ break;
}
}