[-]
[+]
|
Changed |
bird.changes
|
|
[-]
[+]
|
Changed |
bird.spec
^
|
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/bsd/krt-iface.h
^
|
@@ -1,25 +0,0 @@
-/*
- * BIRD -- Unix Kernel Socket Route Syncer -- Dummy Include File
- *
- * (c) 2004 Ondrej Filip <feela@network.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_IFACE_H_
-#define _BIRD_KRT_IFACE_H_
-
-/*
- * We don't have split iface/scan/set parts. See krt-sock.h.
- */
-
-struct krt_if_params {
-};
-
-struct krt_if_status {
-};
-
-static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
-static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { }
-
-#endif
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/bsd/krt-scan.h
^
|
@@ -1,22 +0,0 @@
-/*
- * BIRD -- *BSD Kernel Route Syncer -- Scanning
- *
- * (c) 2004 Ondrej Filip <feela@network.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_SCAN_H_
-#define _BIRD_KRT_SCAN_H_
-
-struct krt_scan_params {
-};
-
-struct krt_scan_status {
- list temp_ifs; /* Temporary interfaces */
-};
-
-static inline int krt_scan_params_same(struct krt_scan_params *o UNUSED, struct krt_scan_params *n UNUSED) { return 1; }
-static inline void krt_scan_copy_params(struct krt_scan_params *d UNUSED, struct krt_scan_params *s UNUSED) { }
-
-#endif
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/bsd/krt-set.h
^
|
@@ -1,17 +0,0 @@
-/*
- * BIRD -- Unix Kernel Socket Route Syncer -- Dummy Include File
- *
- * (c) 2004 Ondrej Filip <feela@network.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_SET_H_
-#define _BIRD_KRT_SET_H_
-
-/*
- * We don't have split iface/scan/set parts. See krt-sock.h.
- */
-#include "lib/krt-sock.h"
-
-#endif
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/bsd/krt-sock.h
^
|
@@ -1,42 +0,0 @@
-/*
- * BIRD -- Unix Kernel Route Syncer -- Setting
- *
- * (c) 2004 Ondrej Filip <feela@network.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_SOCK_H_
-#define _BIRD_KRT_SOCK_H_
-
-#include <sys/socket.h>
-#include <net/route.h>
-#include "lib/socket.h"
-
-#ifndef RTAX_MAX
-#define RTAX_MAX 8
-#endif
-
-
-struct ks_msg
-{
- struct rt_msghdr rtm;
- struct sockaddr_storage buf[RTAX_MAX];
-};
-
-
-
-extern int krt_set_sock;
-
-struct krt_set_params {
-};
-
-struct krt_set_status {
-};
-
-static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
-static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { }
-
-void krt_read_msg(struct proto *p, struct ks_msg *msg, int scan);
-
-#endif
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/cf/linux-20.h
^
|
@@ -1,26 +0,0 @@
-/*
- * Configuration for Linux 2.0 based systems
- *
- * (c) 1998--1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#undef CONFIG_AUTO_ROUTES
-#undef CONFIG_SELF_CONSCIOUS
-#undef CONFIG_MULTIPLE_TABLES
-
-#define CONFIG_UNIX_IFACE
-#define CONFIG_UNIX_SET
-#define CONFIG_UNIX_DONTROUTE
-#undef CONFIG_SKIP_MC_BIND
-#define CONFIG_LINUX_SCAN
-
-#define CONFIG_LINUX_MC_MREQ_BIND
-#define CONFIG_ALL_MULTICAST
-#define CONFIG_UNNUM_MULTICAST
-
-/*
-Link: sysdep/linux
-Link: sysdep/unix
- */
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/cf/linux-21.h
^
|
@@ -1,26 +0,0 @@
-/*
- * Configuration for Linux 2.1/2.2 based systems without Netlink
- *
- * (c) 1998--1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#define CONFIG_AUTO_ROUTES
-#undef CONFIG_SELF_CONSCIOUS
-#undef CONFIG_MULTIPLE_TABLES
-
-#define CONFIG_UNIX_IFACE
-#define CONFIG_UNIX_SET
-#define CONFIG_UNIX_DONTROUTE
-#undef CONFIG_SKIP_MC_BIND
-#define CONFIG_LINUX_SCAN
-
-#define CONFIG_LINUX_MC_MREQN
-#define CONFIG_ALL_MULTICAST
-#define CONFIG_UNNUM_MULTICAST
-
-/*
-Link: sysdep/linux
-Link: sysdep/unix
- */
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/cf/linux-22.h
^
|
@@ -1,26 +0,0 @@
-/*
- * Configuration for Linux 2.2 based systems
- *
- * (c) 1998--1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#define CONFIG_AUTO_ROUTES
-#define CONFIG_SELF_CONSCIOUS
-#define CONFIG_MULTIPLE_TABLES
-#define CONFIG_ALL_TABLES_AT_ONCE
-#define CONFIG_MC_PROPER_SRC
-
-#undef CONFIG_SKIP_MC_BIND
-
-#define CONFIG_LINUX_MC_MREQN
-#define CONFIG_UNIX_DONTROUTE
-
-#define CONFIG_RESTRICTED_PRIVILEGES
-
-/*
-Link: sysdep/linux/netlink
-Link: sysdep/linux
-Link: sysdep/unix
- */
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/linux/krt-scan.c
^
|
@@ -1,199 +0,0 @@
-/*
- * BIRD -- Linux Routing Table Scanning
- *
- * (c) 1998--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#include <stdio.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <net/route.h>
-
-#undef LOCAL_DEBUG
-
-#include "nest/bird.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"
-
-static int krt_scan_fd = -1;
-
-struct iface *
-krt_temp_iface(struct krt_proto *p, char *name)
-{
- struct iface *i;
-
- WALK_LIST(i, p->scan.temp_ifs)
- if (!strcmp(i->name, name))
- return i;
- i = mb_allocz(p->p.pool, sizeof(struct iface));
- strcpy(i->name, name);
- add_tail(&p->scan.temp_ifs, &i->n);
- return i;
-}
-
-static void
-krt_parse_entry(byte *ent, struct krt_proto *p)
-{
- u32 dest0, gw0, mask0;
- ip_addr dest, gw, mask;
- unsigned int flags;
- int masklen;
- net *net;
- byte *iface = ent;
- rte *e;
-
- if (sscanf(ent, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4)
- {
- log(L_ERR "krt read: unable to parse `%s'", ent);
- return;
- }
- while (*ent != '\t')
- ent++;
- *ent = 0;
-
- dest = ipa_from_u32(dest0);
- ipa_ntoh(dest);
- gw = ipa_from_u32(gw0);
- ipa_ntoh(gw);
- mask = ipa_from_u32(mask0);
- ipa_ntoh(mask);
- if ((masklen = ipa_mklen(mask)) < 0)
- {
- log(L_ERR "krt read: invalid netmask %08x", mask0);
- return;
- }
- DBG("Got %I/%d via %I flags %x\n", dest, masklen, gw, flags);
-
- if (!(flags & RTF_UP))
- {
- DBG("Down.\n");
- return;
- }
- if (flags & RTF_HOST)
- masklen = 32;
- if (flags & (RTF_DYNAMIC | RTF_MODIFIED)) /* Redirect route */
- {
- log(L_WARN "krt: Ignoring redirect to %I/%d via %I", dest, masklen, gw);
- return;
- }
-
- net = net_get(p->p.table, dest, masklen);
-
- rta a = {
- .proto = &p->p,
- .source = RTS_INHERIT,
- .scope = SCOPE_UNIVERSE,
- .cast = RTC_UNICAST
- };
-
- if (flags & RTF_GATEWAY)
- {
- neighbor *ng = neigh_find(&p->p, &gw, 0);
- if (ng && ng->scope)
- a.iface = ng->iface;
- else
- {
- log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", gw, net->n.prefix, net->n.pxlen);
- return;
- }
- a.dest = RTD_ROUTER;
- a.gw = gw;
- }
- else if (flags & RTF_REJECT)
- {
- a.dest = RTD_UNREACHABLE;
- a.gw = IPA_NONE;
- }
- else if (isalpha(iface[0]))
- {
- a.dest = RTD_DEVICE;
- a.gw = IPA_NONE;
- a.iface = krt_temp_iface(p, iface);
- }
- else
- {
- log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen);
- return;
- }
-
- e = rte_get_temp(&a);
- e->net = net;
- e->u.krt.src = KRT_SRC_UNKNOWN;
- krt_got_route(p, e);
-}
-
-void
-krt_scan_fire(struct krt_proto *p)
-{
- byte buf[32768];
- int l, seen_hdr;
-
- if (krt_scan_fd < 0)
- {
- krt_scan_fd = open("/proc/net/route", O_RDONLY);
- if (krt_scan_fd < 0)
- die("/proc/net/route: %m");
- }
- else if (lseek(krt_scan_fd, 0, SEEK_SET) < 0)
- {
- log(L_ERR "krt seek: %m");
- return;
- }
- seen_hdr = 0;
- while ((l = read(krt_scan_fd, buf, sizeof(buf))) > 0)
- {
- byte *z = buf;
- if (l & 127)
- {
- log(L_ERR "krt read: misaligned entry: l=%d", l);
- return;
- }
- while (l >= 128)
- {
- if (seen_hdr++)
- krt_parse_entry(z, p);
- z += 128;
- l -= 128;
- }
- }
- if (l < 0)
- {
- log(L_ERR "krt read: %m");
- return;
- }
- DBG("KRT scan done, seen %d lines\n", seen_hdr);
-}
-
-void
-krt_scan_construct(struct krt_config *c)
-{
-}
-
-void
-krt_scan_preconfig(struct config *c)
-{
-}
-
-void
-krt_scan_postconfig(struct krt_config *c)
-{
-}
-
-void
-krt_scan_start(struct krt_proto *x, int first)
-{
- init_list(&x->scan.temp_ifs);
-}
-
-void
-krt_scan_shutdown(struct krt_proto *x, int last)
-{
-}
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/linux/krt-scan.h
^
|
@@ -1,21 +0,0 @@
-/*
- * BIRD -- Linux Kernel Route Syncer -- Scanning
- *
- * (c) 1998--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_SCAN_H_
-#define _BIRD_KRT_SCAN_H_
-
-struct krt_scan_params {
-};
-
-struct krt_scan_status {
- list temp_ifs; /* Temporary interfaces */
-};
-
-static inline int krt_scan_params_same(struct krt_scan_params *o, struct krt_scan_params *n) { return 1; }
-
-#endif
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/linux/netlink
^
|
-(directory)
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/linux/netlink/Modules
^
|
@@ -1,5 +0,0 @@
-krt-iface.h
-krt-set.h
-krt-scan.h
-netlink.c
-netlink.Y
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/linux/netlink/krt-iface.h
^
|
@@ -1,29 +0,0 @@
-/*
- * BIRD -- Unix Kernel Netlink Interface Syncer -- Dummy Include File
- *
- * (c) 1998--1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_IFACE_H_
-#define _BIRD_KRT_IFACE_H_
-
-/*
- * We don't have split iface/scan/set parts. See krt-scan.h.
- */
-
-struct krt_if_params {
-};
-
-struct krt_if_status {
-};
-
-static inline void krt_if_construct(struct kif_config *c UNUSED) { };
-static inline void krt_if_shutdown(struct kif_proto *p UNUSED) { };
-static inline void krt_if_io_init(void) { };
-
-static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
-static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { }
-
-#endif
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/linux/netlink/krt-scan.h
^
|
@@ -1,36 +0,0 @@
-/*
- * BIRD -- Linux Kernel Netlink Route Syncer -- Scanning
- *
- * (c) 1998--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_SCAN_H_
-#define _BIRD_KRT_SCAN_H_
-
-/*
- * We don't have split iface/scan/set for Netlink. All options
- * and run-time parameters are declared here instead of splitting
- * to krt-set.h, krt-iface.h and this file.
- */
-
-#define NL_NUM_TABLES 256
-
-struct krt_scan_params {
- int table_id; /* Kernel table ID we sync with */
-};
-
-struct krt_scan_status {
- list temp_ifs; /* Temporary interfaces */
-};
-
-static inline int krt_scan_params_same(struct krt_scan_params *o, struct krt_scan_params *n)
-{
- return o->table_id == n->table_id;
-}
-
-static inline void krt_scan_copy_params(struct krt_scan_params *d UNUSED, struct krt_scan_params *s UNUSED) { }
-/* table_id copied in krt_copy_config() */
-
-#endif
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/linux/netlink/krt-set.h
^
|
@@ -1,28 +0,0 @@
-/*
- * BIRD -- Unix Kernel Netlink Route Syncer -- Dummy Include File
- *
- * (c) 1998--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_SET_H_
-#define _BIRD_KRT_SET_H_
-
-/*
- * We don't have split iface/scan/set parts. See krt-scan.h.
- */
-
-struct krt_set_params {
-};
-
-struct krt_set_status {
-};
-
-static inline void krt_set_construct(struct krt_config *c UNUSED) { };
-static inline void krt_set_start(struct krt_proto *p UNUSED, int first UNUSED) { };
-static inline void krt_set_shutdown(struct krt_proto *p UNUSED, int last UNUSED) { };
-static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
-static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { }
-
-#endif
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/linux/netlink/netlink.Y
^
|
@@ -1,32 +0,0 @@
-/*
- * BIRD -- Linux Netlink Configuration
- *
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-CF_HDR
-
-CF_DECLS
-
-CF_KEYWORDS(ASYNC, KERNEL, TABLE, KRT_PREFSRC, KRT_REALM)
-
-CF_GRAMMAR
-
-CF_ADDTO(kern_proto, kern_proto nl_item ';')
-
-nl_item:
- KERNEL TABLE expr {
- if ($3 <= 0 || $3 >= NL_NUM_TABLES)
- cf_error("Kernel routing table number out of range");
- THIS_KRT->scan.table_id = $3;
- }
- ;
-
-CF_ADDTO(dynamic_attr, KRT_PREFSRC { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); })
-CF_ADDTO(dynamic_attr, KRT_REALM { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REALM); })
-
-CF_CODE
-
-CF_END
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/linux/netlink/netlink.c
^
|
@@ -1,1123 +0,0 @@
-/*
- * BIRD -- Linux Netlink Interface
- *
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <errno.h>
-
-#undef LOCAL_DEBUG
-
-#include "nest/bird.h"
-#include "nest/route.h"
-#include "nest/protocol.h"
-#include "nest/iface.h"
-#include "lib/alloca.h"
-#include "lib/timer.h"
-#include "lib/unix.h"
-#include "lib/krt.h"
-#include "lib/socket.h"
-#include "lib/string.h"
-#include "conf/conf.h"
-
-#include <asm/types.h>
-#include <linux/if.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-
-#ifndef MSG_TRUNC /* Hack: Several versions of glibc miss this one :( */
-#define MSG_TRUNC 0x20
-#endif
-
-#ifndef IFF_LOWER_UP
-#define IFF_LOWER_UP 0x10000
-#endif
-
-/*
- * Synchronous Netlink interface
- */
-
-struct nl_sock
-{
- int fd;
- u32 seq;
- byte *rx_buffer; /* Receive buffer */
- struct nlmsghdr *last_hdr; /* Recently received packet */
- unsigned int last_size;
-};
-
-#define NL_RX_SIZE 8192
-
-static struct nl_sock nl_scan = {.fd = -1}; /* Netlink socket for synchronous scan */
-static struct nl_sock nl_req = {.fd = -1}; /* Netlink socket for requests */
-
-static void
-nl_open_sock(struct nl_sock *nl)
-{
- if (nl->fd < 0)
- {
- nl->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (nl->fd < 0)
- die("Unable to open rtnetlink socket: %m");
- nl->seq = now;
- nl->rx_buffer = xmalloc(NL_RX_SIZE);
- nl->last_hdr = NULL;
- nl->last_size = 0;
- }
-}
-
-static void
-nl_open(void)
-{
- nl_open_sock(&nl_scan);
- nl_open_sock(&nl_req);
-}
-
-static void
-nl_send(struct nl_sock *nl, struct nlmsghdr *nh)
-{
- struct sockaddr_nl sa;
-
- memset(&sa, 0, sizeof(sa));
- sa.nl_family = AF_NETLINK;
- nh->nlmsg_pid = 0;
- nh->nlmsg_seq = ++(nl->seq);
- if (sendto(nl->fd, nh, nh->nlmsg_len, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0)
- die("rtnetlink sendto: %m");
- nl->last_hdr = NULL;
-}
-
-static void
-nl_request_dump(int cmd)
-{
- struct {
- struct nlmsghdr nh;
- struct rtgenmsg g;
- } req;
- req.nh.nlmsg_type = cmd;
- req.nh.nlmsg_len = sizeof(req);
- req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- /* Is it important which PF_* is used for link-level interface scan?
- It seems that some information is available only when PF_INET is used. */
- req.g.rtgen_family = (cmd == RTM_GETLINK) ? PF_INET : BIRD_PF;
- nl_send(&nl_scan, &req.nh);
-}
-
-static struct nlmsghdr *
-nl_get_reply(struct nl_sock *nl)
-{
- for(;;)
- {
- if (!nl->last_hdr)
- {
- struct iovec iov = { nl->rx_buffer, NL_RX_SIZE };
- struct sockaddr_nl sa;
- struct msghdr m = { (struct sockaddr *) &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
- int x = recvmsg(nl->fd, &m, 0);
- if (x < 0)
- die("nl_get_reply: %m");
- if (sa.nl_pid) /* It isn't from the kernel */
- {
- DBG("Non-kernel packet\n");
- continue;
- }
- nl->last_size = x;
- nl->last_hdr = (void *) nl->rx_buffer;
- if (m.msg_flags & MSG_TRUNC)
- bug("nl_get_reply: got truncated reply which should be impossible");
- }
- if (NLMSG_OK(nl->last_hdr, nl->last_size))
- {
- struct nlmsghdr *h = nl->last_hdr;
- nl->last_hdr = NLMSG_NEXT(h, nl->last_size);
- if (h->nlmsg_seq != nl->seq)
- {
- log(L_WARN "nl_get_reply: Ignoring out of sequence netlink packet (%x != %x)",
- h->nlmsg_seq, nl->seq);
- continue;
- }
- return h;
- }
- if (nl->last_size)
- log(L_WARN "nl_get_reply: Found packet remnant of size %d", nl->last_size);
- nl->last_hdr = NULL;
- }
-}
-
-static struct rate_limit rl_netlink_err;
-
-static int
-nl_error(struct nlmsghdr *h)
-{
- struct nlmsgerr *e;
- int ec;
-
- if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
- {
- log(L_WARN "Netlink: Truncated error message received");
- return ENOBUFS;
- }
- e = (struct nlmsgerr *) NLMSG_DATA(h);
- ec = -e->error;
- if (ec)
- log_rl(&rl_netlink_err, L_WARN "Netlink: %s", strerror(ec));
- return ec;
-}
-
-static struct nlmsghdr *
-nl_get_scan(void)
-{
- struct nlmsghdr *h = nl_get_reply(&nl_scan);
-
- if (h->nlmsg_type == NLMSG_DONE)
- return NULL;
- if (h->nlmsg_type == NLMSG_ERROR)
- {
- nl_error(h);
- return NULL;
- }
- return h;
-}
-
-static int
-nl_exchange(struct nlmsghdr *pkt)
-{
- struct nlmsghdr *h;
-
- nl_send(&nl_req, pkt);
- for(;;)
- {
- h = nl_get_reply(&nl_req);
- if (h->nlmsg_type == NLMSG_ERROR)
- break;
- log(L_WARN "nl_exchange: Unexpected reply received");
- }
- return nl_error(h) ? -1 : 0;
-}
-
-/*
- * Netlink attributes
- */
-
-static int nl_attr_len;
-
-static void *
-nl_checkin(struct nlmsghdr *h, int lsize)
-{
- nl_attr_len = h->nlmsg_len - NLMSG_LENGTH(lsize);
- if (nl_attr_len < 0)
- {
- log(L_ERR "nl_checkin: underrun by %d bytes", -nl_attr_len);
- return NULL;
- }
- return NLMSG_DATA(h);
-}
-
-static int
-nl_parse_attrs(struct rtattr *a, struct rtattr **k, int ksize)
-{
- int max = ksize / sizeof(struct rtattr *);
- bzero(k, ksize);
- while (RTA_OK(a, nl_attr_len))
- {
- if (a->rta_type < max)
- k[a->rta_type] = a;
- a = RTA_NEXT(a, nl_attr_len);
- }
- if (nl_attr_len)
- {
- log(L_ERR "nl_parse_attrs: remnant of size %d", nl_attr_len);
- return 0;
- }
- else
- return 1;
-}
-
-void
-nl_add_attr(struct nlmsghdr *h, unsigned bufsize, unsigned code,
- void *data, unsigned dlen)
-{
- unsigned len = RTA_LENGTH(dlen);
- unsigned pos = NLMSG_ALIGN(h->nlmsg_len);
- struct rtattr *a;
-
- if (pos + len > bufsize)
- bug("nl_add_attr: packet buffer overflow");
- a = (struct rtattr *)((char *)h + pos);
- a->rta_type = code;
- a->rta_len = len;
- h->nlmsg_len = pos + len;
- memcpy(RTA_DATA(a), data, dlen);
-}
-
-static inline void
-nl_add_attr_u32(struct nlmsghdr *h, unsigned bufsize, int code, u32 data)
-{
- nl_add_attr(h, bufsize, code, &data, 4);
-}
-
-static inline void
-nl_add_attr_ipa(struct nlmsghdr *h, unsigned bufsize, int code, ip_addr ipa)
-{
- ipa_hton(ipa);
- nl_add_attr(h, bufsize, code, &ipa, sizeof(ipa));
-}
-
-#define RTNH_SIZE (sizeof(struct rtnexthop) + sizeof(struct rtattr) + sizeof(ip_addr))
-
-static inline void
-add_mpnexthop(char *buf, ip_addr ipa, unsigned iface, unsigned char weight)
-{
- struct rtnexthop *nh = (void *) buf;
- struct rtattr *rt = (void *) (buf + sizeof(*nh));
- nh->rtnh_len = RTNH_SIZE;
- nh->rtnh_flags = 0;
- nh->rtnh_hops = weight;
- nh->rtnh_ifindex = iface;
- rt->rta_len = sizeof(*rt) + sizeof(ipa);
- rt->rta_type = RTA_GATEWAY;
- ipa_hton(ipa);
- memcpy(buf + sizeof(*nh) + sizeof(*rt), &ipa, sizeof(ipa));
-}
-
-
-static void
-nl_add_multipath(struct nlmsghdr *h, unsigned bufsize, struct mpnh *nh)
-{
- unsigned len = sizeof(struct rtattr);
- unsigned pos = NLMSG_ALIGN(h->nlmsg_len);
- char *buf = (char *)h + pos;
- struct rtattr *rt = (void *) buf;
- buf += len;
-
- for (; nh; nh = nh->next)
- {
- len += RTNH_SIZE;
- if (pos + len > bufsize)
- bug("nl_add_multipath: packet buffer overflow");
-
- add_mpnexthop(buf, nh->gw, nh->iface->index, nh->weight);
- buf += RTNH_SIZE;
- }
-
- rt->rta_type = RTA_MULTIPATH;
- rt->rta_len = len;
- h->nlmsg_len = pos + len;
-}
-
-
-static struct mpnh *
-nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
-{
- /* Temporary buffer for multicast nexthops */
- static struct mpnh *nh_buffer;
- static int nh_buf_size; /* in number of structures */
- static int nh_buf_used;
-
- struct rtattr *a[RTA_CACHEINFO+1];
- struct rtnexthop *nh = RTA_DATA(ra);
- struct mpnh *rv, *first, **last;
- int len = RTA_PAYLOAD(ra);
-
- first = NULL;
- last = &first;
- nh_buf_used = 0;
-
- while (len)
- {
- /* Use RTNH_OK(nh,len) ?? */
- if ((len < sizeof(*nh)) || (len < nh->rtnh_len))
- return NULL;
-
- if (nh_buf_used == nh_buf_size)
- {
- nh_buf_size = nh_buf_size ? (nh_buf_size * 2) : 4;
- nh_buffer = xrealloc(nh_buffer, nh_buf_size * sizeof(struct mpnh));
- }
- *last = rv = nh_buffer + nh_buf_used++;
- rv->next = NULL;
- last = &(rv->next);
-
- rv->weight = nh->rtnh_hops;
- rv->iface = if_find_by_index(nh->rtnh_ifindex);
- if (!rv->iface)
- return NULL;
-
- /* Nonexistent RTNH_PAYLOAD ?? */
- nl_attr_len = nh->rtnh_len - RTNH_LENGTH(0);
- nl_parse_attrs(RTNH_DATA(nh), a, sizeof(a));
- if (a[RTA_GATEWAY])
- {
- if (RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr))
- return NULL;
-
- memcpy(&rv->gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ip_addr));
- ipa_ntoh(rv->gw);
-
- neighbor *ng = neigh_find2(&p->p, &rv->gw, rv->iface,
- (nh->rtnh_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
- if (!ng || (ng->scope == SCOPE_HOST))
- return NULL;
- }
- else
- return NULL;
-
- len -= NLMSG_ALIGN(nh->rtnh_len);
- nh = RTNH_NEXT(nh);
- }
-
- return first;
-}
-
-
-/*
- * Scanning of interfaces
- */
-
-static void
-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 *ifi;
- char *name;
- u32 mtu;
- unsigned int fl;
-
- if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFLA_RTA(i), a, sizeof(a)))
- return;
- if (!a[IFLA_IFNAME] || RTA_PAYLOAD(a[IFLA_IFNAME]) < 2 ||
- !a[IFLA_MTU] || RTA_PAYLOAD(a[IFLA_MTU]) != 4)
- {
- if (scan || !a[IFLA_WIRELESS])
- log(L_ERR "nl_parse_link: Malformed message received");
- return;
- }
- name = RTA_DATA(a[IFLA_IFNAME]);
- memcpy(&mtu, RTA_DATA(a[IFLA_MTU]), sizeof(u32));
-
- ifi = if_find_by_index(i->ifi_index);
- if (!new)
- {
- DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
- 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 && 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;
-
- fl = i->ifi_flags;
- if (fl & IFF_UP)
- f.flags |= IF_ADMIN_UP;
- if (fl & IFF_LOWER_UP)
- f.flags |= IF_LINK_UP;
- if (fl & IFF_LOOPBACK) /* Loopback */
- f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE;
- else if (fl & IFF_POINTOPOINT) /* PtP */
- f.flags |= IF_MULTICAST;
- else if (fl & IFF_BROADCAST) /* Broadcast */
- f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST;
- else
- f.flags |= IF_MULTIACCESS; /* NBMA */
- if_update(&f);
- }
-}
-
-static void
-nl_parse_addr(struct nlmsghdr *h)
-{
- struct ifaddrmsg *i;
- struct rtattr *a[IFA_ANYCAST+1];
- int new = h->nlmsg_type == RTM_NEWADDR;
- struct ifa ifa;
- struct iface *ifi;
- int scope;
-
- if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFA_RTA(i), a, sizeof(a)))
- return;
- if (i->ifa_family != BIRD_AF)
- return;
- if (!a[IFA_ADDRESS] || RTA_PAYLOAD(a[IFA_ADDRESS]) != sizeof(ip_addr)
-#ifdef IPV6
- || a[IFA_LOCAL] && RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
-#else
- || !a[IFA_LOCAL] || RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
- || (a[IFA_BROADCAST] && RTA_PAYLOAD(a[IFA_BROADCAST]) != sizeof(ip_addr))
-#endif
- )
- {
- log(L_ERR "nl_parse_addr: Malformed message received");
- return;
- }
-
- ifi = if_find_by_index(i->ifa_index);
- if (!ifi)
- {
- log(L_ERR "KIF: Received address message for unknown interface %d", i->ifa_index);
- return;
- }
-
- bzero(&ifa, sizeof(ifa));
- ifa.iface = ifi;
- if (i->ifa_flags & IFA_F_SECONDARY)
- ifa.flags |= IA_SECONDARY;
-
- /* IFA_LOCAL can be unset for IPv6 interfaces */
- memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL] ? : a[IFA_ADDRESS]), sizeof(ifa.ip));
- ipa_ntoh(ifa.ip);
- ifa.pxlen = i->ifa_prefixlen;
- if (i->ifa_prefixlen > BITS_PER_IP_ADDRESS)
- {
- log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen);
- new = 0;
- }
- if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS)
- {
- ip_addr addr;
- memcpy(&addr, RTA_DATA(a[IFA_ADDRESS]), sizeof(addr));
- ipa_ntoh(addr);
- ifa.prefix = ifa.brd = addr;
-
- /* It is either a host address or a peer address */
- if (ipa_equal(ifa.ip, addr))
- ifa.flags |= IA_HOST;
- else
- {
- ifa.flags |= IA_PEER;
- ifa.opposite = addr;
- }
- }
- else
- {
- ip_addr netmask = ipa_mkmask(ifa.pxlen);
- ifa.prefix = ipa_and(ifa.ip, netmask);
- ifa.brd = ipa_or(ifa.ip, ipa_not(netmask));
- if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 1)
- ifa.opposite = ipa_opposite_m1(ifa.ip);
-
-#ifndef IPV6
- if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 2)
- ifa.opposite = ipa_opposite_m2(ifa.ip);
-
- if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
- {
- ip_addr xbrd;
- memcpy(&xbrd, RTA_DATA(a[IFA_BROADCAST]), sizeof(xbrd));
- ipa_ntoh(xbrd);
- if (ipa_equal(xbrd, ifa.prefix) || ipa_equal(xbrd, ifa.brd))
- ifa.brd = xbrd;
- else if (ifi->flags & IF_TMP_DOWN) /* Complain only during the first scan */
- log(L_ERR "KIF: Invalid broadcast address %I for %s", xbrd, ifi->name);
- }
-#endif
- }
-
- scope = ipa_classify(ifa.ip);
- if (scope < 0)
- {
- log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, ifi->name);
- return;
- }
- ifa.scope = scope & IADDR_SCOPE_MASK;
-
- DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %I/%d, brd %I, opp %I\n",
- ifi->index, ifi->name,
- new ? "added" : "removed",
- ifa.ip, ifa.flags, ifa.prefix, ifa.pxlen, ifa.brd, ifa.opposite);
- if (new)
- ifa_update(&ifa);
- else
- ifa_delete(&ifa);
-}
-
-void
-krt_if_scan(struct kif_proto *p UNUSED)
-{
- struct nlmsghdr *h;
-
- if_start_update();
-
- nl_request_dump(RTM_GETLINK);
- while (h = nl_get_scan())
- if (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)
- nl_parse_link(h, 1);
- else
- log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
-
- nl_request_dump(RTM_GETADDR);
- while (h = nl_get_scan())
- if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
- nl_parse_addr(h);
- else
- log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
-
- if_end_update();
-}
-
-/*
- * Routes
- */
-
-static struct krt_proto *nl_table_map[NL_NUM_TABLES];
-
-int
-krt_capable(rte *e)
-{
- rta *a = e->attrs;
-
- if (a->cast != RTC_UNICAST)
- return 0;
-
- switch (a->dest)
- {
- case RTD_ROUTER:
- if (ipa_has_link_scope(a->gw) && (a->iface == NULL))
- return 0;
- case RTD_DEVICE:
- case RTD_BLACKHOLE:
- case RTD_UNREACHABLE:
- case RTD_PROHIBIT:
- case RTD_MULTIPATH:
- break;
- default:
- return 0;
- }
- return 1;
-}
-
-static inline int
-nh_bufsize(struct mpnh *nh)
-{
- int rv = 0;
- for (; nh != NULL; nh = nh->next)
- rv += RTNH_SIZE;
- return rv;
-}
-
-static int
-nl_send_route(struct krt_proto *p, rte *e, int new)
-{
- eattr *ea;
- net *net = e->net;
- rta *a = e->attrs;
- struct {
- struct nlmsghdr h;
- struct rtmsg r;
- char buf[128 + nh_bufsize(a->nexthops)];
- } r;
-
- DBG("nl_send_route(%I/%d,new=%d)\n", net->n.prefix, net->n.pxlen, new);
-
- bzero(&r.h, sizeof(r.h));
- bzero(&r.r, sizeof(r.r));
- r.h.nlmsg_type = new ? RTM_NEWROUTE : RTM_DELROUTE;
- r.h.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- r.h.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (new ? NLM_F_CREATE|NLM_F_EXCL : 0);
-
- r.r.rtm_family = BIRD_AF;
- r.r.rtm_dst_len = net->n.pxlen;
- r.r.rtm_tos = 0;
- r.r.rtm_table = KRT_CF->scan.table_id;
- r.r.rtm_protocol = RTPROT_BIRD;
- r.r.rtm_scope = RT_SCOPE_UNIVERSE;
- nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
-
- if (ea = ea_find(a->eattrs, EA_KRT_PREFSRC))
- nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
-
- if (ea = ea_find(a->eattrs, EA_KRT_REALM))
- nl_add_attr_u32(&r.h, sizeof(r), RTA_FLOW, ea->u.data);
-
- switch (a->dest)
- {
- case RTD_ROUTER:
- r.r.rtm_type = RTN_UNICAST;
- nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
-
- /* a->iface != NULL checked in krt_capable() */
- if (ipa_has_link_scope(a->gw))
- nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
-
- break;
- case RTD_DEVICE:
- if (!a->iface)
- return -1;
- r.r.rtm_type = RTN_UNICAST;
- nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
- break;
- case RTD_BLACKHOLE:
- r.r.rtm_type = RTN_BLACKHOLE;
- break;
- case RTD_UNREACHABLE:
- r.r.rtm_type = RTN_UNREACHABLE;
- break;
- case RTD_PROHIBIT:
- r.r.rtm_type = RTN_PROHIBIT;
- break;
- case RTD_MULTIPATH:
- r.r.rtm_type = RTN_UNICAST;
- nl_add_multipath(&r.h, sizeof(r), a->nexthops);
- break;
- default:
- bug("krt_capable inconsistent with nl_send_route");
- }
-
- return nl_exchange(&r.h);
-}
-
-void
-krt_set_notify(struct krt_proto *p, net *n, rte *new, rte *old)
-{
- int err = 0;
-
- if (old)
- nl_send_route(p, old, 0);
-
- if (new)
- err = nl_send_route(p, new, 1);
-
- if (err < 0)
- n->n.flags |= KRF_SYNC_ERROR;
- else
- n->n.flags &= ~KRF_SYNC_ERROR;
-}
-
-
-#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
-
-static void
-nl_parse_route(struct nlmsghdr *h, int scan)
-{
- struct krt_proto *p;
- struct rtmsg *i;
- struct rtattr *a[RTA_CACHEINFO+1];
- int new = h->nlmsg_type == RTM_NEWROUTE;
-
- ip_addr dst = IPA_NONE;
- u32 oif = ~0;
- int src;
-
- if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
- return;
- if (i->rtm_family != BIRD_AF)
- return;
- if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
-#ifdef IPV6
- (a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
-#endif
- (a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
- (a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)) ||
- (a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
- (a[RTA_PREFSRC] && RTA_PAYLOAD(a[RTA_PREFSRC]) != sizeof(ip_addr)) ||
- (a[RTA_FLOW] && RTA_PAYLOAD(a[RTA_OIF]) != 4))
- {
- log(L_ERR "KRT: Malformed message received");
- return;
- }
-
- if (a[RTA_DST])
- {
- memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
- ipa_ntoh(dst);
- }
-
- if (a[RTA_OIF])
- memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
-
- DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p->p.name);
-
- p = nl_table_map[i->rtm_table]; /* Do we know this table? */
- if (!p)
- SKIP("unknown table %d", i->rtm_table);
-
-#ifdef IPV6
- if (a[RTA_IIF])
- SKIP("IIF set\n");
-#else
- if (i->rtm_tos != 0) /* We don't support TOS */
- SKIP("TOS %02x\n", i->rtm_tos);
-#endif
-
- if (scan && !new)
- SKIP("RTM_DELROUTE in scan\n");
-
- int c = ipa_classify_net(dst);
- if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
- SKIP("strange class/scope\n");
-
- // ignore rtm_scope, it is not a real scope
- // if (i->rtm_scope != RT_SCOPE_UNIVERSE)
- // SKIP("scope %u\n", i->rtm_scope);
-
- switch (i->rtm_protocol)
- {
- case RTPROT_UNSPEC:
- SKIP("proto unspec\n");
-
- case RTPROT_REDIRECT:
- src = KRT_SRC_REDIRECT;
- break;
-
- case RTPROT_KERNEL:
- src = KRT_SRC_KERNEL;
- return;
-
- case RTPROT_BIRD:
- if (!scan)
- SKIP("echo\n");
- src = KRT_SRC_BIRD;
- break;
-
- case RTPROT_BOOT:
- default:
- src = KRT_SRC_ALIEN;
- }
-
- net *net = net_get(p->p.table, dst, i->rtm_dst_len);
-
- rta ra = {
- .proto = &p->p,
- .source = RTS_INHERIT,
- .scope = SCOPE_UNIVERSE,
- .cast = RTC_UNICAST
- };
-
- switch (i->rtm_type)
- {
- case RTN_UNICAST:
-
- if (a[RTA_MULTIPATH])
- {
- ra.dest = RTD_MULTIPATH;
- ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]);
- if (!ra.nexthops)
- {
- log(L_ERR "KRT: Received strange multipath route %I/%d",
- net->n.prefix, net->n.pxlen);
- return;
- }
-
- break;
- }
-
- ra.iface = if_find_by_index(oif);
- if (!ra.iface)
- {
- log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
- net->n.prefix, net->n.pxlen, oif);
- return;
- }
-
- if (a[RTA_GATEWAY])
- {
- neighbor *ng;
- ra.dest = RTD_ROUTER;
- memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
- ipa_ntoh(ra.gw);
-
- /* Silently skip strange 6to4 routes */
- if (ipa_in_net(ra.gw, IPA_NONE, 96))
- return;
-
- ng = neigh_find2(&p->p, &ra.gw, ra.iface,
- (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
- if (!ng || (ng->scope == SCOPE_HOST))
- {
- log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
- net->n.prefix, net->n.pxlen, ra.gw);
- return;
- }
- }
- else
- {
- ra.dest = RTD_DEVICE;
-
- /*
- * In Linux IPv6, 'native' device routes have proto
- * RTPROT_BOOT and not RTPROT_KERNEL (which they have in
- * IPv4 and which is expected). We cannot distinguish
- * 'native' and user defined device routes, so we ignore all
- * such device routes and for consistency, we have the same
- * behavior in IPv4. Anyway, users should use RTPROT_STATIC
- * for their 'alien' routes.
- */
-
- if (i->rtm_protocol == RTPROT_BOOT)
- src = KRT_SRC_KERNEL;
- }
-
- break;
- case RTN_BLACKHOLE:
- ra.dest = RTD_BLACKHOLE;
- break;
- case RTN_UNREACHABLE:
- ra.dest = RTD_UNREACHABLE;
- break;
- case RTN_PROHIBIT:
- ra.dest = RTD_PROHIBIT;
- break;
- /* FIXME: What about RTN_THROW? */
- default:
- SKIP("type %d\n", i->rtm_type);
- return;
- }
-
- rte *e = rte_get_temp(&ra);
- e->net = net;
- e->u.krt.src = src;
- e->u.krt.proto = i->rtm_protocol;
- e->u.krt.type = i->rtm_type;
-
- if (a[RTA_PRIORITY])
- memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric));
- else
- e->u.krt.metric = 0;
-
- if (a[RTA_PREFSRC])
- {
- ip_addr ps;
- memcpy(&ps, RTA_DATA(a[RTA_PREFSRC]), sizeof(ps));
- ipa_ntoh(ps);
-
- ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr));
- ea->next = ra.eattrs;
- ra.eattrs = ea;
- ea->flags = EALF_SORTED;
- ea->count = 1;
- ea->attrs[0].id = EA_KRT_PREFSRC;
- ea->attrs[0].flags = 0;
- ea->attrs[0].type = EAF_TYPE_IP_ADDRESS;
- ea->attrs[0].u.ptr = alloca(sizeof(struct adata) + sizeof(ps));
- ea->attrs[0].u.ptr->length = sizeof(ps);
- memcpy(ea->attrs[0].u.ptr->data, &ps, sizeof(ps));
- }
-
- if (a[RTA_FLOW])
- {
- ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr));
- ea->next = ra.eattrs;
- ra.eattrs = ea;
- ea->flags = EALF_SORTED;
- ea->count = 1;
- ea->attrs[0].id = EA_KRT_REALM;
- ea->attrs[0].flags = 0;
- ea->attrs[0].type = EAF_TYPE_INT;
- memcpy(&ea->attrs[0].u.data, RTA_DATA(a[RTA_FLOW]), 4);
- }
-
- if (scan)
- krt_got_route(p, e);
- else
- krt_got_route_async(p, e, new);
-}
-
-void
-krt_scan_fire(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NULL */
-{
- struct nlmsghdr *h;
-
- nl_request_dump(RTM_GETROUTE);
- while (h = nl_get_scan())
- if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
- nl_parse_route(h, 1);
- else
- log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
-}
-
-/*
- * Asynchronous Netlink interface
- */
-
-static sock *nl_async_sk; /* BIRD socket for asynchronous notifications */
-static byte *nl_async_rx_buffer; /* Receive buffer */
-
-static void
-nl_async_msg(struct nlmsghdr *h)
-{
- switch (h->nlmsg_type)
- {
- case RTM_NEWROUTE:
- case RTM_DELROUTE:
- DBG("KRT: Received async route notification (%d)\n", h->nlmsg_type);
- nl_parse_route(h, 0);
- break;
- case RTM_NEWLINK:
- case RTM_DELLINK:
- DBG("KRT: Received async link notification (%d)\n", h->nlmsg_type);
- nl_parse_link(h, 0);
- break;
- case RTM_NEWADDR:
- case RTM_DELADDR:
- DBG("KRT: Received async address notification (%d)\n", h->nlmsg_type);
- nl_parse_addr(h);
- break;
- default:
- DBG("KRT: Received unknown async notification (%d)\n", h->nlmsg_type);
- }
-}
-
-static int
-nl_async_hook(sock *sk, int size UNUSED)
-{
- struct iovec iov = { nl_async_rx_buffer, NL_RX_SIZE };
- struct sockaddr_nl sa;
- struct msghdr m = { (struct sockaddr *) &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
- struct nlmsghdr *h;
- int x;
- unsigned int len;
-
- x = recvmsg(sk->fd, &m, 0);
- if (x < 0)
- {
- if (errno == ENOBUFS)
- {
- /*
- * Netlink reports some packets have been thrown away.
- * One day we might react to it by asking for route table
- * scan in near future.
- */
- return 1; /* More data are likely to be ready */
- }
- else if (errno != EWOULDBLOCK)
- log(L_ERR "Netlink recvmsg: %m");
- return 0;
- }
- if (sa.nl_pid) /* It isn't from the kernel */
- {
- DBG("Non-kernel packet\n");
- return 1;
- }
- h = (void *) nl_async_rx_buffer;
- len = x;
- if (m.msg_flags & MSG_TRUNC)
- {
- log(L_WARN "Netlink got truncated asynchronous message");
- return 1;
- }
- while (NLMSG_OK(h, len))
- {
- nl_async_msg(h);
- h = NLMSG_NEXT(h, len);
- }
- if (len)
- log(L_WARN "nl_async_hook: Found packet remnant of size %d", len);
- return 1;
-}
-
-static void
-nl_open_async(void)
-{
- sock *sk;
- struct sockaddr_nl sa;
- int fd;
- static int nl_open_tried = 0;
-
- if (nl_open_tried)
- return;
- nl_open_tried = 1;
-
- DBG("KRT: Opening async netlink socket\n");
-
- fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (fd < 0)
- {
- log(L_ERR "Unable to open asynchronous rtnetlink socket: %m");
- return;
- }
-
- bzero(&sa, sizeof(sa));
- sa.nl_family = AF_NETLINK;
-#ifdef IPV6
- sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
-#else
- sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
-#endif
- if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
- {
- log(L_ERR "Unable to bind asynchronous rtnetlink socket: %m");
- return;
- }
-
- sk = nl_async_sk = sk_new(krt_pool);
- sk->type = SK_MAGIC;
- sk->rx_hook = nl_async_hook;
- sk->fd = fd;
- if (sk_open(sk))
- bug("Netlink: sk_open failed");
-
- if (!nl_async_rx_buffer)
- nl_async_rx_buffer = xmalloc(NL_RX_SIZE);
-}
-
-/*
- * Interface to the UNIX krt module
- */
-
-static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
-
-void
-krt_scan_preconfig(struct config *c UNUSED)
-{
- bzero(&nl_cf_table, sizeof(nl_cf_table));
-}
-
-void
-krt_scan_postconfig(struct krt_config *x)
-{
- int id = x->scan.table_id;
-
- if (nl_cf_table[id/8] & (1 << (id%8)))
- cf_error("Multiple kernel syncers defined for table #%d", id);
- nl_cf_table[id/8] |= (1 << (id%8));
-}
-
-void
-krt_scan_construct(struct krt_config *x)
-{
-#ifndef IPV6
- x->scan.table_id = RT_TABLE_MAIN;
-#else
- x->scan.table_id = 254;
-#endif
-}
-
-void
-krt_scan_start(struct krt_proto *p, int first)
-{
- init_list(&p->scan.temp_ifs);
- nl_table_map[KRT_CF->scan.table_id] = p;
- if (first)
- {
- nl_open();
- nl_open_async();
- }
-}
-
-void
-krt_scan_shutdown(struct krt_proto *p UNUSED, int last UNUSED)
-{
-}
-
-void
-krt_if_start(struct kif_proto *p UNUSED)
-{
- nl_open();
- nl_open_async();
-}
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/unix/krt-iface.c
^
|
@@ -1,233 +0,0 @@
-/*
- * BIRD -- Unix Interface Scanning and Syncing
- *
- * (c) 1998--2000 Martin Mares <mj@ucw.cz>
- * (c) 2004 Ondrej Filip <feela@network.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-
-#undef LOCAL_DEBUG
-
-#include "nest/bird.h"
-#include "nest/iface.h"
-#include "nest/route.h"
-#include "nest/protocol.h"
-#include "lib/timer.h"
-#include "lib/krt.h"
-#include "lib/string.h"
-
-#include "unix.h"
-
-int if_scan_sock = -1;
-
-static void
-scan_ifs(struct ifreq *r, int cnt)
-{
- struct iface i, *pi;
- struct ifa a;
- char *err, *colon;
- unsigned fl;
- ip_addr netmask;
- int l, scope;
- sockaddr *sa;
-
- if_start_update();
- for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
- {
- int sec = 0;
- bzero(&i, sizeof(i));
- bzero(&a, sizeof(a));
- if (colon = strchr(r->ifr_name, ':'))
- {
- /* It's an alias -- let's interpret it as a secondary interface address */
- sec = 1;
- *colon = 0;
- }
- strncpy(i.name, r->ifr_name, sizeof(i.name) - 1);
-
- if(ioctl(if_scan_sock, SIOCGIFADDR,r)<0) continue;
-
- get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL, 1);
- if (ipa_nonzero(a.ip))
- {
- l = ipa_classify(a.ip);
- if (l < 0 || !(l & IADDR_HOST))
- {
- log(L_ERR "%s: Invalid interface address", i.name);
- a.ip = IPA_NONE;
- }
- else
- {
- a.scope = l & IADDR_SCOPE_MASK;
- if (a.scope == SCOPE_HOST)
- i.flags |= IF_LOOPBACK | IF_IGNORE;
- }
- }
-
- if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0)
- {
- err = "SIOCGIFFLAGS";
- faulty:
- log(L_ERR "%s(%s): %m", err, i.name);
- bad:
- i.flags = (i.flags & ~IF_ADMIN_UP) | IF_SHUTDOWN;
- continue;
- }
- fl = r->ifr_flags;
- if (fl & IFF_UP)
- i.flags |= IF_ADMIN_UP;
-
- if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0)
- { err = "SIOCGIFNETMASK"; goto faulty; }
- get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &netmask, NULL, 0);
- l = ipa_mklen(netmask);
- if (l < 0)
- {
- log(L_ERR "%s: Invalid netmask (%x)", i.name, netmask);
- goto bad;
- }
- a.pxlen = l;
-
- if (fl & IFF_POINTOPOINT)
- {
- a.flags |= IA_PEER;
- if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
- { err = "SIOCGIFDSTADDR"; goto faulty; }
- get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL, 1);
- a.prefix = a.opposite;
- a.pxlen = BITS_PER_IP_ADDRESS;
- }
- else
- a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen));
- if (fl & IFF_LOOPBACK)
- i.flags |= IF_LOOPBACK | IF_IGNORE;
- if (1
-#ifndef CONFIG_ALL_MULTICAST
- && (fl & IFF_MULTICAST)
-#endif
-#ifndef CONFIG_UNNUM_MULTICAST
- && !(a.flags & IA_PEER)
-#endif
- )
- i.flags |= IF_MULTICAST;
-
- scope = ipa_classify(a.ip);
- if (scope < 0)
- {
- log(L_ERR "%s: Invalid address", i.name);
- goto bad;
- }
- a.scope = scope & IADDR_SCOPE_MASK;
-
- if (a.pxlen < 32)
- {
- a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen)));
- if (ipa_equal(a.ip, a.prefix) || ipa_equal(a.ip, a.brd))
- {
- log(L_ERR "%s: Using network or broadcast address for interface", i.name);
- goto bad;
- }
- if (fl & IFF_BROADCAST)
- i.flags |= IF_BROADCAST;
- if (a.pxlen < 30)
- i.flags |= IF_MULTIACCESS;
- if (a.pxlen == 30)
- ifa.opposite = ipa_opposite_m2(ifa.ip);
- if (a.pxlen == 31)
- ifa.opposite = ipa_opposite_m1(ifa.ip);
- }
- else
- a.brd = a.opposite;
- a.scope = SCOPE_UNIVERSE;
-
- if (ioctl(if_scan_sock, SIOCGIFMTU, r) < 0)
- { err = "SIOCGIFMTU"; goto faulty; }
- i.mtu = r->ifr_mtu;
-
-#ifdef SIOCGIFINDEX
- if (ioctl(if_scan_sock, SIOCGIFINDEX, r) >= 0)
- i.index = r->ifr_ifindex;
- else if (errno != EINVAL)
- DBG("SIOCGIFINDEX failed: %m\n");
- else /* defined, but not supported by the kernel */
-#endif
- /*
- * The kernel doesn't give us real ifindices, but we still need them
- * at least for OSPF unnumbered links. So let's make them up ourselves.
- */
- if (pi = if_find_by_name(i.name))
- i.index = pi->index;
- else
- {
- static int if_index_counter = 1;
- i.index = if_index_counter++;
- }
-
- pi = NULL;
- if (sec)
- {
- a.flags |= IA_SECONDARY;
- pi = if_find_by_index(i.index);
- }
- if (!pi)
- pi = if_update(&i);
- a.iface = pi;
- ifa_update(&a);
- }
- if_end_update();
-}
-
-void
-krt_if_scan(struct kif_proto *p)
-{
- struct ifconf ic;
- static int last_ifbuf_size = 4*sizeof(struct ifreq);
- int res;
-
- for(;;)
- {
- ic.ifc_buf = alloca(last_ifbuf_size);
- ic.ifc_len = last_ifbuf_size;
- res = ioctl(if_scan_sock, SIOCGIFCONF, &ic);
- if (res < 0 && errno != EFAULT)
- die("SIOCCGIFCONF: %m");
- if (res >= 0 && ic.ifc_len <= last_ifbuf_size)
- break;
- last_ifbuf_size *= 2;
- DBG("Increased ifconf buffer size to %d\n", last_ifbuf_size);
- }
- scan_ifs(ic.ifc_req, ic.ifc_len);
-}
-
-void
-krt_if_construct(struct kif_config *c)
-{
-}
-
-void
-krt_if_start(struct kif_proto *p)
-{
-}
-
-void
-krt_if_shutdown(struct kif_proto *p)
-{
-}
-
-void
-krt_if_io_init(void)
-{
- if_scan_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
- DBG("Using socket %d for interface and route scanning\n", if_scan_sock);
- if (if_scan_sock < 0)
- die("Cannot create scanning socket: %m");
-}
-
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/unix/krt-iface.h
^
|
@@ -1,23 +0,0 @@
-/*
- * BIRD -- Unix Kernel Interface Syncer
- *
- * (c) 1998--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_IFACE_H_
-#define _BIRD_KRT_IFACE_H_
-
-struct krt_if_params {
-};
-
-struct krt_if_status {
-};
-
-extern int if_scan_sock;
-
-static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
-static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { }
-
-#endif
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/unix/krt-set.c
^
|
@@ -1,111 +0,0 @@
-/*
- * BIRD -- Unix Routing Table Syncing
- *
- * (c) 1998--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/ioctl.h>
-#include <net/route.h>
-
-#undef LOCAL_DEBUG
-
-#include "nest/bird.h"
-#include "nest/iface.h"
-#include "nest/route.h"
-#include "nest/protocol.h"
-#include "lib/unix.h"
-#include "lib/krt.h"
-#include "lib/string.h"
-
-int
-krt_capable(rte *e)
-{
- rta *a = e->attrs;
-
-#ifdef CONFIG_AUTO_ROUTES
- if (a->source == RTS_DEVICE)
- return 0;
-#endif
- return
- a->cast == RTC_UNICAST &&
- (a->dest == RTD_ROUTER
- || a->dest == RTD_DEVICE
-#ifdef RTF_REJECT
- || a->dest == RTD_UNREACHABLE
-#endif
- );
-}
-
-static void
-krt_ioctl(int ioc, rte *e, char *name)
-{
- net *net = e->net;
- struct rtentry re;
- rta *a = e->attrs;
-
- bzero(&re, sizeof(re));
- fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0);
- fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0);
- re.rt_flags = RTF_UP;
- if (net->n.pxlen == 32)
- re.rt_flags |= RTF_HOST;
- switch (a->dest)
- {
- case RTD_ROUTER:
- fill_in_sockaddr((struct sockaddr_in *) &re.rt_gateway, a->gw, 0);
- re.rt_flags |= RTF_GATEWAY;
- break;
- case RTD_DEVICE:
- if (!a->iface)
- return;
- re.rt_dev = a->iface->name;
- break;
-#ifdef RTF_REJECT
- case RTD_UNREACHABLE:
- re.rt_flags |= RTF_REJECT;
- break;
-#endif
- default:
- bug("krt set: unknown flags, but not filtered");
- }
-
- if (ioctl(if_scan_sock, ioc, &re) < 0)
- log(L_ERR "%s(%I/%d): %m", name, net->n.prefix, net->n.pxlen);
-}
-
-void
-krt_set_notify(struct krt_proto *p, net *net, rte *new, rte *old)
-{
- if (old)
- {
- DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
- krt_ioctl(SIOCDELRT, old, "SIOCDELRT");
- }
- if (new)
- {
- DBG("krt_add_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
- krt_ioctl(SIOCADDRT, new, "SIOCADDRT");
- }
-}
-
-void
-krt_set_start(struct krt_proto *x, int first)
-{
- if (if_scan_sock < 0)
- bug("krt set: missing socket");
-}
-
-void
-krt_set_construct(struct krt_config *c)
-{
-}
-
-void
-krt_set_shutdown(struct krt_proto *x, int last)
-{
-}
|
[-]
[+]
|
Deleted |
bird-1.3.7.tar.bz2/sysdep/unix/krt-set.h
^
|
@@ -1,21 +0,0 @@
-/*
- * BIRD -- Unix Kernel Route Syncer -- Setting
- *
- * (c) 1998--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_KRT_SET_H_
-#define _BIRD_KRT_SET_H_
-
-struct krt_set_params {
-};
-
-struct krt_set_status {
-};
-
-static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
-static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { }
-
-#endif
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/ChangeLog
^
|
@@ -1,3 +1,358 @@
+commit 94e2f1c111721d6213ea65cac5c53036e38e3973
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Tue Aug 7 11:06:57 2012 +0200
+
+ NEWS and version update.
+
+commit c06de722ddf36f3d6aaabfd4ae9d74a3ea72bbf9
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Aug 6 11:09:13 2012 +0200
+
+ Some minor fixes.
+
+commit 5400c0e7f982757418a0aeb892459b52fbbcffc3
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Aug 6 02:42:24 2012 +0200
+
+ Fixes BGP subcode during global shutdown.
+
+commit bbcfd5a0485a8df9568d8da0fc524e272e3e7601
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Thu Jul 26 13:59:50 2012 +0200
+
+ Fixes default route in OSPF multiple area setting.
+
+commit 48cf5e84e6ed17578e4ad43c5ef54d6ff7d825c4
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Tue Jul 24 20:12:14 2012 +0200
+
+ Documentation update,
+
+commit 0e224d598579626e03d3727d5901ba2d654ac521
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Jul 22 12:35:04 2012 +0200
+
+ RDNSS and DNSSL documentation for RAdv.
+
+commit 36415e4b1dd769458cced44525ee74d26d15f9c6
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri Jul 20 19:56:57 2012 +0200
+
+ Allows to redefine master table.
+
+commit c4b76d7b19cf48ddbcbe913c22ef7f1e8429f5ea
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Jul 18 19:35:30 2012 +0200
+
+ Rename sk_new() to avoid name collision with OpenSSL.
+
+commit 4be266a9831799dcc2e67e83fc83d9db43828a64
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Jul 18 19:29:33 2012 +0200
+
+ Implements wildcard matching in config file include.
+
+ Also fixes some minor bugs in include.
+
+ Thanks Kelly Cochran for suggestion and draft patch.
+
+commit abced4a91495e27fe86b142bc1967cec53bab3dc
+Merge: fc06fb6 7617026
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Jul 16 14:44:45 2012 +0200
+
+ Merge branch 'rt-accepted'
+
+ Conflicts:
+
+ nest/config.Y
+ nest/rt-table.c
+ proto/bgp/bgp.c
+
+commit 761702644397886bd3c1be10fd55c01485b7c454
+Merge: 26822d8 553e405
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Jul 16 10:41:29 2012 +0200
+
+ Merge commit 'origin/rt-accepted' into rt-accepted
+
+commit 26822d8fe1376b2ffd902a3b5caa47f81a88e74e
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Jul 4 21:31:03 2012 +0200
+
+ Finalize RA_ACCEPTED handling.
+
+commit fc06fb62443c135773ee4c05ed83925cc47b046d
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sat Jul 7 10:40:00 2012 +0200
+
+ Implements RDNSS and DNSSL support for RAdv.
+
+commit 95127cbbb76e8870e029454a5313bc4b6ce69a4a
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon May 14 11:47:41 2012 +0200
+
+ Real broadcast mode for OSPFv2.
+
+commit 0ec031f7400fbacdd86b40ae1870c58715a7f108
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri May 11 18:52:59 2012 +0200
+
+ Allows to set instance ID for OSPFv3 interfaces.
+
+commit 47c447c42e0bfa1836d951d1e6c1a2236d39dcbb
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri May 4 23:05:47 2012 +0200
+
+ Minor cleanups.
+
+commit b7f3df79054aca327654c1fb4739c4ff02e59e6e
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri May 11 12:01:27 2012 +0200
+
+ Fixes a bug in RA_ACCEPTED handling.
+
+commit 95616c820248018f4999972cad315f2da60e4960
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri May 4 16:38:25 2012 +0200
+
+ Cleanup in sysdep KRT code, part 4.
+
+ Adding some files that was accidentally removed
+ (instead of moved) in cleanup part 2.
+
+commit 064e7be5cd4dffd564b4ea41ba6d843492a55c97
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri May 4 00:20:23 2012 +0200
+
+ History deduplication in birdc.
+
+commit e14bd38087ed8ef1945dd0a3878cc560478145f0
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Thu May 3 14:04:56 2012 +0200
+
+ Fixes flushing of device routes.
+
+commit ab188fb76d7822350724b182106a19995a73d719
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Thu May 3 12:25:15 2012 +0200
+
+ Implements build options to specify socket dir and suffix.
+
+commit 7a2c48dafce9420a23fd57408c31eecfc20c4fe0
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Apr 30 22:34:06 2012 +0200
+
+ Cleanup in sysdep KRT code, part 3.
+
+ Just one more renaming, old krt_set_notify() to krt_replace_rte().
+
+commit f1aceff59bbf942bc11c2e9a4c51e381c06f2b20
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Apr 30 22:21:52 2012 +0200
+
+ Cleanup in sysdep KRT code, part 2.
+
+ Remove support for historic Linux kernels,
+ merge krt-iface, krt-set and krt-scan stub headers.
+
+commit 396dfa9042305f62da1f56589c4b98fac57fc2f6
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Apr 30 15:31:32 2012 +0200
+
+ Cleanup in sysdep KRT code, part 1.
+
+ OS-dependent functions renamed to be more consistent,
+ prepared to merge krt-set and krt-scan headers.
+
+ Name changes:
+
+ struct krt_if_params -> struct kif_params
+ struct krt_if_status -> struct kif_status
+ struct krt_set/scan_params -> struct krt_params
+ struct krt_set/scan_status -> struct krt_status
+
+ krt_if_params_same -> kif_sys_reconfigure
+ krt_if_copy_params -> kif_sys_copy_config
+ krt_set/scan_params_same -> krt_sys_reconfigure
+ krt_set/scan_copy_params -> krt_sys_copy_config
+
+ krt_if_scan -> kif_do_scan
+ krt_set_notify -> krt_do_notify
+ krt_scan_fire -> krt_do_scan
+
+ krt_if_ -> kif_sys_
+ krt_scan_ -> krt_sys_
+ krt_set_ -> krt_sys_
+
+commit 182a78957d60a4c91c1ff8d1ff0f09b1b64b70ba
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Apr 29 01:35:52 2012 +0200
+
+ Allows some modifications of dest attribute in filters.
+
+commit bf42207332e8e502d636038f1ec44aaea6ec50e0
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sat Apr 28 13:03:48 2012 +0200
+
+ Changes keyword 'exceed' to 'action'.
+
+commit ab758e4fb205346946f2d828236bd23efc2a419e
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sat Apr 28 12:59:40 2012 +0200
+
+ Some fixes in route export limits.
+
+commit d494df63ac3061accdff348511a565c021411b28
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri Apr 27 00:04:51 2012 +0200
+
+ Some minor fixes.
+
+commit d9b77cc28115e5c1ef64c69722c9d1fd1392dcd1
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Tue Apr 24 23:39:57 2012 +0200
+
+ Implements generalized export limits.
+
+ And also fixes some minor bugs in limits.
+
+commit 3589546af4baa4d349409a318f8c9658dd11b3cc
+Merge: 7d0a31d cca9706
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Tue Apr 24 23:37:01 2012 +0200
+
+ Merge commit 'origin/master'
+
+commit cca970666a90af02eaeb6848bbfc3d5a2222fa21
+Author: Ondrej Filip <feela@network.cz>
+Date: Sun Apr 22 14:03:07 2012 +0200
+
+ Small typo in programmer's documentation.
+
+commit 7d0a31deed92971e274aa0314e12619f93c850c9
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sat Apr 21 21:05:36 2012 +0200
+
+ Fixes in generalized import limits.
+
+commit 334a0ed24d015e106558cc9eeef301c6f0d21aec
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri Apr 20 21:04:55 2012 +0200
+
+ Fixes missing device attributes when exporting routes to kernel.
+
+ Thanks to Howden Nick for the bugreport.
+
+commit 9b2b502be521b58a736f7b78644e89ee01b4418b
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri Apr 20 21:04:55 2012 +0200
+
+ Fixes missing device attributes when exporting routes to kernel.
+
+ Thanks to Howden Nick for the bugreport.
+
+commit f93e6f338e59e02b0cddea85e7d367948d9cf3f2
+Author: Ondrej Filip <feela@network.cz>
+Date: Thu Apr 19 17:14:16 2012 +0200
+
+ Small clean up in debug texts
+
+commit 553e4054609e7aa8dcb92849c92a6fea73354f0e
+Author: Ondrej Filip <feela@network.cz>
+Date: Thu Apr 19 17:12:13 2012 +0200
+
+ Small clean up in debug texts
+
+commit ebecb6f6a11bb418dd054cf12a2673ca0d9eac37
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Apr 15 15:28:29 2012 +0200
+
+ Implements generalized import hooks.
+
+ Thanks to Alexander V. Chernikov for the original patch.
+
+commit 3e17e380598b9a512bb369f51a4cf55da269f608
+Merge: 00a09f3 ae8b300
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Apr 15 15:17:03 2012 +0200
+
+ Merge branch 'master' into rt-accepted
+
+commit ae8b300164a975597f9b6caea0b205af2e4db30b
+Merge: d360f12 ed7c4b0
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Apr 15 15:15:05 2012 +0200
+
+ Merge commit 'origin/master'
+
+commit d360f129e393298ff3e5309ec06a3baf170784fb
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Apr 15 15:13:12 2012 +0200
+
+ Fix static protocol w.r.t. some recent changes in protocol ahooks.
+
+commit 00a09f3c367e79297f827b52ec5f16842db1ac4e
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Apr 15 15:07:58 2012 +0200
+
+ Implement RA_ACCEPTED mode of route propagation.
+
+commit ed7c4b0cd530126b9a794f817f5d1d93556a1bce
+Author: Ondrej Filip <feela@network.cz>
+Date: Mon Apr 9 14:19:28 2012 +0200
+
+ Small bugfix in error message related to reconfiguration.
+
+commit bf2abe2f515d7b7aaed5fb4f37af82169adcd2f2
+Merge: fb829de c0adf7e
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri Mar 30 11:04:12 2012 +0200
+
+ Merge branch 'soon'
+
+ Conflicts:
+
+ nest/proto.c
+ nest/rt-table.c
+
+commit fb829de69052755a31d76d73e17525d050e5ff4d
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Mar 28 18:40:04 2012 +0200
+
+ Fixes responsiveness for protocol shutdown.
+
+ When a protocol went down, all its routes were flushed in one step, that
+ may block BIRD for too much time. The patch fixes that by limiting
+ maximum number of routes flushed in one step.
+
+commit cb3cf95859d81c711337738f004675f43c8bbb0e
+Merge: c9df01d 16fc65a
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Mar 25 20:59:13 2012 +0200
+
+ Merge commit 'origin/master'
+
+commit c9df01d3215379c0463dd2a3b0c9b1700d6e2ac3
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Mar 25 19:44:14 2012 +0200
+
+ Fixes several minor bugs in kernel syncer.
+
+commit 9ba2798c65c02254ec000ab03a76fbbaae1ddc97
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri Mar 23 01:17:02 2012 +0100
+
+ Adds krt_metric linux route attribute.
+
+commit 72aed1a00ba9e18116d6fd907f7e1a36d0a0a583
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri Mar 23 00:26:26 2012 +0100
+
+ Adds krt_source route attribute.
+
+ Thanks Jeremie Dimino for the original patch.
+
commit 16fc65acc536d3788efe4c0554a2f52699fedc7f
Author: Ondrej Filip <feela@network.cz>
Date: Thu Mar 22 14:52:40 2012 +0100
@@ -129,6 +484,23 @@
Thanks to Alexander Shikoff for the bugreport.
+commit c0adf7e9fc0bb920175a639c6f56ed7b4190f3e4
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Thu Mar 15 11:58:08 2012 +0100
+
+ Better support for multitable protocols.
+
+ The nest-protocol interaction is changed to better handle multitable
+ protocols. Multitable protocols now declare that by 'multitable' field,
+ which tells nest that a protocol handles things related to proto-rtable
+ interaction (table locking, announce hook adding, reconfiguration of
+ filters) itself.
+
+ Filters and stats are moved to announce hooks, a protocol could have
+ different filters and stats to different tables.
+
+ The patch is based on one from Alexander V. Chernikov, thanks.
+
commit 46c1a583a5c1ea81e8d8f372bd7f614506a63938
Author: Ondrej Zajicek <santiago@crfreenet.org>
Date: Fri Feb 3 11:50:51 2012 +0100
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/NEWS
^
|
@@ -1,3 +1,12 @@
+Version 1.3.8 (2012-08-07)
+ o Generalized import and export route limits.
+ o RDNSS and DNSSL support for RAdv.
+ o Include in config file support wildcards.
+ o History deduplication in BIRD client.
+ o New route attributes krt_source, krt_metric.
+ o Different instance ID support for OSPFv3.
+ o Real broadcast mode for OSPFv2.
+ o Several minor bugfixes.
Version 1.3.7 (2012-03-22)
o Route Origin Authorization basics.
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/aclocal.m4
^
|
@@ -133,23 +133,6 @@
fi
])
-AC_DEFUN(BIRD_CHECK_LINUX_VERSION,
-[AC_CACHE_CHECK([Linux kernel version], bird_cv_sys_linux_version, [
-AC_REQUIRE_CPP()dnl
-cat > conftest.$ac_ext <<EOF
-[#]line __oline__ "configure"
-#include "confdefs.h"
-#include <linux/version.h>
-VERSION: UTS_RELEASE
-EOF
-bird_cv_sys_linux_version=`eval "$ac_cpp conftest.$ac_ext" 2>&AC_FD_CC | sed '/^VERSION/!d;s/^VERSION: "//;s/".*//'`
-rm -rf conftest*
-if test -z "$bird_cv_sys_linux_version" ; then
- AC_MSG_RESULT([unknown])
- AC_MSG_ERROR([Cannot determine kernel version])
-fi
-])])
-
AC_DEFUN(BIRD_CHECK_GCC_OPTIONS,
[AC_CACHE_VAL(bird_cv_c_option_no_pointer_sign, [
cat >conftest.c <<EOF
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/client/client.c
^
|
@@ -135,6 +135,14 @@
num_lines = 2;
}
+static void
+add_history_dedup(char *cmd)
+{
+ /* Add history line if it differs from the last one */
+ HIST_ENTRY *he = history_get(history_length);
+ if (!he || strcmp(he->line, cmd))
+ add_history(cmd);
+}
static void
got_line(char *cmd_buffer)
@@ -151,7 +159,7 @@
cmd = cmd_expand(cmd_buffer);
if (cmd)
{
- add_history(cmd);
+ add_history_dedup(cmd);
if (!handle_internal_command(cmd))
submit_server_command(cmd);
@@ -159,7 +167,7 @@
free(cmd);
}
else
- add_history(cmd_buffer);
+ add_history_dedup(cmd_buffer);
}
free(cmd_buffer);
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/conf/cf-lex.l
^
|
@@ -31,6 +31,12 @@
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
+#include <libgen.h>
+#include <glob.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#define PARSER 1
@@ -64,27 +70,23 @@
};
static struct sym_scope *conf_this_scope;
-#define MAX_INCLUDE_DEPTH 5
-
-static struct include_file_stack *ifs_head;
-static int ifs_depth;
-
static int cf_hash(byte *c);
static struct symbol *cf_find_sym(byte *c, unsigned int h0);
linpool *cfg_mem;
int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
-int (*cf_open_hook)(char *filename);
struct include_file_stack *ifs;
+static struct include_file_stack *ifs_head;
-#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max, ifs->conf_fd);
+#define MAX_INCLUDE_DEPTH 8
+
+#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max, ifs->fd);
#define YY_NO_UNPUT
#define YY_FATAL_ERROR(msg) cf_error(msg)
-static void new_include(void);
+static void cf_include(char *arg, int alen);
static int check_eof(void);
-static struct include_file_stack *new_stack(struct include_file_stack *old);
%}
@@ -103,7 +105,23 @@
include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
%%
-{include} { if(cf_open_hook) new_include(); }
+{include} {
+ char *start, *end;
+
+ if (!ifs->depth)
+ cf_error("Include not allowed in CLI");
+
+ start = strchr(yytext, '"');
+ start++;
+
+ end = strchr(start, '"');
+ *end = 0;
+
+ if (start == end)
+ cf_error("Include with empty argument");
+
+ cf_include(start, end-start);
+}
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
#ifdef IPV6
@@ -200,11 +218,11 @@
["][^"\n]*\n cf_error("Unterminated string");
-<INITIAL,COMMENT><<EOF>> { if(check_eof()) return END; }
+<INITIAL,COMMENT><<EOF>> { if (check_eof()) return END; }
{WHITE}+
-\n ifs->conf_lino++;
+\n ifs->lino++;
# BEGIN(COMMENT);
@@ -213,14 +231,14 @@
. cf_error("Unknown character");
<COMMENT>\n {
- ifs->conf_lino++;
+ ifs->lino++;
BEGIN(INITIAL);
}
<COMMENT>.
<CCOMM>\*\/ BEGIN(INITIAL);
-<CCOMM>\n ifs->conf_lino++;
+<CCOMM>\n ifs->lino++;
<CCOMM>\/\* cf_error("Comment nesting not supported");
<CCOMM><<EOF>> cf_error("Unterminated comment");
<CCOMM>.
@@ -246,48 +264,141 @@
return h;
}
-/* Open included file with properly swapped buffers */
+
+/*
+ * IFS stack - it contains structures needed for recursive processing
+ * of include in config files. On the top of the stack is a structure
+ * for currently processed file. Other structures are either for
+ * active files interrupted because of include directive (these have
+ * fd and flex buffer) or for inactive files scheduled to be processed
+ * later (when parent requested including of several files by wildcard
+ * match - these do not have fd and flex buffer yet).
+ *
+ * FIXME: Most of these ifs and include functions are really sysdep/unix.
+ *
+ * FIXME: Resources (fd, flex buffers and glob data) in IFS stack
+ * are not freed when cf_error() is called.
+ */
+
+static struct include_file_stack *
+push_ifs(struct include_file_stack *old)
+{
+ struct include_file_stack *ret;
+ ret = cfg_allocz(sizeof(struct include_file_stack));
+ ret->lino = 1;
+ ret->prev = old;
+ return ret;
+}
+
+static struct include_file_stack *
+pop_ifs(struct include_file_stack *old)
+{
+ yy_delete_buffer(old->buffer);
+ close(old->fd);
+ return old->prev;
+}
+
+static void
+enter_ifs(struct include_file_stack *new)
+{
+ if (!new->buffer)
+ {
+ new->fd = open(new->file_name, O_RDONLY);
+ if (new->fd < 0)
+ {
+ ifs = ifs->up;
+ cf_error("Unable to open included file %s: %m", new->file_name);
+ }
+
+ new->buffer = yy_create_buffer(NULL, YY_BUF_SIZE);
+ }
+
+ yy_switch_to_buffer(new->buffer);
+}
+
static void
-new_include(void)
+cf_include(char *arg, int alen)
{
- char *fname, *p = NULL;
+ struct include_file_stack *base_ifs = ifs;
+ int new_depth, rv, i;
+ char *patt;
+ glob_t g;
+
+ new_depth = ifs->depth + 1;
+ if (new_depth > MAX_INCLUDE_DEPTH)
+ cf_error("Max include depth reached");
+
+ /* expand arg to properly handle relative filenames */
+ if (*arg != '/')
+ {
+ int dlen = strlen(ifs->file_name);
+ char *dir = alloca(dlen + 1);
+ patt = alloca(dlen + alen + 2);
+ memcpy(dir, ifs->file_name, dlen + 1);
+ sprintf(patt, "%s/%s", dirname(dir), arg);
+ }
+ else
+ patt = arg;
- if ((fname = strchr(yytext, '"')) != NULL) {
+ /* Skip globbing if there are no wildcards, mainly to get proper
+ response when the included config file is missing */
+ if (!strpbrk(arg, "?*["))
+ {
+ ifs = push_ifs(ifs);
+ ifs->file_name = cfg_strdup(patt);
+ ifs->depth = new_depth;
+ ifs->up = base_ifs;
+ enter_ifs(ifs);
+ return;
+ }
- if ((p = strchr(++fname, '"')) != NULL) *p = '\0';
+ /* Expand the pattern */
+ rv = glob(patt, GLOB_ERR | GLOB_NOESCAPE, NULL, &g);
+ if (rv == GLOB_ABORTED)
+ cf_error("Unable to match pattern %s: %m", patt);
+ if ((rv != 0) || (g.gl_pathc <= 0))
+ return;
+
+ /*
+ * Now we put all found files to ifs stack in reverse order, they
+ * will be activated and processed in order as ifs stack is popped
+ * by pop_ifs() and enter_ifs() in check_eof().
+ */
+ for(i = g.gl_pathc - 1; i >= 0; i--)
+ {
+ char *fname = g.gl_pathv[i];
+ struct stat fs;
- if (ifs_depth >= MAX_INCLUDE_DEPTH)
- cf_error("Max include depth reached.");
+ if (stat(fname, &fs) < 0)
+ cf_error("Unable to stat included file %s: %m", fname);
- /* Save current stack */
- ifs->stack = YY_CURRENT_BUFFER;
- /* Prepare new stack */
- ifs->next = new_stack(ifs);
- ifs = ifs->next;
- strcpy(ifs->conf_fname, fname); /* XXX: strlcpy should be here */
- ifs->conf_fd = cf_open_hook(fname);
+ if (fs.st_mode & S_IFDIR)
+ continue;
- yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
- }
+ /* Prepare new stack item */
+ ifs = push_ifs(ifs);
+ ifs->file_name = cfg_strdup(fname);
+ ifs->depth = new_depth;
+ ifs->up = base_ifs;
+ }
+
+ globfree(&g);
+ enter_ifs(ifs);
}
static int
check_eof(void)
{
- if (ifs == ifs_head) {
- /* EOF in main config file */
- ifs->conf_lino = 1;
- return 1;
- }
+ if (ifs == ifs_head)
+ {
+ /* EOF in main config file */
+ ifs->lino = 1; /* Why this? */
+ return 1;
+ }
- ifs_depth--;
- close(ifs->conf_fd);
- ifs = ifs->prev;
- ifs->next = NULL;
-
- yy_delete_buffer(YY_CURRENT_BUFFER);
- yy_switch_to_buffer(ifs->stack);
- return 0;
+ ifs = pop_ifs(ifs);
+ enter_ifs(ifs);
+ return 0;
}
static struct symbol *
@@ -415,16 +526,6 @@
kw_hash_inited = 1;
}
-static struct include_file_stack *
-new_stack(struct include_file_stack *old)
-{
- struct include_file_stack *ret;
- ret = cfg_allocz(sizeof(struct include_file_stack));
- ret->conf_lino = 1;
- ret->prev = old;
- return ret;
-}
-
/**
* cf_lex_init - initialize the lexer
* @is_cli: true if we're going to parse CLI command, false for configuration
@@ -437,19 +538,23 @@
{
if (!kw_hash_inited)
cf_lex_init_kh();
- ifs_head = new_stack(NULL);
- ifs = ifs_head;
- ifs_depth = 0;
- if (!is_cli) {
- ifs->conf_fd = c->file_fd;
- ifs_depth = 1;
- strcpy(ifs->conf_fname, c->file_name);
- }
+
+ ifs_head = ifs = push_ifs(NULL);
+ if (!is_cli)
+ {
+ ifs->file_name = c->file_name;
+ ifs->fd = c->file_fd;
+ ifs->depth = 1;
+ }
+
yyrestart(NULL);
+ ifs->buffer = YY_CURRENT_BUFFER;
+
if (is_cli)
BEGIN(CLI);
else
BEGIN(INITIAL);
+
conf_this_scope = cfg_allocz(sizeof(struct sym_scope));
conf_this_scope->active = 1;
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/conf/conf.c
^
|
@@ -357,8 +357,8 @@
if (bvsnprintf(buf, sizeof(buf), msg, args) < 0)
strcpy(buf, "<bug: error message too long>");
new_config->err_msg = cfg_strdup(buf);
- new_config->err_lino = ifs->conf_lino;
- new_config->err_file_name = ifs->conf_fname;
+ new_config->err_lino = ifs->lino;
+ new_config->err_file_name = ifs->file_name;
longjmp(conf_jmpbuf, 1);
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/conf/conf.h
^
|
@@ -12,7 +12,6 @@
#include "lib/resource.h"
#include "lib/timer.h"
-#define BIRD_FNAME_MAX 255 /* Would be better to use some UNIX define */
/* Configuration structure */
@@ -91,7 +90,6 @@
/* Lexer */
extern int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
-extern int (*cf_open_hook)(char *filename);
struct symbol {
struct symbol *next;
@@ -117,12 +115,14 @@
#define SYM_VARIABLE 0x100 /* 0x100-0x1ff are variable types */
struct include_file_stack {
- void *stack; /* Internal lexer state */
- unsigned int conf_lino; /* Current file lineno (at include) */
- char conf_fname[BIRD_FNAME_MAX]; /* Current file name */
- int conf_fd; /* Current file descriptor */
- struct include_file_stack *prev;
- struct include_file_stack *next;
+ void *buffer; /* Internal lexer state */
+ char *file_name; /* File name */
+ int fd; /* File descriptor */
+ int lino; /* Current line num */
+ int depth; /* Include depth, 0 = cannot include */
+
+ struct include_file_stack *prev; /* Previous record in stack */
+ struct include_file_stack *up; /* Parent (who included this file) */
};
extern struct include_file_stack *ifs;
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/configure
^
|
@@ -594,7 +594,6 @@
ac_subst_vars='LTLIBOBJS
LIBOBJS
-SUFFIX6
CLIENT_LIBS
CLIENT
EGREP
@@ -622,6 +621,10 @@
LDFLAGS
CFLAGS
CC
+CONTROL_SOCKET
+CONFIG_FILE
+SUFFIX
+runtimedir
srcdir_rel_mf
exedir
objdir
@@ -673,9 +676,11 @@
enable_memcheck
enable_client
enable_ipv6
+with_suffix
with_sysconfig
with_protocols
with_sysinclude
+with_runtimedir
with_iproutedir
'
ac_precious_vars='build_alias
@@ -1311,9 +1316,11 @@
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-suffix=STRING use specified suffix for BIRD files (default: 6 for IPv6 version)
--with-sysconfig=FILE use specified BIRD system configuration file
--with-protocols=LIST include specified routing protocols (default: all)
--with-sysinclude=PATH search for system includes on specified place
+ --with-runtimedir=PATH path for runtime files (default: $(localstatedir)/run)
--with-iproutedir=PATH path to iproute2 config files (default: /etc/iproute2)
Some influential environment variables:
@@ -2278,6 +2285,12 @@
fi
+# Check whether --with-suffix was given.
+if test "${with_suffix+set}" = set; then :
+ withval=$with_suffix; given_suffix="yes"
+fi
+
+
# Check whether --with-sysconfig was given.
if test "${with_sysconfig+set}" = set; then :
withval=$with_sysconfig;
@@ -2298,6 +2311,14 @@
fi
+# Check whether --with-runtimedir was given.
+if test "${with_runtimedir+set}" = set; then :
+ withval=$with_runtimedir; runtimedir="$with_runtimedir"
+else
+ runtimedir="\$(localstatedir)/run"
+fi
+
+
# Check whether --with-iproutedir was given.
if test "${with_iproutedir+set}" = set; then :
withval=$with_iproutedir; given_iproutedir="yes"
@@ -2307,6 +2328,7 @@
+
if test "$srcdir" = . ; then
# Building in current directory => create obj directory holding all objects
objdir=obj
@@ -2329,20 +2351,36 @@
+
if test "$enable_ipv6" = yes ; then
ip=ipv6
- SUFFIX6=6
+ SUFFIX=6
all_protocols=bgp,ospf,pipe,radv,rip,static
else
ip=ipv4
- SUFFIX6=""
+ SUFFIX=""
all_protocols=bgp,ospf,pipe,rip,static
fi
+if test "$given_suffix" = yes ; then
+ SUFFIX="$with_suffix"
+fi
+
+
if test "$with_protocols" = all ; then
with_protocols="$all_protocols"
fi
+if test "$enable_debug" = yes ; then
+ CONFIG_FILE="bird$SUFFIX.conf"
+ CONTROL_SOCKET="bird$SUFFIX.ctl"
+else
+ CONFIG_FILE="\$(sysconfdir)/bird$SUFFIX.conf"
+ CONTROL_SOCKET="$runtimedir/bird$SUFFIX.ctl"
+fi
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -4306,64 +4344,11 @@
sysdesc=sysconfig
else
case "$ip:$host_os" in
- ipv4:linux*)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Linux kernel version" >&5
-$as_echo_n "checking Linux kernel version... " >&6; }
-if test "${bird_cv_sys_linux_version+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
-
-cat > conftest.$ac_ext <<EOF
-#line 4317 "configure"
-#include "confdefs.h"
-#include <linux/version.h>
-VERSION: UTS_RELEASE
-EOF
-bird_cv_sys_linux_version=`eval "$ac_cpp conftest.$ac_ext" 2>&5 | sed '/^VERSION/!d;s/^VERSION: "//;s/".*//'`
-rm -rf conftest*
-if test -z "$bird_cv_sys_linux_version" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5
-$as_echo "unknown" >&6; }
- as_fn_error $? "Cannot determine kernel version" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $bird_cv_sys_linux_version" >&5
-$as_echo "$bird_cv_sys_linux_version" >&6; }
+ ipv6:linux*) sysdesc=linux-v6
default_iproutedir="/etc/iproute2"
- case $bird_cv_sys_linux_version in
- 1.*|2.0.*) sysdesc=linux-20 ;;
- *) sysdesc=linux-22 ;;
- esac
;;
- ipv6:linux*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking Linux kernel version" >&5
-$as_echo_n "checking Linux kernel version... " >&6; }
-if test "${bird_cv_sys_linux_version+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
-
-cat > conftest.$ac_ext <<EOF
-#line 4346 "configure"
-#include "confdefs.h"
-#include <linux/version.h>
-VERSION: UTS_RELEASE
-EOF
-bird_cv_sys_linux_version=`eval "$ac_cpp conftest.$ac_ext" 2>&5 | sed '/^VERSION/!d;s/^VERSION: "//;s/".*//'`
-rm -rf conftest*
-if test -z "$bird_cv_sys_linux_version" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5
-$as_echo "unknown" >&6; }
- as_fn_error $? "Cannot determine kernel version" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $bird_cv_sys_linux_version" >&5
-$as_echo "$bird_cv_sys_linux_version" >&6; }
+ ipv4:linux*) sysdesc=linux
default_iproutedir="/etc/iproute2"
- case $bird_cv_sys_linux_version in
- 1.*|2.0.*) as_fn_error $? "This version of Linux doesn't support IPv6." "$LINENO" 5 ;;
- *) sysdesc=linux-v6 ;;
- esac
;;
ipv6:netbsd*) sysdesc=bsd-v6
CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
@@ -4439,7 +4424,7 @@
case $sysdesc in
- */linux-22*|*/linux-v6*)
+ */linux*|*/linux-v6*)
ac_fn_c_check_header_compile "$LINENO" "linux/rtnetlink.h" "ac_cv_header_linux_rtnetlink_h" "
#include <asm/types.h>
#include <sys/socket.h>
@@ -4455,6 +4440,7 @@
;;
esac
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
if test "${ac_cv_path_GREP+set}" = set; then :
@@ -5787,7 +5773,6 @@
-
mkdir -p $objdir/sysdep
ac_config_headers="$ac_config_headers $objdir/sysdep/autoconf.h:sysdep/autoconf.h.in"
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/configure.in
^
|
@@ -6,17 +6,20 @@
AC_INIT(conf/confbase.Y)
AC_CONFIG_AUX_DIR(tools)
-AC_ARG_ENABLE(debug,[ --enable-debug enable internal debugging routines (default: disabled)],,enable_debug=no)
-AC_ARG_ENABLE(memcheck,[ --enable-memcheck check memory allocations when debugging (default: enabled)],,enable_memcheck=yes)
-AC_ARG_ENABLE(client,[ --enable-client enable building of BIRD client (default: enabled)],,enable_client=yes)
-AC_ARG_ENABLE(ipv6,[ --enable-ipv6 enable building of IPv6 version (default: disabled)],,enable_ipv6=no)
-AC_ARG_WITH(sysconfig,[ --with-sysconfig=FILE use specified BIRD system configuration file])
-AC_ARG_WITH(protocols,[ --with-protocols=LIST include specified routing protocols (default: all)],,[with_protocols="all"])
-AC_ARG_WITH(sysinclude,[ --with-sysinclude=PATH search for system includes on specified place])
-AC_ARG_WITH(iproutedir,[ --with-iproutedir=PATH path to iproute2 config files (default: /etc/iproute2)],[given_iproutedir="yes"])
-AC_ARG_VAR([FLEX], [location of the Flex program])
-AC_ARG_VAR([BISON], [location of the Bison program])
-AC_ARG_VAR([M4], [location of the M4 program])
+AC_ARG_ENABLE(debug, [ --enable-debug enable internal debugging routines (default: disabled)],,enable_debug=no)
+AC_ARG_ENABLE(memcheck, [ --enable-memcheck check memory allocations when debugging (default: enabled)],,enable_memcheck=yes)
+AC_ARG_ENABLE(client, [ --enable-client enable building of BIRD client (default: enabled)],,enable_client=yes)
+AC_ARG_ENABLE(ipv6, [ --enable-ipv6 enable building of IPv6 version (default: disabled)],,enable_ipv6=no)
+AC_ARG_WITH(suffix, [ --with-suffix=STRING use specified suffix for BIRD files (default: 6 for IPv6 version)],[given_suffix="yes"])
+AC_ARG_WITH(sysconfig, [ --with-sysconfig=FILE use specified BIRD system configuration file])
+AC_ARG_WITH(protocols, [ --with-protocols=LIST include specified routing protocols (default: all)],,[with_protocols="all"])
+AC_ARG_WITH(sysinclude, [ --with-sysinclude=PATH search for system includes on specified place])
+AC_ARG_WITH(runtimedir, [ --with-runtimedir=PATH path for runtime files (default: $(localstatedir)/run)],[runtimedir="$with_runtimedir"],[runtimedir="\$(localstatedir)/run"])
+AC_ARG_WITH(iproutedir, [ --with-iproutedir=PATH path to iproute2 config files (default: /etc/iproute2)],[given_iproutedir="yes"])
+AC_ARG_VAR([FLEX], [location of the Flex program])
+AC_ARG_VAR([BISON], [location of the Bison program])
+AC_ARG_VAR([M4], [location of the M4 program])
+
if test "$srcdir" = . ; then
# Building in current directory => create obj directory holding all objects
@@ -39,21 +42,37 @@
AC_SUBST(objdir)
AC_SUBST(exedir)
AC_SUBST(srcdir_rel_mf)
+AC_SUBST(runtimedir)
if test "$enable_ipv6" = yes ; then
ip=ipv6
- SUFFIX6=6
+ SUFFIX=6
all_protocols=bgp,ospf,pipe,radv,rip,static
else
ip=ipv4
- SUFFIX6=""
+ SUFFIX=""
all_protocols=bgp,ospf,pipe,rip,static
fi
+if test "$given_suffix" = yes ; then
+ SUFFIX="$with_suffix"
+fi
+AC_SUBST(SUFFIX)
+
if test "$with_protocols" = all ; then
with_protocols="$all_protocols"
fi
+if test "$enable_debug" = yes ; then
+ CONFIG_FILE="bird$SUFFIX.conf"
+ CONTROL_SOCKET="bird$SUFFIX.ctl"
+else
+ CONFIG_FILE="\$(sysconfdir)/bird$SUFFIX.conf"
+ CONTROL_SOCKET="$runtimedir/bird$SUFFIX.ctl"
+fi
+AC_SUBST(CONFIG_FILE)
+AC_SUBST(CONTROL_SOCKET)
+
AC_SEARCH_LIBS(clock_gettime,[c rt posix4])
AC_CANONICAL_HOST
@@ -105,19 +124,11 @@
sysdesc=sysconfig
else
case "$ip:$host_os" in
- ipv4:linux*) BIRD_CHECK_LINUX_VERSION
+ ipv6:linux*) sysdesc=linux-v6
default_iproutedir="/etc/iproute2"
- case $bird_cv_sys_linux_version in
- 1.*|2.0.*) sysdesc=linux-20 ;;
- *) sysdesc=linux-22 ;;
- esac
;;
- ipv6:linux*) BIRD_CHECK_LINUX_VERSION
+ ipv4:linux*) sysdesc=linux
default_iproutedir="/etc/iproute2"
- case $bird_cv_sys_linux_version in
- 1.*|2.0.*) AC_MSG_ERROR([This version of Linux doesn't support IPv6.]) ;;
- *) sysdesc=linux-v6 ;;
- esac
;;
ipv6:netbsd*) sysdesc=bsd-v6
CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
@@ -180,7 +191,7 @@
AC_SUBST(protocols)
case $sysdesc in
- */linux-22*|*/linux-v6*)
+ */linux*|*/linux-v6*)
AC_CHECK_HEADER(linux/rtnetlink.h,,[AC_MSG_ERROR([Appropriate version of Linux kernel headers not found.])],[
#include <asm/types.h>
#include <sys/socket.h>
@@ -233,7 +244,6 @@
fi
AC_SUBST(CLIENT)
AC_SUBST(CLIENT_LIBS)
-AC_SUBST(SUFFIX6)
mkdir -p $objdir/sysdep
AC_CONFIG_HEADERS([$objdir/sysdep/autoconf.h:sysdep/autoconf.h.in])
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/doc/bird-2.html
^
|
@@ -45,7 +45,27 @@
When the routing table gets a route from a protocol, it recalculates
the selected route and broadcasts it to all protocols connected to
the table. The protocols typically send the update to other routers
-in the network.
+in the network. Note that although most protocols are interested
+in receiving just selected routes, some protocols (e.g. the <CODE>Pipe</CODE>
+protocol) receive and process all entries in routing tables (accepted
+by filters).
+<P>
+<P>
+<A NAME="dsc-sorted"></A> Usually, a routing table just chooses a
+selected route from a list of entries for one network. But if the
+<CODE>sorted</CODE> option is activated, these lists of entries are kept
+completely sorted (according to preference or some protocol-dependent
+metric).
+<P>This is needed for some features of some protocols
+(e.g. <CODE>secondary</CODE> option of BGP protocol, which allows to accept
+not just a selected route, but the first route (in the sorted list)
+that is accepted by filters), but it is incompatible with some other
+features (e.g. <CODE>deterministic med</CODE> option of BGP protocol, which
+activates a way of choosing selected route that cannot be described
+using comparison and ordering). Minor advantage is that routes are
+shown sorted in <CODE>show route</CODE>, minor disadvantage is that it is
+slightly more computationally expensive.
+<P>
<P>
<HR>
<A HREF="bird-3.html">Next</A>
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/doc/bird-3.html
^
|
@@ -141,11 +141,14 @@
defaults are here for a compatibility with older versions
and might change in the future.
<P>
-<DT><CODE>table <I>name</I></CODE><DD><P>Create a new routing table. The default
-routing table is created implicitly, other routing tables have
-to be added by this command.
+<DT><CODE>table <I>name</I> [sorted]</CODE><DD><P>Create a new routing table. The default routing table is
+created implicitly, other routing tables have to be added by
+this command. Option <CODE>sorted</CODE> can be used to enable
+sorting of routes, see
+<A HREF="bird-2.html#dsc-sorted">sorted table</A>
+description for details.
<P>
-<DT><CODE>roa table [ { roa table options ... } ] <I>name</I></CODE><DD><P>Create a new ROA (Route Origin Authorization) table. ROA
+<DT><CODE>roa table <I>name</I> [ { roa table options ... } ]</CODE><DD><P>Create a new ROA (Route Origin Authorization) table. ROA
tables can be used to validate route origination of BGP
routes. A ROA table contains ROA entries, each consist of a
network prefix, a max prefix length and an AS number. A ROA
@@ -208,10 +211,34 @@
to override global router id for a given protocol. Default:
uses global router id.
<P>
-<DT><CODE>import all | none | filter <I>name</I> | filter { <I>filter commands</I> } | where <I>filter expression</I></CODE><DD><P>Specify a filter to be used for filtering routes coming from the protocol to the routing table. <CODE>all</CODE> is shorthand for <CODE>where true</CODE> and <CODE>none</CODE> is shorthand for <CODE>where false</CODE>. Default: <CODE>all</CODE>.
+<DT><CODE>import all | none | filter <I>name</I> | filter { <I>filter commands</I> } | where <I>filter expression</I></CODE><DD><P>Specify a filter to be used for filtering routes coming from
+the protocol to the routing table. <CODE>all</CODE> is shorthand for
+<CODE>where true</CODE> and <CODE>none</CODE> is shorthand for
+<CODE>where false</CODE>. Default: <CODE>all</CODE>.
<P>
<DT><CODE>export <I>filter</I></CODE><DD><P>This is similar to the <CODE>import</CODE> keyword, except that it
-works in the direction from the routing table to the protocol. Default: <CODE>none</CODE>.
+works in the direction from the routing table to the protocol.
+Default: <CODE>none</CODE>.
+<P>
+<DT><CODE>import limit <I>number</I> [action warn | block | restart | disable]</CODE><DD><P>Specify an import route limit (a maximum number of routes
+imported from the protocol) and optionally the action to be
+taken when the limit is hit. Warn action just prints warning
+log message. Block action ignores new routes coming from the
+protocol. Restart and disable actions shut the protocol down
+like appropriate commands. Disable is the default action if an
+action is not explicitly specified. Note that limits are reset
+during protocol reconfigure, reload or restart.
+Default: <CODE>none</CODE>.
+<P>
+<DT><CODE>export limit <I>number</I> [action warn | block | restart | disable]</CODE><DD><P>Specify an export route limit, works similarly to
+the <CODE>import limit</CODE> option, but for the routes exported
+to the protocol. This option is experimental, there are some
+problems in details of its behavior -- the number of exported
+routes can temporarily exceed the limit without triggering it
+during protocol reload, exported routes counter ignores route
+blocking and block action also blocks route updates of already
+accepted routes -- and these details will probably change in
+the future. Default: <CODE>none</CODE>.
<P>
<DT><CODE>description "<I>text</I>"</CODE><DD><P>This is an optional
description of the protocol. It is displayed as a part of the
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/doc/bird-5.html
^
|
@@ -361,7 +361,16 @@
be used in the future for broadcast, multicast and anycast
routes). Read-only.
<P>
-<DT><CODE><I>enum</I> dest</CODE><DD><P>Type of destination the packets should be sent to (<CODE>RTD_ROUTER</CODE> for forwarding to a neighboring router, <CODE>RTD_DEVICE</CODE> for routing to a directly-connected network, <CODE>RTD_BLACKHOLE</CODE> for packets to be silently discarded, <CODE>RTD_UNREACHABLE</CODE>, <CODE>RTD_PROHIBIT</CODE> for packets that should be returned with ICMP host unreachable / ICMP administratively prohibited messages). Read-only.
+<DT><CODE><I>enum</I> dest</CODE><DD><P>Type of destination the packets should be sent to
+(<CODE>RTD_ROUTER</CODE> for forwarding to a neighboring router,
+<CODE>RTD_DEVICE</CODE> for routing to a directly-connected network,
+<CODE>RTD_MULTIPATH</CODE> for multipath destinations,
+<CODE>RTD_BLACKHOLE</CODE> for packets to be silently discarded,
+<CODE>RTD_UNREACHABLE</CODE>, <CODE>RTD_PROHIBIT</CODE> for packets that
+should be returned with ICMP host unreachable / ICMP
+administratively prohibited messages). Can be changed, but
+only to <CODE>RTD_BLACKHOLE</CODE>, <CODE>RTD_UNREACHABLE</CODE> or
+<CODE>RTD_PROHIBIT</CODE>.
<P>
<DT><CODE><I>int</I> igp_metric</CODE><DD><P>The optional attribute that can be used to specify a distance
to the network for routes that do not have a native protocol
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/doc/bird-6.html
^
|
@@ -181,8 +181,10 @@
mode is the behavior specified by the BGP standard. Direct
mode is simpler, does not require any routes in a routing
table, and was used in older versions of BIRD, but does not
-handle well nontrivial iBGP setups and multihop. Default:
-<CODE>direct</CODE> for singlehop eBGP, <CODE>recursive</CODE> otherwise.
+handle well nontrivial iBGP setups and multihop. Recursive
+mode is incompatible with
+<A HREF="bird-2.html#dsc-sorted">sorted tables</A>. Default: <CODE>direct</CODE> for singlehop eBGP,
+<CODE>recursive</CODE> otherwise.
<P>
<DT><CODE>igp table <I>name</I></CODE><DD><P>Specifies a table that is used
as an IGP routing table. Default: the same as the table BGP is
@@ -228,6 +230,16 @@
attributes to be transparent (for example does not prepend its AS number to
AS PATH attribute and keeps MED attribute). Default: disabled.
<P>
+<DT><CODE>secondary <I>switch</I></CODE><DD><P>Usually, if an import filter
+rejects a selected route, no other route is propagated for
+that network. This option allows to try the next route in
+order until one that is accepted is found or all routes for
+that network are rejected. This can be used for route servers
+that need to propagate different tables to each client but do
+not want to have these tables explicitly (to conserve memory).
+This option requires that the connected routing table is
+<A HREF="bird-2.html#dsc-sorted">sorted</A>. Default: off.
+<P>
<DT><CODE>enable route refresh <I>switch</I></CODE><DD><P>When BGP speaker
changes its import filter, it has to re-examine all routes
received from its neighbor against the new filter. As these
@@ -274,7 +286,8 @@
<P>
<DT><CODE>route limit <I>number</I></CODE><DD><P>The maximal number of routes
that may be imported from the protocol. If the route limit is
-exceeded, the connection is closed with error. Default: no limit.
+exceeded, the connection is closed with error. Limit is currently implemented as
+<CODE>import limit number exceed restart</CODE>. Default: no limit.
<P>
<DT><CODE>disable after error <I>switch</I></CODE><DD><P>When an error is encountered (either
locally or by the other side), disable the instance automatically
@@ -332,7 +345,10 @@
This option enables a different (and slower) algorithm
implementing proper RFC 4271 route selection, which is
deterministic. Alternative way how to get deterministic
-behavior is to use <CODE>med metric</CODE> option. Default: off.
+behavior is to use <CODE>med metric</CODE> option. This option is
+incompatible with
+<A HREF="bird-2.html#dsc-sorted">sorted tables</A>.
+Default: off.
<P>
<DT><CODE>igp metric <I>switch</I></CODE><DD><P>Enable comparison of internal
distances to boundary routers during best route selection. Default: on.
@@ -574,7 +590,7 @@
<P>Because the kernel protocol is partially integrated with the
connected routing table, there are two limitations - it is not
possible to connect more kernel protocols to the same routing table
-and changing route attributes (even the kernel ones) in an export
+and changing route destination/gateway in an export
filter of a kernel protocol does not work. Both limitations can be
overcome using another routing table and the pipe protocol.
<P>
@@ -610,6 +626,16 @@
We support these attributes:
<P>
<DL>
+<DT><CODE>int <CODE>krt_source</CODE></CODE><DD><P>The original source of the imported
+kernel route. The value is system-dependent. On Linux, it is
+a value of the protocol field of the route. See
+/etc/iproute2/rt_protos for common values. On BSD, it is
+based on STATIC and PROTOx flags. The attribute is read-only.
+<P>
+<DT><CODE>int <CODE>krt_metric</CODE></CODE><DD><P>The kernel metric of
+the route. When multiple same routes are in a kernel routing
+table, the Linux kernel chooses one with lower metric.
+<P>
<DT><CODE>ip <CODE>krt_prefsrc</CODE></CODE><DD><P>(Linux) The preferred source address.
Used in source address selection for outgoing packets. Have to
be one of IP addresses of the router.
@@ -730,7 +756,7 @@
summary <switch>;
cost <num>;
}
- interface <interface pattern> {
+ interface <interface pattern> [instance <num>] {
cost <num>;
stub <switch>;
hello <num>;
@@ -744,6 +770,7 @@
type [broadcast|bcast|pointopoint|ptp|
nonbroadcast|nbma|pointomultipoint|ptmp];
strict nonbroadcast <switch>;
+ real broadcast <switch>;
check link <switch>;
ecmp weight <num>;
authentication [none|simple|cryptographic];
@@ -760,7 +787,7 @@
<ip> eligible;
};
};
- virtual link <id> {
+ virtual link <id> [instance <num>] {
hello <num>;
retransmit <num>;
wait <num>;
@@ -865,13 +892,18 @@
subnetworks of given stub network are suppressed. This might
be used, for example, to aggregate generated stub networks.
<P>
-<DT><CODE>interface <I>pattern</I></CODE><DD><P>Defines that the specified interfaces belong to the area being defined.
+<DT><CODE>interface <I>pattern</I> [instance <I>num</I>]</CODE><DD><P>Defines that the specified interfaces belong to the area being defined.
See
<A HREF="bird-3.html#dsc-iface">interface</A> common option for detailed description.
-<P>
-<DT><CODE>virtual link <I>id</I></CODE><DD><P>Virtual link to router with the router id. Virtual link acts as a
-point-to-point interface belonging to backbone. The actual area is
-used as transport area. This item cannot be in the backbone.
+In OSPFv3, you can specify instance ID for that interface
+description, so it is possible to have several instances of
+that interface with different options or even in different areas.
+<P>
+<DT><CODE>virtual link <I>id</I> [instance <I>num</I>]</CODE><DD><P>Virtual link to router with the router id. Virtual link acts
+as a point-to-point interface belonging to backbone. The
+actual area is used as transport area. This item cannot be in
+the backbone. In OSPFv3, you could also use several virtual
+links to one destination with different instance IDs.
<P>
<DT><CODE>cost <I>num</I></CODE><DD><P>Specifies output cost (metric) of an interface. Default value is 10.
<P>
@@ -941,6 +973,15 @@
<DT><CODE>strict nonbroadcast <I>switch</I></CODE><DD><P>If set, don't send hello to any undefined neighbor. This switch
is ignored on other than NBMA or PtMP networks. Default value is no.
<P>
+<DT><CODE>real broadcast <I>switch</I></CODE><DD><P>In <CODE>type broadcast</CODE> or <CODE>type ptp</CODE> network
+configuration, OSPF packets are sent as IP multicast
+packets. This option changes the behavior to using
+old-fashioned IP broadcast packets. This may be useful as a
+workaround if IP multicast for some reason does not work or
+does not work reliably. This is a non-standard option and
+probably is not interoperable with other OSPF
+implementations. Default value is no.
+<P>
<DT><CODE>check link <I>switch</I></CODE><DD><P>If set, a hardware link state (reported by OS) is taken into
consideration. When a link disappears (e.g. an ethernet cable is
unplugged), neighbors are immediately considered unreachable
@@ -1193,13 +1234,17 @@
basic information about a local network (e.g. a list of network
prefixes), which allows network hosts to autoconfigure network
addresses and choose a default route. BIRD implements router behavior
-as defined in RFC 4861
-<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc4861.txt">ftp://ftp.rfc-editor.org/in-notes/rfc4861.txt</A>.
+as defined in
+RFC 4861
+<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc4861.txt">ftp://ftp.rfc-editor.org/in-notes/rfc4861.txt</A>
+and also the DNS extensions from
+RFC 6106
+<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc6106.txt">ftp://ftp.rfc-editor.org/in-notes/rfc6106.txt</A>.
<P>
<H3>Configuration</H3>
-<P>There are two classes of definitions in RAdv configuration --
-interface definitions and prefix definitions:
+<P>There are several classes of definitions in RAdv configuration --
+interface definitions, prefix definitions and DNS definitions:
<P>
<DL>
<DT><CODE>interface <I>pattern [, ...]</I> { <I>options</I> }</CODE><DD><P>Interface definitions specify a set of interfaces on which the
@@ -1208,7 +1253,7 @@
<A HREF="bird-3.html#dsc-iface">interface</A> common options for
detailed description.
<P>
-<DT><CODE>prefix <I>prefix</I> { <I>options</I> }</CODE><DD><P>Prefix definitions allows to modify a list of advertised
+<DT><CODE>prefix <I>prefix</I> { <I>options</I> }</CODE><DD><P>Prefix definitions allow to modify a list of advertised
prefixes. By default, the advertised prefixes are the same as
the network prefixes assigned to the interface. For each
network prefix, the matching prefix definition is found and
@@ -1221,6 +1266,22 @@
definitions. As expected, the prefix definition is matching if
the network prefix is a subnet of the prefix in prefix
definition.
+<P>
+<DT><CODE>rdnss { <I>options</I> }</CODE><DD><P>RDNSS definitions allow to specify a list of advertised
+recursive DNS servers together with their options. As options
+are seldom necessary, there is also a short variant <CODE>rdnss
+<I>address</I></CODE> that just specifies one DNS server. Multiple
+definitions are cumulative. RDNSS definitions may also be
+interface-specific when used inside interface options. By
+default, interface uses both global and interface-specific
+options, but that can be changed by <CODE>rdnss local</CODE> option.
+<P>
+<DT><CODE>dnssl { <I>options</I> }</CODE><DD><P>DNSSL definitions allow to specify a list of advertised DNS
+search domains together with their options. Like <CODE>rdnss</CODE>
+above, multiple definitions are cumulative, they can be used
+also as interface-specific options and there is a short
+variant <CODE>dnssl <I>domain</I></CODE> that just specifies one DNS
+search domain.
</DL>
<P>
<P>Interface specific options:
@@ -1231,8 +1292,8 @@
intervals, in seconds. Valid values are 4-1800. Default: 600
<P>
<DT><CODE>min ra interval <I>expr</I></CODE><DD><P>This option specifies the minimum length of that intervals, in
-seconds. Must be at least 3 and at most 3/4 * max ra interval.
-Default: about 1/3 * max ra interval.
+seconds. Must be at least 3 and at most 3/4 * <CODE>max ra interval</CODE>.
+Default: about 1/3 * <CODE>max ra interval</CODE>.
<P>
<DT><CODE>min delay <I>expr</I></CODE><DD><P>The minimum delay between two consecutive router advertisements,
in seconds. Default: 3
@@ -1261,7 +1322,15 @@
<DT><CODE>default lifetime <I>expr</I></CODE><DD><P>This option specifies the time (in seconds) how long (after
the receipt of RA) hosts may use the router as a default
router. 0 means do not use as a default router. Default: 3 *
-max ra interval.
+<CODE>max ra interval</CODE>.
+<P>
+<DT><CODE>rdnss local <I>bool</I></CODE><DD><P>Use only local (interface-specific) RDNSS definitions for this
+interface. Otherwise, both global and local definitions are
+used. Could also be used to disable RDNSS for given interface
+if no local definitons are specified. Default: no.
+<P>
+<DT><CODE>dnssl local <I>bool</I></CODE><DD><P>Use only local DNSSL definitions for this interface. See
+<CODE>rdnss local</CODE> option above. Default: no.
</DL>
<P>
<P>
@@ -1286,6 +1355,38 @@
14400 (4 hours)
</DL>
<P>
+<P>
+<P>RDNSS specific options:
+<P>
+<DL>
+<DT><CODE>ns <I>address</I></CODE><DD><P>This option specifies one recursive DNS server. Can be used
+multiple times for multiple servers. It is mandatory to have
+at least one <CODE>ns</CODE> option in <CODE>rdnss</CODE> definition.
+<P>
+<DT><CODE>lifetime [mult] <I>expr</I></CODE><DD><P>This option specifies the time how long the RDNSS information
+may be used by clients after the receipt of RA. It is
+expressed either in seconds or (when <CODE>mult</CODE> is used) in
+multiples of <CODE>max ra interval</CODE>. Note that RDNSS information
+is also invalidated when <CODE>default lifetime</CODE> expires. 0
+means these addresses are no longer valid DNS servers.
+Default: 3 * <CODE>max ra interval</CODE>.
+</DL>
+<P>
+<P>
+<P>DNSSL specific options:
+<P>
+<DL>
+<DT><CODE>domain <I>address</I></CODE><DD><P>This option specifies one DNS search domain. Can be used
+multiple times for multiple domains. It is mandatory to have
+at least one <CODE>domain</CODE> option in <CODE>dnssl</CODE> definition.
+<P>
+<DT><CODE>lifetime [mult] <I>expr</I></CODE><DD><P>This option specifies the time how long the DNSSL information
+may be used by clients after the receipt of RA. Details are
+the same as for RDNSS <CODE>lifetime</CODE> option above.
+Default: 3 * <CODE>max ra interval</CODE>.
+</DL>
+<P>
+<P>
<H3>Example</H3>
<P>
@@ -1309,6 +1410,20 @@
prefix 2001:0DB8:2000::/48 {
autonomous off; # Do not autoconfigure
};
+
+ rdnss 2001:0DB8:1234::10; # Short form of RDNSS
+
+ rdnss {
+ lifetime mult 10;
+ ns 2001:0DB8:1234::11;
+ ns 2001:0DB8:1234::12;
+ };
+
+ dnssl {
+ lifetime 3600;
+ domain "abc.com";
+ domain "xyz.com";
+ };
}
</PRE>
<HR>
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/doc/bird.sgml
^
|
@@ -215,7 +215,27 @@
When the routing table gets a route from a protocol, it recalculates
the selected route and broadcasts it to all protocols connected to
the table. The protocols typically send the update to other routers
-in the network.
+in the network. Note that although most protocols are interested
+in receiving just selected routes, some protocols (e.g. the <cf/Pipe/
+protocol) receive and process all entries in routing tables (accepted
+by filters).
+
+<p><label id="dsc-sorted">Usually, a routing table just chooses a
+selected route from a list of entries for one network. But if the
+<cf/sorted/ option is activated, these lists of entries are kept
+completely sorted (according to preference or some protocol-dependent
+metric).
+
+This is needed for some features of some protocols
+(e.g. <cf/secondary/ option of BGP protocol, which allows to accept
+not just a selected route, but the first route (in the sorted list)
+that is accepted by filters), but it is incompatible with some other
+features (e.g. <cf/deterministic med/ option of BGP protocol, which
+activates a way of choosing selected route that cannot be described
+using comparison and ordering). Minor advantage is that routes are
+shown sorted in <cf/show route/, minor disadvantage is that it is
+slightly more computationally expensive.
+
<chapt>Configuration
@@ -354,11 +374,14 @@
defaults are here for a compatibility with older versions
and might change in the future.
- <tag>table <m/name/</tag> Create a new routing table. The default
- routing table is created implicitly, other routing tables have
- to be added by this command.
+ <tag>table <m/name/ [sorted]</tag>
+ Create a new routing table. The default routing table is
+ created implicitly, other routing tables have to be added by
+ this command. Option <cf/sorted/ can be used to enable
+ sorting of routes, see <ref id="dsc-sorted" name="sorted table">
+ description for details.
- <tag>roa table [ { roa table options ... } ] <m/name/</tag>
+ <tag>roa table <m/name/ [ { roa table options ... } ]</tag>
Create a new ROA (Route Origin Authorization) table. ROA
tables can be used to validate route origination of BGP
routes. A ROA table contains ROA entries, each consist of a
@@ -426,10 +449,37 @@
uses global router id.
<tag>import all | none | filter <m/name/ | filter { <m/filter commands/ } | where <m/filter expression/</tag>
- Specify a filter to be used for filtering routes coming from the protocol to the routing table. <cf/all/ is shorthand for <cf/where true/ and <cf/none/ is shorthand for <cf/where false/. Default: <cf/all/.
-
- <tag>export <m/filter/</tag> This is similar to the <cf>import</cf> keyword, except that it
- works in the direction from the routing table to the protocol. Default: <cf/none/.
+ Specify a filter to be used for filtering routes coming from
+ the protocol to the routing table. <cf/all/ is shorthand for
+ <cf/where true/ and <cf/none/ is shorthand for
+ <cf/where false/. Default: <cf/all/.
+
+ <tag>export <m/filter/</tag>
+ This is similar to the <cf>import</cf> keyword, except that it
+ works in the direction from the routing table to the protocol.
+ Default: <cf/none/.
+
+ <tag>import limit <m/number/ [action warn | block | restart | disable]</tag>
+ Specify an import route limit (a maximum number of routes
+ imported from the protocol) and optionally the action to be
+ taken when the limit is hit. Warn action just prints warning
+ log message. Block action ignores new routes coming from the
+ protocol. Restart and disable actions shut the protocol down
+ like appropriate commands. Disable is the default action if an
+ action is not explicitly specified. Note that limits are reset
+ during protocol reconfigure, reload or restart.
+ Default: <cf/none/.
+
+ <tag>export limit <m/number/ [action warn | block | restart | disable]</tag>
+ Specify an export route limit, works similarly to
+ the <cf>import limit</cf> option, but for the routes exported
+ to the protocol. This option is experimental, there are some
+ problems in details of its behavior -- the number of exported
+ routes can temporarily exceed the limit without triggering it
+ during protocol reload, exported routes counter ignores route
+ blocking and block action also blocks route updates of already
+ accepted routes -- and these details will probably change in
+ the future. Default: <cf/none/.
<tag>description "<m/text/"</tag> This is an optional
description of the protocol. It is displayed as a part of the
@@ -1045,7 +1095,16 @@
routes). Read-only.
<tag><m/enum/ dest</tag>
- Type of destination the packets should be sent to (<cf/RTD_ROUTER/ for forwarding to a neighboring router, <cf/RTD_DEVICE/ for routing to a directly-connected network, <cf/RTD_BLACKHOLE/ for packets to be silently discarded, <cf/RTD_UNREACHABLE/, <cf/RTD_PROHIBIT/ for packets that should be returned with ICMP host unreachable / ICMP administratively prohibited messages). Read-only.
+ Type of destination the packets should be sent to
+ (<cf/RTD_ROUTER/ for forwarding to a neighboring router,
+ <cf/RTD_DEVICE/ for routing to a directly-connected network,
+ <cf/RTD_MULTIPATH/ for multipath destinations,
+ <cf/RTD_BLACKHOLE/ for packets to be silently discarded,
+ <cf/RTD_UNREACHABLE/, <cf/RTD_PROHIBIT/ for packets that
+ should be returned with ICMP host unreachable / ICMP
+ administratively prohibited messages). Can be changed, but
+ only to <cf/RTD_BLACKHOLE/, <cf/RTD_UNREACHABLE/ or
+ <cf/RTD_PROHIBIT/.
<tag><m/int/ igp_metric</tag>
The optional attribute that can be used to specify a distance
@@ -1234,8 +1293,10 @@
mode is the behavior specified by the BGP standard. Direct
mode is simpler, does not require any routes in a routing
table, and was used in older versions of BIRD, but does not
- handle well nontrivial iBGP setups and multihop. Default:
- <cf/direct/ for singlehop eBGP, <cf/recursive/ otherwise.
+ handle well nontrivial iBGP setups and multihop. Recursive
+ mode is incompatible with <ref id="dsc-sorted" name="sorted
+ tables">. Default: <cf/direct/ for singlehop eBGP,
+ <cf/recursive/ otherwise.
<tag>igp table <m/name/</tag> Specifies a table that is used
as an IGP routing table. Default: the same as the table BGP is
@@ -1281,6 +1342,16 @@
attributes to be transparent (for example does not prepend its AS number to
AS PATH attribute and keeps MED attribute). Default: disabled.
+ <tag>secondary <m/switch/</tag> Usually, if an import filter
+ rejects a selected route, no other route is propagated for
+ that network. This option allows to try the next route in
+ order until one that is accepted is found or all routes for
+ that network are rejected. This can be used for route servers
+ that need to propagate different tables to each client but do
+ not want to have these tables explicitly (to conserve memory).
+ This option requires that the connected routing table is
+ <ref id="dsc-sorted" name="sorted">. Default: off.
+
<tag>enable route refresh <m/switch/</tag> When BGP speaker
changes its import filter, it has to re-examine all routes
received from its neighbor against the new filter. As these
@@ -1327,7 +1398,8 @@
<tag>route limit <m/number/</tag> The maximal number of routes
that may be imported from the protocol. If the route limit is
- exceeded, the connection is closed with error. Default: no limit.
+ exceeded, the connection is closed with error. Limit is currently implemented as
+ <cf/import limit number exceed restart/. Default: no limit.
<tag>disable after error <m/switch/</tag> When an error is encountered (either
locally or by the other side), disable the instance automatically
@@ -1385,7 +1457,9 @@
This option enables a different (and slower) algorithm
implementing proper RFC 4271 route selection, which is
deterministic. Alternative way how to get deterministic
- behavior is to use <cf/med metric/ option. Default: off.
+ behavior is to use <cf/med metric/ option. This option is
+ incompatible with <ref id="dsc-sorted" name="sorted tables">.
+ Default: off.
<tag>igp metric <m/switch/</tag> Enable comparison of internal
distances to boundary routers during best route selection. Default: on.
@@ -1618,7 +1692,7 @@
<p>Because the kernel protocol is partially integrated with the
connected routing table, there are two limitations - it is not
possible to connect more kernel protocols to the same routing table
-and changing route attributes (even the kernel ones) in an export
+and changing route destination/gateway in an export
filter of a kernel protocol does not work. Both limitations can be
overcome using another routing table and the pipe protocol.
@@ -1653,6 +1727,16 @@
We support these attributes:
<descrip>
+ <tag>int <cf/krt_source/</tag> The original source of the imported
+ kernel route. The value is system-dependent. On Linux, it is
+ a value of the protocol field of the route. See
+ /etc/iproute2/rt_protos for common values. On BSD, it is
+ based on STATIC and PROTOx flags. The attribute is read-only.
+
+ <tag>int <cf/krt_metric/</tag> The kernel metric of
+ the route. When multiple same routes are in a kernel routing
+ table, the Linux kernel chooses one with lower metric.
+
<tag>ip <cf/krt_prefsrc/</tag> (Linux) The preferred source address.
Used in source address selection for outgoing packets. Have to
be one of IP addresses of the router.
@@ -1764,7 +1848,7 @@
summary <switch>;
cost <num>;
}
- interface <interface pattern> {
+ interface <interface pattern> [instance <num>] {
cost <num>;
stub <switch>;
hello <num>;
@@ -1778,6 +1862,7 @@
type [broadcast|bcast|pointopoint|ptp|
nonbroadcast|nbma|pointomultipoint|ptmp];
strict nonbroadcast <switch>;
+ real broadcast <switch>;
check link <switch>;
ecmp weight <num>;
authentication [none|simple|cryptographic];
@@ -1794,7 +1879,7 @@
<ip> eligible;
};
};
- virtual link <id> {
+ virtual link <id> [instance <num>] {
hello <num>;
retransmit <num>;
wait <num>;
@@ -1914,14 +1999,19 @@
subnetworks of given stub network are suppressed. This might
be used, for example, to aggregate generated stub networks.
- <tag>interface <M>pattern</M></tag>
+ <tag>interface <M>pattern</M> [instance <m/num/]</tag>
Defines that the specified interfaces belong to the area being defined.
See <ref id="dsc-iface" name="interface"> common option for detailed description.
-
- <tag>virtual link <M>id</M></tag>
- Virtual link to router with the router id. Virtual link acts as a
- point-to-point interface belonging to backbone. The actual area is
- used as transport area. This item cannot be in the backbone.
+ In OSPFv3, you can specify instance ID for that interface
+ description, so it is possible to have several instances of
+ that interface with different options or even in different areas.
+
+ <tag>virtual link <M>id</M> [instance <m/num/]</tag>
+ Virtual link to router with the router id. Virtual link acts
+ as a point-to-point interface belonging to backbone. The
+ actual area is used as transport area. This item cannot be in
+ the backbone. In OSPFv3, you could also use several virtual
+ links to one destination with different instance IDs.
<tag>cost <M>num</M></tag>
Specifies output cost (metric) of an interface. Default value is 10.
@@ -2006,6 +2096,16 @@
If set, don't send hello to any undefined neighbor. This switch
is ignored on other than NBMA or PtMP networks. Default value is no.
+ <tag>real broadcast <m/switch/</tag>
+ In <cf/type broadcast/ or <cf/type ptp/ network
+ configuration, OSPF packets are sent as IP multicast
+ packets. This option changes the behavior to using
+ old-fashioned IP broadcast packets. This may be useful as a
+ workaround if IP multicast for some reason does not work or
+ does not work reliably. This is a non-standard option and
+ probably is not interoperable with other OSPF
+ implementations. Default value is no.
+
<tag>check link <M>switch</M></tag>
If set, a hardware link state (reported by OS) is taken into
consideration. When a link disappears (e.g. an ethernet cable is
@@ -2258,22 +2358,25 @@
basic information about a local network (e.g. a list of network
prefixes), which allows network hosts to autoconfigure network
addresses and choose a default route. BIRD implements router behavior
-as defined in RFC 4861<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4861.txt">.
+as defined in
+RFC 4861<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4861.txt">
+and also the DNS extensions from
+RFC 6106<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc6106.txt">.
<sect1>Configuration
-<p>There are two classes of definitions in RAdv configuration --
-interface definitions and prefix definitions:
+<p>There are several classes of definitions in RAdv configuration --
+interface definitions, prefix definitions and DNS definitions:
<descrip>
- <tag>interface <m/pattern [, ...]/ { <m/options/ }</tag>
+ <tag>interface <m/pattern [, ...]/ { <m/options/ }</tag>
Interface definitions specify a set of interfaces on which the
protocol is activated and contain interface specific options.
See <ref id="dsc-iface" name="interface"> common options for
detailed description.
- <tag>prefix <m/prefix/ { <m/options/ }</tag>
- Prefix definitions allows to modify a list of advertised
+ <tag>prefix <m/prefix/ { <m/options/ }</tag>
+ Prefix definitions allow to modify a list of advertised
prefixes. By default, the advertised prefixes are the same as
the network prefixes assigned to the interface. For each
network prefix, the matching prefix definition is found and
@@ -2287,6 +2390,24 @@
definitions. As expected, the prefix definition is matching if
the network prefix is a subnet of the prefix in prefix
definition.
+
+ <tag>rdnss { <m/options/ }</tag>
+ RDNSS definitions allow to specify a list of advertised
+ recursive DNS servers together with their options. As options
+ are seldom necessary, there is also a short variant <cf>rdnss
+ <m/address/</cf> that just specifies one DNS server. Multiple
+ definitions are cumulative. RDNSS definitions may also be
+ interface-specific when used inside interface options. By
+ default, interface uses both global and interface-specific
+ options, but that can be changed by <cf/rdnss local/ option.
+
+ <tag>dnssl { <m/options/ }</tag>
+ DNSSL definitions allow to specify a list of advertised DNS
+ search domains together with their options. Like <cf/rdnss/
+ above, multiple definitions are cumulative, they can be used
+ also as interface-specific options and there is a short
+ variant <cf>dnssl <m/domain/</cf> that just specifies one DNS
+ search domain.
</descrip>
<p>Interface specific options:
@@ -2299,8 +2420,8 @@
<tag>min ra interval <m/expr/</tag>
This option specifies the minimum length of that intervals, in
- seconds. Must be at least 3 and at most 3/4 * max ra interval.
- Default: about 1/3 * max ra interval.
+ seconds. Must be at least 3 and at most 3/4 * <cf/max ra interval/.
+ Default: about 1/3 * <cf/max ra interval/.
<tag>min delay <m/expr/</tag>
The minimum delay between two consecutive router advertisements,
@@ -2337,7 +2458,17 @@
This option specifies the time (in seconds) how long (after
the receipt of RA) hosts may use the router as a default
router. 0 means do not use as a default router. Default: 3 *
- max ra interval.
+ <cf/max ra interval/.
+
+ <tag>rdnss local <m/bool/</tag>
+ Use only local (interface-specific) RDNSS definitions for this
+ interface. Otherwise, both global and local definitions are
+ used. Could also be used to disable RDNSS for given interface
+ if no local definitons are specified. Default: no.
+
+ <tag>dnssl local <m/bool/</tag>
+ Use only local DNSSL definitions for this interface. See
+ <cf/rdnss local/ option above. Default: no.
</descrip>
@@ -2366,6 +2497,42 @@
14400 (4 hours)
</descrip>
+
+<p>RDNSS specific options:
+
+<descrip>
+ <tag>ns <m/address/</tag>
+ This option specifies one recursive DNS server. Can be used
+ multiple times for multiple servers. It is mandatory to have
+ at least one <cf/ns/ option in <cf/rdnss/ definition.
+
+ <tag>lifetime [mult] <m/expr/</tag>
+ This option specifies the time how long the RDNSS information
+ may be used by clients after the receipt of RA. It is
+ expressed either in seconds or (when <cf/mult/ is used) in
+ multiples of <cf/max ra interval/. Note that RDNSS information
+ is also invalidated when <cf/default lifetime/ expires. 0
+ means these addresses are no longer valid DNS servers.
+ Default: 3 * <cf/max ra interval/.
+</descrip>
+
+
+<p>DNSSL specific options:
+
+<descrip>
+ <tag>domain <m/address/</tag>
+ This option specifies one DNS search domain. Can be used
+ multiple times for multiple domains. It is mandatory to have
+ at least one <cf/domain/ option in <cf/dnssl/ definition.
+
+ <tag>lifetime [mult] <m/expr/</tag>
+ This option specifies the time how long the DNSSL information
+ may be used by clients after the receipt of RA. Details are
+ the same as for RDNSS <cf/lifetime/ option above.
+ Default: 3 * <cf/max ra interval/.
+</descrip>
+
+
<sect1>Example
<p><code>
@@ -2387,6 +2554,20 @@
prefix 2001:0DB8:2000::/48 {
autonomous off; # Do not autoconfigure
};
+
+ rdnss 2001:0DB8:1234::10; # Short form of RDNSS
+
+ rdnss {
+ lifetime mult 10;
+ ns 2001:0DB8:1234::11;
+ ns 2001:0DB8:1234::12;
+ };
+
+ dnssl {
+ lifetime 3600;
+ domain "abc.com";
+ domain "xyz.com";
+ };
}
</code>
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/doc/prog-2.html
^
|
@@ -213,7 +213,7 @@
<HR><H3>Function</H3>
<P><I>void</I>
<B>rte_announce</B>
-(<I>rtable *</I> <B>tab</B>, <I>unsigned</I> <B>type</B>, <I>net *</I> <B>net</B>, <I>rte *</I> <B>new</B>, <I>rte *</I> <B>old</B>, <I>ea_list *</I> <B>tmpa</B>) -- announce a routing table change
+(<I>rtable *</I> <B>tab</B>, <I>unsigned</I> <B>type</B>, <I>net *</I> <B>net</B>, <I>rte *</I> <B>new</B>, <I>rte *</I> <B>old</B>, <I>rte *</I> <B>before_old</B>, <I>ea_list *</I> <B>tmpa</B>) -- announce a routing table change
<P>
<H3>Arguments</H3>
<P>
@@ -223,6 +223,7 @@
<DT><I>net *</I> <B>net</B><DD><P>network in question
<DT><I>rte *</I> <B>new</B><DD><P>the new route to be announced
<DT><I>rte *</I> <B>old</B><DD><P>the previous route for the same network
+<DT><I>rte *</I> <B>before_old</B><DD><P>-- undescribed --
<DT><I>ea_list *</I> <B>tmpa</B><DD><P>a list of temporary attributes belonging to the new route
</DL>
<H3>Description</H3>
@@ -260,17 +261,16 @@
<HR><H3>Function</H3>
<P><I>void</I>
-<B>rte_update</B>
-(<I>rtable *</I> <B>table</B>, <I>net *</I> <B>net</B>, <I>struct proto *</I> <B>p</B>, <I>struct proto *</I> <B>src</B>, <I>rte *</I> <B>new</B>) -- enter a new update to a routing table
+<B>rte_update2</B>
+(<I>struct announce_hook *</I> <B>ah</B>, <I>net *</I> <B>net</B>, <I>rte *</I> <B>new</B>, <I>struct proto *</I> <B>src</B>) -- enter a new update to a routing table
<P>
<H3>Arguments</H3>
<P>
<DL>
-<DT><I>rtable *</I> <B>table</B><DD><P>table to be updated
+<DT><I>struct announce_hook *</I> <B>ah</B><DD><P>pointer to table announce hook
<DT><I>net *</I> <B>net</B><DD><P>network node
-<DT><I>struct proto *</I> <B>p</B><DD><P>protocol submitting the update
-<DT><I>struct proto *</I> <B>src</B><DD><P>protocol originating the update
<DT><I>rte *</I> <B>new</B><DD><P>a <I>rte</I> representing the new route or <I>NULL</I> for route removal.
+<DT><I>struct proto *</I> <B>src</B><DD><P>protocol originating the update
</DL>
<H3>Description</H3>
<P>This function is called by the routing protocols whenever they discover
@@ -352,29 +352,15 @@
<HR><H3>Function</H3>
-<P><I>void</I>
-<B>rt_prune</B>
-(<I>rtable *</I> <B>tab</B>) -- prune a routing table
-<P>
-<H3>Arguments</H3>
-<P>
-<DL>
-<DT><I>rtable *</I> <B>tab</B><DD><P>routing table to be pruned
-</DL>
-<H3>Description</H3>
-<P>This function is called whenever a protocol shuts down. It scans
-the routing table and removes all routes belonging to inactive
-protocols and also stale network entries.
-
-
-<HR><H3>Function</H3>
-<P><I>void</I>
-<B>rt_prune_all</B>
-(<B>void</B>) -- prune all routing tables
+<P><I>int</I>
+<B>rt_prune_loop</B>
+(<B>void</B>) -- prune routing tables
<P>
<H3>Description</H3>
-<P>
-<P>This function calls <B>rt_prune()</B> for all known routing tables.
+<P>The prune loop scans routing tables and removes routes belonging to
+inactive protocols and also stale network entries. Returns 1 when
+all such routes are pruned. It is a part of the protocol flushing
+loop.
<HR><H3>Function</H3>
@@ -923,18 +909,25 @@
<HR><H3>Function</H3>
<P><I>struct announce_hook *</I>
<B>proto_add_announce_hook</B>
-(<I>struct proto *</I> <B>p</B>, <I>struct rtable *</I> <B>t</B>) -- connect protocol to a routing table
+(<I>struct proto *</I> <B>p</B>, <I>struct rtable *</I> <B>t</B>, <I>struct proto_stats *</I> <B>stats</B>) -- connect protocol to a routing table
<P>
<H3>Arguments</H3>
<P>
<DL>
<DT><I>struct proto *</I> <B>p</B><DD><P>protocol instance
<DT><I>struct rtable *</I> <B>t</B><DD><P>routing table to connect to
+<DT><I>struct proto_stats *</I> <B>stats</B><DD><P>per-table protocol statistics
</DL>
<H3>Description</H3>
<P>This function creates a connection between the protocol instance <B>p</B>
and the routing table <B>t</B>, making the protocol hear all changes in
the table.
+<P>The announce hook is linked in the protocol ahook list and, if the
+protocol accepts routes, also in the table ahook list. Announce
+hooks are allocated from the routing table resource pool, they are
+unlinked from the table ahook list after the protocol went down,
+(in <B>proto_schedule_flush()</B>) and they are automatically freed after the
+protocol is flushed (in <B>proto_fell_down()</B>).
<P>Unless you want to listen to multiple routing tables (as the Pipe
protocol does), you needn't to worry about this function since the
connection to the protocol's primary routing table is initialized
@@ -942,6 +935,21 @@
<HR><H3>Function</H3>
+<P><I>struct announce_hook *</I>
+<B>proto_find_announce_hook</B>
+(<I>struct proto *</I> <B>p</B>, <I>struct rtable *</I> <B>t</B>) -- find announce hooks
+<P>
+<H3>Arguments</H3>
+<P>
+<DL>
+<DT><I>struct proto *</I> <B>p</B><DD><P>protocol instance
+<DT><I>struct rtable *</I> <B>t</B><DD><P>routing table
+</DL>
+<H3>Description</H3>
+<P>Returns pointer to announce hook or NULL
+
+
+<HR><H3>Function</H3>
<P><I>void *</I>
<B>proto_config_new</B>
(<I>struct protocol *</I> <B>pr</B>, <I>unsigned</I> <B>size</B>, <I>int</I> <B>class</B>) -- create a new protocol configuration
@@ -1116,6 +1124,23 @@
<HR><H3>Function</H3>
<P><I>void</I>
+<B>proto_notify_limit</B>
+(<I>struct announce_hook *</I> <B>ah</B>, <I>struct proto_limit *</I> <B>l</B>, <I>u32</I> <B>rt_count</B>)
+<H3>Arguments</H3>
+<P>
+<DL>
+<DT><I>struct announce_hook *</I> <B>ah</B><DD><P>announce hook
+<DT><I>struct proto_limit *</I> <B>l</B><DD><P>limit being hit
+<DT><I>u32</I> <B>rt_count</B><DD><P>the number of routes
+</DL>
+<H3>Description</H3>
+<P>The function is called by the route processing core when limit <B>l</B>
+is breached. It activates the limit and tooks appropriate action
+according to <B>l</B>->action.
+
+
+<HR><H3>Function</H3>
+<P><I>void</I>
<B>proto_notify_state</B>
(<I>struct proto *</I> <B>p</B>, <I>unsigned</I> <B>ps</B>) -- notify core about protocol state change
<P>
@@ -1255,7 +1280,7 @@
</DL>
<H3>Description</H3>
<P>The <B>start()</B> hook is called by the core when it wishes to start
-the instance.
+the instance. Multitable protocols should lock their tables here.
<H3>Result</H3>
<P>new protocol state
@@ -1278,6 +1303,22 @@
<HR><H3>Function</H3>
+<P><I>void</I>
+<B>cleanup</B>
+(<I>struct proto *</I> <B>p</B>) -- request instance cleanup
+<P>
+<H3>Arguments</H3>
+<P>
+<DL>
+<DT><I>struct proto *</I> <B>p</B><DD><P>protocol instance
+</DL>
+<H3>Description</H3>
+<P>The <B>cleanup()</B> hook is called by the core when the protocol became
+hungry/down, i.e. all protocol ahooks and routes are flushed.
+Multitable protocols should unlock their tables here.
+
+
+<HR><H3>Function</H3>
<P><I>void</I>
<B>get_status</B>
(<I>struct proto *</I> <B>p</B>, <I>byte *</I> <B>buf</B>) -- get instance status
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/doc/prog-5.html
^
|
@@ -784,6 +784,17 @@
in the other one.
<P>To avoid pipe loops, Pipe keeps a `being updated' flag in each routing
table.
+<P>A pipe has two announce hooks, the first connected to the main
+table, the second connected to the peer table. When a new route is
+announced on the main table, it gets checked by an export filter in
+ahook 1, and, after that, it is announced to the peer table via
+<B>rte_update()</B>, an import filter in ahook 2 is called. When a new
+route is announced in the peer table, an export filter in ahook2
+and an import filter in ahook 1 are used. Oviously, there is no
+need in filtering the same route twice, so both import filters are
+set to accept, while user configured 'import' and 'export' filters
+are used as export filters in ahooks 2 and 1. Route limits are
+handled similarly, but on the import side of ahooks.
<P>
<P>
<H2><A NAME="ss5.4">5.4</A> <A HREF="prog.html#toc5.4">Routing Information Protocol</A>
@@ -863,6 +874,9 @@
<B>radv_iface_notify()</B>, which processes asynchronous events (specified
by RA_EV_* codes), and <B>radv_timer()</B>, which triggers sending RAs and
computes the next timeout.
+<P>Supported standards:
+- RFC 4861 - main RA standard
+- RFC 6106 - DNS extensions (RDDNS, DNSSL)
<P>
<P>
<H2><A NAME="ss5.6">5.6</A> <A HREF="prog.html#toc5.6">Static</A>
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/doc/prog-6.html
^
|
@@ -176,7 +176,7 @@
Either with a single routing table and single KRT protocol [traditional UNIX]
or with many routing tables and separate KRT protocols for all of them
or with many routing tables, but every scan including all tables, so we start
-separate KRT protocols which cooperate with each other [Linux 2.2].
+separate KRT protocols which cooperate with each other [Linux].
In this case, we keep only a single scan timer.
<P>We use FIB node flags in the routing table to keep track of route
synchronization status. We also attach temporary <I>rte</I>'s to the routing table,
@@ -185,6 +185,13 @@
<P>When starting up, we cheat by looking if there is another
KRT instance to be initialized later and performing table scan
only once for all the instances.
+<P>The code uses OS-dependent parts for kernel updates and scans. These parts are
+in more specific sysdep directories (e.g. sysdep/linux) in functions krt_sys_*
+and kif_sys_* (and some others like <B>krt_replace_rte()</B>) and krt-sys.h header file.
+This is also used for platform specific protocol options and route attributes.
+<P>There was also an old code that used traditional UNIX ioctls for these tasks.
+It was unmaintained and later removed. For reference, see sysdep/krt-* files
+in commit 396dfa9042305f62da1f56589c4b98fac57fc2f6
<P>
<P>
<HR>
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/doc/prog-8.html
^
|
@@ -219,7 +219,7 @@
<P><B>mb_allocz()</B> allocates memory of a given size, initializes it to
zeroes and creates a memory block resource representing this memory
chunk in the pool <B>p</B>.
-<P>Please note that <B>mb_alloc()</B> returns a pointer to the memory
+<P>Please note that <B>mb_allocz()</B> returns a pointer to the memory
chunk, not to the resource, hence you have to free it using
<B>mb_free()</B>, not <B>rfree()</B>.
@@ -639,7 +639,7 @@
<P>
<P><HR><H3>Function</H3>
<P><I>sock *</I>
-<B>sk_new</B>
+<B>sock_new</B>
(<I>pool *</I> <B>p</B>) -- create a socket
<P>
<H3>Arguments</H3>
@@ -651,6 +651,8 @@
<P>This function creates a new socket resource. If you want to use it,
you need to fill in all the required fields of the structure and
call <B>sk_open()</B> to do the actual opening of the socket.
+<P>The real function name is <B>sock_new()</B>, <B>sk_new()</B> is a macro wrapper
+to avoid collision with OpenSSL.
<HR><H3>Function</H3>
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/filter/config.Y
^
|
@@ -703,7 +703,7 @@
| SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, source); }
| SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope); $$->a1.i = 1; }
| CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = OFFSETOF(struct rta, cast); }
- | DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = OFFSETOF(struct rta, dest); }
+ | DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = OFFSETOF(struct rta, dest); $$->a1.i = 1; }
;
term:
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/filter/f-util.c
^
|
@@ -19,7 +19,7 @@
ret = cfg_alloc(sizeof(struct f_inst));
ret->code = ret->aux = 0;
ret->arg1 = ret->arg2 = ret->next = NULL;
- ret->lineno = ifs->conf_lino;
+ ret->lineno = ifs->lino;
return ret;
}
@@ -60,7 +60,7 @@
{
struct f_inst_roa_check *ret = cfg_allocz(sizeof(struct f_inst_roa_check));
ret->i.code = P('R','C');
- ret->i.lineno = ifs->conf_lino;
+ ret->i.lineno = ifs->lino;
ret->i.arg1 = prefix;
ret->i.arg2 = asn;
/* prefix == NULL <-> asn == NULL */
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/filter/filter.c
^
|
@@ -852,12 +852,25 @@
{
struct rta *rta = (*f_rte)->attrs;
switch (what->aux) {
- case T_ENUM:
- * ((char *) rta + what->a2.i) = v1.val.i;
- break;
+
case T_IP:
* (ip_addr *) ((char *) rta + what->a2.i) = v1.val.px.ip;
break;
+
+ case T_ENUM_SCOPE:
+ rta->scope = v1.val.i;
+ break;
+
+ case T_ENUM_RTD:
+ i = v1.val.i;
+ if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
+ runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
+ rta->dest = i;
+ rta->gw = IPA_NONE;
+ rta->iface = NULL;
+ rta->nexthops = NULL;
+ break;
+
default:
bug( "Unknown type in set of static attribute" );
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/filter/test.conf.inc
^
|
@@ -3,4 +3,3 @@
print "Should be 2: ", 1+1;
print "Leaving include";
-
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/lib/ipv4.c
^
|
@@ -60,7 +60,7 @@
if (a < 0x80000000)
m = 0xff000000;
- if (a < 0xc0000000)
+ else if (a < 0xc0000000)
m = 0xffff0000;
else
m = 0xffffff00;
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/lib/lists.h
^
|
@@ -34,7 +34,8 @@
#define HEAD(list) ((void *)((list).head))
#define TAIL(list) ((void *)((list).tail))
#define NODE_NEXT(n) ((void *)((NODE (n))->next))
-#define WALK_LIST(n,list) for(n=HEAD(list);(NODE (n))->next; n=NODE_NEXT(n))
+#define NODE_VALID(n) ((NODE (n))->next)
+#define WALK_LIST(n,list) for(n=HEAD(list); NODE_VALID(n); n=NODE_NEXT(n))
#define WALK_LIST_DELSAFE(n,nxt,list) \
for(n=HEAD(list); nxt=NODE_NEXT(n); n=(void *) nxt)
/* WALK_LIST_FIRST supposes that called code removes each processed node */
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/lib/resource.c
^
|
@@ -352,7 +352,7 @@
* zeroes and creates a memory block resource representing this memory
* chunk in the pool @p.
*
- * Please note that mb_alloc() returns a pointer to the memory
+ * Please note that mb_allocz() returns a pointer to the memory
* chunk, not to the resource, hence you have to free it using
* mb_free(), not rfree().
*/
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/lib/socket.h
^
|
@@ -48,7 +48,9 @@
char *password; /* Password for MD5 authentication */
} sock;
-sock *sk_new(pool *); /* Allocate new socket */
+sock *sock_new(pool *); /* Allocate new socket */
+#define sk_new(X) sock_new(X) /* Wrapper to avoid name collision with OpenSSL */
+
int sk_open(sock *); /* Open socket */
int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/nest/a-path.c
^
|
@@ -15,7 +15,6 @@
#include "lib/string.h"
#include "filter/filter.h"
-
// static inline void put_as(byte *data, u32 as) { put_u32(data, as); }
// static inline u32 get_as(byte *data) { return get_u32(data); }
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/nest/cli.c
^
|
@@ -251,7 +251,6 @@
bzero(&f, sizeof(f));
f.mem = c->parser_pool;
cf_read_hook = cli_cmd_read_hook;
- cf_open_hook = NULL;
cli_rh_pos = c->rx_buf;
cli_rh_len = strlen(c->rx_buf);
cli_rh_trick_flag = 0;
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/nest/config.Y
^
|
@@ -44,9 +44,10 @@
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
+CF_KEYWORDS(LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE, ROA, MAX, FLUSH)
-CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION)
+CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC)
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
@@ -64,8 +65,9 @@
%type <ro> roa_args
%type <rot> roa_table_arg
%type <sd> sym_args
-%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport roa_mode
+%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport roa_mode limit_action tab_sorted
%type <ps> proto_patt proto_patt2
+%type <g> limit_spec
CF_GRAMMAR
@@ -110,10 +112,17 @@
/* Creation of routing tables */
+tab_sorted:
+ { $$ = 0; }
+ | SORTED { $$ = 1; }
+ ;
+
CF_ADDTO(conf, newtab)
-newtab: TABLE SYM {
- rt_new_table($2);
+newtab: TABLE SYM tab_sorted {
+ struct rtable_config *cf;
+ cf = rt_new_table($2);
+ cf->sorted = $3;
}
;
@@ -176,6 +185,8 @@
| MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
| IMPORT imexport { this_proto->in_filter = $2; }
| EXPORT imexport { this_proto->out_filter = $2; }
+ | IMPORT LIMIT limit_spec { this_proto->in_limit = $3; }
+ | EXPORT LIMIT limit_spec { this_proto->out_limit = $3; }
| TABLE rtable { this_proto->table = $2; }
| ROUTER ID idval { this_proto->router_id = $3; }
| DESCRIPTION TEXT { this_proto->dsc = $2; }
@@ -188,6 +199,23 @@
| NONE { $$ = FILTER_REJECT; }
;
+limit_action:
+ /* default */ { $$ = PLA_DISABLE; }
+ | ACTION WARN { $$ = PLA_WARN; }
+ | ACTION BLOCK { $$ = PLA_BLOCK; }
+ | ACTION RESTART { $$ = PLA_RESTART; }
+ | ACTION DISABLE { $$ = PLA_DISABLE; }
+ ;
+
+limit_spec:
+ expr limit_action {
+ struct proto_limit *l = cfg_allocz(sizeof(struct proto_limit));
+ l->limit = $1;
+ l->action = $2;
+ $$ = l;
+ }
+ ;
+
rtable:
SYM {
if ($1->class != SYM_TABLE) cf_error("Table name expected");
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/nest/proto-hooks.c
^
|
@@ -90,7 +90,7 @@
* @p: protocol instance
*
* The start() hook is called by the core when it wishes to start
- * the instance.
+ * the instance. Multitable protocols should lock their tables here.
*
* Result: new protocol state
*/
@@ -110,6 +110,17 @@
{ DUMMY; }
/**
+ * cleanup - request instance cleanup
+ * @p: protocol instance
+ *
+ * The cleanup() hook is called by the core when the protocol became
+ * hungry/down, i.e. all protocol ahooks and routes are flushed.
+ * Multitable protocols should unlock their tables here.
+ */
+void cleanup(struct proto *p)
+{ DUMMY; }
+
+/**
* get_status - get instance status
* @p: protocol instance
* @buf: buffer to be filled with the status string
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/nest/proto.c
^
|
@@ -34,11 +34,13 @@
static struct proto *initial_device_proto;
static event *proto_flush_event;
+static timer *proto_shutdown_timer;
static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
static char *c_states[] = { "HUNGRY", "FEEDING", "HAPPY", "FLUSHING" };
-static void proto_flush_all(void *);
+static void proto_flush_loop(void *);
+static void proto_shutdown_loop(struct timer *);
static void proto_rethink_goal(struct proto *p);
static char *proto_state_name(struct proto *p);
@@ -112,8 +114,6 @@
p->disabled = c->disabled;
p->proto = pr;
p->table = c->table->table;
- p->in_filter = c->in_filter;
- p->out_filter = c->out_filter;
p->hash_key = random_u32();
c->proto = p;
return p;
@@ -126,49 +126,97 @@
p->pool = rp_new(proto_pool, p->proto->name);
p->attn = ev_new(p->pool);
p->attn->data = p;
- rt_lock_table(p->table);
+
+ if (! p->proto->multitable)
+ rt_lock_table(p->table);
}
+extern pool *rt_table_pool;
/**
* proto_add_announce_hook - connect protocol to a routing table
* @p: protocol instance
* @t: routing table to connect to
+ * @stats: per-table protocol statistics
*
* This function creates a connection between the protocol instance @p
* and the routing table @t, making the protocol hear all changes in
* the table.
*
+ * The announce hook is linked in the protocol ahook list and, if the
+ * protocol accepts routes, also in the table ahook list. Announce
+ * hooks are allocated from the routing table resource pool, they are
+ * unlinked from the table ahook list after the protocol went down,
+ * (in proto_schedule_flush()) and they are automatically freed after the
+ * protocol is flushed (in proto_fell_down()).
+ *
* Unless you want to listen to multiple routing tables (as the Pipe
* protocol does), you needn't to worry about this function since the
* connection to the protocol's primary routing table is initialized
* automatically by the core code.
*/
struct announce_hook *
-proto_add_announce_hook(struct proto *p, struct rtable *t)
+proto_add_announce_hook(struct proto *p, struct rtable *t, struct proto_stats *stats)
{
struct announce_hook *h;
- if (!p->rt_notify)
- return NULL;
DBG("Connecting protocol %s to table %s\n", p->name, t->name);
PD(p, "Connected to table %s", t->name);
- h = mb_alloc(p->pool, sizeof(struct announce_hook));
+
+ h = mb_allocz(rt_table_pool, sizeof(struct announce_hook));
h->table = t;
h->proto = p;
+ h->stats = stats;
+
h->next = p->ahooks;
p->ahooks = h;
- add_tail(&t->hooks, &h->n);
+
+ if (p->rt_notify)
+ add_tail(&t->hooks, &h->n);
return h;
}
+/**
+ * proto_find_announce_hook - find announce hooks
+ * @p: protocol instance
+ * @t: routing table
+ *
+ * Returns pointer to announce hook or NULL
+ */
+struct announce_hook *
+proto_find_announce_hook(struct proto *p, struct rtable *t)
+{
+ struct announce_hook *a;
+
+ for (a = p->ahooks; a; a = a->next)
+ if (a->table == t)
+ return a;
+
+ return NULL;
+}
+
static void
-proto_flush_hooks(struct proto *p)
+proto_unlink_ahooks(struct proto *p)
{
struct announce_hook *h;
- for(h=p->ahooks; h; h=h->next)
- rem_node(&h->n);
+ if (p->rt_notify)
+ for(h=p->ahooks; h; h=h->next)
+ rem_node(&h->n);
+}
+
+static void
+proto_free_ahooks(struct proto *p)
+{
+ struct announce_hook *h, *hn;
+
+ for(h = p->ahooks; h; h = hn)
+ {
+ hn = h->next;
+ mb_free(h);
+ }
+
p->ahooks = NULL;
+ p->main_ahook = NULL;
}
/**
@@ -322,6 +370,8 @@
return q;
}
+int proto_reconfig_type; /* Hack to propagate type info to pipe reconfigure hook */
+
static int
proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
{
@@ -336,23 +386,10 @@
(proto_get_router_id(nc) != proto_get_router_id(oc)))
return 0;
- int import_changed = (type != RECONFIG_SOFT) && ! filter_same(nc->in_filter, oc->in_filter);
- int export_changed = (type != RECONFIG_SOFT) && ! filter_same(nc->out_filter, oc->out_filter);
-
- /* We treat a change in preferences by reimporting routes */
- if (nc->preference != oc->preference)
- import_changed = 1;
-
- /* If the protocol in not UP, it has no routes and we can ignore such changes */
- if (p->proto_state != PS_UP)
- import_changed = export_changed = 0;
-
- /* Without this hook we cannot reload routes and have to restart the protocol */
- if (import_changed && ! p->reload_routes)
- return 0;
p->debug = nc->debug;
p->mrtdump = nc->mrtdump;
+ proto_reconfig_type = type;
/* Execute protocol specific reconfigure hook */
if (! (p->proto->reconfigure && p->proto->reconfigure(p, nc)))
@@ -362,19 +399,46 @@
PD(p, "Reconfigured");
p->cf = nc;
p->name = nc->name;
- p->in_filter = nc->in_filter;
- p->out_filter = nc->out_filter;
p->preference = nc->preference;
+
+ /* Multitable protocols handle rest in their reconfigure hooks */
+ if (p->proto->multitable)
+ return 1;
+
+ /* Update filters and limits in the main announce hook
+ Note that this also resets limit state */
+ if (p->main_ahook)
+ {
+ p->main_ahook->in_filter = nc->in_filter;
+ p->main_ahook->out_filter = nc->out_filter;
+ p->main_ahook->in_limit = nc->in_limit;
+ p->main_ahook->out_limit = nc->out_limit;
+ }
+
+ /* Update routes when filters changed. If the protocol in not UP,
+ it has no routes and we can ignore such changes */
+ if ((p->proto_state != PS_UP) || (type == RECONFIG_SOFT))
+ return 1;
+
+ int import_changed = ! filter_same(nc->in_filter, oc->in_filter);
+ int export_changed = ! filter_same(nc->out_filter, oc->out_filter);
+
+ /* We treat a change in preferences by reimporting routes */
+ if (nc->preference != oc->preference)
+ import_changed = 1;
+
if (import_changed || export_changed)
log(L_INFO "Reloading protocol %s", p->name);
- if (import_changed && ! p->reload_routes(p))
+ /* If import filter changed, call reload hook */
+ if (import_changed && ! (p->reload_routes && p->reload_routes(p)))
{
/* Now, the protocol is reconfigured. But route reload failed
and we have to do regular protocol restart. */
log(L_INFO "Restarting protocol %s", p->name);
p->disabled = 1;
+ p->down_code = PDC_CF_RESTART;
proto_rethink_goal(p);
p->disabled = 0;
proto_rethink_goal(p);
@@ -448,16 +512,21 @@
else if (!p->disabled && nc->disabled)
log(L_INFO "Disabling protocol %s", p->name);
- PD(p, "Restarting");
+ p->down_code = nc->disabled ? PDC_CF_DISABLE : PDC_CF_RESTART;
p->cf_new = nc;
}
- else
+ else if (!shutting_down)
{
- if (!shutting_down)
- log(L_INFO "Removing protocol %s", p->name);
- PD(p, "Unconfigured");
+ log(L_INFO "Removing protocol %s", p->name);
+ p->down_code = PDC_CF_REMOVE;
p->cf_new = NULL;
}
+ else /* global shutdown */
+ {
+ p->down_code = PDC_CMD_SHUTDOWN;
+ p->cf_new = NULL;
+ }
+
p->reconfiguring = 1;
config_add_obstacle(old);
proto_rethink_goal(p);
@@ -553,6 +622,7 @@
protos_dump_all(void)
{
struct proto *p;
+ struct announce_hook *a;
debug("Protocols:\n");
@@ -560,10 +630,14 @@
{
debug(" protocol %s state %s/%s\n", p->name,
p_states[p->proto_state], c_states[p->core_state]);
- if (p->in_filter)
- debug("\tInput filter: %s\n", filter_name(p->in_filter));
- if (p->out_filter != FILTER_REJECT)
- debug("\tOutput filter: %s\n", filter_name(p->out_filter));
+ for (a = p->ahooks; a; a = a->next)
+ {
+ debug("\tTABLE %s\n", a->table->name);
+ if (a->in_filter)
+ debug("\tInput filter: %s\n", filter_name(a->in_filter));
+ if (a->out_filter != FILTER_REJECT)
+ debug("\tOutput filter: %s\n", filter_name(a->out_filter));
+ }
if (p->disabled)
debug("\tDISABLED\n");
else if (p->proto->dump)
@@ -635,7 +709,9 @@
#endif
proto_pool = rp_new(&root_pool, "Protocols");
proto_flush_event = ev_new(proto_pool);
- proto_flush_event->hook = proto_flush_all;
+ proto_flush_event->hook = proto_flush_loop;
+ proto_shutdown_timer = tm_new(proto_pool);
+ proto_shutdown_timer->hook = proto_shutdown_loop;
}
static void
@@ -647,7 +723,10 @@
log(L_ERR "Protocol %s is down but still has %d routes", p->name, p->stats.imp_routes);
bzero(&p->stats, sizeof(struct proto_stats));
- rt_unlock_table(p->table);
+ proto_free_ahooks(p);
+
+ if (! p->proto->multitable)
+ rt_unlock_table(p->table);
if (p->proto->cleanup)
p->proto->cleanup(p);
@@ -686,12 +765,110 @@
return;
DBG("Feeding protocol %s\n", p->name);
- proto_add_announce_hook(p, p->table);
+
if_feed_baby(p);
proto_feed_more(P);
}
static void
+proto_schedule_feed(struct proto *p, int initial)
+{
+ DBG("%s: Scheduling meal\n", p->name);
+ p->core_state = FS_FEEDING;
+ p->refeeding = !initial;
+
+ /* FIXME: This should be changed for better support of multitable protos */
+ if (!initial)
+ {
+ struct announce_hook *ah;
+ for (ah = p->ahooks; ah; ah = ah->next)
+ proto_reset_limit(ah->out_limit);
+
+ /* Hack: reset exp_routes during refeed, and do not decrease it later */
+ p->stats.exp_routes = 0;
+ }
+
+ /* Connect protocol to routing table */
+ if (initial && !p->proto->multitable)
+ {
+ p->main_ahook = proto_add_announce_hook(p, p->table, &p->stats);
+ p->main_ahook->in_filter = p->cf->in_filter;
+ p->main_ahook->out_filter = p->cf->out_filter;
+ p->main_ahook->in_limit = p->cf->in_limit;
+ p->main_ahook->out_limit = p->cf->out_limit;
+ proto_reset_limit(p->main_ahook->in_limit);
+ proto_reset_limit(p->main_ahook->out_limit);
+ }
+
+ proto_relink(p);
+ p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
+ ev_schedule(p->attn);
+}
+
+/*
+ * Flushing loop is responsible for flushing routes and protocols
+ * after they went down. It runs in proto_flush_event. At the start of
+ * one round, protocols waiting to flush are marked in
+ * proto_schedule_flush_loop(). At the end of the round (when routing
+ * table flush is complete), marked protocols are flushed and a next
+ * round may start.
+ */
+
+static int flush_loop_state; /* 1 -> running */
+
+static void
+proto_schedule_flush_loop(void)
+{
+ struct proto *p;
+
+ if (flush_loop_state)
+ return;
+ flush_loop_state = 1;
+
+ rt_schedule_prune_all();
+ WALK_LIST(p, flush_proto_list)
+ p->flushing = 1;
+
+ ev_schedule(proto_flush_event);
+}
+
+static void
+proto_flush_loop(void *unused UNUSED)
+{
+ struct proto *p;
+
+ if (! rt_prune_loop())
+ {
+ /* Rtable pruning is not finished */
+ ev_schedule(proto_flush_event);
+ return;
+ }
+
+ again:
+ WALK_LIST(p, flush_proto_list)
+ if (p->flushing)
+ {
+ /* This will flush interfaces in the same manner
+ like rt_prune_all() flushes routes */
+ if (p->proto == &proto_unix_iface)
+ if_flush_ifaces(p);
+
+ DBG("Flushing protocol %s\n", p->name);
+ p->flushing = 0;
+ p->core_state = FS_HUNGRY;
+ proto_relink(p);
+ if (p->proto_state == PS_DOWN)
+ proto_fell_down(p);
+ goto again;
+ }
+
+ /* This round finished, perhaps there will be another one */
+ flush_loop_state = 0;
+ if (!EMPTY_LIST(flush_proto_list))
+ proto_schedule_flush_loop();
+}
+
+static void
proto_schedule_flush(struct proto *p)
{
/* Need to abort feeding */
@@ -701,26 +878,49 @@
DBG("%s: Scheduling flush\n", p->name);
p->core_state = FS_FLUSHING;
proto_relink(p);
- proto_flush_hooks(p);
- ev_schedule(proto_flush_event);
+ proto_unlink_ahooks(p);
+ proto_schedule_flush_loop();
}
+/* Temporary hack to propagate restart to BGP */
+int proto_restart;
+
static void
-proto_schedule_feed(struct proto *p, int initial)
+proto_shutdown_loop(struct timer *t UNUSED)
{
- DBG("%s: Scheduling meal\n", p->name);
- p->core_state = FS_FEEDING;
- p->refeeding = !initial;
+ struct proto *p, *p_next;
- /* Hack: reset exp_routes during refeed, and do not decrease it later */
- if (!initial)
- p->stats.exp_routes = 0;
+ WALK_LIST_DELSAFE(p, p_next, active_proto_list)
+ if (p->down_sched)
+ {
+ proto_restart = (p->down_sched == PDS_RESTART);
- proto_relink(p);
- p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
- ev_schedule(p->attn);
+ p->disabled = 1;
+ proto_rethink_goal(p);
+ if (proto_restart)
+ {
+ p->disabled = 0;
+ proto_rethink_goal(p);
+ }
+ }
}
+static inline void
+proto_schedule_down(struct proto *p, byte restart, byte code)
+{
+ /* Does not work for other states (even PS_START) */
+ ASSERT(p->proto_state == PS_UP);
+
+ /* Scheduled restart may change to shutdown, but not otherwise */
+ if (p->down_sched == PDS_DISABLE)
+ return;
+
+ p->down_sched = restart ? PDS_RESTART : PDS_DISABLE;
+ p->down_code = code;
+ tm_start_max(proto_shutdown_timer, restart ? 2 : 0);
+}
+
+
/**
* proto_request_feeding - request feeding routes to the protocol
* @p: given protocol
@@ -750,6 +950,62 @@
proto_schedule_feed(p, 0);
}
+static const char *
+proto_limit_name(struct proto_limit *l)
+{
+ const char *actions[] = {
+ [PLA_WARN] = "warn",
+ [PLA_BLOCK] = "block",
+ [PLA_RESTART] = "restart",
+ [PLA_DISABLE] = "disable",
+ };
+
+ return actions[l->action];
+}
+
+/**
+ * proto_notify_limit: notify about limit hit and take appropriate action
+ * @ah: announce hook
+ * @l: limit being hit
+ * @rt_count: the number of routes
+ *
+ * The function is called by the route processing core when limit @l
+ * is breached. It activates the limit and tooks appropriate action
+ * according to @l->action.
+ */
+void
+proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count)
+{
+ struct proto *p = ah->proto;
+ int dir = (ah->in_limit == l);
+
+ if (l->state == PLS_BLOCKED)
+ return;
+
+ /* For warning action, we want the log message every time we hit the limit */
+ if (!l->state || ((l->action == PLA_WARN) && (rt_count == l->limit)))
+ log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
+ p->name, dir ? "import" : "export", l->limit, proto_limit_name(l));
+
+ switch (l->action)
+ {
+ case PLA_WARN:
+ l->state = PLS_ACTIVE;
+ break;
+
+ case PLA_BLOCK:
+ l->state = PLS_BLOCKED;
+ break;
+
+ case PLA_RESTART:
+ case PLA_DISABLE:
+ l->state = PLS_BLOCKED;
+ proto_schedule_down(p, l->action == PLA_RESTART,
+ dir ? PDC_IN_LIMIT_HIT : PDC_OUT_LIMIT_HIT);
+ break;
+ }
+}
+
/**
* proto_notify_state - notify core about protocol state change
* @p: protocol the state of which has changed
@@ -779,6 +1035,8 @@
switch (ps)
{
case PS_DOWN:
+ p->down_code = 0;
+ p->down_sched = 0;
if ((cs == FS_FEEDING) || (cs == FS_HAPPY))
proto_schedule_flush(p);
@@ -802,6 +1060,7 @@
proto_schedule_feed(p, 1);
break;
case PS_STOP:
+ p->down_sched = 0;
if ((cs == FS_FEEDING) || (cs == FS_HAPPY))
proto_schedule_flush(p);
break;
@@ -810,27 +1069,6 @@
}
}
-static void
-proto_flush_all(void *unused UNUSED)
-{
- struct proto *p;
-
- rt_prune_all();
- while ((p = HEAD(flush_proto_list))->n.next)
- {
- /* This will flush interfaces in the same manner
- like rt_prune_all() flushes routes */
- if (p->proto == &proto_unix_iface)
- if_flush_ifaces(p);
-
- DBG("Flushing protocol %s\n", p->name);
- p->core_state = FS_HUNGRY;
- proto_relink(p);
- if (p->proto_state == PS_DOWN)
- proto_fell_down(p);
- }
-}
-
/*
* CLI Commands
*/
@@ -855,9 +1093,8 @@
}
static void
-proto_do_show_stats(struct proto *p)
+proto_show_stats(struct proto_stats *s)
{
- struct proto_stats *s = &p->stats;
cli_msg(-1006, " Routes: %u imported, %u exported, %u preferred",
s->imp_routes, s->exp_routes, s->pref_routes);
cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
@@ -875,47 +1112,30 @@
s->exp_withdraws_received, s->exp_withdraws_accepted);
}
-#ifdef CONFIG_PIPE
-static void
-proto_do_show_pipe_stats(struct proto *p)
+void
+proto_show_limit(struct proto_limit *l, const char *dsc)
{
- struct proto_stats *s1 = &p->stats;
- struct proto_stats *s2 = pipe_get_peer_stats(p);
+ if (!l)
+ return;
- /*
- * Pipe stats (as anything related to pipes) are a bit tricky. There
- * are two sets of stats - s1 for routes going from the primary
- * routing table to the secondary routing table ('exported' from the
- * user point of view) and s2 for routes going in the other
- * direction ('imported' from the user point of view).
- *
- * Each route going through a pipe is, technically, first exported
- * to the pipe and then imported from that pipe and such operations
- * are counted in one set of stats according to the direction of the
- * route propagation. Filtering is done just in the first part
- * (export). Therefore, we compose stats for one directon for one
- * user direction from both import and export stats, skipping
- * immediate and irrelevant steps (exp_updates_accepted,
- * imp_updates_received, imp_updates_filtered, ...)
- */
+ cli_msg(-1006, " %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
+ cli_msg(-1006, " Action: %s", proto_limit_name(l));
+}
- cli_msg(-1006, " Routes: %u imported, %u exported",
- s2->imp_routes, s1->imp_routes);
- cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
- cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
- s2->exp_updates_received, s2->exp_updates_rejected + s2->imp_updates_invalid,
- s2->exp_updates_filtered, s2->imp_updates_ignored, s2->imp_updates_accepted);
- cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u",
- s2->exp_withdraws_received, s2->imp_withdraws_invalid,
- s2->imp_withdraws_ignored, s2->imp_withdraws_accepted);
- cli_msg(-1006, " Export updates: %10u %10u %10u %10u %10u",
- s1->exp_updates_received, s1->exp_updates_rejected + s1->imp_updates_invalid,
- s1->exp_updates_filtered, s1->imp_updates_ignored, s1->imp_updates_accepted);
- cli_msg(-1006, " Export withdraws: %10u %10u --- %10u %10u",
- s1->exp_withdraws_received, s1->imp_withdraws_invalid,
- s1->imp_withdraws_ignored, s1->imp_withdraws_accepted);
+void
+proto_show_basic_info(struct proto *p)
+{
+ // cli_msg(-1006, " Table: %s", p->table->name);
+ cli_msg(-1006, " Preference: %d", p->preference);
+ cli_msg(-1006, " Input filter: %s", filter_name(p->cf->in_filter));
+ cli_msg(-1006, " Output filter: %s", filter_name(p->cf->out_filter));
+
+ proto_show_limit(p->cf->in_limit, "Import limit:");
+ proto_show_limit(p->cf->out_limit, "Export limit:");
+
+ if (p->proto_state != PS_DOWN)
+ proto_show_stats(&p->stats);
}
-#endif
void
proto_cmd_show(struct proto *p, unsigned int verbose, int cnt)
@@ -943,22 +1163,11 @@
cli_msg(-1006, " Description: %s", p->cf->dsc);
if (p->cf->router_id)
cli_msg(-1006, " Router ID: %R", p->cf->router_id);
- cli_msg(-1006, " Preference: %d", p->preference);
- cli_msg(-1006, " Input filter: %s", filter_name(p->in_filter));
- cli_msg(-1006, " Output filter: %s", filter_name(p->out_filter));
-
- if (p->proto_state != PS_DOWN)
- {
-#ifdef CONFIG_PIPE
- if (proto_is_pipe(p))
- proto_do_show_pipe_stats(p);
- else
-#endif
- proto_do_show_stats(p);
- }
if (p->proto->show_proto_info)
p->proto->show_proto_info(p);
+ else
+ proto_show_basic_info(p);
cli_msg(-1006, "");
}
@@ -975,6 +1184,7 @@
log(L_INFO "Disabling protocol %s", p->name);
p->disabled = 1;
+ p->down_code = PDC_CMD_DISABLE;
proto_rethink_goal(p);
cli_msg(-9, "%s: disabled", p->name);
}
@@ -1005,6 +1215,7 @@
log(L_INFO "Restarting protocol %s", p->name);
p->disabled = 1;
+ p->down_code = PDC_CMD_RESTART;
proto_rethink_goal(p);
p->disabled = 0;
proto_rethink_goal(p);
@@ -1028,12 +1239,21 @@
/* re-importing routes */
if (dir != CMD_RELOAD_OUT)
- if (! (p->reload_routes && p->reload_routes(p)))
- {
- cli_msg(-8006, "%s: reload failed", p->name);
- return;
- }
-
+ {
+ if (! (p->reload_routes && p->reload_routes(p)))
+ {
+ cli_msg(-8006, "%s: reload failed", p->name);
+ return;
+ }
+
+ /*
+ * Should be done before reload_routes() hook?
+ * Perhaps, but these hooks work asynchronously.
+ */
+ if (!p->proto->multitable)
+ proto_reset_limit(p->main_ahook->in_limit);
+ }
+
/* re-exporting routes */
if (dir != CMD_RELOAD_IN)
proto_request_feeding(p);
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/nest/protocol.h
^
|
@@ -39,6 +39,7 @@
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 */
+ int multitable; /* Protocol handles all announce hooks itself */
unsigned preference; /* Default protocol preference */
void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */
@@ -93,13 +94,15 @@
u32 router_id; /* Protocol specific router ID */
struct rtable_config *table; /* Table we're attached to */
struct filter *in_filter, *out_filter; /* Attached filters */
+ struct proto_limit *in_limit; /* Limit for importing routes from protocol */
+ struct proto_limit *out_limit; /* Limit for exporting routes to protocol */
/* Check proto_reconfigure() and proto_copy_config() after changing struct proto_config */
/* Protocol-specific data follow... */
};
- /* Protocol statistics */
+/* Protocol statistics */
struct proto_stats {
/* Import - from protocol to core */
u32 imp_routes; /* Number of routes successfully imported to the (adjacent) routing table */
@@ -137,13 +140,16 @@
u32 debug; /* Debugging flags */
u32 mrtdump; /* MRTDump flags */
unsigned preference; /* Default route preference */
- unsigned accept_ra_types; /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */
- unsigned disabled; /* Manually disabled */
- unsigned proto_state; /* Protocol state machine (see below) */
- unsigned core_state; /* Core state machine (see below) */
- unsigned core_goal; /* State we want to reach (see below) */
- unsigned reconfiguring; /* We're shutting down due to reconfiguration */
- unsigned refeeding; /* We are refeeding (valid only if core_state == FS_FEEDING) */
+ byte accept_ra_types; /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */
+ byte disabled; /* Manually disabled */
+ byte proto_state; /* Protocol state machine (PS_*, see below) */
+ byte core_state; /* Core state machine (FS_*, see below) */
+ byte core_goal; /* State we want to reach (FS_*, see below) */
+ byte reconfiguring; /* We're shutting down due to reconfiguration */
+ byte refeeding; /* We are refeeding (valid only if core_state == FS_FEEDING) */
+ byte flushing; /* Protocol is flushed in current flush loop round */
+ byte down_sched; /* Shutdown is scheduled for later (PDS_*) */
+ byte down_code; /* Reason for shutdown (PDC_* codes) */
u32 hash_key; /* Random key used for hashing of neighbors */
bird_clock_t last_state_change; /* Time of last state transition */
char *last_state_name_announced; /* Last state name we've announced to the user */
@@ -193,8 +199,7 @@
void (*rte_remove)(struct network *, struct rte *);
struct rtable *table; /* Our primary routing table */
- struct filter *in_filter; /* Input filter */
- struct filter *out_filter; /* Output filter */
+ struct announce_hook *main_ahook; /* Primary announcement hook */
struct announce_hook *ahooks; /* Announcement hooks for this protocol */
struct fib_iterator *feed_iterator; /* Routing table iterator used during protocol feeding */
@@ -209,6 +214,19 @@
};
+#define PDS_DISABLE 1 /* Proto disable scheduled */
+#define PDS_RESTART 2 /* Proto restart scheduled */
+
+#define PDC_CF_REMOVE 0x01 /* Removed in new config */
+#define PDC_CF_DISABLE 0x02 /* Disabled in new config */
+#define PDC_CF_RESTART 0x03 /* Restart due to reconfiguration */
+#define PDC_CMD_DISABLE 0x11 /* Result of disable command */
+#define PDC_CMD_RESTART 0x12 /* Result of restart command */
+#define PDC_CMD_SHUTDOWN 0x13 /* Result of global shutdown */
+#define PDC_IN_LIMIT_HIT 0x21 /* Route import limit reached */
+#define PDC_OUT_LIMIT_HIT 0x22 /* Route export limit reached */
+
+
void *proto_new(struct proto_config *, unsigned size);
void *proto_config_new(struct protocol *, unsigned size, int class);
void proto_copy_config(struct proto_config *dest, struct proto_config *src);
@@ -218,6 +236,10 @@
proto_copy_rest(struct proto_config *dest, struct proto_config *src, unsigned size)
{ memcpy(dest + 1, src + 1, size - sizeof(struct proto_config)); }
+
+void proto_show_limit(struct proto_limit *l, const char *dsc);
+void proto_show_basic_info(struct proto *p);
+
void proto_cmd_show(struct proto *, unsigned int, int);
void proto_cmd_disable(struct proto *, unsigned int, int);
void proto_cmd_enable(struct proto *, unsigned int, int);
@@ -344,6 +366,36 @@
extern struct proto_config *cf_dev_proto;
+
+/*
+ * Protocol limits
+ */
+
+#define PLA_WARN 1 /* Issue log warning */
+#define PLA_BLOCK 2 /* Block new routes */
+#define PLA_RESTART 4 /* Force protocol restart */
+#define PLA_DISABLE 5 /* Shutdown and disable protocol */
+
+#define PLS_INITIAL 0 /* Initial limit state after protocol start */
+#define PLS_ACTIVE 1 /* Limit was hit */
+#define PLS_BLOCKED 2 /* Limit is active and blocking new routes */
+
+struct proto_limit {
+ u32 limit; /* Maximum number of prefixes */
+ byte action; /* Action to take (PLA_*) */
+ byte state; /* State of limit (PLS_*) */
+};
+
+void proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count);
+
+static inline void
+proto_reset_limit(struct proto_limit *l)
+{
+ if (l)
+ l->state = PLS_INITIAL;
+}
+
+
/*
* Route Announcement Hook
*/
@@ -352,18 +404,15 @@
node n;
struct rtable *table;
struct proto *proto;
+ struct filter *in_filter; /* Input filter */
+ struct filter *out_filter; /* Output filter */
+ struct proto_limit *in_limit; /* Input limit */
+ struct proto_limit *out_limit; /* Output limit */
+ struct proto_stats *stats; /* Per-table protocol statistics */
struct announce_hook *next; /* Next hook for the same protocol */
};
-struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *);
-
-/*
- * Some pipe-specific nest hacks
- */
-
-#ifdef CONFIG_PIPE
-#include "proto/pipe/pipe.h"
-#endif
-
+struct announce_hook *proto_add_announce_hook(struct proto *p, struct rtable *t, struct proto_stats *stats);
+struct announce_hook *proto_find_announce_hook(struct proto *p, struct rtable *t);
#endif
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/nest/route.h
^
|
@@ -12,6 +12,7 @@
#include "lib/lists.h"
#include "lib/resource.h"
#include "lib/timer.h"
+#include "nest/protocol.h"
struct protocol;
struct proto;
@@ -120,6 +121,7 @@
struct proto_config *krt_attached; /* Kernel syncer attached to this table */
int gc_max_ops; /* Maximum number of operations before GC is run */
int gc_min_time; /* Minimum time between two consecutive GC runs */
+ byte sorted; /* Routes of network are sorted according to rte_better() */
};
typedef struct rtable {
@@ -139,8 +141,10 @@
int gc_counter; /* Number of operations since last GC */
bird_clock_t gc_time; /* Time of last GC */
byte gc_scheduled; /* GC is scheduled */
+ byte prune_state; /* Table prune state, 1 -> prune is running */
byte hcu_scheduled; /* Hostcache update is scheduled */
byte nhu_state; /* Next Hop Update state */
+ struct fib_iterator prune_fit; /* Rtable prune FIB iterator */
struct fib_iterator nhu_fit; /* Next Hop Update FIB iterator */
} rtable;
@@ -179,7 +183,7 @@
typedef struct rte {
struct rte *next;
net *net; /* Network this RTE belongs to */
- struct proto *sender; /* Protocol instance that sent the route to the routing table */
+ struct announce_hook *sender; /* Announce hook used to send the route to the routing table */
struct rta *attrs; /* Attributes of this route */
byte flags; /* Flags (REF_...) */
byte pflags; /* Protocol-specific flags */
@@ -216,11 +220,12 @@
} u;
} rte;
-#define REF_COW 1 /* Copy this rte on write */
+#define REF_COW 1 /* Copy this rte on write */
/* Types of route announcement, also used as flags */
-#define RA_OPTIMAL 1 /* Announcement of optimal route change */
-#define RA_ANY 2 /* Announcement of any route change */
+#define RA_OPTIMAL 1 /* Announcement of optimal route change */
+#define RA_ACCEPTED 2 /* Announcement of first accepted route */
+#define RA_ANY 3 /* Announcement of any route change */
struct config;
@@ -234,7 +239,8 @@
static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
rte *rte_find(net *net, struct proto *p);
rte *rte_get_temp(struct rta *);
-void rte_update(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new);
+void rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src);
+static inline void rte_update(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new) { rte_update2(p->main_ahook, net, new, src); }
void rte_discard(rtable *tab, rte *old);
void rte_dump(rte *);
void rte_free(rte *);
@@ -244,7 +250,8 @@
void rt_dump_all(void);
int rt_feed_baby(struct proto *p);
void rt_feed_baby_abort(struct proto *p);
-void rt_prune_all(void);
+void rt_schedule_prune_all(void);
+int rt_prune_loop(void);
struct rtable_config *rt_new_table(struct symbol *s);
struct rt_show_data {
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/nest/rt-table.c
^
|
@@ -55,7 +55,6 @@
static void rt_notify_hostcache(rtable *tab, net *net);
static void rt_update_hostcache(rtable *tab);
static void rt_next_hop_update(rtable *tab);
-static void rt_prune(rtable *tab);
static inline void rt_schedule_gc(rtable *tab);
@@ -183,94 +182,120 @@
rte_trace(p, e, '<', msg);
}
-static inline void
-do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
+static rte *
+export_filter(struct announce_hook *ah, rte *rt0, rte **rt_free, ea_list **tmpa, int silent)
{
- struct proto *p = a->proto;
- struct filter *filter = p->out_filter;
- struct proto_stats *stats = &p->stats;
- rte *new0 = new;
- rte *old0 = old;
- int ok;
+ struct proto *p = ah->proto;
+ struct filter *filter = ah->out_filter;
+ struct proto_stats *stats = ah->stats;
+ ea_list *tmpb = NULL;
+ rte *rt;
+ int v;
+
+ rt = rt0;
+ *rt_free = NULL;
-#ifdef CONFIG_PIPE
- /* The secondary direction of the pipe */
- if (proto_is_pipe(p) && (p->table != a->table))
+ /* If called does not care for eattrs, we prepare one internally */
+ if (!tmpa)
{
- filter = p->in_filter;
- stats = pipe_get_peer_stats(p);
+ struct proto *src = rt->attrs->proto;
+ tmpb = src->make_tmp_attrs ? src->make_tmp_attrs(rt, rte_update_pool) : NULL;
+ tmpa = &tmpb;
}
-#endif
- if (new)
+ v = p->import_control ? p->import_control(p, &rt, tmpa, rte_update_pool) : 0;
+ if (v < 0)
{
- stats->exp_updates_received++;
+ if (silent)
+ goto reject;
- char *drop_reason = NULL;
- if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
- {
- stats->exp_updates_rejected++;
- drop_reason = "rejected by protocol";
- }
- else if (ok)
- rte_trace_out(D_FILTERS, p, new, "forced accept by protocol");
- else if ((filter == FILTER_REJECT) ||
- (filter && f_run(filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
- {
- stats->exp_updates_filtered++;
- drop_reason = "filtered out";
- }
- if (drop_reason)
- {
- rte_trace_out(D_FILTERS, p, new, drop_reason);
- if (new != new0)
- rte_free(new);
- new = NULL;
- }
+ stats->exp_updates_rejected++;
+ rte_trace_out(D_FILTERS, p, rt, "rejected by protocol");
+ goto reject;
+ }
+ if (v > 0)
+ {
+ if (!silent)
+ rte_trace_out(D_FILTERS, p, rt, "forced accept by protocol");
+ goto accept;
}
- else
- stats->exp_withdraws_received++;
+
+ v = filter && ((filter == FILTER_REJECT) ||
+ (f_run(filter, &rt, tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT));
+ if (v)
+ {
+ if (silent)
+ goto reject;
+
+ stats->exp_updates_filtered++;
+ rte_trace_out(D_FILTERS, p, rt, "filtered out");
+ goto reject;
+ }
+
+ accept:
+ if (rt != rt0)
+ *rt_free = rt;
+ return rt;
+
+ reject:
+ /* Discard temporary rte */
+ if (rt != rt0)
+ rte_free(rt);
+ return NULL;
+}
+
+static void
+do_rt_notify(struct announce_hook *ah, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
+{
+ struct proto *p = ah->proto;
+ struct proto_stats *stats = ah->stats;
+
/*
- * This is a tricky part - we don't know whether route 'old' was
- * exported to protocol 'p' or was filtered by the export filter.
- * We try tu run the export filter to know this to have a correct
- * value in 'old' argument of rte_update (and proper filter value)
+ * First, apply export limit.
*
- * FIXME - this is broken because 'configure soft' may change
- * filters but keep routes. Refeed is expected to be called after
- * change of the filters and with old == new, therefore we do not
- * even try to run the filter on an old route, This may lead to
- * 'spurious withdraws' but ensure that there are no 'missing
- * withdraws'.
+ * Export route limits has several problems. Because exp_routes
+ * counter is reset before refeed, we don't really know whether
+ * limit is breached and whether the update is new or not. Therefore
+ * the number of really exported routes may exceed the limit
+ * temporarily (routes exported before and new routes in refeed).
*
- * This is not completely safe as there is a window between
- * reconfiguration and the end of refeed - if a newly filtered
- * route disappears during this period, proper withdraw is not
- * sent (because old would be also filtered) and the route is
- * not refeeded (because it disappeared before that).
+ * Minor advantage is that if the limit is decreased and refeed is
+ * requested, the number of exported routes really decrease.
+ *
+ * Second problem is that with export limits, we don't know whether
+ * old was really exported (it might be blocked by limit). When a
+ * withdraw is exported, we announce it even when the previous
+ * update was blocked. This is not a big issue, but the same problem
+ * is in updating exp_routes counter. Therefore, to be consistent in
+ * increases and decreases of exp_routes, we count exported routes
+ * regardless of blocking by limits.
+ *
+ * Similar problem is in handling updates - when a new route is
+ * received and blocking is active, the route would be blocked, but
+ * when an update for the route will be received later, the update
+ * would be propagated (as old != NULL). Therefore, we have to block
+ * also non-new updates (contrary to import blocking).
*/
- if (old && !refeed)
+ struct proto_limit *l = ah->out_limit;
+ if (l && new)
{
- if (filter == FILTER_REJECT)
- old = NULL;
- else
+ if ((!old || refeed) && (stats->exp_routes >= l->limit))
+ proto_notify_limit(ah, l, stats->exp_routes);
+
+ if (l->state == PLS_BLOCKED)
{
- ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL;
- ok = p->import_control ? p->import_control(p, &old, &tmpb, rte_update_pool) : 0;
- if (ok < 0 || (!ok && filter && f_run(filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
- {
- if (old != old0)
- rte_free(old);
- old = NULL;
- }
+ stats->exp_routes++; /* see note above */
+ stats->exp_updates_rejected++;
+ rte_trace_out(D_FILTERS, p, new, "rejected [limit]");
+ new = NULL;
+
+ if (!old)
+ return;
}
}
- /* FIXME - This is broken because of incorrect 'old' value (see above) */
- if (!new && !old)
- return;
if (new)
stats->exp_updates_accepted++;
@@ -294,22 +319,184 @@
rte_trace_out(D_ROUTES, p, old, "removed");
}
if (!new)
- p->rt_notify(p, a->table, net, NULL, old, NULL);
+ p->rt_notify(p, ah->table, net, NULL, old, NULL);
else if (tmpa)
{
ea_list *t = tmpa;
while (t->next)
t = t->next;
t->next = new->attrs->eattrs;
- p->rt_notify(p, a->table, net, new, old, tmpa);
+ p->rt_notify(p, ah->table, net, new, old, tmpa);
t->next = NULL;
}
else
- p->rt_notify(p, a->table, net, new, old, new->attrs->eattrs);
- if (new && new != new0) /* Discard temporary rte's */
- rte_free(new);
- if (old && old != old0)
- rte_free(old);
+ p->rt_notify(p, ah->table, net, new, old, new->attrs->eattrs);
+}
+
+static void
+rt_notify_basic(struct announce_hook *ah, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
+{
+ // struct proto *p = ah->proto;
+ struct proto_stats *stats = ah->stats;
+
+ rte *new_free = NULL;
+ rte *old_free = NULL;
+
+ if (new)
+ stats->exp_updates_received++;
+ else
+ stats->exp_withdraws_received++;
+
+ /*
+ * This is a tricky part - we don't know whether route 'old' was
+ * exported to protocol 'p' or was filtered by the export filter.
+ * We try to run the export filter to know this to have a correct
+ * value in 'old' argument of rte_update (and proper filter value)
+ *
+ * FIXME - this is broken because 'configure soft' may change
+ * filters but keep routes. Refeed is expected to be called after
+ * change of the filters and with old == new, therefore we do not
+ * even try to run the filter on an old route, This may lead to
+ * 'spurious withdraws' but ensure that there are no 'missing
+ * withdraws'.
+ *
+ * This is not completely safe as there is a window between
+ * reconfiguration and the end of refeed - if a newly filtered
+ * route disappears during this period, proper withdraw is not
+ * sent (because old would be also filtered) and the route is
+ * not refeeded (because it disappeared before that).
+ */
+
+ if (new)
+ new = export_filter(ah, new, &new_free, &tmpa, 0);
+
+ if (old && !refeed)
+ old = export_filter(ah, old, &old_free, NULL, 1);
+
+ /* FIXME - This is broken because of incorrect 'old' value (see above) */
+ if (!new && !old)
+ return;
+
+ do_rt_notify(ah, net, new, old, tmpa, refeed);
+
+ /* Discard temporary rte's */
+ if (new_free)
+ rte_free(new_free);
+ if (old_free)
+ rte_free(old_free);
+}
+
+static void
+rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *old_changed, rte *before_old,
+ ea_list *tmpa, int feed)
+{
+ // struct proto *p = ah->proto;
+ struct proto_stats *stats = ah->stats;
+
+ rte *new_best = NULL;
+ rte *old_best = NULL;
+ rte *new_free = NULL;
+ rte *old_free = NULL;
+ rte *r;
+
+ /* Used to track whether we met old_changed position. If it is NULL
+ it was the first and met it implicitly before current best route. */
+ int old_meet = (old_changed && !before_old) ? 1 : 0;
+
+ if (new_changed)
+ stats->exp_updates_received++;
+ else
+ stats->exp_withdraws_received++;
+
+ /* First, find the new_best route - first accepted by filters */
+ for (r=net->routes; r; r=r->next)
+ {
+ if (new_best = export_filter(ah, r, &new_free, &tmpa, 0))
+ break;
+
+ /* Note if we walked around the position of old_changed route */
+ if (r == before_old)
+ old_meet = 1;
+ }
+
+ /*
+ * Second, handle the feed case. That means we do not care for
+ * old_best. It is NULL for feed, and the new_best for refeed.
+ * For refeed, there is a hack similar to one in rt_notify_basic()
+ * to ensure withdraws in case of changed filters
+ */
+ if (feed)
+ {
+ if (feed == 2) /* refeed */
+ old_best = new_best ? new_best : net->routes;
+ else
+ old_best = NULL;
+
+ if (!new_best && !old_best)
+ return;
+
+ goto found;
+ }
+
+ /*
+ * Now, we find the old_best route. Generally, it is the same as the
+ * new_best, unless new_best is the same as new_changed or
+ * old_changed is accepted before new_best.
+ *
+ * There are four cases:
+ *
+ * - We would find and accept old_changed before new_best, therefore
+ * old_changed is old_best. In remaining cases we suppose this
+ * is not true.
+ *
+ * - We found no new_best, therefore there is also no old_best and
+ * we ignore this withdraw.
+ *
+ * - We found new_best different than new_changed, therefore
+ * old_best is the same as new_best and we ignore this update.
+ *
+ * - We found new_best the same as new_changed, therefore it cannot
+ * be old_best and we have to continue search for old_best.
+ */
+
+ /* First case */
+ if (old_meet)
+ if (old_best = export_filter(ah, old_changed, &old_free, NULL, 1))
+ goto found;
+
+ /* Second case */
+ if (!new_best)
+ return;
+
+ /* Third case, we use r instead of new_best, because export_filter() could change it */
+ if (r != new_changed)
+ {
+ if (new_free)
+ rte_free(new_free);
+ return;
+ }
+
+ /* Fourth case */
+ for (r=r->next; r; r=r->next)
+ {
+ if (old_best = export_filter(ah, r, &old_free, NULL, 1))
+ goto found;
+
+ if (r == before_old)
+ if (old_best = export_filter(ah, old_changed, &old_free, NULL, 1))
+ goto found;
+ }
+
+ /* Implicitly, old_best is NULL and new_best is non-NULL */
+
+ found:
+ do_rt_notify(ah, net, new_best, old_best, tmpa, (feed == 2));
+
+ /* Discard temporary rte's */
+ if (new_free)
+ rte_free(new_free);
+ if (old_free)
+ rte_free(old_free);
}
/**
@@ -342,7 +529,7 @@
* the protocol gets called.
*/
static void
-rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list *tmpa)
+rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, rte *before_old, ea_list *tmpa)
{
struct announce_hook *a;
@@ -361,11 +548,13 @@
{
ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
if (a->proto->accept_ra_types == type)
- do_rte_announce(a, type, net, new, old, tmpa, 0);
+ if (type == RA_ACCEPTED)
+ rt_notify_accepted(a, net, new, old, before_old, tmpa, 0);
+ else
+ rt_notify_basic(a, net, new, old, tmpa, 0);
}
}
-
static inline int
rte_validate(rte *e)
{
@@ -375,7 +564,7 @@
if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
{
log(L_WARN "Ignoring bogus prefix %I/%d received via %s",
- n->n.prefix, n->n.pxlen, e->sender->name);
+ n->n.prefix, n->n.pxlen, e->sender->proto->name);
return 0;
}
@@ -383,7 +572,7 @@
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
{
log(L_WARN "Ignoring bogus route %I/%d received via %s",
- n->n.prefix, n->n.pxlen, e->sender->name);
+ n->n.prefix, n->n.pxlen, e->sender->proto->name);
return 0;
}
@@ -423,17 +612,15 @@
}
static void
-rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte *new, ea_list *tmpa)
+rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, struct proto *src)
{
- struct proto_stats *stats = &p->stats;
+ struct proto *p = ah->proto;
+ struct rtable *table = ah->table;
+ struct proto_stats *stats = ah->stats;
+ rte *before_old = NULL;
rte *old_best = net->routes;
rte *old = NULL;
- rte **k, *r, *s;
-
-#ifdef CONFIG_PIPE
- if (proto_is_pipe(p) && (p->table == table))
- stats = pipe_get_peer_stats(p);
-#endif
+ rte **k;
k = &net->routes; /* Find and remove original route from the same protocol */
while (old = *k)
@@ -449,7 +636,7 @@
* ignore it completely (there might be 'spurious withdraws',
* see FIXME in do_rte_announce())
*/
- if (old->sender != p)
+ if (old->sender->proto != p)
{
if (new)
{
@@ -478,14 +665,33 @@
break;
}
k = &old->next;
+ before_old = old;
}
+ if (!old)
+ before_old = NULL;
+
if (!old && !new)
{
stats->imp_withdraws_ignored++;
return;
}
+ struct proto_limit *l = ah->in_limit;
+ if (l && !old && new)
+ {
+ if (stats->imp_routes >= l->limit)
+ proto_notify_limit(ah, l, stats->imp_routes);
+
+ if (l->state == PLS_BLOCKED)
+ {
+ stats->imp_updates_ignored++;
+ rte_trace_in(D_FILTERS, p, new, "ignored [limit]");
+ rte_free_quick(new);
+ return;
+ }
+ }
+
if (new)
stats->imp_updates_accepted++;
else
@@ -496,82 +702,93 @@
if (old)
stats->imp_routes--;
- rte_announce(table, RA_ANY, net, new, old, tmpa);
-
- if (src->rte_recalculate && src->rte_recalculate(table, net, new, old, old_best))
- goto do_recalculate;
-
- if (new && rte_better(new, old_best))
+ if (table->config->sorted)
{
- /* The first case - the new route is cleary optimal, we link it
- at the first position and announce it */
+ /* If routes are sorted, just insert new route to appropriate position */
+ if (new)
+ {
+ if (before_old && !rte_better(new, before_old))
+ k = &before_old->next;
+ else
+ k = &net->routes;
+
+ for (; *k; k=&(*k)->next)
+ if (rte_better(new, *k))
+ break;
- rte_trace_in(D_ROUTES, p, new, "added [best]");
- rte_announce(table, RA_OPTIMAL, net, new, old_best, tmpa);
- new->next = net->routes;
- net->routes = new;
+ new->next = *k;
+ *k = new;
+ }
}
- else if (old == old_best)
+ else
{
- /* The second case - the old best route disappeared, we add the
- new route (if we have any) to the list (we don't care about
- position) and then we elect the new optimal route and relink
- that route at the first position and announce it. New optimal
- route might be NULL if there is no more routes */
+ /* If routes are not sorted, find the best route and move it on
+ the first position. There are several optimized cases. */
- do_recalculate:
- /* Add the new route to the list */
- if (new)
+ if (src->rte_recalculate && src->rte_recalculate(table, net, new, old, old_best))
+ goto do_recalculate;
+
+ if (new && rte_better(new, old_best))
{
- rte_trace_in(D_ROUTES, p, new, "added");
+ /* The first case - the new route is cleary optimal,
+ we link it at the first position */
+
new->next = net->routes;
net->routes = new;
}
-
- /* Find new optimal route */
- r = NULL;
- for (s=net->routes; s; s=s->next)
- if (rte_better(s, r))
- r = s;
-
- /* Announce optimal route */
- rte_announce(table, RA_OPTIMAL, net, r, old_best, tmpa);
-
- /* And relink it (if there is any) */
- if (r)
+ else if (old == old_best)
{
- k = &net->routes;
- while (s = *k)
+ /* The second case - the old best route disappeared, we add the
+ new route (if we have any) to the list (we don't care about
+ position) and then we elect the new optimal route and relink
+ that route at the first position and announce it. New optimal
+ route might be NULL if there is no more routes */
+
+ do_recalculate:
+ /* Add the new route to the list */
+ if (new)
{
- if (s == r)
- {
- *k = r->next;
- break;
- }
- k = &s->next;
+ new->next = net->routes;
+ net->routes = new;
}
- r->next = net->routes;
- net->routes = r;
+
+ /* Find a new optimal route (if there is any) */
+ if (net->routes)
+ {
+ rte **bp = &net->routes;
+ for (k=&(*bp)->next; *k; k=&(*k)->next)
+ if (rte_better(*k, *bp))
+ bp = k;
+
+ /* And relink it */
+ rte *best = *bp;
+ *bp = best->next;
+ best->next = net->routes;
+ net->routes = best;
+ }
+ }
+ else if (new)
+ {
+ /* The third case - the new route is not better than the old
+ best route (therefore old_best != NULL) and the old best
+ route was not removed (therefore old_best == net->routes).
+ We just link the new route after the old best route. */
+
+ ASSERT(net->routes != NULL);
+ new->next = net->routes->next;
+ net->routes->next = new;
}
- else if (table->gc_counter++ >= table->config->gc_max_ops &&
- table->gc_time + table->config->gc_min_time <= now)
- rt_schedule_gc(table);
+ /* The fourth (empty) case - suboptimal route was removed, nothing to do */
}
- else if (new)
- {
- /* The third case - the new route is not better than the old
- best route (therefore old_best != NULL) and the old best
- route was not removed (therefore old_best == net->routes).
- We just link the new route after the old best route. */
- ASSERT(net->routes != NULL);
- new->next = net->routes->next;
- net->routes->next = new;
- rte_trace_in(D_ROUTES, p, new, "added");
- }
+ if (new)
+ new->lastmod = now;
+
+ /* Log the route change */
+ if (new)
+ rte_trace_in(D_ROUTES, p, new, net->routes == new ? "added [best]" : "added");
- /* Log the route removal */
- if (!new && old && (p->debug & D_ROUTES))
+ if (!new && (p->debug & D_ROUTES))
{
if (old != old_best)
rte_trace_in(D_ROUTES, p, old, "removed");
@@ -581,6 +798,18 @@
rte_trace_in(D_ROUTES, p, old, "removed [sole]");
}
+ /* Propagate the route change */
+ rte_announce(table, RA_ANY, net, new, old, NULL, tmpa);
+ if (net->routes != old_best)
+ rte_announce(table, RA_OPTIMAL, net, net->routes, old_best, NULL, tmpa);
+ if (table->config->sorted)
+ rte_announce(table, RA_ACCEPTED, net, new, old, before_old, tmpa);
+
+ if (!net->routes &&
+ (table->gc_counter++ >= table->config->gc_max_ops) &&
+ (table->gc_time + table->config->gc_min_time <= now))
+ rt_schedule_gc(table);
+
if (old)
{
if (p->rte_remove)
@@ -589,7 +818,6 @@
}
if (new)
{
- new->lastmod = now;
if (p->rte_insert)
p->rte_insert(net, new);
}
@@ -613,6 +841,7 @@
/**
* rte_update - enter a new update to a routing table
* @table: table to be updated
+ * @ah: pointer to table announce hook
* @net: network node
* @p: protocol submitting the update
* @src: protocol originating the update
@@ -652,28 +881,17 @@
*/
void
-rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new)
+rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src)
{
+ struct proto *p = ah->proto;
+ struct proto_stats *stats = ah->stats;
+ struct filter *filter = ah->in_filter;
ea_list *tmpa = NULL;
- struct proto_stats *stats = &p->stats;
-
-#ifdef CONFIG_PIPE
- if (proto_is_pipe(p) && (p->table == table))
- stats = pipe_get_peer_stats(p);
-#endif
rte_update_lock();
if (new)
{
- new->sender = p;
- struct filter *filter = p->in_filter;
-
- /* Do not filter routes going through the pipe,
- they are filtered in the export filter only. */
-#ifdef CONFIG_PIPE
- if (proto_is_pipe(p))
- filter = FILTER_ACCEPT;
-#endif
+ new->sender = ah;
stats->imp_updates_received++;
if (!rte_validate(new))
@@ -710,13 +928,13 @@
else
stats->imp_withdraws_received++;
- rte_recalculate(table, net, p, src, new, tmpa);
+ rte_recalculate(ah, net, new, tmpa, src);
rte_update_unlock();
return;
drop:
rte_free(new);
- rte_recalculate(table, net, p, src, NULL, NULL);
+ rte_recalculate(ah, net, NULL, NULL, src);
rte_update_unlock();
}
@@ -731,7 +949,7 @@
rte_update_lock();
src = new->attrs->proto;
tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(new, rte_update_pool) : NULL;
- rte_announce(tab, type, n, new, old, tmpa);
+ rte_announce(tab, type, n, new, old, NULL, tmpa);
rte_update_unlock();
}
@@ -739,7 +957,7 @@
rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */
{
rte_update_lock();
- rte_recalculate(t, old->net, old->sender, old->attrs->proto, NULL, NULL);
+ rte_recalculate(old->sender, old->net, NULL, NULL, old->attrs->proto);
rte_update_unlock();
}
@@ -753,10 +971,7 @@
rte_dump(rte *e)
{
net *n = e->net;
- if (n)
- debug("%-1I/%2d ", n->n.prefix, n->n.pxlen);
- else
- debug("??? ");
+ debug("%-1I/%2d ", n->n.prefix, n->n.pxlen);
debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod);
rta_dump(e->attrs);
if (e->attrs->proto->proto->dump_attrs)
@@ -838,6 +1053,38 @@
}
static void
+rt_prune_nets(rtable *tab)
+{
+ struct fib_iterator fit;
+ int ncnt = 0, ndel = 0;
+
+#ifdef DEBUGGING
+ fib_check(&tab->fib);
+#endif
+
+ FIB_ITERATE_INIT(&fit, &tab->fib);
+again:
+ FIB_ITERATE_START(&tab->fib, &fit, f)
+ {
+ net *n = (net *) f;
+ ncnt++;
+ if (!n->routes) /* Orphaned FIB entry */
+ {
+ FIB_ITERATE_PUT(&fit, f);
+ fib_delete(&tab->fib, f);
+ ndel++;
+ goto again;
+ }
+ }
+ FIB_ITERATE_END(f);
+ DBG("Pruned %d of %d networks\n", ndel, ncnt);
+
+ tab->gc_counter = 0;
+ tab->gc_time = now;
+ tab->gc_scheduled = 0;
+}
+
+static void
rt_event(void *ptr)
{
rtable *tab = ptr;
@@ -849,7 +1096,7 @@
rt_next_hop_update(tab);
if (tab->gc_scheduled)
- rt_prune(tab);
+ rt_prune_nets(tab);
}
void
@@ -885,70 +1132,96 @@
init_list(&routing_tables);
}
-/**
- * rt_prune - prune a routing table
- * @tab: routing table to be pruned
- *
- * This function is called whenever a protocol shuts down. It scans
- * the routing table and removes all routes belonging to inactive
- * protocols and also stale network entries.
- */
-static void
-rt_prune(rtable *tab)
+
+/* Called from proto_schedule_flush_loop() only,
+ ensuring that all prune states are zero */
+void
+rt_schedule_prune_all(void)
{
- struct fib_iterator fit;
- int rcnt = 0, rdel = 0, ncnt = 0, ndel = 0;
+ rtable *t;
+
+ WALK_LIST(t, routing_tables)
+ t->prune_state = 1;
+}
+
+static inline int
+rt_prune_step(rtable *tab, int *max_feed)
+{
+ struct fib_iterator *fit = &tab->prune_fit;
DBG("Pruning route table %s\n", tab->name);
#ifdef DEBUGGING
fib_check(&tab->fib);
#endif
- FIB_ITERATE_INIT(&fit, &tab->fib);
+
+ if (tab->prune_state == 0)
+ return 1;
+
+ if (tab->prune_state == 1)
+ {
+ FIB_ITERATE_INIT(fit, &tab->fib);
+ tab->prune_state = 2;
+ }
+
again:
- FIB_ITERATE_START(&tab->fib, &fit, f)
+ FIB_ITERATE_START(&tab->fib, fit, fn)
{
- net *n = (net *) f;
+ net *n = (net *) fn;
rte *e;
- ncnt++;
+
rescan:
- for (e=n->routes; e; e=e->next, rcnt++)
- if (e->sender->core_state != FS_HAPPY &&
- e->sender->core_state != FS_FEEDING)
+ for (e=n->routes; e; e=e->next)
+ if (e->sender->proto->core_state != FS_HAPPY &&
+ e->sender->proto->core_state != FS_FEEDING)
{
+ if (*max_feed <= 0)
+ {
+ FIB_ITERATE_PUT(fit, fn);
+ return 0;
+ }
+
rte_discard(tab, e);
- rdel++;
+ (*max_feed)--;
+
goto rescan;
}
- if (!n->routes) /* Orphaned FIB entry? */
+ if (!n->routes) /* Orphaned FIB entry */
{
- FIB_ITERATE_PUT(&fit, f);
- fib_delete(&tab->fib, f);
- ndel++;
+ FIB_ITERATE_PUT(fit, fn);
+ fib_delete(&tab->fib, fn);
goto again;
}
}
- FIB_ITERATE_END(f);
- DBG("Pruned %d of %d routes and %d of %d networks\n", rdel, rcnt, ndel, ncnt);
+ FIB_ITERATE_END(fn);
+
#ifdef DEBUGGING
fib_check(&tab->fib);
#endif
- tab->gc_counter = 0;
- tab->gc_time = now;
- tab->gc_scheduled = 0;
+
+ tab->prune_state = 0;
+ return 1;
}
/**
- * rt_prune_all - prune all routing tables
+ * rt_prune_loop - prune routing tables
+ * @tab: routing table to be pruned
*
- * This function calls rt_prune() for all known routing tables.
+ * The prune loop scans routing tables and removes routes belonging to
+ * inactive protocols and also stale network entries. Returns 1 when
+ * all such routes are pruned. It is a part of the protocol flushing
+ * loop.
*/
-void
-rt_prune_all(void)
+int
+rt_prune_loop(void)
{
rtable *t;
+ int max_feed = 512;
WALK_LIST(t, routing_tables)
- rt_prune(t);
+ if (! rt_prune_step(t, &max_feed))
+ return 0;
+
+ return 1;
}
void
@@ -1026,7 +1299,7 @@
*k = new;
rte_announce_i(tab, RA_ANY, n, new, e);
- rte_trace_in(D_ROUTES, new->sender, new, "updated");
+ rte_trace_in(D_ROUTES, new->sender->proto, new, "updated");
/* Call a pre-comparison hook */
/* Not really an efficient way to compute this */
@@ -1066,7 +1339,7 @@
if (new != old_best)
{
rte_announce_i(tab, RA_OPTIMAL, n, new, old_best);
- rte_trace_in(D_ROUTES, new->sender, new, "updated [best]");
+ rte_trace_in(D_ROUTES, new->sender->proto, new, "updated [best]");
}
if (free_old_best)
@@ -1113,6 +1386,10 @@
struct rtable_config *
rt_new_table(struct symbol *s)
{
+ /* Hack that allows to 'redefine' the master table */
+ if ((s->class == SYM_TABLE) && (s->def == new_config->master_rtc))
+ return s->def;
+
struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
cf_define_symbol(s, SYM_TABLE, c);
@@ -1195,6 +1472,8 @@
r->table = ot;
ot->name = r->name;
ot->config = r;
+ if (o->sorted != r->sorted)
+ log(L_WARN "Reconfiguration of rtable sorted flag not implemented");
}
else
{
@@ -1223,12 +1502,15 @@
static inline void
do_feed_baby(struct proto *p, int type, struct announce_hook *h, net *n, rte *e)
{
- struct proto *q = e->attrs->proto;
+ struct proto *src = e->attrs->proto;
ea_list *tmpa;
rte_update_lock();
- tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
- do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, p->refeeding);
+ tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(e, rte_update_pool) : NULL;
+ if (type == RA_ACCEPTED)
+ rt_notify_accepted(h, n, e, NULL, NULL, tmpa, p->refeeding ? 2 : 1);
+ else
+ rt_notify_basic(h, n, e, p->refeeding ? e : NULL, tmpa, p->refeeding);
rte_update_unlock();
}
@@ -1271,12 +1553,13 @@
return 0;
}
- if (p->accept_ra_types == RA_OPTIMAL)
+ if ((p->accept_ra_types == RA_OPTIMAL) ||
+ (p->accept_ra_types == RA_ACCEPTED))
if (e)
{
if (p->core_state != FS_FEEDING)
return 1; /* In the meantime, the protocol fell down. */
- do_feed_baby(p, RA_OPTIMAL, h, n, e);
+ do_feed_baby(p, p->accept_ra_types, h, n, e);
max_feed--;
}
@@ -1693,6 +1976,7 @@
{
rte *e, *ee;
byte ia[STD_ADDRESS_P_LENGTH+8];
+ struct announce_hook *a;
int ok;
bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
@@ -1700,14 +1984,14 @@
d->net_counter++;
for(e=n->routes; e; e=e->next)
{
- struct ea_list *tmpa, *old_tmpa;
+ struct ea_list *tmpa;
struct proto *p0 = e->attrs->proto;
struct proto *p1 = d->export_protocol;
struct proto *p2 = d->show_protocol;
d->rt_counter++;
ee = e;
rte_update_lock(); /* We use the update buffer for filtering */
- old_tmpa = tmpa = p0->make_tmp_attrs ? p0->make_tmp_attrs(e, rte_update_pool) : NULL;
+ tmpa = p0->make_tmp_attrs ? p0->make_tmp_attrs(e, rte_update_pool) : NULL;
ok = (d->filter == FILTER_ACCEPT || f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
if (p2 && p2 != p0) ok = 0;
if (ok && d->export_mode)
@@ -1722,8 +2006,8 @@
'configure soft' command may change the export filter
and do not update routes */
- if ((p1->out_filter == FILTER_REJECT) ||
- (p1->out_filter && f_run(p1->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
+ if ((a = proto_find_announce_hook(p1, d->table)) && ((a->out_filter == FILTER_REJECT) ||
+ (a->out_filter && f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)))
ok = 0;
}
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/bgp/attrs.c
^
|
@@ -1258,7 +1258,8 @@
static inline int
use_deterministic_med(rte *r)
{
- return ((struct bgp_proto *) r->attrs->proto)->cf->deterministic_med;
+ struct proto *P = r->attrs->proto;
+ return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med;
}
int
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/bgp/bgp.c
^
|
@@ -542,22 +542,6 @@
bgp_start_timer(conn->connect_retry_timer, delay);
}
-int
-bgp_apply_limits(struct bgp_proto *p)
-{
- if (p->cf->route_limit && (p->p.stats.imp_routes > p->cf->route_limit))
- {
- log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
- bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
- bgp_update_startup_delay(p);
- bgp_stop(p, 1); // Errcode 6, 1 - max number of prefixes reached
- return -1;
- }
-
- return 0;
-}
-
-
/**
* bgp_connect - initiate an outgoing connection
* @p: BGP instance
@@ -864,28 +848,59 @@
return PS_START;
}
+extern int proto_restart;
+
static int
bgp_shutdown(struct proto *P)
{
struct bgp_proto *p = (struct bgp_proto *) P;
- unsigned subcode;
+ unsigned subcode = 0;
BGP_TRACE(D_EVENTS, "Shutdown requested");
- bgp_store_error(p, NULL, BE_MAN_DOWN, 0);
- if (P->reconfiguring)
+ switch (P->down_code)
{
- if (P->cf_new)
- subcode = 6; // Errcode 6, 6 - other configuration change
+ case PDC_CF_REMOVE:
+ case PDC_CF_DISABLE:
+ subcode = 3; // Errcode 6, 3 - peer de-configured
+ break;
+
+ case PDC_CF_RESTART:
+ subcode = 6; // Errcode 6, 6 - other configuration change
+ break;
+
+ case PDC_CMD_DISABLE:
+ case PDC_CMD_SHUTDOWN:
+ subcode = 2; // Errcode 6, 2 - administrative shutdown
+ break;
+
+ case PDC_CMD_RESTART:
+ subcode = 4; // Errcode 6, 4 - administrative reset
+ break;
+
+ case PDC_IN_LIMIT_HIT:
+ subcode = 1; // Errcode 6, 1 - max number of prefixes reached
+ /* log message for compatibility */
+ log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
+ goto limit;
+
+ case PDC_OUT_LIMIT_HIT:
+ subcode = proto_restart ? 4 : 2; // Administrative reset or shutdown
+
+ limit:
+ bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
+ if (proto_restart)
+ bgp_update_startup_delay(p);
else
- subcode = 3; // Errcode 6, 3 - peer de-configured
+ p->startup_delay = 0;
+ goto done;
}
- else
- subcode = 2; // Errcode 6, 2 - administrative shutdown
+ bgp_store_error(p, NULL, BE_MAN_DOWN, 0);
p->startup_delay = 0;
- bgp_stop(p, subcode);
+ done:
+ bgp_stop(p, subcode);
return p->p.proto_state;
}
@@ -909,7 +924,7 @@
struct proto *P = proto_new(C, sizeof(struct bgp_proto));
struct bgp_proto *p = (struct bgp_proto *) P;
- P->accept_ra_types = RA_OPTIMAL;
+ P->accept_ra_types = c->secondary ? RA_ACCEPTED : RA_OPTIMAL;
P->rt_notify = bgp_rt_notify;
P->rte_better = bgp_rte_better;
P->import_control = bgp_import_control;
@@ -955,6 +970,7 @@
if (internal && c->rs_client)
cf_error("Only external neighbor can be RS client");
+
if (c->multihop && (c->gw_mode == GW_DIRECT))
cf_error("Multihop BGP cannot use direct gateway mode");
@@ -962,6 +978,7 @@
ipa_has_link_scope(c->source_addr)))
cf_error("Multihop BGP cannot be used with link-local addresses");
+
/* Different default based on rs_client */
if (!c->missing_lladdr)
c->missing_lladdr = c->rs_client ? MLL_IGNORE : MLL_SELF;
@@ -969,6 +986,20 @@
/* Different default for gw_mode */
if (!c->gw_mode)
c->gw_mode = (c->multihop || internal) ? GW_RECURSIVE : GW_DIRECT;
+
+ /* Disable after error incompatible with restart limit action */
+ if (c->c.in_limit && (c->c.in_limit->action == PLA_RESTART) && c->disable_after_error)
+ c->c.in_limit->action = PLA_DISABLE;
+
+
+ if ((c->gw_mode == GW_RECURSIVE) && c->c.table->sorted)
+ cf_error("BGP in recursive mode prohibits sorted table");
+
+ if (c->deterministic_med && c->c.table->sorted)
+ cf_error("BGP with deterministic MED prohibits sorted table");
+
+ if (c->secondary && !c->c.table->sorted)
+ cf_error("BGP with secondary option requires sorted table");
}
static int
@@ -1116,15 +1147,14 @@
bsprintf(buf, "%-14s%s%s", bgp_state_dsc(p), err1, err2);
}
-static inline bird_clock_t tm_remains(timer *t)
-{ return t->expires ? t->expires - now : 0; }
-
static void
bgp_show_proto_info(struct proto *P)
{
struct bgp_proto *p = (struct bgp_proto *) P;
struct bgp_conn *c = p->conn;
+ proto_show_basic_info(P);
+
cli_msg(-1006, " BGP state: %s", bgp_state_dsc(p));
cli_msg(-1006, " Neighbor address: %I%J", p->cf->remote_ip, p->cf->iface);
cli_msg(-1006, " Neighbor AS: %u", p->remote_as);
@@ -1156,9 +1186,9 @@
p->rs_client ? " route-server" : "",
p->as4_session ? " AS4" : "");
cli_msg(-1006, " Source address: %I", p->source_addr);
- if (p->cf->route_limit)
+ if (P->cf->in_limit)
cli_msg(-1006, " Route limit: %d/%d",
- p->p.stats.imp_routes, p->cf->route_limit);
+ p->p.stats.imp_routes, P->cf->in_limit->limit);
cli_msg(-1006, " Hold timer: %d/%d",
tm_remains(c->hold_timer), c->hold_time);
cli_msg(-1006, " Keepalive timer: %d/%d",
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/bgp/bgp.h
^
|
@@ -40,9 +40,9 @@
int rr_client; /* Whether neighbor is RR client of me */
int rs_client; /* Whether neighbor is RS client of me */
int advertise_ipv4; /* Whether we should add IPv4 capability advertisement to OPEN message */
- u32 route_limit; /* Number of routes that may be imported, 0 means disable limit */
int passive; /* Do not initiate outgoing connection */
int interpret_communities; /* Hardwired handling of well-known communities */
+ int secondary; /* Accept also non-best routes (i.e. RA_ACCEPTED) */
unsigned connect_retry_time;
unsigned hold_time, initial_hold_time;
unsigned keepalive_time;
@@ -152,7 +152,6 @@
void bgp_conn_enter_close_state(struct bgp_conn *conn);
void bgp_conn_enter_idle_state(struct bgp_conn *conn);
void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code);
-int bgp_apply_limits(struct bgp_proto *p);
void bgp_stop(struct bgp_proto *p, unsigned subcode);
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/bgp/config.Y
^
|
@@ -25,7 +25,8 @@
CLUSTER, ID, AS4, ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE,
PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
- TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC)
+ TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
+ SECONDARY)
CF_GRAMMAR
@@ -98,9 +99,14 @@
| bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
| bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }
| bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; }
- | bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; }
+ | bgp_proto ROUTE LIMIT expr ';' {
+ this_proto->in_limit = cfg_allocz(sizeof(struct proto_limit));
+ this_proto->in_limit->limit = $4;
+ this_proto->in_limit->action = PLA_RESTART;
+ }
| bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
| bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
+ | bgp_proto SECONDARY bool ';' { BGP_CFG->secondary = $3; }
| bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
| bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
;
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/bgp/packets.c
^
|
@@ -915,9 +915,6 @@
if (n = net_find(p->p.table, prefix, pxlen))
rte_update(p->p.table, n, &p->p, &p->p, NULL);
}
-
- if (bgp_apply_limits(p) < 0)
- goto done;
}
done:
@@ -1034,9 +1031,6 @@
if (n = net_find(p->p.table, prefix, pxlen))
rte_update(p->p.table, n, &p->p, &p->p, NULL);
}
-
- if (bgp_apply_limits(p) < 0)
- goto done;
}
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/config.Y
^
|
@@ -107,7 +107,17 @@
check_defcost(int cost)
{
if ((cost <= 0) || (cost >= LSINFINITY))
- cf_error("Default cost must be in range 1-%d", LSINFINITY);
+ cf_error("Default cost must be in range 1-%d", LSINFINITY-1);
+}
+
+static inline void
+set_instance_id(unsigned id)
+{
+#ifdef OSPFv3
+ OSPF_PATT->instance_id = id;
+#else
+ cf_error("Instance ID requires OSPFv3");
+#endif
}
CF_DECLS
@@ -120,7 +130,7 @@
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
-CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF)
+CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL)
%type <t> opttext
%type <ld> lsadb_args
@@ -218,8 +228,8 @@
;
ospf_vlink:
- ospf_vlink_start '{' ospf_vlink_opts '}' { ospf_iface_finish(); }
- | ospf_vlink_start { ospf_iface_finish(); }
+ ospf_vlink_start ospf_instance_id '{' ospf_vlink_opts '}' { ospf_iface_finish(); }
+ | ospf_vlink_start ospf_instance_id { ospf_iface_finish(); }
;
ospf_vlink_opts:
@@ -277,6 +287,7 @@
| TYPE PTP { OSPF_PATT->type = OSPF_IT_PTP ; }
| TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; }
| TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; }
+ | REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (OSPF_VERSION != 2) cf_error("Real broadcast option requires OSPFv2"); }
| TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
| PRIORITY expr { OSPF_PATT->priority = $2 ; if (($2<0) || ($2>255)) cf_error("Priority must be in range 0-255"); }
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
@@ -364,6 +375,11 @@
}
;
+ospf_instance_id:
+ /* empty */
+ | INSTANCE expr { set_instance_id($2); }
+ ;
+
ospf_iface_opts:
/* empty */
| ospf_iface_opts ospf_iface_item ';'
@@ -375,7 +391,7 @@
;
ospf_iface:
- ospf_iface_start iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); }
+ ospf_iface_start iface_patt_list ospf_instance_id ospf_iface_opt_list { ospf_iface_finish(); }
;
opttext:
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/hello.c
^
|
@@ -303,7 +303,7 @@
{
case OSPF_IT_BCAST:
case OSPF_IT_PTP:
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
break;
case OSPF_IT_NBMA:
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/iface.c
^
|
@@ -120,13 +120,24 @@
sk->saddr = ifa->addr->ip;
if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
{
- sk->ttl = 1; /* Hack, this will affect just multicast packets */
+ if (ifa->cf->real_bcast)
+ {
+ ifa->all_routers = ifa->addr->brd;
+
+ if (sk_set_broadcast(sk, 1) < 0)
+ goto err;
+ }
+ else
+ {
+ ifa->all_routers = AllSPFRouters;
+ sk->ttl = 1; /* Hack, this will affect just multicast packets */
- if (sk_setup_multicast(sk) < 0)
- goto err;
+ if (sk_setup_multicast(sk) < 0)
+ goto err;
- if (sk_join_group(sk, AllSPFRouters) < 0)
- goto err;
+ if (sk_join_group(sk, ifa->all_routers) < 0)
+ goto err;
+ }
}
ifa->sk = sk;
@@ -265,7 +276,7 @@
OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
- if ((ifa->type == OSPF_IT_BCAST) && ifa->sk)
+ if ((ifa->type == OSPF_IT_BCAST) && !ifa->cf->real_bcast && ifa->sk)
{
if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
ospf_sk_join_dr(ifa);
@@ -536,6 +547,7 @@
/* Check validity of interface type */
int old_type = ifa->type;
+ u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
#ifdef OSPFv2
if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
@@ -545,10 +557,10 @@
ifa->type = OSPF_IT_PTMP;
#endif
- if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & IF_MULTICAST))
+ if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag))
ifa->type = OSPF_IT_NBMA;
- if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & IF_MULTICAST))
+ if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & if_multi_flag))
ifa->type = OSPF_IT_PTMP;
if (ifa->type != old_type)
@@ -628,6 +640,9 @@
if (ifa->stub != new_stub)
return 0;
+ if (new->real_bcast != ifa->cf->real_bcast)
+ return 0;
+
ifa->cf = new;
ifa->marked = 0;
@@ -1099,11 +1114,15 @@
void
ospf_iface_info(struct ospf_iface *ifa)
{
- char *strict = "";
+ char *more = "";
if (ifa->strictnbma &&
((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
- strict = "(strict)";
+ more = " (strict)";
+
+ if (ifa->cf->real_bcast &&
+ ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)))
+ more = " (real)";
if (ifa->type == OSPF_IT_VLINK)
{
@@ -1124,11 +1143,10 @@
#else /* OSPFv3 */
cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
#endif
- cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict);
+ cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
}
- cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state],
- ifa->stub ? "(stub)" : "");
+ cli_msg(-1015, "\tState: %s%s", ospf_is[ifa->state], ifa->stub ? " (stub)" : "");
cli_msg(-1015, "\tPriority: %u", ifa->priority);
cli_msg(-1015, "\tCost: %u", ifa->cost);
if (ifa->oa->po->ecmp)
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/lsack.c
^
|
@@ -97,7 +97,9 @@
if (ifa->type == OSPF_IT_BCAST)
{
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
+ else if (ifa->cf->real_bcast)
+ ospf_send_to_bdr(ifa);
else
ospf_send_to(ifa, AllDRouters);
}
@@ -124,7 +126,9 @@
if (ifa->type == OSPF_IT_BCAST)
{
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
+ else if (ifa->cf->real_bcast)
+ ospf_send_to_bdr(ifa);
else
ospf_send_to(ifa, AllDRouters);
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/lsupd.c
^
|
@@ -314,7 +314,9 @@
{
case OSPF_IT_BCAST:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
+ else if (ifa->cf->real_bcast)
+ ospf_send_to_bdr(ifa);
else
ospf_send_to(ifa, AllDRouters);
break;
@@ -327,7 +329,7 @@
break;
case OSPF_IT_PTP:
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
break;
case OSPF_IT_PTMP:
@@ -500,15 +502,17 @@
continue;
}
#else /* OSPFv3 */
+ u16 scope = ntoht(lsa->type) & LSA_SCOPE_MASK;
+
/* 4.5.1 (2) */
- if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
+ if ((scope == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
{
log(L_WARN "Received LSA with AS scope in stub area from %I", n->ip);
continue;
}
/* 4.5.1 (3) */
- if ((LSA_SCOPE(lsa) == LSA_SCOPE_RES))
+ if (scope == LSA_SCOPE_RES)
{
log(L_WARN "Received LSA with invalid scope from %I", n->ip);
continue;
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/ospf.c
^
|
@@ -575,7 +575,7 @@
if (fn->x1 != EXT_EXPORT)
return;
- flush_ext_lsa(oa, fn);
+ flush_ext_lsa(oa, fn, oa_is_nssa(oa));
/* Old external route might blocked some NSSA translation */
if (po->areano > 1)
@@ -1145,16 +1145,16 @@
static inline void
show_lsa_sum_rt(struct top_hash_entry *he)
{
- u32 dst_rid, options;
+ u32 dst_rid;
#ifdef OSPFv2
struct ospf_lsa_sum *ls = he->lsa_body;
dst_rid = he->lsa.id;
- options = 0;
+ // options = 0;
#else /* OSPFv3 */
struct ospf_lsa_sum_rt *ls = he->lsa_body;
dst_rid = ls->drid;
- options = ls->options & OPTIONS_MASK;
+ // options = ls->options & OPTIONS_MASK;
#endif
cli_msg(-1016, "\t\txrouter %R metric %u", dst_rid, ls->metric);
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/ospf.h
^
|
@@ -205,6 +205,7 @@
bird_clock_t csn_use; /* Last time when packet with that CSN was sent */
#endif
+ ip_addr all_routers; /* */
ip_addr drip; /* Designated router */
ip_addr bdrip; /* Backup DR */
u32 drid;
@@ -790,22 +791,23 @@
u32 deadc;
u32 deadint;
u32 inftransdelay;
- u32 priority;
- u32 strictnbma;
list nbma_list;
+ u32 priority;
u32 voa;
u32 vid;
u16 rxbuf;
- u8 check_link;
- u8 ecmp_weight;
#define OSPF_RXBUF_NORMAL 0
#define OSPF_RXBUF_LARGE 1
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
- u32 autype; /* Not really used in OSPFv3 */
+ u16 autype; /* Not really used in OSPFv3 */
#define OSPF_AUTH_NONE 0
#define OSPF_AUTH_SIMPLE 1
#define OSPF_AUTH_CRYPT 2
#define OSPF_AUTH_CRYPT_SIZE 16
+ u8 strictnbma;
+ u8 check_link;
+ u8 ecmp_weight;
+ u8 real_bcast; /* Not really used in OSPFv3 */
#ifdef OSPFv2
list *passwords;
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/packet.c
^
|
@@ -273,7 +273,7 @@
int src_local, dst_local UNUSED, dst_mcast;
src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
- dst_mcast = ipa_equal(sk->laddr, AllSPFRouters) || ipa_equal(sk->laddr, AllDRouters);
+ dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, AllDRouters);
#ifdef OSPFv2
/* First, we eliminate packets with strange address combinations.
@@ -287,6 +287,9 @@
if (!dst_mcast && !dst_local)
return 1;
+ /* Ignore my own broadcast packets */
+ if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
+ return 1;
#else /* OSPFv3 */
/* In OSPFv3, src_local and dst_local mean link-local.
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/packet.h
^
|
@@ -19,6 +19,8 @@
void ospf_send_to_bdr(struct ospf_iface *ifa);
void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
+static inline void ospf_send_to_all(struct ospf_iface *ifa) { ospf_send_to(ifa, ifa->all_routers); }
+
static inline void * ospf_tx_buffer(struct ospf_iface *ifa) { return ifa->sk->tbuf; }
static inline unsigned
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/rt.c
^
|
@@ -1066,7 +1066,7 @@
originate_ext_lsa(po->backbone, fn, EXT_NSSA, rt_metric, rt_fwaddr, rt_tag, 0);
else if (fn->x1 == EXT_NSSA)
- flush_ext_lsa(po->backbone, fn);
+ flush_ext_lsa(po->backbone, fn, 0);
}
/* RFC 2328 16.7. p2 - find new/lost vlink endpoints */
@@ -1189,7 +1189,7 @@
if (oa_is_nssa(oa) && oa->ac->default_nssa)
originate_ext_lsa(oa, &default_nf->fn, 0, oa->ac->default_cost, IPA_NONE, 0, 0);
else
- flush_ext_lsa(oa, &default_nf->fn);
+ flush_ext_lsa(oa, &default_nf->fn, 1);
/* RFC 2328 16.4. (3) - precompute preferred ASBR entries */
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/topology.c
^
|
@@ -798,7 +798,7 @@
body = originate_sum_net_lsa_body(po, &lsa.length, fn, metric);
lsasum_calculate(&lsa, body);
- en = lsa_install_new(po, &lsa, dom, body);
+ lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
}
@@ -835,7 +835,7 @@
body = originate_sum_rt_lsa_body(po, &lsa.length, lsa.id, metric, options);
lsasum_calculate(&lsa, body);
- en = lsa_install_new(po, &lsa, dom, body);
+ lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
}
@@ -862,6 +862,9 @@
if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
{
+ OSPF_TRACE(D_EVENTS, "Flushing summary-LSA (id=%R, type=%d)",
+ en->lsa.id, en->lsa.type);
+
if ((type == ORT_NET) && check_sum_net_lsaid_collision(fn, en))
{
log(L_ERR "%s: LSAID collision for %I/%d",
@@ -873,9 +876,6 @@
en->lsa.age = LSA_MAXAGE;
en->lsa.sn = LSA_MAXSEQNO;
lsasum_calculate(&en->lsa, sum);
-
- OSPF_TRACE(D_EVENTS, "Flushing summary-LSA (id=%R, type=%d)",
- en->lsa.id, en->lsa.type);
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, oa->areaid, 1);
if (can_flush_lsa(po)) flush_lsa(en, po);
}
@@ -1117,7 +1117,7 @@
if (src)
fn->x1 = src;
- en = lsa_install_new(po, &lsa, dom, body);
+ lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
if (po->ebit == 0)
@@ -1131,15 +1131,11 @@
}
void
-flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn)
+flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int nssa)
{
struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
struct top_hash_entry *en;
- int nssa = oa_is_nssa(oa);
-
- OSPF_TRACE(D_EVENTS, "Flushing %s-LSA for %I/%d",
- nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
u32 dom = nssa ? oa->areaid : 0;
u32 type = nssa ? LSA_T_NSSA : LSA_T_EXT;
@@ -1147,6 +1143,9 @@
if (en = ospf_hash_find(po->gr, dom, lsaid, po->router_id, type))
{
+ OSPF_TRACE(D_EVENTS, "Flushing %s-LSA for %I/%d",
+ nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
+
if (check_ext_lsa(en, fn, 0, IPA_NONE, 0) < 0)
{
log(L_ERR "%s: LSAID collision for %I/%d",
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/ospf/topology.h
^
|
@@ -72,7 +72,7 @@
void originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options UNUSED);
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
void originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, u32 metric, ip_addr fwaddr, u32 tag, int pbit);
-void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn);
+void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int nssa);
#ifdef OSPFv2
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/pipe/pipe.c
^
|
@@ -16,6 +16,18 @@
*
* To avoid pipe loops, Pipe keeps a `being updated' flag in each routing
* table.
+ *
+ * A pipe has two announce hooks, the first connected to the main
+ * table, the second connected to the peer table. When a new route is
+ * announced on the main table, it gets checked by an export filter in
+ * ahook 1, and, after that, it is announced to the peer table via
+ * rte_update(), an import filter in ahook 2 is called. When a new
+ * route is announced in the peer table, an export filter in ahook2
+ * and an import filter in ahook 1 are used. Oviously, there is no
+ * need in filtering the same route twice, so both import filters are
+ * set to accept, while user configured 'import' and 'export' filters
+ * are used as export filters in ahooks 2 and 1. Route limits are
+ * handled similarly, but on the import side of ahooks.
*/
#undef LOCAL_DEBUG
@@ -24,6 +36,7 @@
#include "nest/iface.h"
#include "nest/protocol.h"
#include "nest/route.h"
+#include "nest/cli.h"
#include "conf/conf.h"
#include "filter/filter.h"
#include "lib/string.h"
@@ -34,7 +47,8 @@
pipe_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, ea_list *attrs)
{
struct pipe_proto *p = (struct pipe_proto *) P;
- rtable *dest = (src_table == P->table) ? p->peer : P->table; /* The other side of the pipe */
+ struct announce_hook *ah = (src_table == P->table) ? p->peer_ahook : P->main_ahook;
+ rtable *dst_table = ah->table;
struct proto *src;
net *nn;
@@ -44,13 +58,14 @@
if (!new && !old)
return;
- if (dest->pipe_busy)
+ if (dst_table->pipe_busy)
{
log(L_ERR "Pipe loop detected when sending %I/%d to table %s",
- n->n.prefix, n->n.pxlen, dest->name);
+ n->n.prefix, n->n.pxlen, dst_table->name);
return;
}
- nn = net_get(dest, n->n.prefix, n->n.pxlen);
+
+ nn = net_get(dst_table, n->n.prefix, n->n.pxlen);
if (new)
{
memcpy(&a, new->attrs, sizeof(rta));
@@ -85,14 +100,14 @@
}
src_table->pipe_busy = 1;
- rte_update(dest, nn, &p->p, (p->mode == PIPE_OPAQUE) ? &p->p : src, e);
+ rte_update2(ah, nn, e, (p->mode == PIPE_OPAQUE) ? &p->p : src);
src_table->pipe_busy = 0;
}
static int
pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpool *p UNUSED)
{
- struct proto *pp = (*ee)->sender;
+ struct proto *pp = (*ee)->sender->proto;
if (pp == P)
return -1; /* Avoid local loops automatically */
@@ -102,6 +117,8 @@
static int
pipe_reload_routes(struct proto *P)
{
+ struct pipe_proto *p = (struct pipe_proto *) P;
+
/*
* Because the pipe protocol feeds routes from both routing tables
* together, both directions are reloaded during refeed and 'reload
@@ -109,23 +126,52 @@
* request refeed when 'reload in' command is used.
*/
proto_request_feeding(P);
+
+ proto_reset_limit(P->main_ahook->in_limit);
+ proto_reset_limit(p->peer_ahook->in_limit);
+
return 1;
}
-static int
-pipe_start(struct proto *P)
+static struct proto *
+pipe_init(struct proto_config *C)
{
+ struct pipe_config *c = (struct pipe_config *) C;
+ struct proto *P = proto_new(C, sizeof(struct pipe_proto));
struct pipe_proto *p = (struct pipe_proto *) P;
- struct announce_hook *a;
- /* Clean up the secondary stats */
- bzero(&p->peer_stats, sizeof(struct proto_stats));
+ p->mode = c->mode;
+ p->peer_table = c->peer->table;
+ P->accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY;
+ P->rt_notify = pipe_rt_notify;
+ P->import_control = pipe_import_control;
+ P->reload_routes = pipe_reload_routes;
+
+ return P;
+}
- /* Lock the peer table, unlock is handled in pipe_cleanup() */
- rt_lock_table(p->peer);
+static int
+pipe_start(struct proto *P)
+{
+ struct pipe_config *cf = (struct pipe_config *) P->cf;
+ struct pipe_proto *p = (struct pipe_proto *) P;
- /* Connect the protocol also to the peer routing table. */
- a = proto_add_announce_hook(P, p->peer);
+ /* Lock both tables, unlock is handled in pipe_cleanup() */
+ rt_lock_table(P->table);
+ rt_lock_table(p->peer_table);
+
+ /* Going directly to PS_UP - prepare for feeding,
+ connect the protocol to both routing tables */
+
+ P->main_ahook = proto_add_announce_hook(P, P->table, &P->stats);
+ P->main_ahook->out_filter = cf->c.out_filter;
+ P->main_ahook->in_limit = cf->c.in_limit;
+ proto_reset_limit(P->main_ahook->in_limit);
+
+ p->peer_ahook = proto_add_announce_hook(P, p->peer_table, &p->peer_stats);
+ p->peer_ahook->out_filter = cf->c.in_filter;
+ p->peer_ahook->in_limit = cf->c.out_limit;
+ proto_reset_limit(p->peer_ahook->in_limit);
return PS_UP;
}
@@ -134,24 +180,15 @@
pipe_cleanup(struct proto *P)
{
struct pipe_proto *p = (struct pipe_proto *) P;
- rt_unlock_table(p->peer);
-}
-static struct proto *
-pipe_init(struct proto_config *C)
-{
- struct pipe_config *c = (struct pipe_config *) C;
- struct proto *P = proto_new(C, sizeof(struct pipe_proto));
- struct pipe_proto *p = (struct pipe_proto *) P;
+ bzero(&P->stats, sizeof(struct proto_stats));
+ bzero(&p->peer_stats, sizeof(struct proto_stats));
- p->peer = c->peer->table;
- p->mode = c->mode;
- P->accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY;
- P->rt_notify = pipe_rt_notify;
- P->import_control = pipe_import_control;
- P->reload_routes = pipe_reload_routes;
+ P->main_ahook = NULL;
+ p->peer_ahook = NULL;
- return P;
+ rt_unlock_table(P->table);
+ rt_unlock_table(p->peer_table);
}
static void
@@ -165,16 +202,40 @@
cf_error("Primary table and peer table must be different");
}
+extern int proto_reconfig_type;
+
static int
pipe_reconfigure(struct proto *P, struct proto_config *new)
{
- // struct pipe_proto *p = (struct pipe_proto *) P;
- struct pipe_config *o = (struct pipe_config *) P->cf;
- struct pipe_config *n = (struct pipe_config *) new;
+ struct pipe_proto *p = (struct pipe_proto *)P;
+ struct proto_config *old = P->cf;
+ struct pipe_config *oc = (struct pipe_config *) old;
+ struct pipe_config *nc = (struct pipe_config *) new;
- if ((o->peer->table != n->peer->table) || (o->mode != n->mode))
+ if ((oc->peer->table != nc->peer->table) || (oc->mode != nc->mode))
return 0;
+ /* Update output filters in ahooks */
+ if (P->main_ahook)
+ {
+ P->main_ahook->out_filter = new->out_filter;
+ P->main_ahook->in_limit = new->in_limit;
+ }
+
+ if (p->peer_ahook)
+ {
+ p->peer_ahook->out_filter = new->in_filter;
+ p->peer_ahook->in_limit = new->out_limit;
+ }
+
+ if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT))
+ return 1;
+
+ if ((new->preference != old->preference)
+ || ! filter_same(new->in_filter, old->in_filter)
+ || ! filter_same(new->out_filter, old->out_filter))
+ proto_request_feeding(P);
+
return 1;
}
@@ -190,19 +251,84 @@
{
struct pipe_proto *p = (struct pipe_proto *) P;
- bsprintf(buf, "%c> %s", (p->mode == PIPE_OPAQUE) ? '-' : '=', p->peer->name);
+ bsprintf(buf, "%c> %s", (p->mode == PIPE_OPAQUE) ? '-' : '=', p->peer_table->name);
+}
+
+static void
+pipe_show_stats(struct pipe_proto *p)
+{
+ struct proto_stats *s1 = &p->p.stats;
+ struct proto_stats *s2 = &p->peer_stats;
+
+ /*
+ * Pipe stats (as anything related to pipes) are a bit tricky. There
+ * are two sets of stats - s1 for ahook to the primary routing and
+ * s2 for the ahook to the secondary routing table. The user point
+ * of view is that routes going from the primary routing table to
+ * the secondary routing table are 'exported', while routes going in
+ * the other direction are 'imported'.
+ *
+ * Each route going through a pipe is, technically, first exported
+ * to the pipe and then imported from that pipe and such operations
+ * are counted in one set of stats according to the direction of the
+ * route propagation. Filtering is done just in the first part
+ * (export). Therefore, we compose stats for one directon for one
+ * user direction from both import and export stats, skipping
+ * immediate and irrelevant steps (exp_updates_accepted,
+ * imp_updates_received, imp_updates_filtered, ...).
+ *
+ * Rule of thumb is that stats s1 have the correct 'polarity'
+ * (imp/exp), while stats s2 have switched 'polarity'.
+ */
+
+ cli_msg(-1006, " Routes: %u imported, %u exported",
+ s1->imp_routes, s2->imp_routes);
+ cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
+ cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
+ s2->exp_updates_received, s2->exp_updates_rejected + s1->imp_updates_invalid,
+ s2->exp_updates_filtered, s1->imp_updates_ignored, s1->imp_updates_accepted);
+ cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u",
+ s2->exp_withdraws_received, s1->imp_withdraws_invalid,
+ s1->imp_withdraws_ignored, s1->imp_withdraws_accepted);
+ cli_msg(-1006, " Export updates: %10u %10u %10u %10u %10u",
+ s1->exp_updates_received, s1->exp_updates_rejected + s2->imp_updates_invalid,
+ s1->exp_updates_filtered, s2->imp_updates_ignored, s2->imp_updates_accepted);
+ cli_msg(-1006, " Export withdraws: %10u %10u --- %10u %10u",
+ s1->exp_withdraws_received, s2->imp_withdraws_invalid,
+ s2->imp_withdraws_ignored, s2->imp_withdraws_accepted);
+}
+
+static void
+pipe_show_proto_info(struct proto *P)
+{
+ struct pipe_proto *p = (struct pipe_proto *) P;
+ struct pipe_config *cf = (struct pipe_config *) P->cf;
+
+ // cli_msg(-1006, " Table: %s", P->table->name);
+ // cli_msg(-1006, " Peer table: %s", p->peer_table->name);
+ cli_msg(-1006, " Preference: %d", P->preference);
+ cli_msg(-1006, " Input filter: %s", filter_name(cf->c.in_filter));
+ cli_msg(-1006, " Output filter: %s", filter_name(cf->c.out_filter));
+
+ proto_show_limit(cf->c.in_limit, "Import limit:");
+ proto_show_limit(cf->c.out_limit, "Export limit:");
+
+ if (P->proto_state != PS_DOWN)
+ pipe_show_stats(p);
}
struct protocol proto_pipe = {
- name: "Pipe",
- template: "pipe%d",
- preference: DEF_PREF_PIPE,
- postconfig: pipe_postconfig,
- init: pipe_init,
- start: pipe_start,
- cleanup: pipe_cleanup,
- reconfigure: pipe_reconfigure,
- copy_config: pipe_copy_config,
- get_status: pipe_get_status,
+ name: "Pipe",
+ template: "pipe%d",
+ multitable: 1,
+ preference: DEF_PREF_PIPE,
+ postconfig: pipe_postconfig,
+ init: pipe_init,
+ start: pipe_start,
+ cleanup: pipe_cleanup,
+ reconfigure: pipe_reconfigure,
+ copy_config: pipe_copy_config,
+ get_status: pipe_get_status,
+ show_proto_info: pipe_show_proto_info
};
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/pipe/pipe.h
^
|
@@ -20,7 +20,8 @@
struct pipe_proto {
struct proto p;
- struct rtable *peer;
+ struct rtable *peer_table;
+ struct announce_hook *peer_ahook; /* Announce hook for direction peer->primary */
struct proto_stats peer_stats; /* Statistics for the direction peer->primary */
int mode; /* PIPE_OPAQUE or PIPE_TRANSPARENT */
};
@@ -31,10 +32,4 @@
static inline int proto_is_pipe(struct proto *p)
{ return p->proto == &proto_pipe; }
-static inline struct rtable * pipe_get_peer_table(struct proto *P)
-{ return ((struct pipe_proto *) P)->peer; }
-
-static inline struct proto_stats * pipe_get_peer_stats(struct proto *P)
-{ return &((struct pipe_proto *) P)->peer_stats; }
-
#endif
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/radv/config.Y
^
|
@@ -14,32 +14,45 @@
#define RADV_CFG ((struct radv_config *) this_proto)
#define RADV_IFACE ((struct radv_iface_config *) this_ipatt)
#define RADV_PREFIX this_radv_prefix
+#define RADV_RDNSS (&this_radv_rdnss)
+#define RADV_DNSSL (&this_radv_dnssl)
static struct radv_prefix_config *this_radv_prefix;
+static struct radv_rdnss_config this_radv_rdnss;
+static struct radv_dnssl_config this_radv_dnssl;
+static list radv_dns_list; /* Used by radv_rdnss and radv_dnssl */
+static u8 radv_mult_val; /* Used by radv_mult for second return value */
+
CF_DECLS
CF_KEYWORDS(RADV, PREFIX, INTERFACE, MIN, MAX, RA, DELAY, INTERVAL,
MANAGED, OTHER, CONFIG, LINK, MTU, REACHABLE, TIME, RETRANS,
- TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED,
- LIFETIME, SKIP, ONLINK, AUTONOMOUS)
+ TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED, MULT,
+ LIFETIME, SKIP, ONLINK, AUTONOMOUS, RDNSS, DNSSL, NS, DOMAIN,
+ LOCAL)
+%type<i> radv_mult
CF_GRAMMAR
-CF_ADDTO(proto, radv_proto '}')
+CF_ADDTO(proto, radv_proto)
radv_proto_start: proto_start RADV
{
this_proto = proto_config_new(&proto_radv, sizeof(struct radv_config), $1);
init_list(&RADV_CFG->patt_list);
init_list(&RADV_CFG->pref_list);
+ init_list(&RADV_CFG->rdnss_list);
+ init_list(&RADV_CFG->dnssl_list);
};
radv_proto_item:
proto_item
- | PREFIX radv_prefix { add_tail(&RADV_CFG->pref_list, NODE this_radv_prefix); }
| INTERFACE radv_iface
+ | PREFIX radv_prefix { add_tail(&RADV_CFG->pref_list, NODE this_radv_prefix); }
+ | RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_CFG->rdnss_list, &radv_dns_list); }
+ | DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_CFG->dnssl_list, &radv_dns_list); }
;
radv_proto_opts:
@@ -48,7 +61,7 @@
;
radv_proto:
- radv_proto_start proto_name '{' radv_proto_opts;
+ radv_proto_start proto_name '{' radv_proto_opts '}';
radv_iface_start:
@@ -57,6 +70,8 @@
add_tail(&RADV_CFG->patt_list, NODE this_ipatt);
init_list(&this_ipatt->ipn_list);
init_list(&RADV_IFACE->pref_list);
+ init_list(&RADV_IFACE->rdnss_list);
+ init_list(&RADV_IFACE->dnssl_list);
RADV_IFACE->min_ra_int = -1; /* undefined */
RADV_IFACE->max_ra_int = DEFAULT_MAX_RA_INT;
@@ -77,6 +92,10 @@
| CURRENT HOP LIMIT expr { RADV_IFACE->current_hop_limit = $4; if (($4 < 0) || ($4 > 255)) cf_error("Current hop limit must be in range 0-255"); }
| DEFAULT LIFETIME expr { RADV_IFACE->default_lifetime = $3; if (($3 < 0) || ($3 > 9000)) cf_error("Default lifetime must be in range 0-9000"); }
| PREFIX radv_prefix { add_tail(&RADV_IFACE->pref_list, NODE this_radv_prefix); }
+ | RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_IFACE->rdnss_list, &radv_dns_list); }
+ | DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_IFACE->dnssl_list, &radv_dns_list); }
+ | RDNSS LOCAL bool { RADV_IFACE->rdnss_local = $3; }
+ | DNSSL LOCAL bool { RADV_IFACE->dnssl_local = $3; }
;
radv_iface_finish:
@@ -152,6 +171,103 @@
radv_prefix_start radv_prefix_opt_list radv_prefix_finish;
+
+radv_rdnss_node: ipa
+{
+ struct radv_rdnss_config *cf = cfg_allocz(sizeof(struct radv_rdnss_config));
+ add_tail(&radv_dns_list, NODE cf);
+
+ cf->server = $1;
+ cf->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
+};
+
+radv_rdnss_start:
+{
+ RADV_RDNSS->lifetime = 0;
+ RADV_RDNSS->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
+};
+
+radv_rdnss_item:
+ | NS radv_rdnss_node
+ | LIFETIME radv_mult { RADV_RDNSS->lifetime = $2; RADV_RDNSS->lifetime_mult = radv_mult_val; }
+ ;
+
+radv_rdnss_finish:
+{
+ if (EMPTY_LIST(radv_dns_list))
+ cf_error("No nameserver in RDNSS section");
+
+ struct radv_rdnss_config *cf;
+ WALK_LIST(cf, radv_dns_list)
+ {
+ cf->lifetime = RADV_RDNSS->lifetime;
+ cf->lifetime_mult = RADV_RDNSS->lifetime_mult;
+ }
+};
+
+radv_rdnss_opts:
+ /* empty */
+ | radv_rdnss_opts radv_rdnss_item ';'
+ ;
+
+radv_rdnss:
+ radv_rdnss_node
+ | '{' radv_rdnss_start radv_rdnss_opts '}' radv_rdnss_finish
+ ;
+
+
+radv_dnssl_node: TEXT
+{
+ struct radv_dnssl_config *cf = cfg_allocz(sizeof(struct radv_dnssl_config));
+ add_tail(&radv_dns_list, NODE cf);
+
+ cf->domain = $1;
+ cf->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
+
+ if (radv_process_domain(cf) < 0)
+ cf_error("Invalid domain dame");
+};
+
+radv_dnssl_start:
+{
+ RADV_DNSSL->lifetime = 0;
+ RADV_DNSSL->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
+};
+
+radv_dnssl_item:
+ | DOMAIN radv_dnssl_node
+ | LIFETIME radv_mult { RADV_DNSSL->lifetime = $2; RADV_DNSSL->lifetime_mult = radv_mult_val; }
+ ;
+
+radv_dnssl_finish:
+{
+ if (EMPTY_LIST(radv_dns_list))
+ cf_error("No domain in DNSSL section");
+
+ struct radv_dnssl_config *cf;
+ WALK_LIST(cf, radv_dns_list)
+ {
+ cf->lifetime = RADV_DNSSL->lifetime;
+ cf->lifetime_mult = RADV_DNSSL->lifetime_mult;
+ }
+};
+
+radv_dnssl_opts:
+ /* empty */
+ | radv_dnssl_opts radv_dnssl_item ';'
+ ;
+
+radv_dnssl:
+ radv_dnssl_node
+ | '{' radv_dnssl_start radv_dnssl_opts '}' radv_dnssl_finish
+ ;
+
+
+radv_mult:
+ expr { $$ = $1; radv_mult_val = 0; }
+ | MULT expr { $$ = 0; radv_mult_val = $2; if (($2 < 1) || ($2 > 254)) cf_error("Multiplier must be in range 1-254"); }
+ ;
+
CF_CODE
CF_END
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/radv/packets.c
^
|
@@ -24,8 +24,10 @@
#define OPT_RA_MANAGED 0x80
#define OPT_RA_OTHER_CFG 0x40
-#define OPT_PREFIX 3
-#define OPT_MTU 5
+#define OPT_PREFIX 3
+#define OPT_MTU 5
+#define OPT_RDNSS 25
+#define OPT_DNSSL 31
struct radv_opt_prefix
{
@@ -50,6 +52,25 @@
u32 mtu;
};
+struct radv_opt_rdnss
+{
+ u8 type;
+ u8 length;
+ u16 reserved;
+ u32 lifetime;
+ ip_addr servers[];
+};
+
+struct radv_opt_dnssl
+{
+ u8 type;
+ u8 length;
+ u16 reserved;
+ u32 lifetime;
+ char domain[];
+};
+
+
static struct radv_prefix_config default_prefix = {
.onlink = 1,
.autonomous = 1,
@@ -57,6 +78,7 @@
.preferred_lifetime = DEFAULT_PREFERRED_LIFETIME
};
+
static struct radv_prefix_config *
radv_prefix_match(struct radv_iface *ifa, struct ifa *a)
{
@@ -78,10 +100,146 @@
return &default_prefix;
}
+static int
+radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *bufend)
+{
+ struct radv_rdnss_config *rcf = HEAD(*rdnss_list);
+
+ while(NODE_VALID(rcf))
+ {
+ struct radv_rdnss_config *rcf_base = rcf;
+ struct radv_opt_rdnss *op = (void *) *buf;
+ int max_i = (bufend - *buf - sizeof(struct radv_opt_rdnss)) / sizeof(ip_addr);
+ int i = 0;
+
+ if (max_i < 1)
+ goto too_much;
+
+ op->type = OPT_RDNSS;
+ op->reserved = 0;
+
+ if (rcf->lifetime_mult)
+ op->lifetime = htonl(rcf->lifetime_mult * ifa->cf->max_ra_int);
+ else
+ op->lifetime = htonl(rcf->lifetime);
+
+ while(NODE_VALID(rcf) &&
+ (rcf->lifetime == rcf_base->lifetime) &&
+ (rcf->lifetime_mult == rcf_base->lifetime_mult))
+ {
+ if (i >= max_i)
+ goto too_much;
+
+ op->servers[i] = rcf->server;
+ ipa_hton(op->servers[i]);
+ i++;
+
+ rcf = NODE_NEXT(rcf);
+ }
+
+ op->length = 1+2*i;
+ *buf += 8 * op->length;
+ }
+
+ return 0;
+
+ too_much:
+ log(L_WARN "%s: Too many RA options on interface %s",
+ ifa->ra->p.name, ifa->iface->name);
+ return -1;
+}
+
+int
+radv_process_domain(struct radv_dnssl_config *cf)
+{
+ /* Format of domain in search list is <size> <label> <size> <label> ... 0 */
+
+ char *dom = cf->domain;
+ char *dom_end = dom; /* Just to */
+ u8 *dlen_save = &cf->dlen_first;
+ int len;
+
+ while (dom_end)
+ {
+ dom_end = strchr(dom, '.');
+ len = dom_end ? (dom_end - dom) : strlen(dom);
+
+ if (len < 1 || len > 63)
+ return -1;
+
+ *dlen_save = len;
+ dlen_save = (u8 *) dom_end;
+
+ dom += len + 1;
+ }
+
+ len = dom - cf->domain;
+ if (len > 254)
+ return -1;
+
+ cf->dlen_all = len;
+
+ return 0;
+}
+
+static int
+radv_prepare_dnssl(struct radv_iface *ifa, list *dnssl_list, char **buf, char *bufend)
+{
+ struct radv_dnssl_config *dcf = HEAD(*dnssl_list);
+
+ while(NODE_VALID(dcf))
+ {
+ struct radv_dnssl_config *dcf_base = dcf;
+ struct radv_opt_dnssl *op = (void *) *buf;
+ int bsize = bufend - *buf - sizeof(struct radv_opt_dnssl);
+ int bpos = 0;
+
+ if (bsize < 0)
+ goto too_much;
+
+ bsize = bsize & ~7; /* Round down to multiples of 8 */
+
+ op->type = OPT_DNSSL;
+ op->reserved = 0;
+
+ if (dcf->lifetime_mult)
+ op->lifetime = htonl(dcf->lifetime_mult * ifa->cf->max_ra_int);
+ else
+ op->lifetime = htonl(dcf->lifetime);
+
+ while(NODE_VALID(dcf) &&
+ (dcf->lifetime == dcf_base->lifetime) &&
+ (dcf->lifetime_mult == dcf_base->lifetime_mult))
+ {
+ if (bpos + dcf->dlen_all + 1 > bsize)
+ goto too_much;
+
+ op->domain[bpos++] = dcf->dlen_first;
+ memcpy(op->domain + bpos, dcf->domain, dcf->dlen_all);
+ bpos += dcf->dlen_all;
+
+ dcf = NODE_NEXT(dcf);
+ }
+
+ int blen = (bpos + 7) / 8;
+ bzero(op->domain + bpos, 8 * blen - bpos);
+ op->length = 1 + blen;
+ *buf += 8 * op->length;
+ }
+
+ return 0;
+
+ too_much:
+ log(L_WARN "%s: Too many RA options on interface %s",
+ ifa->ra->p.name, ifa->iface->name);
+ return -1;
+}
+
static void
radv_prepare_ra(struct radv_iface *ifa)
{
struct proto_radv *ra = ifa->ra;
+ struct radv_config *cf = (struct radv_config *) (ra->p.cf);
char *buf = ifa->sk->tbuf;
char *bufstart = buf;
@@ -121,7 +279,7 @@
if (buf + sizeof(struct radv_opt_prefix) > bufend)
{
log(L_WARN "%s: Too many prefixes on interface %s", ra->p.name, ifa->iface->name);
- break;
+ goto done;
}
struct radv_opt_prefix *op = (void *) buf;
@@ -137,7 +295,22 @@
ipa_hton(op->prefix);
buf += sizeof(*op);
}
-
+
+ if (! ifa->cf->rdnss_local)
+ if (radv_prepare_rdnss(ifa, &cf->rdnss_list, &buf, bufend) < 0)
+ goto done;
+
+ if (radv_prepare_rdnss(ifa, &ifa->cf->rdnss_list, &buf, bufend) < 0)
+ goto done;
+
+ if (! ifa->cf->dnssl_local)
+ if (radv_prepare_dnssl(ifa, &cf->dnssl_list, &buf, bufend) < 0)
+ goto done;
+
+ if (radv_prepare_dnssl(ifa, &ifa->cf->dnssl_list, &buf, bufend) < 0)
+ goto done;
+
+ done:
ifa->plen = buf - bufstart;
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/radv/radv.c
^
|
@@ -29,6 +29,10 @@
* radv_iface_notify(), which processes asynchronous events (specified
* by RA_EV_* codes), and radv_timer(), which triggers sending RAs and
* computes the next timeout.
+ *
+ * Supported standards:
+ * - RFC 4861 - main RA standard
+ * - RFC 6106 - DNS extensions (RDDNS, DNSSL)
*/
static void
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/radv/radv.h
^
|
@@ -42,24 +42,33 @@
#define DEFAULT_VALID_LIFETIME 86400
#define DEFAULT_PREFERRED_LIFETIME 14400
+#define DEFAULT_DNS_LIFETIME_MULT 3
+
struct radv_config
{
struct proto_config c;
list patt_list; /* List of iface configs (struct radv_iface_config) */
list pref_list; /* Global list of prefix configs (struct radv_prefix_config) */
+ list rdnss_list; /* Global list of RDNSS configs (struct radv_rdnss_config) */
+ list dnssl_list; /* Global list of DNSSL configs (struct radv_dnssl_config) */
};
struct radv_iface_config
{
struct iface_patt i;
list pref_list; /* Local list of prefix configs (struct radv_prefix_config) */
+ list rdnss_list; /* Local list of RDNSS configs (struct radv_rdnss_config) */
+ list dnssl_list; /* Local list of DNSSL configs (struct radv_dnssl_config) */
u32 min_ra_int; /* Standard options from RFC 4261 */
u32 max_ra_int;
u32 min_delay;
- u8 managed;
+ u8 rdnss_local; /* Global list is not used for RDNSS */
+ u8 dnssl_local; /* Global list is not used for DNSSL */
+
+ u8 managed; /* Standard options from RFC 4261 */
u8 other_config;
u32 link_mtu;
u32 reachable_time;
@@ -81,6 +90,25 @@
u32 preferred_lifetime;
};
+struct radv_rdnss_config
+{
+ node n;
+ u32 lifetime; /* Valid if lifetime_mult is 0 */
+ u16 lifetime_mult; /* Lifetime specified as multiple of max_ra_int */
+ ip_addr server; /* IP address of recursive DNS server */
+};
+
+struct radv_dnssl_config
+{
+ node n;
+ u32 lifetime; /* Valid if lifetime_mult is 0 */
+ u16 lifetime_mult; /* Lifetime specified as multiple of max_ra_int */
+ u8 dlen_first; /* Length of first label in domain */
+ u8 dlen_all; /* Both dlen_ filled in radv_process_domain() */
+ char *domain; /* Domain for DNS search list, in processed form */
+};
+
+
struct proto_radv
{
struct proto p;
@@ -123,6 +151,7 @@
void radv_iface_notify(struct radv_iface *ifa, int event);
/* packets.c */
+int radv_process_domain(struct radv_dnssl_config *cf);
void radv_send_ra(struct radv_iface *ifa, int shutdown);
int radv_sk_open(struct radv_iface *ifa);
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/rip/rip.c
^
|
@@ -624,7 +624,6 @@
int i;
node *w;
struct rip_interface *rif;
- i = 0;
CHK_MAGIC;
WALK_LIST( w, P->connections ) {
@@ -995,8 +994,8 @@
rip_get_attr(eattr *a, byte *buf, int buflen UNUSED)
{
switch (a->id) {
- case EA_RIP_METRIC: buf += bsprintf( buf, "metric: %d", a->u.data ); return GA_FULL;
- case EA_RIP_TAG: buf += bsprintf( buf, "tag: %d", a->u.data ); return GA_FULL;
+ case EA_RIP_METRIC: bsprintf( buf, "metric: %d", a->u.data ); return GA_FULL;
+ case EA_RIP_TAG: bsprintf( buf, "tag: %d", a->u.data ); return GA_FULL;
default: return GA_UNKNOWN;
}
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/proto/static/static.c
^
|
@@ -224,6 +224,9 @@
if (cf->igp_table)
rt_lock_table(cf->igp_table->table);
+ /* We have to go UP before routes could be installed */
+ proto_notify_state(p, PS_UP);
+
WALK_LIST(r, cf->other_routes)
static_add(p, cf, r);
return PS_UP;
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/autoconf.h.in
^
|
@@ -62,3 +62,4 @@
/* We have stdint.h */
#undef HAVE_STDINT_H
+#define CONFIG_PATH ?
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/bsd/Modules
^
|
@@ -1,6 +1,3 @@
-krt-scan.h
-krt-iface.h
-sysio.h
-krt-set.h
krt-sock.c
-krt-sock.h
+krt-sys.h
+sysio.h
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/bsd/krt-sock.c
^
|
@@ -33,7 +33,19 @@
#include "lib/string.h"
#include "lib/socket.h"
-int rt_sock = 0;
+
+#ifndef RTAX_MAX
+#define RTAX_MAX 8
+#endif
+
+struct ks_msg
+{
+ struct rt_msghdr rtm;
+ struct sockaddr_storage buf[RTAX_MAX];
+};
+
+
+static int rt_sock = 0;
int
krt_capable(rte *e)
@@ -189,7 +201,8 @@
}
void
-krt_set_notify(struct krt_proto *p UNUSED, net *n, rte *new, rte *old)
+krt_replace_rte(struct krt_proto *p UNUSED, net *n, rte *new, rte *old,
+ struct ea_list *eattrs UNUSED)
{
int err = 0;
@@ -205,45 +218,6 @@
n->n.flags &= ~KRF_SYNC_ERROR;
}
-static int
-krt_set_hook(sock *sk, int size UNUSED)
-{
- struct ks_msg msg;
- int l = read(sk->fd, (char *)&msg, sizeof(msg));
-
- if(l <= 0)
- log(L_ERR "krt-sock: read failed");
- else
- krt_read_msg((struct proto *)sk->data, &msg, 0);
-
- return 0;
-}
-
-void
-krt_set_start(struct krt_proto *x, int first UNUSED)
-{
- sock *sk_rt;
- static int ks_open_tried = 0;
-
- if (ks_open_tried)
- return;
-
- ks_open_tried = 1;
-
- DBG("KRT: Opening kernel socket\n");
-
- if( (rt_sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0)
- die("Cannot open kernel socket for routes");
-
- sk_rt = sk_new(krt_pool);
- sk_rt->type = SK_MAGIC;
- sk_rt->rx_hook = krt_set_hook;
- sk_rt->fd = rt_sock;
- sk_rt->data = x;
- if (sk_open(sk_rt))
- bug("krt-sock: sk_open failed");
-}
-
#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
static void
@@ -255,10 +229,11 @@
ip_addr idst, igate, imask;
void *body = (char *)msg->buf;
int new = (msg->rtm.rtm_type == RTM_ADD);
- int src;
char *errmsg = "KRT: Invalid route received";
int flags = msg->rtm.rtm_flags;
int addrs = msg->rtm.rtm_addrs;
+ int src;
+ byte src2;
if (!(flags & RTF_UP) && scan)
SKIP("not up in scan\n");
@@ -302,12 +277,17 @@
u32 self_mask = RTF_PROTO1;
u32 alien_mask = RTF_STATIC | RTF_PROTO1 | RTF_GATEWAY;
+ src2 = (flags & RTF_STATIC) ? 1 : 0;
+ src2 |= (flags & RTF_PROTO1) ? 2 : 0;
+
#ifdef RTF_PROTO2
alien_mask |= RTF_PROTO2;
+ src2 |= (flags & RTF_PROTO2) ? 4 : 0;
#endif
#ifdef RTF_PROTO3
alien_mask |= RTF_PROTO3;
+ src2 |= (flags & RTF_PROTO3) ? 8 : 0;
#endif
#ifdef RTF_REJECT
@@ -397,9 +377,9 @@
e = rte_get_temp(&a);
e->net = net;
e->u.krt.src = src;
+ e->u.krt.proto = src2;
/* These are probably too Linux-specific */
- e->u.krt.proto = 0;
e->u.krt.type = 0;
e->u.krt.metric = 0;
@@ -641,32 +621,6 @@
}
}
-void
-krt_scan_construct(struct krt_config *c UNUSED)
-{
-}
-
-void
-krt_scan_preconfig(struct config *c UNUSED)
-{
-}
-
-void
-krt_scan_postconfig(struct krt_config *c UNUSED)
-{
-}
-
-void
-krt_scan_start(struct krt_proto *x, int first UNUSED)
-{
- init_list(&x->scan.temp_ifs);
-}
-
-void
-krt_scan_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
-{
-}
-
static void
krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
{
@@ -725,13 +679,13 @@
static size_t kif_buflen = 4096;
void
-krt_scan_fire(struct krt_proto *p)
+krt_do_scan(struct krt_proto *p)
{
krt_sysctl_scan((struct proto *)p, p->krt_pool, &krt_buffer, &krt_buflen, NET_RT_DUMP);
}
void
-krt_if_scan(struct kif_proto *p)
+kif_do_scan(struct kif_proto *p)
{
struct proto *P = (struct proto *)p;
if_start_update();
@@ -739,14 +693,47 @@
if_end_update();
}
+static int
+krt_sock_hook(sock *sk, int size UNUSED)
+{
+ struct ks_msg msg;
+ int l = read(sk->fd, (char *)&msg, sizeof(msg));
+
+ if(l <= 0)
+ log(L_ERR "krt-sock: read failed");
+ else
+ krt_read_msg((struct proto *)sk->data, &msg, 0);
+
+ return 0;
+}
void
-krt_set_construct(struct krt_config *c UNUSED)
+krt_sys_start(struct krt_proto *x, int first UNUSED)
{
+ sock *sk_rt;
+ static int ks_open_tried = 0;
+
+ if (ks_open_tried)
+ return;
+
+ ks_open_tried = 1;
+
+ DBG("KRT: Opening kernel socket\n");
+
+ if( (rt_sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0)
+ die("Cannot open kernel socket for routes");
+
+ sk_rt = sk_new(krt_pool);
+ sk_rt->type = SK_MAGIC;
+ sk_rt->rx_hook = krt_sock_hook;
+ sk_rt->fd = rt_sock;
+ sk_rt->data = x;
+ if (sk_open(sk_rt))
+ bug("krt-sock: sk_open failed");
}
void
-krt_set_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
+krt_sys_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
{
if (!krt_buffer)
return;
@@ -755,23 +742,14 @@
krt_buffer = NULL;
}
-void
-krt_if_io_init(void)
-{
-}
-
-void
-krt_if_construct(struct kif_config *c UNUSED)
-{
-}
void
-krt_if_start(struct kif_proto *p UNUSED)
+kif_sys_start(struct kif_proto *p UNUSED)
{
}
void
-krt_if_shutdown(struct kif_proto *p UNUSED)
+kif_sys_shutdown(struct kif_proto *p UNUSED)
{
if (!kif_buffer)
return;
|
[-]
[+]
|
Added |
bird-1.3.8.tar.bz2/sysdep/bsd/krt-sys.h
^
|
@@ -0,0 +1,49 @@
+/*
+ * BIRD -- *BSD Kernel Route Syncer
+ *
+ * (c) 2004 Ondrej Filip <feela@network.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_KRT_SYS_H_
+#define _BIRD_KRT_SYS_H_
+
+
+/* Kernel interfaces */
+
+struct kif_params {
+};
+
+struct kif_status {
+};
+
+
+static inline void kif_sys_init(struct kif_proto *p UNUSED) { }
+static inline int kif_sys_reconfigure(struct kif_proto *p UNUSED, struct kif_config *n UNUSED, struct kif_config *o UNUSED) { return 1; }
+
+static inline void kif_sys_preconfig(struct config *c UNUSED) { }
+static inline void kif_sys_postconfig(struct kif_config *c UNUSED) { }
+static inline void kif_sys_init_config(struct kif_config *c UNUSED) { }
+static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_config *s UNUSED) { }
+
+
+/* Kernel routes */
+
+struct krt_params {
+};
+
+struct krt_status {
+};
+
+
+static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
+static inline int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n UNUSED, struct krt_config *o UNUSED) { return 1; }
+
+static inline void krt_sys_preconfig(struct config *c UNUSED) { }
+static inline void krt_sys_postconfig(struct krt_config *c UNUSED) { }
+static inline void krt_sys_init_config(struct krt_config *c UNUSED) { }
+static inline void krt_sys_copy_config(struct krt_config *d UNUSED, struct krt_config *s UNUSED) { }
+
+
+#endif
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/cf/README
^
|
@@ -5,19 +5,9 @@
CONFIG_SELF_CONSCIOUS We're able to recognize whether route was installed by us
CONFIG_MULTIPLE_TABLES The kernel supports multiple routing tables
CONFIG_ALL_TABLES_AT_ONCE Kernel scanner wants to process all tables at once
-CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket saddr field
-CONFIG_RESTRICTED_PRIVILEGES Implements restricted privileges using drop_uid()
-CONFIG_UNIX_IFACE Use Unix interface scanner
-CONFIG_UNIX_SET Use Unix route setting
-CONFIG_UNIX_DONTROUTE Use setsockopts DONTROUTE (undef for *BSD)
+CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket saddr field
CONFIG_SKIP_MC_BIND Don't call bind on multicast socket (def for *BSD)
-CONFIG_LINUX_SCAN Use Linux /proc/net/route scanner
-
-CONFIG_ALL_MULTICAST krt-iface: All devices support multicasting (i.e., ignore IFF_MULTICAST)
-CONFIG_UNNUM_MULTICAST krt-iface: We support multicasts on unnumbered PtP devices
-
-CONFIG_LINUX_MC_MREQN Linux: Use struct mreqn for multicasting
-CONFIG_LINUX_MC_MREQ Linux: Use struct mreq
-CONFIG_LINUX_MC_MREQ_BIND Linux: Use struct mreq and SO_BINDTODEVICE
+CONFIG_UNIX_DONTROUTE Use setsockopts DONTROUTE (undef for *BSD)
+CONFIG_RESTRICTED_PRIVILEGES Implements restricted privileges using drop_uid()
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/cf/bsd-v6.h
^
|
@@ -10,14 +10,8 @@
#define CONFIG_AUTO_ROUTES
#define CONFIG_SELF_CONSCIOUS
-#undef CONFIG_MULTIPLE_TABLES
-
-#undef CONFIG_UNIX_IFACE
-#undef CONFIG_UNIX_SET
#define CONFIG_SKIP_MC_BIND
-#define CONFIG_ALL_MULTICAST
-#define CONFIG_UNNUM_MULTICAST
/*
Link: sysdep/unix
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/cf/bsd.h
^
|
@@ -8,15 +8,8 @@
#define CONFIG_AUTO_ROUTES
#define CONFIG_SELF_CONSCIOUS
-#undef CONFIG_MULTIPLE_TABLES
-
-#undef CONFIG_UNIX_IFACE
-#undef CONFIG_UNIX_SET
-#undef CONFIG_UNIX_DONTROUTE
#define CONFIG_SKIP_MC_BIND
-#define CONFIG_ALL_MULTICAST
-#define CONFIG_UNNUM_MULTICAST
/*
Link: sysdep/unix
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/cf/linux-v6.h
^
|
@@ -1,5 +1,5 @@
/*
- * Configuration for Linux 2.2 based systems running IPv6
+ * Configuration for Linux based systems running IPv6
*
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
*
@@ -9,20 +9,13 @@
#define IPV6
#define CONFIG_AUTO_ROUTES
-#define CONFIG_ALL_MULTICAST
#define CONFIG_SELF_CONSCIOUS
-
-/*
- * Netlink supports multiple tables, but kernel IPv6 code doesn't, so we
- * treat it as a multiple table system with number of tables set to 1.
- */
#define CONFIG_MULTIPLE_TABLES
#define CONFIG_ALL_TABLES_AT_ONCE
#define CONFIG_RESTRICTED_PRIVILEGES
/*
-Link: sysdep/linux/netlink
Link: sysdep/linux
Link: sysdep/unix
*/
|
[-]
[+]
|
Added |
bird-1.3.8.tar.bz2/sysdep/cf/linux.h
^
|
@@ -0,0 +1,22 @@
+/*
+ * Configuration for Linux based systems
+ *
+ * (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#define CONFIG_AUTO_ROUTES
+#define CONFIG_SELF_CONSCIOUS
+#define CONFIG_MULTIPLE_TABLES
+#define CONFIG_ALL_TABLES_AT_ONCE
+
+#define CONFIG_MC_PROPER_SRC
+#define CONFIG_UNIX_DONTROUTE
+
+#define CONFIG_RESTRICTED_PRIVILEGES
+
+/*
+Link: sysdep/linux
+Link: sysdep/unix
+ */
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/config.h
^
|
@@ -7,7 +7,7 @@
#define _BIRD_CONFIG_H_
/* BIRD version */
-#define BIRD_VERSION "1.3.7"
+#define BIRD_VERSION "1.3.8"
/* Include parameters determined by configure script */
#include "sysdep/autoconf.h"
@@ -37,23 +37,4 @@
#endif
-/* Path to configuration file */
-#ifdef IPV6
-# ifdef DEBUGGING
-# define PATH_CONFIG "bird6.conf"
-# define PATH_CONTROL_SOCKET "bird6.ctl"
-# else
-# define PATH_CONFIG PATH_CONFIG_DIR "/bird6.conf"
-# define PATH_CONTROL_SOCKET PATH_CONTROL_SOCKET_DIR "/bird6.ctl"
-# endif
-#else
-# ifdef DEBUGGING
-# define PATH_CONFIG "bird.conf"
-# define PATH_CONTROL_SOCKET "bird.ctl"
-# else
-# define PATH_CONFIG PATH_CONFIG_DIR "/bird.conf"
-# define PATH_CONTROL_SOCKET PATH_CONTROL_SOCKET_DIR "/bird.ctl"
-# endif
-#endif
-
#endif
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/linux/Modules
^
|
@@ -1,6 +1,5 @@
-#ifdef CONFIG_LINUX_SCAN
-krt-scan.c
-krt-scan.h
-#endif
+krt-sys.h
+netlink.c
+netlink.Y
sysio.h
syspriv.h
|
[-]
[+]
|
Added |
bird-1.3.8.tar.bz2/sysdep/linux/krt-sys.h
^
|
@@ -0,0 +1,46 @@
+/*
+ * BIRD -- Linux Kernel Netlink Route Syncer
+ *
+ * (c) 1998--2000 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_KRT_SYS_H_
+#define _BIRD_KRT_SYS_H_
+
+
+/* Kernel interfaces */
+
+struct kif_params {
+};
+
+struct kif_status {
+};
+
+
+static inline void kif_sys_init(struct kif_proto *p UNUSED) { }
+static inline int kif_sys_reconfigure(struct kif_proto *p UNUSED, struct kif_config *n UNUSED, struct kif_config *o UNUSED) { return 1; }
+
+static inline void kif_sys_preconfig(struct config *c UNUSED) { }
+static inline void kif_sys_postconfig(struct kif_config *c UNUSED) { }
+static inline void kif_sys_init_config(struct kif_config *c UNUSED) { }
+static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_config *s UNUSED) { }
+
+
+/* Kernel routes */
+
+#define NL_NUM_TABLES 256
+
+struct krt_params {
+ int table_id; /* Kernel table ID we sync with */
+};
+
+struct krt_status {
+};
+
+
+static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
+
+
+#endif
|
[-]
[+]
|
Added |
bird-1.3.8.tar.bz2/sysdep/linux/netlink.Y
^
|
@@ -0,0 +1,32 @@
+/*
+ * BIRD -- Linux Netlink Configuration
+ *
+ * (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+CF_HDR
+
+CF_DECLS
+
+CF_KEYWORDS(ASYNC, KERNEL, TABLE, KRT_PREFSRC, KRT_REALM)
+
+CF_GRAMMAR
+
+CF_ADDTO(kern_proto, kern_proto nl_item ';')
+
+nl_item:
+ KERNEL TABLE expr {
+ if ($3 <= 0 || $3 >= NL_NUM_TABLES)
+ cf_error("Kernel routing table number out of range");
+ THIS_KRT->sys.table_id = $3;
+ }
+ ;
+
+CF_ADDTO(dynamic_attr, KRT_PREFSRC { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); })
+CF_ADDTO(dynamic_attr, KRT_REALM { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REALM); })
+
+CF_CODE
+
+CF_END
|
[-]
[+]
|
Added |
bird-1.3.8.tar.bz2/sysdep/linux/netlink.c
^
|
@@ -0,0 +1,1149 @@
+/*
+ * BIRD -- Linux Netlink Interface
+ *
+ * (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <errno.h>
+
+#undef LOCAL_DEBUG
+
+#include "nest/bird.h"
+#include "nest/route.h"
+#include "nest/protocol.h"
+#include "nest/iface.h"
+#include "lib/alloca.h"
+#include "lib/timer.h"
+#include "lib/unix.h"
+#include "lib/krt.h"
+#include "lib/socket.h"
+#include "lib/string.h"
+#include "conf/conf.h"
+
+#include <asm/types.h>
+#include <linux/if.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#ifndef MSG_TRUNC /* Hack: Several versions of glibc miss this one :( */
+#define MSG_TRUNC 0x20
+#endif
+
+#ifndef IFF_LOWER_UP
+#define IFF_LOWER_UP 0x10000
+#endif
+
+/*
+ * Synchronous Netlink interface
+ */
+
+struct nl_sock
+{
+ int fd;
+ u32 seq;
+ byte *rx_buffer; /* Receive buffer */
+ struct nlmsghdr *last_hdr; /* Recently received packet */
+ unsigned int last_size;
+};
+
+#define NL_RX_SIZE 8192
+
+static struct nl_sock nl_scan = {.fd = -1}; /* Netlink socket for synchronous scan */
+static struct nl_sock nl_req = {.fd = -1}; /* Netlink socket for requests */
+
+static void
+nl_open_sock(struct nl_sock *nl)
+{
+ if (nl->fd < 0)
+ {
+ nl->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (nl->fd < 0)
+ die("Unable to open rtnetlink socket: %m");
+ nl->seq = now;
+ nl->rx_buffer = xmalloc(NL_RX_SIZE);
+ nl->last_hdr = NULL;
+ nl->last_size = 0;
+ }
+}
+
+static void
+nl_open(void)
+{
+ nl_open_sock(&nl_scan);
+ nl_open_sock(&nl_req);
+}
+
+static void
+nl_send(struct nl_sock *nl, struct nlmsghdr *nh)
+{
+ struct sockaddr_nl sa;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.nl_family = AF_NETLINK;
+ nh->nlmsg_pid = 0;
+ nh->nlmsg_seq = ++(nl->seq);
+ if (sendto(nl->fd, nh, nh->nlmsg_len, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0)
+ die("rtnetlink sendto: %m");
+ nl->last_hdr = NULL;
+}
+
+static void
+nl_request_dump(int cmd)
+{
+ struct {
+ struct nlmsghdr nh;
+ struct rtgenmsg g;
+ } req;
+ req.nh.nlmsg_type = cmd;
+ req.nh.nlmsg_len = sizeof(req);
+ req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+ /* Is it important which PF_* is used for link-level interface scan?
+ It seems that some information is available only when PF_INET is used. */
+ req.g.rtgen_family = (cmd == RTM_GETLINK) ? PF_INET : BIRD_PF;
+ nl_send(&nl_scan, &req.nh);
+}
+
+static struct nlmsghdr *
+nl_get_reply(struct nl_sock *nl)
+{
+ for(;;)
+ {
+ if (!nl->last_hdr)
+ {
+ struct iovec iov = { nl->rx_buffer, NL_RX_SIZE };
+ struct sockaddr_nl sa;
+ struct msghdr m = { (struct sockaddr *) &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
+ int x = recvmsg(nl->fd, &m, 0);
+ if (x < 0)
+ die("nl_get_reply: %m");
+ if (sa.nl_pid) /* It isn't from the kernel */
+ {
+ DBG("Non-kernel packet\n");
+ continue;
+ }
+ nl->last_size = x;
+ nl->last_hdr = (void *) nl->rx_buffer;
+ if (m.msg_flags & MSG_TRUNC)
+ bug("nl_get_reply: got truncated reply which should be impossible");
+ }
+ if (NLMSG_OK(nl->last_hdr, nl->last_size))
+ {
+ struct nlmsghdr *h = nl->last_hdr;
+ nl->last_hdr = NLMSG_NEXT(h, nl->last_size);
+ if (h->nlmsg_seq != nl->seq)
+ {
+ log(L_WARN "nl_get_reply: Ignoring out of sequence netlink packet (%x != %x)",
+ h->nlmsg_seq, nl->seq);
+ continue;
+ }
+ return h;
+ }
+ if (nl->last_size)
+ log(L_WARN "nl_get_reply: Found packet remnant of size %d", nl->last_size);
+ nl->last_hdr = NULL;
+ }
+}
+
+static struct rate_limit rl_netlink_err;
+
+static int
+nl_error(struct nlmsghdr *h)
+{
+ struct nlmsgerr *e;
+ int ec;
+
+ if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
+ {
+ log(L_WARN "Netlink: Truncated error message received");
+ return ENOBUFS;
+ }
+ e = (struct nlmsgerr *) NLMSG_DATA(h);
+ ec = -e->error;
+ if (ec)
+ log_rl(&rl_netlink_err, L_WARN "Netlink: %s", strerror(ec));
+ return ec;
+}
+
+static struct nlmsghdr *
+nl_get_scan(void)
+{
+ struct nlmsghdr *h = nl_get_reply(&nl_scan);
+
+ if (h->nlmsg_type == NLMSG_DONE)
+ return NULL;
+ if (h->nlmsg_type == NLMSG_ERROR)
+ {
+ nl_error(h);
+ return NULL;
+ }
+ return h;
+}
+
+static int
+nl_exchange(struct nlmsghdr *pkt)
+{
+ struct nlmsghdr *h;
+
+ nl_send(&nl_req, pkt);
+ for(;;)
+ {
+ h = nl_get_reply(&nl_req);
+ if (h->nlmsg_type == NLMSG_ERROR)
+ break;
+ log(L_WARN "nl_exchange: Unexpected reply received");
+ }
+ return nl_error(h) ? -1 : 0;
+}
+
+/*
+ * Netlink attributes
+ */
+
+static int nl_attr_len;
+
+static void *
+nl_checkin(struct nlmsghdr *h, int lsize)
+{
+ nl_attr_len = h->nlmsg_len - NLMSG_LENGTH(lsize);
+ if (nl_attr_len < 0)
+ {
+ log(L_ERR "nl_checkin: underrun by %d bytes", -nl_attr_len);
+ return NULL;
+ }
+ return NLMSG_DATA(h);
+}
+
+static int
+nl_parse_attrs(struct rtattr *a, struct rtattr **k, int ksize)
+{
+ int max = ksize / sizeof(struct rtattr *);
+ bzero(k, ksize);
+ while (RTA_OK(a, nl_attr_len))
+ {
+ if (a->rta_type < max)
+ k[a->rta_type] = a;
+ a = RTA_NEXT(a, nl_attr_len);
+ }
+ if (nl_attr_len)
+ {
+ log(L_ERR "nl_parse_attrs: remnant of size %d", nl_attr_len);
+ return 0;
+ }
+ else
+ return 1;
+}
+
+void
+nl_add_attr(struct nlmsghdr *h, unsigned bufsize, unsigned code,
+ void *data, unsigned dlen)
+{
+ unsigned len = RTA_LENGTH(dlen);
+ unsigned pos = NLMSG_ALIGN(h->nlmsg_len);
+ struct rtattr *a;
+
+ if (pos + len > bufsize)
+ bug("nl_add_attr: packet buffer overflow");
+ a = (struct rtattr *)((char *)h + pos);
+ a->rta_type = code;
+ a->rta_len = len;
+ h->nlmsg_len = pos + len;
+ memcpy(RTA_DATA(a), data, dlen);
+}
+
+static inline void
+nl_add_attr_u32(struct nlmsghdr *h, unsigned bufsize, int code, u32 data)
+{
+ nl_add_attr(h, bufsize, code, &data, 4);
+}
+
+static inline void
+nl_add_attr_ipa(struct nlmsghdr *h, unsigned bufsize, int code, ip_addr ipa)
+{
+ ipa_hton(ipa);
+ nl_add_attr(h, bufsize, code, &ipa, sizeof(ipa));
+}
+
+#define RTNH_SIZE (sizeof(struct rtnexthop) + sizeof(struct rtattr) + sizeof(ip_addr))
+
+static inline void
+add_mpnexthop(char *buf, ip_addr ipa, unsigned iface, unsigned char weight)
+{
+ struct rtnexthop *nh = (void *) buf;
+ struct rtattr *rt = (void *) (buf + sizeof(*nh));
+ nh->rtnh_len = RTNH_SIZE;
+ nh->rtnh_flags = 0;
+ nh->rtnh_hops = weight;
+ nh->rtnh_ifindex = iface;
+ rt->rta_len = sizeof(*rt) + sizeof(ipa);
+ rt->rta_type = RTA_GATEWAY;
+ ipa_hton(ipa);
+ memcpy(buf + sizeof(*nh) + sizeof(*rt), &ipa, sizeof(ipa));
+}
+
+
+static void
+nl_add_multipath(struct nlmsghdr *h, unsigned bufsize, struct mpnh *nh)
+{
+ unsigned len = sizeof(struct rtattr);
+ unsigned pos = NLMSG_ALIGN(h->nlmsg_len);
+ char *buf = (char *)h + pos;
+ struct rtattr *rt = (void *) buf;
+ buf += len;
+
+ for (; nh; nh = nh->next)
+ {
+ len += RTNH_SIZE;
+ if (pos + len > bufsize)
+ bug("nl_add_multipath: packet buffer overflow");
+
+ add_mpnexthop(buf, nh->gw, nh->iface->index, nh->weight);
+ buf += RTNH_SIZE;
+ }
+
+ rt->rta_type = RTA_MULTIPATH;
+ rt->rta_len = len;
+ h->nlmsg_len = pos + len;
+}
+
+
+static struct mpnh *
+nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
+{
+ /* Temporary buffer for multicast nexthops */
+ static struct mpnh *nh_buffer;
+ static int nh_buf_size; /* in number of structures */
+ static int nh_buf_used;
+
+ struct rtattr *a[RTA_CACHEINFO+1];
+ struct rtnexthop *nh = RTA_DATA(ra);
+ struct mpnh *rv, *first, **last;
+ int len = RTA_PAYLOAD(ra);
+
+ first = NULL;
+ last = &first;
+ nh_buf_used = 0;
+
+ while (len)
+ {
+ /* Use RTNH_OK(nh,len) ?? */
+ if ((len < sizeof(*nh)) || (len < nh->rtnh_len))
+ return NULL;
+
+ if (nh_buf_used == nh_buf_size)
+ {
+ nh_buf_size = nh_buf_size ? (nh_buf_size * 2) : 4;
+ nh_buffer = xrealloc(nh_buffer, nh_buf_size * sizeof(struct mpnh));
+ }
+ *last = rv = nh_buffer + nh_buf_used++;
+ rv->next = NULL;
+ last = &(rv->next);
+
+ rv->weight = nh->rtnh_hops;
+ rv->iface = if_find_by_index(nh->rtnh_ifindex);
+ if (!rv->iface)
+ return NULL;
+
+ /* Nonexistent RTNH_PAYLOAD ?? */
+ nl_attr_len = nh->rtnh_len - RTNH_LENGTH(0);
+ nl_parse_attrs(RTNH_DATA(nh), a, sizeof(a));
+ if (a[RTA_GATEWAY])
+ {
+ if (RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr))
+ return NULL;
+
+ memcpy(&rv->gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ip_addr));
+ ipa_ntoh(rv->gw);
+
+ neighbor *ng = neigh_find2(&p->p, &rv->gw, rv->iface,
+ (nh->rtnh_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
+ if (!ng || (ng->scope == SCOPE_HOST))
+ return NULL;
+ }
+ else
+ return NULL;
+
+ len -= NLMSG_ALIGN(nh->rtnh_len);
+ nh = RTNH_NEXT(nh);
+ }
+
+ return first;
+}
+
+
+/*
+ * Scanning of interfaces
+ */
+
+static void
+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 *ifi;
+ char *name;
+ u32 mtu;
+ unsigned int fl;
+
+ if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFLA_RTA(i), a, sizeof(a)))
+ return;
+ if (!a[IFLA_IFNAME] || RTA_PAYLOAD(a[IFLA_IFNAME]) < 2 ||
+ !a[IFLA_MTU] || RTA_PAYLOAD(a[IFLA_MTU]) != 4)
+ {
+ if (scan || !a[IFLA_WIRELESS])
+ log(L_ERR "nl_parse_link: Malformed message received");
+ return;
+ }
+ name = RTA_DATA(a[IFLA_IFNAME]);
+ memcpy(&mtu, RTA_DATA(a[IFLA_MTU]), sizeof(u32));
+
+ ifi = if_find_by_index(i->ifi_index);
+ if (!new)
+ {
+ DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
+ 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 && 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;
+
+ fl = i->ifi_flags;
+ if (fl & IFF_UP)
+ f.flags |= IF_ADMIN_UP;
+ if (fl & IFF_LOWER_UP)
+ f.flags |= IF_LINK_UP;
+ if (fl & IFF_LOOPBACK) /* Loopback */
+ f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE;
+ else if (fl & IFF_POINTOPOINT) /* PtP */
+ f.flags |= IF_MULTICAST;
+ else if (fl & IFF_BROADCAST) /* Broadcast */
+ f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST;
+ else
+ f.flags |= IF_MULTIACCESS; /* NBMA */
+ if_update(&f);
+ }
+}
+
+static void
+nl_parse_addr(struct nlmsghdr *h)
+{
+ struct ifaddrmsg *i;
+ struct rtattr *a[IFA_ANYCAST+1];
+ int new = h->nlmsg_type == RTM_NEWADDR;
+ struct ifa ifa;
+ struct iface *ifi;
+ int scope;
+
+ if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFA_RTA(i), a, sizeof(a)))
+ return;
+ if (i->ifa_family != BIRD_AF)
+ return;
+ if (!a[IFA_ADDRESS] || RTA_PAYLOAD(a[IFA_ADDRESS]) != sizeof(ip_addr)
+#ifdef IPV6
+ || a[IFA_LOCAL] && RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
+#else
+ || !a[IFA_LOCAL] || RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
+ || (a[IFA_BROADCAST] && RTA_PAYLOAD(a[IFA_BROADCAST]) != sizeof(ip_addr))
+#endif
+ )
+ {
+ log(L_ERR "nl_parse_addr: Malformed message received");
+ return;
+ }
+
+ ifi = if_find_by_index(i->ifa_index);
+ if (!ifi)
+ {
+ log(L_ERR "KIF: Received address message for unknown interface %d", i->ifa_index);
+ return;
+ }
+
+ bzero(&ifa, sizeof(ifa));
+ ifa.iface = ifi;
+ if (i->ifa_flags & IFA_F_SECONDARY)
+ ifa.flags |= IA_SECONDARY;
+
+ /* IFA_LOCAL can be unset for IPv6 interfaces */
+ memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL] ? : a[IFA_ADDRESS]), sizeof(ifa.ip));
+ ipa_ntoh(ifa.ip);
+ ifa.pxlen = i->ifa_prefixlen;
+ if (i->ifa_prefixlen > BITS_PER_IP_ADDRESS)
+ {
+ log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen);
+ new = 0;
+ }
+ if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS)
+ {
+ ip_addr addr;
+ memcpy(&addr, RTA_DATA(a[IFA_ADDRESS]), sizeof(addr));
+ ipa_ntoh(addr);
+ ifa.prefix = ifa.brd = addr;
+
+ /* It is either a host address or a peer address */
+ if (ipa_equal(ifa.ip, addr))
+ ifa.flags |= IA_HOST;
+ else
+ {
+ ifa.flags |= IA_PEER;
+ ifa.opposite = addr;
+ }
+ }
+ else
+ {
+ ip_addr netmask = ipa_mkmask(ifa.pxlen);
+ ifa.prefix = ipa_and(ifa.ip, netmask);
+ ifa.brd = ipa_or(ifa.ip, ipa_not(netmask));
+ if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 1)
+ ifa.opposite = ipa_opposite_m1(ifa.ip);
+
+#ifndef IPV6
+ if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 2)
+ ifa.opposite = ipa_opposite_m2(ifa.ip);
+
+ if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
+ {
+ ip_addr xbrd;
+ memcpy(&xbrd, RTA_DATA(a[IFA_BROADCAST]), sizeof(xbrd));
+ ipa_ntoh(xbrd);
+ if (ipa_equal(xbrd, ifa.prefix) || ipa_equal(xbrd, ifa.brd))
+ ifa.brd = xbrd;
+ else if (ifi->flags & IF_TMP_DOWN) /* Complain only during the first scan */
+ log(L_ERR "KIF: Invalid broadcast address %I for %s", xbrd, ifi->name);
+ }
+#endif
+ }
+
+ scope = ipa_classify(ifa.ip);
+ if (scope < 0)
+ {
+ log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, ifi->name);
+ return;
+ }
+ ifa.scope = scope & IADDR_SCOPE_MASK;
+
+ DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %I/%d, brd %I, opp %I\n",
+ ifi->index, ifi->name,
+ new ? "added" : "removed",
+ ifa.ip, ifa.flags, ifa.prefix, ifa.pxlen, ifa.brd, ifa.opposite);
+ if (new)
+ ifa_update(&ifa);
+ else
+ ifa_delete(&ifa);
+}
+
+void
+kif_do_scan(struct kif_proto *p UNUSED)
+{
+ struct nlmsghdr *h;
+
+ if_start_update();
+
+ nl_request_dump(RTM_GETLINK);
+ while (h = nl_get_scan())
+ if (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)
+ nl_parse_link(h, 1);
+ else
+ log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
+
+ nl_request_dump(RTM_GETADDR);
+ while (h = nl_get_scan())
+ if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
+ nl_parse_addr(h);
+ else
+ log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
+
+ if_end_update();
+}
+
+/*
+ * Routes
+ */
+
+static struct krt_proto *nl_table_map[NL_NUM_TABLES];
+
+int
+krt_capable(rte *e)
+{
+ rta *a = e->attrs;
+
+ if (a->cast != RTC_UNICAST)
+ return 0;
+
+ switch (a->dest)
+ {
+ case RTD_ROUTER:
+ case RTD_DEVICE:
+ if (a->iface == NULL)
+ return 0;
+ case RTD_BLACKHOLE:
+ case RTD_UNREACHABLE:
+ case RTD_PROHIBIT:
+ case RTD_MULTIPATH:
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static inline int
+nh_bufsize(struct mpnh *nh)
+{
+ int rv = 0;
+ for (; nh != NULL; nh = nh->next)
+ rv += RTNH_SIZE;
+ return rv;
+}
+
+static int
+nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
+{
+ eattr *ea;
+ net *net = e->net;
+ rta *a = e->attrs;
+ struct {
+ struct nlmsghdr h;
+ struct rtmsg r;
+ char buf[128 + nh_bufsize(a->nexthops)];
+ } r;
+
+ DBG("nl_send_route(%I/%d,new=%d)\n", net->n.prefix, net->n.pxlen, new);
+
+ bzero(&r.h, sizeof(r.h));
+ bzero(&r.r, sizeof(r.r));
+ r.h.nlmsg_type = new ? RTM_NEWROUTE : RTM_DELROUTE;
+ r.h.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ r.h.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (new ? NLM_F_CREATE|NLM_F_EXCL : 0);
+
+ r.r.rtm_family = BIRD_AF;
+ r.r.rtm_dst_len = net->n.pxlen;
+ r.r.rtm_tos = 0;
+ r.r.rtm_table = KRT_CF->sys.table_id;
+ r.r.rtm_protocol = RTPROT_BIRD;
+ r.r.rtm_scope = RT_SCOPE_UNIVERSE;
+ nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
+
+ u32 metric = 0;
+ if (new && e->attrs->source == RTS_INHERIT)
+ metric = e->u.krt.metric;
+ if (ea = ea_find(eattrs, EA_KRT_METRIC))
+ metric = ea->u.data;
+ if (metric != 0)
+ nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, metric);
+
+ if (ea = ea_find(eattrs, EA_KRT_PREFSRC))
+ nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
+
+ if (ea = ea_find(eattrs, EA_KRT_REALM))
+ nl_add_attr_u32(&r.h, sizeof(r), RTA_FLOW, ea->u.data);
+
+ /* a->iface != NULL checked in krt_capable() for router and device routes */
+
+ switch (a->dest)
+ {
+ case RTD_ROUTER:
+ r.r.rtm_type = RTN_UNICAST;
+ nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
+ nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
+ break;
+ case RTD_DEVICE:
+ r.r.rtm_type = RTN_UNICAST;
+ nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
+ break;
+ case RTD_BLACKHOLE:
+ r.r.rtm_type = RTN_BLACKHOLE;
+ break;
+ case RTD_UNREACHABLE:
+ r.r.rtm_type = RTN_UNREACHABLE;
+ break;
+ case RTD_PROHIBIT:
+ r.r.rtm_type = RTN_PROHIBIT;
+ break;
+ case RTD_MULTIPATH:
+ r.r.rtm_type = RTN_UNICAST;
+ nl_add_multipath(&r.h, sizeof(r), a->nexthops);
+ break;
+ default:
+ bug("krt_capable inconsistent with nl_send_route");
+ }
+
+ return nl_exchange(&r.h);
+}
+
+void
+krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs)
+{
+ int err = 0;
+
+ /*
+ * NULL for eattr of the old route is a little hack, but we don't
+ * get proper eattrs for old in rt_notify() anyway. NULL means no
+ * extended route attributes and therefore matches if the kernel
+ * route has any of them.
+ */
+
+ if (old)
+ nl_send_route(p, old, NULL, 0);
+
+ if (new)
+ err = nl_send_route(p, new, eattrs, 1);
+
+ if (err < 0)
+ n->n.flags |= KRF_SYNC_ERROR;
+ else
+ n->n.flags &= ~KRF_SYNC_ERROR;
+}
+
+
+#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
+
+static void
+nl_parse_route(struct nlmsghdr *h, int scan)
+{
+ struct krt_proto *p;
+ struct rtmsg *i;
+ struct rtattr *a[RTA_CACHEINFO+1];
+ int new = h->nlmsg_type == RTM_NEWROUTE;
+
+ ip_addr dst = IPA_NONE;
+ u32 oif = ~0;
+ int src;
+
+ if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
+ return;
+ if (i->rtm_family != BIRD_AF)
+ return;
+ if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
+#ifdef IPV6
+ (a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
+#endif
+ (a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
+ (a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)) ||
+ (a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
+ (a[RTA_PREFSRC] && RTA_PAYLOAD(a[RTA_PREFSRC]) != sizeof(ip_addr)) ||
+ (a[RTA_FLOW] && RTA_PAYLOAD(a[RTA_FLOW]) != 4))
+ {
+ log(L_ERR "KRT: Malformed message received");
+ return;
+ }
+
+ if (a[RTA_DST])
+ {
+ memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
+ ipa_ntoh(dst);
+ }
+
+ if (a[RTA_OIF])
+ memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
+
+ p = nl_table_map[i->rtm_table]; /* Do we know this table? */
+ DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p ? p->p.name : "(none)");
+ if (!p)
+ SKIP("unknown table %d\n", i->rtm_table);
+
+
+#ifdef IPV6
+ if (a[RTA_IIF])
+ SKIP("IIF set\n");
+#else
+ if (i->rtm_tos != 0) /* We don't support TOS */
+ SKIP("TOS %02x\n", i->rtm_tos);
+#endif
+
+ if (scan && !new)
+ SKIP("RTM_DELROUTE in scan\n");
+
+ int c = ipa_classify_net(dst);
+ if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
+ SKIP("strange class/scope\n");
+
+ // ignore rtm_scope, it is not a real scope
+ // if (i->rtm_scope != RT_SCOPE_UNIVERSE)
+ // SKIP("scope %u\n", i->rtm_scope);
+
+ switch (i->rtm_protocol)
+ {
+ case RTPROT_UNSPEC:
+ SKIP("proto unspec\n");
+
+ case RTPROT_REDIRECT:
+ src = KRT_SRC_REDIRECT;
+ break;
+
+ case RTPROT_KERNEL:
+ src = KRT_SRC_KERNEL;
+ return;
+
+ case RTPROT_BIRD:
+ if (!scan)
+ SKIP("echo\n");
+ src = KRT_SRC_BIRD;
+ break;
+
+ case RTPROT_BOOT:
+ default:
+ src = KRT_SRC_ALIEN;
+ }
+
+ net *net = net_get(p->p.table, dst, i->rtm_dst_len);
+
+ rta ra = {
+ .proto = &p->p,
+ .source = RTS_INHERIT,
+ .scope = SCOPE_UNIVERSE,
+ .cast = RTC_UNICAST
+ };
+
+ switch (i->rtm_type)
+ {
+ case RTN_UNICAST:
+
+ if (a[RTA_MULTIPATH])
+ {
+ ra.dest = RTD_MULTIPATH;
+ ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]);
+ if (!ra.nexthops)
+ {
+ log(L_ERR "KRT: Received strange multipath route %I/%d",
+ net->n.prefix, net->n.pxlen);
+ return;
+ }
+
+ break;
+ }
+
+ ra.iface = if_find_by_index(oif);
+ if (!ra.iface)
+ {
+ log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
+ net->n.prefix, net->n.pxlen, oif);
+ return;
+ }
+
+ if (a[RTA_GATEWAY])
+ {
+ neighbor *ng;
+ ra.dest = RTD_ROUTER;
+ memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
+ ipa_ntoh(ra.gw);
+
+ /* Silently skip strange 6to4 routes */
+ if (ipa_in_net(ra.gw, IPA_NONE, 96))
+ return;
+
+ ng = neigh_find2(&p->p, &ra.gw, ra.iface,
+ (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
+ if (!ng || (ng->scope == SCOPE_HOST))
+ {
+ log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
+ net->n.prefix, net->n.pxlen, ra.gw);
+ return;
+ }
+ }
+ else
+ {
+ ra.dest = RTD_DEVICE;
+
+ /*
+ * In Linux IPv6, 'native' device routes have proto
+ * RTPROT_BOOT and not RTPROT_KERNEL (which they have in
+ * IPv4 and which is expected). We cannot distinguish
+ * 'native' and user defined device routes, so we ignore all
+ * such device routes and for consistency, we have the same
+ * behavior in IPv4. Anyway, users should use RTPROT_STATIC
+ * for their 'alien' routes.
+ */
+
+ if (i->rtm_protocol == RTPROT_BOOT)
+ src = KRT_SRC_KERNEL;
+ }
+
+ break;
+ case RTN_BLACKHOLE:
+ ra.dest = RTD_BLACKHOLE;
+ break;
+ case RTN_UNREACHABLE:
+ ra.dest = RTD_UNREACHABLE;
+ break;
+ case RTN_PROHIBIT:
+ ra.dest = RTD_PROHIBIT;
+ break;
+ /* FIXME: What about RTN_THROW? */
+ default:
+ SKIP("type %d\n", i->rtm_type);
+ return;
+ }
+
+ rte *e = rte_get_temp(&ra);
+ e->net = net;
+ e->u.krt.src = src;
+ e->u.krt.proto = i->rtm_protocol;
+ e->u.krt.type = i->rtm_type;
+
+ if (a[RTA_PRIORITY])
+ memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric));
+ else
+ e->u.krt.metric = 0;
+
+ if (a[RTA_PREFSRC])
+ {
+ ip_addr ps;
+ memcpy(&ps, RTA_DATA(a[RTA_PREFSRC]), sizeof(ps));
+ ipa_ntoh(ps);
+
+ ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr));
+ ea->next = ra.eattrs;
+ ra.eattrs = ea;
+ ea->flags = EALF_SORTED;
+ ea->count = 1;
+ ea->attrs[0].id = EA_KRT_PREFSRC;
+ ea->attrs[0].flags = 0;
+ ea->attrs[0].type = EAF_TYPE_IP_ADDRESS;
+ ea->attrs[0].u.ptr = alloca(sizeof(struct adata) + sizeof(ps));
+ ea->attrs[0].u.ptr->length = sizeof(ps);
+ memcpy(ea->attrs[0].u.ptr->data, &ps, sizeof(ps));
+ }
+
+ if (a[RTA_FLOW])
+ {
+ ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr));
+ ea->next = ra.eattrs;
+ ra.eattrs = ea;
+ ea->flags = EALF_SORTED;
+ ea->count = 1;
+ ea->attrs[0].id = EA_KRT_REALM;
+ ea->attrs[0].flags = 0;
+ ea->attrs[0].type = EAF_TYPE_INT;
+ memcpy(&ea->attrs[0].u.data, RTA_DATA(a[RTA_FLOW]), 4);
+ }
+
+ if (scan)
+ krt_got_route(p, e);
+ else
+ krt_got_route_async(p, e, new);
+}
+
+void
+krt_do_scan(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NULL */
+{
+ struct nlmsghdr *h;
+
+ nl_request_dump(RTM_GETROUTE);
+ while (h = nl_get_scan())
+ if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
+ nl_parse_route(h, 1);
+ else
+ log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
+}
+
+/*
+ * Asynchronous Netlink interface
+ */
+
+static sock *nl_async_sk; /* BIRD socket for asynchronous notifications */
+static byte *nl_async_rx_buffer; /* Receive buffer */
+
+static void
+nl_async_msg(struct nlmsghdr *h)
+{
+ switch (h->nlmsg_type)
+ {
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ DBG("KRT: Received async route notification (%d)\n", h->nlmsg_type);
+ nl_parse_route(h, 0);
+ break;
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ DBG("KRT: Received async link notification (%d)\n", h->nlmsg_type);
+ nl_parse_link(h, 0);
+ break;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ DBG("KRT: Received async address notification (%d)\n", h->nlmsg_type);
+ nl_parse_addr(h);
+ break;
+ default:
+ DBG("KRT: Received unknown async notification (%d)\n", h->nlmsg_type);
+ }
+}
+
+static int
+nl_async_hook(sock *sk, int size UNUSED)
+{
+ struct iovec iov = { nl_async_rx_buffer, NL_RX_SIZE };
+ struct sockaddr_nl sa;
+ struct msghdr m = { (struct sockaddr *) &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
+ struct nlmsghdr *h;
+ int x;
+ unsigned int len;
+
+ x = recvmsg(sk->fd, &m, 0);
+ if (x < 0)
+ {
+ if (errno == ENOBUFS)
+ {
+ /*
+ * Netlink reports some packets have been thrown away.
+ * One day we might react to it by asking for route table
+ * scan in near future.
+ */
+ return 1; /* More data are likely to be ready */
+ }
+ else if (errno != EWOULDBLOCK)
+ log(L_ERR "Netlink recvmsg: %m");
+ return 0;
+ }
+ if (sa.nl_pid) /* It isn't from the kernel */
+ {
+ DBG("Non-kernel packet\n");
+ return 1;
+ }
+ h = (void *) nl_async_rx_buffer;
+ len = x;
+ if (m.msg_flags & MSG_TRUNC)
+ {
+ log(L_WARN "Netlink got truncated asynchronous message");
+ return 1;
+ }
+ while (NLMSG_OK(h, len))
+ {
+ nl_async_msg(h);
+ h = NLMSG_NEXT(h, len);
+ }
+ if (len)
+ log(L_WARN "nl_async_hook: Found packet remnant of size %d", len);
+ return 1;
+}
+
+static void
+nl_open_async(void)
+{
+ sock *sk;
+ struct sockaddr_nl sa;
+ int fd;
+ static int nl_open_tried = 0;
+
+ if (nl_open_tried)
+ return;
+ nl_open_tried = 1;
+
+ DBG("KRT: Opening async netlink socket\n");
+
+ fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (fd < 0)
+ {
+ log(L_ERR "Unable to open asynchronous rtnetlink socket: %m");
+ return;
+ }
+
+ bzero(&sa, sizeof(sa));
+ sa.nl_family = AF_NETLINK;
+#ifdef IPV6
+ sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
+#else
+ sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
+#endif
+ if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
+ {
+ log(L_ERR "Unable to bind asynchronous rtnetlink socket: %m");
+ return;
+ }
+
+ sk = nl_async_sk = sk_new(krt_pool);
+ sk->type = SK_MAGIC;
+ sk->rx_hook = nl_async_hook;
+ sk->fd = fd;
+ if (sk_open(sk))
+ bug("Netlink: sk_open failed");
+
+ if (!nl_async_rx_buffer)
+ nl_async_rx_buffer = xmalloc(NL_RX_SIZE);
+}
+
+/*
+ * Interface to the UNIX krt module
+ */
+
+static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
+
+void
+krt_sys_start(struct krt_proto *p, int first)
+{
+ nl_table_map[KRT_CF->sys.table_id] = p;
+ if (first)
+ {
+ nl_open();
+ nl_open_async();
+ }
+}
+
+void
+krt_sys_shutdown(struct krt_proto *p UNUSED, int last UNUSED)
+{
+}
+
+int
+krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
+{
+ return n->sys.table_id == o->sys.table_id;
+}
+
+
+void
+krt_sys_preconfig(struct config *c UNUSED)
+{
+ bzero(&nl_cf_table, sizeof(nl_cf_table));
+}
+
+void
+krt_sys_postconfig(struct krt_config *x)
+{
+ int id = x->sys.table_id;
+
+ if (nl_cf_table[id/8] & (1 << (id%8)))
+ cf_error("Multiple kernel syncers defined for table #%d", id);
+ nl_cf_table[id/8] |= (1 << (id%8));
+}
+
+void
+krt_sys_init_config(struct krt_config *cf)
+{
+ cf->sys.table_id = RT_TABLE_MAIN;
+}
+
+void
+krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
+{
+ d->sys.table_id = s->sys.table_id;
+}
+
+
+
+void
+kif_sys_start(struct kif_proto *p UNUSED)
+{
+ nl_open();
+ nl_open_async();
+}
+
+void
+kif_sys_shutdown(struct kif_proto *p UNUSED)
+{
+}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/linux/sysio.h
^
|
@@ -57,45 +57,6 @@
ipa_ntoh(*a);
}
-/*
- * Multicasting in Linux systems is a real mess. Not only different kernels
- * have different interfaces, but also different libc's export it in different
- * ways. Horrible.
- */
-
-
-#if defined(CONFIG_LINUX_MC_MREQ) || defined(CONFIG_LINUX_MC_MREQ_BIND)
-/*
- * Older kernels support only struct mreq which matches interfaces by their
- * addresses and thus fails on unnumbered devices. On newer 2.0 kernels
- * we can use SO_BINDTODEVICE to circumvent this problem.
- */
-
-#define MREQ_IFA struct in_addr
-#define MREQ_GRP struct ip_mreq
-static inline void fill_mreq_ifa(struct in_addr *m, struct iface *ifa UNUSED, ip_addr saddr, ip_addr maddr UNUSED)
-{
- set_inaddr(m, saddr);
-}
-
-static inline void fill_mreq_grp(struct ip_mreq *m, struct iface *ifa, ip_addr saddr, ip_addr maddr)
-{
- bzero(m, sizeof(*m));
-#ifdef CONFIG_LINUX_MC_MREQ_BIND
- m->imr_interface.s_addr = INADDR_ANY;
-#else
- set_inaddr(&m->imr_interface, saddr);
-#endif
- set_inaddr(&m->imr_multiaddr, maddr);
-}
-#endif
-
-
-#ifdef CONFIG_LINUX_MC_MREQN
-/*
- * 2.1 and newer kernels use struct mreqn which passes ifindex, so no
- * problems with unnumbered devices.
- */
#ifndef HAVE_STRUCT_IP_MREQN
/* Several versions of glibc don't define this structure, so we have to do it ourselves */
@@ -107,24 +68,19 @@
};
#endif
-#define MREQ_IFA struct ip_mreqn
-#define MREQ_GRP struct ip_mreqn
-#define fill_mreq_ifa fill_mreq
-#define fill_mreq_grp fill_mreq
-static inline void fill_mreq(struct ip_mreqn *m, struct iface *ifa, ip_addr saddr, ip_addr maddr)
+static inline void fill_mreqn(struct ip_mreqn *m, struct iface *ifa, ip_addr saddr, ip_addr maddr)
{
bzero(m, sizeof(*m));
m->imr_ifindex = ifa->index;
set_inaddr(&m->imr_address, saddr);
set_inaddr(&m->imr_multiaddr, maddr);
}
-#endif
static inline char *
sysio_setup_multicast(sock *s)
{
- MREQ_IFA m;
+ struct ip_mreqn m;
int zero = 0;
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
@@ -134,18 +90,15 @@
return "IP_MULTICAST_TTL";
/* This defines where should we send _outgoing_ multicasts */
- fill_mreq_ifa(&m, s->iface, s->saddr, IPA_NONE);
+ fill_mreqn(&m, s->iface, s->saddr, IPA_NONE);
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
return "IP_MULTICAST_IF";
-#if defined(CONFIG_LINUX_MC_MREQ_BIND) || defined(CONFIG_LINUX_MC_MREQN)
- {
- struct ifreq ifr;
- strcpy(ifr.ifr_name, s->iface->name);
- if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
- return "SO_BINDTODEVICE";
- }
-#endif
+ /* Is this necessary? */
+ struct ifreq ifr;
+ strcpy(ifr.ifr_name, s->iface->name);
+ if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
+ return "SO_BINDTODEVICE";
return NULL;
}
@@ -153,10 +106,10 @@
static inline char *
sysio_join_group(sock *s, ip_addr maddr)
{
- MREQ_GRP m;
+ struct ip_mreqn m;
/* And this one sets interface for _receiving_ multicasts from */
- fill_mreq_grp(&m, s->iface, s->saddr, maddr);
+ fill_mreqn(&m, s->iface, s->saddr, maddr);
if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0)
return "IP_ADD_MEMBERSHIP";
@@ -166,10 +119,10 @@
static inline char *
sysio_leave_group(sock *s, ip_addr maddr)
{
- MREQ_GRP m;
+ struct ip_mreqn m;
/* And this one sets interface for _receiving_ multicasts from */
- fill_mreq_grp(&m, s->iface, s->saddr, maddr);
+ fill_mreqn(&m, s->iface, s->saddr, maddr);
if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)) < 0)
return "IP_DROP_MEMBERSHIP";
@@ -348,7 +301,7 @@
if (errno == ENOPROTOOPT)
log(L_ERR "Kernel does not support IPv6 TTL security");
else
- log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
+ log(L_ERR "sk_set_min_ttl6: setsockopt: %m");
return -1;
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/unix/Modules
^
|
@@ -10,13 +10,3 @@
krt.c
krt.h
krt.Y
-
-#ifdef CONFIG_UNIX_IFACE
-krt-iface.c
-krt-iface.h
-#endif
-
-#ifdef CONFIG_UNIX_SET
-krt-set.c
-krt-set.h
-#endif
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/unix/io.c
^
|
@@ -588,9 +588,12 @@
* This function creates a new socket resource. If you want to use it,
* you need to fill in all the required fields of the structure and
* call sk_open() to do the actual opening of the socket.
+ *
+ * The real function name is sock_new(), sk_new() is a macro wrapper
+ * to avoid collision with OpenSSL.
*/
sock *
-sk_new(pool *p)
+sock_new(pool *p)
{
sock *s = ralloc(p, &sk_class);
s->pool = p;
@@ -950,7 +953,7 @@
sk_join_group(sock *s, ip_addr maddr)
{
struct ipv6_mreq mreq;
-
+
set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
#ifdef CONFIG_IPV6_GLIBC_20
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/unix/krt.Y
^
|
@@ -17,7 +17,7 @@
CF_DECLS
-CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES)
+CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, KRT_SOURCE, KRT_METRIC)
CF_GRAMMAR
@@ -25,17 +25,7 @@
CF_ADDTO(proto, kern_proto '}')
-kern_proto_start: proto_start KERNEL {
-#ifndef CONFIG_MULTIPLE_TABLES
- if (cf_krt)
- cf_error("Kernel protocol already defined");
-#endif
- cf_krt = this_proto = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), $1);
- THIS_KRT->scan_time = 60;
- THIS_KRT->learn = THIS_KRT->persist = 0;
- krt_scan_construct(THIS_KRT);
- krt_set_construct(THIS_KRT);
- }
+kern_proto_start: proto_start KERNEL { this_proto = krt_init_config($1); }
;
CF_ADDTO(kern_proto, kern_proto_start proto_name '{')
@@ -62,14 +52,7 @@
CF_ADDTO(proto, kif_proto '}')
-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_KIF->scan_time = 60;
- init_list(&THIS_KIF->primary);
- krt_if_construct(THIS_KIF);
- }
+kif_proto_start: proto_start DEVICE { this_proto = kif_init_config($1); }
;
CF_ADDTO(kif_proto, kif_proto_start proto_name '{')
@@ -90,6 +73,9 @@
}
;
+CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_SOURCE); })
+CF_ADDTO(dynamic_attr, KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_METRIC); })
+
CF_CODE
CF_END
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/unix/krt.c
^
|
@@ -23,7 +23,7 @@
* Either with a single routing table and single KRT protocol [traditional UNIX]
* or with many routing tables and separate KRT protocols for all of them
* or with many routing tables, but every scan including all tables, so we start
- * separate KRT protocols which cooperate with each other [Linux 2.2].
+ * separate KRT protocols which cooperate with each other [Linux].
* In this case, we keep only a single scan timer.
*
* We use FIB node flags in the routing table to keep track of route
@@ -34,6 +34,15 @@
* When starting up, we cheat by looking if there is another
* KRT instance to be initialized later and performing table scan
* only once for all the instances.
+ *
+ * The code uses OS-dependent parts for kernel updates and scans. These parts are
+ * in more specific sysdep directories (e.g. sysdep/linux) in functions krt_sys_*
+ * and kif_sys_* (and some others like krt_replace_rte()) and krt-sys.h header file.
+ * This is also used for platform specific protocol options and route attributes.
+ *
+ * There was also an old code that used traditional UNIX ioctls for these tasks.
+ * It was unmaintained and later removed. For reference, see sysdep/krt-* files
+ * in commit 396dfa9042305f62da1f56589c4b98fac57fc2f6
*/
/*
@@ -46,6 +55,7 @@
#include "nest/iface.h"
#include "nest/route.h"
#include "nest/protocol.h"
+#include "filter/filter.h"
#include "lib/timer.h"
#include "conf/conf.h"
#include "lib/string.h"
@@ -53,45 +63,37 @@
#include "unix.h"
#include "krt.h"
-static int krt_uptodate(rte *k, rte *e);
-
/*
* Global resources
*/
pool *krt_pool;
+static linpool *krt_filter_lp;
void
krt_io_init(void)
{
krt_pool = rp_new(&root_pool, "Kernel Syncer");
- krt_if_io_init();
+ krt_filter_lp = lp_new(krt_pool, 4080);
}
/*
* Interfaces
*/
-struct proto_config *cf_kif;
-
+static struct kif_config *kif_cf;
static struct kif_proto *kif_proto;
static timer *kif_scan_timer;
static bird_clock_t kif_last_shot;
static void
-kif_preconfig(struct protocol *P UNUSED, struct config *c UNUSED)
-{
- cf_kif = NULL;
-}
-
-static void
kif_scan(timer *t)
{
struct kif_proto *p = t->data;
KRT_TRACE(p, D_EVENTS, "Scanning interfaces");
kif_last_shot = now;
- krt_if_scan(p);
+ kif_do_scan(p);
}
static void
@@ -111,45 +113,6 @@
tm_start(kif_scan_timer, 1);
}
-static struct proto *
-kif_init(struct proto_config *c)
-{
- struct kif_proto *p = proto_new(c, sizeof(struct kif_proto));
- return &p->p;
-}
-
-static int
-kif_start(struct proto *P)
-{
- struct kif_proto *p = (struct kif_proto *) P;
-
- kif_proto = p;
- krt_if_start(p);
-
- /* Start periodic interface scanning */
- kif_scan_timer = tm_new(P->pool);
- kif_scan_timer->hook = kif_scan;
- kif_scan_timer->data = p;
- kif_scan_timer->recurrent = KIF_CF->scan_time;
- kif_scan(kif_scan_timer);
- tm_start(kif_scan_timer, KIF_CF->scan_time);
-
- return PS_UP;
-}
-
-static int
-kif_shutdown(struct proto *P)
-{
- struct kif_proto *p = (struct kif_proto *) P;
-
- tm_stop(kif_scan_timer);
- krt_if_shutdown(p);
- kif_proto = NULL;
-
- return PS_DOWN;
-}
-
-
static inline int
prefer_scope(struct ifa *a, struct ifa *b)
{ return (a->scope > SCOPE_LINK) && (b->scope <= SCOPE_LINK); }
@@ -192,13 +155,53 @@
}
+static struct proto *
+kif_init(struct proto_config *c)
+{
+ struct kif_proto *p = proto_new(c, sizeof(struct kif_proto));
+
+ kif_sys_init(p);
+ return &p->p;
+}
+
+static int
+kif_start(struct proto *P)
+{
+ struct kif_proto *p = (struct kif_proto *) P;
+
+ kif_proto = p;
+ kif_sys_start(p);
+
+ /* Start periodic interface scanning */
+ kif_scan_timer = tm_new(P->pool);
+ kif_scan_timer->hook = kif_scan;
+ kif_scan_timer->data = p;
+ kif_scan_timer->recurrent = KIF_CF->scan_time;
+ kif_scan(kif_scan_timer);
+ tm_start(kif_scan_timer, KIF_CF->scan_time);
+
+ return PS_UP;
+}
+
+static int
+kif_shutdown(struct proto *P)
+{
+ struct kif_proto *p = (struct kif_proto *) P;
+
+ tm_stop(kif_scan_timer);
+ kif_sys_shutdown(p);
+ kif_proto = NULL;
+
+ return PS_DOWN;
+}
+
static int
kif_reconfigure(struct proto *p, struct proto_config *new)
{
struct kif_config *o = (struct kif_config *) p->cf;
struct kif_config *n = (struct kif_config *) new;
- if (!kif_params_same(&o->iface, &n->iface))
+ if (!kif_sys_reconfigure((struct kif_proto *) p, n, o))
return 0;
if (o->scan_time != n->scan_time)
@@ -223,6 +226,28 @@
return 1;
}
+
+static void
+kif_preconfig(struct protocol *P UNUSED, struct config *c)
+{
+ kif_cf = NULL;
+ kif_sys_preconfig(c);
+}
+
+struct proto_config *
+kif_init_config(int class)
+{
+ if (kif_cf)
+ cf_error("Kernel device protocol already defined");
+
+ kif_cf = (struct kif_config *) proto_config_new(&proto_unix_iface, sizeof(struct kif_config), class);
+ kif_cf->scan_time = 60;
+ init_list(&kif_cf->primary);
+
+ kif_sys_init_config(kif_cf);
+ return (struct proto_config *) kif_cf;
+}
+
static void
kif_copy_config(struct proto_config *dest, struct proto_config *src)
{
@@ -230,13 +255,13 @@
struct kif_config *s = (struct kif_config *) src;
/* Shallow copy of everything (just scan_time currently) */
- proto_copy_rest(dest, src, sizeof(struct krt_config));
+ proto_copy_rest(dest, src, sizeof(struct kif_config));
/* Copy primary addr list */
cfg_copy_list(&d->primary, &s->primary, sizeof(struct kif_primary_item));
/* Fix sysdep parts */
- kif_copy_params(&d->iface, &s->iface);
+ kif_sys_copy_config(d, s);
}
@@ -278,12 +303,30 @@
static struct rate_limit rl_alien_seen, rl_alien_updated, rl_alien_created, rl_alien_ignored;
+/*
+ * krt_same_key() specifies what (aside from the net) is the key in
+ * kernel routing tables. It should be OS-dependent, this is for
+ * Linux. It is important for asynchronous alien updates, because a
+ * positive update is implicitly a negative one for any old route with
+ * the same key.
+ */
+
static inline int
krt_same_key(rte *a, rte *b)
{
- return a->u.krt.proto == b->u.krt.proto &&
- a->u.krt.metric == b->u.krt.metric &&
- a->u.krt.type == b->u.krt.type;
+ return a->u.krt.metric == b->u.krt.metric;
+}
+
+static inline int
+krt_uptodate(rte *a, rte *b)
+{
+ if (a->attrs != b->attrs)
+ return 0;
+
+ if (a->u.krt.proto != b->u.krt.proto)
+ return 0;
+
+ return 1;
}
static void
@@ -308,6 +351,7 @@
rte_update(p->p.table, n, &p->p, &p->p, NULL);
}
+/* Called when alien route is discovered during scan */
static void
krt_learn_scan(struct krt_proto *p, rte *e)
{
@@ -315,7 +359,7 @@
net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen);
rte *m, **mm;
- e->attrs->source = RTS_INHERIT;
+ e->attrs = rta_lookup(e->attrs);
for(mm=&n->routes; m = *mm; mm=&m->next)
if (krt_same_key(m, e))
@@ -340,7 +384,6 @@
krt_trace_in_rl(&rl_alien_created, p, e, "[alien] created");
if (!m)
{
- e->attrs = rta_lookup(e->attrs);
e->next = n->routes;
n->routes = e;
e->u.krt.seen = 1;
@@ -416,7 +459,7 @@
net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen);
rte *g, **gg, *best, **bestp, *old_best;
- e->attrs->source = RTS_INHERIT;
+ e->attrs = rta_lookup(e->attrs);
old_best = n->routes;
for(gg=&n->routes; g = *gg; gg = &g->next)
@@ -438,7 +481,7 @@
}
else
krt_trace_in(p, e, "[alien async] created");
- e->attrs = rta_lookup(e->attrs);
+
e->next = n->routes;
n->routes = e;
}
@@ -532,22 +575,18 @@
{
net *n = (net *) f;
rte *e = n->routes;
- if (e)
+ if (e && (n->n.flags & KRF_INSTALLED))
{
- rta *a = e->attrs;
- if ((n->n.flags & KRF_INSTALLED) &&
- a->source != RTS_DEVICE && a->source != RTS_INHERIT)
- {
- krt_set_notify(p, e->net, NULL, e);
- n->n.flags &= ~KRF_INSTALLED;
- }
+ /* FIXME: this does not work if gw is changed in export filter */
+ krt_replace_rte(p, e->net, NULL, e, NULL);
+ n->n.flags &= ~KRF_INSTALLED;
}
}
FIB_WALK_END;
}
static int
-krt_uptodate(rte *k, rte *e)
+krt_same_dest(rte *k, rte *e)
{
rta *ka = k->attrs, *ea = e->attrs;
@@ -559,6 +598,8 @@
return ipa_equal(ka->gw, ea->gw);
case RTD_DEVICE:
return !strcmp(ka->iface->name, ea->iface->name);
+ case RTD_MULTIPATH:
+ return mpnh_same(ka->nexthops, ea->nexthops);
default:
return 1;
}
@@ -611,10 +652,12 @@
old = net->routes;
if ((net->n.flags & KRF_INSTALLED) && old)
{
- if (krt_uptodate(e, old))
- verdict = KRF_SEEN;
- else
+ /* There may be changes in route attributes, we ignore that.
+ Also, this does not work well if gw is changed in export filter */
+ if ((net->n.flags & KRF_SYNC_ERROR) || ! krt_same_dest(e, old))
verdict = KRF_UPDATE;
+ else
+ verdict = KRF_SEEN;
}
else
verdict = KRF_DELETE;
@@ -624,7 +667,7 @@
net->n.flags = (net->n.flags & ~KRF_VERDICT_MASK) | verdict;
if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
{
- /* Get a cached copy of attributes and link the route */
+ /* Get a cached copy of attributes and temporarily link the route */
rta *a = e->attrs;
a->source = RTS_DUMMY;
e->attrs = rta_lookup(a);
@@ -635,6 +678,25 @@
rte_free(e);
}
+static inline int
+krt_export_rte(struct krt_proto *p, rte **new, ea_list **tmpa)
+{
+ struct filter *filter = p->p.main_ahook->out_filter;
+
+ if (! *new)
+ return 0;
+
+ if (filter == FILTER_REJECT)
+ return 0;
+
+ if (filter == FILTER_ACCEPT)
+ return 1;
+
+ struct proto *src = (*new)->attrs->proto;
+ *tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(*new, krt_filter_lp) : NULL;
+ return f_run(filter, new, tmpa, krt_filter_lp, FF_FORCE_TMPATTR) <= F_ACCEPT;
+}
+
static void
krt_prune(struct krt_proto *p)
{
@@ -645,16 +707,28 @@
{
net *n = (net *) f;
int verdict = f->flags & KRF_VERDICT_MASK;
- rte *new, *old;
+ rte *new, *new0, *old;
+ ea_list *tmpa = NULL;
- if (verdict != KRF_CREATE && verdict != KRF_SEEN && verdict != KRF_IGNORE)
+ if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
{
+ /* Get a dummy route from krt_got_route() */
old = n->routes;
n->routes = old->next;
}
else
old = NULL;
- new = n->routes;
+
+ new = new0 = n->routes;
+ if (verdict == KRF_CREATE || verdict == KRF_UPDATE)
+ {
+ /* We have to run export filter to get proper 'new' route */
+ if (! krt_export_rte(p, &new, &tmpa))
+ {
+ /* Route rejected, should not happen (KRF_INSTALLED) but to be sure .. */
+ verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE;
+ }
+ }
switch (verdict)
{
@@ -662,7 +736,7 @@
if (new && (f->flags & KRF_INSTALLED))
{
krt_trace_in(p, new, "reinstalling");
- krt_set_notify(p, n, new, NULL);
+ krt_replace_rte(p, n, new, NULL, tmpa);
}
break;
case KRF_SEEN:
@@ -671,17 +745,21 @@
break;
case KRF_UPDATE:
krt_trace_in(p, new, "updating");
- krt_set_notify(p, n, new, old);
+ krt_replace_rte(p, n, new, old, tmpa);
break;
case KRF_DELETE:
krt_trace_in(p, old, "deleting");
- krt_set_notify(p, n, NULL, old);
+ krt_replace_rte(p, n, NULL, old, NULL);
break;
default:
bug("krt_prune: invalid route status");
}
+
if (old)
rte_free(old);
+ if (new != new0)
+ rte_free(new);
+ lp_flush(krt_filter_lp);
f->flags &= ~KRF_VERDICT_MASK;
}
FIB_WALK_END;
@@ -707,7 +785,7 @@
if (new)
{
krt_trace_in(p, e, "[redirect] deleting");
- krt_set_notify(p, net, NULL, e);
+ krt_replace_rte(p, net, NULL, e, NULL);
}
/* If !new, it is probably echo of our deletion */
break;
@@ -741,7 +819,7 @@
p = SKIP_BACK(struct krt_proto, instance_node, HEAD(krt_instance_list));
if (p->instance_node.next)
KRT_TRACE(p, D_EVENTS, "Scanning routing table");
- krt_scan_fire(NULL);
+ krt_do_scan(NULL);
WALK_LIST(q, krt_instance_list)
{
p = SKIP_BACK(struct krt_proto, instance_node, q);
@@ -751,14 +829,45 @@
#else
p = t->data;
KRT_TRACE(p, D_EVENTS, "Scanning routing table");
- krt_scan_fire(p);
+ krt_do_scan(p);
krt_prune(p);
#endif
}
+
/*
* Updates
*/
+
+static struct ea_list *
+krt_make_tmp_attrs(rte *rt, struct linpool *pool)
+{
+ struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr));
+
+ l->next = NULL;
+ l->flags = EALF_SORTED;
+ l->count = 2;
+
+ l->attrs[0].id = EA_KRT_SOURCE;
+ l->attrs[0].flags = 0;
+ l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP;
+ l->attrs[0].u.data = rt->u.krt.proto;
+
+ l->attrs[1].id = EA_KRT_METRIC;
+ l->attrs[1].flags = 0;
+ l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP;
+ l->attrs[1].u.data = rt->u.krt.metric;
+
+ return l;
+}
+
+static void
+krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
+{
+ /* EA_KRT_SOURCE is read-only */
+ rt->u.krt.metric = ea_get_int(attrs, EA_KRT_METRIC, 0);
+}
+
static int
krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool)
{
@@ -781,7 +890,7 @@
static void
krt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
- rte *new, rte *old, struct ea_list *attrs UNUSED)
+ rte *new, rte *old, struct ea_list *eattrs)
{
struct krt_proto *p = (struct krt_proto *) P;
@@ -793,38 +902,38 @@
net->n.flags |= KRF_INSTALLED;
else
net->n.flags &= ~KRF_INSTALLED;
- if (p->initialized) /* Before first scan we don't touch the routes */
- krt_set_notify(p, net, new, old);
+ if (p->initialized) /* Before first scan we don't touch the routes */
+ krt_replace_rte(p, net, new, old, eattrs);
+}
+
+static int
+krt_rte_same(rte *a, rte *b)
+{
+ /* src is always KRT_SRC_ALIEN and type is irrelevant */
+ return (a->u.krt.proto == b->u.krt.proto) && (a->u.krt.metric == b->u.krt.metric);
}
+
/*
* Protocol glue
*/
-struct proto_config *cf_krt;
+struct krt_config *krt_cf;
-static void
-krt_preconfig(struct protocol *P UNUSED, struct config *c)
-{
- cf_krt = NULL;
- krt_scan_preconfig(c);
-}
-
-static void
-krt_postconfig(struct proto_config *C)
+static struct proto *
+krt_init(struct proto_config *c)
{
- struct krt_config *c = (struct krt_config *) C;
+ struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
-#ifdef CONFIG_ALL_TABLES_AT_ONCE
- struct krt_config *first = (struct krt_config *) cf_krt;
- if (first->scan_time != c->scan_time)
- cf_error("All kernel syncers must use the same table scan interval");
-#endif
+ p->p.accept_ra_types = RA_OPTIMAL;
+ p->p.make_tmp_attrs = krt_make_tmp_attrs;
+ p->p.store_tmp_attrs = krt_store_tmp_attrs;
+ p->p.import_control = krt_import_control;
+ p->p.rt_notify = krt_notify;
+ p->p.rte_same = krt_rte_same;
- if (C->table->krt_attached)
- cf_error("Kernel syncer (%s) already attached to table %s", C->table->krt_attached->name, C->table->name);
- C->table->krt_attached = C;
- krt_scan_postconfig(c);
+ krt_sys_init(p);
+ return &p->p;
}
static timer *
@@ -861,8 +970,7 @@
krt_learn_init(p);
#endif
- krt_scan_start(p, first);
- krt_set_start(p, first);
+ krt_sys_start(p, first);
/* Start periodic routing table scanning */
#ifdef CONFIG_ALL_TABLES_AT_ONCE
@@ -896,8 +1004,7 @@
if (p->initialized && !KRT_CF->persist)
krt_flush_routes(p);
- krt_set_shutdown(p, last);
- krt_scan_shutdown(p, last);
+ krt_sys_shutdown(p, last);
#ifdef CONFIG_ALL_TABLES_AT_ONCE
if (last)
@@ -907,30 +1014,55 @@
return PS_DOWN;
}
-static struct proto *
-krt_init(struct proto_config *c)
+static int
+krt_reconfigure(struct proto *p, struct proto_config *new)
{
- struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
+ struct krt_config *o = (struct krt_config *) p->cf;
+ struct krt_config *n = (struct krt_config *) new;
- p->p.accept_ra_types = RA_OPTIMAL;
- p->p.import_control = krt_import_control;
- p->p.rt_notify = krt_notify;
+ if (!krt_sys_reconfigure((struct krt_proto *) p, n, o))
+ return 0;
- return &p->p;
+ /* persist needn't be the same */
+ return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes;
}
-static int
-krt_reconfigure(struct proto *p, struct proto_config *new)
+static void
+krt_preconfig(struct protocol *P UNUSED, struct config *c)
{
- struct krt_config *o = (struct krt_config *) p->cf;
- struct krt_config *n = (struct krt_config *) new;
+ krt_cf = NULL;
+ krt_sys_preconfig(c);
+}
+
+static void
+krt_postconfig(struct proto_config *C)
+{
+ struct krt_config *c = (struct krt_config *) C;
+
+#ifdef CONFIG_ALL_TABLES_AT_ONCE
+ if (krt_cf->scan_time != c->scan_time)
+ cf_error("All kernel syncers must use the same table scan interval");
+#endif
+
+ if (C->table->krt_attached)
+ cf_error("Kernel syncer (%s) already attached to table %s", C->table->krt_attached->name, C->table->name);
+ C->table->krt_attached = C;
+ krt_sys_postconfig(c);
+}
+
+struct proto_config *
+krt_init_config(int class)
+{
+#ifndef CONFIG_MULTIPLE_TABLES
+ if (krt_cf)
+ cf_error("Kernel protocol already defined");
+#endif
+
+ krt_cf = (struct krt_config *) proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), class);
+ krt_cf->scan_time = 60;
- return o->scan_time == n->scan_time
- && o->learn == n->learn /* persist needn't be the same */
- && o->devroutes == n->devroutes
- && krt_set_params_same(&o->set, &n->set)
- && krt_scan_params_same(&o->scan, &n->scan)
- ;
+ krt_sys_init_config(krt_cf);
+ return (struct proto_config *) krt_cf;
}
static void
@@ -943,8 +1075,7 @@
proto_copy_rest(dest, src, sizeof(struct krt_config));
/* Fix sysdep parts */
- krt_set_copy_params(&d->set, &s->set);
- krt_scan_copy_params(&d->scan, &s->scan);
+ krt_sys_copy_config(d, s);
}
static int
@@ -952,12 +1083,22 @@
{
switch (a->id)
{
+ case EA_KRT_SOURCE:
+ bsprintf(buf, "source");
+ return GA_NAME;
+
+ case EA_KRT_METRIC:
+ bsprintf(buf, "metric");
+ return GA_NAME;
+
case EA_KRT_PREFSRC:
bsprintf(buf, "prefsrc");
return GA_NAME;
+
case EA_KRT_REALM:
bsprintf(buf, "realm");
return GA_NAME;
+
default:
return GA_UNKNOWN;
}
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/unix/krt.h
^
|
@@ -15,9 +15,7 @@
struct kif_config;
struct kif_proto;
-#include "lib/krt-scan.h"
-#include "lib/krt-set.h"
-#include "lib/krt-iface.h"
+#include "lib/krt-sys.h"
/* Flags stored in net->n.flags, rest are in nest/route.h */
@@ -28,8 +26,10 @@
#define KRF_DELETE 3 /* Should be deleted */
#define KRF_IGNORE 4 /* To be ignored */
-#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 0)
-#define EA_KRT_REALM EA_CODE(EAP_KRT, 1)
+#define EA_KRT_SOURCE EA_CODE(EAP_KRT, 0)
+#define EA_KRT_METRIC EA_CODE(EAP_KRT, 1)
+#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 2)
+#define EA_KRT_REALM EA_CODE(EAP_KRT, 3)
/* Whenever we recognize our own routes, we allow learing of foreign routes */
@@ -43,8 +43,7 @@
struct krt_config {
struct proto_config c;
- struct krt_set_params set;
- struct krt_scan_params scan;
+ struct krt_params sys; /* Sysdep params */
int persist; /* Keep routes when we exit */
int scan_time; /* How often we re-scan routes */
int learn; /* Learn routes from other sources */
@@ -53,9 +52,7 @@
struct krt_proto {
struct proto p;
- struct krt_set_status set;
- struct krt_scan_status scan;
- struct krt_if_status iface;
+ struct krt_status sys; /* Sysdep state */
#ifdef KRT_ALLOW_LEARN
struct rtable krt_table; /* Internal table of inherited routes */
#endif
@@ -67,7 +64,6 @@
int initialized; /* First scan has already been finished */
};
-extern struct proto_config *cf_krt;
extern pool *krt_pool;
#define KRT_CF ((struct krt_config *)p->p.cf)
@@ -77,6 +73,7 @@
if (pr->p.debug & fl) \
{ log(L_TRACE "%s: " msg, pr->p.name , ## args); } } while(0)
+struct proto_config * kif_init_config(int class);
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);
@@ -99,46 +96,49 @@
struct kif_config {
struct proto_config c;
- struct krt_if_params iface;
+ struct kif_params sys; /* Sysdep params */
int scan_time; /* How often we re-scan interfaces */
list primary; /* Preferences for primary addresses (struct kif_primary_item) */
};
struct kif_proto {
struct proto p;
- struct krt_if_status iface;
+ struct kif_status sys; /* Sysdep state */
};
-extern struct proto_config *cf_kif;
-
#define KIF_CF ((struct kif_config *)p->p.cf)
-/* krt-scan.c */
+struct proto_config * krt_init_config(int class);
+
+
+/* krt sysdep */
+
+void krt_sys_init(struct krt_proto *);
+void krt_sys_start(struct krt_proto *, int);
+void krt_sys_shutdown(struct krt_proto *, int);
+int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o);
-void krt_scan_preconfig(struct config *);
-void krt_scan_postconfig(struct krt_config *);
-void krt_scan_construct(struct krt_config *);
-void krt_scan_start(struct krt_proto *, int);
-void krt_scan_shutdown(struct krt_proto *, int);
+void krt_sys_preconfig(struct config *);
+void krt_sys_postconfig(struct krt_config *);
+void krt_sys_init_config(struct krt_config *);
+void krt_sys_copy_config(struct krt_config *, struct krt_config *);
-void krt_scan_fire(struct krt_proto *);
+int krt_capable(rte *e);
+void krt_do_scan(struct krt_proto *);
+void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs);
-/* krt-set.c */
-void krt_set_construct(struct krt_config *);
-void krt_set_start(struct krt_proto *, int);
-void krt_set_shutdown(struct krt_proto *, int);
+/* kif sysdep */
-int krt_capable(rte *e);
-void krt_set_notify(struct krt_proto *x, net *net, rte *new, rte *old);
+void kif_sys_init(struct kif_proto *);
+void kif_sys_start(struct kif_proto *);
+void kif_sys_shutdown(struct kif_proto *);
+int kif_sys_reconfigure(struct kif_proto *, struct kif_config *, struct kif_config *);
-/* krt-iface.c */
+void kif_sys_init_config(struct kif_config *);
+void kif_sys_copy_config(struct kif_config *, struct kif_config *);
-void krt_if_construct(struct kif_config *);
-void krt_if_start(struct kif_proto *);
-void krt_if_shutdown(struct kif_proto *);
+void kif_do_scan(struct kif_proto *);
-void krt_if_scan(struct kif_proto *);
-void krt_if_io_init(void);
#endif
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/unix/main.c
^
|
@@ -151,7 +151,7 @@
#endif // PATH_IPROUTE_DIR
-static char *config_name = PATH_CONFIG;
+static char *config_name = PATH_CONFIG_FILE;
static int
cf_read(byte *dest, unsigned int len, int fd)
@@ -162,36 +162,13 @@
return l;
}
-static int
-cf_open(char *filename)
-{
- char full_name[BIRD_FNAME_MAX];
- char *cur = filename;
- int ret;
-
- if (*filename != '/') {
- char dir[BIRD_FNAME_MAX];
- strncpy(dir, config_name, sizeof(dir));
- dir[sizeof(dir)-1] = 0;
- snprintf(full_name, sizeof(full_name), "%s/%s", dirname(dir), filename);
- full_name[sizeof(full_name)-1] = 0;
- cur = full_name;
- }
-
- if ((ret = open(cur, O_RDONLY)) == -1)
- cf_error("Unable to open included configuration file: %s", cur);
-
- return ret;
-}
-
-
void
sysdep_preconfig(struct config *c)
{
init_list(&c->logfiles);
#ifdef PATH_IPROUTE_DIR
- // read_iproute_table(PATH_IPROUTE_DIR "/rt_protos", "ipp_", 256);
+ read_iproute_table(PATH_IPROUTE_DIR "/rt_protos", "ipp_", 256);
read_iproute_table(PATH_IPROUTE_DIR "/rt_realms", "ipr_", 256);
read_iproute_table(PATH_IPROUTE_DIR "/rt_scopes", "ips_", 256);
read_iproute_table(PATH_IPROUTE_DIR "/rt_tables", "ipt_", 256);
@@ -216,7 +193,6 @@
if (conf->file_fd < 0)
return 0;
cf_read_hook = cf_read;
- cf_open_hook = cf_open;
ret = config_parse(conf);
close(conf->file_fd);
return ret;
@@ -269,7 +245,7 @@
if (!unix_read_config(&conf, name))
{
if (conf->err_msg)
- cli_msg(8002, "%s, line %d: %s", name, conf->err_lino, conf->err_msg);
+ cli_msg(8002, "%s, line %d: %s", conf->err_file_name, conf->err_lino, conf->err_msg);
else
cli_msg(8002, "%s: %m", name);
config_free(conf);
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/sysdep/unix/timer.h
^
|
@@ -30,6 +30,22 @@
void tm_stop(timer *);
void tm_dump_all(void);
+extern bird_clock_t now; /* Relative, monotonic time in seconds */
+extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */
+
+static inline bird_clock_t
+tm_remains(timer *t)
+{
+ return t->expires ? t->expires - now : 0;
+}
+
+static inline void
+tm_start_max(timer *t, unsigned after)
+{
+ bird_clock_t rem = tm_remains(t);
+ tm_start(t, (rem > after) ? rem : after);
+}
+
static inline timer *
tm_new_set(pool *p, void (*hook)(struct timer *), void *data, unsigned rand, unsigned rec)
{
@@ -41,8 +57,6 @@
return t;
}
-extern bird_clock_t now; /* Relative, monotonic time in seconds */
-extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */
struct timeformat {
char *fmt1, *fmt2;
|
[-]
[+]
|
Changed |
bird-1.3.8.tar.bz2/tools/Makefile.in
^
|
@@ -48,23 +48,23 @@
sysdep/paths.h:
echo >sysdep/paths.h "/* Generated by Makefile, don't edit manually! */"
- echo >>sysdep/paths.h "#define PATH_CONFIG_DIR \"$(sysconfdir)\""
- echo >>sysdep/paths.h "#define PATH_CONTROL_SOCKET_DIR \"$(localstatedir)/run\""
+ echo >>sysdep/paths.h "#define PATH_CONFIG_FILE \"@CONFIG_FILE@\""
+ echo >>sysdep/paths.h "#define PATH_CONTROL_SOCKET \"@CONTROL_SOCKET@\""
if test -n "@iproutedir@" ; then echo >>sysdep/paths.h "#define PATH_IPROUTE_DIR \"@iproutedir@\"" ; fi
tags:
cd $(srcdir) ; etags -lc `find $(static-dirs) $(addprefix $(objdir)/,$(dynamic-dirs)) $(client-dirs) -name *.[chY]`
install: all
- $(INSTALL) -d $(DESTDIR)/$(sbindir) $(DESTDIR)/$(sysconfdir) $(DESTDIR)/$(localstatedir)/run
- $(INSTALL_PROGRAM) -s $(exedir)/bird $(DESTDIR)/$(sbindir)/bird@SUFFIX6@
+ $(INSTALL) -d $(DESTDIR)/$(sbindir) $(DESTDIR)/$(sysconfdir) $(DESTDIR)/@runtimedir@
+ $(INSTALL_PROGRAM) -s $(exedir)/bird $(DESTDIR)/$(sbindir)/bird@SUFFIX@
if test -n "@CLIENT@" ; then \
- $(INSTALL_PROGRAM) -s $(exedir)/birdc $(DESTDIR)/$(sbindir)/birdc@SUFFIX6@ ; \
+ $(INSTALL_PROGRAM) -s $(exedir)/birdc $(DESTDIR)/$(sbindir)/birdc@SUFFIX@ ; \
fi
- if ! test -f $(DESTDIR)/$(sysconfdir)/bird@SUFFIX6@.conf ; then \
- $(INSTALL_DATA) $(srcdir)/doc/bird.conf.example $(DESTDIR)/$(sysconfdir)/bird@SUFFIX6@.conf ; \
+ if ! test -f $(DESTDIR)/@CONFIG_FILE@ ; then \
+ $(INSTALL_DATA) $(srcdir)/doc/bird.conf.example $(DESTDIR)/@CONFIG_FILE@ ; \
else \
- echo "Not overwriting old bird@SUFFIX@.conf" ; \
+ echo "Not overwriting old bird@SUFFIX@.conf" ; \
fi
install-docs:
|