From 548b872ae45485254d6d8a1ef9967e4539f84321 Mon Sep 17 00:00:00 2001 From: Laurent Ghigonis Date: Tue, 4 Dec 2012 00:58:47 +0100 Subject: add libggnet, a helper to keep track of network nodes and connections --- libglouglou/Makefile | 4 +- libglouglou/libggnet.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++ libglouglou/libggnet.h | 70 ++++++++++++++++++++++ 3 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 libglouglou/libggnet.c create mode 100644 libglouglou/libggnet.h diff --git a/libglouglou/Makefile b/libglouglou/Makefile index 83ac0b5..5f1150f 100644 --- a/libglouglou/Makefile +++ b/libglouglou/Makefile @@ -6,8 +6,8 @@ LIBDIR=$(PREFIX)/lib LIBNAME=libglouglou TARGET = ${LIBNAME}.so -SOURCES = libglouglou.c sendbuf.c utils.c -HEADERS = libglouglou.h +SOURCES = libglouglou.c sendbuf.c utils.c libggnet.c +HEADERS = libglouglou.h libggnet.h OBJECTS = $(SOURCES:.c=.o) all: $(TARGET) diff --git a/libglouglou/libggnet.c b/libglouglou/libggnet.c new file mode 100644 index 0000000..c3a82ea --- /dev/null +++ b/libglouglou/libggnet.c @@ -0,0 +1,154 @@ +#include + +#include "libglouglou.h" +#include "libggnet.h" + +struct ggnet * +ggnet_new(void) +{ + struct ggnet *net; + + net = xcalloc(1, sizeof(struct ggnet)); + return net; +} + +void +ggnet_free(struct ggnet *net) +{ + struct ggnet_conn *c, *ctmp; + struct ggnet_node *n, *ntmp; + + LIST_FOREACH_SAFE(c, &net->conn_list, entry, ctmp) + ggnet_conn_del(net, c); + LIST_FOREACH_SAFE(n, &net->node_list, entry, ntmp) + ggnet_node_del(net, n); + free(net); +} + +struct ggnet_node * +ggnet_node_add(struct ggnet *net, struct in_addr *addr) +{ + struct ggnet_node *n; + + gg_log_debug("user: ggnet_node_add"); + + n = xcalloc(1, sizeof(struct ggnet_node)); + n->addr.s_addr = addr->s_addr; + n->namelen = NODENAME_WAITING; + n->lastseen = net->time; + LIST_INSERT_HEAD(&net->node_list, n, entry); + net->node_count++; + + return n; +} + +void +ggnet_node_del(struct ggnet *net, struct ggnet_node *n) +{ + if (n->used) + gg_log_fatal("user: trying to remove a used node !"); + gg_log_debug("user: ggnet_node_del"); + + LIST_REMOVE(n, entry); + free(n->name); + free(n); + net->node_count--; +} + +struct ggnet_node * +ggnet_node_find(struct ggnet *net, struct in_addr *remote) +{ + struct ggnet_node *n; + + LIST_FOREACH(n, &net->node_list, entry) + if (n->addr.s_addr == remote->s_addr) + return n; + return NULL; +} + +struct ggnet_conn * +ggnet_conn_add(struct ggnet *net, struct in_addr *src, int src_port, + struct in_addr *dst, int dst_port, int proto, int size) +{ + struct ggnet_conn *c; + struct ggnet_node *srcnode; + struct ggnet_node *dstnode; + int id; + + gg_log_debug("user: ggnet_conn_add, %x:%d->%x:%d %d [%d]", + src->s_addr, src_port, dst->s_addr, dst_port, proto, size); + if (net->conn_freeids_ptr == GGNET_CONN_FREEIDS_COUNT) { + gg_log_warn("user: out of connection identifiers !"); + return NULL; + } + + id = net->conn_freeids[net->conn_freeids_ptr]; + net->conn_freeids_ptr++; + + srcnode = ggnet_node_find(net, src); + if (!srcnode) + srcnode = ggnet_node_add(net, src); + srcnode->used++; + dstnode = ggnet_node_find(net, dst); + if (!dstnode) + dstnode = ggnet_node_add(net, dst); + dstnode->used++; + + c = xmalloc(sizeof(struct ggnet_conn)); + c->id = id; + c->state = CONNSTATE_ESTABLISHED; + c->src = srcnode; + c->src_port = src_port; + c->dst = dstnode; + c->dst_port = dst_port; + c->proto = proto; + c->size = size; + c->lastseen = net->time; + LIST_INSERT_HEAD(&net->conn_list, c, entry); + + return c; +} + +void +ggnet_conn_data(struct ggnet *net, struct ggnet_conn *c, int size, int response) +{ + gg_log_debug("user: ggnet_conn_data"); + + c->lastseen = net->time; +} + +void +ggnet_conn_del(struct ggnet *net, struct ggnet_conn *c) +{ + gg_log_debug("user: ggnet_conn_del"); + + if (c->proto == IPPROTO_TCP) { + switch (c->state) { + case CONNSTATE_ESTABLISHED: + c->state = CONNSTATE_TCPFIN; + return; + case CONNSTATE_TCPFIN: + c->state = CONNSTATE_TCPFIN2; + return; + case CONNSTATE_TCPFIN2: + break; + } + } + + if (net->conn_freeids_ptr == 0) + gg_log_fatal("net->conn_freeids_ptr == 0"); + net->conn_freeids_ptr--; + net->conn_freeids[net->conn_freeids_ptr] = c->id; + + c->src->used--; + c->dst->used--; + + LIST_REMOVE(c, entry); + free(c); +} + +void +ggnet_time_update(struct ggnet *net, time_t time) +{ + net->time = time; +} diff --git a/libglouglou/libggnet.h b/libglouglou/libggnet.h new file mode 100644 index 0000000..17be7e8 --- /dev/null +++ b/libglouglou/libggnet.h @@ -0,0 +1,70 @@ +#include +#include + +#if defined(__OpenBSD__) +#include +#else +#include +#endif + +#define GGNET_NULL_HDRLEN 4 // XXX portable ? +#define GGNET_NODE_MAX_WITHOUT_TIMEOUT 1000 +#define GGNET_NODE_TIMEOUT 300 // XXX conf ? +#define GGNET_CONN_TIMEOUT 300 // XXX conf ? +#define GGNET_CONN_TIMEOUT_UDP 20 // XXX conf ? +#define GGNET_CONN_TIMEOUT_ICMP 10 // XXX conf ? +#define GGNET_CONN_FREEIDS_COUNT 65536 /* 2^16 as freeids are u_int16_t */ +#define GGNET_CONNTIMER 5 // XXX conf ? + +struct ggnet_node { + LIST_ENTRY(ggnet_node) entry; + struct in_addr addr; + time_t lastseen; + int used; + short namelen; +#define NODENAME_WAITING -1 +#define NODENAME_FAILED -2 + char *name; +}; + +enum ggnet_connstate { + CONNSTATE_ESTABLISHED, + CONNSTATE_TCPFIN, + CONNSTATE_TCPFIN2 +}; + +struct ggnet_conn { + LIST_ENTRY(ggnet_conn) entry; + u_int id; + enum ggnet_connstate state; + struct ggnet_node *src; + u_int src_port; + struct ggnet_node *dst; + u_int dst_port; + u_int proto; + u_int size; + time_t lastseen; +}; + +struct ggnet { + LIST_HEAD(, ggnet_conn) conn_list; + LIST_HEAD(, ggnet_node) node_list; + int conn_count; + int node_count; + u_int16_t conn_freeids[GGNET_CONN_FREEIDS_COUNT]; + int conn_freeids_ptr; + time_t time; +}; + +struct ggnet *ggnet_new(void); +void ggnet_free(struct ggnet *); +struct ggnet_node *ggnet_node_add(struct ggnet *, struct in_addr *); +void ggnet_node_del(struct ggnet *, struct ggnet_node *); +struct ggnet_node *ggnet_node_find(struct ggnet *, struct in_addr *); +struct ggnet_conn *ggnet_conn_add(struct ggnet *, struct in_addr *, int, + struct in_addr *, int, int, int); +void ggnet_conn_data(struct ggnet *, struct ggnet_conn *, + int, int); +void ggnet_conn_del(struct ggnet *, struct ggnet_conn *); +struct ggnet_conn *ggnet_conn_find(struct ggnet *, struct in_addr *); +void ggnet_time_update(struct ggnet *, time_t); -- cgit v1.2.3-59-g8ed1b