From: Ondrej Zajicek (work) Date: Tue, 8 Nov 2016 18:27:58 +0000 (+0100) Subject: Merge branch 'master' into int-new X-Git-Tag: v2.0.0-pre0~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8860e991f6650e47cfe6c1af595fe4fe92a4edfd;p=thirdparty%2Fbird.git Merge branch 'master' into int-new --- 8860e991f6650e47cfe6c1af595fe4fe92a4edfd diff --cc conf/Makefile index c1a906e3e,cd78c8212..e5828538d --- a/conf/Makefile +++ b/conf/Makefile @@@ -8,23 -11,23 +8,24 @@@ BISON_DEBUG=- #FLEX_DEBUG=-d endif -cf-parse.tab.h: cf-parse.tab.c +$(conf-y-targets): $(s)confbase.Y + $(M4) -P $| $^ >$@ -cf-parse.tab.c: cf-parse.y - $(BISON) -bcf-parse -dv -pcf_ $(BISON_DEBUG) cf-parse.y +$(o)cf-parse.y: | $(s)gen_parser.m4 +$(o)keywords.h: | $(s)gen_keywords.m4 +$(o)commands.h: | $(s)gen_commands.m4 $(srcdir)/client/cmds.m4 -cf-parse.y: $(conf-fragments) $(conf-src)/gen_parser.m4 - $(M4) -P $(conf-src)/gen_parser.m4 $(conf-fragments) >cf-parse.y +$(o)cf-parse.tab.h: $(o)cf-parse.tab.c -keywords.h: $(conf-fragments) $(conf-src)/gen_keywords.m4 - $(M4) -P $(conf-src)/gen_keywords.m4 $(conf-fragments) >keywords.h +$(o)cf-parse.tab.c: $(o)cf-parse.y + $(BISON) $(BISON_DEBUG) -dv -pcf_ -b $(@:.tab.c=) $< -commands.h: $(conf-fragments) $(conf-src)/gen_commands.m4 $(srcdir)/client/cmds.m4 - $(M4) -P $(conf-src)/gen_commands.m4 $(srcdir)/client/cmds.m4 $(conf-fragments) | sort >commands.h +$(o)cf-lex.c: $(s)cf-lex.l + $(FLEX) $(FLEX_DEBUG) -s -B -8 -Pcf_ -o$@ $< -cf-lex.c: cf-lex.l - $(FLEX) $(FLEX_DEBUG) -s -B -8 -ocf-lex.c -Pcf_ cf-lex.l +$(o)cf-lex.o: $(o)cf-parse.tab.h $(o)keywords.h ++$(o)cf-lex.o: CFLAGS+=-Wno-sign-compare -Wno-unused-function -depend: keywords.h commands.h cf-parse.tab.c cf-lex.c +$(addprefix $(o), cf-parse.y keywords.h commands.h cf-parse.tab.h cf-parse.tab.c cf-lex.c): $(objdir)/.dir-stamp -cf-lex.o: CFLAGS+=-Wno-sign-compare -Wno-unused-function +$(call clean,cf-parse.tab.h cf-parse.tab.c cf-parse.y keywords.h commands.h cf-lex.c cf-parse.output) diff --cc conf/conf.h index 03fecd32a,41cb434fd..593a5f132 --- a/conf/conf.h +++ b/conf/conf.h @@@ -20,7 -20,8 +20,7 @@@ struct config linpool *mem; /* Linear pool containing configuration data */ list protos; /* Configured protocol instances (struct proto_config) */ list tables; /* Configured routing tables (struct rtable_config) */ - list logfiles; /* Configured log fils (sysdep) */ - list roa_tables; /* Configured ROA tables (struct roa_table_config) */ + list logfiles; /* Configured log files (sysdep) */ int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */ char *syslog_name; /* Name used for syslog (NULL -> no syslog) */ diff --cc conf/confbase.Y index 22edbdfdb,96b32028c..094c81b55 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@@ -182,88 -168,19 +182,88 @@@ pxlen4 } ; -prefix_or_ipa: - prefix - | ipa { $$.addr = $1; $$.len = BITS_PER_IP_ADDRESS; } +net_ip4_: IP4 pxlen4 +{ + net_fill_ip4(&($$), $1, $2); + if (!net_validate_ip4((net_addr_ip4 *) &($$))) + cf_error("Invalid IPv4 prefix"); +}; + +net_ip6_: IP6 '/' NUM +{ + net_fill_ip6(&($$), $1, $3); + if ($3 < 0 || $3 > IP6_MAX_PREFIX_LENGTH) + cf_error("Invalid prefix length %d", $3); + if (!net_validate_ip6((net_addr_ip6 *) &($$))) + cf_error("Invalid IPv6 prefix"); +}; + +net_roa4_: net_ip4_ MAX NUM AS NUM +{ + $$ = cfg_alloc(sizeof(net_addr_roa4)); + net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5); - if ($3 < net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH) ++ if ($3 < (int) net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH) + cf_error("Invalid max prefix length %d", $3); +}; + +net_roa6_: net_ip6_ MAX NUM AS NUM +{ + $$ = cfg_alloc(sizeof(net_addr_roa6)); + net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5); - if ($3 < net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH) ++ if ($3 < (int) net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH) + cf_error("Invalid max prefix length %d", $3); +}; + +net_ip_: net_ip4_ | net_ip6_ ; +net_roa_: net_roa4_ | net_roa6_ ; + +net_: + net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); } + | net_roa_ ; -pxlen: - '/' expr { - if ($2 < 0 || $2 > BITS_PER_IP_ADDRESS) cf_error("Invalid prefix length %d", $2); - $$ = $2; + +/* Networks - regular */ + +net_ip6: + net_ip6_ + | SYM { + if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6)) + cf_error("IPv6 network expected"); + $$ = * SYM_VAL($1).net; + } + ; + +net_ip: + net_ip_ + | SYM { + if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net)) + cf_error("IP network expected"); + $$ = * SYM_VAL($1).net; + } + ; + +net_any: + net_ + | SYM { + if ($1->class != (SYM_CONSTANT | T_NET)) + cf_error("Network expected"); + $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */ } - | ':' ipa { - $$ = ipa_masklen($2); - if ($$ < 0) cf_error("Invalid netmask %I", $2); + ; + +net_or_ipa: + net_ip4_ + | net_ip6_ + | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); } + | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); } + | SYM { + if ($1->class == (SYM_CONSTANT | T_IP)) + net_fill_ip_host(&($$), SYM_VAL($1).ip); + else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net)) + $$ = * SYM_VAL($1).net; + else + cf_error("IP address or network expected"); } ; diff --cc doc/Makefile index 3ff733894,70b73943f..4e7e91ebf --- a/doc/Makefile +++ b/doc/Makefile @@@ -1,48 -1,50 +1,49 @@@ -root-rel=../ -dir-name=doc - -ifneq ($(wildcard ../Rules),) -include ../Rules -else -srcdir=$(shell cd $(root-rel) ; pwd) -srcdir_abs=$(srcdir) -endif - # Force rebuilds -.PHONY: prog.sgml bird.sgml +.PHONY: progspell docs progdocs userdocs + +doc-srcdir := $(shell cd $(s) && pwd) +sgml2 := $(doc-srcdir)/sgml2 docs: progdocs userdocs -progdocs: prog.html prog.ps -userdocs: bird.html bird.pdf -prog.sgml: - $(srcdir)/tools/progdoc $(srcdir_abs) +doc-fmt = $(1): $(o)prog.$(1) $(o)bird.$(1) +$(call doc-fmt,html) +$(call doc-fmt,dvi) +$(call doc-fmt,ps) +$(call doc-fmt,pdf) -%.html: %.sgml - ./sgml2html $< +progdocs: $(o)prog.html $(o)prog.pdf +userdocs: $(o)bird.html $(o)bird.pdf +progspell: $(o)prog.spell -%.dvi: %.tex - latex $< - latex $< +$(o)prog.sgml: $(srcdir)/tools/progdoc $(objdir)/.dir-stamp + $(srcdir)/tools/progdoc $(srcdir) $@ -%.ps: %.dvi - dvips -D600 -ta4 -o $@ $< +$(o)%.sgml: $(s)%.sgml $(objdir)/.dir-stamp + cp $< $@ -%.pdf: %.tex - pdflatex $< - pdflatex $< +$(o)%.html: $(o)%.sgml + cd $(dir $@) && $(sgml2)html $(notdir $<) -%.tex: %.sgml - ./sgml2latex --output=tex $< ++$(o)%.tex: $(o)%.sgml ++ cd $(dir $@) && $(sgml2)latex --output=tex $(notdir $<) ++ +$(o)%.dvi: $(o)%.tex + cd $(dir $@) && TEXINPUTS=$(TEXINPUTS):$(doc-srcdir)/tex latex $(notdir $<) + cd $(dir $@) && TEXINPUTS=$(TEXINPUTS):$(doc-srcdir)/tex latex $(notdir $<) + +$(o)%.ps: $(o)%.dvi + dvips -D600 -ta4 -o $@ $< - $(o)%.pdf: $(o)%.ps - ps2pdf $< $@ - - $(o)%.tex: $(o)%.sgml - cd $(dir $@) && $(sgml2)latex --output=tex $(notdir $<) -%.txt: %.sgml - ./sgml2txt $< ++$(o)%.pdf: $(o)%.tex ++ pdflatex -output-directory=$(dir $@) $< ++ pdflatex -output-directory=$(dir $@) $< -progspell: prog.sgml - sed -f prog-spell.sed prog.spell - ispell prog.spell +$(o)%.txt: $(o)%.sgml + cd $(dir $@) && $(sgml2)txt $(notdir $<) -clean: - rm -f *.tex *.dvi *.log *.txt *.aux *.toc *.spell - rm -f prog.sgml +$(o)prog.spell: $(o)prog.sgml $(s)prog-spell.sed + sed -f $(lastword $^) <$< >$@ + ispell $@ -distclean: clean - rm -f *.html *.ps +$(call clean,prog.spell $(addprefix *.,html dvi ps pdf sgml tex txt aux log toc)) diff --cc filter/config.Y index 3eb5b08f2,5ea83f81b..8af444a3b --- a/filter/config.Y +++ b/filter/config.Y @@@ -291,12 -350,11 +348,12 @@@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UN %type 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 filter filter_body where_filter - %type type break_command pair_expr ec_kind - %type pair_atom ec_expr - %type pair_item ec_item set_item switch_item set_items switch_items switch_body + %type type break_command ec_kind + %type cnum + %type pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body %type fprefix_set -%type set_atom switch_atom fprefix fprefix_s fipa +%type set_atom switch_atom fipa +%type fprefix %type decls declsn one_decl function_params %type bgp_path bgp_path_tail1 bgp_path_tail2 diff --cc filter/filter.c index 3282bd50f,85a062586..09b89401a --- a/filter/filter.c +++ b/filter/filter.c @@@ -96,9 -94,30 +96,21 @@@ pm_format(struct f_path_mask *p, buffe buffer_puts(buf, "=]"); } -static inline int -uint_cmp(uint i1, uint i2) -{ - return (int)(i1 > i2) - (int)(i1 < i2); -} - -static inline int -u64_cmp(u64 i1, u64 i2) -{ - return (int)(i1 > i2) - (int)(i1 < i2); -} +static inline int val_is_ip4(const struct f_val v) +{ return (v.type == T_IP) && ipa_is_ip4(v.val.ip); } + static inline int + lcomm_cmp(lcomm v1, lcomm v2) + { + if (v1.asn != v2.asn) + return (v1.asn > v2.asn) ? 1 : -1; + if (v1.ldp1 != v2.ldp1) + return (v1.ldp1 > v2.ldp1) ? 1 : -1; + if (v1.ldp2 != v2.ldp2) + return (v1.ldp2 > v2.ldp2) ? 1 : -1; + return 0; + } + /** * val_compare - compare two values * @v1: first value @@@ -138,10 -161,14 +150,12 @@@ val_compare(struct f_val v1, struct f_v return uint_cmp(v1.val.i, v2.val.i); case T_EC: return u64_cmp(v1.val.ec, v2.val.ec); + case T_LC: + return lcomm_cmp(v1.val.lc, v2.val.lc); case T_IP: - return ipa_compare(v1.val.px.ip, v2.val.px.ip); - case T_PREFIX: - if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip)) - return rc; - return uint_cmp(v1.val.px.len, v2.val.px.len); + return ipa_compare(v1.val.ip, v2.val.ip); + case T_NET: + return net_compare(v1.val.net, v2.val.net); case T_STRING: return strcmp(v1.val.s, v2.val.s); default: diff --cc filter/filter.h index af4901210,049ceb767..fc11b91eb --- a/filter/filter.h +++ b/filter/filter.h @@@ -35,12 -35,28 +35,23 @@@ struct f_inst { /* Instruction * /* Not enough fields in f_inst for three args used by roa_check() */ struct f_inst_roa_check { struct f_inst i; - struct roa_table_config *rtc; + struct rtable_config *rtc; }; + struct f_inst3 { + struct f_inst i; + union { + int i; + void *p; + } a3; + }; + + #define INST3(x) (((struct f_inst3 *) x)->a3) + + struct f_prefix { - ip_addr ip; - int len; -#define LEN_MASK 0xff -#define LEN_PLUS 0x1000000 -#define LEN_MINUS 0x2000000 -#define LEN_RANGE 0x4000000 - /* If range then prefix must be in range (len >> 16 & 0xff, len >> 8 & 0xff) */ + net_addr net; + u8 lo, hi; }; struct f_val { @@@ -48,8 -64,9 +59,9 @@@ union { uint i; u64 ec; + lcomm lc; - /* ip_addr ip; Folded into prefix */ - struct f_prefix px; + ip_addr ip; + const net_addr *net; char *s; struct f_tree *t; struct f_trie *ti; @@@ -175,7 -211,7 +189,7 @@@ struct f_tree struct f_trie_node { ip_addr addr, mask, accept; -- int plen; ++ uint plen; struct f_trie_node *c[2]; }; diff --cc filter/trie.c index dad873397,565ae82f6..adcfcdf3f --- a/filter/trie.c +++ b/filter/trie.c @@@ -219,8 -196,18 +219,8 @@@ trie_add_prefix(struct f_trie *t, cons return a; } -/** - * trie_match_prefix - * @t: trie - * @px: prefix address - * @plen: prefix length - * - * Tries to find a matching prefix pattern in the trie such that - * prefix @px/@plen matches that prefix pattern. Returns 1 if there - * is such prefix pattern in the trie. - */ -int -trie_match_prefix(struct f_trie *t, ip_addr px, int plen) +static int - trie_match_prefix(struct f_trie *t, ip_addr px, int plen) ++trie_match_prefix(struct f_trie *t, ip_addr px, uint plen) { ip_addr pmask = ipa_mkmask(plen); ip_addr paddr = ipa_and(px, pmask); @@@ -254,29 -241,6 +254,30 @@@ return 0; } +/** + * trie_match_net + * @t: trie + * @n: net address + * + * Tries to find a matching net in the trie such that + * prefix @n matches that prefix pattern. Returns 1 if there + * is such prefix pattern in the trie. + */ +int +trie_match_net(struct f_trie *t, const net_addr *n) +{ - int add = 0; ++ uint add = 0; ++ + switch (n->type) { + case NET_IP4: + case NET_VPN4: + case NET_ROA4: + add = IP6_MAX_PREFIX_LENGTH - IP4_MAX_PREFIX_LENGTH; + } + + return trie_match_prefix(t, net_prefix(n), net_pxlen(n) + add); +} + static int trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2) { diff --cc lib/Makefile index 8e372bd31,000000000..551089c3b mode 100644,000000..100644 --- a/lib/Makefile +++ b/lib/Makefile @@@ -1,3 -1,0 +1,3 @@@ - src := bitops.c checksum.c event.c idm.c ip.c lists.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c xmalloc.c ++src := bitops.c checksum.c event.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c xmalloc.c +obj := $(src-o-files) +$(all-daemon) diff --cc lib/birdlib.h index 188e59b2f,37337078d..ddc963f47 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@@ -63,7 -62,14 +63,6 @@@ static inline int u64_cmp(u64 i1, u64 i #define UNUSED __attribute__((unused)) #define PACKED __attribute__((packed)) -#ifdef IPV6 -#define UNUSED4 -#define UNUSED6 UNUSED -#else -#define UNUSED4 UNUSED -#define UNUSED6 -#endif -- /* Microsecond time */ typedef s64 btime; diff --cc lib/hash.h index c2fd8bca5,4239b1d89..b37d8fa5f --- a/lib/hash.h +++ b/lib/hash.h @@@ -178,37 -188,4 +188,40 @@@ #define HASH_WALK_FILTER_END } while (0) ++ +static inline void +mem_hash_init(u64 *h) +{ + *h = 0x001047d54778bcafULL; +} + +static inline void - mem_hash_mix(u64 *h, void *p, int s) ++mem_hash_mix(u64 *h, void *p, uint s) +{ + const u64 multiplier = 0xb38bc09a61202731ULL; + const char *pp = p; + uint i; ++ + for (i=0; i> 32) ^ (*h & 0xffffffff)); +} + +static inline uint - mem_hash(void *p, int s) ++mem_hash(void *p, uint s) +{ + static u64 h; + mem_hash_init(&h); + mem_hash_mix(&h, p, s); + return mem_hash_value(&h); +} + + #endif diff --cc lib/idm.c index 16d0e855e,000000000..66e311c6a mode 100644,000000..100644 --- a/lib/idm.c +++ b/lib/idm.c @@@ -1,76 -1,0 +1,76 @@@ +/* + * BIRD Library -- ID Map + * + * (c) 2013--2015 Ondrej Zajicek + * (c) 2013--2015 CZ.NIC z.s.p.o. + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#include + +#include "nest/bird.h" +#include "lib/idm.h" +#include "lib/resource.h" +#include "lib/string.h" + + +void +idm_init(struct idm *m, pool *p, uint size) +{ + m->pos = 0; + m->used = 1; + m->size = size; + m->data = mb_allocz(p, m->size * sizeof(u32)); + + /* ID 0 is reserved */ + m->data[0] = 1; +} + +static inline int u32_cto(uint x) { return ffs(~x) - 1; } + +u32 +idm_alloc(struct idm *m) +{ + uint i, j; + + for (i = m->pos; i < m->size; i++) + if (m->data[i] != 0xffffffff) + goto found; + + /* If we are at least 7/8 full, expand */ + if (m->used > (m->size * 28)) + { + m->size *= 2; + m->data = mb_realloc(m->data, m->size * sizeof(u32)); + memset(m->data + i, 0, (m->size - i) * sizeof(u32)); + goto found; + } + + for (i = 0; i < m->pos; i++) + if (m->data[i] != 0xffffffff) + goto found; + + ASSERT(0); + - found: ++found: + ASSERT(i < 0x8000000); + + m->pos = i; + j = u32_cto(m->data[i]); + + m->data[i] |= (1 << j); + m->used++; + return 32 * i + j; +} + +void +idm_free(struct idm *m, u32 id) +{ + uint i = id / 32; + uint j = id % 32; + + ASSERT((i < m->size) && (m->data[i] & (1 << j))); + m->data[i] &= ~(1 << j); + m->used--; +} diff --cc nest/config.Y index 2a746657b,878224fea..776e5d161 --- a/nest/config.Y +++ b/nest/config.Y @@@ -65,10 -56,10 +66,11 @@@ CF_DECL CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT) CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS) +CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6) CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) - CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE) /* ,ROA */ + CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512) -CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA) ++CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE) CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED) CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP) CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS) @@@ -85,11 -76,12 +87,11 @@@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALI %type rtable %type optsym %type r_args -%type roa_args -%type roa_table_arg %type sym_args - %type proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action net_type table_sorted tos -%type proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action tab_sorted tos password_algorithm ++%type proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action net_type table_sorted tos password_algorithm %type proto_patt proto_patt2 -%type limit_spec +%type channel_start proto_channel +%type limit_spec CF_GRAMMAR diff --cc nest/password.h index cbf80b99a,f21483c4d..78244985a --- a/nest/password.h +++ b/nest/password.h @@@ -9,7 -9,8 +9,8 @@@ #ifndef PASSWORD_H #define PASSWORD_H + -#include "lib/timer.h" +#include "sysdep/unix/timer.h" struct password_item { node n; diff --cc nest/route.h index a536def7b,383f4def0..f2e883b60 --- a/nest/route.h +++ b/nest/route.h @@@ -277,20 -268,16 +277,19 @@@ void rt_commit(struct config *new, stru void rt_lock_table(rtable *); void rt_unlock_table(rtable *); void rt_setup(pool *, rtable *, char *, struct rtable_config *); -static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); } -static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); } +static inline net *net_find(rtable *tab, const net_addr *addr) { return (net *) fib_find(&tab->fib, addr); } +static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) fib_get(&tab->fib, addr); } +void *net_route(rtable *tab, const net_addr *n); +int net_roa_check(rtable *tab, const net_addr *n, u32 asn); rte *rte_find(net *net, struct rte_src *src); rte *rte_get_temp(struct rta *); -void rte_update2(struct announce_hook *ah, net *net, rte *new, struct rte_src *src); -static inline void rte_update(struct proto *p, net *net, rte *new) { rte_update2(p->main_ahook, net, new, p->main_source); } -int rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter *filter); -rte *rt_export_merged(struct announce_hook *ah, net *net, rte **rt_free, struct ea_list **tmpa, linpool *pool, int silent); -void rt_refresh_begin(rtable *t, struct announce_hook *ah); -void rt_refresh_end(rtable *t, struct announce_hook *ah); +void rte_update2(struct channel *c, net_addr *n, rte *new, struct rte_src *src); +/* rte_update() moved to protocol.h to avoid dependency conflicts */ - void rte_discard(rtable *tab, rte *old); +int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter); +rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, struct ea_list **tmpa, linpool *pool, int silent); +void rt_refresh_begin(rtable *t, struct channel *c); +void rt_refresh_end(rtable *t, struct channel *c); +void rt_schedule_prune(rtable *t); void rte_dump(rte *); void rte_free(rte *); rte *rte_do_cow(rte *); diff --cc nest/rt-table.c index eb9dc3a50,c6e48c380..4260e4932 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@@ -63,155 -65,34 +63,155 @@@ make_tmp_attrs(struct rte *rt, struct l { struct ea_list *(*mta)(struct rte *rt, struct linpool *pool); mta = rt->attrs->src->proto->make_tmp_attrs; - return mta ? mta(rt, rte_update_pool) : NULL; + return mta ? mta(rt, pool) : NULL; } + /* Like fib_route(), but skips empty net entries */ -static net * -net_route(rtable *tab, ip_addr a, int len) +static inline void * +net_route_ip4(struct fib *f, net_addr_ip4 *n) { - ip_addr a0; - net *n; + net *r; + + while (r = fib_find(f, (net_addr *) n), + !(r && rte_is_valid(r->routes)) && (n->pxlen > 0)) + { + n->pxlen--; + ip4_clrbit(&n->prefix, n->pxlen); + } + + return r; +} + +static inline void * +net_route_ip6(struct fib *f, net_addr_ip6 *n) +{ + net *r; + + while (r = fib_find(f, (net_addr *) n), + !(r && rte_is_valid(r->routes)) && (n->pxlen > 0)) + { + n->pxlen--; + ip6_clrbit(&n->prefix, n->pxlen); + } + + return r; +} + +void * +net_route(rtable *tab, const net_addr *n) +{ + ASSERT(tab->addr_type == n->type); + + net_addr *n0 = alloca(n->length); + net_copy(n0, n); + + switch (n->type) + { + case NET_IP4: + case NET_VPN4: + case NET_ROA4: + return net_route_ip4(&tab->fib, (net_addr_ip4 *) n0); - while (len >= 0) + case NET_IP6: + case NET_VPN6: + case NET_ROA6: + return net_route_ip6(&tab->fib, (net_addr_ip6 *) n0); + + default: + return NULL; + } +} + + +static int +net_roa_check_ip4(rtable *tab, const net_addr_ip4 *px, u32 asn) +{ + struct net_addr_roa4 n = NET_ADDR_ROA4(px->prefix, px->pxlen, 0, 0); + struct fib_node *fn; + int anything = 0; + + while (1) + { + for (fn = fib_get_chain(&tab->fib, (net_addr *) &n); fn; fn = fn->next) { - a0 = ipa_and(a, ipa_mkmask(len)); - n = fib_find(&tab->fib, &a0, len); - if (n && rte_is_valid(n->routes)) - return n; - len--; + net_addr_roa4 *roa = (void *) fn->addr; + net *r = fib_node_to_user(&tab->fib, fn); + + if (net_equal_prefix_roa4(roa, &n) && rte_is_valid(r->routes)) + { + anything = 1; + if (asn && (roa->asn == asn) && (roa->max_pxlen >= px->pxlen)) + return ROA_VALID; + } } - return NULL; + + if (n.pxlen == 0) + break; + + n.pxlen--; + ip4_clrbit(&n.prefix, n.pxlen); + } + + return anything ? ROA_INVALID : ROA_UNKNOWN; } -static void -rte_init(struct fib_node *N) +static int +net_roa_check_ip6(rtable *tab, const net_addr_ip6 *px, u32 asn) { - net *n = (net *) N; + struct net_addr_roa6 n = NET_ADDR_ROA6(px->prefix, px->pxlen, 0, 0); + struct fib_node *fn; + int anything = 0; + + while (1) + { + for (fn = fib_get_chain(&tab->fib, (net_addr *) &n); fn; fn = fn->next) + { + net_addr_roa6 *roa = (void *) fn->addr; + net *r = fib_node_to_user(&tab->fib, fn); - N->flags = 0; - n->routes = NULL; + if (net_equal_prefix_roa6(roa, &n) && rte_is_valid(r->routes)) + { + anything = 1; + if (asn && (roa->asn == asn) && (roa->max_pxlen >= px->pxlen)) + return ROA_VALID; + } + } + + if (n.pxlen == 0) + break; + + n.pxlen--; + ip6_clrbit(&n.prefix, n.pxlen); + } + + return anything ? ROA_INVALID : ROA_UNKNOWN; +} + +/** + * roa_check - check validity of route origination in a ROA table + * @tab: ROA table + * @n: network prefix to check + * @asn: AS number of network prefix + * + * Implements RFC 6483 route validation for the given network prefix. The + * procedure is to find all candidate ROAs - ROAs whose prefixes cover the given + * network prefix. If there is no candidate ROA, return ROA_UNKNOWN. If there is + * a candidate ROA with matching ASN and maxlen field greater than or equal to + * the given prefix length, return ROA_VALID. Otherwise, return ROA_INVALID. If + * caller cannot determine origin AS, 0 could be used (in that case ROA_VALID + * cannot happen). Table @tab must have type NET_ROA4 or NET_ROA6, network @n + * must have type NET_IP4 or NET_IP6, respectively. + */ +int +net_roa_check(rtable *tab, const net_addr *n, u32 asn) +{ + if ((tab->addr_type == NET_ROA4) && (n->type == NET_IP4)) + return net_roa_check_ip4(tab, (const net_addr_ip4 *) n, asn); + else if ((tab->addr_type == NET_ROA6) && (n->type == NET_IP6)) + return net_roa_check_ip6(tab, (const net_addr_ip6 *) n, asn); + else + return ROA_UNKNOWN; /* Should not happen */ } /** @@@ -1686,17 -1598,16 +1686,17 @@@ again rescan: for (e=n->routes; e; e=e->next) - if (e->sender->proto->flushing || (e->flags & REF_DISCARD)) + if (e->sender->flush_active || (e->flags & REF_DISCARD)) { - if (*limit <= 0) + if (limit <= 0) { - FIB_ITERATE_PUT(fit, fn); - return 0; + FIB_ITERATE_PUT(fit); + ev_schedule(tab->rt_event); + return; } - rte_discard(tab, e); + rte_discard(e); - (*limit)--; + limit--; goto rescan; } @@@ -2166,11 -2104,11 +2166,11 @@@ hc_remove(struct hostcache *hc, struct static void hc_alloc_table(struct hostcache *hc, unsigned order) { - unsigned hsize = 1 << order; + uint hsize = 1 << order; hc->hash_order = order; - hc->hash_shift = 16 - order; + hc->hash_shift = 32 - order; - hc->hash_max = (order >= HC_HI_ORDER) ? ~0 : (hsize HC_HI_MARK); - hc->hash_min = (order <= HC_LO_ORDER) ? 0 : (hsize HC_LO_MARK); + hc->hash_max = (order >= HC_HI_ORDER) ? ~0U : (hsize HC_HI_MARK); + hc->hash_min = (order <= HC_LO_ORDER) ? 0U : (hsize HC_LO_MARK); hc->hash_table = mb_allocz(rt_table_pool, hsize * sizeof(struct hostentry *)); } diff --cc proto/ospf/hello.c index 3fbb61673,e00487dc6..2c55155d0 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@@ -222,9 -222,12 +222,12 @@@ ospf_receive_hello(struct ospf_packet * rcv_priority = ps->priority; int pxlen = u32_masklen(ntohl(ps->netmask)); + if (pxlen < 0) + DROP("prefix garbled", ntohl(ps->netmask)); + if ((ifa->type != OSPF_IT_VLINK) && (ifa->type != OSPF_IT_PTP) && - (pxlen != ifa->addr->prefix.pxlen)) - ((uint) pxlen != ifa->addr->pxlen)) ++ ((uint) pxlen != ifa->addr->prefix.pxlen)) DROP("prefix length mismatch", pxlen); neighbors = ps->neighbors; diff --cc proto/ospf/iface.c index 6ef24ffe5,280fa4c1e..675cf76dc --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@@ -51,6 -52,18 +52,20 @@@ ifa_tx_length(struct ospf_iface *ifa return ifa->cf->tx_length ?: ifa->iface->mtu; } + static inline uint + ifa_tx_hdrlen(struct ospf_iface *ifa) + { - uint hlen = SIZE_OF_IP_HEADER; ++ struct ospf_proto *p = ifa->oa->po; ++ ++ uint hlen = ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH; + + /* Relevant just for OSPFv2 */ + if (ifa->autype == OSPF_AUTH_CRYPT) + hlen += max_mac_length(ifa->passwords); + + return hlen; + } + static inline uint ifa_bufsize(struct ospf_iface *ifa) { diff --cc proto/ospf/topology.c index 86e39d752,341eff87e..aaaf2e8e3 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@@ -513,8 -513,9 +513,9 @@@ ospf_update_lsadb(struct ospf_proto *p } } + -static inline u32 -ort_to_lsaid(struct ospf_proto *p UNUSED4 UNUSED6, ort *nf) +static u32 +ort_to_lsaid(struct ospf_proto *p, ort *nf) { /* * In OSPFv2, We have to map IP prefixes to u32 in such manner that resulting diff --cc proto/pipe/pipe.c index d40b3f91e,6ef803222..8924c2000 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@@ -191,9 -257,10 +191,9 @@@ pipe_reconfigure(struct proto *P, struc } static void --pipe_copy_config(struct proto_config *dest, struct proto_config *src) ++pipe_copy_config(struct proto_config *dest UNUSED, struct proto_config *src UNUSED) { /* Just a shallow copy, not many items here */ - proto_copy_rest(dest, src, sizeof(struct pipe_config)); } static void diff --cc proto/rip/packets.c index f89bb1783,468927e6e..9dc492b76 --- a/proto/rip/packets.c +++ b/proto/rip/packets.c @@@ -9,10 -9,8 +9,10 @@@ * Can be freely distributed and used under the terms of the GNU GPL. */ +#undef LOCAL_DEBUG + #include "rip.h" - #include "lib/md5.h" + #include "lib/mac.h" #define RIP_CMD_REQUEST 1 /* want info */ @@@ -132,7 -129,7 +130,7 @@@ rip_put_block(struct rip_proto *p, byt } static inline void - rip_put_next_hop(struct rip_proto *p, byte *pos, struct rip_block *rte) -rip_put_next_hop(struct rip_proto *p UNUSED, byte *pos, struct rip_block *rte UNUSED4) ++rip_put_next_hop(struct rip_proto *p UNUSED, byte *pos, struct rip_block *rte) { struct rip_block_ng *block = (void *) pos; block->prefix = ip6_hton(ipa_to_ip6(rte->next_hop)); diff --cc sysdep/bsd/krt-sock.c index 3440ed637,9c9df51de..d2372a3d4 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@@ -1120,9 -1074,9 +1120,9 @@@ kif_sys_shutdown(struct kif_proto *p struct ifa * - kif_get_primary_ip(struct iface *i) -kif_get_primary_ip(struct iface *i UNUSED6) ++kif_get_primary_ip(struct iface *i UNUSED) { -#ifndef IPV6 +#if 0 static int fd = -1; if (fd < 0) diff --cc sysdep/bsd/krt-sys.h index 870cdf2ce,353ffcec5..ed667e804 --- a/sysdep/bsd/krt-sys.h +++ b/sysdep/bsd/krt-sys.h @@@ -44,8 -44,8 +44,9 @@@ struct krt_state static inline void krt_sys_io_init(void) { } static inline void krt_sys_init(struct krt_proto *p UNUSED) { } +static inline void krt_sys_postconfig(struct krt_config *x UNUSED) { } -static inline int krt_sys_get_attr(eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { return 0; } +static inline int krt_sys_get_attr(eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { return GA_UNKNOWN; } + #endif