free(tokens[1]);
free(tokens);
- verbosef("local network address: %s", ip_to_str(localnet));
- verbosef(" local network mask: %s", ip_to_str(localmask));
+ verbosef("local network address: %s", ip_to_str_af(&localnet, AF_INET));
+ verbosef(" local network mask: %s", ip_to_str_af(&localmask, AF_INET));
if ((localnet & localmask) != localnet)
errx(1, "this is an invalid combination of address and mask!\n"
{
struct bucket *hs = NULL, *hd = NULL;
struct bucket *ps, *pd;
+ struct addr46 ipaddr;
int dir_in, dir_out;
#if 0 /* WANT_CHATTY? */
- printf("%15s > ", ip_to_str(sm->src_ip));
- printf("%15s ", ip_to_str(sm->dest_ip));
+ printf("%15s > ", ip_to_str_af(&sm->src_ip, AF_INET));
+ printf("%15s ", ip_to_str_af(&sm->dest_ip, AF_INET));
printf("len %4d proto %2d", sm->len, sm->proto);
if (sm->proto == IPPROTO_TCP || sm->proto == IPPROTO_UDP)
if (sm->af == AF_INET) {
if (using_localnet) {
- if ((sm->src_ip & localmask) == localnet)
+ if ((sm->src_ip.s_addr & localmask) == localnet)
dir_out = 1;
- if ((sm->dest_ip & localmask) == localnet)
+ 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 (sm->src_ip == localip)
+ if (memcmp(&sm->src_ip, &localip, sizeof(localip)) == 0)
dir_out = 1;
- if (sm->dest_ip == localip)
+ if (memcmp(&sm->dest_ip, &localip, sizeof(localip)) == 0)
dir_in = 1;
}
} else if (sm->af == AF_INET6) {
if (hosts_max == 0) return; /* skip per-host accounting */
/* Hosts. */
- hs = host_get(sm->src_ip);
+ ipaddr.af = sm->af; /* TODO */
+ ipaddr.addr.ip = sm->src_ip; /* TODO */
+ hs = host_get(&ipaddr);
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;
- hd = host_get(sm->dest_ip); /* this can invalidate hs! */
+ ipaddr.addr.ip = sm->dest_ip; /* TODO */
+ hd = host_get(&ipaddr); /* 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. */
- hs = host_find(sm->src_ip);
+ ipaddr.addr.ip = sm->src_ip; /* TODO */
+ hs = host_find(&ipaddr);
if (hs != NULL) {
ps = host_get_ip_proto(hs, sm->proto);
ps->out += sm->len;
return 1;
}
-/* Read an in_addr_t from a file. Addresses are always stored in network
+/* Read a struct addr46 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, in_addr_t *dest)
+readaddr(const int fd, struct addr46 *dest)
{
- assert(sizeof(*dest) == 4);
- return readn(fd, dest, sizeof(*dest));
+ assert(sizeof(*dest) == sizeof(struct addr46));
+ assert(dest->af == AF_INET || dest->af == AF_INET6);
+
+ if (dest->af == AF_INET)
+ return readn(fd, &dest->addr.ip, sizeof(struct in_addr));
+ else
+ return readn(fd, &dest->addr.ip6, sizeof(struct in6_addr));
}
/* Read a network order uint64_t from a file
}
-/* Write an in_addr_t to a file. Addresses are always stored in network
- * order, both in the file and in the host's memory (FIXME: is that right?)
+/* Write the active address part in a struct addr46 structure 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 in_addr_t addr)
+writeaddr(const int fd, const struct addr46 *const ip)
{
- assert(sizeof(addr) == 4);
- return writen(fd, &addr, sizeof(addr));
+ 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));
}
/* ---------------------------------------------------------------------------
* copyright (c) 2007 Ben Stewart, Emil Mikulic.
*/
+#include "hosts_db.h" /* addr46 */
+
void db_import(const char *filename);
void db_export(const char *filename);
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, in_addr_t *dest);
+int readaddr(const int fd, struct addr46 *dest);
int read64(const int fd, uint64_t *dest);
int read_file_header(const int fd, const uint8_t expected[4]);
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 in_addr_t addr);
+int writeaddr(const int fd, const struct addr46 *const addr);
int write64(const int fd, const uint64_t i);
/* vim:set ts=3 sw=3 tw=78 et: */
getsnaplen(const linkhdr_t *lh)
{
assert(lh != NULL);
- return (lh->hdrlen + IPV6_HDR_LEN + max(TCP_HDR_LEN, UDP_HDR_LEN));
+ /* TODO MEA Investigate why the supplementary value 20 is needed on GNU/Linux. */
+ return (20 + lh->hdrlen + IPV6_HDR_LEN + max(TCP_HDR_LEN, UDP_HDR_LEN));
}
/*
- * Convert IP address to a numbers-and-dots notation in a static buffer
- * provided by inet_ntoa().
+ * 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 in_addr_t ip)
+ip_to_str(const struct addr46 *const ip)
{
- struct in_addr in;
+ ipstr[0] = '\0';
+ inet_ntop(ip->af, &ip->addr.ip6, ipstr, sizeof(ipstr));
- in.s_addr = ip;
- return (inet_ntoa(in));
+ return (ipstr);
}
-char ip6str[INET6_ADDRSTRLEN];
-
char *
-ip6_to_str(const struct in6_addr *ip6)
+ip_to_str_af(const void *const addr, sa_family_t af)
{
- ip6str[0] = '\0';
- inet_ntop(AF_INET6, ip6, ip6str, sizeof(ip6str));
+ ipstr[0] = '\0';
+ inet_ntop(af, addr, ipstr, sizeof(ipstr));
- return (ip6str);
+ return (ipstr);
}
/* Decoding functions. */
sm->len = ntohs(hdr->ip_len);
sm->af = AF_INET;
sm->proto = hdr->ip_p;
- sm->src_ip = hdr->ip_src.s_addr;
- sm->dest_ip = hdr->ip_dst.s_addr;
+ memcpy(&sm->src_ip, &hdr->ip_src, sizeof(sm->src_ip));
+ memcpy(&sm->dest_ip, &hdr->ip_dst, sizeof(sm->dest_ip));
switch (sm->proto) {
case IPPROTO_TCP: {
#include <pcap.h>
#include <netinet/in_systm.h> /* n_time */
#define __USE_GNU 1
-#include <netinet/in.h> /* in_addr_t */
+#include <netinet/in.h> /* for <netinet/ip.h> */
#include <netinet/ip.h> /* struct ip */
+#include "hosts_db.h" /* addr46 */
+
#define PPP_HDR_LEN 4
#define FDDI_HDR_LEN 21
#define IP_HDR_LEN sizeof(struct ip)
const linkhdr_t *getlinkhdr(int linktype);
int getsnaplen(const linkhdr_t *lh);
-char *ip_to_str(const in_addr_t ip);
-char *ip6_to_str(const struct in6_addr *ip6);
+char *ip_to_str(const struct addr46 *const ip);
+char *ip_to_str_af(const void *const addr, sa_family_t af);
typedef struct {
/* Fields are in host byte order (except IPs) */
union {
- in_addr_t src_ip;
+ struct in_addr src_ip;
struct in6_addr src_ip6;
};
union {
- in_addr_t dest_ip;
+ struct in_addr dest_ip;
struct in6_addr dest_ip6;
};
time_t time;
static pid_t pid = -1;
struct dns_reply {
- in_addr_t ip;
- int error; /* h_errno, or 0 if no error */
+ struct addr46 addr;
+ int error; /* for gai_strerror(), or 0 if no error */
char name[MAXHOSTNAMELEN];
};
struct tree_rec {
RB_ENTRY(tree_rec) ptree;
- in_addr_t ip;
+ struct addr46 ip;
};
static int
tree_cmp(struct tree_rec *a, struct tree_rec *b)
{
- if (a->ip < b->ip) return (-1); else
- if (a->ip > b->ip) return (+1); else
- return (0);
+ if (a->ip.af != b->ip.af)
+ /* Sort IPv4 to the left of IPv6. */
+ return (a->ip.af == AF_INET ? -1 : +1);
+
+ if (a->ip.af == AF_INET) {
+ return (memcmp(&a->ip.addr.ip, &b->ip.addr.ip, sizeof(a->ip.addr.ip)));
+ }
+
+ /* 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);
RB_GENERATE(tree_t, tree_rec, ptree, tree_cmp)
void
-dns_queue(const in_addr_t ip)
+dns_queue(const struct addr46 *const ipaddr)
{
struct tree_rec *rec;
ssize_t num_w;
if (pid == -1)
return; /* no child was started - we're not doing any DNS */
+#if 1
+ if (ipaddr->af != AF_INET) {
+ verbosef("dns_queue() for unknown family %d.\n", ipaddr->af);
+ /* Not yet IPv6 capable. */
+ return;
+ }
+#endif
+
rec = xmalloc(sizeof(*rec));
- rec->ip = ip;
+ memcpy(&rec->ip, ipaddr, sizeof(rec->ip));
+
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(ip));
+ verbosef("already queued %s", ip_to_str(ipaddr));
free(rec);
return;
}
- num_w = write(sock[PARENT], &ip, sizeof(ip)); /* won't block */
+ num_w = write(sock[PARENT], ipaddr, sizeof(*ipaddr)); /* won't block */
if (num_w == 0)
warnx("dns_queue: write: ignoring end of file");
else if (num_w == -1)
warn("dns_queue: ignoring write error");
- else if (num_w != sizeof(ip))
- err(1, "dns_queue: wrote %d instead of %d",
- (int)num_w, (int)sizeof(ip));
+ else if (num_w != sizeof(*ipaddr))
+ err(1, "dns_queue: wrote %z instead of %z", num_w, sizeof(*ipaddr));
}
static void
-dns_unqueue(const in_addr_t ip)
+dns_unqueue(const struct addr46 *const ipaddr)
{
struct tree_rec tmp, *rec;
- tmp.ip = ip;
+ memcpy(&tmp.ip, ipaddr, sizeof(tmp.ip));
if ((rec = RB_FIND(tree_t, &ip_tree, &tmp)) != NULL) {
RB_REMOVE(tree_t, &ip_tree, rec);
free(rec);
}
else
- verbosef("couldn't unqueue %s - not in queue!", ip_to_str(ip));
+ verbosef("couldn't unqueue %s - not in queue!", ip_to_str(ipaddr));
}
/*
* (name buffer is allocated by dns_poll)
*/
static int
-dns_get_result(in_addr_t *ip, char **name)
+dns_get_result(struct addr46 *ipaddr, char **name)
{
struct dns_reply reply;
ssize_t numread;
if (numread == 0)
goto error; /* EOF */
if (numread != sizeof(reply))
- errx(1, "dns_get_result read got %d, expected %d",
- (int)numread, (int)sizeof(reply));
+ errx(1, "dns_get_result read got %z, expected %z", numread, sizeof(reply));
/* Return successful reply. */
- *ip = reply.ip;
+ memcpy(ipaddr, &reply.addr, sizeof(*ipaddr));
+#if DARKSTAT_USES_HOSTENT
if (reply.error != 0)
xasprintf(name, "(%s)", hstrerror(reply.error));
else
*name = xstrdup(reply.name);
- dns_unqueue(reply.ip);
+#else /* !DARKSTAT_USES_HOSTENT */
+ if (reply.error != 0) {
+ /* Identify common special cases. */
+ char *type = "none";
+
+ if (reply.addr.af == AF_INET6) {
+ if (IN6_IS_ADDR_LINKLOCAL(&reply.addr.addr.ip6))
+ type = "link-local";
+ else if (IN6_IS_ADDR_SITELOCAL(&reply.addr.addr.ip6))
+ type = "site-local";
+ else if (IN6_IS_ADDR_MULTICAST(&reply.addr.addr.ip6))
+ type = "multicast";
+ } else { /* AF_INET */
+ if (IN_MULTICAST(reply.addr.addr.ip.s_addr))
+ type = "multicast";
+ }
+ xasprintf(name, "(%s)", type);
+ }
+ else /* Correctly resolved name. */
+ *name = xstrdup(reply.name);
+#endif /* !DARKSTAT_USES_HOSTENT */
+
+ dns_unqueue(&reply.addr);
return (1);
error:
void
dns_poll(void)
{
- in_addr_t ip;
+ struct addr46 ip;
char *name;
if (pid == -1)
while (dns_get_result(&ip, &name)) {
/* push into hosts_db */
- struct bucket *b = host_find(ip);
+ struct bucket *b = host_find(&ip);
+
if (b == NULL) {
verbosef("resolved %s to %s but it's not in the DB!",
- ip_to_str(ip), name);
+ ip_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);
+ ip_to_str(&ip), name);
return;
}
b->u.host.dns = name;
struct qitem {
STAILQ_ENTRY(qitem) entries;
- in_addr_t ip;
+ struct addr46 ip;
};
STAILQ_HEAD(qhead, qitem) queue = STAILQ_HEAD_INITIALIZER(queue);
static void
-enqueue(const in_addr_t ip)
+enqueue(const struct addr46 *const ip)
{
struct qitem *i;
i = xmalloc(sizeof(*i));
- i->ip = ip;
+ memcpy(&i->ip, ip, sizeof(i->ip));
STAILQ_INSERT_TAIL(&queue, i, entries);
verbosef("DNS: enqueued %s", ip_to_str(ip));
}
/* Return non-zero and populate <ip> pointer if queue isn't empty. */
static int
-dequeue(in_addr_t *ip)
+dequeue(struct addr46 *ip)
{
struct qitem *i;
if (i == NULL)
return (0);
STAILQ_REMOVE_HEAD(&queue, entries);
- *ip = i->ip;
+ memcpy(ip, &i->ip, sizeof(*ip));
free(i);
+ verbosef("DNS: dequeued %s", ip_to_str(ip));
return 1;
}
static void
dns_main(void)
{
- in_addr_t ip;
+ struct addr46 ip;
#ifdef HAVE_SETPROCTITLE
setproctitle("DNS child");
err(1, "DNS: read failed");
}
if (numread != sizeof(ip))
- err(1, "DNS: read got %d bytes, expecting %d",
- (int)numread, (int)sizeof(ip));
- enqueue(ip);
+ err(1, "DNS: read got %z bytes, expecting %z", numread, sizeof(ip));
+ enqueue(&ip);
if (blocking) {
/* After one blocking read, become non-blocking so that when we
* run out of input we fall through to queue processing.
/* Process queue. */
if (dequeue(&ip)) {
struct dns_reply reply;
+#if DARKSTAT_USES_HOSTENT
struct hostent *he;
- reply.ip = ip;
- he = gethostbyaddr((char *)&ip, sizeof(ip), AF_INET);
+ memcpy(&reply.addr, &ip, sizeof(reply.addr));
+ he = gethostbyaddr((char *)&ip.addr.ip, sizeof(ip.addr.ip), ip.af); /* TODO MEA */
/* On some platforms (for example Linux with GLIBC 2.3.3), h_errno
* will be non-zero here even though the lookup succeeded.
}
fd_set_block(sock[CHILD]);
xwrite(sock[CHILD], &reply, sizeof(reply));
- verbosef("DNS: %s is %s", ip_to_str(ip),
+ verbosef("DNS: %s is %s", ip_to_str(&reply.addr),
(h_errno == 0)?reply.name:hstrerror(h_errno));
+#else /* !DARKSTAT_USES_HOSTENT */
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ char host[NI_MAXHOST];
+ int ret, flags;
+
+ reply.addr.af = ip.af;
+ 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));
+ 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));
+ ret = getnameinfo((struct sockaddr *) &sin6, sizeof(sin6),
+ host, sizeof(host), NULL, 0, flags);
+ break;
+ default:
+ ret = EAI_FAMILY;
+
+ }
+
+ if (ret != 0) {
+ reply.name[0] = '\0';
+ reply.error = ret;
+ } else {
+ assert(sizeof(reply.name) > sizeof(char *)); /* not just a ptr */
+ strlcpy(reply.name, host, sizeof(reply.name));
+ reply.error = 0;
+ }
+ fd_set_block(sock[CHILD]);
+ xwrite(sock[CHILD], &reply, sizeof(reply));
+ verbosef("DNS: %s is \"%s\".", ip_to_str(&reply.addr),
+ (ret == 0) ? reply.name : gai_strerror(ret));
+#endif /* !DARKSTAT_USES_HOSTENT */
}
}
}
* GNU General Public License version 2. (see COPYING.GPL)
*/
-#include <netinet/in.h> /* in_addr_t */
+#include "hosts_db.h" /* addr46 */
void dns_init(const char *privdrop_user);
void dns_stop(void);
-void dns_queue(const in_addr_t ip);
+void dns_queue(const struct addr46 *const ip);
void dns_poll(void);
/* vim:set ts=3 sw=3 tw=78 expandtab: */
*/
#include <sys/types.h>
-#include <netinet/in.h> /* for in_addr_t (db.h needs it) */
#include "cap.h"
#include "conv.h"
#include "now.h"
#include <arpa/inet.h> /* inet_aton() */
+#include <netdb.h> /* struct addrinfo */
#include <assert.h>
#include <errno.h>
#include <stdio.h>
* src/sys/netinet/tcp_hostcache.c 1.1
*/
inline static uint32_t
-ipv4_hash(const uint32_t ip)
+ipv4_hash(const struct in_addr *const ip)
{
- return ( (ip) ^ ((ip) >> 7) ^ ((ip) >> 17) );
+ return ( (ip->s_addr) ^ ((ip->s_addr) >> 7) ^ ((ip->s_addr) >> 17) );
}
#ifndef s6_addr32
static uint32_t
hash_func_host(const struct hashtable *h _unused_, const void *key)
{
- return (ipv4_hash(CASTKEY(in_addr_t)));
+ 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;
+ }
}
static uint32_t
static const void *
key_func_host(const struct bucket *b)
{
- return &(b->u.host.ip);
+ return &(b->u.host.ipaddr);
}
static const void *
static int
find_func_host(const struct bucket *b, const void *key)
{
- return (b->u.host.ip == CASTKEY(in_addr_t));
+ 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;
+ }
}
static int
make_func_host(const void *key)
{
MAKE_BUCKET(b, h, host);
- h->ip = CASTKEY(in_addr_t);
+ memcpy(&h->ipaddr, key, sizeof(h->ipaddr));
h->dns = NULL;
h->last_seen = now;
memset(&h->mac_addr, 0, sizeof(h->mac_addr));
format_row_host(struct str *buf, const struct bucket *b,
const char *css_class)
{
- const char *ip = ip_to_str( b->u.host.ip );
+ const char *ip = ip_to_str( &b->u.host.ipaddr );
str_appendf(buf,
"<tr class=\"%s\">\n"
/* Only resolve hosts "on demand" */
if (b->u.host.dns == NULL)
- dns_queue(b->u.host.ip);
+ dns_queue(&b->u.host.ipaddr);
}
static void
* Return existing host or insert a new one.
*/
struct bucket *
-host_get(const in_addr_t ip)
+host_get(const struct addr46 *const ip)
{
- return (hashtable_find_or_insert(hosts_db, &ip));
+ return (hashtable_find_or_insert(hosts_db, ip));
}
/* ---------------------------------------------------------------------------
* Find host, returns NULL if not in DB.
*/
struct bucket *
-host_find(const in_addr_t ip)
+host_find(const struct addr46 *const ip)
{
- return (hashtable_search(hosts_db, &ip));
+ return (hashtable_search(hosts_db, ip));
}
/* ---------------------------------------------------------------------------
static struct bucket *
host_search(const char *ipstr)
{
- struct in_addr addr;
+ struct addr46 ipaddr;
+ struct sockaddr_storage ss;
+ struct addrinfo hints, *ai;
- if (inet_aton(ipstr, &addr) != 1)
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ if (getaddrinfo(ipstr, NULL, &hints, &ai))
return (NULL); /* invalid addr */
- return (hashtable_search(hosts_db, &(addr.s_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);
+ }
+
+ return (hashtable_search(hosts_db, &ipaddr));
}
/* ---------------------------------------------------------------------------
/* Resolve host "on demand" */
if (h->u.host.dns == NULL)
- dns_queue(h->u.host.ip);
+ dns_queue(&h->u.host.ipaddr);
if (show_mac_addrs)
str_appendf(buf,
hosts_db_import_host(const int fd)
{
struct bucket *host;
- in_addr_t addr;
+ struct addr46 ipaddr;
uint8_t hostname_len;
uint64_t in, out;
unsigned int pos = xtell(fd);
return 0;
}
- if (!readaddr(fd, &addr)) return 0;
- verbosef("at file pos %u, importing host %s", pos, ip_to_str(addr));
- host = host_get(addr);
- assert(host->u.host.ip == addr); /* make fn? */
+ 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 (ver > 1) {
uint64_t t;
if (!writen(fd, export_tag_host_ver2, sizeof(export_tag_host_ver2)))
return 0;
- if (!writeaddr(fd, b->u.host.ip)) return 0;
+ if (!writeaddr(fd, &b->u.host.ipaddr)) return 0;
if (!write64(fd, (uint64_t)(b->u.host.last_seen))) return 0;
* GNU General Public License version 2. (see COPYING.GPL)
*/
+#ifndef __HOSTS_DB_H
+# define __HOSTS_DB_H 1
+
#include <sys/types.h>
+#include <sys/socket.h>
#include <netinet/in.h>
#include "str.h"
+struct addr46 {
+ sa_family_t af;
+ union {
+ struct in_addr ip;
+ struct in6_addr ip6;
+ } addr;
+};
+
struct hashtable;
struct host {
- union {
- in_addr_t ip;
- struct in6_addr ip6;
- };
- sa_family_t af;
+ struct addr46 ipaddr;
char *dns;
uint8_t mac_addr[6];
time_t last_seen;
int hosts_db_import(const int fd);
int hosts_db_export(const int fd);
-struct bucket *host_find(const in_addr_t ip); /* can return NULL */
-struct bucket *host_get(const in_addr_t ip);
+struct bucket *host_find(const struct addr46 *const ip); /* can return NULL */
+struct bucket *host_get(const struct addr46 *const ip);
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);
void qsort_buckets(const struct bucket **a, size_t n,
size_t left, size_t right, const enum sort_dir d);
+#endif /* !__HOSTS_DB_H */
/* vim:set ts=3 sw=3 tw=78 expandtab: */
#include "darkstat.h"
#include "conv.h" /* for strlcpy */
-#include "decode.h" /* for ip_to_str, ip6_to_str */
+#include "decode.h" /* for ip_to_str */
#include "err.h"
#include "localip.h"
static const char *iface = NULL;
-in_addr_t localip = 0;
-static in_addr_t last_localip = 0;
+struct in_addr localip = { 0 };
+static struct in_addr last_localip = { 0 };
struct in6_addr localip6;
static struct in6_addr last_localip6;
if (iface == NULL) {
/* reading from capfile */
- localip = 0;
- memset(&localip6, '\0', sizeof(localip6));
+ memset(&localip, 0, sizeof(localip));
+ memset(&localip6, 0, sizeof(localip6));
return;
}
if ( (ifa->ifa_addr->sa_family == AF_INET)
&& ! (flags & HAS_IPV4) ) {
/* Good IPv4 address. */
- localip = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr;
+ localip.s_addr = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr;
flags |= HAS_IPV4;
continue;
}
* __u32 s_addr;
*/
- if (last_localip != localip) {
- verbosef("local_ip update(%s) = %s", iface, ip_to_str(localip));
- last_localip = localip;
+ 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 (memcmp(&last_localip6, &localip6, sizeof(localip6))) {
- verbosef("local_ip6 update(%s) = %s", iface, ip6_to_str(&localip6));
+ verbosef("local_ip6 update(%s) = %s", iface,
+ ip_to_str_af(&localip6, AF_INET6));
memcpy(&last_localip6, &localip6, sizeof(localip6));
}
}
* GNU General Public License version 2. (see COPYING.GPL)
*/
-#include <netinet/in.h> /* for in_addr_t */
+#include <netinet/in.h> /* for in_addr, in6_addr */
-extern in_addr_t localip;
+extern struct in_addr localip;
extern struct in6_addr localip6;
void localip_init(const char *interface);