summaryrefslogtreecommitdiff
path: root/proto/firewall
diff options
context:
space:
mode:
Diffstat (limited to 'proto/firewall')
-rw-r--r--proto/firewall/Doc1
-rw-r--r--proto/firewall/Makefile6
-rw-r--r--proto/firewall/config.Y75
-rw-r--r--proto/firewall/firewall.c201
-rw-r--r--proto/firewall/firewall.h52
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