Merge branch 'master' into add-path
This commit is contained in:
commit
283c7dfada
21 changed files with 169 additions and 109 deletions
15
NEWS
15
NEWS
|
@ -1,12 +1,23 @@
|
||||||
Version 1.3.12 (2013-11-23)
|
Version 1.4.0 (2013-11-25)
|
||||||
o BFD protocol (RFC 5880).
|
o BFD protocol (RFC 5880).
|
||||||
o BFD support for OSPF and BGP.
|
o BFD support for OSPF and BGP.
|
||||||
o New 'allow local as' option for BGP.
|
o New 'allow local as' option for BGP.
|
||||||
o Filters allows setting gw, ifname and ifindex.
|
o Filters allows setting gw, ifname and ifindex.
|
||||||
o Filter operator 'delete/filter' extended to bgp_paths.
|
o Filter operator 'delete/filter' extended to bgp_paths.
|
||||||
o Filter operator 'len' extended to [e]clists.
|
o Filter operator 'len' extended to [e]clists.
|
||||||
o PID file support.
|
o BIRD client now allows shorthands for noninteractive commands.
|
||||||
|
o Flag -P for PID file support.
|
||||||
|
o Flag -f added to force BIRD to run in foreground.
|
||||||
|
o Protocol export/import/receive limits are checked during reconfiguration.
|
||||||
o Several bugfixes and minor improvements.
|
o Several bugfixes and minor improvements.
|
||||||
|
o Several minor but incompatible changes:
|
||||||
|
- IBGP is multihop by default.
|
||||||
|
- Changes primary address selection on BSD to the first one.
|
||||||
|
- Integers in filters are handled as unsigned.
|
||||||
|
- ISO 8601 time formats used by default.
|
||||||
|
- Import of device routes from kernel protocol allowed.
|
||||||
|
- Last state change now tracks just protocol state change.
|
||||||
|
- Minor changes to default router ID calculation.
|
||||||
|
|
||||||
Version 1.3.11 (2013-07-27)
|
Version 1.3.11 (2013-07-27)
|
||||||
o OSPF stub router option (RFC 3137).
|
o OSPF stub router option (RFC 3137).
|
||||||
|
|
|
@ -137,6 +137,21 @@ submit_server_command(char *cmd)
|
||||||
server_send(cmd);
|
server_send(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
submit_init_command(char *cmd_raw)
|
||||||
|
{
|
||||||
|
char *cmd = cmd_expand(cmd_raw);
|
||||||
|
|
||||||
|
if (!cmd)
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
submit_server_command(cmd);
|
||||||
|
free(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
submit_command(char *cmd_raw)
|
submit_command(char *cmd_raw)
|
||||||
{
|
{
|
||||||
|
@ -165,7 +180,7 @@ init_commands(void)
|
||||||
{
|
{
|
||||||
/* First transition - client received hello from BIRD
|
/* First transition - client received hello from BIRD
|
||||||
and there is waiting initial command */
|
and there is waiting initial command */
|
||||||
submit_server_command(init_cmd);
|
submit_init_command(init_cmd);
|
||||||
init_cmd = NULL;
|
init_cmd = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,8 @@ config_alloc(byte *name)
|
||||||
cfg_mem = c->mem = l;
|
cfg_mem = c->mem = l;
|
||||||
c->file_name = cfg_strdup(name);
|
c->file_name = cfg_strdup(name);
|
||||||
c->load_time = now;
|
c->load_time = now;
|
||||||
c->tf_base.fmt1 = c->tf_log.fmt1 = "%d-%m-%Y %T";
|
c->tf_route = c->tf_proto = (struct timeformat){"%T", "%F", 20*3600};
|
||||||
|
c->tf_base = c->tf_log = (struct timeformat){"%F %T", NULL, 0};
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,10 @@ which allows you to talk with BIRD in an extensive way.
|
||||||
<p>In the config, everything on a line after <cf/#/ or inside <cf>/*
|
<p>In the config, everything on a line after <cf/#/ or inside <cf>/*
|
||||||
*/</cf> is a comment, whitespace characters are treated as a single space. If there's a variable number of options, they are grouped using
|
*/</cf> is 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
|
the <cf/{ }/ brackets. Each option is terminated by a <cf/;/. Configuration
|
||||||
is case sensitive.
|
is case sensitive. There are two ways how to name symbols (like protocol names, filter names, constats 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 of numbers, letters. hyphens, dots and colons
|
||||||
|
(e.g. "'1:strange-name'", "'-NAME-'", "'cool::name'").
|
||||||
|
|
||||||
<p>Here is an example of a simple config file. It enables
|
<p>Here is an example of a simple config file. It enables
|
||||||
synchronization of routing tables with OS kernel, scans for
|
synchronization of routing tables with OS kernel, scans for
|
||||||
|
@ -377,7 +380,7 @@ protocol rip {
|
||||||
"<m/format1/" is a format string using <it/strftime(3)/
|
"<m/format1/" is a format string using <it/strftime(3)/
|
||||||
notation (see <it/man strftime/ for details). <m/limit> and
|
notation (see <it/man strftime/ for details). <m/limit> and
|
||||||
"<m/format2/" allow to specify the second format string for
|
"<m/format2/" allow to specify the second format string for
|
||||||
times in past deeper than <m/limit/ seconds. There are two
|
times in past deeper than <m/limit/ seconds. There are few
|
||||||
shorthands: <cf/iso long/ is a ISO 8601 date/time format
|
shorthands: <cf/iso long/ is a ISO 8601 date/time format
|
||||||
(YYYY-MM-DD hh:mm:ss) that can be also specified using <cf/"%F
|
(YYYY-MM-DD hh:mm:ss) that can be also specified using <cf/"%F
|
||||||
%T"/. <cf/iso short/ is a variant of ISO 8601 that uses just
|
%T"/. <cf/iso short/ is a variant of ISO 8601 that uses just
|
||||||
|
@ -385,11 +388,15 @@ protocol rip {
|
||||||
the past) and the date format (YYYY-MM-DD) for far times. This
|
the past) and the date format (YYYY-MM-DD) for far times. This
|
||||||
is a shorthand for <cf/"%T" 72000 "%F"/.
|
is a shorthand for <cf/"%T" 72000 "%F"/.
|
||||||
|
|
||||||
By default, BIRD uses an short, ad-hoc format for <cf/route/
|
By default, BIRD uses the <cf/iso short/ format for <cf/route/ and
|
||||||
and <cf/protocol/ times, and a <cf/iso long/ similar format
|
<cf/protocol/ times, and the <cf/iso long/ format for <cf/base/ and
|
||||||
(DD-MM-YYYY hh:mm:ss) for <cf/base/ and <cf/log/. These
|
<cf/log/ times.
|
||||||
defaults are here for a compatibility with older versions
|
|
||||||
and might change in the future.
|
In pre-1.4.0 versions, BIRD used an short, ad-hoc format for
|
||||||
|
<cf/route/ and <cf/protocol/ times, and a <cf/iso long/ similar format
|
||||||
|
(DD-MM-YYYY hh:mm:ss) for <cf/base/ and <cf/log/. These timeformats
|
||||||
|
could be set by <cf/old short/ and <cf/old long/ compatibility
|
||||||
|
shorthands.
|
||||||
|
|
||||||
<tag>table <m/name/ [sorted]</tag>
|
<tag>table <m/name/ [sorted]</tag>
|
||||||
Create a new routing table. The default routing table is
|
Create a new routing table. The default routing table is
|
||||||
|
@ -922,9 +929,10 @@ incompatible with each other (that is to prevent you from shooting in the foot).
|
||||||
<cf/true/ and <cf/false/. Boolean is the only type you can use in
|
<cf/true/ and <cf/false/. Boolean is the only type you can use in
|
||||||
<cf/if/ statements.
|
<cf/if/ statements.
|
||||||
|
|
||||||
<tag/int/ This is a general integer type, you can expect it to store
|
<tag/int/ This is a general integer type. It is an unsigned 32bit type;
|
||||||
signed values from -2000000000 to +2000000000. Overflows are not
|
i.e., you can expect it to store values from 0 to 4294967295.
|
||||||
checked. You can use <cf/0x1234/ syntax to write hexadecimal values.
|
Overflows are not checked. You can use <cf/0x1234/ syntax to write
|
||||||
|
hexadecimal values.
|
||||||
|
|
||||||
<tag/pair/ This is a pair of two short integers. Each component can have
|
<tag/pair/ This is a pair of two short integers. Each component can have
|
||||||
values from 0 to 65535. Literals of this type are written as
|
values from 0 to 65535. Literals of this type are written as
|
||||||
|
@ -1532,33 +1540,37 @@ This allows to set routing policy and all the other parameters differently
|
||||||
for each neighbor using the following configuration parameters:
|
for each neighbor using the following configuration parameters:
|
||||||
|
|
||||||
<descrip>
|
<descrip>
|
||||||
<tag>local [<m/ip/] as <m/number/</tag> Define which AS we
|
<tag>local [<m/ip/] as <m/number/</tag> Define which AS we are part
|
||||||
are part of. (Note that contrary to other IP routers, BIRD is
|
of. (Note that contrary to other IP routers, BIRD is able to act as a
|
||||||
able to act as a router located in multiple AS'es
|
router located in multiple AS'es simultaneously, but in such cases you
|
||||||
simultaneously, but in such cases you need to tweak the BGP
|
need to tweak the BGP paths manually in the filters to get consistent
|
||||||
paths manually in the filters to get consistent behavior.)
|
behavior.) Optional <cf/ip/ argument specifies a source address,
|
||||||
Optional <cf/ip/ argument specifies a source address,
|
equivalent to the <cf/source address/ option (see below). This
|
||||||
equivalent to the <cf/source address/ option (see below).
|
parameter is mandatory.
|
||||||
|
|
||||||
|
<tag>neighbor <m/ip/ as <m/number/</tag> Define neighboring router this
|
||||||
|
instance will be talking to and what AS it's located in. In case the
|
||||||
|
neighbor is in the same AS as we are, we automatically switch to iBGP.
|
||||||
This parameter is mandatory.
|
This parameter is mandatory.
|
||||||
|
|
||||||
<tag>neighbor <m/ip/ as <m/number/</tag> Define neighboring router
|
<tag>direct</tag> Specify that the neighbor is directly connected. The
|
||||||
this instance will be talking to and what AS it's located in. Unless
|
IP address of the neighbor must be from a directly reachable IP range
|
||||||
you use the <cf/multihop/ clause, it must be directly connected to one
|
(i.e. associated with one of your router's interfaces), otherwise the
|
||||||
of your router's interfaces. In case the neighbor is in the same AS
|
BGP session wouldn't start but it would wait for such interface to
|
||||||
as we are, we automatically switch to iBGP. This parameter is mandatory.
|
appear. The alternative is the <cf/multihop/ option. Default: enabled
|
||||||
|
for eBGP.
|
||||||
|
|
||||||
<tag>multihop [<m/number/]</tag> Configure multihop BGP
|
<tag>multihop [<m/number/]</tag> Configure multihop BGP session to a
|
||||||
session to a neighbor that isn't directly connected.
|
neighbor that isn't directly connected. Accurately, this option should
|
||||||
Accurately, this option should be used if the configured
|
be used if the configured neighbor IP address does not match with any
|
||||||
neighbor IP address does not match with any local network
|
local network subnets. Such IP address have to be reachable through
|
||||||
subnets. Such IP address have to be reachable through system
|
system routing table. The alternative is the <cf/direct/ option. For
|
||||||
routing table. For multihop BGP it is recommended to
|
multihop BGP it is recommended to explicitly configure the source
|
||||||
explicitly configure <cf/source address/ to have it
|
address to have it stable. Optional <cf/number/ argument can be used to
|
||||||
stable. Optional <cf/number/ argument can be used to specify
|
specify the number of hops (used for TTL). Note that the number of
|
||||||
the number of hops (used for TTL). Note that the number of
|
networks (edges) in a path is counted; i.e., if two BGP speakers are
|
||||||
networks (edges) in a path is counted, i.e. if two BGP
|
separated by one router, the number of hops is 2. Default: enabled for
|
||||||
speakers are separated by one router, the number of hops is
|
iBGP.
|
||||||
2. Default: switched off.
|
|
||||||
|
|
||||||
<tag>source address <m/ip/</tag> Define local address we
|
<tag>source address <m/ip/</tag> Define local address we
|
||||||
should use for next hop calculation and as a source address
|
should use for next hop calculation and as a source address
|
||||||
|
@ -1605,8 +1617,8 @@ for each neighbor using the following configuration parameters:
|
||||||
table, and was used in older versions of BIRD, but does not
|
table, and was used in older versions of BIRD, but does not
|
||||||
handle well nontrivial iBGP setups and multihop. Recursive
|
handle well nontrivial iBGP setups and multihop. Recursive
|
||||||
mode is incompatible with <ref id="dsc-sorted" name="sorted
|
mode is incompatible with <ref id="dsc-sorted" name="sorted
|
||||||
tables">. Default: <cf/direct/ for singlehop eBGP,
|
tables">. Default: <cf/direct/ for direct sessions,
|
||||||
<cf/recursive/ otherwise.
|
<cf/recursive/ for multihop sessions.
|
||||||
|
|
||||||
<tag>igp table <m/name/</tag> Specifies a table that is used
|
<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
|
as an IGP routing table. Default: the same as the table BGP is
|
||||||
|
|
|
@ -53,6 +53,7 @@ Reply codes of BIRD command-line interface
|
||||||
1017 Show ospf lsadb
|
1017 Show ospf lsadb
|
||||||
1018 Show memory
|
1018 Show memory
|
||||||
1019 Show ROA list
|
1019 Show ROA list
|
||||||
|
1020 Show BFD sessions
|
||||||
|
|
||||||
8000 Reply too long
|
8000 Reply too long
|
||||||
8001 Route not found
|
8001 Route not found
|
||||||
|
|
|
@ -90,12 +90,6 @@ pm_format(struct f_path_mask *p, buffer *buf)
|
||||||
buffer_puts(buf, "=]");
|
buffer_puts(buf, "=]");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
|
||||||
int_cmp(int i1, int i2)
|
|
||||||
{
|
|
||||||
return (i1 > i2) - (i1 < i2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
uint_cmp(uint i1, uint i2)
|
uint_cmp(uint i1, uint i2)
|
||||||
{
|
{
|
||||||
|
@ -146,7 +140,6 @@ val_compare(struct f_val v1, struct f_val v2)
|
||||||
case T_ENUM:
|
case T_ENUM:
|
||||||
case T_INT:
|
case T_INT:
|
||||||
case T_BOOL:
|
case T_BOOL:
|
||||||
return int_cmp(v1.val.i, v2.val.i);
|
|
||||||
case T_PAIR:
|
case T_PAIR:
|
||||||
case T_QUAD:
|
case T_QUAD:
|
||||||
return uint_cmp(v1.val.i, v2.val.i);
|
return uint_cmp(v1.val.i, v2.val.i);
|
||||||
|
@ -157,7 +150,7 @@ val_compare(struct f_val v1, struct f_val v2)
|
||||||
case T_PREFIX:
|
case T_PREFIX:
|
||||||
if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
|
if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
|
||||||
return rc;
|
return rc;
|
||||||
return int_cmp(v1.val.px.len, v2.val.px.len);
|
return uint_cmp(v1.val.px.len, v2.val.px.len);
|
||||||
case T_STRING:
|
case T_STRING:
|
||||||
return strcmp(v1.val.s, v2.val.s);
|
return strcmp(v1.val.s, v2.val.s);
|
||||||
default:
|
default:
|
||||||
|
@ -442,16 +435,16 @@ val_format(struct f_val v, buffer *buf)
|
||||||
{
|
{
|
||||||
case T_VOID: buffer_puts(buf, "(void)"); return;
|
case T_VOID: buffer_puts(buf, "(void)"); return;
|
||||||
case T_BOOL: buffer_puts(buf, v.val.i ? "TRUE" : "FALSE"); return;
|
case T_BOOL: buffer_puts(buf, v.val.i ? "TRUE" : "FALSE"); return;
|
||||||
case T_INT: buffer_print(buf, "%d", v.val.i); return;
|
case T_INT: buffer_print(buf, "%u", v.val.i); return;
|
||||||
case T_STRING: buffer_print(buf, "%s", v.val.s); return;
|
case T_STRING: buffer_print(buf, "%s", v.val.s); return;
|
||||||
case T_IP: buffer_print(buf, "%I", v.val.px.ip); return;
|
case T_IP: buffer_print(buf, "%I", v.val.px.ip); return;
|
||||||
case T_PREFIX: buffer_print(buf, "%I/%d", v.val.px.ip, v.val.px.len); return;
|
case T_PREFIX: buffer_print(buf, "%I/%d", v.val.px.ip, v.val.px.len); return;
|
||||||
case T_PAIR: buffer_print(buf, "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff); return;
|
case T_PAIR: buffer_print(buf, "(%u,%u)", v.val.i >> 16, v.val.i & 0xffff); return;
|
||||||
case T_QUAD: buffer_print(buf, "%R", v.val.i); return;
|
case T_QUAD: buffer_print(buf, "%R", v.val.i); return;
|
||||||
case T_EC: ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return;
|
case T_EC: ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return;
|
||||||
case T_PREFIX_SET: trie_format(v.val.ti, buf); return;
|
case T_PREFIX_SET: trie_format(v.val.ti, buf); return;
|
||||||
case T_SET: tree_format(v.val.t, buf); return;
|
case T_SET: tree_format(v.val.t, buf); return;
|
||||||
case T_ENUM: buffer_print(buf, "(enum %x)%d", v.type, v.val.i); return;
|
case T_ENUM: buffer_print(buf, "(enum %x)%u", v.type, v.val.i); return;
|
||||||
case T_PATH: as_path_format(v.val.ad, buf2, 1000); buffer_print(buf, "(path %s)", buf2); return;
|
case T_PATH: as_path_format(v.val.ad, buf2, 1000); buffer_print(buf, "(path %s)", buf2); return;
|
||||||
case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); buffer_print(buf, "(clist %s)", buf2); return;
|
case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); buffer_print(buf, "(clist %s)", buf2); return;
|
||||||
case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(eclist %s)", buf2); return;
|
case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(eclist %s)", buf2); return;
|
||||||
|
@ -1167,14 +1160,14 @@ interpret(struct f_inst *what)
|
||||||
/* Community (or cluster) list */
|
/* Community (or cluster) list */
|
||||||
struct f_val dummy;
|
struct f_val dummy;
|
||||||
int arg_set = 0;
|
int arg_set = 0;
|
||||||
i = 0;
|
uint n = 0;
|
||||||
|
|
||||||
if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
|
if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
|
||||||
i = v2.val.i;
|
n = v2.val.i;
|
||||||
#ifndef IPV6
|
#ifndef IPV6
|
||||||
/* IP->Quad implicit conversion */
|
/* IP->Quad implicit conversion */
|
||||||
else if (v2.type == T_IP)
|
else if (v2.type == T_IP)
|
||||||
i = ipa_to_u32(v2.val.px.ip);
|
n = ipa_to_u32(v2.val.px.ip);
|
||||||
#endif
|
#endif
|
||||||
else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
|
else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
|
||||||
arg_set = 1;
|
arg_set = 1;
|
||||||
|
@ -1190,14 +1183,14 @@ interpret(struct f_inst *what)
|
||||||
if (arg_set == 1)
|
if (arg_set == 1)
|
||||||
runtime("Can't add set");
|
runtime("Can't add set");
|
||||||
else if (!arg_set)
|
else if (!arg_set)
|
||||||
res.val.ad = int_set_add(f_pool, v1.val.ad, i);
|
res.val.ad = int_set_add(f_pool, v1.val.ad, n);
|
||||||
else
|
else
|
||||||
res.val.ad = int_set_union(f_pool, v1.val.ad, v2.val.ad);
|
res.val.ad = int_set_union(f_pool, v1.val.ad, v2.val.ad);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
if (!arg_set)
|
if (!arg_set)
|
||||||
res.val.ad = int_set_del(f_pool, v1.val.ad, i);
|
res.val.ad = int_set_del(f_pool, v1.val.ad, n);
|
||||||
else
|
else
|
||||||
res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 0);
|
res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 0);
|
||||||
break;
|
break;
|
||||||
|
@ -1502,7 +1495,7 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
|
||||||
log( L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
|
log( L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
|
||||||
return F_ERROR;
|
return F_ERROR;
|
||||||
}
|
}
|
||||||
DBG( "done (%d)\n", res.val.i );
|
DBG( "done (%u)\n", res.val.i );
|
||||||
return res.val.i;
|
return res.val.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1519,7 +1512,7 @@ f_eval(struct f_inst *expr, struct linpool *tmp_pool)
|
||||||
return interpret(expr);
|
return interpret(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
uint
|
||||||
f_eval_int(struct f_inst *expr)
|
f_eval_int(struct f_inst *expr)
|
||||||
{
|
{
|
||||||
/* Called independently in parse-time to eval expressions */
|
/* Called independently in parse-time to eval expressions */
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct f_prefix {
|
||||||
struct f_val {
|
struct f_val {
|
||||||
int type;
|
int type;
|
||||||
union {
|
union {
|
||||||
int i;
|
uint i;
|
||||||
u64 ec;
|
u64 ec;
|
||||||
/* ip_addr ip; Folded into prefix */
|
/* ip_addr ip; Folded into prefix */
|
||||||
struct f_prefix px;
|
struct f_prefix px;
|
||||||
|
@ -108,7 +108,7 @@ struct rte;
|
||||||
|
|
||||||
int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags);
|
int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags);
|
||||||
struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
|
struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
|
||||||
int f_eval_int(struct f_inst *expr);
|
uint f_eval_int(struct f_inst *expr);
|
||||||
u32 f_eval_asn(struct f_inst *expr);
|
u32 f_eval_asn(struct f_inst *expr);
|
||||||
|
|
||||||
char *filter_name(struct filter *filter);
|
char *filter_name(struct filter *filter);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Summary: BIRD Internet Routing Daemon
|
Summary: BIRD Internet Routing Daemon
|
||||||
Name: bird
|
Name: bird
|
||||||
Version: 1.3.12
|
Version: 1.4.0
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: Networking/Daemons
|
Group: Networking/Daemons
|
||||||
|
|
12
nest/iface.c
12
nest/iface.c
|
@ -600,22 +600,10 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id)
|
||||||
if (a->scope <= SCOPE_LINK)
|
if (a->scope <= SCOPE_LINK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* FIXME: This should go away */
|
|
||||||
if (a->flags & IA_PEER)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* FIXME: This should go away too */
|
|
||||||
if (!mask && (a != i->addr))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Check pattern if specified */
|
/* Check pattern if specified */
|
||||||
if (mask && !iface_patt_match(mask, i, a))
|
if (mask && !iface_patt_match(mask, i, a))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* FIXME: This should go away too */
|
|
||||||
if ((i->flags & IF_IGNORE) && !mask)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* No pattern or pattern matched */
|
/* No pattern or pattern matched */
|
||||||
if (!b || ipa_to_u32(a->ip) < ipa_to_u32(b->ip))
|
if (!b || ipa_to_u32(a->ip) < ipa_to_u32(b->ip))
|
||||||
b = a;
|
b = a;
|
||||||
|
|
|
@ -48,7 +48,6 @@ static void
|
||||||
proto_enqueue(list *l, struct proto *p)
|
proto_enqueue(list *l, struct proto *p)
|
||||||
{
|
{
|
||||||
add_tail(l, &p->n);
|
add_tail(l, &p->n);
|
||||||
p->last_state_change = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -363,6 +362,8 @@ proto_init(struct proto_config *c)
|
||||||
|
|
||||||
q->proto_state = PS_DOWN;
|
q->proto_state = PS_DOWN;
|
||||||
q->core_state = FS_HUNGRY;
|
q->core_state = FS_HUNGRY;
|
||||||
|
q->last_state_change = now;
|
||||||
|
|
||||||
proto_enqueue(&initial_proto_list, q);
|
proto_enqueue(&initial_proto_list, q);
|
||||||
if (p == &proto_unix_iface)
|
if (p == &proto_unix_iface)
|
||||||
initial_device_proto = q;
|
initial_device_proto = q;
|
||||||
|
@ -1084,6 +1085,7 @@ proto_notify_state(struct proto *p, unsigned ps)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p->proto_state = ps;
|
p->proto_state = ps;
|
||||||
|
p->last_state_change = now;
|
||||||
|
|
||||||
switch (ps)
|
switch (ps)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1070,13 +1070,13 @@ bfd_show_sessions(struct proto *P)
|
||||||
|
|
||||||
if (p->p.proto_state != PS_UP)
|
if (p->p.proto_state != PS_UP)
|
||||||
{
|
{
|
||||||
cli_msg(-1013, "%s: is not up", p->p.name);
|
cli_msg(-1020, "%s: is not up", p->p.name);
|
||||||
cli_msg(0, "");
|
cli_msg(0, "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cli_msg(-1013, "%s:", p->p.name);
|
cli_msg(-1020, "%s:", p->p.name);
|
||||||
cli_msg(-1013, "%-25s %-10s %-10s %-10s %8s %8s",
|
cli_msg(-1020, "%-25s %-10s %-10s %-10s %8s %8s",
|
||||||
"IP address", "Interface", "State", "Since", "Interval", "Timeout");
|
"IP address", "Interface", "State", "Since", "Interval", "Timeout");
|
||||||
|
|
||||||
|
|
||||||
|
@ -1092,7 +1092,7 @@ bfd_show_sessions(struct proto *P)
|
||||||
state = (state < 4) ? state : 0;
|
state = (state < 4) ? state : 0;
|
||||||
tm_format_datetime(tbuf, &config->tf_proto, s->last_state_change);
|
tm_format_datetime(tbuf, &config->tf_proto, s->last_state_change);
|
||||||
|
|
||||||
cli_msg(-1013, "%-25I %-10s %-10s %-10s %3u.%03u %3u.%03u",
|
cli_msg(-1020, "%-25I %-10s %-10s %-10s %3u.%03u %3u.%03u",
|
||||||
s->addr, ifname, bfd_state_names[state], tbuf,
|
s->addr, ifname, bfd_state_names[state], tbuf,
|
||||||
tx_int / 1000, tx_int % 1000, timeout / 1000, timeout % 1000);
|
tx_int / 1000, tx_int % 1000, timeout / 1000, timeout % 1000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1009,6 +1009,24 @@ bgp_check_config(struct bgp_config *c)
|
||||||
if (c->c.class == SYM_TEMPLATE)
|
if (c->c.class == SYM_TEMPLATE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
/* EBGP direct by default, IBGP multihop by default */
|
||||||
|
if (c->multihop < 0)
|
||||||
|
c->multihop = internal ? 64 : 0;
|
||||||
|
|
||||||
|
/* Different default for gw_mode */
|
||||||
|
if (!c->gw_mode)
|
||||||
|
c->gw_mode = c->multihop ? GW_RECURSIVE : GW_DIRECT;
|
||||||
|
|
||||||
|
/* Different default based on rs_client */
|
||||||
|
if (!c->missing_lladdr)
|
||||||
|
c->missing_lladdr = c->rs_client ? MLL_IGNORE : MLL_SELF;
|
||||||
|
|
||||||
|
/* 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->local_as)
|
if (!c->local_as)
|
||||||
cf_error("Local AS number must be set");
|
cf_error("Local AS number must be set");
|
||||||
|
|
||||||
|
@ -1024,7 +1042,6 @@ bgp_check_config(struct bgp_config *c)
|
||||||
if (internal && c->rs_client)
|
if (internal && c->rs_client)
|
||||||
cf_error("Only external neighbor can be RS client");
|
cf_error("Only external neighbor can be RS client");
|
||||||
|
|
||||||
|
|
||||||
if (c->multihop && (c->gw_mode == GW_DIRECT))
|
if (c->multihop && (c->gw_mode == GW_DIRECT))
|
||||||
cf_error("Multihop BGP cannot use direct gateway mode");
|
cf_error("Multihop BGP cannot use direct gateway mode");
|
||||||
|
|
||||||
|
@ -1035,20 +1052,6 @@ bgp_check_config(struct bgp_config *c)
|
||||||
if (c->multihop && c->bfd && ipa_zero(c->source_addr))
|
if (c->multihop && c->bfd && ipa_zero(c->source_addr))
|
||||||
cf_error("Multihop BGP with BFD requires specified source address");
|
cf_error("Multihop BGP with BFD requires specified source address");
|
||||||
|
|
||||||
|
|
||||||
/* Different default based on rs_client */
|
|
||||||
if (!c->missing_lladdr)
|
|
||||||
c->missing_lladdr = c->rs_client ? MLL_IGNORE : MLL_SELF;
|
|
||||||
|
|
||||||
/* 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)
|
if ((c->gw_mode == GW_RECURSIVE) && c->c.table->sorted)
|
||||||
cf_error("BGP in recursive mode prohibits sorted table");
|
cf_error("BGP in recursive mode prohibits sorted table");
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ CF_ADDTO(proto, bgp_proto '}' { bgp_check_config(BGP_CFG); } )
|
||||||
|
|
||||||
bgp_proto_start: proto_start BGP {
|
bgp_proto_start: proto_start BGP {
|
||||||
this_proto = proto_config_new(&proto_bgp, sizeof(struct bgp_config), $1);
|
this_proto = proto_config_new(&proto_bgp, sizeof(struct bgp_config), $1);
|
||||||
|
BGP_CFG->multihop = -1; /* undefined */
|
||||||
BGP_CFG->hold_time = 240;
|
BGP_CFG->hold_time = 240;
|
||||||
BGP_CFG->connect_retry_time = 120;
|
BGP_CFG->connect_retry_time = 120;
|
||||||
BGP_CFG->initial_hold_time = 240;
|
BGP_CFG->initial_hold_time = 240;
|
||||||
|
@ -74,6 +75,7 @@ bgp_proto:
|
||||||
| bgp_proto STARTUP HOLD TIME expr ';' { BGP_CFG->initial_hold_time = $5; }
|
| bgp_proto STARTUP HOLD TIME expr ';' { BGP_CFG->initial_hold_time = $5; }
|
||||||
| bgp_proto CONNECT RETRY TIME expr ';' { BGP_CFG->connect_retry_time = $5; }
|
| bgp_proto CONNECT RETRY TIME expr ';' { BGP_CFG->connect_retry_time = $5; }
|
||||||
| bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; }
|
| bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; }
|
||||||
|
| bgp_proto DIRECT ';' { BGP_CFG->multihop = 0; }
|
||||||
| bgp_proto MULTIHOP ';' { BGP_CFG->multihop = 64; }
|
| bgp_proto MULTIHOP ';' { BGP_CFG->multihop = 64; }
|
||||||
| bgp_proto MULTIHOP expr ';' { BGP_CFG->multihop = $3; if (($3<1) || ($3>255)) cf_error("Multihop must be in range 1-255"); }
|
| bgp_proto MULTIHOP expr ';' { BGP_CFG->multihop = $3; if (($3<1) || ($3>255)) cf_error("Multihop must be in range 1-255"); }
|
||||||
| bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; BGP_CFG->next_hop_keep = 0; }
|
| bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; BGP_CFG->next_hop_keep = 0; }
|
||||||
|
|
|
@ -472,10 +472,14 @@ ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
|
||||||
if (! addr)
|
if (! addr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* a host/loopback address */
|
/* a host address */
|
||||||
if (addr->flags & IA_HOST)
|
if (addr->flags & IA_HOST)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* a loopback iface */
|
||||||
|
if (addr->iface->flags & IF_LOOPBACK)
|
||||||
|
return 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We cannot properly support multiple OSPF ifaces on real iface
|
* We cannot properly support multiple OSPF ifaces on real iface
|
||||||
* with multiple prefixes, therefore we force OSPF ifaces with
|
* with multiple prefixes, therefore we force OSPF ifaces with
|
||||||
|
|
|
@ -1058,3 +1058,36 @@ kif_sys_shutdown(struct kif_proto *p)
|
||||||
krt_buffer_release(&p->p);
|
krt_buffer_release(&p->p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ifa *
|
||||||
|
kif_get_primary_ip(struct iface *i)
|
||||||
|
{
|
||||||
|
#ifndef IPV6
|
||||||
|
static int fd = -1;
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
|
struct ifreq ifr;
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
strncpy(ifr.ifr_name, i->name, IFNAMSIZ);
|
||||||
|
|
||||||
|
int rv = ioctl(fd, SIOCGIFADDR, (char *) &ifr);
|
||||||
|
if (rv < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ip_addr addr;
|
||||||
|
struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.ifr_addr;
|
||||||
|
memcpy(&addr, &sin->sin_addr.s_addr, sizeof(ip_addr));
|
||||||
|
ipa_ntoh(addr);
|
||||||
|
|
||||||
|
struct ifa *a;
|
||||||
|
WALK_LIST(a, i->addrs)
|
||||||
|
{
|
||||||
|
if (ipa_equal(a->ip, addr))
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#define _BIRD_CONFIG_H_
|
#define _BIRD_CONFIG_H_
|
||||||
|
|
||||||
/* BIRD version */
|
/* BIRD version */
|
||||||
#define BIRD_VERSION "1.3.12"
|
#define BIRD_VERSION "1.4.0"
|
||||||
|
|
||||||
/* Include parameters determined by configure script */
|
/* Include parameters determined by configure script */
|
||||||
#include "sysdep/autoconf.h"
|
#include "sysdep/autoconf.h"
|
||||||
|
|
|
@ -27,6 +27,8 @@ 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_init_config(struct kif_config *c UNUSED) { }
|
||||||
static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_config *s UNUSED) { }
|
static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_config *s UNUSED) { }
|
||||||
|
|
||||||
|
static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; }
|
||||||
|
|
||||||
|
|
||||||
/* Kernel routes */
|
/* Kernel routes */
|
||||||
|
|
||||||
|
|
|
@ -862,19 +862,6 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ra.dest = RTD_DEVICE;
|
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;
|
break;
|
||||||
|
|
|
@ -14,7 +14,7 @@ CF_HDR
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
|
CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
|
||||||
CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, BASE, NAME, CONFIRM, UNDO, CHECK, TIMEOUT)
|
CF_KEYWORDS(TIMEFORMAT, ISO, OLD, SHORT, LONG, BASE, NAME, CONFIRM, UNDO, CHECK, TIMEOUT)
|
||||||
|
|
||||||
%type <i> log_mask log_mask_list log_cat cfg_timeout
|
%type <i> log_mask log_mask_list log_cat cfg_timeout
|
||||||
%type <g> log_file
|
%type <g> log_file
|
||||||
|
@ -96,6 +96,8 @@ timeformat_spec:
|
||||||
| timeformat_which TEXT expr TEXT { *$1 = (struct timeformat){$2, $4, $3}; }
|
| timeformat_which TEXT expr TEXT { *$1 = (struct timeformat){$2, $4, $3}; }
|
||||||
| timeformat_which ISO SHORT { *$1 = (struct timeformat){"%T", "%F", 20*3600}; }
|
| timeformat_which ISO SHORT { *$1 = (struct timeformat){"%T", "%F", 20*3600}; }
|
||||||
| timeformat_which ISO LONG { *$1 = (struct timeformat){"%F %T", NULL, 0}; }
|
| timeformat_which ISO LONG { *$1 = (struct timeformat){"%F %T", NULL, 0}; }
|
||||||
|
| timeformat_which OLD SHORT { *$1 = (struct timeformat){NULL, NULL, 0}; }
|
||||||
|
| timeformat_which OLD LONG { *$1 = (struct timeformat){"%d-%m-%Y %T", NULL, 0}; }
|
||||||
;
|
;
|
||||||
|
|
||||||
timeformat_base:
|
timeformat_base:
|
||||||
|
|
|
@ -159,6 +159,9 @@ kif_choose_primary(struct iface *i)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (a = kif_get_primary_ip(i))
|
||||||
|
return a;
|
||||||
|
|
||||||
return find_preferred_ifa(i, IPA_NONE, IPA_NONE);
|
return find_preferred_ifa(i, IPA_NONE, IPA_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,5 +142,6 @@ void kif_sys_copy_config(struct kif_config *, struct kif_config *);
|
||||||
|
|
||||||
void kif_do_scan(struct kif_proto *);
|
void kif_do_scan(struct kif_proto *);
|
||||||
|
|
||||||
|
struct ifa *kif_get_primary_ip(struct iface *i);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue