2012-08-15 18:40:13 +02:00
|
|
|
From f610486180e7ba5a0f7b7127edfdcfaf704353a1 Mon Sep 17 00:00:00 2001
|
2012-01-26 16:17:58 +01:00
|
|
|
From: Alexander V. Chernikov <melifaro@ipfw.ru>
|
2012-08-15 18:40:13 +02:00
|
|
|
Date: Wed, 15 Aug 2012 16:09:21 +0000
|
|
|
|
Subject: [PATCH 1/1] Add firewall support v2
|
2012-01-26 16:17:58 +01:00
|
|
|
|
|
|
|
---
|
|
|
|
configure.in | 6 +-
|
|
|
|
doc/bird.sgml | 34 ++++
|
|
|
|
nest/proto.c | 3 +
|
|
|
|
nest/protocol.h | 2 +-
|
|
|
|
nest/route.h | 3 +-
|
|
|
|
proto/firewall/Doc | 1 +
|
|
|
|
proto/firewall/Makefile | 6 +
|
|
|
|
proto/firewall/config.Y | 77 +++++++++
|
|
|
|
proto/firewall/firewall.c | 198 ++++++++++++++++++++++
|
|
|
|
proto/firewall/firewall.h | 54 ++++++
|
|
|
|
sysdep/autoconf.h.in | 5 +
|
|
|
|
sysdep/bsd/Modules | 1 +
|
|
|
|
sysdep/bsd/fw.c | 404 +++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
13 files changed, 791 insertions(+), 3 deletions(-)
|
|
|
|
create mode 100644 proto/firewall/Doc
|
|
|
|
create mode 100644 proto/firewall/Makefile
|
|
|
|
create mode 100644 proto/firewall/config.Y
|
|
|
|
create mode 100644 proto/firewall/firewall.c
|
|
|
|
create mode 100644 proto/firewall/firewall.h
|
|
|
|
create mode 100644 sysdep/bsd/fw.c
|
|
|
|
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/configure.in b/configure.in
|
|
|
|
index 54993df..51b7cc2 100644
|
2012-01-26 16:17:58 +01:00
|
|
|
--- configure.in
|
|
|
|
+++ configure.in
|
2012-08-15 18:40:13 +02:00
|
|
|
@@ -137,10 +137,13 @@ else
|
2012-01-26 16:17:58 +01:00
|
|
|
ipv4:netbsd*) sysdesc=bsd
|
|
|
|
CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
|
|
|
|
LDFLAGS="$LDFLAGS -L/usr/pkg/lib -R/usr/pkg/lib"
|
|
|
|
+ AC_DEFINE(CONFIG_FIREWALL_PF, 1)
|
|
|
|
;;
|
|
|
|
ipv6:freebsd*) sysdesc=bsd-v6
|
|
|
|
;;
|
|
|
|
ipv4:freebsd*) sysdesc=bsd
|
|
|
|
+ AC_DEFINE(CONFIG_FIREWALL_IPFW, 1)
|
|
|
|
+ AC_DEFINE(CONFIG_FIREWALL_PF, 1)
|
|
|
|
;;
|
2012-08-15 18:40:13 +02:00
|
|
|
ipv6:dragonfly*) sysdesc=bsd-v6
|
2012-01-26 16:17:58 +01:00
|
|
|
;;
|
2012-08-15 18:40:13 +02:00
|
|
|
@@ -153,6 +156,7 @@ else
|
2012-01-26 16:17:58 +01:00
|
|
|
ipv6:openbsd*) sysdesc=bsd-v6
|
|
|
|
;;
|
|
|
|
ipv4:openbsd*) sysdesc=bsd
|
|
|
|
+ AC_DEFINE(CONFIG_FIREWALL_PF, 1)
|
|
|
|
;;
|
|
|
|
*) AC_MSG_ERROR([Cannot determine correct system configuration. Please use --with-sysconfig to set it manually.])
|
|
|
|
;;
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/doc/bird.sgml b/doc/bird.sgml
|
|
|
|
index 24bc302..a01ec99 100644
|
|
|
|
--- doc/bird.sgml
|
2012-01-26 16:17:58 +01:00
|
|
|
+++ doc/bird.sgml
|
2012-08-15 18:40:13 +02:00
|
|
|
@@ -2743,6 +2743,40 @@ protocol static {
|
2012-01-26 16:17:58 +01:00
|
|
|
}
|
|
|
|
</code>
|
|
|
|
|
|
|
|
+<sect>Firewall
|
|
|
|
+
|
|
|
|
+<p>Firewall protocol doesn't communicate with any network devices,
|
|
|
|
+but instead it allows you to add announced prefixes to given firewall table.
|
|
|
|
+At the moment IPFW and PF are supported. One can also specify special integer tag
|
|
|
|
+that can be passed as argument to IPFW table. Any number of instances can be configured.
|
|
|
|
+
|
|
|
|
+<p>Firewall protocol does not have many configuration options.
|
|
|
|
+
|
|
|
|
+<descrip>
|
|
|
|
+ <tag>fwtype pf|ipfw</tag> Select firewall type.
|
|
|
|
+ <tag>fwtable <m/name/</tag> Specifies firewall table name.
|
|
|
|
+ <tag>keep on startup|shutdown</tag>Do not flush table on protocol startup or shutdown.
|
|
|
|
+ <tag>keep always</tag>Do not flush table on protocol startup and shutdown.
|
|
|
|
+</descrip>
|
|
|
|
+
|
|
|
|
+<p>Firewall defines single route attribute:
|
|
|
|
+
|
|
|
|
+<descrip>
|
|
|
|
+ <tag>int <cf/fw_value/</tag> Value that can be passed with prefix.
|
|
|
|
+ Value is unsigned 4-byte integer. It can be set when importing routes from the other
|
|
|
|
+ protocols or on protocol export.
|
|
|
|
+</descrip>
|
|
|
|
+
|
|
|
|
+<p>Example firewall config might look like this:
|
|
|
|
+
|
|
|
|
+<p><code>
|
|
|
|
+protocol firewall {
|
|
|
|
+ table testable; # Connect to a non-default routing table
|
|
|
|
+ fwtype ipfw; # Use IPFW as backend
|
|
|
|
+ fwtable "2"; # Use table 2
|
|
|
|
+ export filter { fw_value = 125; accept; }; # Set value 125 for all prefixes
|
|
|
|
+}
|
|
|
|
+</code>
|
|
|
|
<chapt>Conclusions
|
|
|
|
|
|
|
|
<sect>Future work
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/nest/route.h b/nest/route.h
|
|
|
|
index 524e69b..f3062a2 100644
|
2012-01-26 16:17:58 +01:00
|
|
|
--- nest/route.h
|
|
|
|
+++ nest/route.h
|
2012-08-15 18:40:13 +02:00
|
|
|
@@ -361,7 +361,8 @@ typedef struct eattr {
|
2012-01-26 16:17:58 +01:00
|
|
|
#define EAP_OSPF 3 /* OSPF */
|
|
|
|
#define EAP_KRT 4 /* Kernel route attributes */
|
2016-08-14 08:25:17 +02:00
|
|
|
#define EAP_BABEL 5 /* Babel attributes */
|
|
|
|
-#define EAP_MAX 6
|
|
|
|
+#define EAP_FIREWALL 6 /* Abstact firewall interface */
|
|
|
|
+#define EAP_MAX 7
|
2012-01-26 16:17:58 +01:00
|
|
|
|
|
|
|
#define EA_CODE(proto,id) (((proto) << 8) | (id))
|
|
|
|
#define EA_PROTO(ea) ((ea) >> 8)
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/proto/firewall/Doc b/proto/firewall/Doc
|
2012-01-26 16:17:58 +01:00
|
|
|
new file mode 100644
|
|
|
|
index 0000000..5779342
|
|
|
|
--- /dev/null
|
|
|
|
+++ proto/firewall/Doc
|
|
|
|
@@ -0,0 +1 @@
|
|
|
|
+S firewall.c
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/proto/firewall/Makefile b/proto/firewall/Makefile
|
2012-01-26 16:17:58 +01:00
|
|
|
new file mode 100644
|
|
|
|
index 0000000..a322ab6
|
|
|
|
--- /dev/null
|
|
|
|
+++ proto/firewall/Makefile
|
|
|
|
@@ -0,0 +1,6 @@
|
|
|
|
+source=firewall.c
|
|
|
|
+root-rel=../../
|
|
|
|
+dir-name=proto/firewall
|
|
|
|
+
|
|
|
|
+include ../../Rules
|
|
|
|
+
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/proto/firewall/config.Y b/proto/firewall/config.Y
|
2012-01-26 16:17:58 +01:00
|
|
|
new file mode 100644
|
|
|
|
index 0000000..aefc606
|
|
|
|
--- /dev/null
|
|
|
|
+++ proto/firewall/config.Y
|
|
|
|
@@ -0,0 +1,77 @@
|
|
|
|
+/*
|
|
|
|
+ * BIRD -- Firewall Protocol Configuration
|
|
|
|
+ *
|
|
|
|
+ * (c) 2011 Alexander V. Chernikov <melifaro@FreeBSD.org>
|
|
|
|
+ *
|
|
|
|
+ * 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, KEEP, 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_CFG->flush_start = 1;
|
|
|
|
+ FIREWALL_CFG->flush_shutdown = 1;
|
|
|
|
+ }
|
|
|
|
+ ;
|
|
|
|
+
|
|
|
|
+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/build");
|
|
|
|
+ }
|
|
|
|
+ FIREWALL_CFG->fwtype = $2;
|
|
|
|
+ };
|
|
|
|
+ | FWTABLE TEXT { FIREWALL_CFG->fwtable = $2; }
|
|
|
|
+ | KEEP ON STARTUP { FIREWALL_CFG->flush_start = 0; }
|
|
|
|
+ | KEEP ON SHUTDOWN { FIREWALL_CFG->flush_shutdown = 0; }
|
|
|
|
+ | KEEP ALWAYS { FIREWALL_CFG->flush_start = 0; FIREWALL_CFG->flush_shutdown = 0; }
|
|
|
|
+ ;
|
|
|
|
+
|
|
|
|
+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
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/proto/firewall/firewall.c b/proto/firewall/firewall.c
|
2012-01-26 16:17:58 +01:00
|
|
|
new file mode 100644
|
|
|
|
index 0000000..e447470
|
|
|
|
--- /dev/null
|
|
|
|
+++ proto/firewall/firewall.c
|
|
|
|
@@ -0,0 +1,198 @@
|
|
|
|
+/*
|
|
|
|
+ * BIRD -- Firewall Protocol Configuration
|
|
|
|
+ *
|
|
|
|
+ * (c) 2011 Alexander V. Chernikov <melifaro@FreeBSD.org>
|
|
|
|
+ *
|
|
|
|
+ * 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;
|
|
|
|
+struct rate_limit rl_fw_err;
|
|
|
|
+
|
|
|
|
+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)
|
|
|
|
+ {
|
|
|
|
+ p->fw->fw_replace(p->fwdata, n, prefix_data);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (old)
|
|
|
|
+ p->fw->fw_del(p->fwdata, n);
|
|
|
|
+
|
|
|
|
+ if (new)
|
|
|
|
+ p->fw->fw_add(p->fwdata, n, 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_START;
|
|
|
|
+
|
|
|
|
+ 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_START;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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->fwtable);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+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",
|
|
|
|
+ attr_class: EAP_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,
|
|
|
|
+};
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/proto/firewall/firewall.h b/proto/firewall/firewall.h
|
2012-01-26 16:17:58 +01:00
|
|
|
new file mode 100644
|
|
|
|
index 0000000..c97ed38
|
|
|
|
--- /dev/null
|
|
|
|
+++ proto/firewall/firewall.h
|
|
|
|
@@ -0,0 +1,54 @@
|
|
|
|
+/*
|
|
|
|
+ * BIRD -- Firewall Protocol Configuration
|
|
|
|
+ *
|
|
|
|
+ * (c) 2011 Alexander V. Chernikov <melifaro@FreeBSD.org>
|
|
|
|
+ *
|
|
|
|
+ * 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;
|
|
|
|
+extern struct rate_limit rl_fw_err;
|
|
|
|
+#define FW_ERR(x, y...) log_rl(&rl_fw_err, L_ERR x, ##y)
|
|
|
|
+
|
|
|
|
+#endif
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/sysdep/bsd/Modules b/sysdep/bsd/Modules
|
|
|
|
index 3729587..0607321 100644
|
2012-01-26 16:17:58 +01:00
|
|
|
--- sysdep/bsd/Modules
|
|
|
|
+++ sysdep/bsd/Modules
|
2012-08-15 18:40:13 +02:00
|
|
|
@@ -1,3 +1,4 @@
|
2012-01-26 16:17:58 +01:00
|
|
|
krt-sock.c
|
2012-08-15 18:40:13 +02:00
|
|
|
krt-sys.h
|
|
|
|
sysio.h
|
2012-01-26 16:17:58 +01:00
|
|
|
+fw.c
|
2012-08-15 18:40:13 +02:00
|
|
|
diff --git a/sysdep/bsd/fw.c b/sysdep/bsd/fw.c
|
2012-01-26 16:17:58 +01:00
|
|
|
new file mode 100644
|
|
|
|
index 0000000..e841e06
|
|
|
|
--- /dev/null
|
|
|
|
+++ sysdep/bsd/fw.c
|
|
|
|
@@ -0,0 +1,404 @@
|
|
|
|
+/*
|
|
|
|
+ * BIRD -- IPFW/PF manipulations
|
|
|
|
+ *
|
|
|
|
+ * (c) 2011 Alexander V. Chernikov <melifaro@FreeBSD.org>
|
|
|
|
+ *
|
|
|
|
+ * Can be freely distributed and used under the terms of the GNU GPL.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include <stdio.h>
|
|
|
|
+#include <stdlib.h>
|
|
|
|
+#include <limits.h>
|
|
|
|
+#include <ctype.h>
|
|
|
|
+#include <fcntl.h>
|
|
|
|
+#include <unistd.h>
|
|
|
|
+#include <sys/param.h>
|
|
|
|
+#include <sys/types.h>
|
|
|
|
+#include <sys/socket.h>
|
|
|
|
+#include <sys/sysctl.h>
|
|
|
|
+#include <sys/ioctl.h>
|
|
|
|
+#include <netinet/in.h>
|
|
|
|
+#include <errno.h>
|
|
|
|
+#include <err.h>
|
|
|
|
+#include <net/route.h>
|
|
|
|
+#include <net/if.h>
|
|
|
|
+#include <net/if_dl.h>
|
|
|
|
+
|
|
|
|
+#undef LOCAL_DEBUG
|
|
|
|
+
|
|
|
|
+#include "nest/bird.h"
|
|
|
|
+#include "nest/iface.h"
|
|
|
|
+#include "nest/route.h"
|
|
|
|
+#include "nest/protocol.h"
|
|
|
|
+#include "nest/iface.h"
|
|
|
|
+#include "lib/timer.h"
|
|
|
|
+#include "lib/unix.h"
|
|
|
|
+#include "lib/krt.h"
|
|
|
|
+#include "lib/string.h"
|
|
|
|
+#include "lib/socket.h"
|
|
|
|
+#ifdef CONFIG_FIREWALL
|
|
|
|
+#include "proto/firewall/firewall.h"
|
|
|
|
+#ifdef CONFIG_FIREWALL_IPFW
|
|
|
|
+#include "netinet/ip_fw.h"
|
|
|
|
+#endif
|
|
|
|
+#ifdef CONFIG_FIREWALL_PF
|
|
|
|
+#include "net/pfvar.h"
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_FIREWALL_IPFW
|
|
|
|
+
|
|
|
|
+int ipfw_fd = -1;
|
|
|
|
+int ipfw_instance_count = 0;
|
|
|
|
+
|
|
|
|
+struct ipfw_priv {
|
|
|
|
+ int table; /* Table number */
|
|
|
|
+ pool *pool; /* Protocol pool */
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+ipfw_do_cmd(int optname, void *optval, uintptr_t optlen)
|
|
|
|
+{
|
|
|
|
+ return setsockopt(ipfw_fd, IPPROTO_IP, optname, optval, optlen);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void *
|
|
|
|
+ipfw_fw_init(struct proto *p, char *table)
|
|
|
|
+{
|
|
|
|
+ pool *fwpool = p->pool;
|
|
|
|
+ int table_num = strtol(table, NULL, 10);
|
|
|
|
+ int tables_max;
|
|
|
|
+ size_t len = sizeof(tables_max);
|
|
|
|
+
|
|
|
|
+ if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len, NULL, 0) == -1)
|
|
|
|
+ {
|
|
|
|
+ log(L_ERR "Error getting maximum ipfw table count");
|
|
|
|
+ tables_max = IPFW_TABLES_MAX;
|
|
|
|
+ }
|
|
|
|
+ DBG("ipfw maximum table count set to %d\n", tables_max);
|
|
|
|
+
|
|
|
|
+ if ((table_num < 0) || (table_num >= tables_max))
|
|
|
|
+ {
|
|
|
|
+ log(L_ERR "ipfw table %d is not within possible range (0..%d)", table_num, tables_max);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (ipfw_fd == -1)
|
|
|
|
+ {
|
|
|
|
+ if ((ipfw_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
|
|
|
|
+ {
|
|
|
|
+ log(L_ERR "ipfw: error opering raw socket: %m");
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ DBG("Opened IPFW socked %d\n", ipfw_fd);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ struct ipfw_priv *priv = mb_alloc(fwpool, sizeof(struct ipfw_priv));
|
|
|
|
+
|
|
|
|
+ priv->table = table_num;
|
|
|
|
+ priv->pool = fwpool;
|
|
|
|
+
|
|
|
|
+ ipfw_instance_count++;
|
|
|
|
+
|
|
|
|
+ return priv;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+ipfw_fw_shutdown(void *_priv UNUSED)
|
|
|
|
+{
|
|
|
|
+ if (--ipfw_instance_count == 0)
|
|
|
|
+ {
|
|
|
|
+ DBG("Closing ipfw socket %d\n", ipfw_fd);
|
|
|
|
+ close(ipfw_fd);
|
|
|
|
+ ipfw_fd = -1;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+ipfw_fw_flush(void *_priv)
|
|
|
|
+{
|
|
|
|
+ struct ipfw_priv *priv = _priv;
|
|
|
|
+ ipfw_table_entry ent;
|
|
|
|
+
|
|
|
|
+ memset(&ent, 0, sizeof(ent));
|
|
|
|
+ ent.tbl = priv->table;
|
|
|
|
+
|
|
|
|
+ log(L_DEBUG "Flushing ipfw table %d", priv->table);
|
|
|
|
+
|
|
|
|
+ if (ipfw_do_cmd(IP_FW_TABLE_FLUSH, &ent.tbl, sizeof(ent.tbl)) == -1)
|
|
|
|
+ {
|
|
|
|
+ log(L_ERR "Error flushing ipfw table %d: %m", priv->table);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+ipfw_fw_add(void *_priv, net *n, char *prefixdata)
|
|
|
|
+{
|
|
|
|
+ struct ipfw_priv *priv = _priv;
|
|
|
|
+ ip_addr addr;
|
|
|
|
+ ipfw_table_entry ent;
|
|
|
|
+
|
|
|
|
+ addr = n->n.prefix;
|
|
|
|
+ ipa_hton(addr);
|
|
|
|
+
|
|
|
|
+ ent.masklen = n->n.pxlen;
|
|
|
|
+ memcpy(&ent.addr, &addr, sizeof(ip_addr));
|
|
|
|
+ ent.value = strtol(prefixdata, NULL, 0);
|
|
|
|
+ ent.tbl = priv->table;
|
|
|
|
+
|
|
|
|
+ DBG("Adding %I/%d to ipfw table %d with value %s\n", n->n.prefix, n->n.pxlen, priv->table, prefixdata);
|
|
|
|
+
|
|
|
|
+ if (ipfw_do_cmd(IP_FW_TABLE_ADD, &ent, sizeof(ent)) == -1)
|
|
|
|
+ {
|
|
|
|
+ FW_ERR("Error adding %I/%d to ipfw table %d: %m", n->n.prefix, n->n.pxlen, priv->table);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+ipfw_fw_del(void *_priv, net *n)
|
|
|
|
+{
|
|
|
|
+ struct ipfw_priv *priv = _priv;
|
|
|
|
+ ip_addr addr;
|
|
|
|
+ ipfw_table_entry ent;
|
|
|
|
+
|
|
|
|
+ addr = n->n.prefix;
|
|
|
|
+ ipa_hton(addr);
|
|
|
|
+
|
|
|
|
+ ent.masklen = n->n.pxlen;
|
|
|
|
+ memcpy(&ent.addr, &addr, sizeof(ip_addr));
|
|
|
|
+ ent.value = 0;
|
|
|
|
+ ent.tbl = priv->table;
|
|
|
|
+
|
|
|
|
+ DBG("Removing %I/%d from ipfw table %d\n", n->n.prefix, n->n.pxlen, priv->table);
|
|
|
|
+
|
|
|
|
+ if (ipfw_do_cmd(IP_FW_TABLE_DEL, &ent, sizeof(ent)) == -1)
|
|
|
|
+ {
|
|
|
|
+ FW_ERR("Error removing %I/%d from ipfw table %d: %m", n->n.prefix, n->n.pxlen, priv->table);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct firewall_control fw_ipfw = {
|
|
|
|
+ fwtype: FWTYPE_IPFW,
|
|
|
|
+ description: "IPFW",
|
|
|
|
+ fw_init: ipfw_fw_init,
|
|
|
|
+ fw_shutdown: ipfw_fw_shutdown,
|
|
|
|
+ fw_flush: ipfw_fw_flush,
|
|
|
|
+ fw_add: ipfw_fw_add,
|
|
|
|
+ fw_del: ipfw_fw_del,
|
|
|
|
+};
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_FIREWALL_PF
|
|
|
|
+
|
|
|
|
+#define PF_DEVNAME "/dev/pf"
|
|
|
|
+int pf_fd = -1;
|
|
|
|
+int pf_instance_count = 0;
|
|
|
|
+
|
|
|
|
+struct pf_priv {
|
|
|
|
+ struct pfr_table table; /* PF table structure */
|
|
|
|
+ pool *pool; /* Protocol pool */
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define pf_tablename table.pfrt_name
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+pf_do_cmd(struct pfr_table *tbl, unsigned long cmd, void *buffer, int esize, int items, int *nadd, int *ndel, int flags)
|
|
|
|
+{
|
|
|
|
+ struct pfioc_table io;
|
|
|
|
+
|
|
|
|
+ bzero(&io, sizeof(io));
|
|
|
|
+ io.pfrio_flags = flags;
|
|
|
|
+ if (tbl)
|
|
|
|
+ io.pfrio_table = *tbl;
|
|
|
|
+ io.pfrio_buffer = buffer;
|
|
|
|
+ io.pfrio_esize = esize;
|
|
|
|
+ io.pfrio_size = items;
|
|
|
|
+
|
|
|
|
+ /* DBG("Doing PF ioctl %X for table %s on fd %d\n", cmd, tbl ? tbl->pfrt_name : "NULL", pf_fd); */
|
|
|
|
+ if (ioctl(pf_fd, cmd, &io))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if (nadd)
|
|
|
|
+ *nadd = io.pfrio_nadd;
|
|
|
|
+ if (ndel)
|
|
|
|
+ *ndel = io.pfrio_ndel;
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void *
|
|
|
|
+pf_fw_init(struct proto *p, char *table)
|
|
|
|
+{
|
|
|
|
+ pool *fwpool = p->pool;
|
|
|
|
+ struct pfr_table pf_table;
|
|
|
|
+ int nadd = 0;
|
|
|
|
+
|
|
|
|
+ if (strlen(table) > PF_TABLE_NAME_SIZE)
|
|
|
|
+ {
|
|
|
|
+ log(L_ERR "PF table name too long, max %d", PF_TABLE_NAME_SIZE);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ memset(&pf_table, 0, sizeof(pf_table));
|
|
|
|
+
|
|
|
|
+ if (pf_fd == -1)
|
|
|
|
+ {
|
|
|
|
+ if ((pf_fd = open(PF_DEVNAME, O_RDWR)) == -1)
|
|
|
|
+ {
|
|
|
|
+ log(L_ERR "pf: error opening %s: %m", PF_DEVNAME);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DBG("Opened PF socked %d\n", pf_fd);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ strcpy(pf_table.pfrt_name, table);
|
|
|
|
+ pf_table.pfrt_flags |= PFR_TFLAG_PERSIST;
|
|
|
|
+ if (!pf_do_cmd(NULL, DIOCRADDTABLES, &pf_table, sizeof(pf_table), 1, &nadd, NULL, 0))
|
|
|
|
+ {
|
|
|
|
+ log(L_ERR "Error creating PF table %s: %m", table);
|
|
|
|
+ if (pf_instance_count == 0)
|
|
|
|
+ {
|
|
|
|
+ log(L_ERR "Closing PF socket");
|
|
|
|
+ close(pf_fd);
|
|
|
|
+ pf_fd = -1;
|
|
|
|
+ }
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ DBG("PF table %s created\n", table);
|
|
|
|
+ /* Remove persistent flag */
|
|
|
|
+ pf_table.pfrt_flags = 0;
|
|
|
|
+
|
|
|
|
+ struct pf_priv *priv = mb_alloc(fwpool, sizeof(struct pf_priv));
|
|
|
|
+
|
|
|
|
+ priv->table = pf_table;
|
|
|
|
+ priv->pool = fwpool;
|
|
|
|
+
|
|
|
|
+ pf_instance_count++;
|
|
|
|
+
|
|
|
|
+ return priv;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+pf_fw_shutdown(void *_priv UNUSED)
|
|
|
|
+{
|
|
|
|
+ if (--pf_instance_count == 0)
|
|
|
|
+ {
|
|
|
|
+ DBG("Closing PF socket %d\n", pf_fd);
|
|
|
|
+ close(pf_fd);
|
|
|
|
+ pf_fd = -1;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+pf_fw_flush(void *_priv)
|
|
|
|
+{
|
|
|
|
+ struct pf_priv *priv = _priv;
|
|
|
|
+ int ndel;
|
|
|
|
+
|
|
|
|
+ log(L_DEBUG "Flushing PF table %s", priv->pf_tablename);
|
|
|
|
+
|
|
|
|
+ if (!pf_do_cmd(&priv->table, DIOCRCLRADDRS, NULL, 0, 0, NULL, &ndel, 0))
|
|
|
|
+ {
|
|
|
|
+ log(L_ERR "Error flushing PF table %s: %m", priv->pf_tablename);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DBG("Flushed %d record(s) from PF table %s\n", ndel, priv->pf_tablename);
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+pf_put_addr(struct pfr_addr *pf_addr, net *n)
|
|
|
|
+{
|
|
|
|
+ int rt_family = AF_INET;
|
|
|
|
+ ip_addr addr;
|
|
|
|
+
|
|
|
|
+ memset(pf_addr, 0, sizeof(struct pfr_addr));
|
|
|
|
+ pf_addr->pfra_not = 0;
|
|
|
|
+ pf_addr->pfra_net = n->n.pxlen;
|
|
|
|
+ switch (rt_family)
|
|
|
|
+ {
|
|
|
|
+ case AF_INET:
|
|
|
|
+ addr = n->n.prefix;
|
|
|
|
+ ipa_hton(addr);
|
|
|
|
+ pf_addr->pfra_ip4addr.s_addr = addr;
|
|
|
|
+ pf_addr->pfra_af = rt_family;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ log(L_ERR "Address family %d is not supported by pf, ignoring prefix", rt_family);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+pf_fw_add(void *_priv, net *n, char *prefixdata)
|
|
|
|
+{
|
|
|
|
+ struct pf_priv *priv = _priv;
|
|
|
|
+ struct pfr_addr pf_addr;
|
|
|
|
+ int nadd = 0;
|
|
|
|
+
|
|
|
|
+ if (!pf_put_addr(&pf_addr, n))
|
|
|
|
+ {
|
|
|
|
+ FW_ERR("Error adding %I/%d to PF table %s", n->n.prefix, n->n.pxlen, priv->pf_tablename);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DBG("Adding %I/%d to PF table %s with value %s\n", n->n.prefix, n->n.pxlen, priv->pf_tablename, prefixdata);
|
|
|
|
+ if (!pf_do_cmd(&priv->table, DIOCRADDADDRS, &pf_addr, sizeof(pf_addr), 1, &nadd, NULL, 0))
|
|
|
|
+ {
|
|
|
|
+ FW_ERR("Error adding %I/%d to PF table %s: %m", n->n.prefix, n->n.pxlen, priv->pf_tablename);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+pf_fw_del(void *_priv, net *n)
|
|
|
|
+{
|
|
|
|
+ struct pf_priv *priv = _priv;
|
|
|
|
+ struct pfr_addr pf_addr;
|
|
|
|
+ int ndel = 0;
|
|
|
|
+
|
|
|
|
+ if (!pf_put_addr(&pf_addr, n))
|
|
|
|
+ {
|
|
|
|
+ FW_ERR("Error deleting %I/%d from PF table %s", n->n.prefix, n->n.pxlen, priv->pf_tablename);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DBG("Deleting %I/%d from PF table %s\n", n->n.prefix, n->n.pxlen, priv->pf_tablename);
|
|
|
|
+ if (!pf_do_cmd(&priv->table, DIOCRDELADDRS, &pf_addr, sizeof(pf_addr), 1, NULL, &ndel, 0))
|
|
|
|
+ {
|
|
|
|
+ FW_ERR("Error deleting %I/%d from PF table %s: %m", n->n.prefix, n->n.pxlen, priv->pf_tablename);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct firewall_control fw_pf = {
|
|
|
|
+ fwtype: FWTYPE_PF,
|
|
|
|
+ description: "PF",
|
|
|
|
+ fw_init: pf_fw_init,
|
|
|
|
+ fw_shutdown: pf_fw_shutdown,
|
|
|
|
+ fw_flush: pf_fw_flush,
|
|
|
|
+ fw_add: pf_fw_add,
|
|
|
|
+ fw_del: pf_fw_del,
|
|
|
|
+};
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
--
|
|
|
|
1.7.3.2
|
|
|
|
|
2012-08-15 18:40:13 +02:00
|
|
|
--- configure.orig 2012-08-07 13:28:04.000000000 +0400
|
|
|
|
+++ configure 2012-08-15 15:54:05.000000000 +0400
|
2013-03-03 00:54:10 +01:00
|
|
|
@@ -4361,6 +4361,8 @@
|
|
|
|
ipv6:freebsd*) sysdesc=bsd-v6
|
|
|
|
;;
|
|
|
|
ipv4:freebsd*) sysdesc=bsd
|
|
|
|
+ $as_echo "#define CONFIG_FIREWALL_IPFW 1" >>confdefs.h
|
|
|
|
+ $as_echo "#define CONFIG_FIREWALL_PF 1" >>confdefs.h
|
|
|
|
;;
|
|
|
|
ipv6:dragonfly*) sysdesc=bsd-v6
|
|
|
|
;;
|
2013-11-30 22:25:21 +01:00
|
|
|
|