aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libglouglou/Makefile4
-rw-r--r--libglouglou/libggnet.c154
-rw-r--r--libglouglou/libggnet.h70
3 files changed, 226 insertions, 2 deletions
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 <stdlib.h>
+
+#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 <sys/types.h>
+#include <netinet/in.h>
+
+#if defined(__OpenBSD__)
+#include <sys/queue.h>
+#else
+#include <bsd/sys/queue.h>
+#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);