#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)
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) */
}
;
-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");
}
;
-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.sgml >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))
%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 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 <i> type break_command ec_kind
+ %type <i32> cnum
+ %type <e> pair_item ec_item lc_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 <v> set_atom switch_atom fipa
+%type <px> fprefix
%type <s> decls declsn one_decl function_params
%type <h> bgp_path bgp_path_tail1 bgp_path_tail2
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
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:
/* 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 {
union {
uint i;
u64 ec;
- /* ip_addr ip; Folded into prefix */
- struct f_prefix px;
+ lcomm lc;
+ ip_addr ip;
+ const net_addr *net;
char *s;
struct f_tree *t;
struct f_trie *ti;
struct f_trie_node
{
ip_addr addr, mask, accept;
-- int plen;
++ uint plen;
struct f_trie_node *c[2];
};
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);
return 0;
}
- int add = 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)
+{
++ 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)
{
--- /dev/null
- 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)
#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;
#define HASH_WALK_FILTER_END } while (0)
- mem_hash_mix(u64 *h, void *p, int s)
++
+static inline void
+mem_hash_init(u64 *h)
+{
+ *h = 0x001047d54778bcafULL;
+}
+
+static inline void
-
++mem_hash_mix(u64 *h, void *p, uint s)
+{
+ const u64 multiplier = 0xb38bc09a61202731ULL;
+ const char *pp = p;
+ uint i;
++
+ for (i=0; i<s/4; i++)
+ *h = *h * multiplier + ((const u32 *)pp)[i];
- mem_hash(void *p, int s)
++
+ for (i=s & ~0x3; i<s; i++)
+ *h = *h * multiplier + pp[i];
+}
+
+static inline uint
+mem_hash_value(u64 *h)
+{
+ return ((*h >> 32) ^ (*h & 0xffffffff));
+}
+
+static inline uint
++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
--- /dev/null
- found:
+/*
+ * BIRD Library -- ID Map
+ *
+ * (c) 2013--2015 Ondrej Zajicek <santiago@crfreenet.org>
+ * (c) 2013--2015 CZ.NIC z.s.p.o.
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdlib.h>
+
+#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:
+ 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--;
+}
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)
%type <r> rtable
%type <s> optsym
%type <ra> r_args
-%type <ro> roa_args
-%type <rot> roa_table_arg
%type <sd> sym_args
- %type <i> 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 <i> 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 <i> 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 <ps> proto_patt proto_patt2
-%type <g> limit_spec
+%type <cc> channel_start proto_channel
+%type <cl> limit_spec
CF_GRAMMAR
#ifndef PASSWORD_H
#define PASSWORD_H
-#include "lib/timer.h"
+
+#include "sysdep/unix/timer.h"
struct password_item {
node n;
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 *);
{
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 */
}
/**
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;
}
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 *));
}
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;
return ifa->cf->tx_length ?: ifa->iface->mtu;
}
- uint hlen = SIZE_OF_IP_HEADER;
+ static inline uint
+ ifa_tx_hdrlen(struct ospf_iface *ifa)
+ {
++ 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)
{
}
}
-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
}
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
* 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 */
}
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));
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)
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