Commit 7730553b authored by Ondřej Zajíček's avatar Ondřej Zajíček

Merge remote-tracking branch 'origin/soft-int'

parents 0da562a7 ec2194fa
Version 1.5.0pre (2014-11-05) - Not for production
o Major OSPF protocol redesign
o RFC 6549 - OSPFv2 multi-instance extension
Version 1.4.5 (2014-10-06)
o New 'show route noexport' command option.
o Port option for BGP sessions.
......
......@@ -124,22 +124,24 @@ include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
}
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
ip4_addr a;
if (!ip4_pton(yytext, &a))
cf_error("Invalid IPv4 address %s", yytext);
#ifdef IPV6
if (ipv4_pton_u32(yytext, &cf_lval.i32))
return RTRID;
cf_error("Invalid IPv4 address %s", yytext);
cf_lval.i32 = ip4_to_u32(a);
return RTRID;
#else
if (ip_pton(yytext, &cf_lval.a))
return IPA;
cf_error("Invalid IP address %s", yytext);
cf_lval.a = ipa_from_ip4(a);
return IPA;
#endif
}
({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
#ifdef IPV6
if (ip_pton(yytext, &cf_lval.a))
if (ipa_pton(yytext, &cf_lval.a))
return IPA;
cf_error("Invalid IP address %s", yytext);
cf_error("Invalid IPv6 address %s", yytext);
#else
cf_error("This is an IPv4 router, therefore IPv6 addresses are not supported");
#endif
......
......@@ -187,7 +187,7 @@ pxlen:
$$ = $2;
}
| ':' ipa {
$$ = ipa_mklen($2);
$$ = ipa_masklen($2);
if ($$ < 0) cf_error("Invalid netmask %I", $2);
}
;
......
......@@ -2292,6 +2292,7 @@ networks.
<code>
protocol ospf &lt;name&gt; {
rfc1583compat &lt;switch&gt;;
instance id &lt;num&gt;;
stub router &lt;switch&gt;;
tick &lt;num&gt;;
ecmp &lt;switch&gt; [limit &lt;num&gt;];
......@@ -2336,6 +2337,7 @@ protocol ospf &lt;name&gt; {
tx length &lt;num&gt;;
type [broadcast|bcast|pointopoint|ptp|
nonbroadcast|nbma|pointomultipoint|ptmp];
link lsa suppression &lt;switch&gt;;
strict nonbroadcast &lt;switch&gt;;
real broadcast &lt;switch&gt;;
ptp netmask &lt;switch&gt;;
......@@ -2378,14 +2380,24 @@ protocol ospf &lt;name&gt; {
RFC 1583 <htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc1583.txt">.
Default value is no.
<tag>instance id <m/num/</tag>
When multiple OSPF protocol instances are active on the same links, they
should use different instance IDs to distinguish their packets. Although
it could be done on per-interface basis, it is often preferred to set
one instance ID to whole OSPF domain/topology (e.g., when multiple
instances are used to represent separate logical topologies on the same
physical network). This option specifies the default instance ID for all
interfaces of the OSPF instance. Note that this option, if used, must
precede interface definitions. Default value is 0.
<tag>stub router <M>switch</M></tag>
This option configures the router to be a stub router, i.e., a router
that participates in the OSPF topology but does not allow transit
traffic. In OSPFv2, this is implemented by advertising maximum metric
for outgoing links, as suggested by
RFC 3137 <htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc3137.txt">.
In OSPFv3, the stub router behavior is announced by clearing the R-bit
in the router LSA. Default value is no.
for outgoing links. In OSPFv3, the stub router behavior is announced by
clearing the R-bit in the router LSA. See RFC 6987
<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc6987.txt"> for
details. Default value is no.
<tag>tick <M>num</M></tag>
The routing table calculation and clean-up of areas' databases is not
......@@ -2487,22 +2499,26 @@ protocol ospf &lt;name&gt; {
prefix. When option <cf/summary/ is used, also default stub networks
that are subnetworks of given stub network are suppressed. This might be
used, for example, to aggregate generated stub networks.
<tag>interface <M>pattern</M> [instance <m/num/]</tag>
Defines that the specified interfaces belong to the area being defined.
See <ref id="dsc-iface" name="interface"> common option for detailed
description. In OSPFv2, extended interface clauses are used, because
OSPFv2 handles each network prefix as a separate virtual interface. In
OSPFv3, you can specify instance ID for that interface description, so
it is possible to have several instances of that interface with
different options or even in different areas.
each network prefix is handled as a separate virtual interface.
You can specify alternative instance ID for the interface definition,
therefore it is possible to have several instances of that interface
with different options or even in different areas. For OSPFv2,
instance ID support is an extension (RFC 6549
<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc6549.txt">) and is
supposed to be set per-protocol. For OSPFv3, it is an integral feature.
<tag>virtual link <M>id</M> [instance <m/num/]</tag>
Virtual link to router with the router id. Virtual link acts as a
point-to-point interface belonging to backbone. The actual area is used
as transport area. This item cannot be in the backbone. In OSPFv3, you
could also use several virtual links to one destination with different
instance IDs.
as a transport area. This item cannot be in the backbone. Like with
<cf/interface/ option, you could also use several virtual links to one
destination with different instance IDs.
<tag>cost <M>num</M></tag>
Specifies output cost (metric) of an interface. Default value is 10.
......@@ -2533,8 +2549,8 @@ protocol ospf &lt;name&gt; {
<tag>wait <M>num</M></tag>
After start, router waits for the specified number of seconds between
starting election and building adjacency. Default value is 40.
starting election and building adjacency. Default value is 4*<m/hello/.
<tag>dead count <M>num</M></tag>
When the router does not receive any messages from a neighbor in
<m/dead count/*<m/hello/ seconds, it will consider the neighbor down.
......@@ -2600,9 +2616,16 @@ protocol ospf &lt;name&gt; {
communication, or if the NBMA network is used as an (possibly
unnumbered) PtP link.
<tag>strict nonbroadcast <M>switch</M></tag>
<tag>link lsa suppression <m/switch/</tag>
In OSPFv3, link LSAs are generated for each link, announcing link-local
IPv6 address of the router to its local neighbors. These are useless on
PtP or PtMP networks and this option allows to suppress the link LSA
origination for such interfaces. The option is ignored on other than PtP
or PtMP interfaces. Default value is no.
<tag>strict nonbroadcast <m/switch/</tag>
If set, don't send hello to any undefined neighbor. This switch is
ignored on other than NBMA or PtMP networks. Default value is no.
ignored on other than NBMA or PtMP interfaces. Default value is no.
<tag>real broadcast <m/switch/</tag>
In <cf/type broadcast/ or <cf/type ptp/ network configuration, OSPF
......
......@@ -3,13 +3,6 @@ bitops.c
bitops.h
ip.h
ip.c
#ifdef IPV6
ipv6.c
ipv6.h
#else
ipv4.c
ipv4.h
#endif
lists.c
lists.h
md5.c
......
......@@ -33,6 +33,12 @@
#define ABS(a) ((a)>=0 ? (a) : -(a))
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
#define BIT32_VAL(p) (((u32) 1) << ((p) % 32))
#define BIT32_TEST(b,p) ((b)[(p)/32] & BIT32_VAL(p))
#define BIT32_SET(b,p) ((b)[(p)/32] |= BIT32_VAL(p))
#define BIT32_CLR(b,p) ((b)[(p)/32] &= ~BIT32_VAL(p))
#define BIT32_ZERO(b,l) memset((b), 0, (l)/8)
#ifndef NULL
#define NULL ((void *) 0)
#endif
......
......@@ -27,7 +27,7 @@ event_list global_event_list;
inline void
ev_postpone(event *e)
{
if (e->n.next)
if (ev_active(e))
{
rem_node(&e->n);
e->n.next = NULL;
......
......@@ -30,4 +30,11 @@ void ev_schedule(event *);
void ev_postpone(event *);
int ev_run_list(event_list *);
static inline int
ev_active(event *e)
{
return e->n.next != NULL;
}
#endif
/*
* BIRD Library -- IP address routines common for IPv4 and IPv6
* BIRD Library -- IP address functions
*
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include "nest/bird.h"
#include "lib/ip.h"
/**
* DOC: IP addresses
*
......@@ -18,6 +15,333 @@
* they must be manipulated using the following functions and macros.
*/
#include <stdlib.h>
#include "nest/bird.h"
#include "lib/ip.h"
int
ip6_compare(ip6_addr a, ip6_addr b)
{
int i;
for (i=0; i<4; i++)
if (a.addr[i] > b.addr[i])
return 1;
else if (a.addr[i] < b.addr[i])
return -1;
return 0;
}
ip6_addr
ip6_mkmask(uint n)
{
ip6_addr a;
int i;
for (i=0; i<4; i++)
{
if (!n)
a.addr[i] = 0;
else if (n >= 32)
{
a.addr[i] = ~0;
n -= 32;
}
else
{
a.addr[i] = u32_mkmask(n);
n = 0;
}
}
return a;
}
int
ip6_masklen(ip6_addr *a)
{
int i, j, n;
for (i=0, n=0; i<4; i++, n+=32)
if (a->addr[i] != ~0U)
{
j = u32_masklen(a->addr[i]);
if (j < 0)
return j;
n += j;
while (++i < 4)
if (a->addr[i])
return -1;
break;
}
return n;
}
int
ip4_classify(ip4_addr ad)
{
u32 a = _I(ad);
u32 b = a >> 24U;
if (b && b <= 0xdf)
{
if (b == 0x7f)
return IADDR_HOST | SCOPE_HOST;
else if ((b == 0x0a) ||
((a & 0xffff0000) == 0xc0a80000) ||
((a & 0xfff00000) == 0xac100000))
return IADDR_HOST | SCOPE_SITE;
else
return IADDR_HOST | SCOPE_UNIVERSE;
}
if (b >= 0xe0 && b <= 0xef)
return IADDR_MULTICAST | SCOPE_UNIVERSE;
if (a == 0xffffffff)
return IADDR_BROADCAST | SCOPE_LINK;
return IADDR_INVALID;
}
int
ip6_classify(ip6_addr *a)
{
u32 x = a->addr[0];
if ((x & 0xe0000000) == 0x20000000) /* 2000::/3 Aggregatable Global Unicast Address */
return IADDR_HOST | SCOPE_UNIVERSE;
if ((x & 0xffc00000) == 0xfe800000) /* fe80::/10 Link-Local Address */
return IADDR_HOST | SCOPE_LINK;
if ((x & 0xffc00000) == 0xfec00000) /* fec0::/10 Site-Local Address */
return IADDR_HOST | SCOPE_SITE;
if ((x & 0xfe000000) == 0xfc000000) /* fc00::/7 Unique Local Unicast Address (RFC 4193) */
return IADDR_HOST | SCOPE_SITE;
if ((x & 0xff000000) == 0xff000000) /* ff00::/8 Multicast Address */
{
uint scope = (x >> 16) & 0x0f;
switch (scope)
{
case 1: return IADDR_MULTICAST | SCOPE_HOST;
case 2: return IADDR_MULTICAST | SCOPE_LINK;
case 5: return IADDR_MULTICAST | SCOPE_SITE;
case 8: return IADDR_MULTICAST | SCOPE_ORGANIZATION;
case 14: return IADDR_MULTICAST | SCOPE_UNIVERSE;
default: return IADDR_MULTICAST | SCOPE_UNDEFINED;
}
}
if (!x && !a->addr[1])
{
u32 a2 = a->addr[2];
u32 a3 = a->addr[3];
if (a2 == 0 && a3 == 1)
return IADDR_HOST | SCOPE_HOST; /* Loopback address */
if (a2 == 0)
return ip4_classify(_MI4(a3)); /* IPv4 compatible addresses */
if (a2 == 0xffff)
return ip4_classify(_MI4(a3)); /* IPv4 mapped addresses */
return IADDR_INVALID;
}
return IADDR_HOST | SCOPE_UNDEFINED;
}
/*
* Conversion of IPv6 address to presentation format and vice versa.
* Heavily inspired by routines written by Paul Vixie for the BIND project
* and of course by RFC 2373.
*/
char *
ip4_ntop(ip4_addr a, char *b)
{
u32 x = _I(a);
return b + bsprintf(b, "%d.%d.%d.%d", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff);
}
char *
ip6_ntop(ip6_addr a, char *b)
{
u16 words[8];
int bestpos, bestlen, curpos, curlen, i;
/* First of all, preprocess the address and find the longest run of zeros */
bestlen = bestpos = curpos = curlen = 0;
for (i=0; i<8; i++)
{
u32 x = a.addr[i/2];
words[i] = ((i%2) ? x : (x >> 16)) & 0xffff;
if (words[i])
curlen = 0;
else
{
if (!curlen)
curpos = i;
curlen++;
if (curlen > bestlen)
{
bestpos = curpos;
bestlen = curlen;
}
}
}
if (bestlen < 2)
bestpos = -1;
/* Is it an encapsulated IPv4 address? */
if (!bestpos && ((bestlen == 5 && a.addr[2] == 0xffff) || (bestlen == 6)))
{
u32 x = a.addr[3];
b += bsprintf(b, "::%s%d.%d.%d.%d",
a.addr[2] ? "ffff:" : "",
(x >> 24) & 0xff,
(x >> 16) & 0xff,
(x >> 8) & 0xff,
x & 0xff);
return b;
}
/* Normal IPv6 formatting, compress the largest sequence of zeros */
for (i=0; i<8; i++)
{
if (i == bestpos)
{
i += bestlen - 1;
*b++ = ':';
if (i == 7)
*b++ = ':';
}
else
{
if (i)
*b++ = ':';
b += bsprintf(b, "%x", words[i]);
}
}
*b = 0;
return b;
}
int
ip4_pton(char *a, ip4_addr *o)
{
int i;
unsigned long int l;
u32 ia = 0;
i=4;
while (i--)
{
char *d, *c = strchr(a, '.');
if (!c != !i)
return 0;
l = strtoul(a, &d, 10);
if (d != c && *d || l > 255)
return 0;
ia = (ia << 8) | l;
if (c)
c++;
a = c;
}
*o = ip4_from_u32(ia);
return 1;
}
int
ip6_pton(char *a, ip6_addr *o)
{
u16 words[8];
int i, j, k, l, hfil;
char *start;
if (a[0] == ':') /* Leading :: */
{
if (a[1] != ':')
return 0;
a++;
}
hfil = -1;
i = 0;
while (*a)
{
if (*a == ':') /* :: */
{
if (hfil >= 0)
return 0;
hfil = i;
a++;
continue;
}
j = 0;
l = 0;
start = a;
for (;;)
{
if (*a >= '0' && *a <= '9')
k = *a++ - '0';
else if (*a >= 'A' && *a <= 'F')
k = *a++ - 'A' + 10;
else if (*a >= 'a' && *a <= 'f')
k = *a++ - 'a' + 10;
else
break;
j = (j << 4) + k;
if (j >= 0x10000 || ++l > 4)
return 0;
}
if (*a == ':' && a[1])
a++;
else if (*a == '.' && (i == 6 || i < 6 && hfil >= 0))
{ /* Embedded IPv4 address */
ip4_addr x;
if (!ip4_pton(start, &x))
return 0;
words[i++] = _I(x) >> 16;
words[i++] = _I(x);
break;
}
else if (*a)
return 0;
if (i >= 8)
return 0;
words[i++] = j;
}
/* Replace :: with an appropriate number of zeros */
if (hfil >= 0)
{
j = 8 - i;
for (i=7; i-j >= hfil; i--)
words[i] = words[i-j];
for (; i>=hfil; i--)
words[i] = 0;
}
/* Convert the address to ip6_addr format */
for (i=0; i<4; i++)
o->addr[i] = (words[2*i] << 16) | words[2*i+1];
return 1;
}
/**
* ip_scope_text - get textual representation of address scope
* @scope: scope (%SCOPE_xxx)
......@@ -25,7 +349,7 @@
* Returns a pointer to a textual name of the scope given.
*/
char *
ip_scope_text(unsigned scope)
ip_scope_text(uint scope)
{
static char *scope_table[] = { "host", "link", "site", "org", "univ", "undef" };
......@@ -35,6 +359,23 @@ ip_scope_text(unsigned scope)
return scope_table[scope];
}
ip4_addr
ip4_class_mask(ip4_addr ad)
{
u32 m, a = _I(ad);
if (a < 0x80000000)
m = 0xff000000;
else if (a < 0xc0000000)
m = 0xffff0000;
else
m = 0xffffff00;
if (a & ~m)
m = 0xffffffff;
return _MI4(m);
}
#if 0
/**
* ipa_equal - compare two IP addresses for equality
......@@ -102,14 +443,14 @@ ip_addr ipa_not(ip_addr x) { DUMMY }
ip_addr ipa_mkmask(int x) { DUMMY }
/**
* ipa_mkmask - calculate netmask length
* ipa_masklen - calculate netmask length
* @x: IP address
*
* This function checks whether @x represents a valid netmask and
* returns the size of the associate network prefix or -1 for invalid
* mask.
*/
int ipa_mklen(ip_addr x) { DUMMY }
int ipa_masklen(ip_addr x) { DUMMY }
/**
* ipa_hash - hash IP addresses
......@@ -151,8 +492,8 @@ void ipa_ntoh(ip_addr x) { DUMMY }
int ipa_classify(ip_addr x) { DUMMY }
/**
* ipa_class_mask - guess netmask according to address class
* @x: IP address
* ip4_class_mask - guess netmask according to address class
* @x: IPv4 address
*
* This function (available in IPv4 version only) returns a
* network mask according to the address class of @x. Although
......@@ -160,7 +501,7 @@ int ipa_classify(ip_addr x) { DUMMY }
* routing protocols transferring no prefix lengths nor netmasks
* and this function could be useful to them.
*/
ip_addr ipa_class_mask(ip_addr x) { DUMMY }
ip4_addr ip4_class_mask(ip4_addr x) { DUMMY }
/**
* ipa_from_u32 - convert IPv4 address to an integer
......@@ -193,7 +534,7 @@ ip_addr ipa_to_u32(u32 x) { DUMMY }
int ipa_compare(ip_addr x, ip_addr y) { DUMMY }
/**
* ipa_build - build an IPv6 address from parts
* ipa_build6 - build an IPv6 address from parts
* @a1: part #1
* @a2: part #2
* @a3: part #3
......@@ -203,18 +544,7 @@ int ipa_compare(ip_addr x, ip_addr y) { DUMMY }
* address. It's used for example when a protocol wants to bind its
* socket to a hard-wired multicast address.
*/
ip_addr ipa_build(u32 a1, u32 a2, u32 a3, u32 a4) { DUMMY }
/**
* ipa_absolutize - convert link scope IPv6 address to universe scope
* @x: link scope IPv6 address
* @y: universe scope IPv6 prefix of the interface
*
* This function combines a link-scope IPv6 address @x with the universe
* scope prefix @x of the network assigned to an interface to get a
* universe scope form of @x.
*/
ip_addr ipa_absolutize(ip_addr x, ip_addr y) { DUMMY }
ip_addr ipa_build6(u32 a1, u32 a2, u32 a3, u32 a4) { DUMMY }
/**
* ip_ntop - convert IP address to textual representation
......
This diff is collapsed.
/*
* BIRD Library -- IPv4 Address Manipulation Functions
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <stdlib.h>
#include "nest/bird.h"
#include "lib/ip.h"
#include "lib/string.h"
int
ipv4_classify(u32 a)
{
u32 b = a >> 24U;
if (b && b <= 0xdf)
{
if (b == 0x7f)
return IADDR_HOST | SCOPE_HOST;
else if (b == 0x0a ||
(a & 0xffff0000) == 0xc0a80000 ||
(a & 0xfff00000) == 0xac100000)
return IADDR_HOST | SCOPE_SITE;
else
return IADDR_HOST | SCOPE_UNIVERSE;
}
if (b >= 0xe0 && b <= 0xef)
return IADDR_MULTICAST | SCOPE_UNIVERSE;
if (a == 0xffffffff)
return IADDR_BROADCAST | SCOPE_LINK;
return IADDR_INVALID;
}
char *
ip_ntop(ip_addr a, char *b)
{
u32 x = _I(a);
return b + bsprintf(b, "%d.%d.%d.%d",
((x >> 24) & 0xff),
((x >> 16) & 0xff),
((x >> 8) & 0xff),
(x & 0xff));
}
char *
ip_ntox(ip_addr a, char *b)
{
return b + bsprintf(b, "%08x", _I(a));
}
u32
ipv4_class_mask(u32 a)
{
u32 m;
if (a < 0x80000000)
m = 0xff000000;
else if (a < 0xc0000000)
m = 0xffff0000;
else
m = 0xffffff00;
while (a & ~m)
m |= m >> 1;
return m;
}
int
ip_pton(char *a, ip_addr *o)
{
int i;
unsigned long int l;
u32 ia = 0;
i=4;
while (i--)
{
char *d, *c = strchr(a, '.');
if (!c != !i)
return 0;
l = strtoul(a, &d, 10);
if (d != c && *d || l > 255)
return 0;
ia = (ia << 8) | l;
if (c)
c++;
a = c;
}
*o = ipa_from_u32(ia);