- Update to 1.3.6

- Add all current git patches
- for net/bird add beta firewall protocol support

Submitted by:	mainteiner
This commit is contained in:
Sergey Matveychuk 2012-01-26 15:17:58 +00:00
parent de13cf5bad
commit e17400e190
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=289852
7 changed files with 1501 additions and 1093 deletions

View File

@ -6,8 +6,7 @@
#
PORTNAME= bird
PORTVERSION= 1.3.4
PORTREVESION= 1
PORTVERSION= 1.3.6
CATEGORIES= net
MASTER_SITES= ftp://bird.network.cz/pub/bird/
@ -18,7 +17,8 @@ USE_BISON= build
USE_GMAKE= yes
GNU_CONFIGURE= yes
OPTIONS= FIBS "Enable multiple fib support" Off
OPTIONS= FIBS "Enable multiple fib support" Off \
FIREWALL "Enable firewall protocol" Off
MAKE_JOBS_UNSAFE= yes
@ -30,6 +30,10 @@ USE_RC_SUBR= bird
EXTRA_PATCHES+= ${FILESDIR}/fibs.diff
.endif
.if defined(WITH_FIREWALL)
EXTRA_PATCHES+= ${FILESDIR}/firewall_support.patch
.endif
post-install:
@if [ ! -f ${PREFIX}/etc/bird.conf ]; then \
${CP} -p ${PREFIX}/etc/bird.conf.example ${PREFIX}/etc/bird.conf ; \

View File

@ -1,2 +1,2 @@
SHA256 (bird-1.3.4.tar.gz) = 0b97c7486515b3ec81b34935859c0b66d92e2cc3f1f001e640d5d38e10c61dc6
SIZE (bird-1.3.4.tar.gz) = 759228
SHA256 (bird-1.3.6.tar.gz) = 5d060256c179bceff861b7533831adc690eb64d27d14fb1ddfba407eb83d870a
SIZE (bird-1.3.6.tar.gz) = 864775

View File

@ -0,0 +1,982 @@
From c99266ef16e66f94f22a2f78dcea82c795c4611f Mon Sep 17 00:00:00 2001
From: Alexander V. Chernikov <melifaro@ipfw.ru>
Date: Fri, 23 Dec 2011 13:47:59 +0000
Subject: [PATCH 1/1] * Add firewall support, v2
---
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
diff --git configure.in configure.in
index 46a6ecd..bb5f445 100644
--- configure.in
+++ configure.in
@@ -47,7 +47,7 @@ if test "$enable_ipv6" = yes ; then
else
ip=ipv4
SUFFIX6=""
- all_protocols=bgp,ospf,pipe,rip,static
+ all_protocols=bgp,ospf,pipe,rip,static,firewall
fi
if test "$with_protocols" = all ; then
@@ -126,10 +126,13 @@ else
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)
;;
ipv6:kfreebsd*) sysdesc=bsd-v6
;;
@@ -138,6 +141,7 @@ else
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.])
;;
--- configure.orig 2012-01-20 21:04:39.000000000 +0400
+++ configure 2012-01-26 17:37:43.000000000 +0400
@@ -2336,7 +2336,7 @@
else
ip=ipv4
SUFFIX6=""
- all_protocols=bgp,ospf,pipe,rip,static
+ all_protocols=bgp,ospf,pipe,rip,static,firewall
fi
if test "$with_protocols" = all ; then
@@ -4372,10 +4372,13 @@
ipv4:netbsd*) sysdesc=bsd
CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
LDFLAGS="$LDFLAGS -L/usr/pkg/lib -R/usr/pkg/lib"
+ $as_echo "#define CONFIG_FIREWALL_PF 1" >>confdefs.h
;;
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:kfreebsd*) sysdesc=bsd-v6
;;
@@ -4384,6 +4387,7 @@
ipv6:openbsd*) sysdesc=bsd-v6
;;
ipv4:openbsd*) sysdesc=bsd
+ $as_echo "#define CONFIG_FIREWALL_PF 1" >>confdefs.h
;;
*) as_fn_error $? "Cannot determine correct system configuration. Please use --with-sysconfig to set it manually." "$LINENO" 5
;;--- doc/bird.sgml
+++ doc/bird.sgml
@@ -2490,6 +2490,40 @@ protocol static {
}
</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
diff --git nest/proto.c nest/proto.c
index d55c348..85bdb19 100644
--- nest/proto.c
+++ nest/proto.c
@@ -632,6 +632,9 @@ protos_build(void)
#ifdef CONFIG_BGP
proto_build(&proto_bgp);
#endif
+#ifdef CONFIG_FIREWALL
+ proto_build(&proto_firewall);
+#endif
proto_pool = rp_new(&root_pool, "Protocols");
proto_flush_event = ev_new(proto_pool);
proto_flush_event->hook = proto_flush_all;
diff --git nest/protocol.h nest/protocol.h
index a7518c2..d09a556 100644
--- nest/protocol.h
+++ nest/protocol.h
@@ -73,7 +73,7 @@ void protos_dump_all(void);
extern struct protocol
proto_device, proto_radv, proto_rip, proto_static,
- proto_ospf, proto_pipe, proto_bgp;
+ proto_ospf, proto_pipe, proto_bgp, proto_firewall;
/*
* Routing Protocol Instance
diff --git nest/route.h nest/route.h
index a4c0154..e5f18dd 100644
--- nest/route.h
+++ nest/route.h
@@ -349,7 +349,8 @@ typedef struct eattr {
#define EAP_RIP 2 /* RIP */
#define EAP_OSPF 3 /* OSPF */
#define EAP_KRT 4 /* Kernel route attributes */
-#define EAP_MAX 5
+#define EAP_FIREWALL 5 /* Abstact firewall interface */
+#define EAP_MAX 6
#define EA_CODE(proto,id) (((proto) << 8) | (id))
#define EA_PROTO(ea) ((ea) >> 8)
diff --git proto/firewall/Doc proto/firewall/Doc
new file mode 100644
index 0000000..5779342
--- /dev/null
+++ proto/firewall/Doc
@@ -0,0 +1 @@
+S firewall.c
diff --git proto/firewall/Makefile proto/firewall/Makefile
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
+
diff --git proto/firewall/config.Y proto/firewall/config.Y
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
diff --git proto/firewall/firewall.c proto/firewall/firewall.c
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,
+};
diff --git proto/firewall/firewall.h proto/firewall/firewall.h
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
diff --git sysdep/autoconf.h.in sysdep/autoconf.h.in
index d029e2a..c1fcdf7 100644
--- sysdep/autoconf.h.in
+++ sysdep/autoconf.h.in
@@ -42,6 +42,11 @@
#undef CONFIG_BGP
#undef CONFIG_OSPF
#undef CONFIG_PIPE
+#undef CONFIG_FIREWALL
+
+#undef CONFIG_FIREWALL_IPFW
+#undef CONFIG_FIREWALL_PF
+#undef CONFIG_FIREWALL_IPSET
/* We have <syslog.h> and syslog() */
#undef HAVE_SYSLOG
diff --git sysdep/bsd/Modules sysdep/bsd/Modules
index 84abffd..77f26e3 100644
--- sysdep/bsd/Modules
+++ sysdep/bsd/Modules
@@ -4,3 +4,4 @@ sysio.h
krt-set.h
krt-sock.c
krt-sock.h
+fw.c
diff --git sysdep/bsd/fw.c sysdep/bsd/fw.c
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

View File

@ -0,0 +1,507 @@
diff --git nest/config.Y nest/config.Y
index a6baf4e..3fcfa52 100644
--- nest/config.Y
+++ nest/config.Y
@@ -219,7 +219,6 @@ CF_ADDTO(proto, dev_proto '}')
dev_proto_start: proto_start DIRECT {
this_proto = proto_config_new(&proto_device, sizeof(struct rt_dev_config), $1);
- this_proto->preference = DEF_PREF_DIRECT;
init_list(&DIRECT_CFG->iface_list);
}
;
diff --git nest/iface.c nest/iface.c
index b8b214e..eea3d3b 100644
--- nest/iface.c
+++ nest/iface.c
@@ -253,6 +253,24 @@ if_change_flags(struct iface *i, unsigned flags)
}
/**
+ * if_delete - remove interface
+ * @old: interface
+ *
+ * This function is called by the low-level platform dependent code
+ * whenever it notices an interface disappears. It is just a shorthand
+ * for if_update().
+ */
+
+void
+if_delete(struct iface *old)
+{
+ struct iface f = {};
+ strncpy(f.name, old->name, sizeof(f.name)-1);
+ f.flags = IF_SHUTDOWN;
+ if_update(&f);
+}
+
+/**
* if_update - update interface status
* @new: new interface status
*
@@ -288,13 +306,14 @@ if_update(struct iface *new)
new->addr = i->addr;
memcpy(&new->addrs, &i->addrs, sizeof(i->addrs));
memcpy(i, new, sizeof(*i));
+ i->flags &= ~IF_UP; /* IF_TMP_DOWN will be added later */
goto newif;
}
- else if (c)
- {
- if_copy(i, new);
- if_notify_change(c, i);
- }
+
+ if_copy(i, new);
+ if (c)
+ if_notify_change(c, i);
+
i->flags |= IF_UPDATED;
return i;
}
@@ -400,7 +419,7 @@ if_find_by_index(unsigned idx)
struct iface *i;
WALK_LIST(i, iface_list)
- if (i->index == idx)
+ if (i->index == idx && !(i->flags & IF_SHUTDOWN))
return i;
return NULL;
}
diff --git nest/iface.h nest/iface.h
index d6d58ff..2416f82 100644
--- nest/iface.h
+++ nest/iface.h
@@ -88,6 +88,7 @@ void ifa_dump(struct ifa *);
void if_show(void);
void if_show_summary(void);
struct iface *if_update(struct iface *);
+void if_delete(struct iface *old);
struct ifa *ifa_update(struct ifa *);
void ifa_delete(struct ifa *);
void if_start_update(void);
diff --git nest/proto.c nest/proto.c
index d55c348..0fc72ce 100644
--- nest/proto.c
+++ nest/proto.c
@@ -200,6 +200,7 @@ proto_config_new(struct protocol *pr, unsigned size, int class)
c->global = new_config;
c->protocol = pr;
c->name = pr->name;
+ c->preference = pr->preference;
c->class = class;
c->out_filter = FILTER_REJECT;
c->table = c->global->master_rtc;
diff --git nest/protocol.h nest/protocol.h
index 3766e15..a83c4ff 100644
--- nest/protocol.h
+++ nest/protocol.h
@@ -39,6 +39,7 @@ struct protocol {
char *template; /* Template for automatic generation of names */
int name_counter; /* Counter for automatic name generation */
int attr_class; /* Attribute class known to this protocol */
+ unsigned preference; /* Default protocol preference */
void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */
void (*postconfig)(struct proto_config *); /* After configuring each instance */
diff --git nest/rt-dev.c nest/rt-dev.c
index 497ee80..54cb14b 100644
--- nest/rt-dev.c
+++ nest/rt-dev.c
@@ -109,6 +109,7 @@ dev_copy_config(struct proto_config *dest, struct proto_config *src)
struct protocol proto_device = {
name: "Direct",
template: "direct%d",
+ preference: DEF_PREF_DIRECT,
init: dev_init,
reconfigure: dev_reconfigure,
copy_config: dev_copy_config
diff --git proto/bgp/bgp.c proto/bgp/bgp.c
index 66fdc60..4d3c32f 100644
--- proto/bgp/bgp.c
+++ proto/bgp/bgp.c
@@ -1178,6 +1178,7 @@ struct protocol proto_bgp = {
name: "BGP",
template: "bgp%d",
attr_class: EAP_BGP,
+ preference: DEF_PREF_BGP,
init: bgp_init,
start: bgp_start,
shutdown: bgp_shutdown,
diff --git proto/bgp/config.Y proto/bgp/config.Y
index 5fb6094..78ca52d 100644
--- proto/bgp/config.Y
+++ proto/bgp/config.Y
@@ -33,7 +33,6 @@ CF_ADDTO(proto, bgp_proto '}' { bgp_check_config(BGP_CFG); } )
bgp_proto_start: proto_start BGP {
this_proto = proto_config_new(&proto_bgp, sizeof(struct bgp_config), $1);
- this_proto->preference = DEF_PREF_BGP;
BGP_CFG->hold_time = 240;
BGP_CFG->connect_retry_time = 120;
BGP_CFG->initial_hold_time = 240;
diff --git proto/ospf/config.Y proto/ospf/config.Y
index 4ada41e..24e125a 100644
--- proto/ospf/config.Y
+++ proto/ospf/config.Y
@@ -129,7 +129,6 @@ CF_ADDTO(proto, ospf_proto '}' { ospf_proto_finish(); } )
ospf_proto_start: proto_start OSPF {
this_proto = proto_config_new(&proto_ospf, sizeof(struct ospf_config), $1);
- this_proto->preference = DEF_PREF_OSPF;
init_list(&OSPF_CFG->area_list);
init_list(&OSPF_CFG->vlink_list);
OSPF_CFG->rfc1583 = DEFAULT_RFC1583;
diff --git proto/ospf/ospf.c proto/ospf/ospf.c
index ce7ad37..73c06c2 100644
--- proto/ospf/ospf.c
+++ proto/ospf/ospf.c
@@ -1542,6 +1542,7 @@ struct protocol proto_ospf = {
name: "OSPF",
template: "ospf%d",
attr_class: EAP_OSPF,
+ preference: DEF_PREF_OSPF,
init: ospf_init,
dump: ospf_dump,
start: ospf_start,
diff --git proto/ospf/ospf.h proto/ospf/ospf.h
index 60a34fb..d696151 100644
--- proto/ospf/ospf.h
+++ proto/ospf/ospf.h
@@ -177,7 +177,7 @@ struct ospf_area_config
struct ospf_iface
{
node n;
- struct iface *iface; /* Nest's iface */
+ struct iface *iface; /* Nest's iface, non-NULL (unless type OSPF_IT_VLINK) */
struct ifa *addr; /* IP prefix associated with that OSPF iface */
struct ospf_area *oa;
struct ospf_iface_patt *cf;
diff --git proto/ospf/packet.c proto/ospf/packet.c
index df67d5a..7a26967 100644
--- proto/ospf/packet.c
+++ proto/ospf/packet.c
@@ -489,17 +489,17 @@ ospf_rx_hook(sock *sk, int size)
void
ospf_tx_hook(sock * sk)
{
-// struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
+ struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
// struct proto *p = (struct proto *) (ifa->oa->po);
- log(L_ERR "OSPF: TX_Hook called");
+ log(L_ERR "OSPF: TX hook called on %s", ifa->iface->name);
}
void
ospf_err_hook(sock * sk, int err)
{
-// struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
+ struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
// struct proto *p = (struct proto *) (ifa->oa->po);
- log(L_ERR "OSPF: Socket error: %M", err);
+ log(L_ERR "OSPF: Socket error on %s: %M", ifa->iface->name, err);
}
void
diff --git proto/pipe/config.Y proto/pipe/config.Y
index 4478afe..4063755 100644
--- proto/pipe/config.Y
+++ proto/pipe/config.Y
@@ -24,7 +24,6 @@ CF_ADDTO(proto, pipe_proto '}')
pipe_proto_start: proto_start PIPE {
this_proto = proto_config_new(&proto_pipe, sizeof(struct pipe_config), $1);
- this_proto->preference = DEF_PREF_PIPE;
PIPE_CFG->mode = PIPE_TRANSPARENT;
}
;
diff --git proto/pipe/pipe.c proto/pipe/pipe.c
index 420c5a9..fe8618b 100644
--- proto/pipe/pipe.c
+++ proto/pipe/pipe.c
@@ -197,6 +197,7 @@ pipe_get_status(struct proto *P, byte *buf)
struct protocol proto_pipe = {
name: "Pipe",
template: "pipe%d",
+ preference: DEF_PREF_PIPE,
postconfig: pipe_postconfig,
init: pipe_init,
start: pipe_start,
diff --git proto/rip/rip.c proto/rip/rip.c
index 543aa30..f0a4134 100644
--- proto/rip/rip.c
+++ proto/rip/rip.c
@@ -975,7 +975,6 @@ void
rip_init_config(struct rip_proto_config *c)
{
init_list(&c->iface_list);
- c->c.preference = DEF_PREF_RIP;
c->infinity = 16;
c->port = 520;
c->period = 30;
@@ -1032,6 +1031,7 @@ struct protocol proto_rip = {
name: "RIP",
template: "rip%d",
attr_class: EAP_RIP,
+ preference: DEF_PREF_RIP,
get_route_info: rip_get_route_info,
get_attr: rip_get_attr,
diff --git proto/static/static.c proto/static/static.c
index f6c2a33..aaa9bfa 100644
--- proto/static/static.c
+++ proto/static/static.c
@@ -353,7 +353,6 @@ static_if_notify(struct proto *p, unsigned flags, struct iface *i)
void
static_init_config(struct static_config *c)
{
- c->c.preference = DEF_PREF_STATIC;
init_list(&c->iface_routes);
init_list(&c->other_routes);
}
@@ -523,6 +522,7 @@ static_copy_config(struct proto_config *dest, struct proto_config *src)
struct protocol proto_static = {
name: "Static",
template: "static%d",
+ preference: DEF_PREF_STATIC,
init: static_init,
dump: static_dump,
start: static_start,
diff --git sysdep/bsd/krt-sock.c sysdep/bsd/krt-sock.c
index 4bf6600..4ee5495 100644
--- sysdep/bsd/krt-sock.c
+++ sysdep/bsd/krt-sock.c
@@ -410,14 +410,42 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
}
static void
+krt_read_ifannounce(struct ks_msg *msg)
+{
+ struct if_announcemsghdr *ifam = (struct if_announcemsghdr *)&msg->rtm;
+
+ if (ifam->ifan_what == IFAN_ARRIVAL)
+ {
+ /* Not enough info to create the iface, so we just trigger iface scan */
+ kif_request_scan();
+ }
+ else if (ifam->ifan_what == IFAN_DEPARTURE)
+ {
+ struct iface *iface = if_find_by_index(ifam->ifan_index);
+
+ /* Interface is destroyed */
+ if (!iface)
+ {
+ DBG("KRT: unknown interface (%s, #%d) going down. Ignoring\n", ifam->ifan_name, ifam->ifan_index);
+ return;
+ }
+
+ if_delete(iface);
+ }
+
+ DBG("KRT: IFANNOUNCE what: %d index %d name %s\n", ifam->ifan_what, ifam->ifan_index, ifam->ifan_name);
+}
+
+static void
krt_read_ifinfo(struct ks_msg *msg)
{
struct if_msghdr *ifm = (struct if_msghdr *)&msg->rtm;
void *body = (void *)(ifm + 1);
struct sockaddr_dl *dl = NULL;
unsigned int i;
- struct iface *iface = NULL, f;
+ struct iface *iface = NULL, f = {};
int fl = ifm->ifm_flags;
+ int nlen = 0;
for (i = 1; i<=RTA_IFP; i <<= 1)
{
@@ -432,31 +460,42 @@ krt_read_ifinfo(struct ks_msg *msg)
}
}
- if(dl && (dl->sdl_family != AF_LINK))
+ if (dl && (dl->sdl_family != AF_LINK))
{
- log("Ignoring strange IFINFO");
+ log(L_WARN "Ignoring strange IFINFO");
return;
}
- iface = if_find_by_index(ifm->ifm_index);
+ if (dl)
+ nlen = MIN(sizeof(f.name)-1, dl->sdl_nlen);
- if(!iface)
+ /* Note that asynchronous IFINFO messages do not contain iface
+ name, so we have to found an existing iface by iface index */
+
+ iface = if_find_by_index(ifm->ifm_index);
+ if (!iface)
{
/* New interface */
- if(!dl) return; /* No interface name, ignoring */
+ if (!dl)
+ return; /* No interface name, ignoring */
- bzero(&f, sizeof(f));
- f.index = ifm->ifm_index;
- memcpy(f.name, dl->sdl_data, MIN(sizeof(f.name)-1, dl->sdl_nlen));
- DBG("New interface '%s' found", f.name);
+ memcpy(f.name, dl->sdl_data, nlen);
+ DBG("New interface '%s' found\n", f.name);
+ }
+ else if (dl && memcmp(iface->name, dl->sdl_data, nlen))
+ {
+ /* Interface renamed */
+ if_delete(iface);
+ memcpy(f.name, dl->sdl_data, nlen);
}
else
{
- memcpy(&f, iface, sizeof(struct iface));
+ /* Old interface */
+ memcpy(f.name, iface->name, sizeof(f.name));
}
+ f.index = ifm->ifm_index;
f.mtu = ifm->ifm_data.ifi_mtu;
- f.flags = 0;
if (fl & IFF_UP)
f.flags |= IF_ADMIN_UP;
@@ -471,8 +510,7 @@ krt_read_ifinfo(struct ks_msg *msg)
else
f.flags |= IF_MULTIACCESS; /* NBMA */
- if((!iface) || memcmp(&f, iface, sizeof(struct iface)))
- if_update(&f); /* Just if something happens */
+ if_update(&f);
}
static void
@@ -588,6 +626,9 @@ krt_read_msg(struct proto *p, struct ks_msg *msg, int scan)
case RTM_DELETE:
krt_read_rt(msg, (struct krt_proto *)p, scan);
break;
+ case RTM_IFANNOUNCE:
+ krt_read_ifannounce(msg);
+ break;
case RTM_IFINFO:
krt_read_ifinfo(msg);
break;
diff --git sysdep/linux/netlink/netlink.c sysdep/linux/netlink/netlink.c
index cf80823..17c369e 100644
--- sysdep/linux/netlink/netlink.c
+++ sysdep/linux/netlink/netlink.c
@@ -386,7 +386,7 @@ nl_parse_link(struct nlmsghdr *h, int scan)
struct ifinfomsg *i;
struct rtattr *a[IFLA_WIRELESS+1];
int new = h->nlmsg_type == RTM_NEWLINK;
- struct iface f;
+ struct iface f = {};
struct iface *ifi;
char *name;
u32 mtu;
@@ -408,26 +408,21 @@ nl_parse_link(struct nlmsghdr *h, int scan)
if (!new)
{
DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
- if (ifi && !scan)
- {
- memcpy(&f, ifi, sizeof(struct iface));
- f.flags |= IF_SHUTDOWN;
- if_update(&f);
- }
+ if (!ifi)
+ return;
+
+ if_delete(ifi);
}
else
{
DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i->ifi_index, name, mtu, i->ifi_flags);
- if (ifi)
- memcpy(&f, ifi, sizeof(f));
- else
- {
- bzero(&f, sizeof(f));
- f.index = i->ifi_index;
- }
- strncpy(f.name, RTA_DATA(a[IFLA_IFNAME]), sizeof(f.name)-1);
+ if (ifi && strncmp(ifi->name, name, sizeof(ifi->name)-1))
+ if_delete(ifi);
+
+ strncpy(f.name, name, sizeof(f.name)-1);
+ f.index = i->ifi_index;
f.mtu = mtu;
- f.flags = 0;
+
fl = i->ifi_flags;
if (fl & IFF_UP)
f.flags |= IF_ADMIN_UP;
diff --git sysdep/unix/krt.Y sysdep/unix/krt.Y
index 8608196..18e1e52 100644
--- sysdep/unix/krt.Y
+++ sysdep/unix/krt.Y
@@ -31,7 +31,6 @@ kern_proto_start: proto_start KERNEL {
cf_error("Kernel protocol already defined");
#endif
cf_krt = this_proto = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), $1);
- this_proto->preference = DEF_PREF_INHERITED;
THIS_KRT->scan_time = 60;
THIS_KRT->learn = THIS_KRT->persist = 0;
krt_scan_construct(THIS_KRT);
@@ -67,7 +66,6 @@ kif_proto_start: proto_start DEVICE {
if (cf_kif)
cf_error("Kernel device protocol already defined");
cf_kif = this_proto = proto_config_new(&proto_unix_iface, sizeof(struct kif_config), $1);
- this_proto->preference = DEF_PREF_DIRECT;
THIS_KIF->scan_time = 60;
init_list(&THIS_KIF->primary);
krt_if_construct(THIS_KIF);
diff --git sysdep/unix/krt.c sysdep/unix/krt.c
index e5a8ce1..231c5fc 100644
--- sysdep/unix/krt.c
+++ sysdep/unix/krt.c
@@ -104,6 +104,13 @@ kif_force_scan(void)
}
}
+void
+kif_request_scan(void)
+{
+ if (kif_proto && kif_scan_timer->expires > now)
+ tm_start(kif_scan_timer, 1);
+}
+
static struct proto *
kif_init(struct proto_config *c)
{
@@ -236,6 +243,7 @@ kif_copy_config(struct proto_config *dest, struct proto_config *src)
struct protocol proto_unix_iface = {
name: "Device",
template: "device%d",
+ preference: DEF_PREF_DIRECT,
preconfig: kif_preconfig,
init: kif_init,
start: kif_start,
@@ -961,6 +969,7 @@ struct protocol proto_unix_kernel = {
name: "Kernel",
template: "kernel%d",
attr_class: EAP_KRT,
+ preference: DEF_PREF_INHERITED,
preconfig: krt_preconfig,
postconfig: krt_postconfig,
init: krt_init,
diff --git sysdep/unix/krt.h sysdep/unix/krt.h
index 7bb4fe7..b0c4dc5 100644
--- sysdep/unix/krt.h
+++ sysdep/unix/krt.h
@@ -77,6 +77,7 @@ extern pool *krt_pool;
if (pr->p.debug & fl) \
{ log(L_TRACE "%s: " msg, pr->p.name , ## args); } } while(0)
+void kif_request_scan(void);
void krt_got_route(struct krt_proto *p, struct rte *e);
void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
#
PORTNAME= bird6
PORTVERSION= 1.3.4
PORTVERSION= 1.3.6
CATEGORIES= net
MASTER_SITES= ftp://bird.network.cz/pub/bird/
DISTNAME= bird-${PORTVERSION}

View File

@ -1,2 +1,2 @@
SHA256 (bird-1.3.4.tar.gz) = 0b97c7486515b3ec81b34935859c0b66d92e2cc3f1f001e640d5d38e10c61dc6
SIZE (bird-1.3.4.tar.gz) = 759228
SHA256 (bird-1.3.6.tar.gz) = 5d060256c179bceff861b7533831adc690eb64d27d14fb1ddfba407eb83d870a
SIZE (bird-1.3.6.tar.gz) = 864775