summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2011-11-09 16:08:47 +0100
committerBjørn Mork <bjorn@mork.no>2011-11-09 16:20:38 +0100
commit0877b97bd68fd60e3dbcd9dd2286f3006430c298 (patch)
treed0d1d2a23eaf3bd885da0a83536b16eb0afd9ce4
parent6801b5f1358c3d60e9125755cc8e4c517bd5e63d (diff)
adding primitive config file handlingHEADmaster
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--.gitignore2
-rw-r--r--Makefile23
-rw-r--r--btree.c174
3 files changed, 196 insertions, 3 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <net/if.h>
+
+/* 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;
+}