From 2b06450a6e1756b6d31a983108a7b553c7cb21d8 Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Tue, 10 May 2011 22:01:25 +1000 Subject: [PATCH] Use struct addr - big cleanup. --- acct.c | 224 +++++++++++++++++++++-------------------------------- acct.h | 6 +- db.c | 31 ++++---- db.h | 9 ++- decode.c | 79 ++++++++----------- decode.h | 24 ++---- dns.c | 90 ++++++++++----------- dns.h | 4 +- hosts_db.c | 140 +++++++++++++++------------------ hosts_db.h | 19 +---- localip.c | 70 +++++++---------- localip.h | 5 +- 12 files changed, 287 insertions(+), 414 deletions(-) diff --git a/acct.c b/acct.c index 65e2bc1..49ec8e2 100644 --- a/acct.c +++ b/acct.c @@ -18,6 +18,7 @@ #include "darkstat.h" #include "acct.h" +#include "decode.h" #include "conv.h" #include "daylog.h" #include "err.h" @@ -29,86 +30,75 @@ #define __FAVOR_BSD #include #include +#include +#include /* for isdigit */ +#include /* for gai_strerror */ #include /* for free */ #include /* for memcpy */ -#include /* isdigit() */ uint64_t total_packets = 0, total_bytes = 0; -static int using_localnet = 0; -static int using_localnet6 = 0; -static in_addr_t localnet, localmask; -static struct in6_addr localnet6, localmask6; +static int using_localnet4 = 0, using_localnet6 = 0; +static struct addr localnet4, localmask4, localnet6, localmask6; /* Parse the net/mask specification into two IPs or die trying. */ void acct_init_localnet(const char *spec) { - char **tokens, *p; - int num_tokens, isnum, j; - int build_ipv6; /* Zero for IPv4, one for IPv6. */ + char **tokens; + int num_tokens, isnum, j, ret; int pfxlen, octets, remainder; - struct in_addr addr; - struct in6_addr addr6; + struct addr localnet, localmask; tokens = split('/', spec, &num_tokens); if (num_tokens != 2) errx(1, "expecting network/netmask, got \"%s\"", spec); - /* Presence of a colon distinguishes address families. */ - if (strchr(tokens[0], ':')) { - build_ipv6 = 1; - if (inet_pton(AF_INET6, tokens[0], &addr6) != 1) - errx(1, "invalid IPv6 network address \"%s\"", tokens[0]); - memcpy(&localnet6, &addr6, sizeof(localnet6)); - } else { - build_ipv6 = 0; - if (inet_pton(AF_INET, tokens[0], &addr) != 1) - errx(1, "invalid network address \"%s\"", tokens[0]); - localnet = addr.s_addr; - } + if ((ret = str_to_addr(tokens[0], &localnet)) != 0) + errx(1, "couldn't parse \"%s\": %s", tokens[0], gai_strerror(ret)); /* Detect a purely numeric argument. */ isnum = 0; - p = tokens[1]; - while (*p != '\0') { - if (isdigit(*p)) { - isnum = 1; - ++p; - continue; - } else { - isnum = 0; - break; + { + const char *p = tokens[1]; + while (*p != '\0') { + if (isdigit(*p)) { + isnum = 1; + ++p; + continue; + } else { + isnum = 0; + break; + } } } if (!isnum) { - if (build_ipv6) { - if (inet_pton(AF_INET6, tokens[1], &addr6) != 1) - errx(1, "invalid IPv6 network mask \"%s\"", tokens[1]); - memcpy(&localmask6, &addr6, sizeof(localmask6)); - } else { - if (inet_pton(AF_INET, tokens[1], &addr) != 1) - errx(1, "invalid network mask \"%s\"", tokens[1]); - localmask = addr.s_addr; - } + if ((ret = str_to_addr(tokens[1], &localmask)) != 0) + errx(1, "couldn't parse \"%s\": %s", tokens[1], gai_strerror(ret)); + if (localmask.family != localnet.family) + errx(1, "family mismatch between net and mask"); } else { uint8_t frac, *p; + localmask.family = localnet.family; + /* Compute the prefix length. */ - pfxlen = strtonum(tokens[1], 1, build_ipv6 ? 128 : 32, NULL); + pfxlen = strtonum(tokens[1], 1, + (localnet.family == IPv6) ? 128 : 32, NULL); if (pfxlen == 0) errx(1, "invalid network prefix length \"%s\"", tokens[1]); /* Construct the network mask. */ octets = pfxlen / 8; remainder = pfxlen % 8; - p = build_ipv6 ? (uint8_t *) localmask6.s6_addr : (uint8_t *) &localmask; + p = (localnet.family == IPv6) ? (localmask.ip.v6.s6_addr) + : ((uint8_t *) &(localmask.ip.v4)); - if (build_ipv6) - memset(&localmask6, 0, sizeof(localmask6)); + if (localnet.family == IPv6) + memset(p, 0, 16); else - memset(&localmask, 0, sizeof(localmask)); + memset(p, 0, 4); for (j = 0; j < octets; ++j) p[j] = 0xff; @@ -118,47 +108,65 @@ acct_init_localnet(const char *spec) p[j] = frac; /* Have contribution for next position. */ } + free(tokens[0]); + free(tokens[1]); + free(tokens); + /* Register the correct netmask and calculate the correct net. */ - if (build_ipv6) { + addr_mask(&localnet, &localmask); + if (localnet.family == IPv6) { using_localnet6 = 1; - for (j = 0; j < 16; ++j) - localnet6.s6_addr[j] &= localmask6.s6_addr[j]; + localnet6 = localnet; + localmask6 = localmask; } else { - using_localnet = 1; - localnet &= localmask; + using_localnet4 = 1; + localnet4 = localnet; + localmask4 = localmask; } - free(tokens[0]); - free(tokens[1]); - free(tokens); + verbosef("local network address: %s", addr_to_str(&localnet)); + verbosef(" local network mask: %s", addr_to_str(&localmask)); +} - if (build_ipv6) { - verbosef("local network address: %s", ip_to_str_af(&localnet6, AF_INET6)); - verbosef(" local network mask: %s", ip_to_str_af(&localmask6, AF_INET6)); +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 { - verbosef("local network address: %s", ip_to_str_af(&localnet, AF_INET)); - verbosef(" local network mask: %s", ip_to_str_af(&localmask, AF_INET)); + assert(a->family == IPv6); + if (using_localnet6) { + if (addr_inside(a, &localnet6, &localmask6)) + return 1; + } else { + if (addr_equal(a, &localip6)) + return 1; + } } - + return 0; } /* Account for the given packet summary. */ void -acct_for(const pktsummary *sm) +acct_for(const struct pktsummary * const sm) { struct bucket *hs = NULL, *hd = NULL; struct bucket *ps, *pd; - struct addr46 ipaddr; - struct in6_addr scribble; - int dir_in, dir_out, j; + int dir_in, dir_out; #if 0 /* WANT_CHATTY? */ - printf("%15s > ", ip_to_str_af(&sm->src_ip, AF_INET)); - printf("%15s ", ip_to_str_af(&sm->dest_ip, AF_INET)); + printf("%15s > ", addr_to_str(&sm->src)); + printf("%15s ", addr_to_str(&sm->dst)); printf("len %4d proto %2d", sm->len, sm->proto); if (sm->proto == IPPROTO_TCP || sm->proto == IPPROTO_UDP) - printf(" port %5d : %5d", sm->src_port, sm->dest_port); + printf(" port %5d : %5d", sm->src_port, sm->dst_port); if (sm->proto == IPPROTO_TCP) printf(" %s%s%s%s%s%s", (sm->tcp_flags & TH_FIN)?"F":"", @@ -176,42 +184,12 @@ acct_for(const pktsummary *sm) total_bytes += sm->len; /* Graphs. */ - dir_in = dir_out = 0; - - if (sm->af == AF_INET) { - if (using_localnet) { - if ((sm->src_ip.s_addr & localmask) == localnet) - dir_out = 1; - if ((sm->dest_ip.s_addr & localmask) == localnet) - dir_in = 1; - if (dir_in == 1 && dir_out == 1) - /* Traffic staying within the network isn't counted. */ - dir_in = dir_out = 0; - } else { - if (memcmp(&sm->src_ip, &localip, sizeof(localip)) == 0) - dir_out = 1; - if (memcmp(&sm->dest_ip, &localip, sizeof(localip)) == 0) - dir_in = 1; - } - } else if (sm->af == AF_INET6) { - if (using_localnet6) { - for (j = 0; j < 16; ++j) - scribble.s6_addr[j] = sm->src_ip6.s6_addr[j] & localmask6.s6_addr[j]; - if (memcmp(&scribble, &localnet6, sizeof(scribble)) == 0) - dir_out = 1; - else { - for (j = 0; j < 16; ++j) - scribble.s6_addr[j] = sm->dest_ip6.s6_addr[j] & localmask6.s6_addr[j]; - if (memcmp(&scribble, &localnet6, sizeof(scribble)) == 0) - dir_in = 1; - } - } else { - if (memcmp(&sm->src_ip6, &localip6, sizeof(localip6)) == 0) - dir_out = 1; - if (memcmp(&sm->dest_ip6, &localip6, sizeof(localip6)) == 0) - dir_in = 1; - } - } + dir_out = addr_is_local(&(sm->src)); + dir_in = addr_is_local(&(sm->dst)); + + /* Traffic staying within the network isn't counted. */ + if (dir_in == 1 && dir_out == 1) + dir_in = dir_out = 0; if (dir_out) { daylog_acct((uint64_t)sm->len, GRAPH_OUT); @@ -225,48 +203,20 @@ acct_for(const pktsummary *sm) if (hosts_max == 0) return; /* skip per-host accounting */ /* Hosts. */ - ipaddr.af = sm->af; - switch (ipaddr.af) { - case AF_INET6: - memcpy(&ipaddr.addr.ip6, &sm->src_ip6, sizeof(ipaddr.addr.ip6)); - break; - case AF_INET: - default: - memcpy(&ipaddr.addr.ip, &sm->src_ip, sizeof(ipaddr.addr.ip)); - break; - } - hs = host_get(&ipaddr); + 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.last_seen = now; - switch (ipaddr.af) { - case AF_INET6: - memcpy(&ipaddr.addr.ip6, &sm->dest_ip6, sizeof(ipaddr.addr.ip6)); - break; - case AF_INET: - default: - memcpy(&ipaddr.addr.ip, &sm->dest_ip, sizeof(ipaddr.addr.ip)); - break; - } - hd = host_get(&ipaddr); /* this can invalidate hs! */ + hd = host_get(&(sm->dst)); /* this can invalidate hs! */ hd->in += sm->len; hd->total += sm->len; memcpy(hd->u.host.mac_addr, sm->dst_mac, sizeof(sm->dst_mac)); hd->u.host.last_seen = now; /* Protocols. */ - switch (ipaddr.af) { - case AF_INET6: - memcpy(&ipaddr.addr.ip6, &sm->src_ip6, sizeof(ipaddr.addr.ip6)); - break; - case AF_INET: - default: - memcpy(&ipaddr.addr.ip, &sm->src_ip, sizeof(ipaddr.addr.ip)); - break; - } - hs = host_find(&ipaddr); + hs = host_find(&(sm->src)); if (hs != NULL) { ps = host_get_ip_proto(hs, sm->proto); ps->out += sm->len; @@ -290,9 +240,9 @@ acct_for(const pktsummary *sm) ps->total += sm->len; } - if (sm->dest_port <= highest_port) + if (sm->dst_port <= highest_port) { - pd = host_get_port_tcp(hd, sm->dest_port); + pd = host_get_port_tcp(hd, sm->dst_port); pd->in += sm->len; pd->total += sm->len; if (sm->tcp_flags == TH_SYN) @@ -308,9 +258,9 @@ acct_for(const pktsummary *sm) ps->total += sm->len; } - if (sm->dest_port <= highest_port) + if (sm->dst_port <= highest_port) { - pd = host_get_port_udp(hd, sm->dest_port); + pd = host_get_port_udp(hd, sm->dst_port); pd->in += sm->len; pd->total += sm->len; } diff --git a/acct.h b/acct.h index 336ac85..c0434ed 100644 --- a/acct.h +++ b/acct.h @@ -4,12 +4,14 @@ * acct.h: traffic accounting */ -#include "decode.h" +#include + +struct pktsummary; extern uint64_t total_packets, total_bytes; void acct_init_localnet(const char *spec); -void acct_for(const pktsummary *sm); +void acct_for(const struct pktsummary * const sm); extern unsigned int highest_port; diff --git a/db.c b/db.c index 6a15ade..7dd7901 100644 --- a/db.c +++ b/db.c @@ -152,20 +152,18 @@ read32(const int fd, uint32_t *dest) return 1; } -/* Read a struct addr46 from a file. Addresses are always stored in network +/* Read a struct addr from a file. Addresses are always stored in network * order, both in the file and in the host's memory (FIXME: is that right?) - * The component "dest->af" must specify AF_INET or AF_INET6. */ int -readaddr(const int fd, struct addr46 *dest) +readaddr(const int fd, struct addr *dest) { - assert(sizeof(*dest) == sizeof(struct addr46)); - assert(dest->af == AF_INET || dest->af == AF_INET6); + assert(dest->family == IPv4 || dest->family == AF_INET6); - if (dest->af == AF_INET) - return readn(fd, &dest->addr.ip, sizeof(struct in_addr)); + if (dest->family == IPv4) + return readn(fd, &(dest->ip.v4), sizeof(dest->ip.v4)); else - return readn(fd, &dest->addr.ip6, sizeof(struct in6_addr)); + return readn(fd, dest->ip.v6.s6_addr, sizeof(dest->ip.v6.s6_addr)); } /* Read a network order uint64_t from a file @@ -243,20 +241,19 @@ write64(const int fd, const uint64_t i) } -/* Write the active address part in a struct addr46 structure to a file. +/* Write the active address part in a struct addr to a file. * Addresses are always stored in network order, both in the file and * in the host's memory (FIXME: is that right?) */ int -writeaddr(const int fd, const struct addr46 *const ip) +writeaddr(const int fd, const struct addr *const a) { - assert(sizeof(*ip) == sizeof(struct addr46)); - assert(ip->af == AF_INET || ip->af == AF_INET6); - - if (ip->af == AF_INET) - return writen(fd, &ip->addr.ip, sizeof(ip->addr.ip)); - else - return writen(fd, &ip->addr.ip6, sizeof(ip->addr.ip6)); + if (a->family == IPv4) + return writen(fd, &(a->ip.v4), sizeof(a->ip.v4)); + else { + assert(a->family == IPv6); + return writen(fd, a->ip.v6.s6_addr, sizeof(a->ip.v6.s6_addr)); + } } /* --------------------------------------------------------------------------- diff --git a/db.h b/db.h index 8f3e686..866b17c 100644 --- a/db.h +++ b/db.h @@ -4,7 +4,10 @@ * copyright (c) 2007 Ben Stewart, Emil Mikulic. */ -#include "hosts_db.h" /* addr46 */ +#include /* for size_t */ +#include /* for uint64_t */ + +struct addr; void db_import(const char *filename); void db_export(const char *filename); @@ -21,8 +24,8 @@ int read8(const int fd, uint8_t *dest); int expect8(const int fd, uint8_t expecting); int read16(const int fd, uint16_t *dest); int read32(const int fd, uint32_t *dest); -int readaddr(const int fd, struct addr46 *dest); int read64(const int fd, uint64_t *dest); +int readaddr(const int fd, struct addr *dest); int read_file_header(const int fd, const uint8_t expected[4]); /* write helpers */ @@ -30,7 +33,7 @@ int writen(const int fd, const void *dest, const size_t len); int write8(const int fd, const uint8_t i); int write16(const int fd, const uint16_t i); int write32(const int fd, const uint32_t i); -int writeaddr(const int fd, const struct addr46 *const addr); int write64(const int fd, const uint64_t i); +int writeaddr(const int fd, const struct addr *const a); /* vim:set ts=3 sw=3 tw=78 et: */ diff --git a/decode.c b/decode.c index 0cd6cb3..d2c0b85 100644 --- a/decode.c +++ b/decode.c @@ -13,11 +13,12 @@ #include "darkstat.h" #include "acct.h" #include "cap.h" +#include "decode.h" +#include "err.h" #include #include #include -#include "err.h" #include #include #include @@ -74,15 +75,15 @@ static void decode_ppp(u_char *, const struct pcap_pkthdr *, static void decode_pppoe(u_char *, const struct pcap_pkthdr *, const u_char *); static void decode_pppoe_real(const u_char *pdata, const uint32_t len, - pktsummary *sm); + struct pktsummary *sm); static void decode_linux_sll(u_char *, const struct pcap_pkthdr *, const u_char *); static void decode_raw(u_char *, const struct pcap_pkthdr *, const u_char *); static void decode_ip(const u_char *pdata, const uint32_t len, - pktsummary *sm); + struct pktsummary *sm); static void decode_ipv6(const u_char *pdata, const uint32_t len, - pktsummary *sm); + struct pktsummary *sm); /* Link-type header information */ static const struct linkhdr linkhdrs[] = { @@ -100,7 +101,7 @@ static const struct linkhdr linkhdrs[] = { { DLT_LINUX_SLL, SLL_HDR_LEN, decode_linux_sll }, #endif { DLT_RAW, RAW_HDR_LEN, decode_raw }, - { -1, -1, NULL } + { -1, 0, NULL } }; /* @@ -131,30 +132,6 @@ getsnaplen(const struct linkhdr *lh) return (20 + lh->hdrlen + IPV6_HDR_LEN + max(TCP_HDR_LEN, UDP_HDR_LEN)); } -/* - * Convert IP address to a presentation notation in a static buffer - * using inet_ntop(3). - */ -char ipstr[INET6_ADDRSTRLEN]; /* TODO Reentrant? */ - -char * -ip_to_str(const struct addr46 *const ip) -{ - ipstr[0] = '\0'; - inet_ntop(ip->af, &ip->addr.ip6, ipstr, sizeof(ipstr)); - - return (ipstr); -} - -char * -ip_to_str_af(const void *const addr, sa_family_t af) -{ - ipstr[0] = '\0'; - inet_ntop(af, addr, ipstr, sizeof(ipstr)); - - return (ipstr); -} - /* Decoding functions. */ static void decode_ether(u_char *user _unused_, @@ -163,7 +140,7 @@ decode_ether(u_char *user _unused_, { u_short type; const struct ether_header *hdr = (const struct ether_header *)pdata; - pktsummary sm; + struct pktsummary sm; memset(&sm, 0, sizeof(sm)); sm.time = pheader->ts.tv_sec; @@ -212,7 +189,7 @@ decode_loop(u_char *user _unused_, const u_char *pdata) { uint32_t family; - pktsummary sm; + struct pktsummary sm; memset(&sm, 0, sizeof(sm)); if (pheader->caplen < NULL_HDR_LEN) { @@ -244,7 +221,7 @@ decode_ppp(u_char *user _unused_, const struct pcap_pkthdr *pheader, const u_char *pdata) { - pktsummary sm; + struct pktsummary sm; memset(&sm, 0, sizeof(sm)); if (pheader->caplen < PPPOE_HDR_LEN) { @@ -265,7 +242,7 @@ decode_pppoe(u_char *user _unused_, const struct pcap_pkthdr *pheader, const u_char *pdata) { - pktsummary sm; + struct pktsummary sm; memset(&sm, 0, sizeof(sm)); sm.time = pheader->ts.tv_sec; decode_pppoe_real(pdata, pheader->caplen, &sm); @@ -273,7 +250,7 @@ decode_pppoe(u_char *user _unused_, static void decode_pppoe_real(const u_char *pdata, const uint32_t len, - pktsummary *sm) + struct pktsummary *sm) { if (len < PPPOE_HDR_LEN) { verbosef("pppoe: packet too short (%u bytes)", len); @@ -311,7 +288,7 @@ decode_linux_sll(u_char *user _unused_, uint16_t ether_type; } *hdr = (const struct sll_header *)pdata; u_short type; - pktsummary sm; + struct pktsummary sm; memset(&sm, 0, sizeof(sm)); if (pheader->caplen < SLL_HDR_LEN) { @@ -340,7 +317,7 @@ decode_raw(u_char *user _unused_, const struct pcap_pkthdr *pheader, const u_char *pdata) { - pktsummary sm; + struct pktsummary sm; memset(&sm, 0, sizeof(sm)); decode_ip(pdata, pheader->caplen, &sm); @@ -349,7 +326,7 @@ decode_raw(u_char *user _unused_, } static void -decode_ip(const u_char *pdata, const uint32_t len, pktsummary *sm) +decode_ip(const u_char *pdata, const uint32_t len, struct pktsummary *sm) { const struct ip *hdr = (const struct ip *)pdata; @@ -368,10 +345,13 @@ decode_ip(const u_char *pdata, const uint32_t len, pktsummary *sm) } sm->len = ntohs(hdr->ip_len); - sm->af = AF_INET; sm->proto = hdr->ip_p; - memcpy(&sm->src_ip, &hdr->ip_src, sizeof(sm->src_ip)); - memcpy(&sm->dest_ip, &hdr->ip_dst, sizeof(sm->dest_ip)); + + sm->src.family = IPv4; + sm->src.ip.v4 = hdr->ip_src.s_addr; + + sm->dst.family = IPv4; + sm->dst.ip.v4 = hdr->ip_dst.s_addr; switch (sm->proto) { case IPPROTO_TCP: { @@ -382,7 +362,7 @@ decode_ip(const u_char *pdata, const uint32_t len, pktsummary *sm) return; } sm->src_port = ntohs(thdr->th_sport); - sm->dest_port = ntohs(thdr->th_dport); + sm->dst_port = ntohs(thdr->th_dport); sm->tcp_flags = thdr->th_flags & (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG); break; @@ -396,7 +376,7 @@ decode_ip(const u_char *pdata, const uint32_t len, pktsummary *sm) return; } sm->src_port = ntohs(uhdr->uh_sport); - sm->dest_port = ntohs(uhdr->uh_dport); + sm->dst_port = ntohs(uhdr->uh_dport); break; } @@ -413,7 +393,7 @@ decode_ip(const u_char *pdata, const uint32_t len, pktsummary *sm) } static void -decode_ipv6(const u_char *pdata, const uint32_t len, pktsummary *sm) +decode_ipv6(const u_char *pdata, const uint32_t len, struct pktsummary *sm) { const struct ip6_hdr *hdr = (const struct ip6_hdr *)pdata; @@ -423,10 +403,13 @@ decode_ipv6(const u_char *pdata, const uint32_t len, pktsummary *sm) } sm->len = ntohs(hdr->ip6_plen) + IPV6_HDR_LEN; - sm->af = AF_INET6; sm->proto = hdr->ip6_nxt; - memcpy(&sm->src_ip6, &hdr->ip6_src, sizeof(sm->src_ip6)); - memcpy(&sm->dest_ip6, &hdr->ip6_dst, sizeof(sm->dest_ip6)); + + sm->src.family = IPv6; + memcpy(&sm->src.ip.v6, &hdr->ip6_src, sizeof(sm->src.ip.v6)); + + sm->dst.family = IPv6; + memcpy(&sm->dst.ip.v6, &hdr->ip6_dst, sizeof(sm->dst.ip.v6)); switch (sm->proto) { case IPPROTO_TCP: { @@ -437,7 +420,7 @@ decode_ipv6(const u_char *pdata, const uint32_t len, pktsummary *sm) return; } sm->src_port = ntohs(thdr->th_sport); - sm->dest_port = ntohs(thdr->th_dport); + sm->dst_port = ntohs(thdr->th_dport); sm->tcp_flags = thdr->th_flags & (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG); break; @@ -451,7 +434,7 @@ decode_ipv6(const u_char *pdata, const uint32_t len, pktsummary *sm) return; } sm->src_port = ntohs(uhdr->uh_sport); - sm->dest_port = ntohs(uhdr->uh_dport); + sm->dst_port = ntohs(uhdr->uh_dport); break; } diff --git a/decode.h b/decode.h index d4c8bc0..f497ac3 100644 --- a/decode.h +++ b/decode.h @@ -15,7 +15,7 @@ #include /* for */ #include /* struct ip */ -#include "hosts_db.h" /* addr46 */ +#include "addr.h" #define PPP_HDR_LEN 4 #define FDDI_HDR_LEN 21 @@ -44,28 +44,18 @@ struct linkhdr { const struct linkhdr *getlinkhdr(const int linktype); int getsnaplen(const struct linkhdr *lh); -char *ip_to_str(const struct addr46 *const ip); -char *ip_to_str_af(const void *const addr, sa_family_t af); -typedef struct { +struct pktsummary { /* Fields are in host byte order (except IPs) */ - union { - struct in_addr src_ip; - struct in6_addr src_ip6; - }; - union { - struct in_addr dest_ip; - struct in6_addr dest_ip6; - }; + struct addr src, dst; time_t time; uint16_t len; - sa_family_t af; /* AF_{UNSPEC, INET, INET6} */ - uint8_t proto; /* IPPROTO_{TCP, UDP, ICMP} */ - uint8_t tcp_flags; /* only for TCP */ - uint16_t src_port, dest_port; /* only for TCP, UDP */ + uint8_t proto; /* IPPROTO_{TCP, UDP, ICMP} */ + uint8_t tcp_flags; /* only for TCP */ + uint16_t src_port, dst_port; /* only for TCP, UDP */ uint8_t src_mac[ETHER_ADDR_LEN], dst_mac[ETHER_ADDR_LEN]; /* only for Ethernet */ -} pktsummary; +}; #endif /* __DARKSTAT_DECODE_H */ /* vim:set ts=3 sw=3 tw=78 expandtab: */ diff --git a/dns.c b/dns.c index 125ab62..1c6dc24 100644 --- a/dns.c +++ b/dns.c @@ -14,6 +14,7 @@ #include "err.h" #include "hosts_db.h" #include "queue.h" +#include "str.h" #include "tree.h" #include @@ -35,7 +36,7 @@ static int sock[2]; static pid_t pid = -1; struct dns_reply { - struct addr46 addr; + struct addr addr; int error; /* for gai_strerror(), or 0 if no error */ char name[MAXHOSTNAMELEN]; }; @@ -86,26 +87,22 @@ dns_stop(void) struct tree_rec { RB_ENTRY(tree_rec) ptree; - struct addr46 ip; + struct addr ip; }; static int tree_cmp(struct tree_rec *a, struct tree_rec *b) { - if (a->ip.af != b->ip.af) + if (a->ip.family != b->ip.family) /* Sort IPv4 to the left of IPv6. */ - return (a->ip.af == AF_INET ? -1 : +1); + return ((a->ip.family == IPv4) ? -1 : +1); - if (a->ip.af == AF_INET) { - return (memcmp(&a->ip.addr.ip, &b->ip.addr.ip, sizeof(a->ip.addr.ip))); + if (a->ip.family == IPv4) + return (memcmp(&a->ip.ip.v4, &b->ip.ip.v4, sizeof(a->ip.ip.v4))); + else { + assert(a->ip.family == IPv6); + return (memcmp(&a->ip.ip.v6, &b->ip.ip.v6, sizeof(a->ip.ip.v6))); } - - /* AF_INET6 should remain. */ - if (a->ip.af == AF_INET6) - return (memcmp(&a->ip.addr.ip6, &b->ip.addr.ip6, sizeof(a->ip.addr.ip6))); - - /* Last resort. */ - return -1; } static RB_HEAD(tree_t, tree_rec) ip_tree = RB_INITIALIZER(&tree_rec); @@ -117,7 +114,7 @@ static struct tree_rec * tree_t_RB_MINMAX(struct tree_t *head, int val) RB_GENERATE(tree_t, tree_rec, ptree, tree_cmp) void -dns_queue(const struct addr46 *const ipaddr) +dns_queue(const struct addr *const ipaddr) { struct tree_rec *rec; ssize_t num_w; @@ -125,8 +122,8 @@ dns_queue(const struct addr46 *const ipaddr) if (pid == -1) return; /* no child was started - we're not doing any DNS */ - if (ipaddr->af != AF_INET && ipaddr->af != AF_INET6) { - verbosef("dns_queue() for unknown family %d.\n", ipaddr->af); + if ((ipaddr->family != IPv4) && (ipaddr->family != IPv6)) { + verbosef("dns_queue() for unknown family %d", ipaddr->family); return; } @@ -136,7 +133,7 @@ dns_queue(const struct addr46 *const ipaddr) if (RB_INSERT(tree_t, &ip_tree, rec) != NULL) { /* Already queued - this happens seldom enough that we don't care about * the performance hit of needlessly malloc()ing. */ - verbosef("already queued %s", ip_to_str(ipaddr)); + verbosef("already queued %s", addr_to_str(ipaddr)); free(rec); return; } @@ -151,7 +148,7 @@ dns_queue(const struct addr46 *const ipaddr) } static void -dns_unqueue(const struct addr46 *const ipaddr) +dns_unqueue(const struct addr *const ipaddr) { struct tree_rec tmp, *rec; @@ -161,7 +158,7 @@ dns_unqueue(const struct addr46 *const ipaddr) free(rec); } else - verbosef("couldn't unqueue %s - not in queue!", ip_to_str(ipaddr)); + verbosef("couldn't unqueue %s - not in queue!", addr_to_str(ipaddr)); } /* @@ -169,7 +166,7 @@ dns_unqueue(const struct addr46 *const ipaddr) * (name buffer is allocated by dns_poll) */ static int -dns_get_result(struct addr46 *ipaddr, char **name) +dns_get_result(struct addr *ipaddr, char **name) { struct dns_reply reply; ssize_t numread; @@ -196,17 +193,17 @@ dns_get_result(struct addr46 *ipaddr, char **name) #else /* !DARKSTAT_USES_HOSTENT */ if (reply.error != 0) { /* Identify common special cases. */ - char *type = "none"; + const char *type = "none"; - if (reply.addr.af == AF_INET6) { - if (IN6_IS_ADDR_LINKLOCAL(&reply.addr.addr.ip6)) + if (reply.addr.family == IPv6) { + if (IN6_IS_ADDR_LINKLOCAL(&reply.addr.ip.v6)) type = "link-local"; - else if (IN6_IS_ADDR_SITELOCAL(&reply.addr.addr.ip6)) + else if (IN6_IS_ADDR_SITELOCAL(&reply.addr.ip.v6)) type = "site-local"; - else if (IN6_IS_ADDR_MULTICAST(&reply.addr.addr.ip6)) + else if (IN6_IS_ADDR_MULTICAST(&reply.addr.ip.v6)) type = "multicast"; } else { /* AF_INET */ - if (IN_MULTICAST(reply.addr.addr.ip.s_addr)) + if (IN_MULTICAST(reply.addr.ip.v4)) type = "multicast"; } xasprintf(name, "(%s)", type); @@ -227,7 +224,7 @@ error: void dns_poll(void) { - struct addr46 ip; + struct addr ip; char *name; if (pid == -1) @@ -239,12 +236,12 @@ dns_poll(void) if (b == NULL) { verbosef("resolved %s to %s but it's not in the DB!", - ip_to_str(&ip), name); + addr_to_str(&ip), name); return; } if (b->u.host.dns != NULL) { verbosef("resolved %s to %s but it's already in the DB!", - ip_to_str(&ip), name); + addr_to_str(&ip), name); return; } b->u.host.dns = name; @@ -255,25 +252,25 @@ dns_poll(void) struct qitem { STAILQ_ENTRY(qitem) entries; - struct addr46 ip; + struct addr ip; }; STAILQ_HEAD(qhead, qitem) queue = STAILQ_HEAD_INITIALIZER(queue); static void -enqueue(const struct addr46 *const ip) +enqueue(const struct addr *const ip) { struct qitem *i; i = xmalloc(sizeof(*i)); memcpy(&i->ip, ip, sizeof(i->ip)); STAILQ_INSERT_TAIL(&queue, i, entries); - verbosef("DNS: enqueued %s", ip_to_str(ip)); + verbosef("DNS: enqueued %s", addr_to_str(ip)); } /* Return non-zero and populate pointer if queue isn't empty. */ static int -dequeue(struct addr46 *ip) +dequeue(struct addr *ip) { struct qitem *i; @@ -283,7 +280,7 @@ dequeue(struct addr46 *ip) STAILQ_REMOVE_HEAD(&queue, entries); memcpy(ip, &i->ip, sizeof(*ip)); free(i); - verbosef("DNS: dequeued %s", ip_to_str(ip)); + verbosef("DNS: dequeued %s", addr_to_str(ip)); return 1; } @@ -301,7 +298,7 @@ xwrite(const int d, const void *buf, const size_t nbytes) static void dns_main(void) { - struct addr46 ip; + struct addr ip; #ifdef HAVE_SETPROCTITLE setproctitle("DNS child"); @@ -365,7 +362,7 @@ dns_main(void) } fd_set_block(sock[CHILD]); xwrite(sock[CHILD], &reply, sizeof(reply)); - verbosef("DNS: %s is %s", ip_to_str(&reply.addr), + verbosef("DNS: %s is %s", addr_to_str(&reply.addr), (h_errno == 0)?reply.name:hstrerror(h_errno)); #else /* !DARKSTAT_USES_HOSTENT */ struct sockaddr_in sin; @@ -373,29 +370,26 @@ dns_main(void) char host[NI_MAXHOST]; int ret, flags; - reply.addr.af = ip.af; + reply.addr = ip; flags = NI_NAMEREQD; # ifdef NI_IDN flags |= NI_IDN; # endif - switch (ip.af) { - case AF_INET: - sin.sin_family = ip.af; - memcpy(&reply.addr.addr.ip, &ip.addr.ip, sizeof(reply.addr.addr.ip)); - memcpy(&sin.sin_addr, &ip.addr.ip, sizeof(sin.sin_addr)); + switch (ip.family) { + case IPv4: + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = ip.ip.v4; ret = getnameinfo((struct sockaddr *) &sin, sizeof(sin), host, sizeof(host), NULL, 0, flags); break; - case AF_INET6: - sin6.sin6_family = ip.af; - memcpy(&reply.addr.addr.ip6, &ip.addr.ip6, sizeof(reply.addr.addr.ip6)); - memcpy(&sin6.sin6_addr, &ip.addr.ip6, sizeof(sin6.sin6_addr)); + case IPv6: + sin6.sin6_family = AF_INET6; + memcpy(&sin6.sin6_addr, &ip.ip.v6, sizeof(sin6.sin6_addr)); ret = getnameinfo((struct sockaddr *) &sin6, sizeof(sin6), host, sizeof(host), NULL, 0, flags); break; default: ret = EAI_FAMILY; - } if (ret != 0) { @@ -408,7 +402,7 @@ dns_main(void) } fd_set_block(sock[CHILD]); xwrite(sock[CHILD], &reply, sizeof(reply)); - verbosef("DNS: %s is \"%s\".", ip_to_str(&reply.addr), + verbosef("DNS: %s is \"%s\".", addr_to_str(&reply.addr), (ret == 0) ? reply.name : gai_strerror(ret)); #endif /* !DARKSTAT_USES_HOSTENT */ } diff --git a/dns.h b/dns.h index f7fdb3c..775f377 100644 --- a/dns.h +++ b/dns.h @@ -7,11 +7,11 @@ * GNU General Public License version 2. (see COPYING.GPL) */ -#include "hosts_db.h" /* addr46 */ +struct addr; void dns_init(const char *privdrop_user); void dns_stop(void); -void dns_queue(const struct addr46 *const ip); +void dns_queue(const struct addr *const ipaddr); void dns_poll(void); /* vim:set ts=3 sw=3 tw=78 expandtab: */ diff --git a/hosts_db.c b/hosts_db.c index d72fe47..902774f 100644 --- a/hosts_db.c +++ b/hosts_db.c @@ -17,6 +17,7 @@ #include "html.h" #include "ncache.h" #include "now.h" +#include "str.h" #include /* inet_aton() */ #include /* struct addrinfo */ @@ -102,9 +103,10 @@ coprime(const uint32_t u) * src/sys/netinet/tcp_hostcache.c 1.1 */ inline static uint32_t -ipv4_hash(const struct in_addr *const ip) +ipv4_hash(const struct addr *const a) { - return ( (ip->s_addr) ^ ((ip->s_addr) >> 7) ^ ((ip->s_addr) >> 17) ); + uint32_t ip = a->ip.v4; + return ( (ip) ^ ((ip) >> 7) ^ ((ip) >> 17) ); } #ifndef s6_addr32 @@ -118,31 +120,30 @@ ipv4_hash(const struct in_addr *const ip) * svn rev 122922. */ inline static uint32_t -ipv6_hash(const struct in6_addr *const ip6) +ipv6_hash(const struct addr *const a) { - return ( ip6->s6_addr32[0] ^ ip6->s6_addr32[1] ^ ip6->s6_addr32[2] ^ ip6->s6_addr32[3] ); + const struct in6_addr *const ip6 = &(a->ip.v6); + return ( ip6->s6_addr32[0] ^ ip6->s6_addr32[1] ^ + ip6->s6_addr32[2] ^ ip6->s6_addr32[3] ); } /* --------------------------------------------------------------------------- * hash_func collection */ -#define CASTKEY(type) (*((const type *)key)) - static uint32_t hash_func_host(const struct hashtable *h _unused_, const void *key) { - struct addr46 *ip = (struct addr46 *) key; - - switch (ip->af) { - case AF_INET: - return (ipv4_hash(&ip->addr.ip)); - case AF_INET6: - return (ipv6_hash(&ip->addr.ip6)); - default: - return 0; + const struct addr *a = key; + if (a->family == IPv4) + return (ipv4_hash(a)); + else { + assert(a->family == IPv6); + return (ipv6_hash(a)); } } +#define CASTKEY(type) (*((const type *)key)) + static uint32_t hash_func_short(const struct hashtable *h, const void *key) { @@ -162,7 +163,7 @@ hash_func_byte(const struct hashtable *h, const void *key) static const void * key_func_host(const struct bucket *b) { - return &(b->u.host.ipaddr); + return &(b->u.host.addr); } static const void * @@ -190,23 +191,7 @@ key_func_ip_proto(const struct bucket *b) static int find_func_host(const struct bucket *b, const void *key) { - struct addr46 *ipaddr = (struct addr46 *) key; - - if (b->u.host.ipaddr.af != ipaddr->af) - return 0; /* not comparable */ - - switch (ipaddr->af) { - case AF_INET: - return (memcmp(&b->u.host.ipaddr.addr.ip, - &ipaddr->addr.ip, sizeof(ipaddr->addr.ip)) - == 0); - case AF_INET6: - return (memcmp(&b->u.host.ipaddr.addr.ip6, - &ipaddr->addr.ip6, sizeof(ipaddr->addr.ip6)) - == 0); - default: - return 0; - } + return (addr_equal(key, &(b->u.host.addr))); } static int @@ -244,7 +229,7 @@ static struct bucket * make_func_host(const void *key) { MAKE_BUCKET(b, h, host); - memcpy(&h->ipaddr, key, sizeof(h->ipaddr)); + h->addr = CASTKEY(struct addr); h->dns = NULL; h->last_seen = now; memset(&h->mac_addr, 0, sizeof(h->mac_addr)); @@ -327,7 +312,7 @@ static void format_row_host(struct str *buf, const struct bucket *b, const char *css_class) { - const char *ip = ip_to_str( &b->u.host.ipaddr ); + const char *ip = addr_to_str(&(b->u.host.addr)); str_appendf(buf, "\n" @@ -377,7 +362,7 @@ format_row_host(struct str *buf, const struct bucket *b, /* Only resolve hosts "on demand" */ if (b->u.host.dns == NULL) - dns_queue(&b->u.host.ipaddr); + dns_queue(&(b->u.host.addr)); } static void @@ -657,18 +642,18 @@ hashtable_free(struct hashtable *h) * Return existing host or insert a new one. */ struct bucket * -host_get(const struct addr46 *const ip) +host_get(const struct addr *const a) { - return (hashtable_find_or_insert(hosts_db, ip)); + return (hashtable_find_or_insert(hosts_db, a)); } /* --------------------------------------------------------------------------- * Find host, returns NULL if not in DB. */ struct bucket * -host_find(const struct addr46 *const ip) +host_find(const struct addr *const a) { - return (hashtable_search(hosts_db, ip)); + return (hashtable_search(hosts_db, a)); } /* --------------------------------------------------------------------------- @@ -677,8 +662,7 @@ host_find(const struct addr46 *const ip) static struct bucket * host_search(const char *ipstr) { - struct addr46 ipaddr; - struct sockaddr_storage ss; + struct addr a; struct addrinfo hints, *ai; memset(&hints, 0, sizeof(hints)); @@ -688,24 +672,23 @@ host_search(const char *ipstr) if (getaddrinfo(ipstr, NULL, &hints, &ai)) return (NULL); /* invalid addr */ - memcpy(&ss, ai->ai_addr, ai->ai_addrlen); - freeaddrinfo(ai); - - ipaddr.af = ss.ss_family; - switch (ss.ss_family) { - case AF_INET: - memcpy(&ipaddr.addr.ip, &((struct sockaddr_in *) &ss)->sin_addr, - sizeof(ipaddr.addr.ip)); - break; - case AF_INET6: - memcpy(&ipaddr.addr.ip6, &((struct sockaddr_in6 *) &ss)->sin6_addr, - sizeof(ipaddr.addr.ip6)); - break; - default: - return (NULL); + if (ai->ai_family == AF_INET) { + a.family = IPv4; + a.ip.v4 = ((const struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr; + } + else if (ai->ai_family == AF_INET6) { + a.family = IPv6; + memcpy(&(a.ip.v6), + ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, + sizeof(a.ip.v6)); + } else { + freeaddrinfo(ai); + return (NULL); /* unknown family */ } + freeaddrinfo(ai); - return (hashtable_search(hosts_db, &ipaddr)); + verbosef("search(%s) turned into %s", ipstr, addr_to_str(&a)); + return (hashtable_search(hosts_db, &a)); } /* --------------------------------------------------------------------------- @@ -1030,38 +1013,42 @@ html_hosts_detail(const char *ip) struct bucket *h; struct str *buf, *ls_len; char ls_when[100]; + const char *canonical; time_t ls; h = host_search(ip); if (h == NULL) return (NULL); /* no such host */ + canonical = addr_to_str(&(h->u.host.addr)); + /* Overview. */ buf = str_make(); str_append(buf, html_header_1); str_appendf(buf, " %s\n", ip); str_append(buf, html_header_2); + str_appendf(buf, "

%s

\n", ip); + if (strcmp(ip, canonical) != 0) + str_appendf(buf, "(canonically %s)\n", canonical); str_appendf(buf, - "

%s

\n" "

\n" "Hostname: %s
\n", - ip, (h->u.host.dns == NULL)?"(resolving...)":h->u.host.dns); /* Resolve host "on demand" */ if (h->u.host.dns == NULL) - dns_queue(&h->u.host.ipaddr); + dns_queue(&(h->u.host.addr)); if (show_mac_addrs) - str_appendf(buf, - "MAC Address: " - "%x:%x:%x:%x:%x:%x
\n", - h->u.host.mac_addr[0], - h->u.host.mac_addr[1], - h->u.host.mac_addr[2], - h->u.host.mac_addr[3], - h->u.host.mac_addr[4], - h->u.host.mac_addr[5]); + str_appendf(buf, + "MAC Address: " + "%x:%x:%x:%x:%x:%x
\n", + h->u.host.mac_addr[0], + h->u.host.mac_addr[1], + h->u.host.mac_addr[2], + h->u.host.mac_addr[3], + h->u.host.mac_addr[4], + h->u.host.mac_addr[5]); str_append(buf, "

\n" @@ -1226,7 +1213,7 @@ static int hosts_db_import_host(const int fd) { struct bucket *host; - struct addr46 ipaddr; + struct addr a; uint8_t hostname_len; uint64_t in, out; unsigned int pos = xtell(fd); @@ -1244,11 +1231,10 @@ hosts_db_import_host(const int fd) return 0; } - ipaddr.af = AF_INET; - if (!readaddr(fd, &ipaddr)) return 0; - verbosef("at file pos %u, importing host %s", pos, ip_to_str(&ipaddr)); - host = host_get(&ipaddr); - assert(host->u.host.ipaddr.addr.ip.s_addr == ipaddr.addr.ip.s_addr); /* make fn? */ + if (!readaddr(fd, &a)) return 0; + verbosef("at file pos %u, importing host %s", pos, addr_to_str(&a)); + host = host_get(&a); + assert(addr_equal(&(host->u.host.addr), &a)); if (ver > 1) { uint64_t t; @@ -1326,7 +1312,7 @@ int hosts_db_export(const int fd) if (!writen(fd, export_tag_host_ver2, sizeof(export_tag_host_ver2))) return 0; - if (!writeaddr(fd, &b->u.host.ipaddr)) return 0; + if (!writeaddr(fd, &(b->u.host.addr))) return 0; if (!write64(fd, (uint64_t)(b->u.host.last_seen))) return 0; diff --git a/hosts_db.h b/hosts_db.h index 4b324ba..f9ed169 100644 --- a/hosts_db.h +++ b/hosts_db.h @@ -9,23 +9,12 @@ #ifndef __DARKSTAT_HOSTS_DB_H #define __DARKSTAT_HOSTS_DB_H -#include -#include -#include -#include "str.h" - -struct addr46 { - sa_family_t af; - union { - struct in_addr ip; - struct in6_addr ip6; - } addr; -}; +#include "addr.h" struct hashtable; struct host { - struct addr46 ipaddr; + struct addr addr; char *dns; uint8_t mac_addr[6]; time_t last_seen; @@ -73,8 +62,8 @@ void hosts_db_free(void); int hosts_db_import(const int fd); int hosts_db_export(const int fd); -struct bucket *host_find(const struct addr46 *const ip); /* can return NULL */ -struct bucket *host_get(const struct addr46 *const ip); +struct bucket *host_find(const struct addr *const a); /* can return NULL */ +struct bucket *host_get(const struct addr *const a); struct bucket *host_get_port_tcp(struct bucket *host, const uint16_t port); struct bucket *host_get_port_udp(struct bucket *host, const uint16_t port); struct bucket *host_get_ip_proto(struct bucket *host, const uint8_t proto); diff --git a/localip.c b/localip.c index 2980bc9..33f5a71 100644 --- a/localip.c +++ b/localip.c @@ -8,8 +8,8 @@ */ #include "darkstat.h" +#include "addr.h" #include "conv.h" /* for strlcpy */ -#include "decode.h" /* for ip_to_str */ #include "err.h" #include "localip.h" @@ -21,12 +21,8 @@ #include static const char *iface = NULL; - -struct in_addr localip = { 0 }; -static struct in_addr last_localip = { 0 }; - -struct in6_addr localip6; -static struct in6_addr last_localip6; +struct addr localip4, localip6; +static struct addr last_localip4, last_localip6; void localip_init(const char *interface) @@ -39,15 +35,15 @@ void localip_update(void) { struct ifaddrs *ifas, *ifa; - int flags = 0; + int got_v4 = 0, got_v6 = 0; -#define HAS_IPV4 0x01 -#define HAS_IPV6 0x02 + localip4.family = IPv4; + localip6.family = IPv6; if (iface == NULL) { /* reading from capfile */ - memset(&localip, 0, sizeof(localip)); - memset(&localip6, 0, sizeof(localip6)); + localip4.ip.v4 = 0; + memset(&(localip6.ip.v6), 0, sizeof(localip6.ip.v6)); return; } @@ -55,18 +51,19 @@ localip_update(void) err(1, "can't get own IP address on interface \"%s\"", iface); for (ifa = ifas; ifa; ifa = ifa->ifa_next) { - if (flags == (HAS_IPV4 | HAS_IPV6)) + if (got_v4 && got_v6) break; /* Task is already complete. */ if (strncmp(ifa->ifa_name, iface, IFNAMSIZ)) continue; /* Wrong interface. */ /* The first IPv4 name is always functional. */ - if ( (ifa->ifa_addr->sa_family == AF_INET) - && ! (flags & HAS_IPV4) ) { + if ((ifa->ifa_addr->sa_family == AF_INET) && !got_v4) + { /* Good IPv4 address. */ - localip.s_addr = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr; - flags |= HAS_IPV4; + localip4.ip.v4 = + ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; + got_v4 = 1; continue; } @@ -77,41 +74,26 @@ localip_update(void) if ( IN6_IS_ADDR_LINKLOCAL(&(sa6->sin6_addr)) || IN6_IS_ADDR_SITELOCAL(&(sa6->sin6_addr)) ) continue; - else - /* Only standard IPv6 can reach this point. */ - memcpy(&localip6, &sa6->sin6_addr, sizeof(localip6)); - flags |= HAS_IPV6; + + /* Only standard IPv6 can reach this point. */ + memcpy(&(localip6.ip.v6), &sa6->sin6_addr, sizeof(localip6.ip.v6)); + got_v6 = 1; } } freeifaddrs(ifas); - /* Repport an error if IPv4 address could not be found. */ - if ( !(flags & HAS_IPV4) ) + /* Report an error if IPv4 address could not be found. */ + if (!got_v4) err(1, "can't get own IPv4 address on interface \"%s\"", iface); - /* struct sockaddr { - * sa_family_t sa_family; * address family, AF_xxx - * char sa_data[14]; * 14 bytes of protocol address - * - * struct sockaddr_in { - * sa_family_t sin_family; * Address family - * unsigned short int sin_port; * Port number - * struct in_addr sin_addr; * Internet address - * - * struct in_addr { - * __u32 s_addr; - */ - - if (last_localip.s_addr != localip.s_addr) { - verbosef("local_ip update(%s) = %s", iface, - ip_to_str_af(&localip, AF_INET)); - memcpy(&last_localip, &localip, sizeof(last_localip)); + if (!addr_equal(&last_localip4, &localip4)) { + verbosef("localip4 update(%s) = %s", iface, addr_to_str(&localip4)); + last_localip4 = localip4; } - if (memcmp(&last_localip6, &localip6, sizeof(localip6))) { - verbosef("local_ip6 update(%s) = %s", iface, - ip_to_str_af(&localip6, AF_INET6)); - memcpy(&last_localip6, &localip6, sizeof(localip6)); + if (!addr_equal(&last_localip6, &localip6)) { + verbosef("localip6 update(%s) = %s", iface, addr_to_str(&localip6)); + last_localip6 = localip6; } } diff --git a/localip.h b/localip.h index a16a6a9..37c5649 100644 --- a/localip.h +++ b/localip.h @@ -7,10 +7,7 @@ * GNU General Public License version 2. (see COPYING.GPL) */ -#include /* for in_addr, in6_addr */ - -extern struct in_addr localip; -extern struct in6_addr localip6; +extern struct addr localip4, localip6; void localip_init(const char *interface); void localip_update(void); -- 2.17.1