]>
git.ipfire.org Git - thirdparty/bird.git/blob - nest/rt-roa.c
2 * BIRD -- Route Origin Authorization
5 * Can be freely distributed and used under the terms of the GNU GPL.
10 #include "nest/bird.h"
11 #include "nest/route.h"
13 #include "lib/lists.h"
14 #include "lib/resource.h"
15 #include "lib/event.h"
16 #include "lib/string.h"
17 #include "conf/conf.h"
21 static slab
*roa_slab
; /* Slab of struct roa_item */
22 static list roa_table_list
; /* List of struct roa_table */
23 struct roa_table
*roa_table_default
; /* The first ROA table in the config */
26 src_match(struct roa_item
*it
, byte src
)
27 { return !src
|| it
->src
== src
; }
30 * roa_add_item - add a ROA entry
32 * @prefix: prefix of the ROA entry
33 * @pxlen: prefix length of the ROA entry
34 * @maxlen: max length field of the ROA entry
35 * @asn: AS number field of the ROA entry
36 * @src: source of the ROA entry (ROA_SRC_*)
38 * The function adds a new ROA entry to the ROA table. If the same ROA
39 * is already in the table, nothing is added. @src field is used to
40 * distinguish different sources of ROAs.
43 roa_add_item(struct roa_table
*t
, ip_addr prefix
, byte pxlen
, byte maxlen
, u32 asn
, byte src
)
45 struct roa_node
*n
= fib_get(&t
->fib
, &prefix
, pxlen
);
47 // if ((n->items == NULL) && (n->n.x0 != ROA_INVALID))
51 for (it
= n
->items
; it
; it
= it
->next
)
52 if ((it
->maxlen
== maxlen
) && (it
->asn
== asn
) && src_match(it
, src
))
55 it
= sl_alloc(roa_slab
);
64 * roa_delete_item - delete a ROA entry
66 * @prefix: prefix of the ROA entry
67 * @pxlen: prefix length of the ROA entry
68 * @maxlen: max length field of the ROA entry
69 * @asn: AS number field of the ROA entry
70 * @src: source of the ROA entry (ROA_SRC_*)
72 * The function removes a specified ROA entry from the ROA table and
73 * frees it. If @src field is not ROA_SRC_ANY, only entries from
74 * that source are considered.
77 roa_delete_item(struct roa_table
*t
, ip_addr prefix
, byte pxlen
, byte maxlen
, u32 asn
, byte src
)
79 struct roa_node
*n
= fib_find(&t
->fib
, &prefix
, pxlen
);
84 struct roa_item
*it
, **itp
;
85 for (itp
= &n
->items
; it
= *itp
; itp
= &it
->next
)
86 if ((it
->maxlen
== maxlen
) && (it
->asn
== asn
) && src_match(it
, src
))
93 sl_free(roa_slab
, it
);
95 // if ((n->items == NULL) && (n->n.x0 != ROA_INVALID))
101 * roa_flush - flush a ROA table
103 * @src: source of ROA entries (ROA_SRC_*)
105 * The function removes and frees ROA entries from the ROA table. If
106 * @src is ROA_SRC_ANY, all entries in the table are removed,
107 * otherwise only all entries from that source are removed.
110 roa_flush(struct roa_table
*t
, byte src
)
112 struct roa_item
*it
, **itp
;
115 FIB_WALK(&t
->fib
, fn
)
117 n
= (struct roa_node
*) fn
;
121 if (src_match(it
, src
))
124 sl_free(roa_slab
, it
);
131 // TODO add cleanup of roa_nodes
138 roa_check(struct roa_table *t, ip_addr prefix, byte pxlen, u32 asn)
140 struct roa_node *n = fib_find(&t->fib, &prefix, pxlen);
142 if (n && n->n.x0 == ROA_UNKNOWN)
145 if (n && n->n.x0 == ROA_VALID && asn == n->cached_asn)
148 byte rv = roa_match(t, n, prefix, pxlen, asn);
150 if (rv != ROA_INVALID)
154 if (t->cached_items >= t->cached_items_max)
155 n = fib_get(&t->fib, &prefix, pxlen);
168 * roa_check - check validity of route origination in a ROA table
170 * @prefix: network prefix to check
171 * @pxlen: length of network prefix
172 * @asn: AS number of network prefix
174 * Implements RFC 6483 route validation for the given network
175 * prefix. The procedure is to find all candidate ROAs - ROAs whose
176 * prefixes cover the give network prefix. If there is no candidate
177 * ROA, return ROA_UNKNOWN. If there is a candidate ROA with matching
178 * ASN and maxlen field greater than or equal to the given prefix
179 * length, return ROA_VALID. Otherwise return ROA_INVALID. If caller
180 * cannot determine origin AS, 0 could be used (in that case ROA_VALID
184 roa_check(struct roa_table
*t
, ip_addr prefix
, byte pxlen
, u32 asn
)
191 for (len
= pxlen
; len
>= 0; len
--)
193 px
= ipa_and(prefix
, ipa_mkmask(len
));
194 n
= fib_find(&t
->fib
, &px
, len
);
200 for (it
= n
->items
; it
; it
= it
->next
)
203 if ((it
->maxlen
>= pxlen
) && (it
->asn
== asn
) && asn
)
208 return anything
? ROA_INVALID
: ROA_UNKNOWN
;
212 roa_node_init(struct fib_node
*fn
)
214 struct roa_node
*n
= (struct roa_node
*) fn
;
219 roa_populate(struct roa_table
*t
)
221 struct roa_item_config
*ric
;
222 for (ric
= t
->cf
->roa_items
; ric
; ric
= ric
->next
)
223 roa_add_item(t
, ric
->prefix
, ric
->pxlen
, ric
->maxlen
, ric
->asn
, ROA_SRC_CONFIG
);
227 roa_new_table(struct roa_table_config
*cf
)
231 t
= mb_allocz(roa_pool
, sizeof(struct roa_table
));
232 fib_init(&t
->fib
, roa_pool
, sizeof(struct roa_node
), 0, roa_node_init
);
237 add_tail(&roa_table_list
, &t
->n
);
242 struct roa_table_config
*
243 roa_new_table_config(struct symbol
*s
)
245 struct roa_table_config
*rtc
= cfg_allocz(sizeof(struct roa_table_config
));
247 cf_define_symbol(s
, SYM_ROA
, rtc
);
249 add_tail(&new_config
->roa_tables
, &rtc
->n
);
254 * roa_add_item_config - add a static ROA entry to a ROA table configuration
256 * Arguments are self-explanatory. The first is the ROA table config, rest
257 * are specifying the ROA entry.
260 roa_add_item_config(struct roa_table_config
*rtc
, ip_addr prefix
, byte pxlen
, byte maxlen
, u32 asn
)
262 struct roa_item_config
*ric
= cfg_allocz(sizeof(struct roa_item_config
));
264 ric
->prefix
= prefix
;
266 ric
->maxlen
= maxlen
;
268 ric
->next
= rtc
->roa_items
;
269 rtc
->roa_items
= ric
;
273 * roa_init - initialize ROA tables
275 * This function is called during BIRD startup. It initializes
276 * the ROA table module.
281 roa_pool
= rp_new(&root_pool
, "ROA tables");
282 roa_slab
= sl_new(roa_pool
, sizeof(struct roa_item
));
283 init_list(&roa_table_list
);
287 roa_preconfig(struct config
*c
)
289 init_list(&c
->roa_tables
);
294 * roa_commit - commit new ROA table configuration
295 * @new: new configuration
296 * @old: original configuration or %NULL if it's boot time config
298 * Scan differences between @old and @new configuration and modify the
299 * ROA tables according to these changes. If @new defines a previously
300 * unknown table, create it, if it omits a table existing in @old,
301 * delete it (there are no references, only indirect through struct
302 * roa_table_config). If it exists in both configurations, update the
303 * configured ROA entries.
306 roa_commit(struct config
*new, struct config
*old
)
308 struct roa_table_config
*cf
;
312 WALK_LIST(t
, roa_table_list
)
314 struct symbol
*sym
= cf_find_symbol(new, t
->name
);
315 if (sym
&& sym
->class == SYM_ROA
)
317 /* Found old table in new config */
324 roa_flush(t
, ROA_SRC_CONFIG
);
332 roa_flush(t
, ROA_SRC_ANY
);
340 WALK_LIST(cf
, new->roa_tables
)
344 roa_table_default
= EMPTY_LIST(new->roa_tables
) ? NULL
:
345 ((struct roa_table_config
*) HEAD(new->roa_tables
))->table
;
351 roa_show_node(struct cli
*c
, struct roa_node
*rn
, int len
, u32 asn
)
355 for (ri
= rn
->items
; ri
; ri
= ri
->next
)
356 if ((ri
->maxlen
>= len
) && (!asn
|| (ri
->asn
== asn
)))
357 cli_printf(c
, -1019, "%I/%d max %d as %u", rn
->n
.prefix
, rn
->n
.pxlen
, ri
->maxlen
, ri
->asn
);
361 roa_show_cont(struct cli
*c
)
363 struct roa_show_data
*d
= c
->rover
;
364 struct fib
*fib
= &d
->table
->fib
;
365 struct fib_iterator
*it
= &d
->fit
;
369 FIB_ITERATE_START(fib
, it
, f
)
371 rn
= (struct roa_node
*) f
;
375 FIB_ITERATE_PUT(it
, f
);
379 if ((d
->mode
== ROA_SHOW_ALL
) ||
380 net_in_net(rn
->n
.prefix
, rn
->n
.pxlen
, d
->prefix
, d
->pxlen
))
381 roa_show_node(c
, rn
, 0, d
->asn
);
385 cli_printf(c
, 0, "");
386 c
->cont
= c
->cleanup
= NULL
;
390 roa_show_cleanup(struct cli
*c
)
392 struct roa_show_data
*d
= c
->rover
;
394 /* Unlink the iterator */
395 fit_get(&d
->table
->fib
, &d
->fit
);
399 roa_show(struct roa_show_data
*d
)
409 FIB_ITERATE_INIT(&d
->fit
, &d
->table
->fib
);
410 this_cli
->cont
= roa_show_cont
;
411 this_cli
->cleanup
= roa_show_cleanup
;
416 rn
= fib_find(&d
->table
->fib
, &d
->prefix
, d
->pxlen
);
419 roa_show_node(this_cli
, rn
, 0, d
->asn
);
423 cli_msg(-8001, "Network not in table");
427 for (len
= d
->pxlen
; len
>= 0; len
--)
429 px
= ipa_and(d
->prefix
, ipa_mkmask(len
));
430 rn
= fib_find(&d
->table
->fib
, &px
, len
);
435 roa_show_node(this_cli
, rn
, 0, d
->asn
);