[-]
[+]
|
Changed |
bird.spec
|
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/ChangeLog
^
|
@@ -1,3 +1,125 @@
+commit 1e69379e70da3486a601cab7a41ccf7a5825101d
+Author: Ondrej Filip <feela@network.cz>
+Date: Sun Sep 11 21:43:24 2011 +0200
+
+ NEWS file updated.
+
+commit 48ec367aabaaa5328f4072d237001e245a7363df
+Author: Ondrej Filip <feela@network.cz>
+Date: Sun Sep 11 21:21:47 2011 +0200
+
+ Configuration can include other files.
+
+commit a98995273bd8788cf525f44479026d5ce6b7dd52
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Sep 4 13:23:26 2011 +0200
+
+ NEWS and version update.
+
+commit cb2b586f00f5e7ef9a902b028fc5bfe117890457
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Sep 4 10:39:10 2011 +0200
+
+ NetBSD compile fix.
+
+commit 51947659abbf9af861aa7dec36fd1c845fb617ab
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Sep 4 00:56:02 2011 +0200
+
+ Minor changes in BGP protocol info.
+
+ Shows neighbor IP and ASN even if protocol is down.
+
+commit 6c4df70373fa640a7f068d4e1b563621b67c0d2b
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sat Sep 3 21:59:40 2011 +0200
+
+ Fixes possible buffer overflow when printing BGP attributes.
+
+ Thanks to Alexander V. Chernikov for the patch.
+
+commit 2918e61046388821c3d4411c602dc5b28ad59329
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sat Sep 3 21:31:26 2011 +0200
+
+ Fixes for OSPF NSSA handling.
+
+commit b1b19433602f2a2ff58cfe2c1858ff883eee7b20
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Tue Aug 16 23:05:35 2011 +0200
+
+ The generalized TTL security mechanism (RFC 5082) support.
+
+ Thanks to Alexander V. Chernikov for the patch.
+
+commit a52d52fa91ffcbcea58326fc2de476ce5644256f
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Aug 15 20:54:58 2011 +0200
+
+ Fixes some missing tabs.
+
+ They unintentionally disappeared in 1.3.2.
+
+commit a209d5d8e1bea2b37a7cddebe1f275da4ebde4e3
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Aug 15 02:06:56 2011 +0200
+
+ A minor fix in BSD.
+
+commit 8815d846bf77e4231f36b64d8e4ac9a3ec2d1504
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Aug 14 15:53:47 2011 +0200
+
+ BGP Extended communities documentation.
+
+commit 42a0c05408c4151442e6a0ec1c6889acbcfe9c17
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri Aug 12 21:03:43 2011 +0200
+
+ BGP Extended communities.
+
+commit bde872bba745e5596bdb066df6ef323b7cabcfdd
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Aug 8 10:57:54 2011 +0200
+
+ The documentation update.
+
+commit ed317862c2958303cf541fe63f4ea26d00918a9a
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Aug 8 01:45:31 2011 +0200
+
+ OSPF NSSA support, inter-area LSA translation.
+
+commit aca0e79faa391a2841134dac78a499dfdca68bd9
+Author: root <root@localhost.(none)>
+Date: Fri Jul 29 14:52:28 2011 +0200
+
+ Handles missing macro.
+
+commit 14272097df989808790673521f643053f898aa8c
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Thu Jul 28 13:50:02 2011 +0200
+
+ Fixes crash on BSD.
+
+commit 4160a9dd9416ee5afd215750bdd6c6e7a4e7ed1f
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Fri Jul 22 20:00:24 2011 +0200
+
+ OSPF NSSA translator election.
+
+commit 41b612c31be05409e69e7365db82b3d1aefc4ca3
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Jul 20 23:40:20 2011 +0200
+
+ OSPF NSSA support, part one.
+
+commit 9008579b97239564e1dcac855cf726fa9ab7dabd
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Jul 20 23:46:03 2011 +0200
+
+ Fixes broken multi-area OSPF.
+
commit c49490f8c096ef1379f08e7d70cc24f0c28b80ef
Author: Ondrej Zajicek <santiago@crfreenet.org>
Date: Fri Jul 8 08:58:50 2011 +0200
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/NEWS
^
|
@@ -1,4 +1,11 @@
+Version 1.3.3 (2011-09-11)
+ o OSPF NSSA
+ o BGP extended communities
+ o BGP TTL security
+ o Configuration option "include" added (based on patch from Alexander V. Chernikov)
+ o Some minor bugfixes.
+
Version 1.3.2 (2011-07-08)
o Allows run with restricted privileges.
o Community list filter operation.
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/aclocal.m4
^
|
@@ -6,7 +6,8 @@
AC_CHECK_SIZEOF(short int, 0)
AC_CHECK_SIZEOF(int, 0)
AC_CHECK_SIZEOF(long int, 0)
-for size in 1 2 4 ; do
+AC_CHECK_SIZEOF(long long int, 0)
+for size in 1 2 4 8; do
bits=`expr $size "*" 8`
AC_MSG_CHECKING([for $bits-bit type])
if test $ac_cv_sizeof_int = $size ; then
@@ -17,6 +18,8 @@
res="short int"
elif test $ac_cv_sizeof_long_int = $size ; then
res="long int"
+ elif test $ac_cv_sizeof_long_long_int = $size ; then
+ res="long long int"
else
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Cannot find $bits-bit integer type.])
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/conf/cf-lex.l
^
|
@@ -63,19 +63,27 @@
};
static struct sym_scope *conf_this_scope;
-int conf_lino;
+#define MAX_INCLUDE_DEPTH 5
+
+static struct include_file_stack *ifs_head;
+static int ifs_depth;
static int cf_hash(byte *c);
static struct symbol *cf_find_sym(byte *c, unsigned int h0);
linpool *cfg_mem;
-int (*cf_read_hook)(byte *buf, unsigned int max);
+int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
+int (*cf_open_hook)(char *filename);
-#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max);
+#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max, ifs->conf_fd);
#define YY_NO_UNPUT
#define YY_FATAL_ERROR(msg) cf_error(msg)
+static void new_include(void);
+static int check_eof(void);
+static struct include_file_stack *new_stack(struct include_file_stack *old);
+
%}
%option noyywrap
@@ -90,8 +98,10 @@
XIGIT [0-9a-fA-F]
ALNUM [a-zA-Z_0-9]
WHITE [ \t]
+include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
%%
+{include} { if(cf_open_hook) new_include(); }
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
#ifdef IPV6
@@ -188,11 +198,11 @@
["][^"\n]*\n cf_error("Unterminated string");
-<INITIAL,COMMENT><<EOF>> return END;
+<INITIAL,COMMENT><<EOF>> { if(check_eof()) return END; }
{WHITE}+
-\n conf_lino++;
+\n ifs->conf_lino++;
# BEGIN(COMMENT);
@@ -201,14 +211,14 @@
. cf_error("Unknown character");
<COMMENT>\n {
- conf_lino++;
+ ifs->conf_lino++;
BEGIN(INITIAL);
}
<COMMENT>.
<CCOMM>\*\/ BEGIN(INITIAL);
-<CCOMM>\n conf_lino++;
+<CCOMM>\n ifs->conf_lino++;
<CCOMM>\/\* cf_error("Comment nesting not supported");
<CCOMM><<EOF>> cf_error("Unterminated comment");
<CCOMM>.
@@ -234,6 +244,50 @@
return h;
}
+/* Open included file with properly swapped buffers */
+static void
+new_include(void)
+{
+ char *fname, *p = NULL;
+
+ if ((fname = strchr(yytext, '"')) != NULL) {
+
+ if ((p = strchr(++fname, '"')) != NULL) *p = '\0';
+
+ if (ifs_depth >= MAX_INCLUDE_DEPTH)
+ cf_error("Max include depth reached.");
+
+ /* Save current stack */
+ ifs->stack = YY_CURRENT_BUFFER;
+ /* Prepare new stack */
+ ifs->next = new_stack(ifs);
+ ifs = ifs->next;
+ strcpy(ifs->conf_fname, fname); /* XXX: strlcpy should be here */
+ ifs->conf_fd = cf_open_hook(fname);
+
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+ }
+}
+
+static int
+check_eof(void)
+{
+ if (ifs == ifs_head) {
+ /* EOF in main config file */
+ ifs->conf_lino = 1;
+ return 1;
+ }
+
+ ifs_depth--;
+ close(ifs->conf_fd);
+ ifs = ifs->prev;
+ ifs->next = NULL;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(ifs->stack);
+ return 0;
+}
+
static struct symbol *
cf_new_sym(byte *c, unsigned int h)
{
@@ -359,6 +413,16 @@
kw_hash_inited = 1;
}
+static struct include_file_stack *
+new_stack(struct include_file_stack *old)
+{
+ struct include_file_stack *ret;
+ ret = cfg_allocz(sizeof(struct include_file_stack));
+ ret->conf_lino = 1;
+ ret->prev = old;
+ return ret;
+}
+
/**
* cf_lex_init - initialize the lexer
* @is_cli: true if we're going to parse CLI command, false for configuration
@@ -367,11 +431,18 @@
* parsing of a new input.
*/
void
-cf_lex_init(int is_cli)
+cf_lex_init(int is_cli, struct config *c)
{
if (!kw_hash_inited)
cf_lex_init_kh();
- conf_lino = 1;
+ ifs_head = new_stack(NULL);
+ ifs = ifs_head;
+ ifs_depth = 0;
+ if (!is_cli) {
+ ifs->conf_fd = c->file_fd;
+ ifs_depth = 1;
+ strcpy(ifs->conf_fname, c->file_name);
+ }
yyrestart(NULL);
if (is_cli)
BEGIN(CLI);
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/conf/conf.c
^
|
@@ -108,7 +108,7 @@
cfg_mem = c->mem;
if (setjmp(conf_jmpbuf))
return 0;
- cf_lex_init(0);
+ cf_lex_init(0, c);
sysdep_preconfig(c);
protos_preconfig(c);
rt_preconfig(c);
@@ -138,7 +138,7 @@
cfg_mem = c->mem;
if (setjmp(conf_jmpbuf))
return 0;
- cf_lex_init(1);
+ cf_lex_init(1, c);
cf_parse();
return 1;
}
@@ -355,7 +355,8 @@
if (bvsnprintf(buf, sizeof(buf), msg, args) < 0)
strcpy(buf, "<bug: error message too long>");
new_config->err_msg = cfg_strdup(buf);
- new_config->err_lino = conf_lino;
+ new_config->err_lino = ifs->conf_lino;
+ new_config->err_file_name = ifs->conf_fname;
longjmp(conf_jmpbuf, 1);
}
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/conf/conf.h
^
|
@@ -12,6 +12,8 @@
#include "lib/resource.h"
#include "lib/timer.h"
+#define BIRD_FNAME_MAX 255 /* Would be better to use some UNIX define */
+
/* Configuration structure */
struct config {
@@ -38,7 +40,9 @@
int cli_debug; /* Tracing of CLI connections and commands */
char *err_msg; /* Parser error message */
int err_lino; /* Line containing error */
- char *file_name; /* Name of configuration file */
+ char *err_file_name; /* File name containing error */
+ char *file_name; /* Name of main configuration file */
+ int file_fd; /* File descriptor of main configuration file */
struct symbol **sym_hash; /* Lexer: symbol hash table */
struct symbol **sym_fallback; /* Lexer: fallback symbol hash table */
int obstacle_count; /* Number of items blocking freeing of this config */
@@ -83,7 +87,8 @@
/* Lexer */
-extern int (*cf_read_hook)(byte *buf, unsigned int max);
+extern int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
+extern int (*cf_open_hook)(char *filename);
struct symbol {
struct symbol *next;
@@ -106,10 +111,20 @@
#define SYM_VARIABLE 0x100 /* 0x100-0x1ff are variable types */
-extern int conf_lino;
+struct include_file_stack {
+ void *stack; /* Internal lexer state */
+ unsigned int conf_lino; /* Current file lineno (at include) */
+ char conf_fname[BIRD_FNAME_MAX]; /* Current file name */
+ int conf_fd; /* Current file descriptor */
+ struct include_file_stack *prev;
+ struct include_file_stack *next;
+};
+
+struct include_file_stack *ifs;
+
int cf_lex(void);
-void cf_lex_init(int is_cli);
+void cf_lex_init(int is_cli, struct config *c);
struct symbol *cf_find_symbol(byte *c);
struct symbol *cf_default_name(char *template, int *counter);
struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def);
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/configure
^
|
@@ -6993,7 +6993,412 @@
_ACEOF
-for size in 1 2 4 ; do
+{ echo "$as_me:$LINENO: checking for long long int" >&5
+echo $ECHO_N "checking for long long int... $ECHO_C" >&6; }
+if test "${ac_cv_type_long_long_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef long long int ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_long_long_int=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_long_long_int=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_long_long_int" >&5
+echo "${ECHO_T}$ac_cv_type_long_long_int" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of long long int" >&5
+echo $ECHO_N "checking size of long long int... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_long_long_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+ typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+ typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+ typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+ typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+ typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long_long_int=$ac_lo;;
+'') if test "$ac_cv_type_long_long_int" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long long int)
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+ else
+ ac_cv_sizeof_long_long_int=0
+ fi ;;
+esac
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+ typedef long long int ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ return 1;
+ if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+ {
+ long int i = longval ();
+ if (i != ((long int) (sizeof (ac__type_sizeof_))))
+ return 1;
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long int i = ulongval ();
+ if (i != ((long int) (sizeof (ac__type_sizeof_))))
+ return 1;
+ fprintf (f, "%lu\n", i);
+ }
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_long_long_int=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_long_long_int" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long long int)
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+ else
+ ac_cv_sizeof_long_long_int=0
+ fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_long_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int
+_ACEOF
+
+
+for size in 1 2 4 8; do
bits=`expr $size "*" 8`
{ echo "$as_me:$LINENO: checking for $bits-bit type" >&5
echo $ECHO_N "checking for $bits-bit type... $ECHO_C" >&6; }
@@ -7005,6 +7410,8 @@
res="short int"
elif test $ac_cv_sizeof_long_int = $size ; then
res="long int"
+ elif test $ac_cv_sizeof_long_long_int = $size ; then
+ res="long long int"
else
{ echo "$as_me:$LINENO: result: not found" >&5
echo "${ECHO_T}not found" >&6; }
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/doc/bird-3.html
^
|
@@ -59,6 +59,8 @@
<P>
<DL>
+<DT><CODE>include "<I>filename</I>"</CODE><DD><P>This statement causes inclusion of a new file. The maximal depth is set to 5.
+<P>
<DT><CODE>log "<I>filename</I>"|syslog [name <I>name</I>]|stderr all|{ <I>list of classes</I> }</CODE><DD><P>Set logging of messages having the given class (either <CODE>all</CODE> or <CODE>{
error, trace }</CODE> etc.) into selected destination (a file specified as a filename string,
syslog with optional name argument, or the stderr output). Classes are:
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/doc/bird-5.html
^
|
@@ -143,26 +143,44 @@
<CODE>.ip</CODE> which extracts the IP address from the pair, and <CODE>.len</CODE>, which separates prefix
length from the pair. So <CODE>1.2.0.0/16.pxlen = 16</CODE> is true.
<P>
-<DT><CODE>int|pair|quad|ip|prefix|enum set</CODE><DD><P>Filters recognize four types of sets. Sets are similar to strings: you can pass them around
+<DT><CODE>ec</CODE><DD><P>This is a specialized type used to represent BGP
+extended community values. It is essentially a 64bit value,
+literals of this type are usually written as <CODE>(<I>kind</I>,
+<I>key</I>, <I>value</I>)</CODE>, where <CODE>kind</CODE> is a kind of
+extended community (e.g. <CODE>rt</CODE> / <CODE>ro</CODE> for a route
+target / route origin communities), the format and possible
+values of <CODE>key</CODE> and <CODE>value</CODE> are usually integers, but
+it depends on the used kind. Similarly to pairs, ECs can be
+constructed using expressions for <CODE>key</CODE> and
+<CODE>value</CODE> parts, (e.g. <CODE>(ro, myas, 3*10)</CODE>, where
+<CODE>myas</CODE> is an integer variable).
+<P>
+<DT><CODE>int|pair|quad|ip|prefix|ec|enum set</CODE><DD><P>Filters recognize four types of sets. Sets are similar to strings: you can pass them around
but you can't modify them. Literals of type <CODE>int set</CODE> look like <CODE>[ 1, 2, 5..7 ]</CODE>. As you can see, both simple values and ranges are permitted in
sets.
-For pair sets, expressions like <CODE>(123,*)</CODE> can be used to denote ranges (in
+<P>For pair sets, expressions like <CODE>(123,*)</CODE> can be used to denote ranges (in
that case <CODE>(123,0)..(123,65535)</CODE>). You can also use <CODE>(123,5..100)</CODE> for range
<CODE>(123,5)..(123,100)</CODE>. You can also use <CODE>*</CODE> and <CODE>a..b</CODE> expressions
in the first part of a pair, note that such expressions are translated to a set
of intervals, which may be memory intensive. E.g. <CODE>(*,4..20)</CODE> is translated to
<CODE>(0,4..20), (1,4..20), (2,4..20), ... (65535, 4..20)</CODE>.
-You can also use expressions for both, pair sets and int sets. However it must
+<P>EC sets use similar expressions like pair sets, e.g. <CODE>(rt, 123, 10..20)</CODE>
+or <CODE>(ro, 123, *)</CODE>. Expressions requiring the translation (like <CODE>(rt, *, 3)</CODE>)
+are not allowed (as they usually have 4B range for ASNs).
+<P>You can also use expressions for int, pair and EC set values. However it must
be possible to evaluate these expressions before daemon boots. So you can use
only constants inside them. E.g.
<HR>
<PRE>
define one=1;
+ define myas=64500;
int set odds;
pair set ps;
+ ec set es;
- odds = [ one, (2+1), (6-one), (2*2*2-1), 9, 11 ];
+ odds = [ one, 2+1, 6-one, 2*2*2-1, 9, 11 ];
ps = [ (1,one+one), (3,4)..(4,8), (5,*), (6,3..6), (7..9,*) ];
+ es = [ (rt, myas, 3*10), (rt, myas+one, 0..16*16*16-1), (ro, myas+2, *) ];
</PRE>
<HR>
@@ -220,7 +238,7 @@
<DT><CODE>clist</CODE><DD><P>Clist is similar to a set, except that unlike other sets, it
can be modified. The type is used for community list (a set
of pairs) and for cluster list (a set of quads). There exist
-no literals of this type. There are two special operators on
+no literals of this type. There are three special operators on
clists:
<P><CODE>add(<I>C</I>,<I>P</I>)</CODE> adds pair (or quad) <I>P</I> to clist
<I>C</I> and returns the result. If item <I>P</I> is already in
@@ -239,6 +257,13 @@
<CODE><I>C</I>.add(<I>P</I>);</CODE> if <I>C</I> is appropriate route
attribute (for example <CODE>bgp_community</CODE>). Similarly for
<CODE>delete</CODE> and <CODE>filter</CODE>.
+<P>
+<DT><CODE>eclist</CODE><DD><P>Eclist is a data type used for BGP extended community lists.
+Eclists are very similar to clists, but they are sets of ECs
+instead of pairs. The same operations (like <CODE>add</CODE>,
+<CODE>delete</CODE>, or <CODE>~</CODE> membership operator) can be
+used to modify or test eclists, with ECs instead of pairs as
+arguments.
</DL>
<P>
<H2><A NAME="ss5.3">5.3</A> <A HREF="bird.html#toc5.3">Operators</A>
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/doc/bird-6.html
^
|
@@ -52,15 +52,21 @@
MD5 password authentication
(RFC 2385
<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc2385.txt">ftp://ftp.rfc-editor.org/in-notes/rfc2385.txt</A>),
+extended communities
+(RFC 4360
+<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc4360.txt">ftp://ftp.rfc-editor.org/in-notes/rfc4360.txt</A>),
route reflectors
(RFC 4456
<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc4456.txt">ftp://ftp.rfc-editor.org/in-notes/rfc4456.txt</A>),
multiprotocol extensions
(RFC 4760
<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc4760.txt">ftp://ftp.rfc-editor.org/in-notes/rfc4760.txt</A>),
-and 4B AS numbers
+4B AS numbers
(RFC 4893
-<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc4893.txt">ftp://ftp.rfc-editor.org/in-notes/rfc4893.txt</A>).
+<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc4893.txt">ftp://ftp.rfc-editor.org/in-notes/rfc4893.txt</A>),
+and 4B AS numbers in extended communities
+(RFC 5668
+<A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc5668.txt">ftp://ftp.rfc-editor.org/in-notes/rfc5668.txt</A>).
<P>
<P>For IPv6, it uses the standard multiprotocol extensions defined in
RFC 2283
@@ -131,9 +137,11 @@
subnets. Such IP address have to be reachable through system
routing table. For multihop BGP it is recommended to
explicitly configure <CODE>source address</CODE> to have it
-stable. Optional <CODE>number</CODE> argument can be used to limit TTL
-(the number of hops).
-Default: switched off.
+stable. Optional <CODE>number</CODE> argument can be used to specify
+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 separated by one router, the number of hops is
+2. Default: switched off.
<P>
<DT><CODE>source address <I>ip</I></CODE><DD><P>Define local address we
should use for next hop calculation and as a source address
@@ -180,6 +188,18 @@
as an IGP routing table. Default: the same as the table BGP is
connected to.
<P>
+<DT><CODE>ttl security <I>switch</I></CODE><DD><P>Use GTSM (RFC 5082 - the
+generalized TTL security mechanism). GTSM protects against
+spoofed packets by ignoring received packets with a smaller
+than expected TTL. To work properly, GTSM have to be enabled
+on both sides of a BGP session. If both <CODE>ttl security</CODE> and
+<CODE>multihop</CODE> options are enabled, <CODE>multihop</CODE> option should
+specify proper hop value to compute expected TTL. Kernel
+support required: Linux: 2.6.34+ (IPv4), 2.6.35+ (IPv6), BSD:
+since long ago, IPv4 only. Note that full (ICMP protection,
+for example) RFC 5082 support is provided by Linux
+only. Default: disabled.
+<P>
<DT><CODE>password <I>string</I></CODE><DD><P>Use this password for MD5 authentication
of BGP sessions. Default: no authentication. Password has to be set by
external utility (e.g. setkey(8)) on BSD systems.
@@ -373,6 +393,12 @@
its own routing policy, it also has a complete freedom about which community
attributes it defines and what will their semantics be.
<P>
+<DT><CODE>eclist <CODE>bgp_ext_community</CODE> [O]</CODE><DD><P>List of extended community
+values associated with the route. Extended communities have similar usage
+as plain communities, but they have an extended range (to allow 4B ASNs)
+and a nontrivial structure with a type field. Individual community values are
+represented using an <CODE>ec</CODE> data type inside the filters.
+<P>
<DT><CODE>quad <CODE>bgp_originator_id</CODE> [I, O]</CODE><DD><P>This attribute is created by the
route reflector when reflecting the route and contains the router ID of the
originator of the route in the local AS.
@@ -665,11 +691,24 @@
tick <num>;
ecmp <switch> [limit <num>];
area <id> {
- stub cost <num>;
+ stub;
+ nssa;
+ summary <switch>;
+ default nssa <switch>;
+ default cost <num>;
+ default cost2 <num>;
+ translator <switch>;
+ translator stability <num>;
+
networks {
<prefix>;
<prefix> hidden;
}
+ external {
+ <prefix>;
+ <prefix> hidden;
+ <prefix> tag <num>;
+ }
stubnet <prefix>;
stubnet <prefix> {
hidden <switch>;
@@ -743,13 +782,58 @@
address, similarly to a router ID). The most important area is
the backbone (ID 0) to which every other area must be connected.
<P>
-<DT><CODE>stub cost <I>num</I></CODE><DD><P>No external (except default) routes are flooded into stub areas.
-Setting this value marks area stub with defined cost of default route.
-Default value is no. (Area is not stub.)
+<DT><CODE>stub</CODE><DD><P>This option configures the area to be a stub area. External
+routes are not flooded into stub areas. Also summary LSAs can be
+limited in stub areas (see option <CODE>summary</CODE>).
+By default, the area is not a stub area.
+<P>
+<DT><CODE>nssa</CODE><DD><P>This option configures the area to be a NSSA (Not-So-Stubby
+Area). NSSA is a variant of a stub area which allows a
+limited way of external route propagation. Global external
+routes are not propagated into a NSSA, but an external route
+can be imported into NSSA as a (area-wide) NSSA-LSA (and
+possibly translated and/or aggregated on area boundary).
+By default, the area is not NSSA.
+<P>
+<DT><CODE>summary <I>switch</I></CODE><DD><P>This option controls propagation of summary LSAs into stub or
+NSSA areas. If enabled, summary LSAs are propagated as usual,
+otherwise just the default summary route (0.0.0.0/0) is
+propagated (this is sometimes called totally stubby area). If
+a stub area has more area boundary routers, propagating
+summary LSAs could lead to more efficient routing at the cost
+of larger link state database. Default value is no.
+<P>
+<DT><CODE>default nssa <I>switch</I></CODE><DD><P>When <CODE>summary</CODE> option is enabled, default summary route is
+no longer propagated to the NSSA. In that case, this option
+allows to originate default route as NSSA-LSA to the NSSA.
+Default value is no.
+<P>
+<DT><CODE>default cost <I>num</I></CODE><DD><P>This option controls the cost of a default route propagated to
+stub and NSSA areas. Default value is 1000.
+<P>
+<DT><CODE>default cost2 <I>num</I></CODE><DD><P>When a default route is originated as NSSA-LSA, its cost
+can use either type 1 or type 2 metric. This option allows
+to specify the cost of a default route in type 2 metric.
+By default, type 1 metric (option <CODE>default cost</CODE>) is used.
+<P>
+<DT><CODE>translator <I>switch</I></CODE><DD><P>This option controls translation of NSSA-LSAs into external
+LSAs. By default, one translator per NSSA is automatically
+elected from area boundary routers. If enabled, this area
+boundary router would unconditionally translate all NSSA-LSAs
+regardless of translator election. Default value is no.
+<P>
+<DT><CODE>translator stability <I>num</I></CODE><DD><P>This option controls the translator stability interval (in
+seconds). When the new translator is elected, the old one
+keeps translating until the interval is over. Default value
+is 40.
<P>
<DT><CODE>networks { <I>set</I> }</CODE><DD><P>Definition of area IP ranges. This is used in summary LSA origination.
Hidden networks are not propagated into other areas.
<P>
+<DT><CODE>external { <I>set</I> }</CODE><DD><P>Definition of external area IP ranges for NSSAs. This is used
+for NSSA-LSA translation. Hidden networks are not translated
+into external LSAs. Networks can have configured route tag.
+<P>
<DT><CODE>stubnet <I>prefix</I> { <I>options</I> }</CODE><DD><P>Stub networks are networks that are not transit networks
between OSPF routers. They are also propagated through an
OSPF area as a part of a link state database. By default,
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/doc/bird.conf.example
^
|
@@ -25,6 +25,8 @@
#filter sink { reject; }
#filter okay { accept; }
+#include "filters.conf";
+
# Define another routing table
#table testable;
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/doc/bird.sgml
^
|
@@ -259,6 +259,9 @@
<sect>Global options
<p><descrip>
+ <tag>include "<m/filename/"</tag>
+ This statement causes inclusion of a new file. The maximal depth is set to 5.
+
<tag>log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag>
Set logging of messages having the given class (either <cf/all/ or <cf/{
error, trace }/ etc.) into selected destination (a file specified as a filename string,
@@ -746,27 +749,48 @@
<cf/.ip/ which extracts the IP address from the pair, and <cf/.len/, which separates prefix
length from the pair. So <cf>1.2.0.0/16.pxlen = 16</cf> is true.
- <tag/int|pair|quad|ip|prefix|enum set/
+ <tag/ec/ This is a specialized type used to represent BGP
+ extended community values. It is essentially a 64bit value,
+ literals of this type are usually written as <cf>(<m/kind/,
+ <m/key/, <m/value/)</cf>, where <cf/kind/ is a kind of
+ extended community (e.g. <cf/rt/ / <cf/ro/ for a route
+ target / route origin communities), the format and possible
+ values of <cf/key/ and <cf/value/ are usually integers, but
+ it depends on the used kind. Similarly to pairs, ECs can be
+ constructed using expressions for <cf/key/ and
+ <cf/value/ parts, (e.g. <cf/(ro, myas, 3*10)/, where
+ <cf/myas/ is an integer variable).
+
+ <tag/int|pair|quad|ip|prefix|ec|enum set/
Filters recognize four types of sets. Sets are similar to strings: you can pass them around
but you can't modify them. Literals of type <cf>int set</cf> look like <cf>
[ 1, 2, 5..7 ]</cf>. As you can see, both simple values and ranges are permitted in
sets.
+
For pair sets, expressions like <cf/(123,*)/ can be used to denote ranges (in
that case <cf/(123,0)..(123,65535)/). You can also use <cf/(123,5..100)/ for range
<cf/(123,5)..(123,100)/. You can also use <cf/*/ and <cf/a..b/ expressions
in the first part of a pair, note that such expressions are translated to a set
of intervals, which may be memory intensive. E.g. <cf/(*,4..20)/ is translated to
<cf/(0,4..20), (1,4..20), (2,4..20), ... (65535, 4..20)/.
- You can also use expressions for both, pair sets and int sets. However it must
+
+ EC sets use similar expressions like pair sets, e.g. <cf/(rt, 123, 10..20)/
+ or <cf/(ro, 123, *)/. Expressions requiring the translation (like <cf/(rt, *, 3)/)
+ are not allowed (as they usually have 4B range for ASNs).
+
+ You can also use expressions for int, pair and EC set values. However it must
be possible to evaluate these expressions before daemon boots. So you can use
only constants inside them. E.g.
<code>
define one=1;
+ define myas=64500;
int set odds;
pair set ps;
+ ec set es;
- odds = [ one, (2+1), (6-one), (2*2*2-1), 9, 11 ];
+ odds = [ one, 2+1, 6-one, 2*2*2-1, 9, 11 ];
ps = [ (1,one+one), (3,4)..(4,8), (5,*), (6,3..6), (7..9,*) ];
+ es = [ (rt, myas, 3*10), (rt, myas+one, 0..16*16*16-1), (ro, myas+2, *) ];
</code>
Sets of prefixes are special: their literals does not allow ranges, but allows
@@ -835,7 +859,7 @@
Clist is similar to a set, except that unlike other sets, it
can be modified. The type is used for community list (a set
of pairs) and for cluster list (a set of quads). There exist
- no literals of this type. There are two special operators on
+ no literals of this type. There are three special operators on
clists:
<cf>add(<m/C/,<m/P/)</cf> adds pair (or quad) <m/P/ to clist
@@ -858,6 +882,14 @@
<cf><m/C/.add(<m/P/);</cf> if <m/C/ is appropriate route
attribute (for example <cf/bgp_community/). Similarly for
<cf/delete/ and <cf/filter/.
+
+ <tag/eclist/
+ Eclist is a data type used for BGP extended community lists.
+ Eclists are very similar to clists, but they are sets of ECs
+ instead of pairs. The same operations (like <cf/add/,
+ <cf/delete/, or <cf/˜/ membership operator) can be
+ used to modify or test eclists, with ECs instead of pairs as
+ arguments.
</descrip>
<sect>Operators
@@ -1013,12 +1045,16 @@
(RFC 3392<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc3392.txt">),
MD5 password authentication
(RFC 2385<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc2385.txt">),
+extended communities
+(RFC 4360<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4360.txt">),
route reflectors
(RFC 4456<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4456.txt">),
multiprotocol extensions
(RFC 4760<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4760.txt">),
-and 4B AS numbers
-(RFC 4893<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4893.txt">).
+4B AS numbers
+(RFC 4893<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4893.txt">),
+and 4B AS numbers in extended communities
+(RFC 5668<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc5668.txt">).
For IPv6, it uses the standard multiprotocol extensions defined in
@@ -1087,9 +1123,11 @@
subnets. Such IP address have to be reachable through system
routing table. For multihop BGP it is recommended to
explicitly configure <cf/source address/ to have it
- stable. Optional <cf/number/ argument can be used to limit TTL
- (the number of hops).
- Default: switched off.
+ stable. Optional <cf/number/ argument can be used to specify
+ 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 separated by one router, the number of hops is
+ 2. Default: switched off.
<tag>source address <m/ip/</tag> Define local address we
should use for next hop calculation and as a source address
@@ -1136,6 +1174,18 @@
as an IGP routing table. Default: the same as the table BGP is
connected to.
+ <tag>ttl security <m/switch/</tag> Use GTSM (RFC 5082 - the
+ generalized TTL security mechanism). GTSM protects against
+ spoofed packets by ignoring received packets with a smaller
+ than expected TTL. To work properly, GTSM have to be enabled
+ on both sides of a BGP session. If both <cf/ttl security/ and
+ <cf/multihop/ options are enabled, <cf/multihop/ option should
+ specify proper hop value to compute expected TTL. Kernel
+ support required: Linux: 2.6.34+ (IPv4), 2.6.35+ (IPv6), BSD:
+ since long ago, IPv4 only. Note that full (ICMP protection,
+ for example) RFC 5082 support is provided by Linux
+ only. Default: disabled.
+
<tag>password <m/string/</tag> Use this password for MD5 authentication
of BGP sessions. Default: no authentication. Password has to be set by
external utility (e.g. setkey(8)) on BSD systems.
@@ -1331,6 +1381,12 @@
its own routing policy, it also has a complete freedom about which community
attributes it defines and what will their semantics be.
+ <tag>eclist <cf/bgp_ext_community/ [O]</tag> List of extended community
+ values associated with the route. Extended communities have similar usage
+ as plain communities, but they have an extended range (to allow 4B ASNs)
+ and a nontrivial structure with a type field. Individual community values are
+ represented using an <cf/ec/ data type inside the filters.
+
<tag>quad <cf/bgp_originator_id/ [I, O]</tag> This attribute is created by the
route reflector when reflecting the route and contains the router ID of the
originator of the route in the local AS.
@@ -1602,11 +1658,24 @@
tick <num>;
ecmp <switch> [limit <num>];
area <id> {
- stub cost <num>;
+ stub;
+ nssa;
+ summary <switch>;
+ default nssa <switch>;
+ default cost <num>;
+ default cost2 <num>;
+ translator <switch>;
+ translator stability <num>;
+
networks {
<prefix>;
<prefix> hidden;
}
+ external {
+ <prefix>;
+ <prefix> hidden;
+ <prefix> tag <num>;
+ }
stubnet <prefix>;
stubnet <prefix> {
hidden <switch>;
@@ -1683,15 +1752,68 @@
address, similarly to a router ID). The most important area is
the backbone (ID 0) to which every other area must be connected.
- <tag>stub cost <M>num</M></tag>
- No external (except default) routes are flooded into stub areas.
- Setting this value marks area stub with defined cost of default route.
- Default value is no. (Area is not stub.)
+ <tag>stub</tag>
+ This option configures the area to be a stub area. External
+ routes are not flooded into stub areas. Also summary LSAs can be
+ limited in stub areas (see option <cf/summary/).
+ By default, the area is not a stub area.
+
+ <tag>nssa</tag>
+ This option configures the area to be a NSSA (Not-So-Stubby
+ Area). NSSA is a variant of a stub area which allows a
+ limited way of external route propagation. Global external
+ routes are not propagated into a NSSA, but an external route
+ can be imported into NSSA as a (area-wide) NSSA-LSA (and
+ possibly translated and/or aggregated on area boundary).
+ By default, the area is not NSSA.
+
+ <tag>summary <M>switch</M></tag>
+ This option controls propagation of summary LSAs into stub or
+ NSSA areas. If enabled, summary LSAs are propagated as usual,
+ otherwise just the default summary route (0.0.0.0/0) is
+ propagated (this is sometimes called totally stubby area). If
+ a stub area has more area boundary routers, propagating
+ summary LSAs could lead to more efficient routing at the cost
+ of larger link state database. Default value is no.
+
+ <tag>default nssa <M>switch</M></tag>
+ When <cf/summary/ option is enabled, default summary route is
+ no longer propagated to the NSSA. In that case, this option
+ allows to originate default route as NSSA-LSA to the NSSA.
+ Default value is no.
+
+ <tag>default cost <M>num</M></tag>
+ This option controls the cost of a default route propagated to
+ stub and NSSA areas. Default value is 1000.
+
+ <tag>default cost2 <M>num</M></tag>
+ When a default route is originated as NSSA-LSA, its cost
+ can use either type 1 or type 2 metric. This option allows
+ to specify the cost of a default route in type 2 metric.
+ By default, type 1 metric (option <cf/default cost/) is used.
+
+ <tag>translator <M>switch</M></tag>
+ This option controls translation of NSSA-LSAs into external
+ LSAs. By default, one translator per NSSA is automatically
+ elected from area boundary routers. If enabled, this area
+ boundary router would unconditionally translate all NSSA-LSAs
+ regardless of translator election. Default value is no.
+
+ <tag>translator stability <M>num</M></tag>
+ This option controls the translator stability interval (in
+ seconds). When the new translator is elected, the old one
+ keeps translating until the interval is over. Default value
+ is 40.
<tag>networks { <m/set/ }</tag>
Definition of area IP ranges. This is used in summary LSA origination.
Hidden networks are not propagated into other areas.
+ <tag>external { <m/set/ }</tag>
+ Definition of external area IP ranges for NSSAs. This is used
+ for NSSA-LSA translation. Hidden networks are not translated
+ into external LSAs. Networks can have configured route tag.
+
<tag>stubnet <m/prefix/ { <m/options/ }</tag>
Stub networks are networks that are not transit networks
between OSPF routers. They are also propagated through an
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/doc/prog-3.html
^
|
@@ -242,12 +242,13 @@
<HR><H3>Function</H3>
<P><I>void</I>
<B>cf_lex_init</B>
-(<I>int</I> <B>is_cli</B>) -- initialize the lexer
+(<I>int</I> <B>is_cli</B>, <I>struct config *</I> <B>c</B>) -- initialize the lexer
<P>
<H3>Arguments</H3>
<P>
<DL>
<DT><I>int</I> <B>is_cli</B><DD><P>true if we're going to parse CLI command, false for configuration
+<DT><I>struct config *</I> <B>c</B><DD><P>-- undescribed --
</DL>
<H3>Description</H3>
<P><B>cf_lex_init()</B> initializes the lexical analyzer and prepares it for
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/doc/prog-5.html
^
|
@@ -442,7 +442,7 @@
<HR><H3>Function</H3>
<P><I>void</I>
<B>ospf_disp</B>
-(<I>timer *</I> <B>timer</B>) -- invokes routing table calctulation, aging and also <B>area_disp()</B>
+(<I>timer *</I> <B>timer</B>) -- invokes routing table calculation, aging and also <B>area_disp()</B>
<P>
<H3>Arguments</H3>
<P>
@@ -542,19 +542,25 @@
<HR><H3>Function</H3>
<P><I>void</I>
<B>originate_ext_lsa</B>
-(<I>net *</I> <B>n</B>, <I>rte *</I> <B>e</B>, <I>struct proto_ospf *</I> <B>po</B>, <I>struct ea_list *</I> <B>attrs</B>) -- new route received from nest and filters
+(<I>struct ospf_area *</I> <B>oa</B>, <I>struct fib_node *</I> <B>fn</B>, <I>int</I> <B>src</B>, <I>u32</I> <B>metric</B>, <I>ip_addr</I> <B>fwaddr</B>, <I>u32</I> <B>tag</B>, <I>int</I> <B>pbit</B>) -- new route received from nest and filters
<P>
<H3>Arguments</H3>
<P>
<DL>
-<DT><I>net *</I> <B>n</B><DD><P>network prefix and mask
-<DT><I>rte *</I> <B>e</B><DD><P>rte
-<DT><I>struct proto_ospf *</I> <B>po</B><DD><P>current instance of OSPF
-<DT><I>struct ea_list *</I> <B>attrs</B><DD><P>list of extended attributes
+<DT><I>struct ospf_area *</I> <B>oa</B><DD><P>ospf_area for which LSA is originated
+<DT><I>struct fib_node *</I> <B>fn</B><DD><P>network prefix and mask
+<DT><I>int</I> <B>src</B><DD><P>the source of origination of the LSA (EXT_EXPORT/EXT_NSSA)
+<DT><I>u32</I> <B>metric</B><DD><P>the metric of a route
+<DT><I>ip_addr</I> <B>fwaddr</B><DD><P>the forwarding address
+<DT><I>u32</I> <B>tag</B><DD><P>the route tag
+<DT><I>int</I> <B>pbit</B><DD><P>P-bit for NSSA LSAs, ignored for external LSAs
</DL>
<H3>Description</H3>
<P>If I receive a message that new route is installed, I try to originate an
-external LSA.
+external LSA. If <B>oa</B> is an NSSA area, NSSA-LSA is originated instead.
+<B>oa</B> should not be a stub area. <B>src</B> does not specify whether the LSA
+is external or NSSA, but it specifies the source of origination -
+the export from <B>ospf_rt_notify()</B>, or the NSSA-EXT translation.
<P>The function also sets flag ebit. If it's the first time, the new router lsa
origination is necessary.
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/doc/prog-8.html
^
|
@@ -656,7 +656,7 @@
<HR><H3>Function</H3>
<P><I>int</I>
<B>sk_set_ttl</B>
-(<I>sock *</I> <B>s</B>, <I>int</I> <B>ttl</B>) -- set TTL for given socket.
+(<I>sock *</I> <B>s</B>, <I>int</I> <B>ttl</B>) -- set transmit TTL for given socket.
<P>
<H3>Arguments</H3>
<P>
@@ -671,6 +671,23 @@
<H3>Result</H3>
<P>0 for success, -1 for an error.
+
+<HR><H3>Function</H3>
+<P><I>int</I>
+<B>sk_set_min_ttl</B>
+(<I>sock *</I> <B>s</B>, <I>int</I> <B>ttl</B>) -- set minimal accepted TTL for given socket.
+<P>
+<H3>Arguments</H3>
+<P>
+<DL>
+<DT><I>sock *</I> <B>s</B><DD><P>socket
+<DT><I>int</I> <B>ttl</B><DD><P>TTL value
+</DL>
+<H3>Description</H3>
+<P>Can be used in TTL security implementation
+<H3>Result</H3>
+<P>0 for success, -1 for an error.
+
<HR><H3>Function</H3>
<P><I>int</I>
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/filter/config.Y
^
|
@@ -75,13 +75,185 @@
return lst;
}
+#define EC_ALL 0xFFFFFFFF
+
+static struct f_tree *
+f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt)
+{
+ u64 fm, to;
+
+ if (ipv4_used || (key >= 0x10000)) {
+ check_u16(vf);
+ if (vt == EC_ALL)
+ vt = 0xFFFF;
+ else
+ check_u16(vt);
+ }
+
+ if (kind == EC_GENERIC) {
+ fm = ec_generic(key, vf);
+ to = ec_generic(key, vt);
+ }
+ else if (ipv4_used) {
+ fm = ec_ip4(kind, key, vf);
+ to = ec_ip4(kind, key, vt);
+ }
+ else if (key < 0x10000) {
+ fm = ec_as2(kind, key, vf);
+ to = ec_as2(kind, key, vt);
+ }
+ else {
+ fm = ec_as4(kind, key, vf);
+ to = ec_as4(kind, key, vt);
+ }
+
+ struct f_tree *t = f_new_tree();
+ t->right = t;
+ t->from.type = t->to.type = T_EC;
+ t->from.val.ec = fm;
+ t->to.val.ec = to;
+ return t;
+}
+
+static inline struct f_inst *
+f_generate_empty(struct f_inst *dyn)
+{
+ struct f_inst *e = f_new_inst();
+ e->code = 'E';
+
+ switch (dyn->aux & EAF_TYPE_MASK) {
+ case EAF_TYPE_AS_PATH:
+ e->aux = T_PATH;
+ break;
+ case EAF_TYPE_INT_SET:
+ e->aux = T_CLIST;
+ break;
+ case EAF_TYPE_EC_SET:
+ e->aux = T_ECLIST;
+ break;
+ default:
+ cf_error("Can't empty that attribute");
+ }
+
+ dyn->code = P('e','S');
+ dyn->a1.p = e;
+ return dyn;
+}
+
+
+static inline struct f_inst *
+f_generate_dpair(struct f_inst *t1, struct f_inst *t2)
+{
+ struct f_inst *rv;
+
+ if ((t1->code == 'c') && (t2->code == 'c')) {
+ if ((t1->aux != T_INT) || (t2->aux != T_INT))
+ cf_error( "Can't operate with value of non-integer type in pair constructor");
+
+ check_u16(t1->a2.i);
+ check_u16(t2->a2.i);
+
+ rv = f_new_inst();
+ rv->code = 'c';
+ rv->aux = T_PAIR;
+ rv->a2.i = pair(t1->a2.i, t2->a2.i);
+ }
+ else {
+ rv = f_new_inst();
+ rv->code = P('m', 'p');
+ rv->a1.p = t1;
+ rv->a2.p = t2;
+ }
+
+ return rv;
+}
+
+static inline struct f_inst *
+f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
+{
+ struct f_inst *rv;
+ int c1 = 0, c2 = 0, ipv4_used = 0;
+ u32 key = 0, val2 = 0;
+
+ if (tk->code == 'c') {
+ c1 = 1;
+
+ if (tk->aux == T_INT) {
+ ipv4_used = 0; key = tk->a2.i;
+ }
+ else if (tk->aux == T_QUAD) {
+ ipv4_used = 1; key = tk->a2.i;
+ }
+ else
+ cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
+ }
+
+#ifndef IPV6
+ /* IP->Quad implicit conversion */
+ else if (tk->code == 'C') {
+ c1 = 1;
+ struct f_val *val = tk->a1.p;
+ if (val->type == T_IP) {
+ ipv4_used = 1; key = ipa_to_u32(val->val.px.ip);
+ }
+ else
+ cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
+ }
+#endif
+
+ if (tv->code == 'c') {
+ if (tv->aux != T_INT)
+ cf_error("Can't operate with value of non-integer type in EC constructor");
+ c2 = 1;
+ val2 = tv->a2.i;
+ }
+
+ if (c1 && c2) {
+ u64 ec;
+
+ if (kind == EC_GENERIC) {
+ ec = ec_generic(key, val2);
+ }
+ else if (ipv4_used) {
+ check_u16(val2);
+ ec = ec_ip4(kind, key, val2);
+ }
+ else if (key < 0x10000) {
+ ec = ec_as2(kind, key, val2);
+ }
+ else {
+ check_u16(val2);
+ ec = ec_as4(kind, key, val2);
+ }
+
+ NEW_F_VAL;
+ rv = f_new_inst();
+ rv->code = 'C';
+ rv->a1.p = val;
+ val->type = T_EC;
+ val->val.ec = ec;
+ }
+ else {
+ rv = f_new_inst();
+ rv->code = P('m','c');
+ rv->aux = kind;
+ rv->a1.p = tk;
+ rv->a2.p = tv;
+ }
+
+ return rv;
+};
+
+
+
CF_DECLS
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ACCEPT, REJECT, ERROR, QUITBIRD,
- INT, BOOL, IP, PREFIX, PAIR, QUAD, SET, STRING, BGPMASK, BGPPATH, CLIST,
+ INT, BOOL, IP, PREFIX, PAIR, QUAD, EC,
+ SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST,
IF, THEN, ELSE, CASE,
- TRUE, FALSE,
+ TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, PREFERENCE,
LEN,
DEFINED,
@@ -93,11 +265,11 @@
%nonassoc THEN
%nonassoc ELSE
-%type <x> term block cmds cmds_int cmd function_body constant print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol dpair bgp_path_expr
+%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr
%type <f> filter filter_body where_filter
-%type <i> type break_command pair_expr
-%type <i32> pair_atom
-%type <e> pair_item set_item switch_item set_items switch_items switch_body
+%type <i> type break_command pair_expr ec_kind
+%type <i32> pair_atom ec_expr
+%type <e> pair_item ec_item set_item switch_item set_items switch_items switch_body
%type <trie> fprefix_set
%type <v> set_atom switch_atom fprefix fprefix_s fipa
%type <s> decls declsn one_decl function_params
@@ -128,15 +300,18 @@
| PREFIX { $$ = T_PREFIX; }
| PAIR { $$ = T_PAIR; }
| QUAD { $$ = T_QUAD; }
+ | EC { $$ = T_EC; }
| STRING { $$ = T_STRING; }
| BGPMASK { $$ = T_PATH_MASK; }
| BGPPATH { $$ = T_PATH; }
| CLIST { $$ = T_CLIST; }
+ | ECLIST { $$ = T_ECLIST; }
| type SET {
switch ($1) {
case T_INT:
case T_PAIR:
case T_QUAD:
+ case T_EC:
case T_IP:
$$ = T_SET;
break;
@@ -324,14 +499,32 @@
}
;
+ec_expr:
+ term { $$ = f_eval_int($1); }
+
+ec_kind:
+ RT { $$ = EC_RT; }
+ | RO { $$ = EC_RO; }
+ | UNKNOWN NUM { $$ = $2; }
+ | GENERIC { $$ = EC_GENERIC; }
+ ;
+
+ec_item:
+ '(' ec_kind ',' ec_expr ',' ec_expr ')' { $$ = f_new_ec_item($2, 0, $4, $6, $6); }
+ | '(' ec_kind ',' ec_expr ',' ec_expr DDOT ec_expr ')' { $$ = f_new_ec_item($2, 0, $4, $6, $8); }
+ | '(' ec_kind ',' ec_expr ',' '*' ')' { $$ = f_new_ec_item($2, 0, $4, 0, EC_ALL); }
+ ;
+
set_item:
pair_item
+ | ec_item
| set_atom { $$ = f_new_item($1, $1); }
| set_atom DDOT set_atom { $$ = f_new_item($1, $3); }
;
switch_item:
pair_item
+ | ec_item
| switch_atom { $$ = f_new_item($1, $1); }
| switch_atom DDOT switch_atom { $$ = f_new_item($1, $3); }
;
@@ -411,20 +604,6 @@
| { $$ = NULL; }
;
-dpair:
- '(' term ',' term ')' {
- if (($2->code == 'c') && ($4->code == 'c'))
- {
- if (($2->aux != T_INT) || ($4->aux != T_INT))
- cf_error( "Can't operate with value of non-integer type in pair constructor" );
- check_u16($2->a2.i); check_u16($4->a2.i);
- $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR; $$->a2.i = pair($2->a2.i, $4->a2.i);
- }
- else
- { $$ = f_new_inst(); $$->code = P('m', 'p'); $$->a1.p = $2; $$->a2.p = $4; }
- }
- ;
-
constant:
NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $1; }
| TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; }
@@ -439,6 +618,11 @@
| bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; }
;
+constructor:
+ '(' term ',' term ')' { $$ = f_generate_dpair($2, $4); };
+ | '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); };
+ ;
+
/*
* Maybe there are no dynamic attributes defined by protocols.
@@ -490,6 +674,7 @@
case SYM_VARIABLE | T_INT:
case SYM_VARIABLE | T_PAIR:
case SYM_VARIABLE | T_QUAD:
+ case SYM_VARIABLE | T_EC:
case SYM_VARIABLE | T_STRING:
case SYM_VARIABLE | T_IP:
case SYM_VARIABLE | T_PREFIX:
@@ -498,6 +683,7 @@
case SYM_VARIABLE | T_PATH:
case SYM_VARIABLE | T_PATH_MASK:
case SYM_VARIABLE | T_CLIST:
+ case SYM_VARIABLE | T_ECLIST:
$$->code = 'V';
$$->a1.p = $1->def;
$$->a2.p = $1->name;
@@ -539,7 +725,7 @@
| symbol { $$ = $1; }
| constant { $$ = $1; }
- | dpair { $$ = $1; }
+ | constructor { $$ = $1; }
| PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; }
@@ -563,6 +749,7 @@
| '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; }
| '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; }
+ | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_ECLIST; }
| PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; }
| ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; }
| DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
@@ -702,12 +889,11 @@
}
- | rtadot dynamic_attr '.' EMPTY ';'
- { struct f_inst *i = f_new_inst(); i->code = 'E'; i->aux = T_CLIST; $$ = $2; $$->code = P('e','S'); $$->a1.p = i; }
+ | rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); }
| rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); }
- | rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); }
- | rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); }
- | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); }
+ | rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); }
+ | rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); }
+ | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); }
;
CF_END
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/filter/f-util.c
^
|
@@ -19,7 +19,7 @@
ret = cfg_alloc(sizeof(struct f_inst));
ret->code = ret->aux = 0;
ret->arg1 = ret->arg2 = ret->next = NULL;
- ret->lineno = conf_lino;
+ ret->lineno = ifs->conf_lino;
return ret;
}
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/filter/filter.c
^
|
@@ -51,10 +51,10 @@
#define CMP_ERROR 999
static struct adata *
-adata_empty(struct linpool *pool)
+adata_empty(struct linpool *pool, int l)
{
- struct adata *res = lp_alloc(pool, sizeof(struct adata));
- res->length = 0;
+ struct adata *res = lp_alloc(pool, sizeof(struct adata) + l);
+ res->length = l;
return res;
}
@@ -126,6 +126,13 @@
else return 1;
}
+static inline int u64_cmp(u64 i1, u64 i2)
+{
+ if (i1 == i2) return 0;
+ if (i1 < i2) return -1;
+ else return 1;
+}
+
/**
* val_compare - compare two values
* @v1: first value
@@ -167,6 +174,8 @@
case T_PAIR:
case T_QUAD:
return uint_cmp(v1.val.i, v2.val.i);
+ case T_EC:
+ return u64_cmp(v1.val.ec, v2.val.ec);
case T_IP:
return ipa_compare(v1.val.px.ip, v2.val.px.ip);
case T_PREFIX:
@@ -226,6 +235,9 @@
if ((v1.type == T_IP) && (v2.type == T_CLIST))
return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
#endif
+ if ((v1.type == T_EC) && (v2.type == T_ECLIST))
+ return ec_set_contains(v2.val.ad, v1.val.ec);
+
if ((v1.type == T_STRING) && (v2.type == T_STRING))
return patmatch(v2.val.s, v1.val.s);
@@ -258,6 +270,10 @@
}
}
+static inline int
+eclist_set_type(struct f_tree *set)
+{ return set->from.type == T_EC; }
+
static int
clist_match_set(struct adata *clist, struct f_tree *set)
{
@@ -270,6 +286,7 @@
u32 *l = (u32 *) clist->data;
u32 *end = l + clist->length/4;
+
while (l < end) {
v.val.i = *l++;
if (find_tree(set, v))
@@ -278,6 +295,30 @@
return 0;
}
+static int
+eclist_match_set(struct adata *list, struct f_tree *set)
+{
+ if (!list)
+ return 0;
+
+ if (!eclist_set_type(set))
+ return CMP_ERROR;
+
+ struct f_val v;
+ u32 *l = int_set_get_data(list);
+ int len = int_set_get_size(list);
+ int i;
+
+ v.type = T_EC;
+ for (i = 0; i < len; i += 2) {
+ v.val.ec = ec_get(l, i);
+ if (find_tree(set, v))
+ return 1;
+ }
+
+ return 0;
+}
+
static struct adata *
clist_filter(struct linpool *pool, struct adata *clist, struct f_tree *set, int pos)
{
@@ -302,8 +343,39 @@
if (nl == clist->length)
return clist;
- struct adata *res = lp_alloc(pool, sizeof(struct adata) + nl);
- res->length = nl;
+ struct adata *res = adata_empty(pool, nl);
+ memcpy(res->data, tmp, nl);
+ return res;
+}
+
+static struct adata *
+eclist_filter(struct linpool *pool, struct adata *list, struct f_tree *set, int pos)
+{
+ if (!list)
+ return NULL;
+
+ struct f_val v;
+
+ int len = int_set_get_size(list);
+ u32 *l = int_set_get_data(list);
+ u32 tmp[len];
+ u32 *k = tmp;
+ int i;
+
+ v.type = T_EC;
+ for (i = 0; i < len; i += 2) {
+ v.val.ec = ec_get(l, i);
+ if (pos == !!find_tree(set, v)) { /* pos && find_tree || !pos && !find_tree */
+ *k++ = l[i];
+ *k++ = l[i+1];
+ }
+ }
+
+ int nl = (k - tmp) * 4;
+ if (nl == list->length)
+ return list;
+
+ struct adata *res = adata_empty(pool, nl);
memcpy(res->data, tmp, nl);
return res;
}
@@ -332,6 +404,9 @@
if ((v1.type == T_CLIST) && (v2.type == T_SET))
return clist_match_set(v1.val.ad, v2.val.t);
+ if ((v1.type == T_ECLIST) && (v2.type == T_SET))
+ return eclist_match_set(v1.val.ad, v2.val.t);
+
if (v2.type == T_SET)
switch (v1.type) {
case T_ENUM:
@@ -339,6 +414,7 @@
case T_PAIR:
case T_QUAD:
case T_IP:
+ case T_EC:
{
struct f_tree *n;
n = find_tree(v2.val.t, v1);
@@ -397,11 +473,13 @@
case T_PREFIX: logn("%I/%d", v.val.px.ip, v.val.px.len); return;
case T_PAIR: logn("(%d,%d)", v.val.i >> 16, v.val.i & 0xffff); return;
case T_QUAD: logn("%R", v.val.i); return;
+ case T_EC: ec_format(buf2, v.val.ec); logn("%s", buf2); return;
case T_PREFIX_SET: trie_print(v.val.ti); return;
case T_SET: tree_print(v.val.t); return;
case T_ENUM: logn("(enum %x)%d", v.type, v.val.i); return;
case T_PATH: as_path_format(v.val.ad, buf2, 1000); logn("(path %s)", buf2); return;
case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); logn("(clist %s)", buf2); return;
+ case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); logn("(eclist %s)", buf2); return;
case T_PATH_MASK: pm_format(v.val.path_mask, buf2, 1000); logn("(pathmask%s)", buf2); return;
default: logn( "[unknown type %x]", v.type ); return;
}
@@ -541,7 +619,7 @@
break;
case P('m','p'):
- TWOARGS_C;
+ TWOARGS;
if ((v1.type != T_INT) || (v2.type != T_INT))
runtime( "Can't operate with value of non-integer type in pair constructor" );
u1 = v1.val.i;
@@ -552,6 +630,53 @@
res.type = T_PAIR;
break;
+ case P('m','c'):
+ {
+ TWOARGS;
+
+ int check, ipv4_used;
+ u32 key, val;
+
+ if (v1.type == T_INT) {
+ ipv4_used = 0; key = v1.val.i;
+ }
+ else if (v1.type == T_QUAD) {
+ ipv4_used = 1; key = v1.val.i;
+ }
+#ifndef IPV6
+ /* IP->Quad implicit conversion */
+ else if (v1.type == T_IP) {
+ ipv4_used = 1; key = ipa_to_u32(v1.val.px.ip);
+ }
+#endif
+ else
+ runtime("Can't operate with key of non-integer/IPv4 type in EC constructor");
+
+ if (v2.type != T_INT)
+ runtime("Can't operate with value of non-integer type in EC constructor");
+ val = v2.val.i;
+
+ res.type = T_EC;
+
+ if (what->aux == EC_GENERIC) {
+ check = 0; res.val.ec = ec_generic(key, val);
+ }
+ else if (ipv4_used) {
+ check = 1; res.val.ec = ec_ip4(what->aux, key, val);
+ }
+ else if (key < 0x10000) {
+ check = 0; res.val.ec = ec_as2(what->aux, key, val);
+ }
+ else {
+ check = 1; res.val.ec = ec_as4(what->aux, key, val);
+ }
+
+ if (check && (val > 0xFFFF))
+ runtime("Can't operate with value out of bounds in EC constructor");
+
+ break;
+ }
+
/* Relational operators */
#define COMPARE(x) \
@@ -723,9 +848,16 @@
/* A special case: undefined int_set looks like empty int_set */
if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) {
res.type = T_CLIST;
- res.val.ad = adata_empty(f_pool);
+ res.val.ad = adata_empty(f_pool, 0);
+ break;
+ }
+ /* The same special case for ec_set */
+ else if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) {
+ res.type = T_ECLIST;
+ res.val.ad = adata_empty(f_pool, 0);
break;
}
+
/* Undefined value */
res.type = T_VOID;
break;
@@ -757,6 +889,10 @@
res.type = T_CLIST;
res.val.ad = e->u.ptr;
break;
+ case EAF_TYPE_EC_SET:
+ res.type = T_ECLIST;
+ res.val.ad = e->u.ptr;
+ break;
case EAF_TYPE_UNDEF:
res.type = T_VOID;
break;
@@ -802,7 +938,12 @@
break;
case EAF_TYPE_INT_SET:
if (v1.type != T_CLIST)
- runtime( "Setting int set attribute to non-clist value" );
+ runtime( "Setting clist attribute to non-clist value" );
+ l->attrs[0].u.ptr = v1.val.ad;
+ break;
+ case EAF_TYPE_EC_SET:
+ if (v1.type != T_ECLIST)
+ runtime( "Setting eclist attribute to non-eclist value" );
l->attrs[0].u.ptr = v1.val.ad;
break;
case EAF_TYPE_UNDEF:
@@ -926,7 +1067,7 @@
case 'E': /* Create empty attribute */
res.type = what->aux;
- res.val.ad = adata_empty(f_pool);
+ res.val.ad = adata_empty(f_pool, 0);
break;
case P('A','p'): /* Path prepend */
TWOARGS;
@@ -939,52 +1080,93 @@
res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
break;
- case P('C','a'): /* Community list add or delete */
+ case P('C','a'): /* (Extended) Community list add or delete */
TWOARGS;
- if (v1.type != T_CLIST)
- runtime("Can't add/delete to non-clist");
-
- struct f_val dummy;
- int arg_set = 0;
- i = 0;
+ if (v1.type == T_CLIST)
+ {
+ /* Community (or cluster) list */
+ struct f_val dummy;
+ int arg_set = 0;
+ i = 0;
- if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
- i = v2.val.i;
+ if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
+ i = v2.val.i;
#ifndef IPV6
- /* IP->Quad implicit conversion */
- else if (v2.type == T_IP)
- i = ipa_to_u32(v2.val.px.ip);
+ /* IP->Quad implicit conversion */
+ else if (v2.type == T_IP)
+ i = ipa_to_u32(v2.val.px.ip);
#endif
- else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
- arg_set = 1;
- else
- runtime("Can't add/delete non-pair");
+ else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
+ arg_set = 1;
+ else
+ runtime("Can't add/delete non-pair");
- res.type = T_CLIST;
- switch (what->aux)
+ res.type = T_CLIST;
+ switch (what->aux)
+ {
+ case 'a':
+ if (arg_set)
+ runtime("Can't add set");
+ res.val.ad = int_set_add(f_pool, v1.val.ad, i);
+ break;
+
+ case 'd':
+ if (!arg_set)
+ res.val.ad = int_set_del(f_pool, v1.val.ad, i);
+ else
+ res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 0);
+ break;
+
+ case 'f':
+ if (!arg_set)
+ runtime("Can't filter pair");
+ res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 1);
+ break;
+
+ default:
+ bug("unknown Ca operation");
+ }
+ }
+ else if (v1.type == T_ECLIST)
{
- case 'a':
- if (arg_set)
- runtime("Can't add set");
- res.val.ad = int_set_add(f_pool, v1.val.ad, i);
- break;
+ /* Extended community list */
+ int arg_set = 0;
- case 'd':
- if (!arg_set)
- res.val.ad = int_set_del(f_pool, v1.val.ad, i);
- else
- res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 0);
- break;
+ /* v2.val is either EC or EC-set */
+ if ((v2.type == T_SET) && eclist_set_type(v2.val.t))
+ arg_set = 1;
+ else if (v2.type != T_EC)
+ runtime("Can't add/delete non-pair");
- case 'f':
- if (!arg_set)
- runtime("Can't filter pair");
- res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 1);
- break;
+ res.type = T_ECLIST;
+ switch (what->aux)
+ {
+ case 'a':
+ if (arg_set)
+ runtime("Can't add set");
+ res.val.ad = ec_set_add(f_pool, v1.val.ad, v2.val.ec);
+ break;
+
+ case 'd':
+ if (!arg_set)
+ res.val.ad = ec_set_del(f_pool, v1.val.ad, v2.val.ec);
+ else
+ res.val.ad = eclist_filter(f_pool, v1.val.ad, v2.val.t, 0);
+ break;
- default:
- bug("unknown Ca operation");
+ case 'f':
+ if (!arg_set)
+ runtime("Can't filter ec");
+ res.val.ad = eclist_filter(f_pool, v1.val.ad, v2.val.t, 1);
+ break;
+
+ default:
+ bug("unknown Ca operation");
+ }
}
+ else
+ runtime("Can't add/delete to non-(e)clist");
+
break;
default:
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/filter/filter.h
^
|
@@ -46,6 +46,7 @@
int type;
union {
int i;
+ u64 ec;
/* ip_addr ip; Folded into prefix */
struct f_prefix px;
char *s;
@@ -152,6 +153,8 @@
#define T_PATH_MASK 0x23 /* mask for BGP path */
#define T_PATH 0x24 /* BGP path */
#define T_CLIST 0x25 /* Community list */
+#define T_ECLIST 0x26 /* Extended community list */
+#define T_EC 0x27 /* Extended community value, u64 */
#define T_RETURN 0x40
#define T_SET 0x80
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/filter/test.conf
^
|
@@ -11,6 +11,7 @@
define xyzzy = (120+10);
define '1a-a1' = (20+10);
define one = 1;
+define ten = 10;
function onef(int a)
{
@@ -56,6 +57,7 @@
bgpmask pm2;
bgppath p2;
clist l;
+eclist el;
{
pm1 = / 4 3 2 1 /;
pm2 = [= 4 3 2 1 =];
@@ -118,6 +120,29 @@
print "Community list (3,1) ", l;
l = delete( l, [(*,(onef(5)))] );
print "Community list empty ", l;
+
+ el = -- empty --;
+ el = add(el, (rt, 10, 20));
+ el = add(el, (ro, 10.20.30.40, 100));
+ el = add(el, (ro, 11.21.31.41.mask(16), 200));
+ print "EC list (rt, 10, 20) (ro, 10.20.30.40, 100) (ro, 11.21.0.0, 200):";
+ print el;
+ el = delete(el, (rt, 10, 20));
+ el = delete(el, (rt, 10, 30));
+ el = add(el, (unknown 2, ten, 1));
+ el = add(el, (unknown 5, ten, 1));
+ el = add(el, (rt, ten, one+one));
+ el = add(el, (rt, 10, 3));
+ el = add(el, (rt, 10, 4));
+ el = add(el, (rt, 10, 5));
+ el = add(el, (generic, 0x2000a, 3*ten));
+ el = delete(el, [(rt, 10, 2..ten)]);
+ print "EC list (ro, 10.20.30.40, 100) (ro, 11.21.0.0, 200) (rt, 10, 1) (unknown 0x5, 10, 1) (rt, 10, 30):";
+ print el;
+ el = filter(el, [(rt, 10, *)]);
+ print "EC list (rt, 10, 1) (rt, 10, 30): ", el;
+ print "Testing EC list, true: ", (rt, 10, 1) ~ el, " ", el ~ [(rt, 10, ten..40)];
+ print "Testing EC list, false: ", (rt, 10, 20) ~ el, " ", (ro, 10.20.30.40, 100) ~ el, " ", el ~ [(rt, 10, 35..40)], " ", el ~ [(ro, 10, *)];
}
function bla()
@@ -175,11 +200,13 @@
ip p;
pair pp;
quad qq;
+ec cc;
int set is;
int set is1;
int set is2;
int set is3;
pair set ps;
+ec set ecs;
prefix set pxs;
string s;
{
@@ -250,6 +277,19 @@
", true: ", qq = 1.2.3.4, " ", qq ~ [1.2.3.4, 5.6.7.8],
", false: ", qq = 4.3.2.1, " ", qq ~ [1.2.1.1, 1.2.3.5];
+ cc = (rt, 12345, 200000);
+ print "Testing EC: (rt, 12345, 200000) = ", cc;
+ print "Testing EC: (ro, 100000, 20000) = ", (ro, 100000, 20000);
+ print "Testing EC: (rt, 10.20.30.40, 20000) = ", (rt, 10.20.30.40, 20000);
+ print " true: ", cc = (rt, 12345, 200000), " ", cc < (rt, 12345, 200010),
+ ", false: ", cc = (rt, 12346, 200000), " ", cc = (ro, 12345, 200000), " ", cc > (rt, 12345, 200010);
+
+ ecs = [(rt, ten, (one+onef(0))*10), (ro, 100000, 100..200), (rt, 12345, *)];
+ print "EC set: ", ecs;
+ print "Testing EC set, true: ", (rt, 10, 20) ~ ecs, " ", (ro, 100000, 100) ~ ecs, " ", (ro, 100000, 200) ~ ecs,
+ " ", (rt, 12345, 0) ~ ecs, " ", cc ~ ecs, " ", (rt, 12345, 4000000) ~ ecs;
+ print "Testing EC set, false: ", (ro, 10, 20) ~ ecs, " ", (rt, 10, 21) ~ ecs, " ", (ro, 100000, 99) ~ ecs,
+ " ", (ro, 12345, 10) ~ ecs, " ", (rt, 12346, 0) ~ ecs, " ", (ro, 0.1.134.160, 150) ~ ecs;
s = "Hello";
print "Testing string: ", s, " true: ", s ~ "Hell*", " false: ", s ~ "ell*";
@@ -289,6 +329,9 @@
test_undef(3);
test_undef(2);
+ print "Testing include";
+ include "test.conf.inc";
+
print "done";
quitbird;
# print "*** FAIL: this is unreachable";
|
[-]
[+]
|
Added |
bird-1.3.3.tar.bz2/filter/test.conf.inc
^
|
@@ -0,0 +1,6 @@
+
+print "Entering include";
+print "Should be 2: ", 1+1;
+print "Leaving include";
+
+
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/lib/socket.h
^
|
@@ -54,7 +54,8 @@
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */
void sk_dump_all(void);
-int sk_set_ttl(sock *s, int ttl); /* Set TTL for given socket */
+int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
+int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
/* Add or remove security associations for given passive socket */
int sk_set_md5_auth(sock *s, ip_addr a, char *passwd);
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/nest/a-set.c
^
|
@@ -36,10 +36,11 @@
{
u32 *z = (u32 *) set->data;
byte *end = buf + size - 24;
+ int from2 = MAX(from, 0);
int to = set->length / 4;
int i;
- for (i = MAX(from, 0); i < to; i++)
+ for (i = from2; i < to; i++)
{
if (buf > end)
{
@@ -50,7 +51,7 @@
return i;
}
- if (i > from)
+ if (i > from2)
*buf++ = ' ';
if (way)
@@ -63,16 +64,116 @@
}
int
+ec_format(byte *buf, u64 ec)
+{
+ u32 type, key, val;
+ char tbuf[16], *kind;
+
+ type = ec >> 48;
+ switch (type & 0xf0ff)
+ {
+ case EC_RT: kind = "rt"; break;
+ case EC_RO: kind = "ro"; break;
+
+ default:
+ kind = tbuf;
+ bsprintf(kind, "unknown 0x%x", type);
+ }
+
+ switch (ec >> 56)
+ {
+ /* RFC 4360 3.1. Two-Octet AS Specific Extended Community */
+ case 0x00:
+ case 0x40:
+ key = (ec >> 32) & 0xFFFF;
+ val = ec;
+ return bsprintf(buf, "(%s, %u, %u)", kind, key, val);
+
+ /* RFC 4360 3.2. IPv4 Address Specific Extended Community */
+ case 0x01:
+ case 0x41:
+ key = ec >> 16;
+ val = ec & 0xFFFF;
+ return bsprintf(buf, "(%s, %R, %u)", kind, key, val);
+
+ /* RFC 5668 4-Octet AS Specific BGP Extended Community */
+ case 0x02:
+ case 0x42:
+ key = ec >> 16;
+ val = ec & 0xFFFF;
+ return bsprintf(buf, "(%s, %u, %u)", kind, key, val);
+
+ /* Generic format for unknown kinds of extended communities */
+ default:
+ key = ec >> 32;
+ val = ec;
+ return bsprintf(buf, "(generic, 0x%x, 0x%x)", key, val);
+ }
+
+}
+
+int
+ec_set_format(struct adata *set, int from, byte *buf, unsigned int size)
+{
+ u32 *z = int_set_get_data(set);
+ byte *end = buf + size - 24;
+ int from2 = MAX(from, 0);
+ int to = int_set_get_size(set);
+ int i;
+
+ for (i = from2; i < to; i += 2)
+ {
+ if (buf > end)
+ {
+ if (from < 0)
+ strcpy(buf, " ...");
+ else
+ *buf = 0;
+ return i;
+ }
+
+ if (i > from2)
+ *buf++ = ' ';
+
+ buf += ec_format(buf, ec_get(z, i));
+ }
+ *buf = 0;
+ return 0;
+}
+
+int
int_set_contains(struct adata *list, u32 val)
{
if (!list)
return 0;
u32 *l = (u32 *) list->data;
- unsigned int i;
- for (i=0; i<list->length/4; i++)
+ int len = int_set_get_size(list);
+ int i;
+
+ for (i = 0; i < len; i++)
if (*l++ == val)
return 1;
+
+ return 0;
+}
+
+int
+ec_set_contains(struct adata *list, u64 val)
+{
+ if (!list)
+ return 0;
+
+ u32 *l = int_set_get_data(list);
+ int len = int_set_get_size(list);
+ u32 eh = ec_hi(val);
+ u32 el = ec_lo(val);
+ int i;
+
+ for (i=0; i < len; i += 2)
+ if (l[i] == eh && l[i+1] == el)
+ return 1;
+
return 0;
}
@@ -86,7 +187,7 @@
return list;
len = list ? list->length : 0;
- res = lp_alloc(pool, len + sizeof(struct adata) + 4);
+ res = lp_alloc(pool, sizeof(struct adata) + len + 4);
res->length = len + 4;
* (u32 *) res->data = val;
if (list)
@@ -95,23 +196,71 @@
}
struct adata *
-int_set_del(struct linpool *pool, struct adata *list, u32 val)
+ec_set_add(struct linpool *pool, struct adata *list, u64 val)
{
- struct adata *res;
- u32 *l, *k;
- unsigned int i;
+ if (ec_set_contains(list, val))
+ return list;
+
+ int olen = list ? list->length : 0;
+ struct adata *res = lp_alloc(pool, sizeof(struct adata) + olen + 8);
+ res->length = olen + 8;
+
+ if (list)
+ memcpy(res->data, list->data, list->length);
+
+ u32 *l = (u32 *) (res->data + res->length - 8);
+ l[0] = ec_hi(val);
+ l[1] = ec_lo(val);
+
+ return res;
+}
+
+struct adata *
+int_set_del(struct linpool *pool, struct adata *list, u32 val)
+{
if (!int_set_contains(list, val))
return list;
- res = lp_alloc(pool, list->length + sizeof(struct adata) - 4);
- res->length = list->length-4;
+ struct adata *res;
+ res = lp_alloc(pool, sizeof(struct adata) + list->length - 4);
+ res->length = list->length - 4;
+
+ u32 *l = int_set_get_data(list);
+ u32 *k = int_set_get_data(res);
+ int len = int_set_get_size(list);
+ int i;
- l = (u32 *) list->data;
- k = (u32 *) res->data;
- for (i=0; i<list->length/4; i++)
+ for (i = 0; i < len; i++)
if (l[i] != val)
*k++ = l[i];
return res;
}
+
+struct adata *
+ec_set_del(struct linpool *pool, struct adata *list, u64 val)
+{
+ if (!ec_set_contains(list, val))
+ return list;
+
+ struct adata *res;
+ res = lp_alloc(pool, sizeof(struct adata) + list->length - 8);
+ res->length = list->length - 8;
+
+ u32 *l = int_set_get_data(list);
+ u32 *k = int_set_get_data(res);
+ int len = int_set_get_size(list);
+ u32 eh = ec_hi(val);
+ u32 el = ec_lo(val);
+ int i;
+
+ for (i=0; i < len; i += 2)
+ if (! (l[i] == eh && l[i+1] == el))
+ {
+ *k++ = l[i];
+ *k++ = l[i+1];
+ }
+
+ return res;
+}
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/nest/attrs.h
^
|
@@ -50,12 +50,52 @@
/* a-set.c */
+
+/* Extended Community subtypes (kinds) */
+#define EC_RT 0x0002
+#define EC_RO 0x0003
+
+#define EC_GENERIC 0xFFFF
+
+/* Transitive bit (for first u32 half of EC) */
+#define EC_TBIT 0x40000000
+
+
+static inline int int_set_get_size(struct adata *list)
+{ return list->length / 4; }
+
+static inline u32 *int_set_get_data(struct adata *list)
+{ return (u32 *) list->data; }
+
+static inline u32 ec_hi(u64 ec) { return ec >> 32; }
+static inline u32 ec_lo(u64 ec) { return ec; }
+static inline u64 ec_get(const u32 *l, int i)
+{ return (((u64) l[i]) << 32) | l[i+1]; }
+
+/* RFC 4360 3.1. Two-Octet AS Specific Extended Community */
+static inline u64 ec_as2(u64 kind, u64 key, u64 val)
+{ return ((kind | 0x0000) << 48) | (key << 32) | val; }
+
+/* RFC 5668 4-Octet AS Specific BGP Extended Community */
+static inline u64 ec_as4(u64 kind, u64 key, u64 val)
+{ return ((kind | 0x0200) << 48) | (key << 16) | val; }
+
+/* RFC 4360 3.2. IPv4 Address Specific Extended Community */
+static inline u64 ec_ip4(u64 kind, u64 key, u64 val)
+{ return ((kind | 0x0100) << 48) | (key << 16) | val; }
+
+static inline u64 ec_generic(u64 key, u64 val)
+{ return (key << 32) | val; }
+
int int_set_format(struct adata *set, int way, int from, byte *buf, unsigned int size);
-struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val);
+int ec_format(byte *buf, u64 ec);
+int ec_set_format(struct adata *set, int from, byte *buf, unsigned int size);
int int_set_contains(struct adata *list, u32 val);
+int ec_set_contains(struct adata *list, u64 val);
+struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val);
+struct adata *ec_set_add(struct linpool *pool, struct adata *list, u64 val);
struct adata *int_set_del(struct linpool *pool, struct adata *list, u32 val);
+struct adata *ec_set_del(struct linpool *pool, struct adata *list, u64 val);
-static inline int int_set_get_size(struct adata *list)
-{ return list->length / 4; }
#endif
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/nest/cli.c
^
|
@@ -251,6 +251,7 @@
bzero(&f, sizeof(f));
f.mem = c->parser_pool;
cf_read_hook = cli_cmd_read_hook;
+ cf_open_hook = NULL;
cli_rh_pos = c->rx_buf;
cli_rh_len = strlen(c->rx_buf);
cli_rh_trick_flag = 0;
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/nest/route.h
^
|
@@ -363,6 +363,7 @@
#define EAF_TYPE_ROUTER_ID 0x05 /* Router ID (IPv4 address) */
#define EAF_TYPE_AS_PATH 0x06 /* BGP AS path (encoding per RFC 1771:4.3) */
#define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */
+#define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */
#define EAF_TYPE_UNDEF 0x0f /* `force undefined' entry */
#define EAF_EMBEDDED 0x01 /* Data stored in eattr.u.data (part of type spec) */
#define EAF_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/nest/rt-attr.c
^
|
@@ -457,11 +457,23 @@
ea_show_int_set(struct cli *c, struct adata *ad, int way, byte *pos, byte *buf, byte *end)
{
int i = int_set_format(ad, way, 0, pos, end - pos);
- cli_printf(c, -1012, "%s", buf);
+ cli_printf(c, -1012, "\t%s", buf);
while (i)
{
i = int_set_format(ad, way, i, buf, end - buf - 1);
- cli_printf(c, -1012, "\t%s", buf);
+ cli_printf(c, -1012, "\t\t%s", buf);
+ }
+}
+
+static inline void
+ea_show_ec_set(struct cli *c, struct adata *ad, byte *pos, byte *buf, byte *end)
+{
+ int i = ec_set_format(ad, 0, pos, end - pos);
+ cli_printf(c, -1012, "\t%s", buf);
+ while (i)
+ {
+ i = ec_set_format(ad, i, buf, end - buf - 1);
+ cli_printf(c, -1012, "\t\t%s", buf);
}
}
@@ -523,12 +535,15 @@
case EAF_TYPE_INT_SET:
ea_show_int_set(c, ad, 1, pos, buf, end);
return;
+ case EAF_TYPE_EC_SET:
+ ea_show_ec_set(c, ad, pos, buf, end);
+ return;
case EAF_TYPE_UNDEF:
default:
bsprintf(pos, "<type %02x>", e->type);
}
}
- cli_printf(c, -1012, "%s", buf);
+ cli_printf(c, -1012, "\t%s", buf);
}
/**
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/bgp/attrs.c
^
|
@@ -247,7 +247,6 @@
return ((len % 4) == 0) ? 0 : WITHDRAW;
}
-
static int
bgp_check_cluster_list(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
{
@@ -281,6 +280,13 @@
return IGNORE;
}
+static int
+bgp_check_ext_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
+{
+ return ((len % 8) == 0) ? 0 : WITHDRAW;
+}
+
+
static struct attr_desc bgp_attr_table[] = {
{ NULL, -1, 0, 0, 0, /* Undefined */
NULL, NULL },
@@ -311,7 +317,8 @@
bgp_check_reach_nlri, NULL },
{ "mp_unreach_nlri", -1, BAF_OPTIONAL, EAF_TYPE_OPAQUE, 1, /* BA_MP_UNREACH_NLRI */
bgp_check_unreach_nlri, NULL },
- { .name = NULL }, /* BA_EXTENDED_COMM */
+ { "ext_community", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_EC_SET, 1, /* BA_EXT_COMMUNITY */
+ bgp_check_ext_community, NULL },
{ "as4_path", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */
NULL, NULL },
{ "as4_aggregator", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */
@@ -468,7 +475,7 @@
unsigned int
bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
{
- unsigned int i, code, flags;
+ unsigned int i, code, type, flags;
byte *start = w;
int len, rv;
@@ -477,6 +484,7 @@
eattr *a = &attrs->attrs[i];
ASSERT(EA_PROTO(a->id) == EAP_BGP);
code = EA_ID(a->id);
+
#ifdef IPV6
/* When talking multiprotocol BGP, the NEXT_HOP attributes are used only temporarily. */
if (code == BA_NEXT_HOP)
@@ -559,11 +567,12 @@
/* Standard path continues here ... */
+ type = a->type & EAF_TYPE_MASK;
flags = a->flags & (BAF_OPTIONAL | BAF_TRANSITIVE | BAF_PARTIAL);
len = bgp_get_attr_len(a);
- /* Skip empty int sets */
- if (((a->type & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) && (len == 0))
+ /* Skip empty sets */
+ if (((type == EAF_TYPE_INT_SET) || (type == EAF_TYPE_EC_SET)) && (len == 0))
continue;
if (remains < len + 4)
@@ -572,7 +581,7 @@
rv = bgp_encode_attr_hdr(w, flags, code, len);
ADVANCE(w, remains, rv);
- switch (a->type & EAF_TYPE_MASK)
+ switch (type)
{
case EAF_TYPE_INT:
case EAF_TYPE_ROUTER_ID:
@@ -589,8 +598,9 @@
break;
}
case EAF_TYPE_INT_SET:
+ case EAF_TYPE_EC_SET:
{
- u32 *z = (u32 *)a->u.ptr->data;
+ u32 *z = int_set_get_data(a->u.ptr);
int i;
for(i=0; i<len; i+=4)
put_u32(w+i, *z++);
@@ -624,13 +634,50 @@
return (*x < *y) ? -1 : (*x > *y) ? 1 : 0;
}
-static void
-bgp_normalize_set(u32 *dest, u32 *src, unsigned cnt)
+static inline void
+bgp_normalize_int_set(u32 *dest, u32 *src, unsigned cnt)
{
memcpy(dest, src, sizeof(u32) * cnt);
qsort(dest, cnt, sizeof(u32), (int(*)(const void *, const void *)) bgp_compare_u32);
}
+static int
+bgp_compare_ec(const u32 *xp, const u32 *yp)
+{
+ u64 x = ec_get(xp, 0);
+ u64 y = ec_get(yp, 0);
+ return (x < y) ? -1 : (x > y) ? 1 : 0;
+}
+
+static inline void
+bgp_normalize_ec_set(struct adata *ad, u32 *src, int internal)
+{
+ u32 *dst = int_set_get_data(ad);
+
+ /* Remove non-transitive communities (EC_TBIT active) on external sessions */
+ if (! internal)
+ {
+ int len = int_set_get_size(ad);
+ u32 *t = dst;
+ int i;
+
+ for (i=0; i < len; i += 2)
+ {
+ if (src[i] & EC_TBIT)
+ continue;
+
+ *t++ = src[i];
+ *t++ = src[i+1];
+ }
+
+ ad->length = (t - dst) * 4;
+ }
+ else
+ memcpy(dst, src, ad->length);
+
+ qsort(dst, ad->length / 8, 8, (int(*)(const void *, const void *)) bgp_compare_ec);
+}
+
static void
bgp_rehash_buckets(struct bgp_proto *p)
{
@@ -763,7 +810,15 @@
{
struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
z->length = d->u.ptr->length;
- bgp_normalize_set((u32 *) z->data, (u32 *) d->u.ptr->data, z->length / 4);
+ bgp_normalize_int_set((u32 *) z->data, (u32 *) d->u.ptr->data, z->length / 4);
+ d->u.ptr = z;
+ break;
+ }
+ case EAF_TYPE_EC_SET:
+ {
+ struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
+ z->length = d->u.ptr->length;
+ bgp_normalize_ec_set(z, (u32 *) d->u.ptr->data, p->is_internal);
d->u.ptr = z;
break;
}
@@ -1447,6 +1502,7 @@
ipa_ntoh(*(ip_addr *)ad->data);
break;
case EAF_TYPE_INT_SET:
+ case EAF_TYPE_EC_SET:
{
u32 *z = (u32 *) ad->data;
for(i=0; i<ad->length/4; i++)
@@ -1520,16 +1576,18 @@
{
unsigned int i = EA_ID(a->id);
struct attr_desc *d;
+ int len;
if (ATTR_KNOWN(i))
{
d = &bgp_attr_table[i];
- buf += bsprintf(buf, "%s", d->name);
+ len = bsprintf(buf, "%s", d->name);
+ buf += len;
if (d->format)
{
*buf++ = ':';
*buf++ = ' ';
- d->format(a, buf, buflen);
+ d->format(a, buf, buflen - len - 2);
return GA_FULL;
}
return GA_NAME;
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/bgp/bgp.c
^
|
@@ -92,6 +92,8 @@
bgp_open(struct bgp_proto *p)
{
struct config *cfg = p->cf->c.global;
+ int errcode;
+
bgp_counter++;
if (!bgp_listen_sk)
@@ -100,10 +102,8 @@
if (!bgp_listen_sk)
{
bgp_counter--;
- p->p.disabled = 1;
- bgp_store_error(p, NULL, BE_MISC, BEM_NO_SOCKET);
- proto_notify_state(&p->p, PS_DOWN);
- return -1;
+ errcode = BEM_NO_SOCKET;
+ goto err;
}
if (!bgp_linpool)
@@ -115,14 +115,18 @@
if (rv < 0)
{
bgp_close(p, 0);
- p->p.disabled = 1;
- bgp_store_error(p, NULL, BE_MISC, BEM_INVALID_MD5);
- proto_notify_state(&p->p, PS_DOWN);
- return -1;
+ errcode = BEM_INVALID_MD5;
+ goto err;
}
}
return 0;
+
+err:
+ p->p.disabled = 1;
+ bgp_store_error(p, NULL, BE_MISC, errcode);
+ proto_notify_state(&p->p, PS_DOWN);
+ return -1;
}
static void
@@ -567,6 +571,7 @@
{
sock *s;
struct bgp_conn *conn = &p->outgoing_conn;
+ int hops = p->cf->multihop ? : 1;
DBG("BGP: Connecting\n");
s = sk_new(p->p.pool);
@@ -574,7 +579,7 @@
s->saddr = p->source_addr;
s->daddr = p->cf->remote_ip;
s->dport = BGP_PORT;
- s->ttl = p->cf->multihop ? : 1;
+ s->ttl = p->cf->ttl_security ? 255 : hops;
s->rbsize = BGP_RX_BUFFER_SIZE;
s->tbsize = BGP_TX_BUFFER_SIZE;
s->tos = IP_PREC_INTERNET_CONTROL;
@@ -584,11 +589,25 @@
bgp_setup_conn(p, conn);
bgp_setup_sk(conn, s);
bgp_conn_set_state(conn, BS_CONNECT);
- if (sk_open(s))
+
+ if (sk_open(s) < 0)
{
bgp_sock_err(s, 0);
return;
}
+
+ /* Set minimal receive TTL if needed */
+ if (p->cf->ttl_security)
+ {
+ DBG("Setting minimum received TTL to %d", 256 - hops);
+ if (sk_set_min_ttl(s, 256 - hops) < 0)
+ {
+ log(L_ERR "TTL security configuration failed, closing session");
+ bgp_sock_err(s, 0);
+ return;
+ }
+ }
+
DBG("BGP: Waiting for connect success\n");
bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
}
@@ -627,9 +646,22 @@
if (!acc)
goto err;
+ int hops = p->cf->multihop ? : 1;
+ if (p->cf->ttl_security)
+ {
+ /* TTL security support */
+ if ((sk_set_ttl(sk, 255) < 0) ||
+ (sk_set_min_ttl(sk, 256 - hops) < 0))
+ {
+ log(L_ERR "TTL security configuration failed, closing session");
+ goto err;
+ }
+ }
+ else
+ sk_set_ttl(sk, hops);
+
bgp_setup_conn(p, &p->incoming_conn);
bgp_setup_sk(&p->incoming_conn, sk);
- sk_set_ttl(sk, p->cf->multihop ? : 1);
bgp_send_open(&p->incoming_conn);
return 0;
}
@@ -656,6 +688,7 @@
sock *s = sk_new(&root_pool);
DBG("BGP: Creating listening socket\n");
s->type = SK_TCP_PASSIVE;
+ s->ttl = 255;
s->saddr = addr;
s->sport = port ? port : BGP_PORT;
s->flags = flags ? 0 : SKF_V6ONLY;
@@ -664,14 +697,15 @@
s->tbsize = BGP_TX_BUFFER_SIZE;
s->rx_hook = bgp_incoming_connection;
s->err_hook = bgp_listen_sock_err;
- if (sk_open(s))
+
+ if (sk_open(s) < 0)
{
log(L_ERR "BGP: Unable to open listening socket");
rfree(s);
return NULL;
}
- else
- return s;
+
+ return s;
}
static void
@@ -1008,8 +1042,8 @@
static const char *
bgp_state_dsc(struct bgp_proto *p)
{
- //if (p->p.proto_state == PS_DOWN)
- // return "Down";
+ if (p->p.proto_state == PS_DOWN)
+ return "Down";
int state = MAX(p->incoming_conn.state, p->outgoing_conn.state);
if ((state == BS_IDLE) && (p->start_state >= BSS_CONNECT) && p->cf->passive)
@@ -1041,10 +1075,9 @@
struct bgp_proto *p = (struct bgp_proto *) P;
struct bgp_conn *c = p->conn;
- if (P->proto_state == PS_DOWN)
- return;
-
cli_msg(-1006, " BGP state: %s", bgp_state_dsc(p));
+ cli_msg(-1006, " Neighbor address: %I", p->cf->remote_ip);
+ cli_msg(-1006, " Neighbor AS: %u", p->remote_as);
if (P->proto_state == PS_START)
{
@@ -1062,18 +1095,17 @@
}
else if (P->proto_state == PS_UP)
{
- cli_msg(-1006, " Session: %s%s%s%s",
+ cli_msg(-1006, " Neighbor ID: %R", p->remote_id);
+ cli_msg(-1006, " Neighbor caps: %s%s",
+ c->peer_refresh_support ? " refresh" : "",
+ c->peer_as4_support ? " AS4" : "");
+ cli_msg(-1006, " Session: %s%s%s%s%s",
p->is_internal ? "internal" : "external",
+ p->cf->multihop ? " multihop" : "",
p->rr_client ? " route-reflector" : "",
p->rs_client ? " route-server" : "",
p->as4_session ? " AS4" : "");
- cli_msg(-1006, " Neighbor AS: %u", p->remote_as);
- cli_msg(-1006, " Neighbor ID: %R", p->remote_id);
- cli_msg(-1006, " Neighbor address: %I", p->cf->remote_ip);
cli_msg(-1006, " Source address: %I", p->source_addr);
- cli_msg(-1006, " Neighbor caps: %s%s",
- c->peer_refresh_support ? " refresh" : "",
- c->peer_as4_support ? " AS4" : "");
if (p->cf->route_limit)
cli_msg(-1006, " Route limit: %d/%d",
p->p.stats.imp_routes, p->cf->route_limit);
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/bgp/bgp.h
^
|
@@ -20,6 +20,7 @@
u32 local_as, remote_as;
ip_addr remote_ip;
int multihop; /* Number of hops if multihop */
+ int ttl_security; /* Enable TTL security [RFC5082] */
ip_addr source_addr; /* Source address to use */
int next_hop_self; /* Always set next hop to local IP address */
int missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */
@@ -236,7 +237,7 @@
#define BA_RCID_PATH 0x0d
#define BA_MP_REACH_NLRI 0x0e /* [RFC2283] */
#define BA_MP_UNREACH_NLRI 0x0f
-#define BA_EXTENDED_COMM 0x10 /* draft-ramachandra-bgp-ext-communities */
+#define BA_EXT_COMMUNITY 0x10 /* [RFC4360] */
#define BA_AS4_PATH 0x11 /* [RFC4893] */
#define BA_AS4_AGGREGATOR 0x12
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/bgp/config.Y
^
|
@@ -21,11 +21,11 @@
PATH, METRIC, ERROR, START, DELAY, FORGET, WAIT, ENABLE,
DISABLE, AFTER, BGP_PATH, BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN,
BGP_NEXT_HOP, BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY,
- SOURCE, ADDRESS, PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4,
- ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER,
- MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH, INTERPRET,
- COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, TABLE,
- GATEWAY, DIRECT, RECURSIVE, MED)
+ BGP_EXT_COMMUNITY, SOURCE, ADDRESS, PASSWORD, RR, RS, CLIENT,
+ CLUSTER, ID, AS4, ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE,
+ PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
+ INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
+ TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY)
CF_GRAMMAR
@@ -71,7 +71,7 @@
| bgp_proto CONNECT RETRY TIME expr ';' { BGP_CFG->connect_retry_time = $5; }
| bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; }
| bgp_proto MULTIHOP ';' { BGP_CFG->multihop = 64; }
- | bgp_proto MULTIHOP expr ';' { BGP_CFG->multihop = $3; }
+ | 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_proto MISSING LLADDR SELF ';' { BGP_CFG->missing_lladdr = MLL_SELF; }
| bgp_proto MISSING LLADDR DROP ';' { BGP_CFG->missing_lladdr = MLL_DROP; }
@@ -98,6 +98,7 @@
| bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
| bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
| bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
+ | bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
;
CF_ADDTO(dynamic_attr, BGP_ORIGIN
@@ -120,6 +121,9 @@
{ $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_CODE(EAP_BGP, BA_ORIGINATOR_ID)); })
CF_ADDTO(dynamic_attr, BGP_CLUSTER_LIST
{ $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(EAP_BGP, BA_CLUSTER_LIST)); })
+CF_ADDTO(dynamic_attr, BGP_EXT_COMMUNITY
+ { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(EAP_BGP, BA_EXT_COMMUNITY)); })
+
CF_ENUM(T_ENUM_BGP_ORIGIN, ORIGIN_, IGP, EGP, INCOMPLETE)
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/config.Y
^
|
@@ -17,6 +17,7 @@
static struct ospf_area_config *this_area;
static struct nbma_node *this_nbma;
+static list *this_nets;
static struct area_net_config *this_pref;
static struct ospf_stubnet_config *this_stubnet;
@@ -56,8 +57,17 @@
static void
ospf_area_finish(void)
{
- if ((this_area->areaid == 0) && (this_area->stub != 0))
- cf_error( "Backbone area cannot be stub");
+ if ((this_area->areaid == 0) && (this_area->type != OPT_E))
+ cf_error("Backbone area cannot be stub/NSSA");
+
+ if (this_area->summary && (this_area->type == OPT_E))
+ cf_error("Only Stub/NSSA areas can use summary propagation");
+
+ if (this_area->default_nssa && ((this_area->type != OPT_N) || ! this_area->summary))
+ cf_error("Only NSSA areas with summary propagation can use NSSA default route");
+
+ if ((this_area->default_cost & LSA_EXT_EBIT) && ! this_area->default_nssa)
+ cf_error("Only NSSA default route can use type 2 metric");
}
static void
@@ -85,23 +95,31 @@
add_head(&cf->area_list, NODE ac);
init_list(&ac->patt_list);
init_list(&ac->net_list);
+ init_list(&ac->enet_list);
init_list(&ac->stubnet_list);
}
if (!cf->abr && !EMPTY_LIST(cf->vlink_list))
- cf_error( "No configured areas in OSPF");
+ cf_error( "Vlinks cannot be used on single area router");
+}
+
+static inline void
+check_defcost(int cost)
+{
+ if ((cost <= 0) || (cost >= LSINFINITY))
+ cf_error("Default cost must be in range 1-%d", LSINFINITY);
}
CF_DECLS
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
-CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
+CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, COST2, RETRANSMIT)
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, TYPE, BROADCAST, BCAST)
CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
-CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY)
-CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT)
+CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
+CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
%type <t> opttext
@@ -137,9 +155,13 @@
this_area = cfg_allocz(sizeof(struct ospf_area_config));
add_tail(&OSPF_CFG->area_list, NODE this_area);
this_area->areaid = $2;
- this_area->stub = 0;
+ this_area->default_cost = DEFAULT_STUB_COST;
+ this_area->type = OPT_E;
+ this_area->transint = DEFAULT_TRANSINT;
+
init_list(&this_area->patt_list);
init_list(&this_area->net_list);
+ init_list(&this_area->enet_list);
init_list(&this_area->stubnet_list);
}
;
@@ -153,9 +175,17 @@
;
ospf_area_item:
- STUB COST expr { this_area->stub = $3 ; if($3<=0) cf_error("Stub cost must be greater than zero"); }
- | STUB bool {if($2) { if(!this_area->stub) this_area->stub=DEFAULT_STUB_COST;}else{ this_area->stub=0;}}
- | NETWORKS '{' pref_list '}'
+ STUB bool { this_area->type = $2 ? 0 : OPT_E; /* We should remove the option */ }
+ | NSSA { this_area->type = OPT_N; }
+ | SUMMARY bool { this_area->summary = $2; }
+ | DEFAULT NSSA bool { this_area->default_nssa = $3; }
+ | DEFAULT COST expr { this_area->default_cost = $3; check_defcost($3); }
+ | DEFAULT COST2 expr { this_area->default_cost = $3 | LSA_EXT_EBIT; check_defcost($3); }
+ | STUB COST expr { this_area->default_cost = $3; check_defcost($3); }
+ | TRANSLATOR bool { this_area->translator = $2; }
+ | TRANSLATOR STABILITY expr { this_area->transint = $3; }
+ | NETWORKS { this_nets = &this_area->net_list; } '{' pref_list '}'
+ | EXTERNAL { this_nets = &this_area->enet_list; } '{' pref_list '}'
| STUBNET ospf_stubnet
| INTERFACE ospf_iface
| ospf_vlink
@@ -267,28 +297,22 @@
| pref_list pref_item
;
-pref_item:
- pref_el
- | pref_hid;
+pref_item: pref_base pref_opt ';' ;
-pref_el: prefix ';'
+pref_base: prefix
{
this_pref = cfg_allocz(sizeof(struct area_net_config));
- add_tail(&this_area->net_list, NODE this_pref);
+ add_tail(this_nets, NODE this_pref);
this_pref->px.addr = $1.addr;
this_pref->px.len = $1.len;
}
;
-pref_hid: prefix HIDDEN ';'
- {
- this_pref = cfg_allocz(sizeof(struct area_net_config));
- add_tail(&this_area->net_list, NODE this_pref);
- this_pref->px.addr = $1.addr;
- this_pref->px.len = $1.len;
- this_pref->hidden = 1;
- }
-;
+pref_opt:
+ /* empty */
+ | HIDDEN { this_pref->hidden = 1; }
+ | TAG expr { this_pref->tag = $2; }
+ ;
ipa_list:
/* empty */
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/hello.c
^
|
@@ -94,10 +94,10 @@
return;
}
- tmp = !(ps->options & OPT_E);
- if (tmp != !!ifa->oa->stub)
+ /* Check whether bits E, N match */
+ if ((ps->options ^ ifa->oa->options) & (OPT_E | OPT_N))
{
- log(L_ERR "%s%I - stub area flag mismatch (%d)", beg, faddr, tmp);
+ log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, ps->options);
return;
}
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/lsalib.c
^
|
@@ -490,6 +490,7 @@
case LSA_T_SUM_RT:
return lsa_validate_sum_rt(lsa, body);
case LSA_T_EXT:
+ case LSA_T_NSSA:
return lsa_validate_ext(lsa, body);
#ifdef OSPFv3
case LSA_T_LINK:
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/lsupd.c
^
|
@@ -77,7 +77,7 @@
{
if (ifa->type == OSPF_IT_VLINK)
return 0;
- if (ifa->oa->stub)
+ if (!oa_is_ext(ifa->oa))
return 0;
return 1;
}
@@ -97,6 +97,7 @@
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
case LSA_T_EXT:
+ case LSA_T_NSSA:
case LSA_T_LINK:
case LSA_T_PREFIX:
return 0;
@@ -126,7 +127,7 @@
case LSA_SCOPE_AS:
if (ifa->type == OSPF_IT_VLINK)
return 0;
- if (ifa->oa->stub)
+ if (!oa_is_ext(ifa->oa))
return 0;
return 1;
@@ -486,21 +487,21 @@
#ifdef OSPFv2
/* pg 143 (2) */
- if ((lsa->type < LSA_T_RT) || (lsa->type > LSA_T_EXT))
+ if ((lsa->type == 0) || (lsa->type == 6) || (lsa->type > LSA_T_NSSA))
{
log(L_WARN "Unknown LSA type from %I", n->ip);
continue;
}
/* pg 143 (3) */
- if ((lsa->type == LSA_T_EXT) && ifa->oa->stub)
+ if ((lsa->type == LSA_T_EXT) && !oa_is_ext(ifa->oa))
{
log(L_WARN "Received External LSA in stub area from %I", n->ip);
continue;
}
#else /* OSPFv3 */
/* 4.5.1 (2) */
- if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && ifa->oa->stub)
+ if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
{
log(L_WARN "Received LSA with AS scope in stub area from %I", n->ip);
continue;
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/ospf.c
^
|
@@ -126,11 +126,19 @@
struct area_net *an;
fib_init(&oa->net_fib, po->proto.pool, sizeof(struct area_net), 0, ospf_area_initfib);
+ fib_init(&oa->enet_fib, po->proto.pool, sizeof(struct area_net), 0, ospf_area_initfib);
WALK_LIST(anc, ac->net_list)
{
an = (struct area_net *) fib_get(&oa->net_fib, &anc->px.addr, anc->px.len);
- an->hidden = an->hidden;
+ an->hidden = anc->hidden;
+ }
+
+ WALK_LIST(anc, ac->enet_list)
+ {
+ an = (struct area_net *) fib_get(&oa->enet_fib, &anc->px.addr, anc->px.len);
+ an->hidden = anc->hidden;
+ an->tag = anc->tag;
}
}
@@ -147,7 +155,6 @@
po->areano++;
oa->ac = ac;
- oa->stub = ac->stub;
oa->areaid = ac->areaid;
oa->rt = NULL;
oa->po = po;
@@ -158,11 +165,19 @@
po->backbone = oa;
#ifdef OSPFv2
- oa->options = (oa->stub ? 0 : OPT_E);
+ oa->options = ac->type;
#else /* OSPFv3 */
- oa->options = OPT_R | (oa->stub ? 0 : OPT_E) | OPT_V6;
+ oa->options = OPT_R | ac->type | OPT_V6;
#endif
+ /*
+ * Set E-bit for NSSA ABR routers. No need to explicitly call
+ * schedule_rt_lsa() for other areas, will be done anyway.
+ * We use cf->abr because po->areano is not yet complete.
+ */
+ if (oa_is_nssa(oa) && ((struct ospf_config *) (p->cf))->abr)
+ po->ebit = 1;
+
if (reconf)
ospf_ifaces_reconfigure(oa, ac);
}
@@ -178,6 +193,10 @@
fib_free(&oa->rtr);
fib_free(&oa->net_fib);
+ fib_free(&oa->enet_fib);
+
+ if (oa->translator_timer)
+ rfree(oa->translator_timer);
oa->po->areano--;
rem_node(NODE oa);
@@ -442,7 +461,7 @@
}
/**
- * ospf_disp - invokes routing table calctulation, aging and also area_disp()
+ * ospf_disp - invokes routing table calculation, aging and also area_disp()
* @timer: timer usually called every @proto_ospf->tick second, @timer->data
* point to @proto_ospf
*/
@@ -480,11 +499,15 @@
ospf_import_control(struct proto *p, rte ** new, ea_list ** attrs,
struct linpool *pool)
{
+ struct ospf_area *oa = ospf_main_area((struct proto_ospf *) p);
rte *e = *new;
if (p == e->attrs->proto)
return -1; /* Reject our own routes */
+ if (oa_is_stub(oa))
+ return -1; /* Do not export routes to stub areas */
+
eattr *ea = ea_find(e->attrs->eattrs, EA_GEN_IGP_METRIC);
u32 m1 = (ea && (ea->u.data < LSINFINITY)) ? ea->u.data : LSINFINITY;
@@ -543,16 +566,38 @@
ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * old UNUSED, ea_list * attrs)
{
struct proto_ospf *po = (struct proto_ospf *) p;
+ struct ospf_area *oa = ospf_main_area(po);
+ ort *nf = (ort *) fib_get(&po->rtf, &n->n.prefix, n->n.pxlen);
+ struct fib_node *fn = &nf->fn;
+
+ if (!new)
+ {
+ if (fn->x1 != EXT_EXPORT)
+ return;
-/* Temporarily down write anything
- OSPF_TRACE(D_EVENTS, "Got route %I/%d %s", p->name, n->n.prefix,
- n->n.pxlen, new ? "up" : "down");
-*/
+ flush_ext_lsa(oa, fn);
- if (new) /* Got some new route */
- originate_ext_lsa(n, new, po, attrs);
- else
- flush_ext_lsa(n, po);
+ /* Old external route might blocked some NSSA translation */
+ if (po->areano > 1)
+ schedule_rtcalc(po);
+
+ return;
+ }
+
+ /* Get route attributes */
+ u32 m1 = ea_get_int(attrs, EA_OSPF_METRIC1, LSINFINITY);
+ u32 m2 = ea_get_int(attrs, EA_OSPF_METRIC2, 10000);
+ u32 metric = (m1 != LSINFINITY) ? m1 : (m2 | LSA_EXT_EBIT);
+ u32 tag = ea_get_int(attrs, EA_OSPF_TAG, 0);
+ ip_addr gw = IPA_NONE;
+ // FIXME check for gw should be per ifa, not per iface
+ if ((new->attrs->dest == RTD_ROUTER) &&
+ ipa_nonzero(new->attrs->gw) &&
+ !ipa_has_link_scope(new->attrs->gw) &&
+ (ospf_iface_find((struct proto_ospf *) p, new->attrs->iface) != NULL))
+ gw = new->attrs->gw;
+
+ originate_ext_lsa(oa, fn, EXT_EXPORT, metric, gw, tag, 1);
}
static void
@@ -605,7 +650,7 @@
if (rte->attrs->source == RTS_OSPF_EXT2)
buf += bsprintf(buf, "/%d", rte->u.ospf.metric2);
buf += bsprintf(buf, ")");
- if ((rte->attrs->source == RTS_OSPF_EXT2 || rte->attrs->source == RTS_OSPF_EXT1) && rte->u.ospf.tag)
+ if ((rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2) && rte->u.ospf.tag)
{
buf += bsprintf(buf, " [%x]", rte->u.ospf.tag);
}
@@ -639,12 +684,21 @@
ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
{
oa->ac = nac;
- oa->stub = nac->stub;
+
+ // FIXME better area type reconfiguration
+#ifdef OSPFv2
+ oa->options = nac->type;
+#else /* OSPFv3 */
+ oa->options = OPT_R | nac->type | OPT_V6;
+#endif
+ if (oa_is_nssa(oa) && (oa->po->areano > 1))
+ oa->po->ebit = 1;
ospf_ifaces_reconfigure(oa, nac);
/* Handle net_list */
fib_free(&oa->net_fib);
+ fib_free(&oa->enet_fib);
add_area_nets(oa, nac);
/* No need to handle stubnet_list */
@@ -797,8 +851,14 @@
}
}
}
- cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No");
+
+ cli_msg(-1014, "\t\tStub:\t%s", oa_is_stub(oa) ? "Yes" : "No");
+ cli_msg(-1014, "\t\tNSSA:\t%s", oa_is_nssa(oa) ? "Yes" : "No");
cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No");
+
+ if (oa_is_nssa(oa))
+ cli_msg(-1014, "\t\tNSSA translation:\t%s%s", oa->translate ? "Yes" : "No",
+ oa->translate == TRANS_WAIT ? " (run down)" : "");
cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano);
cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);
cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno);
@@ -816,6 +876,21 @@
anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
}
FIB_WALK_END;
+
+ firstfib = 1;
+ FIB_WALK(&oa->enet_fib, nftmp)
+ {
+ anet = (struct area_net *) nftmp;
+ if(firstfib)
+ {
+ cli_msg(-1014, "\t\tArea external networks:");
+ firstfib = 0;
+ }
+ cli_msg(-1014, "\t\t\t%1I/%u\t%s\t%s", anet->fn.prefix, anet->fn.pxlen,
+ anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
+ }
+ FIB_WALK_END;
+
}
cli_msg(0, "");
}
@@ -1096,7 +1171,8 @@
int pxlen, ebit, rt_fwaddr_valid;
u32 rt_tag, rt_metric;
- he->domain = 0; /* Unmark the LSA */
+ if (he->lsa.type == LSA_T_EXT)
+ he->domain = 0; /* Unmark the LSA */
rt_metric = ext->metric & METRIC_MASK;
ebit = ext->metric & LSA_EXT_EBIT;
@@ -1130,8 +1206,9 @@
if (rt_tag)
bsprintf(str_tag, " tag %08x", rt_tag);
- cli_msg(-1016, "\t\texternal %I/%d metric%s %u%s%s", ip, pxlen,
- ebit ? "2" : "", rt_metric, str_via, str_tag);
+ cli_msg(-1016, "\t\t%s %I/%d metric%s %u%s%s",
+ (he->lsa.type == LSA_T_NSSA) ? "nssa-ext" : "external",
+ ip, pxlen, ebit ? "2" : "", rt_metric, str_via, str_tag);
}
#ifdef OSPFv3
@@ -1206,6 +1283,7 @@
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
+ case LSA_T_NSSA:
#ifdef OSPFv3
case LSA_T_PREFIX:
#endif
@@ -1307,6 +1385,7 @@
#endif
case LSA_T_EXT:
+ case LSA_T_NSSA:
show_lsa_external(he);
break;
}
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/ospf.h
^
|
@@ -75,6 +75,7 @@
#define DEFAULT_RFC1583 0 /* compatibility with rfc1583 */
#define DEFAULT_STUB_COST 1000
#define DEFAULT_ECMP_LIMIT 16
+#define DEFAULT_TRANSINT 40
struct ospf_config
@@ -101,6 +102,7 @@
node n;
struct prefix px;
int hidden;
+ u32 tag;
};
struct area_net
@@ -109,6 +111,7 @@
int hidden;
int active;
u32 metric;
+ u32 tag;
};
struct ospf_stubnet_config
@@ -123,9 +126,16 @@
{
node n;
u32 areaid;
- u32 stub;
+ u32 default_cost; /* Cost of default route for stub areas */
+ u8 type; /* Area type (standard, stub, NSSA), represented
+ by option flags (OPT_E, OPT_N) */
+ u8 summary; /* Import summaries to this stub/NSSA area, valid for ABR */
+ u8 default_nssa; /* Generate default NSSA route for NSSA+summary area */
+ u8 translator; /* Translator role, for NSSA ABR */
+ u32 transint; /* Translator stability interval */
list patt_list;
list net_list; /* List of aggregate networks for that area */
+ list enet_list; /* List of aggregate external (NSSA) networks */
list stubnet_list; /* List of stub networks added to Router LSA */
};
@@ -137,12 +147,14 @@
#define OPT_DC 0x20
#ifdef OSPFv2
+#define OPT_P 0x08 /* flags P and N share position, see NSSA RFC */
#define OPT_EA 0x10
/* VEB flags are are stored independently in 'u16 options' */
#define OPT_RT_B (0x01 << 8)
#define OPT_RT_E (0x02 << 8)
#define OPT_RT_V (0x04 << 8)
+#define OPT_RT_NT (0x10 << 8)
#endif
#ifdef OSPFv3
@@ -363,6 +375,7 @@
#define LSA_T_SUM_NET 3
#define LSA_T_SUM_RT 4
#define LSA_T_EXT 5
+#define LSA_T_NSSA 7
#define LSA_SCOPE_AREA 0x2000
#define LSA_SCOPE_AS 0x4000
@@ -377,6 +390,7 @@
#define LSA_T_SUM_NET 0x2003
#define LSA_T_SUM_RT 0x2004
#define LSA_T_EXT 0x4005
+#define LSA_T_NSSA 0x2007
#define LSA_T_LINK 0x0008
#define LSA_T_PREFIX 0x2009
@@ -720,20 +734,26 @@
{
node n;
u32 areaid;
- struct ospf_area_config *ac; /* Related area config, might be NULL */
+ struct ospf_area_config *ac; /* Related area config */
struct top_hash_entry *rt; /* My own router LSA */
struct top_hash_entry *pxr_lsa; /* Originated prefix LSA */
list cand; /* List of candidates for RT calc. */
struct fib net_fib; /* Networks to advertise or not */
- u32 stub; /* 0 or stub area cost */
+ struct fib enet_fib; /* External networks for NSSAs */
u32 options; /* Optional features */
byte origrt; /* Rt lsa origination scheduled? */
byte trcap; /* Transit capability? */
byte marked; /* Used in OSPF reconfigure */
+ byte translate; /* Translator state (TRANS_*), for NSSA ABR */
+ timer *translator_timer; /* For NSSA translator switch */
struct proto_ospf *po;
struct fib rtr; /* Routing tables for routers */
};
+#define TRANS_OFF 0
+#define TRANS_ON 1
+#define TRANS_WAIT 2 /* Waiting before the end of translation */
+
struct proto_ospf
{
struct proto proto;
@@ -796,7 +816,6 @@
#endif
};
-
int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
struct linpool *pool);
struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
@@ -806,6 +825,16 @@
void schedule_net_lsa(struct ospf_iface *ifa);
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
+static inline struct ospf_area *ospf_main_area(struct proto_ospf *po)
+{ return (po->areano == 1) ? HEAD(po->area_list) : po->backbone; }
+
+static inline int oa_is_stub(struct ospf_area *oa)
+{ return (oa->options & (OPT_E | OPT_N)) == 0; }
+static inline int oa_is_ext(struct ospf_area *oa)
+{ return oa->options & OPT_E; }
+static inline int oa_is_nssa(struct ospf_area *oa)
+{ return oa->options & OPT_N; }
+
#ifdef OSPFv3
void schedule_link_lsa(struct ospf_iface *ifa);
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/rt.c
^
|
@@ -33,7 +33,7 @@
ort *ri = (ort *) fn;
reset_ri(ri);
ri->old_rta = NULL;
- ri->fn.x0 = 0;
+ ri->fn.x0 = ri->fn.x1 = 0;
}
static inline int
@@ -128,6 +128,23 @@
return 0;
}
+static int
+orta_prio(orta *nf)
+{
+ /* RFC 3103 2.5 (6e) priorities */
+ u32 opts = nf->options & (ORTA_NSSA | ORTA_PROP);
+
+ /* A Type-7 LSA with the P-bit set */
+ if (opts == (ORTA_NSSA | ORTA_PROP))
+ return 2;
+
+ /* A Type-5 LSA */
+ if (opts == 0)
+ return 1;
+
+ return 0;
+}
+
/* 16.4. (6), return 1 if new is better */
static int
ri_better_ext(struct proto_ospf *po, orta *new, orta *old)
@@ -172,6 +189,20 @@
if (new->metric1 > old->metric1)
return 0;
+ /* RFC 3103, 2.5. (6e) */
+ int new_prio = orta_prio(new);
+ int old_prio = orta_prio(old);
+
+ if (new_prio > old_prio)
+ return 1;
+
+ if (old_prio > new_prio)
+ return 0;
+
+ /* make it more deterministic */
+ if (new->rid > old->rid)
+ return 1;
+
return 0;
}
@@ -213,7 +244,7 @@
{
struct ospf_iface *ifa;
WALK_LIST(ifa, oa->po->iface_list)
- if (pos >= ifa->rt_pos_beg && pos < ifa->rt_pos_end)
+ if (ifa->oa == oa && pos >= ifa->rt_pos_beg && pos < ifa->rt_pos_end)
return ifa;
return NULL;
}
@@ -224,7 +255,7 @@
{
struct ospf_iface *ifa;
WALK_LIST(ifa, oa->po->iface_list)
- if (pos >= ifa->px_pos_beg && pos < ifa->px_pos_end)
+ if (ifa->oa == oa && pos >= ifa->px_pos_beg && pos < ifa->px_pos_end)
return ifa;
return NULL;
}
@@ -826,7 +857,8 @@
static int
decide_anet_lsa(struct ospf_area *oa, struct area_net *anet, struct ospf_area *anet_oa)
{
- if (oa->stub)
+ /* 12.4.3.1. - for stub/NSSA areas, originating summary routes is configurable */
+ if (!oa_is_ext(oa) && !oa->ac->summary)
return 0;
if (oa == anet_oa)
@@ -843,8 +875,8 @@
static int
decide_sum_lsa(struct ospf_area *oa, ort *nf, int dest)
{
- /* 12.4.3.1. - do not send summary into stub areas, we send just default route */
- if (oa->stub)
+ /* 12.4.3.1. - for stub/NSSA areas, originating summary routes is configurable */
+ if (!oa_is_ext(oa) && !oa->ac->summary)
return 0;
/* Invalid field - no route */
@@ -872,7 +904,7 @@
{
/* We call decide_sum_lsa() on preferred ASBR entries, no need for 16.4. (3) */
/* 12.4.3 p1 */
- return (nf->n.options & ORTA_ASBR);
+ return oa_is_ext(oa) && (nf->n.options & ORTA_ASBR);
}
/* 12.4.3 p7 - inter-area route */
@@ -946,6 +978,96 @@
}
}
+static inline int
+decide_nssa_lsa(ort *nf, u32 *rt_metric, ip_addr *rt_fwaddr, u32 *rt_tag)
+{
+ struct ospf_area *oa = nf->n.oa;
+ struct top_hash_entry *en = nf->n.en;
+ int propagate;
+
+ if (!rt_is_nssa(nf) || !oa->translate)
+ return 0;
+
+ /* Condensed area network found */
+ if (fib_route(&oa->enet_fib, nf->fn.prefix, nf->fn.pxlen))
+ return 0;
+
+ if (!en || (en->lsa.type != LSA_T_NSSA))
+ return 0;
+
+ /* We do not store needed data in struct orta, we have to parse the LSA */
+ struct ospf_lsa_ext *le = en->lsa_body;
+
+#ifdef OSPFv2
+ *rt_fwaddr = le->fwaddr;
+ *rt_tag = le->tag;
+ propagate = en->lsa.options & OPT_P;
+#else /* OSPFv3 */
+ u32 *buf = le->rest;
+ u8 pxlen = (*buf >> 24);
+ u8 pxopts = (*buf >> 16);
+ buf += IPV6_PREFIX_WORDS(pxlen); /* Skip the IP prefix */
+
+ if (pxopts & OPT_PX_NU)
+ return 0;
+
+ if (le->metric & LSA_EXT_FBIT)
+ buf = lsa_get_ipv6_addr(buf, rt_fwaddr);
+ else
+ *rt_fwaddr = IPA_NONE;
+
+ if (le->metric & LSA_EXT_TBIT)
+ *rt_tag = *buf++;
+ else
+ *rt_tag = 0;
+
+ propagate = pxopts & OPT_PX_P;
+#endif
+
+ if (!propagate || ipa_zero(*rt_fwaddr))
+ return 0;
+
+ *rt_metric = le->metric & (METRIC_MASK | LSA_EXT_EBIT);
+ return 1;
+}
+
+/* RFC 3103 3.2 - translating Type-7 LSAs into Type-5 LSAs */
+static inline void
+check_nssa_lsa(struct proto_ospf *po, ort *nf)
+{
+ struct fib_node *fn = &nf->fn;
+ struct area_net *anet = NULL;
+ struct ospf_area *oa = NULL;
+ u32 rt_metric, rt_tag;
+ ip_addr rt_fwaddr;
+
+ /* Do not translate LSA if there is already the external LSA from route export */
+ if (fn->x1 == EXT_EXPORT)
+ return;
+
+ /* RT entry marked as area network */
+ if (fn->x0)
+ {
+ /* Find that area network */
+ WALK_LIST(oa, po->area_list)
+ {
+ anet = (struct area_net *) fib_find(&oa->enet_fib, &fn->prefix, fn->pxlen);
+ if (anet)
+ break;
+ }
+ }
+
+ /* RFC 3103 3.2 (3) - originate the aggregated address range */
+ if (anet && anet->active && !anet->hidden && oa->translate)
+ originate_ext_lsa(po->backbone, fn, EXT_NSSA, anet->metric, IPA_NONE, anet->tag, 0);
+
+ /* RFC 3103 3.2 (2) - originate the same network */
+ else if (decide_nssa_lsa(nf, &rt_metric, &rt_fwaddr, &rt_tag))
+ originate_ext_lsa(po->backbone, fn, EXT_NSSA, rt_metric, rt_fwaddr, rt_tag, 0);
+
+ else if (fn->x1 == EXT_NSSA)
+ flush_ext_lsa(po->backbone, fn);
+}
/* RFC 2328 16.7. p2 - find new/lost vlink endpoints */
static void
@@ -997,9 +1119,10 @@
}
}
+
/* Miscellaneous route processing that needs to be done by ABRs */
static void
-ospf_rt_abr(struct proto_ospf *po)
+ospf_rt_abr1(struct proto_ospf *po)
{
struct area_net *anet;
ort *nf, *default_nf;
@@ -1048,21 +1171,38 @@
WALK_LIST(oa, po->area_list)
{
- /* 12.4.3.1. - originate or flush default summary LSA for stub areas */
- if (oa->stub)
- originate_sum_net_lsa(oa, &default_nf->fn, oa->stub);
+ /* 12.4.3.1. - originate or flush default route for stub/NSSA areas */
+ if (oa_is_stub(oa) || (oa_is_nssa(oa) && !oa->ac->summary))
+ originate_sum_net_lsa(oa, &default_nf->fn, oa->ac->default_cost);
else
flush_sum_lsa(oa, &default_nf->fn, ORT_NET);
+ /*
+ * Originate type-7 default route for NSSA areas
+ *
+ * Because type-7 default LSAs are originated by ABRs, they do not
+ * collide with other type-7 LSAs (as ABRs generate type-5 LSAs
+ * for both external route export or external-NSSA translation),
+ * so we use 0 for the src arg.
+ */
+
+ if (oa_is_nssa(oa) && oa->ac->default_nssa)
+ originate_ext_lsa(oa, &default_nf->fn, 0, oa->ac->default_cost, IPA_NONE, 0, 0);
+ else
+ flush_ext_lsa(oa, &default_nf->fn);
+
/* RFC 2328 16.4. (3) - precompute preferred ASBR entries */
- FIB_WALK(&oa->rtr, nftmp)
+ if (oa_is_ext(oa))
{
- nf = (ort *) nftmp;
- if (nf->n.options & ORTA_ASBR)
- ri_install_asbr(po, &nf->fn.prefix, &nf->n);
+ FIB_WALK(&oa->rtr, nftmp)
+ {
+ nf = (ort *) nftmp;
+ if (nf->n.options & ORTA_ASBR)
+ ri_install_asbr(po, &nf->fn.prefix, &nf->n);
+ }
+ FIB_WALK_END;
}
- FIB_WALK_END;
}
@@ -1078,6 +1218,124 @@
ospf_check_vlinks(po);
}
+
+static void
+translator_timer_hook(timer *timer)
+{
+ struct ospf_area *oa = timer->data;
+
+ if (oa->translate != TRANS_WAIT)
+ return;
+
+ oa->translate = TRANS_OFF;
+ schedule_rtcalc(oa->po);
+}
+
+static void
+ospf_rt_abr2(struct proto_ospf *po)
+{
+ struct ospf_area *oa;
+ struct top_hash_entry *en;
+ ort *nf, *nf2;
+
+
+ /* RFC 3103 3.1 - type-7 translator election */
+ struct ospf_area *bb = po->backbone;
+ WALK_LIST(oa, po->area_list)
+ if (oa_is_nssa(oa))
+ {
+ int translate = 1;
+
+ if (oa->ac->translator)
+ goto decided;
+
+ FIB_WALK(&oa->rtr, nftmp)
+ {
+ nf = (ort *) nftmp;
+ if (!nf->n.type || !(nf->n.options & ORTA_ABR))
+ continue;
+
+ nf2 = fib_find(&bb->rtr, &nf->fn.prefix, MAX_PREFIX_LENGTH);
+ if (!nf2 || !nf2->n.type || !(nf2->n.options & ORTA_ABR))
+ continue;
+
+ en = ospf_hash_find_rt(po->gr, oa->areaid, nf->n.rid);
+ if (!en || (en->color != INSPF))
+ continue;
+
+ struct ospf_lsa_rt *rt = en->lsa_body;
+ /* There is better candidate - Nt-bit or higher Router ID */
+ if ((rt->options & OPT_RT_NT) || (po->router_id < nf->n.rid))
+ {
+ translate = 0;
+ goto decided;
+ }
+ }
+ FIB_WALK_END;
+
+ decided:
+ if (translate && (oa->translate != TRANS_ON))
+ {
+ if (oa->translate == TRANS_WAIT)
+ tm_stop(oa->translator_timer);
+
+ oa->translate = TRANS_ON;
+ }
+
+ if (!translate && (oa->translate == TRANS_ON))
+ {
+ if (oa->translator_timer == NULL)
+ oa->translator_timer = tm_new_set(po->proto.pool, translator_timer_hook, oa, 0, 0);
+
+ /* Schedule the end of translation */
+ tm_start(oa->translator_timer, oa->ac->transint);
+ oa->translate = TRANS_WAIT;
+ }
+ }
+
+
+ /* Compute condensed external networks */
+ FIB_WALK(&po->rtf, nftmp)
+ {
+ nf = (ort *) nftmp;
+ if (rt_is_nssa(nf) && (nf->n.options & ORTA_PROP))
+ {
+ struct area_net *anet = (struct area_net *)
+ fib_route(&nf->n.oa->enet_fib, nf->fn.prefix, nf->fn.pxlen);
+
+ if (anet)
+ {
+ if (!anet->active)
+ {
+ anet->active = 1;
+
+ /* Get a RT entry and mark it to know that it is an area network */
+ nf2 = (ort *) fib_get(&po->rtf, &anet->fn.prefix, anet->fn.pxlen);
+ nf2->fn.x0 = 1;
+ }
+
+ u32 metric = (nf->n.type == RTS_OSPF_EXT1) ?
+ nf->n.metric1 : ((nf->n.metric2 + 1) | LSA_EXT_EBIT);
+
+ if (anet->metric < metric)
+ anet->metric = metric;
+ }
+ }
+ }
+ FIB_WALK_END;
+
+
+ FIB_WALK(&po->rtf, nftmp)
+ {
+ nf = (ort *) nftmp;
+
+ check_sum_net_lsa(po, nf);
+ check_nssa_lsa(po, nf);
+ }
+ FIB_WALK_END;
+}
+
+
/* Like fib_route(), but ignores dummy rt entries */
static void *
ospf_fib_route(struct fib *f, ip_addr a, int len)
@@ -1105,7 +1363,7 @@
struct top_hash_entry *en;
struct proto *p = &po->proto;
struct ospf_lsa_ext *le;
- int pxlen, ebit, rt_fwaddr_valid;
+ int pxlen, ebit, rt_fwaddr_valid, rt_propagate;
ip_addr ip, rtid, rt_fwaddr;
u32 br_metric, rt_metric, rt_tag;
struct ospf_area *atmp;
@@ -1116,7 +1374,7 @@
WALK_SLIST(en, po->lsal)
{
/* 16.4. (1) */
- if (en->lsa.type != LSA_T_EXT)
+ if ((en->lsa.type != LSA_T_EXT) && (en->lsa.type != LSA_T_NSSA))
continue;
if (en->lsa.age == LSA_MAXAGE)
@@ -1143,6 +1401,7 @@
rt_fwaddr = le->fwaddr;
rt_fwaddr_valid = !ipa_equal(rt_fwaddr, IPA_NONE);
rt_tag = le->tag;
+ rt_propagate = en->lsa.options & OPT_P;
#else /* OSPFv3 */
u8 pxopts;
u16 rest;
@@ -1162,6 +1421,8 @@
rt_tag = *buf++;
else
rt_tag = 0;
+
+ rt_propagate = pxopts & OPT_PX_P;
#endif
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
@@ -1171,10 +1432,19 @@
continue;
}
+
/* 16.4. (3) */
- /* If there are more areas, we already precomputed preferred ASBR entries
- in ospf_asbr_spf() and stored them in the backbone table */
- atmp = (po->areano > 1) ? po->backbone : HEAD(po->area_list);
+ /* If there are more areas, we already precomputed preferred ASBR
+ entries in ospf_rt_abr1() and stored them in the backbone
+ table. For NSSA, we examine the area to which the LSA is assigned */
+ if (en->lsa.type == LSA_T_EXT)
+ atmp = ospf_main_area(po);
+ else /* NSSA */
+ atmp = ospf_find_area(po, en->domain);
+
+ if (!atmp)
+ continue; /* Should not happen */
+
rtid = ipa_from_rid(en->lsa.rt);
nf1 = fib_find(&atmp->rtr, &rtid, MAX_PREFIX_LENGTH);
@@ -1184,6 +1454,12 @@
if (!(nf1->n.options & ORTA_ASBR))
continue; /* It is not ASBR */
+ /* 16.4. (3) NSSA - special rule for default routes */
+ /* ABR should use default only if P-bit is set and summaries are active */
+ if ((en->lsa.type == LSA_T_NSSA) && ipa_zero(ip) && (pxlen == 0) &&
+ (po->areano > 1) && !(rt_propagate && atmp->ac->summary))
+ continue;
+
if (!rt_fwaddr_valid)
{
nf2 = nf1;
@@ -1196,8 +1472,18 @@
if (!nf2)
continue;
- if ((nf2->n.type != RTS_OSPF) && (nf2->n.type != RTS_OSPF_IA))
- continue;
+ if (en->lsa.type == LSA_T_EXT)
+ {
+ /* For ext routes, we accept intra-area or inter-area routes */
+ if ((nf2->n.type != RTS_OSPF) && (nf2->n.type != RTS_OSPF_IA))
+ continue;
+ }
+ else /* NSSA */
+ {
+ /* For NSSA routes, we accept just intra-area in the same area */
+ if ((nf2->n.type != RTS_OSPF) || (nf2->n.oa != atmp))
+ continue;
+ }
/* Next-hop is a part of a configured stubnet */
if (!nf2->n.nhs)
@@ -1228,12 +1514,19 @@
/* Whether the route is preferred in route selection according to 16.4.1 */
nfa.options = epath_preferred(&nf2->n) ? ORTA_PREF : 0;
+ if (en->lsa.type == LSA_T_NSSA)
+ {
+ nfa.options |= ORTA_NSSA;
+ if (rt_propagate)
+ nfa.options |= ORTA_PROP;
+ }
nfa.tag = rt_tag;
nfa.rid = en->lsa.rt;
- nfa.oa = nf1->n.oa; /* undefined in RFC 2328 */
+ nfa.oa = atmp; /* undefined in RFC 2328 */
nfa.voa = NULL;
nfa.nhs = nhs;
+ nfa.en = en; /* store LSA for later (NSSA processing) */
ri_install_ext(po, ip, pxlen, &nfa);
}
@@ -1286,6 +1579,14 @@
anet->metric = 0;
}
FIB_WALK_END;
+
+ FIB_WALK(&oa->enet_fib, nftmp)
+ {
+ anet = (struct area_net *) nftmp;
+ anet->active = 0;
+ anet->metric = 0;
+ }
+ FIB_WALK_END;
}
}
}
@@ -1317,10 +1618,7 @@
ospf_rt_spfa(oa);
/* 16. (3) */
- if (po->areano == 1)
- ospf_rt_sum(HEAD(po->area_list));
- else
- ospf_rt_sum(po->backbone);
+ ospf_rt_sum(ospf_main_area(po));
/* 16. (4) */
WALK_LIST(oa, po->area_list)
@@ -1328,11 +1626,14 @@
ospf_rt_sum_tr(oa);
if (po->areano > 1)
- ospf_rt_abr(po);
+ ospf_rt_abr1(po);
/* 16. (5) */
ospf_ext_spf(po);
+ if (po->areano > 1)
+ ospf_rt_abr2(po);
+
rt_sync(po);
lp_flush(po->nhpool);
@@ -1679,9 +1980,6 @@
}
}
- if (po->areano > 1)
- check_sum_net_lsa(po, nf);
-
/* Remove configured stubnets */
if (!nf->n.nhs)
reset_ri(nf);
@@ -1744,7 +2042,7 @@
}
/* Remove unused rt entry. Entries with fn.x0 == 1 are persistent. */
- if (!nf->n.type && !nf->fn.x0)
+ if (!nf->n.type && !nf->fn.x0 && !nf->fn.x1)
{
FIB_ITERATE_PUT(&fit, nftmp);
fib_delete(fib, nftmp);
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/rt.h
^
|
@@ -35,6 +35,9 @@
* intra-area (type == RTS_OSPF) and its area is not a backbone.
*/
#define ORTA_PREF 0x80000000
+#define ORTA_NSSA 0x40000000
+#define ORTA_PROP 0x20000000
+
u32 metric1;
u32 metric2;
u32 tag;
@@ -43,13 +46,10 @@
struct ospf_area *voa; /* Used when route is replaced in ospf_rt_sum_tr(),
NULL otherwise */
struct mpnh *nhs; /* Next hops computed during SPF */
+ struct top_hash_entry *en; /* LSA responsible for this orta */
}
orta;
-// struct ospf_iface *ifa; /* Outgoing interface */
-// ip_addr nh; /* Next hop */
-
-
typedef struct ort
{
/*
@@ -57,6 +57,10 @@
* LSAs that don't have 'proper' rt entry (area networks + default to stubs)
* to keep uid stable (used for LSA ID in OSPFv3 - see fibnode_to_lsaid()).
*
+ * We use fn.x1 to note whether the external route was originated
+ * from the route export (in ospf_rt_notify()) or from the NSSA
+ * route translation (in check_nssa_lsa()).
+ *
* old_* values are here to represent the last route update. old_rta
* is cached (we keep reference), mainly for multipath nexthops.
* old_rta == NULL means route wasn not in the last update, in that
@@ -69,6 +73,12 @@
}
ort;
+static inline int rt_is_nssa(ort *nf)
+{ return nf->n.options & ORTA_NSSA; }
+
+#define EXT_EXPORT 1
+#define EXT_NSSA 2
+
/*
* Invariants for structs top_hash_entry (nodes of LSA db)
* enforced by SPF calculation for final nodes (color == INSPF):
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/topology.c
^
|
@@ -222,7 +222,10 @@
if (po->areano > 1)
rt->options |= OPT_RT_B;
- if ((po->ebit) && (!oa->stub))
+ if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
+ rt->options |= OPT_RT_NT;
+
+ if (po->ebit && !oa_is_stub(oa))
rt->options |= OPT_RT_E;
rt = NULL; /* buffer might be reallocated later */
@@ -388,7 +391,10 @@
if (po->areano > 1)
rt->options |= OPT_RT_B;
- if ((po->ebit) && (!oa->stub))
+ if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
+ rt->options |= OPT_RT_NT;
+
+ if (po->ebit && !oa_is_stub(oa))
rt->options |= OPT_RT_E;
rt = NULL; /* buffer might be reallocated later */
@@ -878,14 +884,14 @@
#ifdef OSPFv2
static inline void *
-originate_ext_lsa_body(struct proto_ospf *po, u16 *length, net *n,
- u32 metric, ip_addr fwaddr, u32 tag)
+originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
+ u32 metric, ip_addr fwaddr, u32 tag, int pbit UNUSED)
{
struct ospf_lsa_ext *ext = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_ext));
*length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_ext);
ext->metric = metric;
- ext->netmask = ipa_mkmask(n->n.pxlen);
+ ext->netmask = ipa_mkmask(fn->pxlen);
ext->fwaddr = fwaddr;
ext->tag = tag;
@@ -922,11 +928,11 @@
#else /* OSPFv3 */
static inline void *
-originate_ext_lsa_body(struct proto_ospf *po, u16 *length, net *n,
- u32 metric, ip_addr fwaddr, u32 tag)
+originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
+ u32 metric, ip_addr fwaddr, u32 tag, int pbit)
{
int size = sizeof(struct ospf_lsa_ext)
- + IPV6_PREFIX_SPACE(n->n.pxlen)
+ + IPV6_PREFIX_SPACE(fn->pxlen)
+ (ipa_nonzero(fwaddr) ? 16 : 0)
+ (tag ? 4 : 0);
@@ -936,7 +942,7 @@
ext->metric = metric;
u32 *buf = ext->rest;
- buf = put_ipv6_prefix(buf, n->n.prefix, n->n.pxlen, 0, 0);
+ buf = put_ipv6_prefix(buf, fn->prefix, fn->pxlen, pbit ? OPT_PX_P : 0, 0);
if (ipa_nonzero(fwaddr))
{
@@ -987,57 +993,113 @@
#endif
+static inline ip_addr
+find_surrogate_fwaddr(struct ospf_area *oa)
+{
+ struct proto_ospf *po = oa->po;
+ struct ospf_iface *ifa;
+ struct ifa *a, *cur_addr = NULL;
+ int np, cur_np = 0;
+
+ WALK_LIST(ifa, po->iface_list)
+ {
+ if ((ifa->oa != oa) ||
+ (ifa->state == OSPF_IS_DOWN) ||
+ (ifa->type == OSPF_IT_VLINK))
+ continue;
+
+#ifdef OSPFv2
+ a = ifa->addr;
+ if (a->flags & IA_PEER)
+ continue;
+
+ np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
+ if (np > cur_np)
+ {
+ cur_addr = a;
+ cur_np = np;
+ }
+
+#else /* OSPFv3 */
+ WALK_LIST(a, ifa->iface->addrs)
+ {
+ if ((a->flags & IA_SECONDARY) ||
+ (a->flags & IA_PEER) ||
+ (a->scope <= SCOPE_LINK))
+ continue;
+
+ np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
+ if (np > cur_np)
+ {
+ cur_addr = a;
+ cur_np = np;
+ }
+ }
+#endif
+ }
+
+ return cur_addr ? cur_addr->ip : IPA_NONE;
+}
+
+
/**
* originate_ext_lsa - new route received from nest and filters
- * @n: network prefix and mask
- * @e: rte
- * @po: current instance of OSPF
- * @attrs: list of extended attributes
+ * @oa: ospf_area for which LSA is originated
+ * @fn: network prefix and mask
+ * @src: the source of origination of the LSA (EXT_EXPORT/EXT_NSSA)
+ * @metric: the metric of a route
+ * @fwaddr: the forwarding address
+ * @tag: the route tag
+ * @pbit: P-bit for NSSA LSAs, ignored for external LSAs
*
* If I receive a message that new route is installed, I try to originate an
- * external LSA.
+ * external LSA. If @oa is an NSSA area, NSSA-LSA is originated instead.
+ * @oa should not be a stub area. @src does not specify whether the LSA
+ * is external or NSSA, but it specifies the source of origination -
+ * the export from ospf_rt_notify(), or the NSSA-EXT translation.
*
* The function also sets flag ebit. If it's the first time, the new router lsa
* origination is necessary.
*/
void
-originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
- struct ea_list *attrs)
+originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
+ u32 metric, ip_addr fwaddr, u32 tag, int pbit)
{
+ struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
- struct fib_node *fn = &n->n;
struct ospf_lsa_header lsa;
struct top_hash_entry *en = NULL;
void *body;
- struct ospf_area *oa;
+ int nssa = oa_is_nssa(oa);
+ u32 dom = nssa ? oa->areaid : 0;
- OSPF_TRACE(D_EVENTS, "Originating AS-external-LSA for %I/%d",
- fn->prefix, fn->pxlen);
+ OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d",
+ nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
lsa.age = 0;
#ifdef OSPFv2
- lsa.options = 0; /* or oa->options ? */
+ lsa.options = nssa ? (pbit ? OPT_P : 0) : OPT_E;
#endif
- lsa.type = LSA_T_EXT;
+ lsa.type = nssa ? LSA_T_NSSA : LSA_T_EXT;
lsa.id = fibnode_to_lsaid(po, fn);
lsa.rt = po->router_id;
- /* Compute LSA content */
- u32 m1 = ea_get_int(attrs, EA_OSPF_METRIC1, LSINFINITY);
- u32 m2 = ea_get_int(attrs, EA_OSPF_METRIC2, 10000);
- u32 metric = (m1 != LSINFINITY) ? m1 : (m2 | LSA_EXT_EBIT);
- u32 tag = ea_get_int(attrs, EA_OSPF_TAG, 0);
- ip_addr gw = IPA_NONE;
- // FIXME check for gw should be per ifa, not per iface
- if ((e->attrs->dest == RTD_ROUTER) &&
- ipa_nonzero(e->attrs->gw) &&
- !ipa_has_link_scope(e->attrs->gw) &&
- (ospf_iface_find((struct proto_ospf *) p, e->attrs->iface) != NULL))
- gw = e->attrs->gw;
+ if (nssa && pbit && ipa_zero(fwaddr))
+ {
+ /* NSSA-LSA with P-bit set must have non-zero forwarding address */
+
+ fwaddr = find_surrogate_fwaddr(oa);
+ if (ipa_zero(fwaddr))
+ {
+ log(L_ERR, "%s: Cannot find forwarding address for NSSA-LSA %I/%d",
+ p->name, fn->prefix, fn->pxlen);
+ return;
+ }
+ }
- if ((en = ospf_hash_find_header(po->gr, 0, &lsa)) != NULL)
+ if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
{
- int rv = check_ext_lsa(en, fn, metric, gw, tag);
+ int rv = check_ext_lsa(en, fn, metric, fwaddr, tag);
if (rv < 0)
{
log(L_ERR, "%s: LSAID collision for %I/%d",
@@ -1050,11 +1112,14 @@
}
lsa.sn = get_seqnum(en);
- body = originate_ext_lsa_body(po, &lsa.length, n, metric, gw, tag);
+ body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit);
lsasum_calculate(&lsa, body);
- en = lsa_install_new(po, &lsa, 0, body);
- ospf_lsupd_flood(po, NULL, NULL, &lsa, 0, 1);
+ if (src)
+ fn->x1 = src;
+
+ en = lsa_install_new(po, &lsa, dom, body);
+ ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
if (po->ebit == 0)
{
@@ -1067,18 +1132,21 @@
}
void
-flush_ext_lsa(net *n, struct proto_ospf *po)
+flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn)
{
+ struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
- struct fib_node *fn = &n->n;
struct top_hash_entry *en;
+ int nssa = oa_is_nssa(oa);
- OSPF_TRACE(D_EVENTS, "Flushing AS-external-LSA for %I/%d",
- fn->prefix, fn->pxlen);
+ OSPF_TRACE(D_EVENTS, "Flushing %s-LSA for %I/%d",
+ nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
+ u32 dom = nssa ? oa->areaid : 0;
+ u32 type = nssa ? LSA_T_NSSA : LSA_T_EXT;
u32 lsaid = fibnode_to_lsaid(po, fn);
- if (en = ospf_hash_find(po->gr, 0, lsaid, po->router_id, LSA_T_EXT))
+ if (en = ospf_hash_find(po->gr, dom, lsaid, po->router_id, type))
{
if (check_ext_lsa(en, fn, 0, IPA_NONE, 0) < 0)
{
@@ -1087,6 +1155,7 @@
return;
}
+ fn->x1 = 0;
ospf_lsupd_flush_nlsa(po, en);
}
}
@@ -1316,7 +1385,7 @@
return buf + IPV6_PREFIX_WORDS(pxl);
}
-/* FIXME eliminate items wit LA bit set? see 4.4.3.9 */
+/* FIXME eliminate items with LA bit set? see 4.4.3.9 */
static void
add_prefix(struct proto_ospf *po, u32 *px, int offset, int *pxc)
{
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/proto/ospf/topology.h
^
|
@@ -71,10 +71,8 @@
void originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric);
void originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options UNUSED);
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
-
-void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
- struct ea_list *attrs);
-void flush_ext_lsa(net *n, struct proto_ospf *po);
+void originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, u32 metric, ip_addr fwaddr, u32 tag, int pbit);
+void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn);
#ifdef OSPFv2
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/sysdep/autoconf.h.in
^
|
@@ -18,6 +18,9 @@
/* 32-bit integer type */
#define INTEGER_32 ?
+/* 64-bit integer type */
+#define INTEGER_64 ?
+
/* CPU endianity */
#undef CPU_LITTLE_ENDIAN
#undef CPU_BIG_ENDIAN
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/sysdep/bsd/krt-sock.c
^
|
@@ -697,6 +697,9 @@
void
krt_set_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
{
+ if (!krt_buffer)
+ return;
+
mb_free(krt_buffer);
krt_buffer = NULL;
}
@@ -719,6 +722,9 @@
void
krt_if_shutdown(struct kif_proto *p UNUSED)
{
+ if (!kif_buffer)
+ return;
+
mb_free(kif_buffer);
kif_buffer = NULL;
}
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/sysdep/bsd/sysio.h
^
|
@@ -237,3 +237,47 @@
return rv;
}
+
+
+#ifndef IPV6
+
+#ifdef IP_MINTTL
+
+static int
+sk_set_min_ttl4(sock *s, int ttl)
+{
+ if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
+ {
+ if (errno == ENOPROTOOPT)
+ log(L_ERR "Kernel does not support IPv4 TTL security");
+ else
+ log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
+
+ return -1;
+ }
+
+ return 0;
+}
+
+#else /* no IP_MINTTL */
+
+static int
+sk_set_min_ttl4(sock *s, int ttl)
+{
+ log(L_ERR "IPv4 TTL security not supported");
+ return -1;
+}
+
+#endif
+
+#else /* IPv6 */
+
+static int
+sk_set_min_ttl6(sock *s, int ttl)
+{
+ log(L_ERR "IPv6 TTL security not supported");
+ return -1;
+}
+
+#endif
+
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/sysdep/config.h
^
|
@@ -7,7 +7,7 @@
#define _BIRD_CONFIG_H_
/* BIRD version */
-#define BIRD_VERSION "1.3.2"
+#define BIRD_VERSION "1.3.3"
/* Include parameters determined by configure script */
#include "sysdep/autoconf.h"
@@ -30,6 +30,8 @@
typedef unsigned INTEGER_16 u16;
typedef INTEGER_32 s32;
typedef unsigned INTEGER_32 u32;
+typedef INTEGER_64 s64;
+typedef unsigned INTEGER_64 u64;
typedef u8 byte;
typedef u16 word;
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/sysdep/linux/sysio.h
^
|
@@ -309,3 +309,51 @@
*/
#endif
+
+
+#ifndef IP_MINTTL
+#define IP_MINTTL 21
+#endif
+
+#ifndef IPV6_MINHOPCOUNT
+#define IPV6_MINHOPCOUNT 73
+#endif
+
+
+#ifndef IPV6
+
+static int
+sk_set_min_ttl4(sock *s, int ttl)
+{
+ if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
+ {
+ if (errno == ENOPROTOOPT)
+ log(L_ERR "Kernel does not support IPv4 TTL security");
+ else
+ log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
+
+ return -1;
+ }
+
+ return 0;
+}
+
+#else
+
+static int
+sk_set_min_ttl6(sock *s, int ttl)
+{
+ if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
+ {
+ if (errno == ENOPROTOOPT)
+ log(L_ERR "Kernel does not support IPv6 TTL security");
+ else
+ log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
+
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/sysdep/linux/syspriv.h
^
|
@@ -7,6 +7,11 @@
#define _LINUX_CAPABILITY_U32S_3 2
#endif
+/* CAP_TO_MASK is missing in CentOS header files */
+#ifndef CAP_TO_MASK
+#define CAP_TO_MASK(x) (1 << ((x) & 31))
+#endif
+
/* capset() prototype is missing ... */
int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/sysdep/unix/io.c
^
|
@@ -805,7 +805,7 @@
}
/**
- * sk_set_ttl - set TTL for given socket.
+ * sk_set_ttl - set transmit TTL for given socket.
* @s: socket
* @ttl: TTL value
*
@@ -828,6 +828,28 @@
return (err ? -1 : 0);
}
+/**
+ * sk_set_min_ttl - set minimal accepted TTL for given socket.
+ * @s: socket
+ * @ttl: TTL value
+ *
+ * Can be used in TTL security implementation
+ *
+ * Result: 0 for success, -1 for an error.
+ */
+
+int
+sk_set_min_ttl(sock *s, int ttl)
+{
+ int err;
+#ifdef IPV6
+ err = sk_set_min_ttl6(s, ttl);
+#else
+ err = sk_set_min_ttl4(s, ttl);
+#endif
+
+ return err;
+}
/**
* sk_set_md5_auth - add / remove MD5 security association for given socket.
|
[-]
[+]
|
Changed |
bird-1.3.3.tar.bz2/sysdep/unix/main.c
^
|
@@ -17,6 +17,8 @@
#include <signal.h>
#include <pwd.h>
#include <grp.h>
+#include <sys/stat.h>
+#include <libgen.h>
#include "nest/bird.h"
#include "lib/lists.h"
@@ -149,18 +151,34 @@
#endif // PATH_IPROUTE_DIR
-static int conf_fd;
static char *config_name = PATH_CONFIG;
static int
-cf_read(byte *dest, unsigned int len)
+cf_read(byte *dest, unsigned int len, int fd)
{
- int l = read(conf_fd, dest, len);
+ int l = read(fd, dest, len);
if (l < 0)
cf_error("Read error");
return l;
}
+static int
+cf_open(char *filename)
+{
+ char full_name[BIRD_FNAME_MAX];
+ char *cur = filename;
+ int ret;
+
+ if (*filename != '/') {
+ snprintf(full_name, sizeof(full_name), "%s/%s", dirname(config_name), filename);
+ cur = full_name;
+ }
+
+ if ((ret = open(cur, O_RDONLY)) == -1)
+ cf_error("Unable to open included configuration file: %s", cur);
+}
+
+
void
sysdep_preconfig(struct config *c)
{
@@ -188,12 +206,13 @@
int ret;
*cp = conf;
- conf_fd = open(name, O_RDONLY);
- if (conf_fd < 0)
+ conf->file_fd = open(name, O_RDONLY);
+ if (conf->file_fd < 0)
return 0;
cf_read_hook = cf_read;
+ cf_open_hook = cf_open;
ret = config_parse(conf);
- close(conf_fd);
+ close(conf->file_fd);
return ret;
}
@@ -205,7 +224,7 @@
if (!unix_read_config(&conf, config_name))
{
if (conf->err_msg)
- die("%s, line %d: %s", config_name, conf->err_lino, conf->err_msg);
+ die("%s, line %d: %s", conf->err_file_name, conf->err_lino, conf->err_msg);
else
die("Unable to open configuration file %s: %m", config_name);
}
@@ -221,7 +240,7 @@
if (!unix_read_config(&conf, config_name))
{
if (conf->err_msg)
- log(L_ERR "%s, line %d: %s", config_name, conf->err_lino, conf->err_msg);
+ log(L_ERR "%s, line %d: %s", conf->err_file_name, conf->err_lino, conf->err_msg);
else
log(L_ERR "Unable to open configuration file %s: %m", config_name);
config_free(conf);
|