Merge branch 'master' into add-path

This commit is contained in:
Ondrej Zajicek 2013-11-25 18:42:47 +01:00
commit 283c7dfada
21 changed files with 169 additions and 109 deletions

15
NEWS
View file

@ -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).

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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)
{ {

View file

@ -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);
} }

View file

@ -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");

View file

@ -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; }

View file

@ -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

View file

@ -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;
}

View file

@ -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"

View file

@ -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 */

View file

@ -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;

View file

@ -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:

View file

@ -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);
} }

View file

@ -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