Rework the way we do extended communities (mainly in the parser) and update
authorclaudio <claudio@openbsd.org>
Wed, 31 May 2017 10:44:00 +0000 (10:44 +0000)
committerclaudio <claudio@openbsd.org>
Wed, 31 May 2017 10:44:00 +0000 (10:44 +0000)
the IANA table to a somewhat more complete list. This includes BGP Prefix
Origin Validation State support via the ext-community ovs keyword.
OK henning@ benno@ based on a diff by Job Snijders

usr.sbin/bgpd/bgpd.h
usr.sbin/bgpd/kroute.c
usr.sbin/bgpd/parse.y
usr.sbin/bgpd/printconf.c
usr.sbin/bgpd/rde_attr.c
usr.sbin/bgpd/util.c

index 69046a1..db52f85 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bgpd.h,v 1.307 2017/05/28 20:14:15 claudio Exp $ */
+/*     $OpenBSD: bgpd.h,v 1.308 2017/05/31 10:44:00 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -760,18 +760,23 @@ struct filter_peers {
 #define EXT_COMMUNITY_IANA             0x80
 #define EXT_COMMUNITY_TRANSITIVE       0x40
 #define EXT_COMMUNITY_VALUE            0x3f
-/* extended types */
-#define EXT_COMMUNITY_TWO_AS           0       /* 2 octet AS specific */
-#define EXT_COMMUNITY_IPV4             1       /* IPv4 specific */
-#define EXT_COMMUNITY_FOUR_AS          2       /* 4 octet AS specific */
-#define EXT_COMMUNITY_OPAQUE           3       /* opaque ext community */
-/* sub types */
-#define EXT_COMMUNITY_ROUTE_TGT                2       /* RFC 4360 & RFC4364 */
-#define EXT_COMMUNITY_ROUTE_ORIG       3       /* RFC 4360 & RFC4364 */
-#define EXT_COMMUNITY_OSPF_DOM_ID      5       /* RFC 4577 */
-#define EXT_COMMUNITY_OSPF_RTR_TYPE    6       /* RFC 4577 */
-#define EXT_COMMUNITY_OSPF_RTR_ID      7       /* RFC 4577 */
-#define EXT_COMMUNITY_BGP_COLLECT      8       /* RFC 4384 */
+/* extended types transitive */
+#define EXT_COMMUNITY_TRANS_TWO_AS     0x00    /* 2 octet AS specific */
+#define EXT_COMMUNITY_TRANS_IPV4       0x01    /* IPv4 specific */
+#define EXT_COMMUNITY_TRANS_FOUR_AS    0x02    /* 4 octet AS specific */
+#define EXT_COMMUNITY_TRANS_OPAQUE     0x03    /* opaque ext community */
+#define EXT_COMMUNITY_TRANS_EVPN       0x06    /* EVPN RFC7432 */
+/* extended types non-transitive */
+#define EXT_COMMUNITY_NON_TRANS_TWO_AS 0x40    /* 2 octet AS specific */
+#define EXT_COMMUNITY_NON_TRANS_IPV4   0x41    /* IPv4 specific */
+#define EXT_COMMUNITY_NON_TRANS_FOUR_AS        0x42    /* 4 octet AS specific */
+#define EXT_COMMUNITY_NON_TRANS_OPAQUE 0x43    /* opaque ext community */
+
+/* BGP Origin Validation State Extended Community RFC8097 */
+#define EXT_COMMUNITY_OVS_VALID                0
+#define EXT_COMMUNITY_OVS_NOTFOUND     1
+#define EXT_COMMUNITY_OVS_INVALID      2
+
 /* other handy defines */
 #define EXT_COMMUNITY_OPAQUE_MAX       0xffffffffffffULL
 #define EXT_COMMUNITY_FLAG_VALID       0x01
@@ -779,22 +784,41 @@ struct filter_peers {
 struct ext_comm_pairs {
        u_int8_t        type;
        u_int8_t        subtype;
-       u_int8_t        transitive;     /* transitive bit needs to be set */
-};
-
-#define IANA_EXT_COMMUNITIES   {                                       \
-       { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_ROUTE_TGT, 0 },           \
-       { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_ROUTE_ORIG, 0 },          \
-       { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_OSPF_DOM_ID, 0 },         \
-       { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_BGP_COLLECT, 0 },         \
-       { EXT_COMMUNITY_FOUR_AS, EXT_COMMUNITY_ROUTE_TGT, 0 },          \
-       { EXT_COMMUNITY_FOUR_AS, EXT_COMMUNITY_ROUTE_ORIG, 0 },         \
-       { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_ROUTE_TGT, 0 },             \
-       { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_ROUTE_ORIG, 0 },            \
-       { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_OSPF_RTR_ID, 0 },           \
-       { EXT_COMMUNITY_OPAQUE, EXT_COMMUNITY_OSPF_RTR_TYPE, 0 }        \
+       const char      *subname;
+};
+
+#define IANA_EXT_COMMUNITIES   {                               \
+       { EXT_COMMUNITY_TRANS_TWO_AS, 0x02, "rt" },             \
+       { EXT_COMMUNITY_TRANS_TWO_AS, 0x03, "soo" },            \
+       { EXT_COMMUNITY_TRANS_TWO_AS, 0x05, "odi" },            \
+       { EXT_COMMUNITY_TRANS_TWO_AS, 0x08, "bdc" },            \
+       { EXT_COMMUNITY_TRANS_TWO_AS, 0x09, "srcas" },          \
+       { EXT_COMMUNITY_TRANS_TWO_AS, 0x0a, "l2vid" },          \
+                                                               \
+       { EXT_COMMUNITY_TRANS_FOUR_AS, 0x02, "rt" },            \
+       { EXT_COMMUNITY_TRANS_FOUR_AS, 0x03, "soo" },           \
+       { EXT_COMMUNITY_TRANS_FOUR_AS, 0x05, "odi" },           \
+       { EXT_COMMUNITY_TRANS_FOUR_AS, 0x08, "bdc" },           \
+       { EXT_COMMUNITY_TRANS_FOUR_AS, 0x09, "srcas" },         \
+                                                               \
+       { EXT_COMMUNITY_TRANS_IPV4, 0x02, "rt" },               \
+       { EXT_COMMUNITY_TRANS_IPV4, 0x03, "soo" },              \
+       { EXT_COMMUNITY_TRANS_IPV4, 0x05, "odi" },              \
+       { EXT_COMMUNITY_TRANS_IPV4, 0x07, "ori" },              \
+       { EXT_COMMUNITY_TRANS_IPV4, 0x0a, "l2vid" },            \
+       { EXT_COMMUNITY_TRANS_IPV4, 0x0b, "vrfri" },            \
+                                                               \
+       { EXT_COMMUNITY_TRANS_OPAQUE, 0x06, "ort" },            \
+       { EXT_COMMUNITY_TRANS_OPAQUE, 0x0d, "defgw" },          \
+                                                               \
+       { EXT_COMMUNITY_NON_TRANS_OPAQUE, 0x00, "ovs" },        \
+                                                               \
+       { EXT_COMMUNITY_TRANS_EVPN, 0x00, "mac-mob" },          \
+       { EXT_COMMUNITY_TRANS_EVPN, 0x01, "esi-lab" },          \
+       { EXT_COMMUNITY_TRANS_EVPN, 0x02, "esi-rt" },           \
 }
 
+extern const struct ext_comm_pairs iana_ext_comms[];
 
 struct filter_prefix {
        struct bgpd_addr        addr;
@@ -1079,7 +1103,7 @@ const char        *log_in6addr(const struct in6_addr *);
 const char     *log_sockaddr(struct sockaddr *);
 const char     *log_as(u_int32_t);
 const char     *log_rd(u_int64_t);
-const char     *log_ext_subtype(u_int8_t);
+const char     *log_ext_subtype(u_int8_t, u_int8_t);
 const char     *log_shutcomm(const char *);
 int             aspath_snprint(char *, size_t, void *, u_int16_t);
 int             aspath_asprint(char **, void *, u_int16_t);
index 138f768..8a8a0b0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kroute.c,v 1.213 2017/05/28 15:16:33 henning Exp $ */
+/*     $OpenBSD: kroute.c,v 1.214 2017/05/31 10:44:00 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -1281,6 +1281,10 @@ kr_redistribute(int type, struct ktable *kt, struct kroute *kr)
                kr->flags |= F_REDISTRIBUTED;
 
 sendit:
+       log_debug("kr_redistribute: %s (%s)", inet_ntoa(kr->prefix),
+           type == IMSG_NETWORK_ADD ? "IMSG_NETWORK_ADD" :
+           "IMSG_NETWORK_REMOVE");
+
        bzero(&net, sizeof(net));
        net.prefix.aid = AID_INET;
        net.prefix.v4.s_addr = kr->prefix.s_addr;
@@ -1350,6 +1354,11 @@ kr_redistribute6(int type, struct ktable *kt, struct kroute6 *kr6)
        } else
                kr6->flags |= F_REDISTRIBUTED;
 sendit:
+       log_debug("kr_redistribute6: %s/%u (%s)",
+           log_in6addr(&kr6->prefix), kr6->prefixlen,
+           type == IMSG_NETWORK_ADD ? "IMSG_NETWORK_ADD" :
+           "IMSG_NETWORK_REMOVE");
+
        bzero(&net, sizeof(net));
        net.prefix.aid = AID_INET6;
        memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
@@ -1389,9 +1398,13 @@ kr_reload(void)
                if (hasdyn) {
                        /* only evaluate the full tree if we need */
                        RB_FOREACH(kr, kroute_tree, &kt->krt)
-                               kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r);
+                               if(!(kr->r.flags & F_DOWN))
+                                       kr_redistribute(IMSG_NETWORK_ADD,
+                                           kt, &kr->r);
                        RB_FOREACH(kr6, kroute6_tree, &kt->krt6)
-                               kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr6->r);
+                               if(!(kr6->r.flags & F_DOWN))
+                                       kr_redistribute6(IMSG_NETWORK_ADD,
+                                           kt, &kr6->r);
                }
        }
 
@@ -2502,6 +2515,10 @@ if_change(u_short ifindex, int flags, struct if_data *ifd)
                if (kt == NULL)
                        continue;
 
+               kr_redistribute(reachable ?
+                   IMSG_NETWORK_ADD : IMSG_NETWORK_REMOVE,
+                   kt, &(kkr->kr->r));
+
                knexthop_track(kt, kkr->kr);
        }
        LIST_FOREACH(kkr6, &kif->kroute6_l, entry) {
@@ -2513,6 +2530,10 @@ if_change(u_short ifindex, int flags, struct if_data *ifd)
                if (kt == NULL)
                        continue;
 
+               kr_redistribute6(reachable ?
+                   IMSG_NETWORK_ADD : IMSG_NETWORK_REMOVE,
+                   kt, &(kkr6->kr->r));
+
                knexthop_track(kt, kkr6->kr);
        }
 }
index 331f04e..3359fcd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.307 2017/05/29 07:49:27 phessler Exp $ */
+/*     $OpenBSD: parse.y,v 1.308 2017/05/31 10:44:00 claudio Exp $ */
 
 /*
  * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -150,7 +150,7 @@ int          getcommunity(char *);
 int             parsecommunity(struct filter_community *, char *);
 int64_t         getlargecommunity(char *);
 int             parselargecommunity(struct filter_largecommunity *, char *);
-int             parsesubtype(char *);
+int             parsesubtype(char *, int *, int *);
 int             parseextvalue(char *, u_int32_t *);
 int             parseextcommunity(struct filter_extcommunity *, char *,
                    char *);
@@ -871,13 +871,13 @@ rdomainopts       : RD STRING {
                        }
                        rd = betoh64(rd) & 0xffffffffffffULL;
                        switch (ext.type) {
-                       case EXT_COMMUNITY_TWO_AS:
+                       case EXT_COMMUNITY_TRANS_TWO_AS:
                                rd |= (0ULL << 48);
                                break;
-                       case EXT_COMMUNITY_IPV4:
+                       case EXT_COMMUNITY_TRANS_IPV4:
                                rd |= (1ULL << 48);
                                break;
-                       case EXT_COMMUNITY_FOUR_AS:
+                       case EXT_COMMUNITY_TRANS_FOUR_AS:
                                rd |= (2ULL << 48);
                                break;
                        default:
@@ -3089,26 +3089,23 @@ parselargecommunity(struct filter_largecommunity *c, char *s)
 }
 
 int
-parsesubtype(char *type)
+parsesubtype(char *name, int *type, int *subtype)
 {
-       /* this has to be sorted always */
-       static const struct keywords keywords[] = {
-               { "bdc",        EXT_COMMUNITY_BGP_COLLECT },
-               { "odi",        EXT_COMMUNITY_OSPF_DOM_ID },
-               { "ori",        EXT_COMMUNITY_OSPF_RTR_ID },
-               { "ort",        EXT_COMMUNITY_OSPF_RTR_TYPE },
-               { "rt",         EXT_COMMUNITY_ROUTE_TGT },
-               { "soo",        EXT_COMMUNITY_ROUTE_ORIG }
-       };
-       const struct keywords   *p;
-
-       p = bsearch(type, keywords, sizeof(keywords)/sizeof(keywords[0]),
-           sizeof(keywords[0]), kw_cmp);
+       const struct ext_comm_pairs *cp;
+       int found = 0;
 
-       if (p)
-               return (p->k_val);
-       else
-               return (-1);
+       for (cp = iana_ext_comms; cp->subname != NULL; cp++) {
+               if (strcmp(name, cp->subname) == 0) {
+                       if (found == 0) {
+                               *type = cp->type;
+                               *subtype = cp->subtype;
+                       }
+                       found++;
+               }
+       }
+       if (found > 1)
+               *type = -1;
+       return (found);
 }
 
 int
@@ -3127,10 +3124,10 @@ parseextvalue(char *s, u_int32_t *v)
                        return (-1);
                }
                *v = uval;
-               if (uval > USHRT_MAX)
-                       return (EXT_COMMUNITY_FOUR_AS);
+               if (uval <= USHRT_MAX)
+                       return (EXT_COMMUNITY_TRANS_TWO_AS);
                else
-                       return (EXT_COMMUNITY_TWO_AS);
+                       return (EXT_COMMUNITY_TRANS_FOUR_AS);
        } else if (strchr(p + 1, '.') == NULL) {
                /* AS_DOT number (4-byte) */
                *p++ = '\0';
@@ -3145,7 +3142,7 @@ parseextvalue(char *s, u_int32_t *v)
                        return (-1);
                }
                *v = uval | (uvalh << 16);
-               return (EXT_COMMUNITY_FOUR_AS);
+               return (EXT_COMMUNITY_TRANS_FOUR_AS);
        } else {
                /* more than one dot -> IP address */
                if (inet_aton(s, &ip) == 0) {
@@ -3153,7 +3150,7 @@ parseextvalue(char *s, u_int32_t *v)
                        return (-1);
                }
                *v = ip.s_addr;
-               return (EXT_COMMUNITY_IPV4);
+               return (EXT_COMMUNITY_TRANS_IPV4);
        }
        return (-1);
 }
@@ -3161,75 +3158,90 @@ parseextvalue(char *s, u_int32_t *v)
 int
 parseextcommunity(struct filter_extcommunity *c, char *t, char *s)
 {
-       const struct ext_comm_pairs      iana[] = IANA_EXT_COMMUNITIES;
+       const struct ext_comm_pairs *cp;
        const char      *errstr;
        u_int64_t        ullval;
        u_int32_t        uval;
        char            *p, *ep;
-       unsigned int     i;
        int              type, subtype;
 
-       if ((subtype = parsesubtype(t)) == -1) {
+       if (parsesubtype(t, &type, &subtype) == 0) {
                yyerror("Bad ext-community unknown type");
                return (-1);
        }
 
-       if ((p = strchr(s, ':')) == NULL) {
-               type = EXT_COMMUNITY_OPAQUE,
-               errno = 0;
-               ullval = strtoull(s, &ep, 0);
-               if (s[0] == '\0' || *ep != '\0') {
-                       yyerror("Bad ext-community bad value");
-                       return (-1);
-               }
-               if (errno == ERANGE && ullval > EXT_COMMUNITY_OPAQUE_MAX) {
-                       yyerror("Bad ext-community value to big");
+       switch (type) {
+       case -1:
+               if ((p = strchr(s, ':')) == NULL) {
+                       yyerror("Bad ext-community %s is %s", s, errstr);
                        return (-1);
                }
-               c->data.ext_opaq = ullval;
-       } else {
                *p++ = '\0';
                if ((type = parseextvalue(s, &uval)) == -1)
                        return (-1);
                switch (type) {
-               case EXT_COMMUNITY_TWO_AS:
+               case EXT_COMMUNITY_TRANS_TWO_AS:
                        ullval = strtonum(p, 0, UINT_MAX, &errstr);
                        break;
-               case EXT_COMMUNITY_IPV4:
-               case EXT_COMMUNITY_FOUR_AS:
+               case EXT_COMMUNITY_TRANS_IPV4:
+               case EXT_COMMUNITY_TRANS_FOUR_AS:
                        ullval = strtonum(p, 0, USHRT_MAX, &errstr);
                        break;
                default:
                        fatalx("parseextcommunity: unexpected result");
                }
                if (errstr) {
-                       yyerror("Bad ext-community %s is %s", p,
-                           errstr);
+                       yyerror("Bad ext-community %s is %s", p, errstr);
                        return (-1);
                }
                switch (type) {
-               case EXT_COMMUNITY_TWO_AS:
+               case EXT_COMMUNITY_TRANS_TWO_AS:
                        c->data.ext_as.as = uval;
                        c->data.ext_as.val = ullval;
                        break;
-               case EXT_COMMUNITY_IPV4:
+               case EXT_COMMUNITY_TRANS_IPV4:
                        c->data.ext_ip.addr.s_addr = uval;
                        c->data.ext_ip.val = ullval;
                        break;
-               case EXT_COMMUNITY_FOUR_AS:
+               case EXT_COMMUNITY_TRANS_FOUR_AS:
                        c->data.ext_as4.as4 = uval;
                        c->data.ext_as4.val = ullval;
                        break;
                }
+               break;
+       case EXT_COMMUNITY_TRANS_OPAQUE:
+       case EXT_COMMUNITY_TRANS_EVPN:
+               errno = 0;
+               ullval = strtoull(s, &ep, 0);
+               if (s[0] == '\0' || *ep != '\0') {
+                       yyerror("Bad ext-community bad value");
+                       return (-1);
+               }
+               if (errno == ERANGE && ullval > EXT_COMMUNITY_OPAQUE_MAX) {
+                       yyerror("Bad ext-community value to big");
+                       return (-1);
+               }
+               c->data.ext_opaq = ullval;
+               break;
+       case EXT_COMMUNITY_NON_TRANS_OPAQUE:
+               if (strcmp(s, "valid") == 0)
+                       c->data.ext_opaq = EXT_COMMUNITY_OVS_VALID;
+               else if (strcmp(s, "invalid") == 0)
+                       c->data.ext_opaq = EXT_COMMUNITY_OVS_INVALID;
+               else if (strcmp(s, "not-found") == 0)
+                       c->data.ext_opaq = EXT_COMMUNITY_OVS_NOTFOUND;
+               else {
+                       yyerror("Bad ext-community %s is %s", s, errstr);
+                       return (-1);
+               }
+               break;
        }
        c->type = type;
        c->subtype = subtype;
 
        /* verify type/subtype combo */
-       for (i = 0; i < sizeof(iana)/sizeof(iana[0]); i++) {
-               if (iana[i].type == type && iana[i].subtype == subtype) {
-                       if (iana[i].transitive)
-                               c->type |= EXT_COMMUNITY_TRANSITIVE;
+       for (cp = iana_ext_comms; cp->subname != NULL; cp++) {
+               if (cp->type == type && cp->subtype == subtype) {
                        c->flags |= EXT_COMMUNITY_FLAG_VALID;
                        return (0);
                }
index 9e5710a..afa96e4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: printconf.c,v 1.103 2017/05/27 18:12:23 phessler Exp $        */
+/*     $OpenBSD: printconf.c,v 1.104 2017/05/31 10:44:00 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -145,25 +145,39 @@ print_largecommunity(int64_t as, int64_t ld1, int64_t ld2)
 void
 print_extcommunity(struct filter_extcommunity *c)
 {
-       switch (c->type & EXT_COMMUNITY_VALUE) {
-       case EXT_COMMUNITY_TWO_AS:
-               printf("%s %hu:%u ", log_ext_subtype(c->subtype),
-                   c->data.ext_as.as, c->data.ext_as.val);
+       printf("%s ", log_ext_subtype(c->type, c->subtype));
+
+       switch (c->type) {
+       case EXT_COMMUNITY_TRANS_TWO_AS:
+               printf("%hu:%u ", c->data.ext_as.as, c->data.ext_as.val);
+               break;
+       case EXT_COMMUNITY_TRANS_IPV4:
+               printf("%s:%u ", inet_ntoa(c->data.ext_ip.addr),
+                   c->data.ext_ip.val);
                break;
-       case EXT_COMMUNITY_IPV4:
-               printf("%s %s:%u ", log_ext_subtype(c->subtype),
-                   inet_ntoa(c->data.ext_ip.addr), c->data.ext_ip.val);
+       case EXT_COMMUNITY_TRANS_FOUR_AS:
+               printf("%s:%u ", log_as(c->data.ext_as4.as4),
+                   c->data.ext_as.val);
                break;
-       case EXT_COMMUNITY_FOUR_AS:
-               printf("%s %s:%u ", log_ext_subtype(c->subtype),
-                   log_as(c->data.ext_as4.as4), c->data.ext_as.val);
+       case EXT_COMMUNITY_TRANS_OPAQUE:
+       case EXT_COMMUNITY_TRANS_EVPN:
+               printf("0x%llx ", c->data.ext_opaq);
                break;
-       case EXT_COMMUNITY_OPAQUE:
-               printf("%s 0x%llx ", log_ext_subtype(c->subtype),
-                   c->data.ext_opaq);
+       case EXT_COMMUNITY_NON_TRANS_OPAQUE:
+               switch (c->data.ext_opaq) {
+               case EXT_COMMUNITY_OVS_VALID:
+                       printf("valid ");
+                       break;
+               case EXT_COMMUNITY_OVS_NOTFOUND:
+                       printf("not-found ");
+                       break;
+               case EXT_COMMUNITY_OVS_INVALID:
+                       printf("invalid ");
+                       break;
+               }
                break;
        default:
-               printf("0x%x 0x%llx ", c->type, c->data.ext_opaq);
+               printf("0x%llx ", c->data.ext_opaq);
                break;
        }
 }
index 179849d..c53c211 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rde_attr.c,v 1.99 2017/05/30 18:08:15 benno Exp $ */
+/*     $OpenBSD: rde_attr.c,v 1.100 2017/05/31 10:44:00 claudio Exp $ */
 
 /*
  * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -1253,23 +1253,23 @@ community_ext_conv(struct filter_extcommunity *c, u_int16_t neighas,
 
        com = (u_int64_t)c->type << 56;
        switch (c->type & EXT_COMMUNITY_VALUE) {
-       case EXT_COMMUNITY_TWO_AS:
+       case EXT_COMMUNITY_TRANS_TWO_AS:
                com |= (u_int64_t)c->subtype << 48;
                com |= (u_int64_t)c->data.ext_as.as << 32;
                com |= c->data.ext_as.val;
                break;
-       case EXT_COMMUNITY_IPV4:
+       case EXT_COMMUNITY_TRANS_IPV4:
                com |= (u_int64_t)c->subtype << 48;
                ip = ntohl(c->data.ext_ip.addr.s_addr);
                com |= (u_int64_t)ip << 16;
                com |= c->data.ext_ip.val;
                break;
-       case EXT_COMMUNITY_FOUR_AS:
+       case EXT_COMMUNITY_TRANS_FOUR_AS:
                com |= (u_int64_t)c->subtype << 48;
                com |= (u_int64_t)c->data.ext_as4.as4 << 16;
                com |= c->data.ext_as4.val;
                break;
-       case EXT_COMMUNITY_OPAQUE:
+       case EXT_COMMUNITY_TRANS_OPAQUE:
                com |= (u_int64_t)c->subtype << 48;
                com |= c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX;
                break;
@@ -1298,10 +1298,10 @@ community_ext_matchone(struct filter_extcommunity *c, u_int16_t neighas,
                return (0);
 
        switch (c->type & EXT_COMMUNITY_VALUE) {
-       case EXT_COMMUNITY_TWO_AS:
-       case EXT_COMMUNITY_IPV4:
-       case EXT_COMMUNITY_FOUR_AS:
-       case EXT_COMMUNITY_OPAQUE:
+       case EXT_COMMUNITY_TRANS_TWO_AS:
+       case EXT_COMMUNITY_TRANS_IPV4:
+       case EXT_COMMUNITY_TRANS_FOUR_AS:
+       case EXT_COMMUNITY_TRANS_OPAQUE:
                com = (u_int64_t)c->subtype << 48;
                mask = 0xffULL << 48;
                if ((com & mask) != (community & mask))
@@ -1317,7 +1317,7 @@ community_ext_matchone(struct filter_extcommunity *c, u_int16_t neighas,
 
 
        switch (c->type & EXT_COMMUNITY_VALUE) {
-       case EXT_COMMUNITY_TWO_AS:
+       case EXT_COMMUNITY_TRANS_TWO_AS:
                com = (u_int64_t)c->data.ext_as.as << 32;
                mask = 0xffffULL << 32;
                if ((com & mask) != (community & mask))
@@ -1328,7 +1328,7 @@ community_ext_matchone(struct filter_extcommunity *c, u_int16_t neighas,
                if ((com & mask) == (community & mask))
                        return (1);
                break;
-       case EXT_COMMUNITY_IPV4:
+       case EXT_COMMUNITY_TRANS_IPV4:
                ip = ntohl(c->data.ext_ip.addr.s_addr);
                com = (u_int64_t)ip << 16;
                mask = 0xffffffff0000ULL;
@@ -1340,7 +1340,7 @@ community_ext_matchone(struct filter_extcommunity *c, u_int16_t neighas,
                if ((com & mask) == (community & mask))
                        return (1);
                break;
-       case EXT_COMMUNITY_FOUR_AS:
+       case EXT_COMMUNITY_TRANS_FOUR_AS:
                com = (u_int64_t)c->data.ext_as4.as4 << 16;
                mask = 0xffffffffULL << 16;
                if ((com & mask) != (community & mask))
@@ -1351,7 +1351,7 @@ community_ext_matchone(struct filter_extcommunity *c, u_int16_t neighas,
                if ((com & mask) == (community & mask))
                        return (1);
                break;
-       case EXT_COMMUNITY_OPAQUE:
+       case EXT_COMMUNITY_TRANS_OPAQUE:
                com = c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX;
                mask = EXT_COMMUNITY_OPAQUE_MAX;
                if ((com & mask) == (community & mask))
index f6b2641..bcf257e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: util.c,v 1.24 2017/01/24 04:22:42 benno Exp $ */
+/*     $OpenBSD: util.c,v 1.25 2017/05/31 10:44:00 claudio Exp $ */
 
 /*
  * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@@ -112,17 +112,17 @@ log_rd(u_int64_t rd)
 
        rd = betoh64(rd);
        switch (rd >> 48) {
-       case EXT_COMMUNITY_TWO_AS:
+       case EXT_COMMUNITY_TRANS_TWO_AS:
                u32 = rd & 0xffffffff;
                u16 = (rd >> 32) & 0xffff;
                snprintf(buf, sizeof(buf), "rd %hu:%u", u16, u32);
                break;
-       case EXT_COMMUNITY_FOUR_AS:
+       case EXT_COMMUNITY_TRANS_FOUR_AS:
                u32 = (rd >> 16) & 0xffffffff;
                u16 = rd & 0xffff;
                snprintf(buf, sizeof(buf), "rd %s:%hu", log_as(u32), u16);
                break;
-       case EXT_COMMUNITY_IPV4:
+       case EXT_COMMUNITY_TRANS_IPV4:
                u32 = (rd >> 16) & 0xffffffff;
                u16 = rd & 0xffff;
                addr.s_addr = htonl(u32);
@@ -134,30 +134,22 @@ log_rd(u_int64_t rd)
        return (buf);
 }
 
+const struct ext_comm_pairs iana_ext_comms[] = IANA_EXT_COMMUNITIES;
+
 /* NOTE: this function does not check if the type/subtype combo is
  * actually valid. */
 const char *
-log_ext_subtype(u_int8_t subtype)
+log_ext_subtype(u_int8_t type, u_int8_t subtype)
 {
        static char etype[6];
+       const struct ext_comm_pairs *cp;
 
-       switch (subtype) {
-       case EXT_COMMUNITY_ROUTE_TGT:
-               return ("rt");  /* route target */
-       case EXT_COMMUNITY_ROUTE_ORIG:
-               return ("soo"); /* source of origin */
-       case EXT_COMMUNITY_OSPF_DOM_ID:
-               return ("odi"); /* ospf domain id */
-       case EXT_COMMUNITY_OSPF_RTR_TYPE:
-               return ("ort"); /* ospf route type */
-       case EXT_COMMUNITY_OSPF_RTR_ID:
-               return ("ori"); /* ospf router id */
-       case EXT_COMMUNITY_BGP_COLLECT:
-               return ("bdc"); /* bgp data collection */
-       default:
-               snprintf(etype, sizeof(etype), "[%u]", subtype);
-               return (etype);
+       for (cp = iana_ext_comms; cp->subname != NULL; cp++) {
+               if (type == cp->type && subtype == cp->subtype)
+                       return (cp->subname);
        }
+       snprintf(etype, sizeof(etype), "[%u]", subtype);
+       return (etype);
 }
 
 const char *