On Thu, Sep 20, 2018 at 07:58:10PM +0200, Denis Fondras wrote:
> On Thu, Sep 20, 2018 at 01:56:04PM +0200, Claudio Jeker wrote:
> > This is the next step for ROA validation.
> >
> > Implement code to parse, print and reload roa-set tables.
> > This is sharing a lot of code with prefixset which makes all a bit easier.
> > A roa-set is defined like this:
> > roa-set "test2" {
> > 1.2.3.0/24 source-as 1,
> > 1.2.8.0/22 source-as 3
> > }
> >
>
> Shouldn't roa-set include maxlen ?
It does in the code, forgot to show it in this example. Sorry about that.
Wanted something short which was a bad idea.
> > This does not include any code to acutally use the data yet, I'm working
> > on that now and that will be then the next and hopefully last diff to
> > support ROA validations in bgpd.
> > --
> > :wq Claudio
> >
> >
> > Index: bgpd.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/bgpd/bgpd.c,v
> > retrieving revision 1.200
> > diff -u -p -r1.200 bgpd.c
> > --- bgpd.c 20 Sep 2018 11:45:59 -0000 1.200
> > +++ bgpd.c 20 Sep 2018 11:49:56 -0000
> > @@ -516,6 +516,34 @@ reconfigure(char *conffile, struct bgpd_
> > if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIXSETITEM, 0,
> > 0, -1, psi, sizeof(*psi)) == -1)
> > return (-1);
> > + set_free(psi->set);
> > + free(psi);
> > + }
> > + free(ps);
> > + }
> > +
> > + /* roasets for filters in the RDE */
> > + while ((ps = SIMPLEQ_FIRST(conf->roasets)) != NULL) {
> > + SIMPLEQ_REMOVE_HEAD(conf->roasets, entry);
> > + if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_SET, 0, 0, -1,
> > + ps->name, sizeof(ps->name)) == -1)
> > + return (-1);
> > + RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) {
> > + u_int32_t *as;
> > + size_t i, l, n;
> > + RB_REMOVE(prefixset_tree, &ps->psitems, psi);
> > + as = set_get(psi->set, &n);
> > + for (i = 0; i < n; i += l) {
> > + l = (n - i > 1024 ? 1024 : n - i);
> > + if (imsg_compose(ibuf_rde,
> > + IMSG_RECONF_ROA_AS_SET_ITEMS,
> > + 0, 0, -1, as + i, l) == -1)
> > + return -1;
> > + }
> > + if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIXSETITEM, 0,
> > + 0, -1, psi, sizeof(*psi)) == -1)
> > + return (-1);
> > + set_free(psi->set);
> > free(psi);
> > }
> > free(ps);
> > Index: bgpd.h
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
> > retrieving revision 1.343
> > diff -u -p -r1.343 bgpd.h
> > --- bgpd.h 20 Sep 2018 11:45:59 -0000 1.343
> > +++ bgpd.h 20 Sep 2018 11:49:56 -0000
> > @@ -229,7 +229,9 @@ struct bgpd_config {
> > struct listen_addrs *listen_addrs;
> > struct mrt_head *mrt;
> > struct prefixset_head *prefixsets;
> > + struct prefixset_head *roasets;
> > struct rde_prefixset_head *rde_prefixsets;
> > + struct rde_prefixset_head *rde_roasets;
> > struct as_set_head *as_sets;
> > char *csock;
> > char *rcsock;
> > @@ -431,6 +433,8 @@ enum imsg_type {
> > IMSG_RECONF_AS_SET,
> > IMSG_RECONF_AS_SET_ITEMS,
> > IMSG_RECONF_AS_SET_DONE,
> > + IMSG_RECONF_ROA_SET,
> > + IMSG_RECONF_ROA_AS_SET_ITEMS,
> > IMSG_RECONF_DONE,
> > IMSG_UPDATE,
> > IMSG_UPDATE_ERR,
> > @@ -961,6 +965,7 @@ struct roa_set {
> > struct prefixset_item {
> > struct filter_prefix p;
> > RB_ENTRY(prefixset_item) entry;
> > + struct set_table *set;
> > };
> > RB_HEAD(prefixset_tree, prefixset_item);
> >
> > Index: config.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/bgpd/config.c,v
> > retrieving revision 1.74
> > diff -u -p -r1.74 config.c
> > --- config.c 20 Sep 2018 07:46:39 -0000 1.74
> > +++ config.c 20 Sep 2018 11:49:56 -0000
> > @@ -67,6 +67,8 @@ new_config(void)
> > if ((conf->prefixsets = calloc(1, sizeof(struct prefixset_head)))
> > == NULL)
> > fatal(NULL);
> > + if ((conf->roasets = calloc(1, sizeof(struct prefixset_head))) == NULL)
> > + fatal(NULL);
> > if ((conf->as_sets = calloc(1, sizeof(struct as_set_head))) == NULL)
> > fatal(NULL);
> > if ((conf->filters = calloc(1, sizeof(struct filter_head))) == NULL)
> > @@ -81,6 +83,7 @@ new_config(void)
> > TAILQ_INIT(&conf->networks);
> > SIMPLEQ_INIT(&conf->rdomains);
> > SIMPLEQ_INIT(conf->prefixsets);
> > + SIMPLEQ_INIT(conf->roasets);
> > SIMPLEQ_INIT(conf->as_sets);
> >
> > TAILQ_INIT(conf->filters);
> > @@ -129,6 +132,7 @@ free_prefixsets(struct prefixset_head *p
> > ps = SIMPLEQ_FIRST(psh);
> > RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) {
> > RB_REMOVE(prefixset_tree, &ps->psitems, psi);
> > + set_free(psi->set);
> > free(psi);
> > }
> > SIMPLEQ_REMOVE_HEAD(psh, entry);
> > @@ -147,6 +151,7 @@ free_config(struct bgpd_config *conf)
> > free_networks(&conf->networks);
> > filterlist_free(conf->filters);
> > free_prefixsets(conf->prefixsets);
> > + free_prefixsets(conf->roasets);
> > as_sets_free(conf->as_sets);
> >
> > while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
> > @@ -224,6 +229,11 @@ merge_config(struct bgpd_config *xconf,
> > free_prefixsets(xconf->prefixsets);
> > xconf->prefixsets = conf->prefixsets;
> > conf->prefixsets = NULL;
> > +
> > + /* switch the roasets, first remove the old ones */
> > + free_prefixsets(xconf->roasets);
> > + xconf->roasets = conf->roasets;
> > + conf->roasets = NULL;
> >
> > /* switch the as_sets, first remove the old ones */
> > as_sets_free(xconf->as_sets);
> > Index: parse.y
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
> > retrieving revision 1.355
> > diff -u -p -r1.355 parse.y
> > --- parse.y 20 Sep 2018 11:45:59 -0000 1.355
> > +++ parse.y 20 Sep 2018 11:49:57 -0000
> > @@ -93,6 +93,7 @@ static struct peer *curpeer;
> > static struct peer *curgroup;
> > static struct rdomain *currdom;
> > static struct prefixset *curpset;
> > +static struct prefixset *curroaset;
> > static struct filter_head *filter_l;
> > static struct filter_head *peerfilter_l;
> > static struct filter_head *groupfilter_l;
> > @@ -162,7 +163,8 @@ int parseextcommunity(struct filter_ex
> > static int new_as_set(char *);
> > static void add_as_set(u_int32_t);
> > static void done_as_set(void);
> > -static int new_prefix_set(char *);
> > +static struct prefixset *new_prefix_set(char *, int);
> > +static void add_roa_set(struct prefixset_item *, u_int32_t,
> > u_int8_t);
> >
> > typedef struct {
> > union {
> > @@ -211,7 +213,7 @@ typedef struct {
> > %token FROM TO ANY
> > %token CONNECTED STATIC
> > %token COMMUNITY EXTCOMMUNITY LARGECOMMUNITY DELETE
> > -%token PREFIX PREFIXLEN PREFIXSET
> > +%token PREFIX PREFIXLEN PREFIXSET ROASET
> > %token ASSET SOURCEAS TRANSITAS PEERAS MAXASLEN MAXASSEQ
> > %token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF
> > %token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN PRIORITY
> > @@ -250,6 +252,7 @@ grammar : /* empty */
> > | grammar include '\n'
> > | grammar as_set '\n'
> > | grammar prefixset '\n'
> > + | grammar roa_set '\n'
> > | grammar conf_main '\n'
> > | grammar rdomain '\n'
> > | grammar neighbor '\n'
> > @@ -423,7 +426,7 @@ as_set_l : as4number_any {
> > add_as_set(
> > | as_set_l comma as4number_any { add_as_set($3); }
> >
> > prefixset : PREFIXSET STRING '{' optnl {
> > - if (new_prefix_set($2) != 0) {
> > + if ((curpset = new_prefix_set($2, 0)) == NULL) {
> > free($2);
> > YYERROR;
> > }
> > @@ -433,7 +436,7 @@ prefixset : PREFIXSET STRING '{' optnl
> > curpset = NULL;
> > }
> > | PREFIXSET STRING '{' optnl '}' {
> > - if (new_prefix_set($2) != 0) {
> > + if ((curpset = new_prefix_set($2, 0)) == NULL) {
> > free($2);
> > YYERROR;
> > }
> > @@ -487,6 +490,47 @@ prefixset_item : prefix prefixlenop
> > {
> > }
> > ;
> >
> > +roa_set : ROASET STRING '{' optnl {
> > + if ((curroaset = new_prefix_set($2, 1)) == NULL) {
> > + free($2);
> > + YYERROR;
> > + }
> > + free($2);
> > + } roa_set_l optnl '}' {
> > + SIMPLEQ_INSERT_TAIL(conf->roasets, curroaset, entry);
> > + curroaset = NULL;
> > + }
> > + | ROASET STRING '{' optnl '}' {
> > + if ((curroaset = new_prefix_set($2, 1)) == NULL) {
> > + free($2);
> > + YYERROR;
> > + }
> > + free($2);
> > + SIMPLEQ_INSERT_TAIL(conf->roasets, curroaset, entry);
> > + curroaset = NULL;
> > + }
> > + ;
> > +
> > +roa_set_l : prefixset_item SOURCEAS as4number_any {
> > + if ($1->p.len_min != $1->p.len) {
> > + yyerror("unsupported prefixlen operation in "
> > + "roa-set");
> > + free($1);
> > + YYERROR;
> > + }
> > + add_roa_set($1, $3, $1->p.len_max);
> > + }
> > + | roa_set_l comma prefixset_item SOURCEAS as4number_any {
> > + if ($3->p.len_min != $3->p.len) {
> > + yyerror("unsupported prefixlen operation in "
> > + "roa-set");
> > + free($3);
> > + YYERROR;
> > + }
> > + add_roa_set($3, $5, $3->p.len_max);
> > + }
> > + ;
> > +
> > conf_main : AS as4number {
> > conf->as = $2;
> > if ($2 > USHRT_MAX)
> > @@ -2768,6 +2812,7 @@ lookup(char *s)
> > { "restart", RESTART},
> > { "restricted", RESTRICTED},
> > { "rib", RIB},
> > + { "roa-set", ROASET },
> > { "route-collector", ROUTECOLL},
> > { "route-reflector", REFLECTOR},
> > { "router-id", ROUTERID},
> > @@ -4230,21 +4275,52 @@ done_as_set(void)
> > curset = NULL;
> > }
> >
> > -static int
> > -new_prefix_set(char *name)
> > +static struct prefixset *
> > +new_prefix_set(char *name, int is_roa)
> > {
> > - if (find_prefixset(name, conf->prefixsets) != NULL) {
> > - yyerror("prefix-set \"%s\" already exists", name);
> > - return -1;
> > + const char *type = "prefix-set";
> > + struct prefixset_head *sets = conf->prefixsets;
> > + struct prefixset *pset;
> > +
> > + if (is_roa) {
> > + type = "roa-set";
> > + sets = conf->roasets;
> > }
> > - if ((curpset = calloc(1, sizeof(*curpset))) == NULL)
> > +
> > + if (find_prefixset(name, sets) != NULL) {
> > + yyerror("%s \"%s\" already exists", type, name);
> > + return NULL;
> > + }
> > + if ((pset = calloc(1, sizeof(*pset))) == NULL)
> > fatal("prefixset");
> > - if (strlcpy(curpset->name, name, sizeof(curpset->name)) >=
> > - sizeof(curpset->name)) {
> > + if (strlcpy(pset->name, name, sizeof(pset->name)) >=
> > + sizeof(pset->name)) {
> > yyerror("prefix-set \"%s\" too long: max %zu",
> > - name, sizeof(curpset->name) - 1);
> > - return -1;
> > + name, sizeof(pset->name) - 1);
> > + free(pset);
> > + return NULL;
> > }
> > - RB_INIT(&curpset->psitems);
> > - return 0;
> > + RB_INIT(&pset->psitems);
> > + return pset;
> > +}
> > +
> > +static void
> > +add_roa_set(struct prefixset_item *npsi, u_int32_t as, u_int8_t max)
> > +{
> > + struct prefixset_item *psi;
> > + struct roa_set rs;
> > +
> > + /* no prefixlen option on this tree */
> > + npsi->p.len_max = npsi->p.len_min = npsi->p.len;
> > + psi = RB_INSERT(prefixset_tree, &curroaset->psitems, npsi);
> > + if (psi == NULL)
> > + psi = npsi;
> > +
> > + if (psi->set == NULL)
> > + if ((psi->set = set_new(1, sizeof(rs))) == NULL)
> > + fatal("set_new");
> > + rs.as = as;
> > + rs.maxlen = max;
> > + if (set_add(psi->set, &rs, 1) != 0)
> > + fatal("as_set_new");
> > }
> > Index: printconf.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
> > retrieving revision 1.121
> > diff -u -p -r1.121 printconf.c
> > --- printconf.c 20 Sep 2018 11:45:59 -0000 1.121
> > +++ printconf.c 20 Sep 2018 11:49:57 -0000
> > @@ -42,6 +42,7 @@ const char *print_af(u_int8_t);
> > void print_network(struct network_config *, const char *);
> > void print_as_sets(struct as_set_head *);
> > void print_prefixsets(struct prefixset_head *);
> > +void print_roasets(struct prefixset_head *);
> > void print_peer(struct peer_config *, struct bgpd_config *,
> > const char *);
> > const char *print_auth_alg(u_int8_t);
> > @@ -486,6 +487,35 @@ print_prefixsets(struct prefixset_head *
> > }
> >
> > void
> > +print_roasets(struct prefixset_head *psh)
> > +{
> > + struct prefixset *ps;
> > + struct prefixset_item *psi;
> > + struct roa_set *rs;
> > + size_t i, n;
> > +
> > + SIMPLEQ_FOREACH(ps, psh, entry) {
> > + int count = 0;
> > + printf("roa-set \"%s\" {", ps->name);
> > + RB_FOREACH(psi, prefixset_tree, &ps->psitems) {
> > + rs = set_get(psi->set, &n);
> > + for (i = 0; i < n; i++) {
> > + if (count++ % 2 == 0)
> > + printf("\n\t");
> > + else
> > + printf(", ");
> > +
> > + print_prefix(&psi->p);
> > + if (psi->p.len != rs[i].maxlen)
> > + printf(" maxlen %u", rs[i].maxlen);
> > + printf(" source-as %u", rs[i].as);
> > + }
> > + }
> > + printf("\n}\n\n");
> > + }
> > +}
> > +
> > +void
> > print_peer(struct peer_config *p, struct bgpd_config *conf, const char *c)
> > {
> > char *method;
> > @@ -891,6 +921,7 @@ print_config(struct bgpd_config *conf, s
> > print_mainconf(conf);
> > print_prefixsets(conf->prefixsets);
> > print_as_sets(conf->as_sets);
> > + print_roasets(conf->roasets);
> > TAILQ_FOREACH(n, net_l, entry)
> > print_network(&n->net, "");
> > if (!SIMPLEQ_EMPTY(rdom_l))
> > Index: rde.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
> > retrieving revision 1.425
> > diff -u -p -r1.425 rde.c
> > --- rde.c 20 Sep 2018 11:45:59 -0000 1.425
> > +++ rde.c 20 Sep 2018 11:49:57 -0000
> > @@ -131,6 +131,7 @@ time_t reloadtime;
> > struct rde_peer_head peerlist;
> > struct rde_peer *peerself;
> > struct rde_prefixset_head *prefixsets_tmp, *prefixsets_old;
> > +struct rde_prefixset_head *roasets_tmp, *roasets_old;
> > struct as_set_head *as_sets_tmp, *as_sets_old;
> > struct filter_head *out_rules, *out_rules_tmp;
> > struct rdomain_head *rdomains_l, *newdomains;
> > @@ -689,6 +690,7 @@ rde_dispatch_imsg_parent(struct imsgbuf
> > {
> > static struct rde_prefixset *last_prefixset;
> > static struct as_set *last_as_set;
> > + static struct set_table *last_set;
> > static struct rdomain *rd;
> > struct imsg imsg;
> > struct mrt xmrt;
> > @@ -702,7 +704,7 @@ rde_dispatch_imsg_parent(struct imsgbuf
> > struct prefixset_item psi;
> > char *name;
> > size_t nmemb;
> > - int n, fd;
> > + int n, fd, rv;
> > u_int16_t rid;
> >
> > while (ibuf) {
> > @@ -774,6 +776,11 @@ rde_dispatch_imsg_parent(struct imsgbuf
> > if (prefixsets_tmp == NULL)
> > fatal(NULL);
> > SIMPLEQ_INIT(prefixsets_tmp);
> > + roasets_tmp = calloc(1,
> > + sizeof(struct rde_prefixset_head));
> > + if (roasets_tmp == NULL)
> > + fatal(NULL);
> > + SIMPLEQ_INIT(roasets_tmp);
> > as_sets_tmp = calloc(1,
> > sizeof(struct as_set_head));
> > if (as_sets_tmp == NULL)
> > @@ -877,6 +884,7 @@ rde_dispatch_imsg_parent(struct imsgbuf
> > TAILQ_INSERT_TAIL(out_rules_tmp, r, entry);
> > break;
> > case IMSG_RECONF_PREFIXSET:
> > + case IMSG_RECONF_ROA_SET:
> > if (imsg.hdr.len - IMSG_HEADER_SIZE !=
> > sizeof(ps->name))
> > fatalx("IMSG_RECONF_PREFIXSET bad len");
> > @@ -884,9 +892,22 @@ rde_dispatch_imsg_parent(struct imsgbuf
> > if (ps == NULL)
> > fatal(NULL);
> > memcpy(ps->name, imsg.data, sizeof(ps->name));
> > - SIMPLEQ_INSERT_TAIL(prefixsets_tmp, ps, entry);
> > + if (imsg.hdr.type == IMSG_RECONF_ROA_SET) {
> > + SIMPLEQ_INSERT_TAIL(roasets_tmp, ps, entry);
> > + ps->roa = 1;
> > + last_set = set_new(1, sizeof(struct roa_set));
> > + if (last_set == NULL)
> > + fatal(NULL);
> > + } else
> > + SIMPLEQ_INSERT_TAIL(prefixsets_tmp, ps, entry);
> > last_prefixset = ps;
> > break;
> > + case IMSG_RECONF_ROA_AS_SET_ITEMS:
> > + nmemb = imsg.hdr.len - IMSG_HEADER_SIZE;
> > + nmemb /= sizeof(struct roa_set);
> > + if (set_add(last_set, imsg.data, nmemb) != 0)
> > + fatal(NULL);
> > + break;
> > case IMSG_RECONF_PREFIXSETITEM:
> > if (imsg.hdr.len - IMSG_HEADER_SIZE !=
> > sizeof(psi))
> > @@ -894,11 +915,19 @@ rde_dispatch_imsg_parent(struct imsgbuf
> > memcpy(&psi, imsg.data, sizeof(psi));
> > if (last_prefixset == NULL)
> > fatalx("King Bula has no prefixset");
> > - if (trie_add(&last_prefixset->th, &psi.p.addr,
> > - psi.p.len, psi.p.len_min, psi.p.len_max) == -1)
> > - log_warnx("trie_add(%s) %s/%u, %u-%u) failed",
> > + if (last_prefixset->roa) {
> > + set_prep(last_set);
> > + rv = trie_roa_add(&last_prefixset->th,
> > + &psi.p.addr, psi.p.len, last_set);
> > + } else {
> > + rv = trie_add(&last_prefixset->th,
> > + &psi.p.addr, psi.p.len,
> > + psi.p.len_min, psi.p.len_max);
> > + }
> > + if (rv == -1)
> > + log_warnx("trie_add(%s) %s/%u) failed",
> > last_prefixset->name, log_addr(&psi.p.addr),
> > - psi.p.len, psi.p.len_min, psi.p.len_max);
> > + psi.p.len);
> > break;
> > case IMSG_RECONF_AS_SET:
> > if (imsg.hdr.len - IMSG_HEADER_SIZE !=
> > @@ -2795,6 +2824,7 @@ rde_reload_done(void)
> > }
> >
> > prefixsets_old = conf->rde_prefixsets;
> > + roasets_old = conf->rde_roasets;
> > as_sets_old = conf->as_sets;
> >
> > memcpy(conf, nconf, sizeof(struct bgpd_config));
> > @@ -2802,6 +2832,7 @@ rde_reload_done(void)
> > conf->csock = NULL;
> > conf->rcsock = NULL;
> > conf->prefixsets = NULL;
> > + conf->roasets = NULL;
> > free(nconf);
> > nconf = NULL;
> >
> > @@ -2826,11 +2857,15 @@ rde_reload_done(void)
> > /* XXX WHERE IS THE SYNC ??? */
> >
> > rde_mark_prefixsets_dirty(prefixsets_old, prefixsets_tmp);
> > + rde_mark_prefixsets_dirty(roasets_old, roasets_tmp);
> > as_sets_mark_dirty(as_sets_old, as_sets_tmp);
> >
> > /* swap the prefixsets */
> > conf->rde_prefixsets = prefixsets_tmp;
> > prefixsets_tmp = NULL;
> > + /* the roa-sets */
> > + conf->rde_roasets = roasets_tmp;
> > + roasets_tmp = NULL;
> > /* and the as_sets */
> > conf->as_sets = as_sets_tmp;
> > as_sets_tmp = NULL;
> > @@ -3022,6 +3057,8 @@ rde_softreconfig_done(void)
> >
> > rde_free_prefixsets(prefixsets_old);
> > prefixsets_old = NULL;
> > + rde_free_prefixsets(roasets_old);
> > + roasets_old = NULL;
> > as_sets_free(as_sets_old);
> > as_sets_old = NULL;
> >
> >
>
--
:wq Claudio