Merge branch 'int-new' of gitlab.labs.nic.cz:labs/bird into int-new
This commit is contained in:
commit
5af7b59660
51 changed files with 4210 additions and 122 deletions
17
NEWS
17
NEWS
|
@ -1,3 +1,20 @@
|
|||
Version 1.6.0 (2016-04-29)
|
||||
o Major RIP protocol redesign
|
||||
o New Babel routing protocol
|
||||
o BGP multipath support
|
||||
o KRT: Add support for plenty of kernel route metrics
|
||||
o KRT: Allow more than 256 routing tables
|
||||
o Static: Allow to specify attributes for static routes
|
||||
o Static: Support for BFD controlled static routes
|
||||
o FreeBSD: Setup password for BGP MD5 authentication
|
||||
o IO: Remove socket number limit
|
||||
o Plenty of bug fixes
|
||||
|
||||
Upgrade notes:
|
||||
|
||||
For RIP, most protocol options were moved to interface blocks.
|
||||
|
||||
|
||||
Version 1.5.0 (2015-04-20)
|
||||
o Major OSPF protocol redesign.
|
||||
o OSPFv2 multi-instance extension (RFC 6549).
|
||||
|
|
|
@ -153,7 +153,7 @@ input_init(void)
|
|||
|
||||
// readline library does strange things when stdin is nonblocking.
|
||||
// if (fcntl(0, F_SETFL, O_NONBLOCK) < 0)
|
||||
// die("fcntl: %m");
|
||||
// DIE("fcntl");
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
|
@ -109,7 +110,7 @@ more_begin(void)
|
|||
tty.c_lflag &= (~ICANON);
|
||||
|
||||
if (tcsetattr (0, TCSANOW, &tty) < 0)
|
||||
die("tcsetattr: %m");
|
||||
DIE("tcsetattr");
|
||||
|
||||
more_active = 1;
|
||||
}
|
||||
|
@ -120,7 +121,7 @@ more_end(void)
|
|||
more_active = 0;
|
||||
|
||||
if (tcsetattr (0, TCSANOW, &stored_tty) < 0)
|
||||
die("tcsetattr: %m");
|
||||
DIE("tcsetattr");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -137,7 +138,7 @@ input_init(void)
|
|||
return;
|
||||
|
||||
if (tcgetattr(0, &stored_tty) < 0)
|
||||
die("tcgetattr: %m");
|
||||
DIE("tcgetattr");
|
||||
|
||||
if (signal(SIGINT, sig_handler) == SIG_IGN)
|
||||
signal(SIGINT, SIG_IGN);
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#define SERVER_READ_BUF_LEN 4096
|
||||
|
||||
static char *opt_list = "s:vr";
|
||||
static char *opt_list = "s:vrl";
|
||||
static int verbose, restricted, once;
|
||||
static char *init_cmd;
|
||||
|
||||
|
@ -59,13 +59,14 @@ int term_lns, term_cls;
|
|||
static void
|
||||
usage(char *name)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-s <control-socket>] [-v] [-r]\n", name);
|
||||
fprintf(stderr, "Usage: %s [-s <control-socket>] [-v] [-r] [-l]\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_args(int argc, char **argv)
|
||||
{
|
||||
int server_changed = 0;
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, opt_list)) >= 0)
|
||||
|
@ -73,6 +74,7 @@ parse_args(int argc, char **argv)
|
|||
{
|
||||
case 's':
|
||||
server_path = optarg;
|
||||
server_changed = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
|
@ -80,6 +82,10 @@ parse_args(int argc, char **argv)
|
|||
case 'r':
|
||||
restricted = 1;
|
||||
break;
|
||||
case 'l':
|
||||
if (!server_changed)
|
||||
server_path = xbasename(server_path);
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
@ -242,7 +248,7 @@ server_connect(void)
|
|||
|
||||
server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (server_fd < 0)
|
||||
die("Cannot create socket: %m");
|
||||
DIE("Cannot create socket");
|
||||
|
||||
if (strlen(server_path) >= sizeof(sa.sun_path))
|
||||
die("server_connect: path too long");
|
||||
|
@ -251,9 +257,9 @@ server_connect(void)
|
|||
sa.sun_family = AF_UNIX;
|
||||
strcpy(sa.sun_path, server_path);
|
||||
if (connect(server_fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) < 0)
|
||||
die("Unable to connect to server control socket (%s): %m", server_path);
|
||||
DIE("Unable to connect to server control socket (%s)", server_path);
|
||||
if (fcntl(server_fd, F_SETFL, O_NONBLOCK) < 0)
|
||||
die("fcntl: %m");
|
||||
DIE("fcntl");
|
||||
}
|
||||
|
||||
|
||||
|
@ -303,13 +309,13 @@ server_read(void)
|
|||
redo:
|
||||
c = read(server_fd, server_read_pos, server_read_buf + sizeof(server_read_buf) - server_read_pos);
|
||||
if (!c)
|
||||
die("Connection closed by server.");
|
||||
die("Connection closed by server");
|
||||
if (c < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto redo;
|
||||
else
|
||||
die("Server read error: %m");
|
||||
DIE("Server read error");
|
||||
}
|
||||
|
||||
start = server_read_buf;
|
||||
|
@ -360,7 +366,7 @@ select_loop(void)
|
|||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
die("select: %m");
|
||||
DIE("select");
|
||||
}
|
||||
|
||||
if (FD_ISSET(0, &select_fds))
|
||||
|
@ -393,7 +399,7 @@ wait_for_write(int fd)
|
|||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
die("select: %m");
|
||||
DIE("select");
|
||||
}
|
||||
|
||||
if (FD_ISSET(server_fd, &set))
|
||||
|
@ -420,7 +426,7 @@ server_send(char *cmd)
|
|||
else if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
die("Server write error: %m");
|
||||
DIE("Server write error");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -430,19 +436,6 @@ server_send(char *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* XXXX
|
||||
|
||||
get_term_size();
|
||||
|
||||
if (tcgetattr(0, &tty_save) != 0)
|
||||
{
|
||||
perror("tcgetattr error");
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
|
|
@ -34,3 +34,6 @@ char *cmd_expand(char *cmd);
|
|||
/* client.c */
|
||||
|
||||
void submit_command(char *cmd_raw);
|
||||
|
||||
/* die() with system error messages */
|
||||
#define DIE(x, y...) die(x ": %s", ##y, strerror(errno))
|
||||
|
|
|
@ -60,7 +60,7 @@ cmd_build_tree(void)
|
|||
if (!new)
|
||||
{
|
||||
int size = sizeof(struct cmd_node) + c-d;
|
||||
new = xmalloc(size);
|
||||
new = malloc(size);
|
||||
bzero(new, size);
|
||||
*old->plastson = new;
|
||||
old->plastson = &new->sibling;
|
||||
|
@ -314,7 +314,7 @@ cmd_expand(char *cmd)
|
|||
puts("No such command. Press `?' for help.");
|
||||
return NULL;
|
||||
}
|
||||
b = xmalloc(strlen(n->cmd->command) + strlen(args) + 1);
|
||||
b = malloc(strlen(n->cmd->command) + strlen(args) + 1);
|
||||
sprintf(b, "%s%s", n->cmd->command, args);
|
||||
return b;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,11 @@ vlog(const char *msg, va_list args)
|
|||
{
|
||||
char buf[1024];
|
||||
|
||||
if (bvsnprintf(buf, sizeof(buf)-1, msg, args) < 0)
|
||||
bsprintf(buf + sizeof(buf) - 100, " ... <too long>");
|
||||
int n = vsnprintf(buf, sizeof(buf), msg, args);
|
||||
if (n < 0)
|
||||
snprintf(buf, sizeof(buf), "???");
|
||||
if (n >= sizeof(buf))
|
||||
snprintf(buf + sizeof(buf) - 100, 100, " ... <too long>");
|
||||
fputs(buf, stderr);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
|
|
@ -563,6 +563,7 @@ cf_lex_init_kh(void)
|
|||
/**
|
||||
* cf_lex_init - initialize the lexer
|
||||
* @is_cli: true if we're going to parse CLI command, false for configuration
|
||||
* @c: configuration structure
|
||||
*
|
||||
* cf_lex_init() initializes the lexical analyzer and prepares it for
|
||||
* parsing of a new input.
|
||||
|
|
|
@ -167,7 +167,7 @@ fi
|
|||
|
||||
AC_SUBST(iproutedir)
|
||||
|
||||
# all_protocols="$proto_bfd bgp ospf pipe radv rip static"
|
||||
# all_protocols="$proto_bfd babel bgp ospf pipe radv rip static"
|
||||
all_protocols="$proto_bfd ospf pipe radv rip static"
|
||||
|
||||
all_protocols=`echo $all_protocols | sed 's/ /,/g'`
|
||||
|
|
230
doc/bird.sgml
230
doc/bird.sgml
|
@ -171,6 +171,11 @@ BIRD executable by configuring out routing protocols you don't use, and
|
|||
<tag>-f</tag>
|
||||
run bird in foreground.
|
||||
|
||||
<tag>-l</tag>
|
||||
look for a configuration file and a communication socket in the current
|
||||
working directory instead of in default system locations. However, paths
|
||||
specified by options <cf/-c/, <cf/-s/ have higher priority.
|
||||
|
||||
<tag>-R</tag>
|
||||
apply graceful restart recovery after start.
|
||||
</descrip>
|
||||
|
@ -190,7 +195,7 @@ privileges (capabilities CAP_NET_*). Note that the control socket is created
|
|||
before the privileges are dropped, but the config file is read after that. The
|
||||
privilege restriction is not implemented in BSD port of BIRD.
|
||||
|
||||
<p>A nonprivileged user (as an argument to <cf/-u/ options) may be the user
|
||||
<p>An unprivileged user (as an argument to <cf/-u/ options) may be the user
|
||||
<cf/nobody/, but it is suggested to use a new dedicated user account (like
|
||||
<cf/bird/). The similar considerations apply for the group option, but there is
|
||||
one more condition -- the users in the same group can use <file/birdc/ to
|
||||
|
@ -283,7 +288,7 @@ extensive way.
|
|||
a comment, whitespace characters are treated as a single space. If there's a
|
||||
variable number of options, they are grouped using the <cf/{ }/ brackets. Each
|
||||
option is terminated by a <cf/;/. Configuration is case sensitive. There are two
|
||||
ways how to name symbols (like protocol names, filter names, constats etc.). You
|
||||
ways how to name symbols (like protocol names, filter names, constants etc.). You
|
||||
can either use a simple string starting with a letter followed by any
|
||||
combination of letters and numbers (e.g. "R123", "myfilter", "bgp5") or you can
|
||||
enclose the name into apostrophes (<cf/'/) and than you can use any combination
|
||||
|
@ -712,6 +717,10 @@ This argument can be omitted if there exists only a single instance.
|
|||
Show router status, that is BIRD version, uptime and time from last
|
||||
reconfiguration.
|
||||
|
||||
<tag>show interfaces [summary]</tag>
|
||||
Show the list of interfaces. For each interface, print its type, state,
|
||||
MTU and addresses assigned.
|
||||
|
||||
<tag>show protocols [all]</tag>
|
||||
Show list of protocol instances along with tables they are connected to
|
||||
and protocol status, possibly giving verbose information, if <cf/all/ is
|
||||
|
@ -739,16 +748,18 @@ This argument can be omitted if there exists only a single instance.
|
|||
Show contents of an OSPF LSA database. Options could be used to filter
|
||||
entries.
|
||||
|
||||
<tag>show rip interfaces [<m/name/] ["<m/interface/"]</tag>
|
||||
Show detailed information about RIP interfaces.
|
||||
|
||||
<tag>show rip neighbors [<m/name/] ["<m/interface/"]</tag>
|
||||
Show a list of RIP neighbors and associated state.
|
||||
|
||||
<tag>show static [<m/name/]</tag>
|
||||
Show detailed information about static routes.
|
||||
|
||||
<tag>show bfd sessions [<m/name/]</tag>
|
||||
Show information about BFD sessions.
|
||||
|
||||
<tag>show interfaces [summary]</tag>
|
||||
Show the list of interfaces. For each interface, print its type, state,
|
||||
MTU and addresses assigned.
|
||||
|
||||
<tag>show symbols [table|filter|function|protocol|template|roa|<m/symbol/]</tag>
|
||||
Show the list of symbols defined in the configuration (names of
|
||||
protocols, routing tables etc.).
|
||||
|
@ -824,7 +835,7 @@ This argument can be omitted if there exists only a single instance.
|
|||
configuration could be either confirmed using <cf/configure confirm/
|
||||
command, or it will be reverted to the old one when the config timer
|
||||
expires. This is useful for cases when reconfiguration breaks current
|
||||
routing and a router becames inaccessible for an administrator. The
|
||||
routing and a router becomes inaccessible for an administrator. The
|
||||
config timeout expiration is equivalent to <cf/configure undo/
|
||||
command. The timeout duration could be specified, default is 300 s.
|
||||
|
||||
|
@ -1005,7 +1016,7 @@ foot).
|
|||
of type <cf/string/, print such variables, use standard string
|
||||
comparison operations (e.g. <cf/=, !=, <, >, <=, >=/), but
|
||||
you can't concatenate two strings. String literals are written as
|
||||
<cf/"This is a string constant"/. Additionaly matching <cf/˜/
|
||||
<cf/"This is a string constant"/. Additionally matching <cf/˜/
|
||||
operator could be used to match a string value against a shell pattern
|
||||
(represented also as a string).
|
||||
|
||||
|
@ -1369,6 +1380,102 @@ corresponding protocol sections.
|
|||
|
||||
<chapt>Protocols
|
||||
|
||||
<sect>Babel
|
||||
|
||||
<sect1>Introduction
|
||||
|
||||
<p>The Babel protocol (RFC6126) is a loop-avoiding distance-vector routing
|
||||
protocol that is robust and efficient both in ordinary wired networks and in
|
||||
wireless mesh networks. Babel is conceptually very simple in its operation and
|
||||
"just works" in its default configuration, though some configuration is possible
|
||||
and in some cases desirable.
|
||||
|
||||
<p>While the Babel protocol is dual stack (i.e., can carry both IPv4 and IPv6
|
||||
routes over the same IPv6 transport), BIRD presently implements only the IPv6
|
||||
subset of the protocol. No Babel extensions are implemented, but the BIRD
|
||||
implementation can coexist with implementations using the extensions (and will
|
||||
just ignore extension messages).
|
||||
|
||||
<p>The Babel protocol implementation in BIRD is currently in alpha stage.
|
||||
|
||||
<sect1>Configuration
|
||||
|
||||
<p>Babel supports no global configuration options apart from those common to all
|
||||
other protocols, but supports the following per-interface configuration options:
|
||||
|
||||
<code>
|
||||
protocol babel [<name>] {
|
||||
interface <interface pattern> {
|
||||
type <wired|wireless>;
|
||||
rxcost <number>;
|
||||
hello interval <number>;
|
||||
update interval <number>;
|
||||
port <number>;
|
||||
tx class|dscp <number>;
|
||||
tx priority <number>;
|
||||
rx buffer <number>;
|
||||
tx length <number>;
|
||||
check link <switch>;
|
||||
};
|
||||
}
|
||||
</code>
|
||||
|
||||
<descrip>
|
||||
<tag>type wired|wireless </tag>
|
||||
This option specifies the interface type: Wired or wireless. Wired
|
||||
interfaces are considered more reliable, and so the default hello
|
||||
interval is higher, and a neighbour is considered unreachable after only
|
||||
a small number of "hello" packets are lost. On wireless interfaces,
|
||||
hello packets are sent more often, and the ETX link quality estimation
|
||||
technique is used to compute the metrics of routes discovered over this
|
||||
interface. This technique will gradually degrade the metric of routes
|
||||
when packets are lost rather than the more binary up/down mechanism of
|
||||
wired type links. Default: <cf/wired/.
|
||||
|
||||
<tag>rxcost <m/num/</tag>
|
||||
This specifies the RX cost of the interface. The route metrics will be
|
||||
computed from this value with a mechanism determined by the interface
|
||||
<cf/type/. Default: 96 for wired interfaces, 256 for wireless.
|
||||
|
||||
<tag>hello interval <m/num/</tag>
|
||||
Interval at which periodic "hello" messages are sent on this interface,
|
||||
in seconds. Default: 4 seconds.
|
||||
|
||||
<tag>update interval <m/num/</tag>
|
||||
Interval at which periodic (full) updates are sent. Default: 4 times the
|
||||
hello interval.
|
||||
|
||||
<tag>port <m/number/</tag>
|
||||
This option selects an UDP port to operate on. The default is to operate
|
||||
on port 6696 as specified in the Babel RFC.
|
||||
|
||||
<tag>tx class|dscp|priority <m/number/</tag>
|
||||
These options specify the ToS/DiffServ/Traffic class/Priority of the
|
||||
outgoing Babel packets. See <ref id="dsc-prio" name="tx class"> common
|
||||
option for detailed description.
|
||||
|
||||
<tag>rx buffer <m/number/</tag>
|
||||
This option specifies the size of buffers used for packet processing.
|
||||
The buffer size should be bigger than maximal size of received packets.
|
||||
The default value is the interface MTU, and the value will be clamped to a
|
||||
minimum of 512 bytes + IP packet overhead.
|
||||
|
||||
<tag>tx length <m/number/</tag>
|
||||
This option specifies the maximum length of generated Babel packets. To
|
||||
avoid IP fragmentation, it should not exceed the interface MTU value.
|
||||
The default value is the interface MTU value, and the value will be
|
||||
clamped to a minimum of 512 bytes + IP packet overhead.
|
||||
|
||||
<tag>check link <m/switch/</tag>
|
||||
If set, the hardware link state (as reported by OS) is taken into
|
||||
consideration. When the link disappears (e.g. an ethernet cable is
|
||||
unplugged), neighbors are immediately considered unreachable and all
|
||||
routes received from them are withdrawn. It is possible that some
|
||||
hardware drivers or platforms do not implement this feature. Default:
|
||||
yes.
|
||||
</descrip>
|
||||
|
||||
|
||||
<sect><label id="sect-bfd">BFD
|
||||
|
||||
<sect1>Introduction
|
||||
|
@ -1472,7 +1579,7 @@ protocol bfd [<name>] {
|
|||
|
||||
The session is identified by the IP address of the neighbor, with
|
||||
optional specification of used interface and local IP. By default
|
||||
the neighbor must be directly connected, unless the the session is
|
||||
the neighbor must be directly connected, unless the session is
|
||||
configured as multihop. Note that local IP must be specified for
|
||||
multihop sessions.
|
||||
</descrip>
|
||||
|
@ -1515,7 +1622,7 @@ protocol bfd [<name>] {
|
|||
Default: 5.
|
||||
|
||||
<tag>passive <m/switch/</tag>
|
||||
Generally, both BFD session endpoinds try to establish the session by
|
||||
Generally, both BFD session endpoints try to establish the session by
|
||||
sending control packets to the other side. This option allows to enable
|
||||
passive mode, which means that the router does not send BFD packets
|
||||
until it has received one from the other side. Default: disabled.
|
||||
|
@ -1753,9 +1860,20 @@ using the following configuration parameters:
|
|||
only. Default: disabled.
|
||||
|
||||
<tag>password <m/string/</tag>
|
||||
Use this password for MD5 authentication of BGP sessions. Default: no
|
||||
authentication. Password has to be set by external utility
|
||||
(e.g. setkey(8)) on BSD systems.
|
||||
Use this password for MD5 authentication of BGP sessions (RFC 2385).
|
||||
When used on BSD systems, see also <cf/setkey/ option below. Default:
|
||||
no authentication.
|
||||
|
||||
<tag>setkey <m/switch/</tag>
|
||||
On BSD systems, keys for TCP MD5 authentication are stored in the global
|
||||
SA/SP database, which can be accessed by external utilities (e.g.
|
||||
setkey(8)). BIRD configures security associations in the SA/SP database
|
||||
automatically based on <cf/password/ options (see above), this option
|
||||
allows to disable automatic updates by BIRD when manual configuration by
|
||||
external utilities is preferred. Note that automatic SA/SP database
|
||||
updates are currently implemented only for FreeBSD. Passwords have to be
|
||||
set manually by an external utility on NetBSD and OpenBSD. Default:
|
||||
enabled (ignored on non-FreeBSD).
|
||||
|
||||
<tag>passive <m/switch/</tag>
|
||||
Standard BGP behavior is both initiating outgoing connections and
|
||||
|
@ -2150,7 +2268,7 @@ conditions, because a lower priority IGP route for the same network is not
|
|||
exported to the kernel routing table. This is an issue on BSD systems only, as
|
||||
on Linux systems BIRD cannot change non-BIRD route in the kernel routing table.
|
||||
|
||||
<p>The only configurable thing about direct is what interfaces it watches:
|
||||
<p>There are just few configuration options for the Direct protocol:
|
||||
|
||||
<p><descrip>
|
||||
<tag>interface <m/pattern [, ...]/</tag>
|
||||
|
@ -2161,6 +2279,12 @@ on Linux systems BIRD cannot change non-BIRD route in the kernel routing table.
|
|||
interfaces), just use this clause. See <ref id="dsc-iface" name="interface">
|
||||
common option for detailed description. The Direct protocol uses
|
||||
extended interface clauses.
|
||||
|
||||
<tag>check link <m/switch/</tag>
|
||||
If enabled, a hardware link state (reported by OS) is taken into
|
||||
consideration. Routes for directly connected networks are generated only
|
||||
if link up is reported and they are withdrawn when link disappears
|
||||
(e.g., an ethernet cable is unplugged). Default value is no.
|
||||
</descrip>
|
||||
|
||||
<p>Direct device routes don't contain any specific attributes.
|
||||
|
@ -2634,7 +2758,7 @@ protocol ospf <name> {
|
|||
<tag>dead <M>num</M></tag>
|
||||
When the router does not receive any messages from a neighbor in
|
||||
<m/dead/ seconds, it will consider the neighbor down. If both directives
|
||||
<cf/dead count/ and <cf/dead/ are used, <cf/dead/ has precendence.
|
||||
<cf/dead count/ and <cf/dead/ are used, <cf/dead/ has precedence.
|
||||
|
||||
<tag>secondary <M>switch</M></tag>
|
||||
On BSD systems, older versions of BIRD supported OSPFv2 only for the
|
||||
|
@ -3365,6 +3489,11 @@ protocol rip [<name>] {
|
|||
RIP, the option is not supported for RIPng, as no further versions are
|
||||
defined.
|
||||
|
||||
<tag>version only <m/switch/</tag>
|
||||
Regardless of RIP version configured for the interface, BIRD accepts
|
||||
incoming packets of any RIP version. This option restrict accepted
|
||||
packets to the configured version. Default: no.
|
||||
|
||||
<tag>split horizon <m/switch/</tag>
|
||||
Split horizon is a scheme for preventing routing loops. When split
|
||||
horizon is active, routes are not regularly propagated back to the
|
||||
|
@ -3509,7 +3638,7 @@ default route to prevent routing loops).
|
|||
packets to a neighboring router, multipath routes specifying several (possibly
|
||||
weighted) neighboring routers, device routes specifying forwarding to hosts on a
|
||||
directly connected network, recursive routes computing their nexthops by doing
|
||||
route table lookups for a given IP and special routes (sink, blackhole etc.)
|
||||
route table lookups for a given IP, and special routes (sink, blackhole etc.)
|
||||
which specify a special action to be done instead of forwarding the packet.
|
||||
|
||||
<p>When the particular destination is not available (the interface is down or
|
||||
|
@ -3517,8 +3646,26 @@ the next hop of the route is not a neighbor at the moment), Static just
|
|||
uninstalls the route from the table it is connected to and adds it again as soon
|
||||
as the destination becomes adjacent again.
|
||||
|
||||
<p>The Static protocol does not have many configuration options. The definition
|
||||
of the protocol contains mainly a list of static routes:
|
||||
<p>There are three classes of definitions in Static protocol configuration --
|
||||
global options, static route definitions, and per-route options. Usually, the
|
||||
definition of the protocol contains mainly a list of static routes.
|
||||
|
||||
<p>Global options:
|
||||
|
||||
<descrip>
|
||||
<tag>check link <m/switch/</tag>
|
||||
If set, hardware link states of network interfaces are taken into
|
||||
consideration. When link disappears (e.g. ethernet cable is unplugged),
|
||||
static routes directing to that interface are removed. It is possible
|
||||
that some hardware drivers or platforms do not implement this feature.
|
||||
Default: off.
|
||||
|
||||
<tag>igp table <m/name/</tag>
|
||||
Specifies a table that is used for route table lookups of recursive
|
||||
routes. Default: the same table as the protocol is connected to.
|
||||
</descrip>
|
||||
|
||||
<p>Route definitions (each may also contain a block of per-route options):
|
||||
|
||||
<descrip>
|
||||
<tag>route <m/prefix/ via <m/ip/</tag>
|
||||
|
@ -3526,7 +3673,7 @@ of the protocol contains mainly a list of static routes:
|
|||
interface can be specified as a part of the address (e.g.,
|
||||
<cf/via fe80::1234%eth0/).
|
||||
|
||||
<tag>route <m/prefix/ multipath via <m/ip/ [weight <m/num/] [via ...]</tag>
|
||||
<tag>route <m/prefix/ multipath via <m/ip/ [weight <m/num/] [bfd <m/switch/] [via ...]</tag>
|
||||
Static multipath route. Contains several nexthops (gateways), possibly
|
||||
with their weights.
|
||||
|
||||
|
@ -3542,17 +3689,33 @@ of the protocol contains mainly a list of static routes:
|
|||
Special routes specifying to silently drop the packet, return it as
|
||||
unreachable or return it as administratively prohibited. First two
|
||||
targets are also known as <cf/drop/ and <cf/reject/.
|
||||
</descrip>
|
||||
|
||||
<tag>check link <m/switch/</tag>
|
||||
If set, hardware link states of network interfaces are taken into
|
||||
consideration. When link disappears (e.g. ethernet cable is unplugged),
|
||||
static routes directing to that interface are removed. It is possible
|
||||
that some hardware drivers or platforms do not implement this feature.
|
||||
Default: off.
|
||||
<p>Per-route options:
|
||||
|
||||
<tag>igp table <m/name/</tag>
|
||||
Specifies a table that is used for route table lookups of recursive
|
||||
routes. Default: the same table as the protocol is connected to.
|
||||
<descrip>
|
||||
<tag>bfd <m/switch/</tag>
|
||||
The Static protocol could use BFD protocol for next hop liveness
|
||||
detection. If enabled, a BFD session to the route next hop is created
|
||||
and the static route is BFD-controlled -- the static route is announced
|
||||
only if the next hop liveness is confirmed by BFD. If the BFD session
|
||||
fails, the static route is removed. Note that this is a bit different
|
||||
compared to other protocols, which may use BFD as an advisory mechanism
|
||||
for fast failure detection but ignores it if a BFD session is not even
|
||||
established.
|
||||
|
||||
This option can be used for static routes with a direct next hop, or
|
||||
also for for individual next hops in a static multipath route (see
|
||||
above). Note that BFD protocol also has to be configured, see
|
||||
<ref id="sect-bfd" name="BFD"> section for details. Default value is no.
|
||||
|
||||
<tag><m/filter expression/</tag>
|
||||
This is a special option that allows filter expressions to be configured
|
||||
on per-route basis. Can be used multiple times. These expressions are
|
||||
evaluated when the route is originated, similarly to the import filter
|
||||
of the static protocol. This is especially useful for configuring route
|
||||
attributes, e.g., <cf/ospf_metric1 = 100;/ for a route that will be
|
||||
exported to the OSPF protocol.
|
||||
</descrip>
|
||||
|
||||
<p>Static routes have no specific attributes.
|
||||
|
@ -3562,13 +3725,22 @@ of the protocol contains mainly a list of static routes:
|
|||
<p><code>
|
||||
protocol static {
|
||||
table testable; # Connect to a non-default routing table
|
||||
check link; # Advertise routes only if link is up
|
||||
route 0.0.0.0/0 via 198.51.100.130; # Default route
|
||||
route 10.0.0.0/8 multipath # Multipath route
|
||||
via 198.51.100.10 weight 2
|
||||
via 198.51.100.20
|
||||
via 198.51.100.20 bfd # BFD-controlled next hop
|
||||
via 192.0.2.1;
|
||||
route 203.0.113.0/24 unreachable; # Sink route
|
||||
route 10.2.0.0/24 via "arc0"; # Secondary network
|
||||
route 192.168.10.0/24 via 198.51.100.100 {
|
||||
ospf_metric1 = 20; # Set extended attribute
|
||||
}
|
||||
route 192.168.10.0/24 via 198.51.100.100 {
|
||||
ospf_metric2 = 100; # Set extended attribute
|
||||
ospf_tag = 2; # Set extended attribute
|
||||
bfd; # BFD-controlled route
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
|
|
@ -57,6 +57,9 @@ Reply codes of BIRD command-line interface
|
|||
1020 Show BFD sessions
|
||||
1021 Show RIP interface
|
||||
1022 Show RIP neighbors
|
||||
1023 Show Babel interfaces
|
||||
1024 Show Babel neighbors
|
||||
1025 Show Babel entries
|
||||
|
||||
8000 Reply too long
|
||||
8001 Route not found
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
src := bitops.c checksum.c ip.c lists.c md5.c net.c patmatch.c printf.c sha1.c sha256.c sha512.c slists.c xmalloc.c
|
||||
obj := $(src-o-files)
|
||||
$(all-client)
|
||||
|
||||
src := bitops.c checksum.c event.c idm.c ip.c lists.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c xmalloc.c
|
||||
obj := $(src-o-files)
|
||||
$(all-daemon)
|
||||
|
|
|
@ -61,6 +61,7 @@ static inline int u64_cmp(u64 i1, u64 i2)
|
|||
|
||||
#define NORET __attribute__((noreturn))
|
||||
#define UNUSED __attribute__((unused))
|
||||
#define PACKED __attribute__((packed))
|
||||
|
||||
|
||||
/* Microsecond time */
|
||||
|
|
|
@ -25,5 +25,6 @@ u32 u32_log2(u32 v);
|
|||
|
||||
static inline u32 u32_hash(u32 v) { return v * 2902958171u; }
|
||||
|
||||
#endif
|
||||
static inline u8 u32_popcount(u32 v) { return __builtin_popcount(v); }
|
||||
|
||||
#endif
|
||||
|
|
1
lib/ip.h
1
lib/ip.h
|
@ -26,6 +26,7 @@
|
|||
#define IP6_OSPF_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 5)
|
||||
#define IP6_OSPF_DES_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
|
||||
#define IP6_RIP_ROUTERS ipa_build6(0xFF020000, 0, 0, 9)
|
||||
#define IP6_BABEL_ROUTERS ipa_build6(0xFF020000, 0, 0, 0x00010006)
|
||||
|
||||
#define IP4_NONE _MI4(0)
|
||||
#define IP6_NONE _MI6(0,0,0,0)
|
||||
|
|
23
lib/printf.c
23
lib/printf.c
|
@ -124,9 +124,10 @@ static char * number(char * str, long num, int base, int size, int precision,
|
|||
* standard IP address width which depends on whether we use IPv4 or IPv6; |%I4|
|
||||
* or |%I6| can be used for explicit ip4_addr / ip6_addr arguments, |%N| for
|
||||
* generic network addresses (net_addr *), |%R| for Router / Network ID (u32
|
||||
* value printed as IPv4 address) and |%m| resp. |%M| for error messages (uses
|
||||
* strerror() to translate @errno code to message text). On the other hand, it
|
||||
* doesn't support floating point numbers.
|
||||
* value printed as IPv4 address), |%lR| for 64bit Router / Network ID (u64
|
||||
* value printed as eight :-separated octets) and |%m| resp. |%M| for error
|
||||
* messages (uses strerror() to translate @errno code to message text). On the
|
||||
* other hand, it doesn't support floating point numbers.
|
||||
*
|
||||
* Result: number of characters of the output string or -1 if
|
||||
* the buffer space was insufficient.
|
||||
|
@ -137,6 +138,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
|
|||
unsigned long num;
|
||||
int i, base;
|
||||
u32 x;
|
||||
u64 X;
|
||||
char *str, *start;
|
||||
const char *s;
|
||||
char ipbuf[NET_MAX_TEXT_LENGTH+1];
|
||||
|
@ -338,8 +340,23 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
|
|||
|
||||
/* Router/Network ID - essentially IPv4 address in u32 value */
|
||||
case 'R':
|
||||
if (qualifier == 'l') {
|
||||
X = va_arg(args, u64);
|
||||
bsprintf(ipbuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
((X >> 56) & 0xff),
|
||||
((X >> 48) & 0xff),
|
||||
((X >> 40) & 0xff),
|
||||
((X >> 32) & 0xff),
|
||||
((X >> 24) & 0xff),
|
||||
((X >> 16) & 0xff),
|
||||
((X >> 8) & 0xff),
|
||||
(X & 0xff));
|
||||
}
|
||||
else
|
||||
{
|
||||
x = va_arg(args, u32);
|
||||
ip4_ntop(ip4_from_u32(x), ipbuf);
|
||||
}
|
||||
s = ipbuf;
|
||||
goto str;
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ int sk_leave_group(sock *s, ip_addr maddr); /* Leave multicast group on sk iface
|
|||
int sk_setup_broadcast(sock *s);
|
||||
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
|
||||
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
|
||||
int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
|
||||
int sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd, int setkey);
|
||||
int sk_set_ipv6_checksum(sock *s, int offset);
|
||||
int sk_set_icmp6_filter(sock *s, int p1, int p2);
|
||||
void sk_log_error(sock *s, const char *p);
|
||||
|
|
|
@ -24,4 +24,12 @@ void buffer_puts(buffer *buf, const char *str);
|
|||
|
||||
int patmatch(const byte *pat, const byte *str);
|
||||
|
||||
static inline char *xbasename(const char *str)
|
||||
{
|
||||
char *s = strrchr(str, '/');
|
||||
return s ? s+1 : (char *) str;
|
||||
}
|
||||
|
||||
#define ROUTER_ID_64_LENGTH 23
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Summary: BIRD Internet Routing Daemon
|
||||
Name: bird
|
||||
Version: 1.5.0
|
||||
Version: 1.6.0
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Networking/Daemons
|
||||
|
|
|
@ -357,6 +357,7 @@ dev_proto:
|
|||
| dev_proto proto_item ';'
|
||||
| dev_proto proto_channel ';'
|
||||
| dev_proto dev_iface_patt ';'
|
||||
| dev_proto CHECK LINK bool ';' { DIRECT_CFG->check_link = $4; }
|
||||
;
|
||||
|
||||
dev_iface_init:
|
||||
|
|
|
@ -340,7 +340,7 @@ neigh_if_link(struct iface *i)
|
|||
|
||||
/**
|
||||
* neigh_ifa_update: notify neighbor cache about interface address add or remove event
|
||||
* @ifa: interface address in question
|
||||
* @a: interface address in question
|
||||
*
|
||||
* Tell the neighbor cache that an address was added or removed.
|
||||
*
|
||||
|
|
|
@ -148,6 +148,7 @@ void get_route_info(rte *e, byte *buf, ea_list *attrs)
|
|||
* get_attr - get attribute information
|
||||
* @a: an extended attribute
|
||||
* @buf: buffer to be filled with attribute information
|
||||
* @buflen: a length of the @buf parameter
|
||||
*
|
||||
* The get_attr() hook is called by the core to obtain a user friendly
|
||||
* representation of an extended route attribute. It can either leave
|
||||
|
|
|
@ -1068,6 +1068,7 @@ graceful_restart_init(void)
|
|||
|
||||
/**
|
||||
* graceful_restart_done - finalize graceful restart
|
||||
* @t: unused
|
||||
*
|
||||
* When there are no locks on graceful restart, the functions finalizes the
|
||||
* graceful restart recovery. Protocols postponing route export until the end of
|
||||
|
@ -1258,6 +1259,9 @@ protos_build(void)
|
|||
proto_build(&proto_bfd);
|
||||
bfd_init_all();
|
||||
#endif
|
||||
#ifdef CONFIG_BABEL
|
||||
proto_build(&proto_babel);
|
||||
#endif
|
||||
|
||||
proto_pool = rp_new(&root_pool, "Protocols");
|
||||
proto_shutdown_timer = tm_new(proto_pool);
|
||||
|
|
|
@ -81,7 +81,7 @@ void protos_dump_all(void);
|
|||
|
||||
extern struct protocol
|
||||
proto_device, proto_radv, proto_rip, proto_static,
|
||||
proto_ospf, proto_pipe, proto_bgp, proto_bfd;
|
||||
proto_ospf, proto_pipe, proto_bgp, proto_bfd, proto_babel;
|
||||
|
||||
/*
|
||||
* Routing Protocol Instance
|
||||
|
|
11
nest/route.h
11
nest/route.h
|
@ -228,6 +228,12 @@ typedef struct rte {
|
|||
struct {
|
||||
u8 suppressed; /* Used for deterministic MED comparison */
|
||||
} bgp;
|
||||
#endif
|
||||
#ifdef CONFIG_BABEL
|
||||
struct {
|
||||
u16 metric; /* Babel metric */
|
||||
u64 router_id; /* Babel router id */
|
||||
} babel;
|
||||
#endif
|
||||
struct { /* Routes generated by krt sync (both temporary and inherited ones) */
|
||||
s8 src; /* Alleged route source (see krt.h) */
|
||||
|
@ -377,6 +383,7 @@ typedef struct rta {
|
|||
#define RTS_OSPF_EXT2 10 /* OSPF external route type 2 */
|
||||
#define RTS_BGP 11 /* BGP route */
|
||||
#define RTS_PIPE 12 /* Inter-table wormhole */
|
||||
#define RTS_BABEL 13 /* Babel route */
|
||||
|
||||
#define RTC_UNICAST 0
|
||||
#define RTC_BROADCAST 1
|
||||
|
@ -425,7 +432,8 @@ typedef struct eattr {
|
|||
#define EAP_RIP 2 /* RIP */
|
||||
#define EAP_OSPF 3 /* OSPF */
|
||||
#define EAP_KRT 4 /* Kernel route attributes */
|
||||
#define EAP_MAX 5
|
||||
#define EAP_BABEL 5 /* Babel attributes */
|
||||
#define EAP_MAX 6
|
||||
|
||||
#define EA_CODE(proto,id) (((proto) << 8) | (id))
|
||||
#define EA_PROTO(ea) ((ea) >> 8)
|
||||
|
@ -550,6 +558,7 @@ extern struct protocol *attr_class_to_protocol[EAP_MAX];
|
|||
#define DEF_PREF_DIRECT 240 /* Directly connected */
|
||||
#define DEF_PREF_STATIC 200 /* Static route */
|
||||
#define DEF_PREF_OSPF 150 /* OSPF intra-area, inter-area and type 1 external routes */
|
||||
#define DEF_PREF_BABEL 130 /* Babel */
|
||||
#define DEF_PREF_RIP 120 /* RIP */
|
||||
#define DEF_PREF_BGP 100 /* BGP */
|
||||
#define DEF_PREF_INHERITED 10 /* Routes inherited from other routing daemons */
|
||||
|
|
|
@ -353,7 +353,7 @@ ea_find(ea_list *e, unsigned id)
|
|||
* for first occurrences of attributes with ID in specified interval from @id to
|
||||
* (@id + @max - 1), returning pointers to found &eattr structures, storing its
|
||||
* walk state in @s for subsequent calls.
|
||||
|
||||
*
|
||||
* The function ea_walk() is supposed to be called in a loop, with initially
|
||||
* zeroed walk state structure @s with filled the initial extended attribute
|
||||
* list, returning one found attribute in each call or %NULL when no other
|
||||
|
|
|
@ -68,6 +68,9 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
|
|||
|
||||
DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);
|
||||
|
||||
if (cf->check_link && !(ad->iface->flags & IF_LINK_UP))
|
||||
return;
|
||||
|
||||
/* Use iface ID as local source ID */
|
||||
struct rte_src *src = rt_get_source(P, ad->iface->index);
|
||||
|
||||
|
@ -87,6 +90,25 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dev_if_notify(struct proto *p, uint c, struct iface *iface)
|
||||
{
|
||||
struct rt_dev_config *cf = (void *) p->cf;
|
||||
|
||||
if (c & (IF_CHANGE_UP | IF_CHANGE_DOWN))
|
||||
return;
|
||||
|
||||
if ((c & IF_CHANGE_LINK) && cf->check_link)
|
||||
{
|
||||
uint ac = (iface->flags & IF_LINK_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN;
|
||||
|
||||
struct ifa *a;
|
||||
WALK_LIST(a, iface->addrs)
|
||||
dev_ifa_notify(p, ac, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct proto *
|
||||
dev_init(struct proto_config *CF)
|
||||
{
|
||||
|
@ -97,6 +119,7 @@ dev_init(struct proto_config *CF)
|
|||
proto_configure_channel(P, &p->ip4_channel, proto_cf_find_channel(CF, NET_IP4));
|
||||
proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6));
|
||||
|
||||
P->if_notify = dev_if_notify;
|
||||
P->ifa_notify = dev_ifa_notify;
|
||||
|
||||
return P;
|
||||
|
@ -109,7 +132,8 @@ dev_reconfigure(struct proto *P, struct proto_config *CF)
|
|||
struct rt_dev_config *o = (void *) P->cf;
|
||||
struct rt_dev_config *n = (void *) CF;
|
||||
|
||||
if (!iface_patts_equal(&o->iface_list, &n->iface_list, NULL))
|
||||
if (!iface_patts_equal(&o->iface_list, &n->iface_list, NULL) ||
|
||||
(o->check_link != n->check_link))
|
||||
return 0;
|
||||
|
||||
return
|
||||
|
@ -131,6 +155,8 @@ dev_copy_config(struct proto_config *dest, struct proto_config *src)
|
|||
* old nodes cannot be modified (although they contain internal lists).
|
||||
*/
|
||||
cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt));
|
||||
|
||||
d->check_link = s->check_link;
|
||||
}
|
||||
|
||||
struct protocol proto_device = {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
struct rt_dev_config {
|
||||
struct proto_config c;
|
||||
list iface_list; /* list of struct iface_patt */
|
||||
int check_link;
|
||||
};
|
||||
|
||||
struct rt_dev_proto {
|
||||
|
|
|
@ -834,16 +834,20 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
|
|||
* @net: network in question
|
||||
* @new: the new route to be announced
|
||||
* @old: the previous route for the same network
|
||||
* @new_best: the new best route for the same network
|
||||
* @old_best: the previous best route for the same network
|
||||
* @before_old: The previous route before @old for the same network.
|
||||
* If @before_old is NULL @old was the first.
|
||||
*
|
||||
* This function gets a routing table update and announces it
|
||||
* to all protocols that acccepts given type of route announcement
|
||||
* and are connected to the same table by their announcement hooks.
|
||||
*
|
||||
* Route announcement of type RA_OPTIMAL si generated when optimal
|
||||
* Route announcement of type %RA_OPTIMAL si generated when optimal
|
||||
* route (in routing table @tab) changes. In that case @old stores the
|
||||
* old optimal route.
|
||||
*
|
||||
* Route announcement of type RA_ANY si generated when any route (in
|
||||
* Route announcement of type %RA_ANY si generated when any route (in
|
||||
* routing table @tab) changes In that case @old stores the old route
|
||||
* from the same protocol.
|
||||
*
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
H Protocols
|
||||
C babel
|
||||
C bfd
|
||||
C bgp
|
||||
C ospf
|
||||
|
|
2
proto/babel/Doc
Normal file
2
proto/babel/Doc
Normal file
|
@ -0,0 +1,2 @@
|
|||
S babel.c
|
||||
S packets.c
|
5
proto/babel/Makefile
Normal file
5
proto/babel/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
source=babel.c packets.c
|
||||
root-rel=../../
|
||||
dir-name=proto/babel
|
||||
|
||||
include ../../Rules
|
2055
proto/babel/babel.c
Normal file
2055
proto/babel/babel.c
Normal file
File diff suppressed because it is too large
Load diff
335
proto/babel/babel.h
Normal file
335
proto/babel/babel.h
Normal file
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* BIRD -- The Babel protocol
|
||||
*
|
||||
* Copyright (c) 2015--2016 Toke Hoiland-Jorgensen
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*
|
||||
* This file contains the data structures used by Babel.
|
||||
*/
|
||||
|
||||
#ifndef _BIRD_BABEL_H_
|
||||
#define _BIRD_BABEL_H_
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "nest/cli.h"
|
||||
#include "nest/iface.h"
|
||||
#include "nest/route.h"
|
||||
#include "nest/protocol.h"
|
||||
#include "nest/locks.h"
|
||||
#include "lib/resource.h"
|
||||
#include "lib/lists.h"
|
||||
#include "lib/socket.h"
|
||||
#include "lib/string.h"
|
||||
#include "lib/timer.h"
|
||||
|
||||
#ifndef IPV6
|
||||
#error "The Babel protocol only speaks IPv6"
|
||||
#endif
|
||||
|
||||
#define EA_BABEL_METRIC EA_CODE(EAP_BABEL, 0)
|
||||
#define EA_BABEL_ROUTER_ID EA_CODE(EAP_BABEL, 1)
|
||||
|
||||
#define BABEL_MAGIC 42
|
||||
#define BABEL_VERSION 2
|
||||
#define BABEL_PORT 6696
|
||||
#define BABEL_INFINITY 0xFFFF
|
||||
|
||||
|
||||
#define BABEL_HELLO_INTERVAL_WIRED 4 /* Default hello intervals in seconds */
|
||||
#define BABEL_HELLO_INTERVAL_WIRELESS 4
|
||||
#define BABEL_UPDATE_INTERVAL_FACTOR 4
|
||||
#define BABEL_IHU_INTERVAL_FACTOR 3
|
||||
#define BABEL_IHU_EXPIRY_FACTOR(X) ((X)*3/2) /* 1.5 */
|
||||
#define BABEL_HELLO_EXPIRY_FACTOR(X) ((X)*3/2) /* 1.5 */
|
||||
#define BABEL_ROUTE_EXPIRY_FACTOR(X) ((X)*7/2) /* 3.5 */
|
||||
#define BABEL_ROUTE_REFRESH_INTERVAL 2 /* Seconds before route expiry to send route request */
|
||||
#define BABEL_HOLD_TIME 10 /* Expiry time for our own routes */
|
||||
#define BABEL_RXCOST_WIRED 96
|
||||
#define BABEL_RXCOST_WIRELESS 256
|
||||
#define BABEL_INITIAL_HOP_COUNT 255
|
||||
#define BABEL_MAX_SEND_INTERVAL 5
|
||||
#define BABEL_TIME_UNITS 100 /* On-wire times are counted in centiseconds */
|
||||
|
||||
#define BABEL_SEQNO_REQUEST_EXPIRY 60
|
||||
#define BABEL_GARBAGE_INTERVAL 300
|
||||
|
||||
#define BABEL_OVERHEAD (SIZE_OF_IP_HEADER+UDP_HEADER_LENGTH)
|
||||
#define BABEL_MIN_MTU (512 + BABEL_OVERHEAD)
|
||||
|
||||
|
||||
enum babel_tlv_type {
|
||||
BABEL_TLV_PAD1 = 0,
|
||||
BABEL_TLV_PADN = 1,
|
||||
BABEL_TLV_ACK_REQ = 2,
|
||||
BABEL_TLV_ACK = 3,
|
||||
BABEL_TLV_HELLO = 4,
|
||||
BABEL_TLV_IHU = 5,
|
||||
BABEL_TLV_ROUTER_ID = 6,
|
||||
BABEL_TLV_NEXT_HOP = 7,
|
||||
BABEL_TLV_UPDATE = 8,
|
||||
BABEL_TLV_ROUTE_REQUEST = 9,
|
||||
BABEL_TLV_SEQNO_REQUEST = 10,
|
||||
/* extensions - not implemented
|
||||
BABEL_TLV_TS_PC = 11,
|
||||
BABEL_TLV_HMAC = 12,
|
||||
BABEL_TLV_SS_UPDATE = 13,
|
||||
BABEL_TLV_SS_REQUEST = 14,
|
||||
BABEL_TLV_SS_SEQNO_REQUEST = 15,
|
||||
*/
|
||||
BABEL_TLV_MAX
|
||||
};
|
||||
|
||||
enum babel_iface_type {
|
||||
/* In practice, UNDEF and WIRED give equivalent behaviour */
|
||||
BABEL_IFACE_TYPE_UNDEF = 0,
|
||||
BABEL_IFACE_TYPE_WIRED = 1,
|
||||
BABEL_IFACE_TYPE_WIRELESS = 2,
|
||||
BABEL_IFACE_TYPE_MAX
|
||||
};
|
||||
|
||||
enum babel_ae_type {
|
||||
BABEL_AE_WILDCARD = 0,
|
||||
BABEL_AE_IP4 = 1,
|
||||
BABEL_AE_IP6 = 2,
|
||||
BABEL_AE_IP6_LL = 3,
|
||||
BABEL_AE_MAX
|
||||
};
|
||||
|
||||
|
||||
struct babel_config {
|
||||
struct proto_config c;
|
||||
|
||||
list iface_list; /* Patterns configured -- keep it first; see babel_reconfigure why */
|
||||
};
|
||||
|
||||
struct babel_iface_config {
|
||||
struct iface_patt i;
|
||||
|
||||
u16 rxcost;
|
||||
u8 type;
|
||||
u8 check_link;
|
||||
int port;
|
||||
u16 hello_interval;
|
||||
u16 ihu_interval;
|
||||
u16 update_interval;
|
||||
|
||||
u16 rx_buffer; /* RX buffer size, 0 for MTU */
|
||||
u16 tx_length; /* TX packet length limit (including headers), 0 for MTU */
|
||||
int tx_tos;
|
||||
int tx_priority;
|
||||
};
|
||||
|
||||
struct babel_proto {
|
||||
struct proto p;
|
||||
timer *timer;
|
||||
struct fib rtable;
|
||||
list interfaces; /* Interfaces we really know about (struct babel_iface) */
|
||||
u64 router_id;
|
||||
u16 update_seqno; /* To be increased on request */
|
||||
u8 triggered; /* For triggering global updates */
|
||||
|
||||
slab *route_slab;
|
||||
slab *source_slab;
|
||||
slab *msg_slab;
|
||||
|
||||
slab *seqno_slab;
|
||||
list seqno_cache; /* Seqno requests in the cache (struct babel_seqno_request) */
|
||||
|
||||
struct tbf log_pkt_tbf; /* TBF for packet messages */
|
||||
};
|
||||
|
||||
struct babel_iface {
|
||||
node n;
|
||||
|
||||
struct babel_proto *proto;
|
||||
struct iface *iface;
|
||||
|
||||
struct babel_iface_config *cf;
|
||||
|
||||
u8 up;
|
||||
|
||||
pool *pool;
|
||||
char *ifname;
|
||||
sock *sk;
|
||||
ip_addr addr;
|
||||
int tx_length;
|
||||
list neigh_list; /* List of neighbors seen on this iface (struct babel_neighbor) */
|
||||
list msg_queue;
|
||||
|
||||
u16 hello_seqno; /* To be increased on each hello */
|
||||
|
||||
bird_clock_t next_hello;
|
||||
bird_clock_t next_regular;
|
||||
bird_clock_t next_triggered;
|
||||
bird_clock_t want_triggered;
|
||||
|
||||
timer *timer;
|
||||
event *send_event;
|
||||
};
|
||||
|
||||
struct babel_neighbor {
|
||||
node n;
|
||||
struct babel_iface *ifa;
|
||||
|
||||
ip_addr addr;
|
||||
u16 txcost;
|
||||
u8 hello_cnt;
|
||||
u16 hello_map;
|
||||
u16 next_hello_seqno;
|
||||
/* expiry timers */
|
||||
bird_clock_t hello_expiry;
|
||||
bird_clock_t ihu_expiry;
|
||||
|
||||
list routes; /* Routes this neighbour has sent us (struct babel_route) */
|
||||
};
|
||||
|
||||
struct babel_source {
|
||||
node n;
|
||||
|
||||
u64 router_id;
|
||||
u16 seqno;
|
||||
u16 metric;
|
||||
bird_clock_t expires;
|
||||
};
|
||||
|
||||
struct babel_route {
|
||||
node n;
|
||||
node neigh_route;
|
||||
struct babel_entry *e;
|
||||
struct babel_neighbor *neigh;
|
||||
|
||||
u16 seqno;
|
||||
u16 advert_metric;
|
||||
u16 metric;
|
||||
u64 router_id;
|
||||
ip_addr next_hop;
|
||||
bird_clock_t refresh_time;
|
||||
bird_clock_t expires;
|
||||
u16 expiry_interval;
|
||||
};
|
||||
|
||||
struct babel_entry {
|
||||
struct fib_node n;
|
||||
struct babel_proto *proto;
|
||||
struct babel_route *selected_in;
|
||||
struct babel_route *selected_out;
|
||||
|
||||
bird_clock_t updated;
|
||||
|
||||
list sources; /* Source entries for this prefix (struct babel_source). */
|
||||
list routes; /* Routes for this prefix (struct babel_route) */
|
||||
};
|
||||
|
||||
/* Stores forwarded seqno requests for duplicate suppression. */
|
||||
struct babel_seqno_request {
|
||||
node n;
|
||||
ip_addr prefix;
|
||||
u8 plen;
|
||||
u64 router_id;
|
||||
u16 seqno;
|
||||
bird_clock_t updated;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Internal TLV messages
|
||||
*/
|
||||
|
||||
struct babel_msg_ack_req {
|
||||
u8 type;
|
||||
u16 nonce;
|
||||
u16 interval;
|
||||
ip_addr sender;
|
||||
};
|
||||
|
||||
struct babel_msg_ack {
|
||||
u8 type;
|
||||
u16 nonce;
|
||||
};
|
||||
|
||||
struct babel_msg_hello {
|
||||
u8 type;
|
||||
u16 seqno;
|
||||
u16 interval;
|
||||
ip_addr sender;
|
||||
};
|
||||
|
||||
struct babel_msg_ihu {
|
||||
u8 type;
|
||||
u8 ae;
|
||||
u16 rxcost;
|
||||
u16 interval;
|
||||
ip_addr addr;
|
||||
ip_addr sender;
|
||||
};
|
||||
|
||||
struct babel_msg_update {
|
||||
u8 type;
|
||||
u8 ae;
|
||||
u8 plen;
|
||||
u16 interval;
|
||||
u16 seqno;
|
||||
u16 metric;
|
||||
ip_addr prefix;
|
||||
u64 router_id;
|
||||
ip_addr next_hop;
|
||||
ip_addr sender;
|
||||
};
|
||||
|
||||
struct babel_msg_route_request {
|
||||
u8 type;
|
||||
u8 full;
|
||||
u8 plen;
|
||||
ip_addr prefix;
|
||||
};
|
||||
|
||||
struct babel_msg_seqno_request {
|
||||
u8 type;
|
||||
u8 plen;
|
||||
u16 seqno;
|
||||
u8 hop_count;
|
||||
u64 router_id;
|
||||
ip_addr prefix;
|
||||
ip_addr sender;
|
||||
};
|
||||
|
||||
union babel_msg {
|
||||
u8 type;
|
||||
struct babel_msg_ack_req ack_req;
|
||||
struct babel_msg_ack ack;
|
||||
struct babel_msg_hello hello;
|
||||
struct babel_msg_ihu ihu;
|
||||
struct babel_msg_update update;
|
||||
struct babel_msg_route_request route_request;
|
||||
struct babel_msg_seqno_request seqno_request;
|
||||
};
|
||||
|
||||
struct babel_msg_node {
|
||||
node n;
|
||||
union babel_msg msg;
|
||||
};
|
||||
|
||||
|
||||
/* babel.c */
|
||||
void babel_handle_ack_req(union babel_msg *msg, struct babel_iface *ifa);
|
||||
void babel_handle_ack(union babel_msg *msg, struct babel_iface *ifa);
|
||||
void babel_handle_hello(union babel_msg *msg, struct babel_iface *ifa);
|
||||
void babel_handle_ihu(union babel_msg *msg, struct babel_iface *ifa);
|
||||
void babel_handle_router_id(union babel_msg *msg, struct babel_iface *ifa);
|
||||
void babel_handle_update(union babel_msg *msg, struct babel_iface *ifa);
|
||||
void babel_handle_route_request(union babel_msg *msg, struct babel_iface *ifa);
|
||||
void babel_handle_seqno_request(union babel_msg *msg, struct babel_iface *ifa);
|
||||
|
||||
void babel_show_interfaces(struct proto *P, char *iff);
|
||||
void babel_show_neighbors(struct proto *P, char *iff);
|
||||
void babel_show_entries(struct proto *P);
|
||||
|
||||
/* packets.c */
|
||||
void babel_enqueue(union babel_msg *msg, struct babel_iface *ifa);
|
||||
void babel_send_unicast(union babel_msg *msg, struct babel_iface *ifa, ip_addr dest);
|
||||
int babel_open_socket(struct babel_iface *ifa);
|
||||
void babel_send_queue(void *arg);
|
||||
|
||||
|
||||
#endif
|
129
proto/babel/config.Y
Normal file
129
proto/babel/config.Y
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* BIRD -- Babel Configuration
|
||||
*
|
||||
* Copyright (c) 2015-2016 Toke Hoiland-Jorgensen
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
CF_HDR
|
||||
|
||||
#include "proto/babel/babel.h"
|
||||
#include "nest/iface.h"
|
||||
|
||||
CF_DEFINES
|
||||
|
||||
#define BABEL_CFG ((struct babel_config *) this_proto)
|
||||
#define BABEL_IFACE ((struct babel_iface_config *) this_ipatt)
|
||||
|
||||
CF_DECLS
|
||||
|
||||
CF_KEYWORDS(BABEL, METRIC, RXCOST, HELLO, UPDATE, INTERVAL, PORT, WIRED,
|
||||
WIRELESS, RX, TX, BUFFER, LENGTH, CHECK, LINK, BABEL_METRIC)
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
CF_ADDTO(proto, babel_proto)
|
||||
|
||||
babel_proto_start: proto_start BABEL
|
||||
{
|
||||
this_proto = proto_config_new(&proto_babel, $1);
|
||||
init_list(&BABEL_CFG->iface_list);
|
||||
};
|
||||
|
||||
babel_proto_item:
|
||||
proto_item
|
||||
| INTERFACE babel_iface
|
||||
;
|
||||
|
||||
babel_proto_opts:
|
||||
/* empty */
|
||||
| babel_proto_opts babel_proto_item ';'
|
||||
;
|
||||
|
||||
babel_proto:
|
||||
babel_proto_start proto_name '{' babel_proto_opts '}';
|
||||
|
||||
|
||||
babel_iface_start:
|
||||
{
|
||||
this_ipatt = cfg_allocz(sizeof(struct babel_iface_config));
|
||||
add_tail(&BABEL_CFG->iface_list, NODE this_ipatt);
|
||||
init_list(&this_ipatt->ipn_list);
|
||||
BABEL_IFACE->port = BABEL_PORT;
|
||||
BABEL_IFACE->type = BABEL_IFACE_TYPE_WIRED;
|
||||
BABEL_IFACE->tx_tos = IP_PREC_INTERNET_CONTROL;
|
||||
BABEL_IFACE->tx_priority = sk_priority_control;
|
||||
BABEL_IFACE->check_link = 1;
|
||||
};
|
||||
|
||||
|
||||
babel_iface_finish:
|
||||
{
|
||||
if (BABEL_IFACE->type == BABEL_IFACE_TYPE_WIRELESS)
|
||||
{
|
||||
if (!BABEL_IFACE->hello_interval)
|
||||
BABEL_IFACE->hello_interval = BABEL_HELLO_INTERVAL_WIRELESS;
|
||||
if (!BABEL_IFACE->rxcost)
|
||||
BABEL_IFACE->rxcost = BABEL_RXCOST_WIRELESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!BABEL_IFACE->hello_interval)
|
||||
BABEL_IFACE->hello_interval = BABEL_HELLO_INTERVAL_WIRED;
|
||||
if (!BABEL_IFACE->rxcost)
|
||||
BABEL_IFACE->rxcost = BABEL_RXCOST_WIRED;
|
||||
}
|
||||
|
||||
if (!BABEL_IFACE->update_interval)
|
||||
BABEL_IFACE->update_interval = BABEL_IFACE->hello_interval*BABEL_UPDATE_INTERVAL_FACTOR;
|
||||
BABEL_IFACE->ihu_interval = BABEL_IFACE->hello_interval*BABEL_IHU_INTERVAL_FACTOR;
|
||||
};
|
||||
|
||||
|
||||
babel_iface_item:
|
||||
| PORT expr { BABEL_IFACE->port = $2; if (($2<1) || ($2>65535)) cf_error("Invalid port number"); }
|
||||
| RXCOST expr { BABEL_IFACE->rxcost = $2; if (($2<1) || ($2>65535)) cf_error("Invalid rxcost"); }
|
||||
| HELLO INTERVAL expr { BABEL_IFACE->hello_interval = $3; if (($3<1) || ($3>65535)) cf_error("Invalid hello interval"); }
|
||||
| UPDATE INTERVAL expr { BABEL_IFACE->update_interval = $3; if (($3<1) || ($3>65535)) cf_error("Invalid hello interval"); }
|
||||
| TYPE WIRED { BABEL_IFACE->type = BABEL_IFACE_TYPE_WIRED; }
|
||||
| TYPE WIRELESS { BABEL_IFACE->type = BABEL_IFACE_TYPE_WIRELESS; }
|
||||
| RX BUFFER expr { BABEL_IFACE->rx_buffer = $3; if (($3<256) || ($3>65535)) cf_error("RX buffer must be in range 256-65535"); }
|
||||
| TX LENGTH expr { BABEL_IFACE->tx_length = $3; if (($3<256) || ($3>65535)) cf_error("TX length must be in range 256-65535"); }
|
||||
| TX tos { BABEL_IFACE->tx_tos = $2; }
|
||||
| TX PRIORITY expr { BABEL_IFACE->tx_priority = $3; }
|
||||
| CHECK LINK bool { BABEL_IFACE->check_link = $3; }
|
||||
;
|
||||
|
||||
babel_iface_opts:
|
||||
/* empty */
|
||||
| babel_iface_opts babel_iface_item ';'
|
||||
;
|
||||
|
||||
babel_iface_opt_list:
|
||||
/* empty */
|
||||
| '{' babel_iface_opts '}'
|
||||
;
|
||||
|
||||
|
||||
babel_iface:
|
||||
babel_iface_start iface_patt_list_nopx babel_iface_opt_list babel_iface_finish;
|
||||
|
||||
CF_ADDTO(dynamic_attr, BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_BABEL_METRIC); })
|
||||
|
||||
CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]);
|
||||
|
||||
CF_CLI(SHOW BABEL INTERFACES, optsym opttext, [<name>] [\"<interface>\"], [[Show information about Babel interfaces]])
|
||||
{ babel_show_interfaces(proto_get_named($4, &proto_babel), $5); };
|
||||
|
||||
CF_CLI(SHOW BABEL NEIGHBORS, optsym opttext, [<name>] [\"<interface>\"], [[Show information about Babel neighbors]])
|
||||
{ babel_show_neighbors(proto_get_named($4, &proto_babel), $5); };
|
||||
|
||||
CF_CLI(SHOW BABEL ENTRIES, optsym opttext, [<name>], [[Show information about Babel prefix entries]])
|
||||
{ babel_show_entries(proto_get_named($4, &proto_babel)); };
|
||||
|
||||
CF_CODE
|
||||
|
||||
CF_END
|
1093
proto/babel/packets.c
Normal file
1093
proto/babel/packets.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -121,7 +121,8 @@ bgp_open(struct bgp_proto *p)
|
|||
bgp_counter++;
|
||||
|
||||
if (p->cf->password)
|
||||
if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password) < 0)
|
||||
if (sk_set_md5_auth(bgp_listen_sk, p->cf->source_addr, p->cf->remote_ip,
|
||||
p->cf->iface, p->cf->password, p->cf->setkey) < 0)
|
||||
{
|
||||
sk_log_error(bgp_listen_sk, p->p.name);
|
||||
bgp_close(p, 0);
|
||||
|
@ -191,7 +192,8 @@ bgp_close(struct bgp_proto *p, int apply_md5)
|
|||
bgp_counter--;
|
||||
|
||||
if (p->cf->password && apply_md5)
|
||||
if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL) < 0)
|
||||
if (sk_set_md5_auth(bgp_listen_sk, p->cf->source_addr, p->cf->remote_ip,
|
||||
p->cf->iface, NULL, p->cf->setkey) < 0)
|
||||
sk_log_error(bgp_listen_sk, p->p.name);
|
||||
|
||||
if (!bgp_counter)
|
||||
|
|
|
@ -51,6 +51,7 @@ struct bgp_config {
|
|||
int add_path; /* Use ADD-PATH extension [draft] */
|
||||
int allow_local_as; /* Allow that number of local ASNs in incoming AS_PATHs */
|
||||
int gr_mode; /* Graceful restart mode (BGP_GR_*) */
|
||||
int setkey; /* Set MD5 password to system SA/SP database */
|
||||
unsigned gr_time; /* Graceful restart timeout */
|
||||
unsigned connect_delay_time; /* Minimum delay between connect attempts */
|
||||
unsigned connect_retry_time; /* Timeout for connect attempts */
|
||||
|
|
|
@ -27,7 +27,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
|
|||
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
|
||||
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
|
||||
SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
|
||||
CHECK, LINK, PORT, EXTENDED, MESSAGES)
|
||||
CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY)
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
|
@ -54,6 +54,7 @@ bgp_proto_start: proto_start BGP {
|
|||
BGP_CFG->default_local_pref = 100;
|
||||
BGP_CFG->gr_mode = BGP_GR_AWARE;
|
||||
BGP_CFG->gr_time = 120;
|
||||
BGP_CFG->setkey = 1;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -112,6 +113,7 @@ bgp_proto:
|
|||
| 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 SETKEY bool ';' { BGP_CFG->setkey = $3; }
|
||||
| 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; }
|
||||
|
|
|
@ -192,6 +192,7 @@ ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
|
|||
|
||||
/**
|
||||
* ospf_send_dbdes - transmit database description packet
|
||||
* @p: OSPF protocol instance
|
||||
* @n: neighbor
|
||||
*
|
||||
* Sending of a database description packet is described in 10.8 of RFC 2328.
|
||||
|
|
|
@ -552,12 +552,13 @@ lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
|
|||
/**
|
||||
* lsa_validate - check whether given LSA is valid
|
||||
* @lsa: LSA header
|
||||
* @lsa_type: internal LSA type (%LSA_T_xxx)
|
||||
* @ospf2: %true for OSPFv2, %false for OSPFv3
|
||||
* @body: pointer to LSA body
|
||||
*
|
||||
* Checks internal structure of given LSA body (minimal length,
|
||||
* consistency). Returns true if valid.
|
||||
*/
|
||||
|
||||
int
|
||||
lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body)
|
||||
{
|
||||
|
|
|
@ -207,7 +207,7 @@ drop:
|
|||
/**
|
||||
* ospf_rx_hook
|
||||
* @sk: socket we received the packet.
|
||||
* @size: size of the packet
|
||||
* @len: length of the packet
|
||||
*
|
||||
* This is the entry point for messages from neighbors. Many checks (like
|
||||
* authentication, checksums, size) are done before the packet is passed to
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#undef CONFIG_BGP
|
||||
#undef CONFIG_OSPF
|
||||
#undef CONFIG_PIPE
|
||||
#undef CONFIG_BABEL
|
||||
|
||||
/* We use multithreading */
|
||||
#undef USE_PTHREADS
|
||||
|
|
170
sysdep/bsd/setkey.h
Normal file
170
sysdep/bsd/setkey.h
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* BIRD -- Manipulation the IPsec SA/SP database using setkey(8) utility
|
||||
*
|
||||
* (c) 2016 CZ.NIC z.s.p.o.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/pfkeyv2.h>
|
||||
#include <netipsec/ipsec.h>
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "lib/unix.h"
|
||||
|
||||
|
||||
/*
|
||||
* Open a socket for manage the IPsec SA/SP database entries
|
||||
*/
|
||||
static int
|
||||
setkey_open_socket(void)
|
||||
{
|
||||
int s = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
|
||||
if (s < 0)
|
||||
{
|
||||
log(L_ERR "SETKEY: socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static int
|
||||
setkey_send(struct sadb_msg *msg, uint len)
|
||||
{
|
||||
int s = setkey_open_socket();
|
||||
if (s < 0)
|
||||
return -1;
|
||||
|
||||
if (msg->sadb_msg_type == SADB_ADD)
|
||||
{
|
||||
/* Delete possible current key in the IPsec SA/SP database */
|
||||
msg->sadb_msg_type = SADB_DELETE;
|
||||
send(s, msg, len, 0);
|
||||
msg->sadb_msg_type = SADB_ADD;
|
||||
}
|
||||
|
||||
if (send(s, msg, len, 0) < 0)
|
||||
{
|
||||
log(L_ERR "SETKEY: send: %m");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform setkey(8)-like operation for set the password for TCP MD5 Signature.
|
||||
* Could be called with SABD_ADD or SADB_DELETE argument. Note that SADB_ADD
|
||||
* argument is internally processed as a pair of SADB_ADD and SADB_DELETE
|
||||
* operations to implement replace.
|
||||
*/
|
||||
static int
|
||||
setkey_md5(sockaddr *src, sockaddr *dst, char *passwd, uint type)
|
||||
{
|
||||
uint passwd_len = passwd ? strlen(passwd) : 0;
|
||||
|
||||
uint total =
|
||||
sizeof(struct sadb_msg) +
|
||||
sizeof(struct sadb_key) + PFKEY_ALIGN8(passwd_len) +
|
||||
sizeof(struct sadb_sa) +
|
||||
sizeof(struct sadb_x_sa2) +
|
||||
sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa.sa_len) +
|
||||
sizeof(struct sadb_address) + PFKEY_ALIGN8(dst->sa.sa_len);
|
||||
|
||||
char *buf = alloca(total);
|
||||
char *pos = buf;
|
||||
uint len;
|
||||
|
||||
memset(buf, 0, total);
|
||||
|
||||
struct sadb_msg *msg = (void *) pos;
|
||||
len = sizeof(struct sadb_msg);
|
||||
msg->sadb_msg_version = PF_KEY_V2;
|
||||
msg->sadb_msg_type = type;
|
||||
msg->sadb_msg_satype = SADB_X_SATYPE_TCPSIGNATURE;
|
||||
msg->sadb_msg_len = 0; /* Fix it later */
|
||||
msg->sadb_msg_pid = getpid();
|
||||
pos += len;
|
||||
|
||||
/* Set authentication algorithm and password */
|
||||
struct sadb_key *key = (void *) pos;
|
||||
len = sizeof(struct sadb_key) + PFKEY_ALIGN8(passwd_len);
|
||||
key->sadb_key_len = PFKEY_UNIT64(len);
|
||||
key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
|
||||
key->sadb_key_bits = passwd_len * 8;
|
||||
memcpy(pos + sizeof(struct sadb_key), passwd, passwd_len);
|
||||
pos += len;
|
||||
|
||||
struct sadb_sa *sa = (void *) pos;
|
||||
len = sizeof(struct sadb_sa);
|
||||
sa->sadb_sa_len = PFKEY_UNIT64(len);
|
||||
sa->sadb_sa_exttype = SADB_EXT_SA;
|
||||
sa->sadb_sa_spi = htonl((u32) TCP_SIG_SPI);
|
||||
sa->sadb_sa_auth = SADB_X_AALG_TCP_MD5;
|
||||
sa->sadb_sa_encrypt = SADB_EALG_NONE;
|
||||
sa->sadb_sa_flags = SADB_X_EXT_CYCSEQ;
|
||||
pos += len;
|
||||
|
||||
struct sadb_x_sa2 *sa2 = (void *) pos;
|
||||
len = sizeof(struct sadb_x_sa2);
|
||||
sa2->sadb_x_sa2_len = PFKEY_UNIT64(len);
|
||||
sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
|
||||
sa2->sadb_x_sa2_mode = IPSEC_MODE_ANY;
|
||||
pos += len;
|
||||
|
||||
/* Set source address */
|
||||
struct sadb_address *saddr = (void *) pos;
|
||||
len = sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa.sa_len);
|
||||
saddr->sadb_address_len = PFKEY_UNIT64(len);
|
||||
saddr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
|
||||
saddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
|
||||
saddr->sadb_address_prefixlen = MAX_PREFIX_LENGTH;
|
||||
memcpy(pos + sizeof(struct sadb_address), &src->sa, src->sa.sa_len);
|
||||
pos += len;
|
||||
|
||||
/* Set destination address */
|
||||
struct sadb_address *daddr = (void *) pos;
|
||||
len = sizeof(struct sadb_address) + PFKEY_ALIGN8(dst->sa.sa_len);
|
||||
daddr->sadb_address_len = PFKEY_UNIT64(len);
|
||||
daddr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
|
||||
daddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
|
||||
daddr->sadb_address_prefixlen = MAX_PREFIX_LENGTH;
|
||||
memcpy(pos + sizeof(struct sadb_address), &dst->sa, dst->sa.sa_len);
|
||||
pos += len;
|
||||
|
||||
len = pos - buf;
|
||||
msg->sadb_msg_len = PFKEY_UNIT64(len);
|
||||
|
||||
return setkey_send(msg, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Manipulation with the IPsec SA/SP database
|
||||
*/
|
||||
static int
|
||||
sk_set_md5_in_sasp_db(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd)
|
||||
{
|
||||
sockaddr src, dst;
|
||||
sockaddr_fill(&src, s->af, local, ifa, 0);
|
||||
sockaddr_fill(&dst, s->af, remote, ifa, 0);
|
||||
|
||||
if (passwd && *passwd)
|
||||
{
|
||||
int len = strlen(passwd);
|
||||
if (len > TCP_KEYLEN_MAX)
|
||||
ERR_MSG("The password for TCP MD5 Signature is too long");
|
||||
|
||||
if (setkey_md5(&src, &dst, passwd, SADB_ADD) < 0)
|
||||
ERR_MSG("Cannot add TCP-MD5 password into the IPsec SA/SP database");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (setkey_md5(&src, &dst, NULL, SADB_DELETE) < 0)
|
||||
ERR_MSG("Cannot delete TCP-MD5 password from the IPsec SA/SP database");
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -189,30 +189,26 @@ sk_prepare_ip_header(sock *s, void *hdr, int dlen)
|
|||
#ifndef TCP_KEYLEN_MAX
|
||||
#define TCP_KEYLEN_MAX 80
|
||||
#endif
|
||||
|
||||
#ifndef TCP_SIG_SPI
|
||||
#define TCP_SIG_SPI 0x1000
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FIXME: Passwords has to be set by setkey(8) command. This is the same
|
||||
* behaviour like Quagga. We need to add code for SA/SP entries
|
||||
* management.
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
#define USE_MD5SIG_SETKEY
|
||||
#include "lib/setkey.h"
|
||||
#endif
|
||||
|
||||
int
|
||||
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
|
||||
sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd, int setkey UNUSED)
|
||||
{
|
||||
int enable = 0;
|
||||
|
||||
if (passwd && *passwd)
|
||||
{
|
||||
int len = strlen(passwd);
|
||||
enable = TCP_SIG_SPI;
|
||||
|
||||
if (len > TCP_KEYLEN_MAX)
|
||||
ERR_MSG("MD5 password too long");
|
||||
}
|
||||
#ifdef USE_MD5SIG_SETKEY
|
||||
if (setkey)
|
||||
if (sk_set_md5_in_sasp_db(s, local, remote, ifa, passwd) < 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
int enable = (passwd && *passwd) ? TCP_SIG_SPI : 0;
|
||||
if (setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable)) < 0)
|
||||
{
|
||||
if (errno == ENOPROTOOPT)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#define _BIRD_CONFIG_H_
|
||||
|
||||
/* BIRD version */
|
||||
#define BIRD_VERSION "1.5.0"
|
||||
#define BIRD_VERSION "1.6.0"
|
||||
|
||||
/* Include parameters determined by configure script */
|
||||
#include "sysdep/autoconf.h"
|
||||
|
|
|
@ -126,7 +126,12 @@ nl_get_reply(struct nl_sock *nl)
|
|||
{
|
||||
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 };
|
||||
struct msghdr m = {
|
||||
.msg_name = &sa,
|
||||
.msg_namelen = sizeof(sa),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
int x = recvmsg(nl->fd, &m, 0);
|
||||
if (x < 0)
|
||||
die("nl_get_reply: %m");
|
||||
|
@ -1343,7 +1348,12 @@ 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 msghdr m = {
|
||||
.msg_name = &sa,
|
||||
.msg_namelen = sizeof(sa),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
struct nlmsghdr *h;
|
||||
int x;
|
||||
uint len;
|
||||
|
|
|
@ -179,19 +179,19 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||
*/
|
||||
|
||||
int
|
||||
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
|
||||
sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, struct iface *ifa, char *passwd, int setkey UNUSED)
|
||||
{
|
||||
struct tcp_md5sig md5;
|
||||
|
||||
memset(&md5, 0, sizeof(md5));
|
||||
sockaddr_fill((sockaddr *) &md5.tcpm_addr, fam_to_af[s->fam], a, ifa, 0);
|
||||
sockaddr_fill((sockaddr *) &md5.tcpm_addr, fam_to_af[s->fam], remote, ifa, 0);
|
||||
|
||||
if (passwd)
|
||||
{
|
||||
int len = strlen(passwd);
|
||||
|
||||
if (len > TCP_MD5SIG_MAXKEYLEN)
|
||||
ERR_MSG("MD5 password too long");
|
||||
ERR_MSG("The password for TCP MD5 Signature is too long");
|
||||
|
||||
md5.tcpm_keylen = len;
|
||||
memcpy(&md5.tcpm_key, passwd, len);
|
||||
|
|
|
@ -448,6 +448,7 @@ tm_format_reltime(char *x, struct tm *tm, bird_clock_t delta)
|
|||
/**
|
||||
* tm_format_datetime - convert date and time to textual representation
|
||||
* @x: destination buffer of size %TM_DATETIME_BUFFER_SIZE
|
||||
* @fmt_spec: specification of resulting textual representation of the time
|
||||
* @t: time
|
||||
*
|
||||
* This function formats the given relative time value @t to a textual
|
||||
|
@ -952,23 +953,32 @@ sk_set_min_ttl(sock *s, int ttl)
|
|||
/**
|
||||
* sk_set_md5_auth - add / remove MD5 security association for given socket
|
||||
* @s: socket
|
||||
* @a: IP address of the other side
|
||||
* @local: IP address of local side
|
||||
* @remote: IP address of remote side
|
||||
* @ifa: Interface for link-local IP address
|
||||
* @passwd: password used for MD5 authentication
|
||||
* @passwd: Password used for MD5 authentication
|
||||
* @setkey: Update also system SA/SP database
|
||||
*
|
||||
* In TCP MD5 handling code in kernel, there is a set of pairs (address,
|
||||
* password) used to choose password according to address of the other side.
|
||||
* This function is useful for listening socket, for active sockets it is enough
|
||||
* to set s->password field.
|
||||
* In TCP MD5 handling code in kernel, there is a set of security associations
|
||||
* used for choosing password and other authentication parameters according to
|
||||
* the local and remote address. This function is useful for listening socket,
|
||||
* for active sockets it may be enough to set s->password field.
|
||||
*
|
||||
* When called with passwd != NULL, the new pair is added,
|
||||
* When called with passwd == NULL, the existing pair is removed.
|
||||
*
|
||||
* Note that while in Linux, the MD5 SAs are specific to socket, in BSD they are
|
||||
* stored in global SA/SP database (but the behavior also must be enabled on
|
||||
* per-socket basis). In case of multiple sockets to the same neighbor, the
|
||||
* socket-specific state must be configured for each socket while global state
|
||||
* just once per src-dst pair. The @setkey argument controls whether the global
|
||||
* state (SA/SP database) is also updated.
|
||||
*
|
||||
* Result: 0 for success, -1 for an error.
|
||||
*/
|
||||
|
||||
int
|
||||
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
|
||||
sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd, int setkey)
|
||||
{ DUMMY; }
|
||||
#endif
|
||||
|
||||
|
@ -1436,7 +1446,7 @@ sk_open(sock *s)
|
|||
}
|
||||
|
||||
if (s->password)
|
||||
if (sk_set_md5_auth(s, s->daddr, s->iface, s->password) < 0)
|
||||
if (sk_set_md5_auth(s, s->saddr, s->daddr, s->iface, s->password, 0) < 0)
|
||||
goto err;
|
||||
|
||||
switch (s->type)
|
||||
|
|
|
@ -89,6 +89,7 @@ static char *class_names[] = {
|
|||
/**
|
||||
* log_commit - commit a log message
|
||||
* @class: message class information (%L_DEBUG to %L_BUG, see |lib/birdlib.h|)
|
||||
* @buf: message to write
|
||||
*
|
||||
* This function writes a message prepared in the log buffer to the
|
||||
* log file (as specified in the configuration). The log buffer is
|
||||
|
|
|
@ -621,7 +621,7 @@ signal_init(void)
|
|||
* Parsing of command-line arguments
|
||||
*/
|
||||
|
||||
static char *opt_list = "c:dD:ps:P:u:g:fR";
|
||||
static char *opt_list = "c:dD:ps:P:u:g:flR";
|
||||
static int parse_and_exit;
|
||||
char *bird_name;
|
||||
static char *use_user;
|
||||
|
@ -631,7 +631,7 @@ static int run_in_foreground = 0;
|
|||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-P <pid-file>] [-u <user>] [-g <group>] [-f] [-R]\n", bird_name);
|
||||
fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-P <pid-file>] [-u <user>] [-g <group>] [-f] [-l] [-R]\n", bird_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -698,6 +698,8 @@ get_gid(const char *s)
|
|||
static void
|
||||
parse_args(int argc, char **argv)
|
||||
{
|
||||
int config_changed = 0;
|
||||
int socket_changed = 0;
|
||||
int c;
|
||||
|
||||
bird_name = get_bird_name(argv[0], "bird");
|
||||
|
@ -716,6 +718,7 @@ parse_args(int argc, char **argv)
|
|||
{
|
||||
case 'c':
|
||||
config_name = optarg;
|
||||
config_changed = 1;
|
||||
break;
|
||||
case 'd':
|
||||
debug_flag |= 1;
|
||||
|
@ -729,6 +732,7 @@ parse_args(int argc, char **argv)
|
|||
break;
|
||||
case 's':
|
||||
path_control_socket = optarg;
|
||||
socket_changed = 1;
|
||||
break;
|
||||
case 'P':
|
||||
pid_file = optarg;
|
||||
|
@ -742,6 +746,12 @@ parse_args(int argc, char **argv)
|
|||
case 'f':
|
||||
run_in_foreground = 1;
|
||||
break;
|
||||
case 'l':
|
||||
if (!config_changed)
|
||||
config_name = xbasename(config_name);
|
||||
if (!socket_changed)
|
||||
path_control_socket = xbasename(path_control_socket);
|
||||
break;
|
||||
case 'R':
|
||||
graceful_restart_recovery();
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue