Annotation of embedaddon/bird/nest/rt-roa.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  *     BIRD -- Route Origin Authorization
                      3:  *
                      4:  *
                      5:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      6:  */
                      7: 
                      8: #undef LOCAL_DEBUG
                      9: 
                     10: #include "nest/bird.h"
                     11: #include "nest/route.h"
                     12: #include "nest/cli.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"
                     18: 
                     19: 
                     20: pool *roa_pool;
                     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 */
                     24: 
                     25: static inline int
                     26: src_match(struct roa_item *it, byte src)
                     27: { return !src || it->src == src; }
                     28: 
                     29: /**
                     30:  * roa_add_item - add a ROA entry
                     31:  * @t: ROA table
                     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_*)
                     37:  *
                     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.
                     41:  */
                     42: void
                     43: roa_add_item(struct roa_table *t, ip_addr prefix, byte pxlen, byte maxlen, u32 asn, byte src)
                     44: {
                     45:   struct roa_node *n = fib_get(&t->fib, &prefix, pxlen);
                     46: 
                     47:   // if ((n->items == NULL) && (n->n.x0 != ROA_INVALID))
                     48:   // t->cached_items--;
                     49: 
                     50:   struct roa_item *it;
                     51:   for (it = n->items; it; it = it->next)
                     52:     if ((it->maxlen == maxlen) && (it->asn == asn) && src_match(it, src))
                     53:       return;
                     54: 
                     55:   it = sl_alloc(roa_slab);
                     56:   it->asn = asn;
                     57:   it->maxlen = maxlen;
                     58:   it->src = src;
                     59:   it->next = n->items;
                     60:   n->items = it;
                     61: }
                     62: 
                     63: /**
                     64:  * roa_delete_item - delete a ROA entry
                     65:  * @t: ROA table
                     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_*)
                     71:  *
                     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.
                     75:  */
                     76: void
                     77: roa_delete_item(struct roa_table *t, ip_addr prefix, byte pxlen, byte maxlen, u32 asn, byte src)
                     78: {
                     79:   struct roa_node *n = fib_find(&t->fib, &prefix, pxlen);
                     80: 
                     81:   if (!n)
                     82:     return;
                     83: 
                     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))
                     87:       break;
                     88: 
                     89:   if (!it)
                     90:     return;
                     91: 
                     92:   *itp = it->next;
                     93:   sl_free(roa_slab, it);
                     94: 
                     95:   // if ((n->items == NULL) && (n->n.x0 != ROA_INVALID))
                     96:   // t->cached_items++;
                     97: }
                     98: 
                     99: 
                    100: /**
                    101:  * roa_flush - flush a ROA table
                    102:  * @t: ROA table
                    103:  * @src: source of ROA entries (ROA_SRC_*)
                    104:  *
                    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.
                    108:  */
                    109: void
                    110: roa_flush(struct roa_table *t, byte src)
                    111: {
                    112:   struct roa_item *it, **itp;
                    113:   struct roa_node *n;
                    114: 
                    115:   FIB_WALK(&t->fib, fn)
                    116:     {
                    117:       n = (struct roa_node *) fn;
                    118: 
                    119:       itp = &n->items;
                    120:       while (it = *itp)
                    121:        if (src_match(it, src))
                    122:          {
                    123:            *itp = it->next;
                    124:            sl_free(roa_slab, it);
                    125:          }
                    126:        else
                    127:          itp = &it->next;
                    128:     }
                    129:   FIB_WALK_END;
                    130: 
                    131:   // TODO add cleanup of roa_nodes
                    132: }
                    133: 
                    134: 
                    135: 
                    136: /*
                    137: byte
                    138: roa_check(struct roa_table *t, ip_addr prefix, byte pxlen, u32 asn)
                    139: {
                    140:   struct roa_node *n = fib_find(&t->fib, &prefix, pxlen);
                    141: 
                    142:   if (n && n->n.x0 == ROA_UNKNOWN)
                    143:     return ROA_UNKNOWN;
                    144: 
                    145:   if (n && n->n.x0 == ROA_VALID && asn == n->cached_asn)
                    146:     return ROA_VALID;
                    147: 
                    148:   byte rv = roa_match(t, n, prefix, pxlen, asn);
                    149: 
                    150:   if (rv != ROA_INVALID)
                    151:     {
                    152:       if (!n)
                    153:        {
                    154:          if (t->cached_items >= t->cached_items_max)
                    155:          n = fib_get(&t->fib, &prefix, pxlen);
                    156:          t->cached_items++;
                    157:        }
                    158: 
                    159:       n->cached_asn = asn;
                    160:       n->n.x0 = rv;
                    161:     }
                    162: 
                    163:   return rv;
                    164: }
                    165: */
                    166: 
                    167: /**
                    168:  * roa_check - check validity of route origination in a ROA table 
                    169:  * @t: ROA table
                    170:  * @prefix: network prefix to check
                    171:  * @pxlen: length of network prefix
                    172:  * @asn: AS number of network prefix
                    173:  *
                    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
                    181:  * cannot happen).
                    182:  */
                    183: byte
                    184: roa_check(struct roa_table *t, ip_addr prefix, byte pxlen, u32 asn)
                    185: {
                    186:   struct roa_node *n;
                    187:   ip_addr px;
                    188:   byte anything = 0;
                    189: 
                    190:   int len;
                    191:   for (len = pxlen; len >= 0; len--)
                    192:     {
                    193:       px = ipa_and(prefix, ipa_mkmask(len));
                    194:       n = fib_find(&t->fib, &px, len);
                    195: 
                    196:       if (!n)
                    197:        continue;
                    198: 
                    199:       struct roa_item *it;
                    200:       for (it = n->items; it; it = it->next)
                    201:        {
                    202:          anything = 1;
                    203:          if ((it->maxlen >= pxlen) && (it->asn == asn) && asn)
                    204:            return ROA_VALID;
                    205:        }
                    206:     }
                    207: 
                    208:   return anything ? ROA_INVALID : ROA_UNKNOWN;
                    209: }
                    210: 
                    211: static void
                    212: roa_node_init(struct fib_node *fn)
                    213: {
                    214:   struct roa_node *n = (struct roa_node *) fn;
                    215:   n->items = NULL;
                    216: }
                    217: 
                    218: static inline void
                    219: roa_populate(struct roa_table *t)
                    220: {
                    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);
                    224: }
                    225: 
                    226: static void
                    227: roa_new_table(struct roa_table_config *cf)
                    228: {
                    229:   struct roa_table *t;
                    230: 
                    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);
                    233:   t->name = cf->name;
                    234:   t->cf = cf;
                    235: 
                    236:   cf->table = t;
                    237:   add_tail(&roa_table_list, &t->n);
                    238: 
                    239:   roa_populate(t);
                    240: }
                    241: 
                    242: struct roa_table_config *
                    243: roa_new_table_config(struct symbol *s)
                    244: {
                    245:   struct roa_table_config *rtc = cfg_allocz(sizeof(struct roa_table_config));
                    246: 
                    247:   cf_define_symbol(s, SYM_ROA, rtc);
                    248:   rtc->name = s->name;
                    249:   add_tail(&new_config->roa_tables, &rtc->n);
                    250:   return rtc;
                    251: }
                    252: 
                    253: /**
                    254:  * roa_add_item_config - add a static ROA entry to a ROA table configuration
                    255:  *
                    256:  * Arguments are self-explanatory. The first is the ROA table config, rest
                    257:  * are specifying the ROA entry.
                    258:  */
                    259: void
                    260: roa_add_item_config(struct roa_table_config *rtc, ip_addr prefix, byte pxlen, byte maxlen, u32 asn)
                    261: {
                    262:   struct roa_item_config *ric = cfg_allocz(sizeof(struct roa_item_config));
                    263: 
                    264:   ric->prefix = prefix;
                    265:   ric->pxlen = pxlen;
                    266:   ric->maxlen = maxlen;
                    267:   ric->asn = asn;
                    268:   ric->next = rtc->roa_items;
                    269:   rtc->roa_items = ric;
                    270: }
                    271: 
                    272: /**
                    273:  * roa_init - initialize ROA tables
                    274:  *
                    275:  * This function is called during BIRD startup. It initializes
                    276:  * the ROA table module.
                    277:  */
                    278: void
                    279: roa_init(void)
                    280: {
                    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);
                    284: }
                    285: 
                    286: void
                    287: roa_preconfig(struct config *c)
                    288: {
                    289:   init_list(&c->roa_tables);
                    290: }
                    291: 
                    292: 
                    293: /**
                    294:  * roa_commit - commit new ROA table configuration
                    295:  * @new: new configuration
                    296:  * @old: original configuration or %NULL if it's boot time config
                    297:  *
                    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.
                    304:  */
                    305: void
                    306: roa_commit(struct config *new, struct config *old)
                    307: {
                    308:   struct roa_table_config *cf;
1.1.1.2 ! misho     309:   struct roa_table *t, *tx;
1.1       misho     310: 
                    311:   if (old)
1.1.1.2 ! misho     312:     WALK_LIST_DELSAFE(t, tx, roa_table_list)
1.1       misho     313:       {
                    314:        struct symbol *sym = cf_find_symbol(new, t->name);
                    315:        if (sym && sym->class == SYM_ROA)
                    316:          {
                    317:            /* Found old table in new config */
                    318:            cf = sym->def;
                    319:            cf->table = t;
                    320:            t->name = cf->name;
                    321:            t->cf = cf;
                    322: 
                    323:            /* Reconfigure it */
                    324:            roa_flush(t, ROA_SRC_CONFIG);
                    325:            roa_populate(t);
                    326:          }
                    327:        else
                    328:          {
                    329:            t->cf->table = NULL;
                    330: 
                    331:            /* Free it now */
                    332:            roa_flush(t, ROA_SRC_ANY);
                    333:            rem_node(&t->n);
                    334:            fib_free(&t->fib);
                    335:            mb_free(t);
                    336:          }
                    337:       }
                    338: 
                    339:   /* Add new tables */
                    340:   WALK_LIST(cf, new->roa_tables)
                    341:     if (! cf->table)
                    342:       roa_new_table(cf);
                    343: 
                    344:   roa_table_default = EMPTY_LIST(new->roa_tables) ? NULL :
                    345:     ((struct roa_table_config *) HEAD(new->roa_tables))->table;
                    346: }
                    347: 
                    348: 
                    349: 
                    350: static void
                    351: roa_show_node(struct cli *c, struct roa_node *rn, int len, u32 asn)
                    352: {
                    353:   struct roa_item *ri;
                    354: 
                    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);
                    358: }
                    359: 
                    360: static void
                    361: roa_show_cont(struct cli *c)
                    362: {
                    363:   struct roa_show_data *d = c->rover;
                    364:   struct fib *fib = &d->table->fib;
                    365:   struct fib_iterator *it = &d->fit;
                    366:   struct roa_node *rn;
                    367:   unsigned max = 32;
                    368: 
                    369:   FIB_ITERATE_START(fib, it, f)
                    370:     {
                    371:       rn = (struct roa_node *) f;
                    372: 
                    373:       if (!max--)
                    374:        {
                    375:          FIB_ITERATE_PUT(it, f);
                    376:          return;
                    377:        }
                    378: 
                    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);
                    382:     }
                    383:   FIB_ITERATE_END(f);
                    384: 
                    385:   cli_printf(c, 0, "");
                    386:   c->cont = c->cleanup = NULL;
                    387: }
                    388: 
                    389: static void
                    390: roa_show_cleanup(struct cli *c)
                    391: {
                    392:   struct roa_show_data *d = c->rover;
                    393: 
                    394:   /* Unlink the iterator */
                    395:   fit_get(&d->table->fib, &d->fit);
                    396: }
                    397: 
                    398: void
                    399: roa_show(struct roa_show_data *d)
                    400: {
                    401:   struct roa_node *rn;
                    402:   ip_addr px;
                    403:   int len;
                    404: 
                    405:   switch (d->mode)
                    406:     {
                    407:     case ROA_SHOW_ALL:
                    408:     case ROA_SHOW_IN:
                    409:       FIB_ITERATE_INIT(&d->fit, &d->table->fib);
                    410:       this_cli->cont = roa_show_cont;
                    411:       this_cli->cleanup = roa_show_cleanup;
                    412:       this_cli->rover = d;
                    413:       break;
                    414: 
                    415:     case ROA_SHOW_PX:
                    416:       rn = fib_find(&d->table->fib, &d->prefix, d->pxlen);
                    417:       if (rn)
                    418:        {
                    419:          roa_show_node(this_cli, rn, 0, d->asn);
                    420:          cli_msg(0, "");
                    421:        }
                    422:       else
                    423:        cli_msg(-8001, "Network not in table");
                    424:       break;
                    425: 
                    426:     case ROA_SHOW_FOR:
                    427:       for (len = d->pxlen; len >= 0; len--)
                    428:        {
                    429:          px = ipa_and(d->prefix, ipa_mkmask(len));
                    430:          rn = fib_find(&d->table->fib, &px, len);
                    431: 
                    432:          if (!rn)
                    433:            continue;
                    434: 
                    435:          roa_show_node(this_cli, rn, 0, d->asn);
                    436:        }
                    437:       cli_msg(0, "");
                    438:       break;
                    439:     }
                    440: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>