From 0877b97bd68fd60e3dbcd9dd2286f3006430c298 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Wed, 9 Nov 2011 16:08:47 +0100 Subject: adding primitive config file handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork --- .gitignore | 2 + Makefile | 23 ++++++-- btree.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 btree.c diff --git a/.gitignore b/.gitignore index 0f3ed06..6d2689a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.o *~ ldra +btree +conf diff --git a/Makefile b/Makefile index f4adeff..6bd105e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,22 @@ -all: ldra +CC=gcc +CFLAGS= +BINARIES=ldra btree +LINK_MODE= +LDFLAGS= -ldra: ldra.c dhcpv6.h - gcc -o ldra ldra.c +.PHONY: all clean +all: $(BINARIES) + +%.o: %.c + $(CC) $(CFLAGS) -c $< + +btree: btree.o + $(CC) $(LDFLAGS) $(LINK_MODE) -o $@ $^ + + +ldra: ldra.o + $(CC) $(LDFLAGS) $(LINK_MODE) -o $@ $^ + +clean: + rm -rf *.o *.so *.lo *~ $(BINARIES) .libs diff --git a/btree.c b/btree.c new file mode 100644 index 0000000..92912e5 --- /dev/null +++ b/btree.c @@ -0,0 +1,174 @@ +#include +#include +#include +#include +#include + +/* maybe just use +http://cjson.sourceforge.net/ +or maybe even better: +https://bitbucket.org/zserge/jsmn/src + +for the parsing? * + + +/* parse downstream configuration file + format: + port;vlan;remote-id;subscriber-id;trusted + + port: + interface name + vlan: + vlanid || 0 + remote-id: + string for REMOTE-ID attribute (requires enterprise number as input option) + subscriber-id: + string for SUBSCRIBER-ID attribute + trusted: + boolean 0 || 1 indicating whether we allow RELAY-FORW messages from this port + + + example: + eth2;604;123abc;hansen;0 + + output: + we combine port+vlan into a 32bit value which is used directly as the INTERFACE-ID key + + a structure is allocated with pointers to the remote-id and + + a rather large structure is allocated for each new port: + + + + +*/ + +/* flags */ +#define SUB_F_TRUSTED 1 +#define SUB_F_ALL SUB_F_TRUSTED + +/* suscriber struct */ +struct subscriber { + int interfaceid; + int flags; + char *remoteid; + char *subscriberid; +}; + +/* bintree structure */ +struct e_btree { + struct subscriber data; + struct e_btree *l,*r; + +}; + +static struct e_btree *head = NULL; + +/* simple recursive bintree insert */ +struct e_btree *binsert(struct e_btree **p, struct subscriber *data) +{ + if (!*p) { + *p = malloc(sizeof(struct e_btree)); + if (!*p) + return NULL; /* malloc failed? */ + (*p)->l = NULL; + (*p)->r = NULL; + memcpy(&(*p)->data, data, sizeof(struct subscriber)); + return *p; + } + if (data->interfaceid < (*p)->data.interfaceid) { + fprintf(stderr, "%d < %d\n", data->interfaceid, (*p)->data.interfaceid); + return binsert(&(*p)->l, data); +} + fprintf(stderr, "%d > %d\n", data->interfaceid, (*p)->data.interfaceid); + return binsert(&(*p)->r, data); +} + +/* simple recursive bintree shift() */ +struct subscriber *bshift(struct e_btree **p, struct subscriber *e) +{ + static int level = 0; + + if (!*p) + return NULL; /* finished */ + + /* dump right tree */ + if ((*p)->r) + bshift(&(*p)->r, e); + + + /* we can now finish this node */ + fprintf(stderr, "going to return ifid=%d now\n", (*p)->data.interfaceid); + + /* dump left tree */ + if ((*p)->l) + bshift(&(*p)->l, e); + +/* memcpy(e, &(*p)->data, sizeof(*e)); + free(*p); + *p = NULL; + return e; +*/ + return NULL; +} + +/* global array holding all the entries */ +static struct subscriber sentry[]; +static int nsubscribers = 0; + + +/* strategy: + dynamically allocate entries as they are parsed and temporarily store them in a bintree + allocate an array which is just big enough after parsing + store all entries *sorted* in the array + + the reason for not keeping the bintree is that it most likely is very sub-optimal, as the + data typically will appear in a semi-sorted order in the configuration file + + use binary search when looking up an entry + + note that lookup is only necessary for down => up packets +*/ + + +int parse_config(char *fname) +{ + FILE *f; + int n, i = 0; + char ifname[IFNAMSIZ]; + struct subscriber e; + + f = fopen(fname, "r"); + if (!f) { + fprintf(stderr, "%s(): cannot open configuration file \"%s\": %m\n", __FUNCTION__, fname); + return -1; + } + while (n = fscanf(f, " %[^;] ; %u ; %m[^;] ; %m[^;] ; %u ; ", &ifname, &e.interfaceid, &e.remoteid, &e.subscriberid, &e.flags) > 0) { + /* FIXME: do cached lookup of ifindex for ifname and add to interfaceid */ + + e.interfaceid &= 0xfff; /* VLAN tags are 12bit only */ + e.flags &= SUB_F_ALL; /* mask out invalid flags */ + fprintf(stderr, "parsed entry %d (ifname=%s, ifid=%d)\n", i, ifname, e.interfaceid); + binsert(&head, &e); + i++; + } + fclose(f); +} + + +int main(int argc, char *argv[]) +{ + struct subscriber e; + + if (argc < 2) + return -1; + + + parse_config(argv[1]); + + while (bshift(&head, &e)) + ;; +// fprintf(stderr, "ifid=%d, rid=%s, sid=%s, flags=%d\n", e.interfaceid, e.remoteid, e.subscriberid, e.flags); + + return 0; +} -- cgit v1.2.3