]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Improve custom BGP attributes
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 5 Oct 2023 19:29:04 +0000 (21:29 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 5 Oct 2023 19:54:25 +0000 (21:54 +0200)
 - Implement EA_GET for custom BGP attributes
 - Forbid EA_SET on existing opaque attributes
 - Forbid redefining existing attributes
 - Document possible compatibility problems

doc/bird.sgml
filter/f-inst.c
proto/bgp/attrs.c
proto/bgp/bgp.h
proto/bgp/config.Y

index a023473fe2e60e755699b0a624091316febe132c..5e795450dbf4f08d612c33f810462d5a482530ae 100644 (file)
@@ -3561,10 +3561,14 @@ some of them (marked with `<tt/O/') are optional.
        name="local role"> is configured it set automatically.
 </descrip>
 
-<p>For attributes unknown by BIRD, the user can assign a name (on top level)
-to an attribute by its number. This defined name can be used then to both set
-(by a bytestring literal, transitive) or unset the given attribute even though
-BIRD knows nothing about it:
+<p>For attributes unknown by BIRD, the user can assign a name (on top level) to
+an attribute by its number. This defined name can be used then to get, set (as a
+bytestring, transitive) or unset the given attribute even though BIRD knows
+nothing about it.
+
+<p>Note that it is not possible to define an attribute with the same number
+as one known by BIRD, therefore use of this statement carries a risk of
+incompatibility with future BIRD versions.
 
 <tt><label id="bgp-attribute-custom">attribute bgp <m/number/ bytestring <m/name/;</tt>
 
index 4356a735f9c227a09d3eca681fcddfad6a093424..9cc46aa0853e869721b0743fdf06451f69b1c49b 100644 (file)
        RESULT_(T_QUAD, i, e->u.data);
        break;
       case EAF_TYPE_OPAQUE:
-       RESULT_(T_ENUM_EMPTY, i, 0);
+       if (da.f_type == T_ENUM_EMPTY)
+         RESULT_(T_ENUM_EMPTY, i, 0);
+       else
+         RESULT_(T_BYTESTRING, ad, e->u.ptr);
        break;
       case EAF_TYPE_IP_ADDRESS:
        RESULT_(T_IP, ip, *((ip_addr *) e->u.ptr->data));
     ARG_ANY(1);
     DYNAMIC_ATTR;
     ARG_TYPE(1, da.f_type);
+
+    FID_NEW_BODY;
+      if (da.f_type == T_ENUM_EMPTY)
+       cf_error("Setting opaque attribute is not allowed");
+
+    FID_INTERPRET_BODY;
     {
       struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr));
 
index 9387ddba97f99bd928abdc4f2f57674a9def02e7..4346cd5d484ca7574afb873792db28e8e297c06e 100644 (file)
@@ -1152,6 +1152,12 @@ bgp_attr_known(uint code)
   return (code < ARRAY_SIZE(bgp_attr_table)) && bgp_attr_table[code].name;
 }
 
+const char *
+bgp_attr_name(uint code)
+{
+  return (code < ARRAY_SIZE(bgp_attr_table)) ? bgp_attr_table[code].name : NULL;
+}
+
 void bgp_fix_attr_flags(ea_list *attrs)
 {
   for (u8 i = 0; i < attrs->count; i++)
index 1ba3de5e2e4e899d827f7b64a45ee33f9add225e..2e95037c75658d88a5e470b3cd4c9e0a315b487b 100644 (file)
@@ -611,6 +611,7 @@ bgp_unset_attr(ea_list **to, struct linpool *pool, uint code)
 
 int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
 
+const char * bgp_attr_name(uint code);
 int bgp_encode_attrs(struct bgp_write_state *s, ea_list *attrs, byte *buf, byte *end);
 ea_list * bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len);
 void bgp_finish_attrs(struct bgp_parse_state *s, rta *a);
index 4e7d0329d3eba8d312edf6539297365b41115e75..6981a117ccbe4e3e95d78f9abf6c24a2f3964d4d 100644 (file)
@@ -365,11 +365,14 @@ dynamic_attr: BGP_LARGE_COMMUNITY
 dynamic_attr: BGP_OTC
        { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_ONLY_TO_CUSTOMER)); } ;
 
-custom_attr: ATTRIBUTE BGP NUM type symbol ';' {
-  if($3 > 255 || $3 < 1)
-    cf_error("Invalid attribute number. (Given %i, must be 1-255.)", $3);
-  if($4 != T_BYTESTRING)
+custom_attr: ATTRIBUTE BGP expr type symbol ';' {
+  if ($3 > 255 || $3 < 1)
+    cf_error("Invalid attribute number (Given %i, must be 1-255)", $3);
+  if ($4 != T_BYTESTRING)
     cf_error("Attribute type must be bytestring, not %s", f_type_name($4));
+  if (bgp_attr_name($3))
+    cf_error("Attribute BGP.%d already known as %s", $3, bgp_attr_name($3));
+
   struct f_dynamic_attr *a = cfg_alloc(sizeof(struct f_dynamic_attr));
   *a = f_new_dynamic_attr(f_type_attr($4), T_BYTESTRING, EA_CODE(PROTOCOL_BGP, $3));
   a->flags = BAF_TRANSITIVE | BAF_OPTIONAL;