]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
RPKI: added documentation and RTR version config options
authorMaria Matejka <mq@ucw.cz>
Mon, 25 Nov 2024 08:35:33 +0000 (09:35 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 26 Nov 2024 03:47:33 +0000 (04:47 +0100)
doc/bird.sgml
proto/rpki/config.Y
proto/rpki/packets.c
proto/rpki/rpki.c
proto/rpki/rpki.h

index 0d1e6f490426bf3d576d40cec6bca58d253def85..ed45f6054205f9914fbc9d3d9d148a3be9a26564 100644 (file)
@@ -5728,6 +5728,10 @@ affected routes after RPKI update, see option <ref id="proto-rpki-reload"
 name="rpki reload">. Or you can use a BIRD client command <cf>reload in
 <m/bgp_protocol_name/</cf> for manual call of revalidation of all routes.
 
+<p>The same protocol, since version 2, also receives and maintains a set
+of ASPAs. You can then validate AS paths using function <cf/aspa_check()/
+in (import) filters.
+
 <sect1>Supported transports
 <p>
 <itemize>
@@ -5747,6 +5751,7 @@ define more RPKI protocols generally.
 protocol rpki [&lt;name&gt;] {
         roa4 { table &lt;tab&gt;; };
         roa6 { table &lt;tab&gt;; };
+       aspa { table &lt;tab&gt;; };
         remote &lt;ip&gt; | "&lt;domain&gt;" [port &lt;num&gt;];
         port &lt;num&gt;;
         local address &lt;ip&gt;;
@@ -5762,10 +5767,12 @@ protocol rpki [&lt;name&gt;] {
                 remote public key "&lt;/path/to/known_host&gt;";
                 user "&lt;name&gt;";
         };
+       max version 2;
+       min version 2;
 }
 </code>
 
-<p>Alse note that you have to specify the ROA channel. If you want to import
+<p>Alse note that you have to specify the ROA and ASPA channels. If you want to import
 only IPv4 prefixes you have to specify only roa4 channel. Similarly with IPv6
 prefixes only. If you want to fetch both IPv4 and even IPv6 ROAs you have to
 specify both channels.
@@ -5812,6 +5819,16 @@ specify both channels.
        instead. This may be useful for implementing loose RPKI check for
        blackholes. Default: disabled.
 
+       <tag>min version <m/num/</tag>
+       Minimal allowed version of the RTR protocol. BIRD will refuse to
+       downgrade a connection below this version and drop the session instead.
+       Default: 0
+
+       <tag>max version <m/num/</tag>
+       Maximal allowed version of the RTR protocol. BIRD will start with this
+        version. Use this option if sending version 2 to your cache causes
+        problems. Default: 2
+
         <tag>transport tcp { <m/TCP transport options.../ }</tag> Transport over
         TCP, it's the default transport. Cannot be combined with a SSH transport.
         Default: TCP, no authentication.
index 60a4b9f078ce5d8912f7753b69f4acbbf585bf72..68e0ebfdc918022b9e10929cccbc1d166d5dcbc0 100644 (file)
@@ -33,8 +33,8 @@ rpki_check_unused_transport(void)
 CF_DECLS
 
 CF_KEYWORDS(RPKI, REMOTE, BIRD, PRIVATE, PUBLIC, KEY, TCP, SSH, TRANSPORT, USER,
-           RETRY, REFRESH, EXPIRE, KEEP, IGNORE, MAX, LENGTH, LOCAL, ADDRESS,
-           AUTHENTICATION, NONE, MD5, PASSWORD)
+           RETRY, REFRESH, EXPIRE, KEEP, IGNORE, MAX, MIN, LENGTH, LOCAL, ADDRESS,
+           AUTHENTICATION, NONE, MD5, PASSWORD, VERSION)
 
 %type <i> rpki_keep_interval
 
@@ -47,6 +47,8 @@ rpki_proto_start: proto_start RPKI {
   RPKI_CFG->retry_interval = RPKI_RETRY_INTERVAL;
   RPKI_CFG->refresh_interval = RPKI_REFRESH_INTERVAL;
   RPKI_CFG->expire_interval = RPKI_EXPIRE_INTERVAL;
+  RPKI_CFG->min_version = 0;
+  RPKI_CFG->max_version = RPKI_MAX_VERSION;
 };
 
 rpki_proto: rpki_proto_start proto_name '{' rpki_proto_opts '}' { rpki_check_config(RPKI_CFG); };
@@ -83,6 +85,14 @@ rpki_proto_item:
      RPKI_CFG->keep_expire_interval = $2;
    }
  | IGNORE MAX LENGTH bool { RPKI_CFG->ignore_max_length = $4; }
+ | MIN VERSION expr {
+     if ($3 > RPKI_MAX_VERSION) cf_error("RPKI version %u unsupported, min version must be in range 0-%u", $3, RPKI_MAX_VERSION);
+     RPKI_CFG->min_version = $3;
+   }
+ | MAX VERSION expr {
+     if ($3 > RPKI_MAX_VERSION) cf_error("RPKI version %u unsupported, max version must be in range 0-%u", $3, RPKI_MAX_VERSION);
+     RPKI_CFG->max_version = $3;
+   }
  ;
 
 rpki_keep_interval:
index de9e861953d07c65128d8c5c9d1d403249c98794..c26c46d1206362bbf95ac38dc4a32e69efdccb9f 100644 (file)
@@ -628,7 +628,9 @@ rpki_check_receive_packet(struct rpki_cache *cache, const struct pdu_header *pdu
       }
       else if (!cache->last_update &&
               (pdu->ver <= RPKI_MAX_VERSION) &&
-              (pdu->ver < cache->version))
+              (pdu->ver < cache->version) &&
+              (pdu->ver >= cache->min_version)
+              )
       {
         CACHE_TRACE(D_EVENTS, cache, "Downgrade session to %s from %u to %u version", rpki_get_cache_ident(cache), cache->version, pdu->ver);
         cache->version = pdu->ver;
@@ -679,7 +681,8 @@ rpki_handle_error_pdu(struct rpki_cache *cache, const struct pdu_error *pdu)
   case UNSUPPORTED_PROTOCOL_VER:
     CACHE_TRACE(D_PACKETS, cache, "Client uses unsupported protocol version");
     if (pdu->ver <= RPKI_MAX_VERSION &&
-       pdu->ver < cache->version)
+       pdu->ver < cache->version &&
+       pdu->ver >= cache->min_version)
     {
       CACHE_TRACE(D_EVENTS, cache, "Downgrading from protocol version %d to version %d", cache->version, pdu->ver);
       cache->version = pdu->ver;
index e9d2a60aa6fc6d067719a189b4282925b7ed61c7..327c6215b43150ce9047049c89f6759adf3ffde8 100644 (file)
@@ -599,7 +599,8 @@ rpki_init_cache(struct rpki_proto *p, struct rpki_config *cf)
 
   cache->state = RPKI_CS_SHUTDOWN;
   cache->request_session_id = 1;
-  cache->version = RPKI_MAX_VERSION;
+  cache->version = cf->max_version;
+  cache->min_version = cf->min_version;
 
   cache->refresh_interval = cf->refresh_interval;
   cache->retry_interval = cf->retry_interval;
@@ -704,6 +705,23 @@ rpki_reconfigure_cache(struct rpki_proto *p UNUSED, struct rpki_cache *cache, st
     return NEED_RESTART;
   }
 
+  if (new->min_version > cache->version)
+  {
+    CACHE_TRACE(D_EVENTS, cache, "Protocol min version %u higher than current version %u",
+       new->min_version, cache->version);
+    return NEED_RESTART;
+  }
+  else
+    cache->min_version = new->min_version;
+
+  if (new->max_version < cache->version)
+  {
+    CACHE_TRACE(D_EVENTS, cache, "Protocol max version %u lower than current version %u",
+       new->max_version, cache->version);
+    cache->version = new->max_version;
+    try_reset = 1;
+  }
+
   if (old->tr_config.type != new->tr_config.type)
   {
     CACHE_TRACE(D_EVENTS, cache, "Transport type changed");
@@ -963,6 +981,9 @@ rpki_show_proto_info(struct proto *P)
 void
 rpki_check_config(struct rpki_config *cf)
 {
+  if (cf->min_version > cf->max_version)
+    cf_error("Impossible min/max version for RPKI: %u/%u", cf->min_version, cf->max_version);
+
   /* Do not check templates at all */
   if (cf->c.class == SYM_TEMPLATE)
     return;
index 307ec315a178d2e60d311c2ccbc222e2f4342fd6..1f5f978e25c123bc61df20054f8d414de758c330 100644 (file)
@@ -61,6 +61,7 @@ struct rpki_cache {
   u8 request_session_id;               /* 1: have to request new session id; 0: we have already received session id */
   u32 serial_num;                      /* Serial number denotes the logical version of data from cache server */
   u8 version;                          /* Protocol version */
+  u8 min_version;                      /* Minimum allowed protocol version */
   btime last_update;                   /* Last successful synchronization with cache server */
   btime last_rx_prefix;                        /* Last received prefix PDU */
 
@@ -132,6 +133,8 @@ struct rpki_config {
   u8 keep_retry_interval:1;            /* Do not overwrite retry interval by cache server update */
   u8 keep_expire_interval:1;           /* Do not overwrite expire interval by cache server update */
   u8 ignore_max_length:1;              /* Ignore received max length and use MAX_PREFIX_LENGTH instead */
+  u8 min_version;                      /* Minimum version allowed */
+  u8 max_version;                      /* Maximum version allowed (to start with) */
 };
 
 void rpki_check_config(struct rpki_config *cf);