diff options
Diffstat (limited to 'proto/firewall')
-rw-r--r-- | proto/firewall/Doc | 1 | ||||
-rw-r--r-- | proto/firewall/Makefile | 6 | ||||
-rw-r--r-- | proto/firewall/config.Y | 75 | ||||
-rw-r--r-- | proto/firewall/firewall.c | 201 | ||||
-rw-r--r-- | proto/firewall/firewall.h | 52 |
5 files changed, 335 insertions, 0 deletions
diff --git a/proto/firewall/Doc b/proto/firewall/Doc new file mode 100644 index 00000000..57793429 --- /dev/null +++ b/proto/firewall/Doc @@ -0,0 +1 @@ +S firewall.c diff --git a/proto/firewall/Makefile b/proto/firewall/Makefile new file mode 100644 index 00000000..a322ab6a --- /dev/null +++ b/proto/firewall/Makefile @@ -0,0 +1,6 @@ +source=firewall.c +root-rel=../../ +dir-name=proto/firewall + +include ../../Rules + diff --git a/proto/firewall/config.Y b/proto/firewall/config.Y new file mode 100644 index 00000000..805fc3fe --- /dev/null +++ b/proto/firewall/config.Y @@ -0,0 +1,75 @@ +/* + * BIRD -- Firewall Protocol Configuration + * + * (c) 2011 Alexander V. Chernikov <<A HREF="http://trubka.network.cz/mailman/listinfo/bird-users">melifaro at FreeBSD.org</A>> + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +CF_HDR + +#include "proto/firewall/firewall.h" + +CF_DEFINES + +#define FIREWALL_CFG ((struct firewall_config *) this_proto) + +CF_DECLS + +CF_KEYWORDS(FIREWALL, FWTABLE, FWTYPE, FW_VALUE, IPFW, PF, IPSET, FLUSH, ON, STARTUP, SHUTDOWN, ALWAYS) + +%type <i> firewall_type +CF_GRAMMAR + +CF_ADDTO(proto, firewall_proto '}') + +firewall_proto_start: proto_start FIREWALL { + this_proto = proto_config_new(&proto_firewall, sizeof(struct firewall_config), $1); + this_proto->preference = 0; + } + ; + +firewall_proto: + firewall_proto_start proto_name '{' + | firewall_proto proto_item ';' + | firewall_proto firewall_proto_item ';' + ; + +firewall_proto_item: + FWTYPE firewall_type { + switch ($2) + { +#ifdef CONFIG_FIREWALL_IPFW + case FWTYPE_IPFW: + break; +#endif +#ifdef CONFIG_FIREWALL_PF + case FWTYPE_PF: + break; +#endif +#ifdef CONFIG_FIREWALL_IPSET + case FWTYPE_IPSET: + break; +#endif + default: + cf_error("firewall type is not supported by your OS"); + } + FIREWALL_CFG->fwtype = $2; + }; + | FWTABLE TEXT { FIREWALL_CFG->fwtable = $2; } + | FLUSH ON STARTUP { FIREWALL_CFG->flush_start = 1; } + | FLUSH ON SHUTDOWN { FIREWALL_CFG->flush_shutdown = 1; } + | FLUSH ALWAYS { FIREWALL_CFG->flush_start = 1; FIREWALL_CFG->flush_shutdown = 1; } + ; + +firewall_type: + IPFW { $$ = FWTYPE_IPFW; } + | PF { $$ = FWTYPE_PF; } + | IPSET { $$ = FWTYPE_IPSET; } + ; + +CF_ADDTO(dynamic_attr, FW_VALUE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_FIREWALL_VALUE); }) + +CF_CODE + +CF_END diff --git a/proto/firewall/firewall.c b/proto/firewall/firewall.c new file mode 100644 index 00000000..36172cf7 --- /dev/null +++ b/proto/firewall/firewall.c @@ -0,0 +1,201 @@ +/* + * BIRD -- Firewall Protocol Configuration + * + * (c) 2011 Alexander V. Chernikov <<A HREF="http://trubka.network.cz/mailman/listinfo/bird-users">melifaro at FreeBSD.org</A>> + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +/** + * DOC: Firewall + * + * Firewall protocol is very simple. It adds or removes exported routes to given firewall + * table with zero (or filter-specified) value. Table can be flushed on startup to + * avoid error messages on bird restart. + */ + +#undef LOCAL_DEBUG + +#include "nest/bird.h" +#include "nest/iface.h" +#include "nest/protocol.h" +#include "nest/route.h" +#include "conf/conf.h" +#include "filter/filter.h" +#include "lib/string.h" + +#include "firewall.h" + +static int init_done = 0; + +static void +firewall_collect(void) +{ + memset(&firewalls, 0, sizeof(firewalls)); + log(L_DEBUG "Initializing firewalls.."); +#ifdef CONFIG_FIREWALL_IPFW + firewalls[FWTYPE_IPFW] = &fw_ipfw; + log(L_DEBUG "IPFW.."); +#endif +#ifdef CONFIG_FIREWALL_PF + firewalls[FWTYPE_PF] = &fw_pf; + log(L_DEBUG "PF.."); +#endif +#ifdef CONFIG_FIREWALL_IPSET + firewalls[FWTYPE_IPSET] = &fw_ipset; + log(L_DEBUG "IPSET.."); +#endif +} + +static void +firewall_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, ea_list *attrs) +{ + struct firewall_proto *p = (struct firewall_proto *) P; + u32 prefix_val; + char prefix_data[10]; + + if (!new && !old) + return; + + prefix_val = ea_get_int(attrs, EA_FIREWALL_VALUE, 0); + + if (prefix_val) + bsnprintf(prefix_data, sizeof(prefix_data), "%u", prefix_val); + else + prefix_data[0] = '\0'; + + DBG("Got prefix %I/%d with data '%s'\n", n->n.prefix, n->n.pxlen, prefix_data); + + if (old && new && p->fw->fw_replace) + { + if (!p->fw->fw_replace(p->fwdata, n, prefix_data)) + log(L_ERR "Replacing prefix %I/%d with data '%S' failed", n->n.prefix, n->n.pxlen, prefix_data); + return; + } + + if (old) + if (!p->fw->fw_del(p->fwdata, n)) + log(L_ERR "Removing prefix %I/%d failed", n->n.prefix, n->n.pxlen); + + if (new) + if (!p->fw->fw_add(p->fwdata, n, prefix_data)) + log(L_ERR "Adding prefix %I/%d with data '%s' failed", n->n.prefix, n->n.pxlen, prefix_data); + +} + +static int +firewall_start(struct proto *P) +{ + struct firewall_proto *p = (struct firewall_proto *) P; + struct firewall_config *c = (struct firewall_config *)P->cf; + void *fwdata; + + if ((fwdata = p->fw->fw_init(P, c->fwtable)) == NULL) + return PS_DOWN; + + p->fwdata = fwdata; + + /* Flush table if needed */ + if ((c->flush_start) && (p->fw->fw_flush)) + if (!p->fw->fw_flush(fwdata)) + { + log(L_ERR "flush failed for table %s", c->fwtable); + return PS_DOWN; + } + + return PS_UP; +} + +static int +firewall_shutdown(struct proto *P) +{ + struct firewall_proto *p = (struct firewall_proto *) P; + struct firewall_config *c = (struct firewall_config *)P->cf; + + log(L_DEBUG, "Shutdown requested"); + + /* Flush table if needed */ + if ((c->flush_shutdown) && (p->fw->fw_flush)) + if (!p->fw->fw_flush(p->fwdata)) + log(L_ERR "flush failed for table %s", c->fwtable); + + p->fw->fw_shutdown(p->fwdata); + + return PS_DOWN; +} + +static struct proto * +firewall_init(struct proto_config *C) +{ + struct firewall_config *c = (struct firewall_config *) C; + struct proto *P = proto_new(C, sizeof(struct firewall_proto)); + struct firewall_proto *p = (struct firewall_proto *) P; + + /* Configure firewalls */ + if (!init_done) + { + init_done = 1; + firewall_collect(); + } + + p->fwtype = c->fwtype; + p->fw = firewalls[p->fwtype]; + P->accept_ra_types = RA_OPTIMAL; + P->rt_notify = firewall_rt_notify; + + return P; +} + +static int +firewall_reconfigure(struct proto *P, struct proto_config *new) +{ + struct firewall_config *o = (struct firewall_config *) P->cf; + struct firewall_config *n = (struct firewall_config *) new; + + if ((o->fwtype != n->fwtype) || (strcmp(o->fwtable, n->fwtable))) + return 0; + + return 1; +} + +static void +firewall_copy_config(struct proto_config *dest, struct proto_config *src) +{ + /* Just a shallow copy, not many items here */ + proto_copy_rest(dest, src, sizeof(struct firewall_config)); +} + +static void +firewall_get_status(struct proto *P, byte *buf) +{ + struct firewall_config *c = (struct firewall_config *) P->cf; + + bsprintf(buf, "Table [%s]", c ? c->fwtable : "none"); +} + +static int +firewall_get_attr(eattr * a, byte * buf, int buflen UNUSED) +{ + switch (a->id) + { + case EA_FIREWALL_VALUE: + bsprintf(buf, "fw_value"); + return GA_NAME; + default: + return GA_UNKNOWN; + } +} + + +struct protocol proto_firewall = { + name: "Firewall", + template: "fw%d", + class: PROTOCOL_FIREWALL, + init: firewall_init, + start: firewall_start, + shutdown: firewall_shutdown, + reconfigure: firewall_reconfigure, + copy_config: firewall_copy_config, + get_status: firewall_get_status, + get_attr: firewall_get_attr, +}; diff --git a/proto/firewall/firewall.h b/proto/firewall/firewall.h new file mode 100644 index 00000000..7b16301a --- /dev/null +++ b/proto/firewall/firewall.h @@ -0,0 +1,52 @@ +/* + * BIRD -- Firewall Protocol Configuration + * + * (c) 2011 Alexander V. Chernikov <<A HREF="http://trubka.network.cz/mailman/listinfo/bird-users">melifaro at FreeBSD.org</A>> + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#ifndef _BIRD_FIREWALL_H_ +#define _BIRD_FIREWALL_H_ + +#define FWTYPE_IPFW 0 +#define FWTYPE_PF 1 +#define FWTYPE_IPSET 2 + +#define FWTYPE_MAX 3 + +#define EA_FIREWALL_VALUE EA_CODE(EAP_FIREWALL, 0) + +struct firewall_config { + struct proto_config c; + int fwtype; /* Firewall type */ + char *fwtable; /* Firewall table to write to */ + int flush_start; /* Do table flush on startup? */ + int flush_shutdown; /* Do table flush on shutdown? */ +}; + +struct firewall_control { + int fwtype; /* Firewall type */ + char *description; /* Firewall description */ + void *(*fw_init)(struct proto *, char *); /* Init firewall instance */ + void (*fw_shutdown)(void *); /* Shutdown firewall instance */ + int (*fw_flush)(void *); /* Flush firewall table */ + int (*fw_add)(void *, net *, char *); /* Add record to table */ + int (*fw_del)(void *, net *); /* Remove record from table */ + int (*fw_replace)(void *, net *, char *); /* Replace record. Optional */ +}; + +struct firewall_control * firewalls[FWTYPE_MAX]; + +struct firewall_proto { + struct proto p; + int fwtype; /* Firewall type */ + struct firewall_control *fw; /* Pointer to configured protocol type */ + void *fwdata; /* Firewall instance private data */ +}; + +extern struct protocol proto_firewall; + +extern struct firewall_control fw_ipfw, fw_pf, fw_ipset; + +#endif |