bgpd: Split rpki cache command into separate per SSH/TCP

Current command (bundled two into one) is absolutely wrong.

When you configure TCP session with the source, the command thinks, that
it's a SSH session with a username.

It's much better to split this into two separate commands where it's much
easier to do the changes in the future (if more options comes in).

Yes, this is a breaking change, but there is no other proper way to overcome
this.

Bonus note how it looks, which also can lead to crashes (due to port 0x0):

```
(gdb) p *cache->tr_config.ssh_config
$11 = {host = 0x5555562f9cd0 "1.1.1.1", port = 0, bindaddr = 0x0,
  username = 0x55555629ad00 "",
  server_hostkey_path = 0x7ffff53667a0 <rpki_create_socket> "Uf\017\357\300H\211\345AWAVAUATSH\201", <incomplete sequence \354\230>, client_privkey_path = 0x0,
  data = 0x0, new_socket = 0x51, connect_timeout = 4143762592,
  password = 0x7ffff6fccca0 <main_arena+96> "\300\"0VUU"}
(gdb) p *cache->tr_config.tcp_config
$12 = {host = 0x5555562f9cd0 "1.1.1.1", port = 0x0, bindaddr = 0x0,
  data = 0x55555629ad00, new_socket = 0x7ffff53667a0 <rpki_create_socket>,
  connect_timeout = 0}
```

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
This commit is contained in:
Donatas Abraitis 2024-05-16 23:27:34 +03:00
parent 03e3da09a8
commit 043cff5286
4 changed files with 173 additions and 25 deletions

View File

@ -1621,7 +1621,7 @@ static int bgp_rpki_write_vrf(struct vty *vty, struct vrf *vrf)
#endif #endif
case TCP: case TCP:
tcp_config = cache->tr_config.tcp_config; tcp_config = cache->tr_config.tcp_config;
vty_out(vty, "%s rpki cache %s %s ", sep, vty_out(vty, "%s rpki cache tcp %s %s ", sep,
tcp_config->host, tcp_config->port); tcp_config->host, tcp_config->port);
if (tcp_config->bindaddr) if (tcp_config->bindaddr)
vty_out(vty, "source %s ", vty_out(vty, "source %s ",
@ -1630,7 +1630,7 @@ static int bgp_rpki_write_vrf(struct vty *vty, struct vrf *vrf)
#if defined(FOUND_SSH) #if defined(FOUND_SSH)
case SSH: case SSH:
ssh_config = cache->tr_config.ssh_config; ssh_config = cache->tr_config.ssh_config;
vty_out(vty, "%s rpki cache %s %u %s %s %s ", sep, vty_out(vty, "%s rpki cache ssh %s %u %s %s %s ", sep,
ssh_config->host, ssh_config->port, ssh_config->host, ssh_config->port,
ssh_config->username, ssh_config->username,
ssh_config->client_privkey_path, ssh_config->client_privkey_path,
@ -1918,6 +1918,9 @@ DEFUN (no_rpki_retry_interval,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
#if CONFDATE > 20240916
CPP_NOTICE("Remove rpki_cache_cmd")
#endif
DEFPY(rpki_cache, rpki_cache_cmd, DEFPY(rpki_cache, rpki_cache_cmd,
"rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)", "rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)",
RPKI_OUTPUT_STRING RPKI_OUTPUT_STRING
@ -1990,12 +1993,136 @@ DEFPY(rpki_cache, rpki_cache_cmd,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFPY(rpki_cache_tcp, rpki_cache_tcp_cmd,
"rpki cache tcp <A.B.C.D|WORD>$cache TCPPORT [source <A.B.C.D>$bindaddr] preference (1-255)",
RPKI_OUTPUT_STRING
"Install a cache server to current group\n"
"Use TCP\n"
"IP address of cache server\n"
"Hostname of cache server\n"
"TCP port number\n"
"Configure source IP address of RPKI connection\n"
"Define a Source IP Address\n"
"Preference of the cache server\n"
"Preference value\n")
{
int return_value;
struct listnode *cache_node;
struct cache *current_cache;
struct rpki_vrf *rpki_vrf;
bool init;
if (vty->node == RPKI_VRF_NODE)
rpki_vrf = VTY_GET_CONTEXT_SUB(rpki_vrf);
else
rpki_vrf = VTY_GET_CONTEXT(rpki_vrf);
if (!rpki_vrf)
return CMD_WARNING_CONFIG_FAILED;
if (!rpki_vrf || !rpki_vrf->cache_list)
return CMD_WARNING;
init = !!list_isempty(rpki_vrf->cache_list);
for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node,
current_cache)) {
if (current_cache->preference == preference) {
vty_out(vty,
"Cache with preference %ld is already configured\n",
preference);
return CMD_WARNING;
}
}
return_value = add_tcp_cache(rpki_vrf, cache, tcpport, preference,
bindaddr_str);
if (return_value == ERROR) {
vty_out(vty, "Could not create new rpki cache\n");
return CMD_WARNING;
}
if (init)
start(rpki_vrf);
return CMD_SUCCESS;
}
DEFPY(rpki_cache_ssh, rpki_cache_ssh_cmd,
"rpki cache ssh <A.B.C.D|WORD>$cache (1-65535)$sshport SSH_UNAME SSH_PRIVKEY [SERVER_PUBKEY] [source <A.B.C.D>$bindaddr] preference (1-255)",
RPKI_OUTPUT_STRING
"Install a cache server to current group\n"
"Use SSH\n"
"IP address of cache server\n"
"Hostname of cache server\n"
"SSH port number\n"
"SSH user name\n"
"Path to own SSH private key\n"
"Path to Public key of cache server\n"
"Configure source IP address of RPKI connection\n"
"Define a Source IP Address\n"
"Preference of the cache server\n"
"Preference value\n")
{
int return_value;
struct listnode *cache_node;
struct cache *current_cache;
struct rpki_vrf *rpki_vrf;
bool init;
if (vty->node == RPKI_VRF_NODE)
rpki_vrf = VTY_GET_CONTEXT_SUB(rpki_vrf);
else
rpki_vrf = VTY_GET_CONTEXT(rpki_vrf);
if (!rpki_vrf)
return CMD_WARNING_CONFIG_FAILED;
if (!rpki_vrf || !rpki_vrf->cache_list)
return CMD_WARNING;
init = !!list_isempty(rpki_vrf->cache_list);
for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node,
current_cache)) {
if (current_cache->preference == preference) {
vty_out(vty,
"Cache with preference %ld is already configured\n",
preference);
return CMD_WARNING;
}
}
#if defined(FOUND_SSH)
return_value = add_ssh_cache(rpki_vrf, cache, sshport, ssh_uname,
ssh_privkey, server_pubkey, preference,
bindaddr_str);
#else
return_value = SUCCESS;
vty_out(vty,
"ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
#endif
if (return_value == ERROR) {
vty_out(vty, "Could not create new rpki cache\n");
return CMD_WARNING;
}
if (init)
start(rpki_vrf);
return CMD_SUCCESS;
}
DEFPY (no_rpki_cache, DEFPY (no_rpki_cache,
no_rpki_cache_cmd, no_rpki_cache_cmd,
"no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)", "no rpki cache <tcp|ssh> <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)",
NO_STR NO_STR
RPKI_OUTPUT_STRING RPKI_OUTPUT_STRING
"Install a cache server to current group\n" "Install a cache server to current group\n"
"Use TCP\n"
"Use SSH\n"
"IP address of cache server\n" "IP address of cache server\n"
"Hostname of cache server\n" "Hostname of cache server\n"
"TCP port number\n" "TCP port number\n"
@ -2257,10 +2384,16 @@ DEFPY (show_rpki_cache_server,
if (cache->type == TCP) { if (cache->type == TCP) {
if (!json) { if (!json) {
vty_out(vty, vty_out(vty,
"host: %s port: %s, preference: %hhu\n", "host: %s port: %s, preference: %hhu, protocol: tcp",
cache->tr_config.tcp_config->host, cache->tr_config.tcp_config->host,
cache->tr_config.tcp_config->port, cache->tr_config.tcp_config->port,
cache->preference); cache->preference);
if (cache->tr_config.tcp_config->bindaddr)
vty_out(vty, ", source: %s\n",
cache->tr_config.tcp_config
->bindaddr);
else
vty_out(vty, "\n");
} else { } else {
json_server = json_object_new_object(); json_server = json_object_new_object();
json_object_string_add(json_server, "mode", json_object_string_add(json_server, "mode",
@ -2273,6 +2406,12 @@ DEFPY (show_rpki_cache_server,
cache->tr_config.tcp_config->port); cache->tr_config.tcp_config->port);
json_object_int_add(json_server, "preference", json_object_int_add(json_server, "preference",
cache->preference); cache->preference);
if (cache->tr_config.tcp_config->bindaddr)
json_object_string_add(json_server,
"source",
cache->tr_config
.tcp_config
->bindaddr);
json_object_array_add(json_servers, json_object_array_add(json_servers,
json_server); json_server);
} }
@ -2281,7 +2420,7 @@ DEFPY (show_rpki_cache_server,
} else if (cache->type == SSH) { } else if (cache->type == SSH) {
if (!json) { if (!json) {
vty_out(vty, vty_out(vty,
"host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s, preference: %hhu\n", "host: %s, port: %d, username: %s, server_hostkey_path: %s, client_privkey_path: %s, preference: %hhu, protocol: ssh",
cache->tr_config.ssh_config->host, cache->tr_config.ssh_config->host,
cache->tr_config.ssh_config->port, cache->tr_config.ssh_config->port,
cache->tr_config.ssh_config->username, cache->tr_config.ssh_config->username,
@ -2290,6 +2429,12 @@ DEFPY (show_rpki_cache_server,
cache->tr_config.ssh_config cache->tr_config.ssh_config
->client_privkey_path, ->client_privkey_path,
cache->preference); cache->preference);
if (cache->tr_config.ssh_config->bindaddr)
vty_out(vty, ", source: %s\n",
cache->tr_config.ssh_config
->bindaddr);
else
vty_out(vty, "\n");
} else { } else {
json_server = json_object_new_object(); json_server = json_object_new_object();
json_object_string_add(json_server, "mode", json_object_string_add(json_server, "mode",
@ -2313,6 +2458,12 @@ DEFPY (show_rpki_cache_server,
->client_privkey_path); ->client_privkey_path);
json_object_int_add(json_server, "preference", json_object_int_add(json_server, "preference",
cache->preference); cache->preference);
if (cache->tr_config.ssh_config->bindaddr)
json_object_string_add(json_server,
"source",
cache->tr_config
.ssh_config
->bindaddr);
json_object_array_add(json_servers, json_object_array_add(json_servers,
json_server); json_server);
} }
@ -2665,6 +2816,8 @@ static void install_cli_commands(void)
install_element(RPKI_NODE, &no_rpki_retry_interval_cmd); install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
/* Install rpki cache commands */ /* Install rpki cache commands */
install_element(RPKI_NODE, &rpki_cache_tcp_cmd);
install_element(RPKI_NODE, &rpki_cache_ssh_cmd);
install_element(RPKI_NODE, &rpki_cache_cmd); install_element(RPKI_NODE, &rpki_cache_cmd);
install_element(RPKI_NODE, &no_rpki_cache_cmd); install_element(RPKI_NODE, &no_rpki_cache_cmd);
@ -2687,6 +2840,8 @@ static void install_cli_commands(void)
install_element(RPKI_VRF_NODE, &no_rpki_retry_interval_cmd); install_element(RPKI_VRF_NODE, &no_rpki_retry_interval_cmd);
/* Install rpki cache commands */ /* Install rpki cache commands */
install_element(RPKI_VRF_NODE, &rpki_cache_tcp_cmd);
install_element(RPKI_VRF_NODE, &rpki_cache_ssh_cmd);
install_element(RPKI_VRF_NODE, &rpki_cache_cmd); install_element(RPKI_VRF_NODE, &rpki_cache_cmd);
install_element(RPKI_VRF_NODE, &no_rpki_cache_cmd); install_element(RPKI_VRF_NODE, &no_rpki_cache_cmd);

View File

@ -131,19 +131,13 @@ The following commands are available for independent of a specific cache server.
The default value is 600 seconds. The default value is 600 seconds.
.. clicmd:: rpki cache (A.B.C.D|WORD) PORT [SSH_USERNAME] [SSH_PRIVKEY_PATH] [KNOWN_HOSTS_PATH] [source A.B.C.D] preference (1-255) .. clicmd:: rpki cache tcp HOST PORT [source A.B.C.D] preference (1-255)
Add a TCP cache server to the socket.
Add a cache server to the socket. By default, the connection between router .. clicmd:: rpki cache ssh HOST PORT SSH_USERNAME SSH_PRIVKEY_PATH [SERVER_PUBKEY] [source A.B.C.D] preference (1-255)
and cache server is based on plain TCP. Protecting the connection between
router and cache server by SSH is optional. Deleting a socket removes the
associated cache server and terminates the existing connection.
A.B.C.D|WORD Add a SSH cache server to the socket.
Address of the cache server.
PORT
Port number to connect to the cache server
SSH_USERNAME SSH_USERNAME
SSH username to establish an SSH connection to the cache server. SSH username to establish an SSH connection to the cache server.
@ -151,7 +145,7 @@ The following commands are available for independent of a specific cache server.
SSH_PRIVKEY_PATH SSH_PRIVKEY_PATH
Local path that includes the private key file of the router. Local path that includes the private key file of the router.
KNOWN_HOSTS_PATH SERVER_PUBKEY
Local path that includes the known hosts file. The default value depends Local path that includes the known hosts file. The default value depends
on the configuration of the operating system environment, usually on the configuration of the operating system environment, usually
:file:`~/.ssh/known_hosts`. :file:`~/.ssh/known_hosts`.
@ -159,7 +153,6 @@ The following commands are available for independent of a specific cache server.
source A.B.C.D source A.B.C.D
Source address of the RPKI connection to access cache server. Source address of the RPKI connection to access cache server.
.. _validating-bgp-updates: .. _validating-bgp-updates:
Validating BGP Updates Validating BGP Updates
@ -267,9 +260,9 @@ RPKI Configuration Example
rpki polling_period 1000 rpki polling_period 1000
rpki timeout 10 rpki timeout 10
! SSH Example: ! SSH Example:
rpki cache example.com 22 rtr-ssh ./ssh_key/id_rsa preference 1 rpki cache ssh example.com 22 rtr-ssh ./ssh_key/id_rsa preference 1
! TCP Example: ! TCP Example:
rpki cache rpki-validator.realmv6.org 8282 preference 2 rpki cache tcp rpki-validator.realmv6.org 8282 preference 2
exit exit
! !
exit-vrf exit-vrf
@ -278,9 +271,9 @@ RPKI Configuration Example
rpki polling_period 1000 rpki polling_period 1000
rpki timeout 10 rpki timeout 10
! SSH Example: ! SSH Example:
rpki cache example.com source 198.51.100.223 22 rtr-ssh ./ssh_key/id_rsa preference 1 rpki cache ssh example.com source 198.51.100.223 22 rtr-ssh ./ssh_key/id_rsa preference 1
! TCP Example: ! TCP Example:
rpki cache rpki-validator.realmv6.org 8282 preference 2 rpki cache tcp rpki-validator.realmv6.org 8282 preference 2
exit exit
! !
router bgp 65001 router bgp 65001

View File

@ -21,5 +21,5 @@ router bgp 65002 vrf vrf10
! !
rpki rpki
rpki retry_interval 5 rpki retry_interval 5
rpki cache 192.0.2.1 15432 preference 1 rpki cache tcp 192.0.2.1 15432 preference 1
exit exit

View File

@ -189,7 +189,7 @@ def test_show_bgp_rpki_prefixes_no_rpki_cache():
""" """
configure configure
rpki rpki
no rpki cache 192.0.2.1 15432 preference 1 no rpki cache tcp 192.0.2.1 15432 preference 1
exit exit
""" """
) )
@ -219,7 +219,7 @@ def test_show_bgp_rpki_prefixes_reconnect():
""" """
configure configure
rpki rpki
rpki cache 192.0.2.1 15432 preference 1 rpki cache tcp 192.0.2.1 15432 preference 1
exit exit
""" """
) )
@ -319,7 +319,7 @@ def test_show_bgp_rpki_prefixes_vrf():
configure configure
vrf vrf10 vrf vrf10
rpki rpki
rpki cache 192.0.2.3 15432 preference 1 rpki cache tcp 192.0.2.3 15432 preference 1
exit exit
exit exit
""" """