Commit 96871cd7 authored by Pavel Tvrdík's avatar Pavel Tvrdík
Browse files

Merge branch 'master' into HEAD

parents 4ae31b19 33b4f40a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ cmd_build_tree(void)
	      new->plastson = &new->son;
	      new->len = c-d;
	      memcpy(new->token, d, c-d);
	      new->prio = (new->len == 3 && !memcmp(new->token, "roa", 3)) ? 0 : 1; /* Hack */
	      new->prio = (new->len == 3 && (!memcmp(new->token, "roa", 3) || !memcmp(new->token, "rip", 3))) ? 0 : 1; /* Hack */
	    }
	  old = new;
	  while (isspace(*c))
+43 −21
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ struct sym_scope {
static struct sym_scope *conf_this_scope;

static int cf_hash(byte *c);
static struct symbol *cf_find_sym(byte *c, unsigned int h0);
static inline struct symbol * cf_get_sym(byte *c, uint h0);

linpool *cfg_mem;

@@ -194,7 +194,7 @@ else: {
	}
      k=k->next;
    }
  cf_lval.s = cf_find_sym(yytext, h);
  cf_lval.s = cf_get_sym(yytext, h);
  return SYM;
}

@@ -426,8 +426,9 @@ check_eof(void)
}

static struct symbol *
cf_new_sym(byte *c, unsigned int h)
cf_new_sym(byte *c, uint h0)
{
  uint h = h0 & (SYM_HASH_SIZE-1);
  struct symbol *s, **ht;
  int l;

@@ -449,56 +450,77 @@ cf_new_sym(byte *c, unsigned int h)
}

static struct symbol *
cf_find_sym(byte *c, unsigned int h0)
cf_find_sym(struct config *cfg, byte *c, uint h0)
{
  unsigned int h = h0 & (SYM_HASH_SIZE-1);
  uint h = h0 & (SYM_HASH_SIZE-1);
  struct symbol *s, **ht;

  if (ht = new_config->sym_hash)
  if (ht = cfg->sym_hash)
    {
      for(s = ht[h]; s; s=s->next)
	if (!strcmp(s->name, c) && s->scope->active)
	  return s;
    }
  if (new_config->sym_fallback)
  if (ht = cfg->sym_fallback)
    {
      /* We know only top-level scope is active */
      for(s = new_config->sym_fallback[h]; s; s=s->next)
      for(s = ht[h]; s; s=s->next)
	if (!strcmp(s->name, c) && s->scope->active)
	  return s;
    }
  return cf_new_sym(c, h);

  return NULL;
}

static inline struct symbol *
cf_get_sym(byte *c, uint h0)
{
  return cf_find_sym(new_config, c, h0) ?: cf_new_sym(c, h0);
}

/**
 * cf_find_symbol - find a symbol by name
 * @cfg: specificed config
 * @c: symbol name
 *
 * This functions searches the symbol table for a symbol of given
 * name. First it examines the current scope, then the second recent
 * one and so on until it either finds the symbol and returns a pointer
 * to its &symbol structure or reaches the end of the scope chain
 * and returns %NULL to signify no match.
 * This functions searches the symbol table in the config @cfg for a symbol of
 * given name. First it examines the current scope, then the second recent one
 * and so on until it either finds the symbol and returns a pointer to its
 * &symbol structure or reaches the end of the scope chain and returns %NULL to
 * signify no match.
 */
struct symbol *
cf_find_symbol(byte *c)
cf_find_symbol(struct config *cfg, byte *c)
{
  return cf_find_sym(c, cf_hash(c));
  return cf_find_sym(cfg, c, cf_hash(c));
}

/**
 * cf_get_symbol - get a symbol by name
 * @c: symbol name
 *
 * This functions searches the symbol table of the currently parsed config
 * (@new_config) for a symbol of given name. It returns either the already
 * existing symbol or a newly allocated undefined (%SYM_VOID) symbol if no
 * existing symbol is found.
 */
struct symbol *
cf_get_symbol(byte *c)
{
  return cf_get_sym(c, cf_hash(c));
}

struct symbol *
cf_default_name(char *template, int *counter)
{
  char buf[32];
  char buf[SYM_MAX_LEN];
  struct symbol *s;
  char *perc = strchr(template, '%');

  for(;;)
    {
      bsprintf(buf, template, ++(*counter));
      s = cf_find_sym(buf, cf_hash(buf));
      if (!s)
	break;
      s = cf_get_sym(buf, cf_hash(buf));
      if (s->class == SYM_VOID)
	return s;
      if (!perc)
@@ -529,7 +551,7 @@ cf_define_symbol(struct symbol *sym, int type, void *def)
    {
      if (sym->scope == conf_this_scope)
	cf_error("Symbol already defined");
      sym = cf_new_sym(sym->name, cf_hash(sym->name) & (SYM_HASH_SIZE-1));
      sym = cf_new_sym(sym->name, cf_hash(sym->name));
    }
  sym->class = type;
  sym->def = def;
+39 −26
Original line number Diff line number Diff line
@@ -20,19 +20,19 @@
 *
 * There can exist up to four different configurations at one time: an active
 * one (pointed to by @config), configuration we are just switching from
 * (@old_config), one queued for the next reconfiguration (@future_config;
 * if there is one and the user wants to reconfigure once again, we just
 * free the previous queued config and replace it with the new one) and
 * finally a config being parsed (@new_config). The stored @old_config 
 * is also used for undo reconfiguration, which works in a similar way.
 * Reconfiguration could also have timeout (using @config_timer) and undo
 * is automatically called if the new configuration is not confirmed later.
 * (@old_config), one queued for the next reconfiguration (@future_config; if
 * there is one and the user wants to reconfigure once again, we just free the
 * previous queued config and replace it with the new one) and finally a config
 * being parsed (@new_config). The stored @old_config is also used for undo
 * reconfiguration, which works in a similar way. Reconfiguration could also
 * have timeout (using @config_timer) and undo is automatically called if the
 * new configuration is not confirmed later. The new config (@new_config) and
 * associated linear pool (@cfg_mem) is non-NULL only during parsing.
 *
 * Loading of new configuration is very simple: just call config_alloc()
 * to get a new &config structure, then use config_parse() to parse a
 * configuration file and fill all fields of the structure
 * and finally ask the config manager to switch to the new
 * config by calling config_commit().
 * Loading of new configuration is very simple: just call config_alloc() to get
 * a new &config structure, then use config_parse() to parse a configuration
 * file and fill all fields of the structure and finally ask the config manager
 * to switch to the new config by calling config_commit().
 *
 * CLI commands are parsed in a very similar way -- there is also a stripped-down
 * &config structure associated with them and they are lex-ed and parsed by the
@@ -91,10 +91,15 @@ config_alloc(byte *name)
  linpool *l = lp_new(p, 4080);
  struct config *c = lp_allocz(l, sizeof(struct config));

  /* Duplication of name string in local linear pool */
  uint nlen = strlen(name) + 1;
  char *ndup = lp_allocu(l, nlen);
  memcpy(ndup, name, nlen);

  c->mrtdump_file = -1; /* Hack, this should be sysdep-specific */
  c->pool = p;
  cfg_mem = c->mem = l;
  c->file_name = cfg_strdup(name);
  c->mem = l;
  c->file_name = ndup;
  c->load_time = now;
  c->tf_route = c->tf_proto = (struct timeformat){"%T", "%F", 20*3600};
  c->tf_base = c->tf_log = (struct timeformat){"%F %T", NULL, 0};
@@ -119,11 +124,13 @@ config_alloc(byte *name)
int
config_parse(struct config *c)
{
  int done = 0;
  DBG("Parsing configuration file `%s'\n", c->file_name);
  new_config = c;
  cfg_mem = c->mem;
  if (setjmp(conf_jmpbuf))
    return 0;
    goto cleanup;

  cf_lex_init(0, c);
  sysdep_preconfig(c);
  protos_preconfig(c);
@@ -137,7 +144,12 @@ config_parse(struct config *c)
  if (!c->router_id)
    cf_error("Router ID must be configured manually on IPv6 routers");
#endif
  return 1;
  done = 1;

cleanup:
  new_config = NULL;
  cfg_mem = NULL;
  return done;
}

/**
@@ -150,14 +162,22 @@ config_parse(struct config *c)
int
cli_parse(struct config *c)
{
  new_config = c;
  int done = 0;
  c->sym_fallback = config->sym_hash;
  new_config = c;
  cfg_mem = c->mem;
  if (setjmp(conf_jmpbuf))
    return 0;
    goto cleanup;

  cf_lex_init(1, c);
  cf_parse();
  return 1;
  done = 1;

cleanup:
  c->sym_fallback = NULL;
  new_config = NULL;
  cfg_mem = NULL;
  return done;
}

/**
@@ -237,10 +257,6 @@ config_do_commit(struct config *c, int type)
  if (old_config && !config->shutdown)
    log(L_INFO "Reconfiguring");

  /* This should not be necessary, but it seems there are some
     functions that access new_config instead of config */
  new_config = config;

  if (old_config)
    old_config->obstacle_count++;

@@ -254,9 +270,6 @@ config_do_commit(struct config *c, int type)
  DBG("protos_commit\n");
  protos_commit(c, old_config, force_restart, type);

  /* Just to be sure nobody uses that now */
  new_config = NULL;

  int obs = 0;
  if (old_config)
    obs = --old_config->obstacle_count;
+3 −1
Original line number Diff line number Diff line
@@ -147,7 +147,9 @@ int cf_lex(void);
void cf_lex_init(int is_cli, struct config *c);
void cf_lex_unwind(void);

struct symbol *cf_find_symbol(byte *c);
struct symbol *cf_find_symbol(struct config *cfg, byte *c);

struct symbol *cf_get_symbol(byte *c);
struct symbol *cf_default_name(char *template, int *counter);
struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def);
void cf_push_scope(struct symbol *);
+173 −71
Original line number Diff line number Diff line
@@ -2476,7 +2476,7 @@ protocol ospf <name> {
	This option specifies whether OSPF is allowed to generate ECMP
	(equal-cost multipath) routes. Such routes are used when there are
	several directions to the destination, each with the same (computed)
	cost. This option also allows to specify a limit on maximal number of
	cost. This option also allows to specify a limit on maximum number of
	nexthops in one route. By default, ECMP is disabled. If enabled,
	default	value of the limit is 16.

@@ -3244,16 +3244,14 @@ one). After some time, the distance reaches infinity (that's 15 in RIP) and all
routers know that network is unreachable. RIP tries to minimize situations where
counting to infinity is necessary, because it is slow. Due to infinity being 16,
you can't use RIP on networks where maximal distance is higher than 15
hosts. You can read more about RIP at
<HTMLURL URL="http://www.ietf.org/html.charters/rip-charter.html"
name="http://www.ietf.org/html.charters/rip-charter.html">. Both IPv4
(RFC 1723 <htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc1723.txt">) and IPv6
(RFC 2080 <htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc2080.txt">) versions
of RIP are supported by BIRD, historical RIPv1
(RFC 1058 <htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc1058.txt">) is not
currently supported. RIPv4 MD5 authentication
(RFC 2082 <htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc2082.txt">) is
supported.
hosts.

<p>BIRD supports RIPv1
(RFC 1058<htmlurl url="http://www.rfc-editor.org/rfc/rfc1058.txt">),
RIPv2 (RFC 2453<htmlurl url="http://www.rfc-editor.org/rfc/rfc2453.txt">),
RIPng (RFC 2080<htmlurl url="http://www.rfc-editor.org/rfc/rfc2080.txt">),
and RIP cryptographic authentication (SHA-1 not implemented)
(RFC 4822<htmlurl url="http://www.rfc-editor.org/rfc/rfc4822.txt">).

<p>RIP is a very simple protocol, and it has a lot of shortcomings. Slow
convergence, big network load and inability to handle larger networks makes it
@@ -3261,39 +3259,156 @@ pretty much obsolete. It is still usable on very small networks.

<sect1>Configuration

<p>In addition to options common for all to other protocols, RIP supports the
following ones:
<p>RIP configuration consists mainly of common protocol options and interface
definitions, most RIP options are interface specific.

<code>
protocol rip [&lt;name&gt;] {
	infinity &lt;number&gt;;
	ecmp &lt;switch&gt; [limit &lt;number&gt;];
	interface &lt;interface pattern&gt; {
		metric &lt;number&gt;;
		mode multicast|broadcast;
		passive &lt;switch&gt;;
		address &lt;ip&gt;;
		port &lt;number&gt;;
		version 1|2;
		split horizon &lt;switch&gt;;
		poison reverse &lt;switch&gt;;
		check zero &lt;switch&gt;;
		update time &lt;number&gt;;
		timeout time &lt;number&gt;;
		garbage time &lt;number&gt;;
		ecmp weight &lt;number&gt;;
		ttl security &lt;switch&gt;; | tx only;
		tx class|dscp &lt;number&gt;;
		tx priority &lt;number&gt;;
		rx buffer &lt;number&gt;;
		tx length &lt;number&gt;;
		check link &lt;switch&gt;;
		authentication none|plaintext|cryptographic;
		password "&lt;text&gt;";
		password "&lt;text&gt;" {
			id &lt;num&gt;;
			generate from "&lt;date&gt;";
			generate to "&lt;date&gt;";
			accept from "&lt;date&gt;";
			accept to "&lt;date&gt;";
		};
	};
}
</code>

<descrip>
	<tag>authentication none|plaintext|md5</tag>
	Selects authentication method to be used. <cf/none/ means that packets
	are not authenticated at all, <cf/plaintext/ means that a plaintext
	password is embedded into each packet, and <cf/md5/ means that packets
	are authenticated using a MD5 cryptographic hash. If you set
	authentication to not-none, it is a good idea to add <cf>password</cf>
	section. Default: none.
	<tag>infinity <M>number</M></tag>
	Selects the distance of infinity. Bigger values will make
	protocol convergence even slower. The default value is 16.

	<tag>honor always|neighbor|never</tag>
	Specifies when should requests for dumping routing table be honored.
	(Always, when sent from a host on a directly connected network or
	never.) Routing table updates are honored only from neighbors, that is
	not configurable. Default: never.
	<tag>ecmp <M>switch</M> [limit <M>number</M>]</tag>
	This option specifies whether RIP is allowed to generate ECMP
	(equal-cost multipath) routes. Such routes are used when there are
	several directions to the destination, each with the same (computed)
	cost. This option also allows to specify a limit on maximum number of
	nexthops in one route. By default, ECMP is disabled. If enabled,
	default	value of the limit is 16.

	<tag>interface <m/pattern [, ...]/ { <m/options/ }</tag>
	Interface definitions specify a set of interfaces on which the
	protocol is activated and contain interface specific options.
	See <ref id="dsc-iface" name="interface"> common options for
	detailed description.
</descrip>

<p>There are some options that can be specified per-interface:
<p>Interface specific options:

<descrip>
	<tag>metric <m/num/</tag>
	This option specifies the metric of the interface. Valid
	This option specifies the metric of the interface. When a route is
	received from the interface, its metric is increased by this value
	before further processing. Valid values are 1-255, but values higher
	than infinity has no further meaning. Default: 1.

	<tag>mode multicast|broadcast</tag>
	This option selects the mode for RIP to use on the interface. The
	default is multicast mode for RIPv2 and broadcast mode for RIPv1.
	RIPng always uses the multicast mode.

	<tag>passive <m/switch/</tag>
	Passive interfaces receive routing updates but do not transmit any
	messages. Default: no.

	<tag>address <m/ip/</tag>
	This option specifies a destination address used for multicast or
	broadcast messages, the default is the official RIP (224.0.0.9) or RIPng
	(ff02::9) multicast address, or an appropriate broadcast address in the
	broadcast mode.

	<tag>port <m/number/</tag>
	This option selects an UDP port to operate on, the default is the
	official RIP (520) or RIPng (521) port.

	<tag>version 1|2</tag>
	This option selects the version of RIP used on the interface. For RIPv1,
	automatic subnet aggregation is not implemented, only classful network
	routes and host routes are propagated. Note that BIRD allows RIPv1 to be
	configured with features that are defined for RIPv2 only, like
	authentication or using multicast sockets. The default is RIPv2 for IPv4
	RIP, the option is not supported for RIPng, as no further versions are
	defined.

	<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
	interface from which they were received. They are either not propagated
	back at all (plain split horizon) or propagated back with an infinity
	metric (split horizon with poisoned reverse). Therefore, other routers
	on the interface will not consider the router as a part of an
	independent path to the destination of the route. Default: yes.

	<tag>poison reverse <m/switch/</tag>
	When split horizon is active, this option specifies whether the poisoned
	reverse variant (propagating routes back with an infinity metric) is
	used. The poisoned reverse has some advantages in faster convergence,
	but uses more network traffic. Default: yes.

	<tag>check zero <m/switch/</tag>
	Received RIPv1 packets with non-zero values in reserved fields should
	be discarded. This option specifies whether the check is performed or
	such packets are just processed as usual. Default: yes.

	<tag>update time <m/number/</tag>
	Specifies the number of seconds between periodic updates. A lower number
	will mean faster convergence but bigger network load. Default: 30.

	<tag>timeout time <m/number/</tag>
	Specifies the time interval (in seconds) between the last received route
	announcement and the route expiration. After that, the network is
	considered unreachable, but still is propagated with infinity distance.
	Default: 180.

	<tag>garbage time <m/number/</tag>
	Specifies the time interval (in seconds) between the route expiration
	and the removal of the unreachable network entry. The garbage interval,
	when a route with infinity metric is propagated, is used for both
	internal (after expiration) and external (after withdrawal) routes.
	Default: 120.

	<tag>ecmp weight <m/number/</tag>
	When ECMP (multipath) routes are allowed, this value specifies a
	relative weight used for nexthops going through the iface. Valid
	values are 1-256. Default value is 1.

	<tag>authentication none|plaintext|cryptographic</tag>
	Selects authentication method to be used. <cf/none/ means that packets
	are not authenticated at all, <cf/plaintext/ means that a plaintext
	password is embedded into each packet, and <cf/cryptographic/ means that
	packets are authenticated using a MD5 cryptographic hash. If you set
	authentication to not-none, it is a good idea to add <cf>password</cf>
	section. Default: none.

	<tag>mode multicast|broadcast|quiet|nolisten|version1</tag>
	This option selects the mode for RIP to use on the interface. If nothing
	is specified, RIP runs in multicast mode. <cf/version1/ is currently
	equivalent to <cf/broadcast/, and it makes RIP talk to a broadcast
	address even through multicast mode is possible. <cf/quiet/ option means
	that RIP will not transmit any periodic messages to this interface and
	<cf/nolisten/ means that RIP will send to this interface butnot listen
	to it.
	<tag>password "<m/text/"</tag>
	Specifies a password used for authentication. See <ref id="dsc-pass"
	name="password"> common option for detailed description.

	<tag>ttl security [<m/switch/ | tx only]</tag>
	TTL security is a feature that protects routing protocols from remote
@@ -3309,43 +3424,31 @@ following ones:
	compatibility with neighbors regardless of whether they use ttl
	security.

	Note that for RIPng, TTL security is a standard behavior (required by
	RFC 2080), but BIRD uses <cf/tx only/ by default, for compatibility with
	older versions. For IPv4 RIP, default value is no.
	For RIPng, TTL security is a standard behavior (required by RFC 2080)
	and therefore default value is yes. For IPv4 RIP, default value is no.

	<tag>tx class|dscp|priority <m/num/</tag>
	<tag>tx class|dscp|priority <m/number/</tag>
	These options specify the ToS/DiffServ/Traffic class/Priority of the
	outgoing RIP packets. See <ref id="dsc-prio" name="tx class"> common
	option for detailed description.
</descrip>

<p>The following options generally override behavior specified in RFC. If you
use any of these options, BIRD will no longer be RFC-compliant, which means it
will not be able to talk to anything other than equally configured BIRD. I have
warned you.
	<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 532 for IPv4 RIP and interface MTU value for RIPng.

<descrip>
	<tag>port <M>number</M></tag>
	Selects IP port to operate on, default 520. (This is useful when testing
	BIRD, if you set this to an address &gt;1024, you will not need to run
	bird with UID==0).
	<tag>tx length <m/number/</tag>
	This option specifies the maximum length of generated RIP packets. To
	avoid IP fragmentation, it should not exceed the interface MTU value.
	The default value is 532 for IPv4 RIP and interface MTU value for RIPng.

	<tag>infinity <M>number</M></tag>
	Selects the value of infinity, default is 16. Bigger values will make
	protocol convergence even slower.

	<tag>period <M>number</M></tag>
	Specifies the number of seconds between periodic updates. Default is 30
	seconds. A lower number will mean faster convergence but bigger network
	load. Do not use values lower than 12.

	<tag>timeout time <M>number</M></tag>
	Specifies how old route has to be to be considered unreachable.
	Default is 4*<cf/period/.

	<tag>garbage time <M>number</M></tag>
	Specifies how old route has to be to be discarded. Default is
	10*<cf/period/.
	<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:
	no.
</descrip>

<sect1>Attributes
@@ -3356,27 +3459,26 @@ warned you.
	<tag>int <cf/rip_metric/</tag>
	RIP metric of the route (ranging from 0 to <cf/infinity/).  When routes
	from different RIP instances are available and all of them have the same
	preference, BIRD prefers the route with lowest <cf/rip_metric/. When
	importing a non-RIP route, the metric defaults to 5.
	preference, BIRD prefers the route with lowest <cf/rip_metric/. When a
	non-RIP route is exported to RIP, the default metric is 1.

	<tag>int <cf/rip_tag/</tag>
	RIP route tag: a 16-bit number which can be used to carry additional
	information with the route (for example, an originating AS number in
	case of external routes). When importing a non-RIP route, the tag
	defaults to 0.
	case of external routes). When a non-RIP route is exported to RIP, the
	default tag is 0.
</descrip>

<sect1>Example

<p><code>
protocol rip MyRIP_test {
protocol rip {
        debug all;
        port 1520;
        period 12;
        garbage time 60;
        interface "eth0" { metric 3; mode multicast; };
	interface "eth*" { metric 2; mode broadcast; };
        honor neighbor;
        authentication none;
        import filter { print "importing"; accept; };
        export filter { print "exporting"; accept; };
Loading