mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 05:27:16 +02:00
bgpd: create cache server socket in vrf
Create cache server socket in vrf Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com> Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
parent
a3bd9bad37
commit
a951752d4a
230
bgpd/bgp_rpki.c
230
bgpd/bgp_rpki.c
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include "bgpd/bgp_rpki_clippy.c"
|
||||
|
||||
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_TEMP, "BGP RPKI Intermediate Buffer");
|
||||
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE, "BGP RPKI Cache server");
|
||||
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE_GROUP, "BGP RPKI Cache server group");
|
||||
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_RTRLIB, "BGP RPKI RTRLib");
|
||||
|
@ -75,6 +76,7 @@ struct cache {
|
|||
} tr_config;
|
||||
struct rtr_socket *rtr_socket;
|
||||
uint8_t preference;
|
||||
struct rpki_vrf *rpki_vrf;
|
||||
};
|
||||
|
||||
enum return_values { SUCCESS = 0, ERROR = -1 };
|
||||
|
@ -287,6 +289,99 @@ static int bgp_rpki_vrf_update(struct vrf *vrf, bool enabled)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* tcp identifier : <HOST>:<PORT>
|
||||
* ssh identifier : <user>@<HOST>:<PORT>
|
||||
*/
|
||||
static struct rpki_vrf *find_rpki_vrf_from_ident(const char *ident)
|
||||
{
|
||||
#if defined(FOUND_SSH)
|
||||
struct tr_ssh_config *ssh_config;
|
||||
#endif
|
||||
struct tr_tcp_config *tcp_config;
|
||||
struct listnode *rpki_vrf_nnode;
|
||||
unsigned int cache_port, port;
|
||||
struct listnode *cache_node;
|
||||
struct rpki_vrf *rpki_vrf;
|
||||
struct cache *cache;
|
||||
bool is_tcp = true;
|
||||
size_t host_len;
|
||||
char *endptr;
|
||||
char *host;
|
||||
char *ptr;
|
||||
char *buf;
|
||||
|
||||
/* extract the <SOCKET> */
|
||||
ptr = strrchr(ident, ':');
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
ptr++;
|
||||
/* extract port */
|
||||
port = atoi(ptr);
|
||||
if (port == 0)
|
||||
/* not ours */
|
||||
return NULL;
|
||||
|
||||
/* extract host */
|
||||
ptr--;
|
||||
host_len = (size_t)(ptr - ident);
|
||||
buf = XCALLOC(MTYPE_BGP_RPKI_TEMP, host_len + 1);
|
||||
memcpy(buf, ident, host_len);
|
||||
buf[host_len] = '\0';
|
||||
endptr = strrchr(buf, '@');
|
||||
|
||||
/* ssh session */
|
||||
if (endptr) {
|
||||
host = XCALLOC(MTYPE_BGP_RPKI_TEMP,
|
||||
(size_t)(buf + host_len - endptr) + 1);
|
||||
memcpy(host, endptr + 1, (size_t)(buf + host_len - endptr) + 1);
|
||||
is_tcp = false;
|
||||
} else {
|
||||
host = buf;
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(rpki_vrf_list, rpki_vrf_nnode, rpki_vrf)) {
|
||||
for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node,
|
||||
cache)) {
|
||||
if ((cache->type == TCP && !is_tcp)
|
||||
#if defined(FOUND_SSH)
|
||||
|| (cache->type == SSH && is_tcp)
|
||||
#endif
|
||||
)
|
||||
continue;
|
||||
|
||||
if (is_tcp) {
|
||||
tcp_config = cache->tr_config.tcp_config;
|
||||
cache_port = atoi(tcp_config->port);
|
||||
if (cache_port != port)
|
||||
continue;
|
||||
if (strlen(tcp_config->host) != strlen(host))
|
||||
continue;
|
||||
if (memcmp(tcp_config->host, host, host_len) ==
|
||||
0)
|
||||
break;
|
||||
}
|
||||
#if defined(FOUND_SSH)
|
||||
else {
|
||||
ssh_config = cache->tr_config.ssh_config;
|
||||
if (port != ssh_config->port)
|
||||
continue;
|
||||
if (strmatch(ssh_config->host, host))
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (cache)
|
||||
break;
|
||||
}
|
||||
if (host)
|
||||
XFREE(MTYPE_BGP_RPKI_TEMP, host);
|
||||
if (buf)
|
||||
XFREE(MTYPE_BGP_RPKI_TEMP, buf);
|
||||
return rpki_vrf;
|
||||
}
|
||||
|
||||
static struct rpki_vrf *find_rpki_vrf(const char *vrfname)
|
||||
{
|
||||
struct listnode *rpki_vrf_nnode;
|
||||
|
@ -608,8 +703,23 @@ static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
|
|||
{
|
||||
struct rpki_vrf *rpki_vrf;
|
||||
const char *msg;
|
||||
const struct rtr_socket *rtr = rec.socket;
|
||||
const char *ident;
|
||||
|
||||
rpki_vrf = find_rpki_vrf(NULL);
|
||||
if (!rtr) {
|
||||
msg = "could not find rtr_socket from cb_sync_rtr";
|
||||
goto err;
|
||||
}
|
||||
if (!rtr->tr_socket) {
|
||||
msg = "could not find tr_socket from cb_sync_rtr";
|
||||
goto err;
|
||||
}
|
||||
ident = rtr->tr_socket->ident_fp(rtr->tr_socket->socket);
|
||||
if (!ident) {
|
||||
msg = "could not find ident from cb_sync_rtr";
|
||||
goto err;
|
||||
}
|
||||
rpki_vrf = find_rpki_vrf_from_ident(ident);
|
||||
if (!rpki_vrf) {
|
||||
msg = "could not find rpki_vrf";
|
||||
goto err;
|
||||
|
@ -1068,11 +1178,16 @@ static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
|
|||
return RPKI_NOT_BEING_USED;
|
||||
}
|
||||
|
||||
static int add_cache(struct cache *cache, struct rpki_vrf *rpki_vrf)
|
||||
static int add_cache(struct cache *cache)
|
||||
{
|
||||
uint8_t preference = cache->preference;
|
||||
struct rtr_mgr_group group;
|
||||
struct list *cache_list;
|
||||
struct rpki_vrf *rpki_vrf;
|
||||
|
||||
rpki_vrf = cache->rpki_vrf;
|
||||
if (!rpki_vrf)
|
||||
return ERROR;
|
||||
|
||||
group.preference = preference;
|
||||
group.sockets_len = 1;
|
||||
|
@ -1097,6 +1212,105 @@ static int add_cache(struct cache *cache, struct rpki_vrf *rpki_vrf)
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int rpki_create_socket(void *_cache)
|
||||
{
|
||||
struct timeval prev_snd_tmout, prev_rcv_tmout, timeout;
|
||||
struct cache *cache = (struct cache *)_cache;
|
||||
struct rpki_vrf *rpki_vrf = cache->rpki_vrf;
|
||||
struct tr_tcp_config *tcp_config;
|
||||
struct addrinfo *res = NULL;
|
||||
struct addrinfo hints = {};
|
||||
socklen_t optlen;
|
||||
char *host, *port;
|
||||
struct vrf *vrf;
|
||||
int cancel_state;
|
||||
int socket;
|
||||
int ret;
|
||||
#if defined(FOUND_SSH)
|
||||
struct tr_ssh_config *ssh_config;
|
||||
char s_port[10];
|
||||
#endif
|
||||
|
||||
if (!cache)
|
||||
return -1;
|
||||
|
||||
if (rpki_vrf->vrfname == NULL)
|
||||
vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
else
|
||||
vrf = vrf_lookup_by_name(rpki_vrf->vrfname);
|
||||
if (!vrf)
|
||||
return -1;
|
||||
|
||||
if (!CHECK_FLAG(vrf->status, VRF_ACTIVE) || vrf->vrf_id == VRF_UNKNOWN)
|
||||
return -1;
|
||||
|
||||
if (cache->type == TCP) {
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
|
||||
tcp_config = cache->tr_config.tcp_config;
|
||||
host = tcp_config->host;
|
||||
port = tcp_config->port;
|
||||
}
|
||||
#if defined(FOUND_SSH)
|
||||
else {
|
||||
ssh_config = cache->tr_config.ssh_config;
|
||||
host = ssh_config->host;
|
||||
snprintf(s_port, sizeof(s_port), "%hu", ssh_config->port);
|
||||
port = s_port;
|
||||
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
}
|
||||
#endif
|
||||
|
||||
frr_with_privs (&bgpd_privs) {
|
||||
ret = vrf_getaddrinfo(host, port, &hints, &res, vrf->vrf_id);
|
||||
}
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
frr_with_privs (&bgpd_privs) {
|
||||
socket = vrf_socket(res->ai_family, res->ai_socktype,
|
||||
res->ai_protocol, vrf->vrf_id, NULL);
|
||||
}
|
||||
if (socket < 0)
|
||||
return -1;
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancel_state);
|
||||
timeout.tv_sec = 30;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
optlen = sizeof(prev_rcv_tmout);
|
||||
getsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &prev_rcv_tmout, &optlen);
|
||||
getsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &prev_snd_tmout, &optlen);
|
||||
|
||||
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
if (connect(socket, res->ai_addr, res->ai_addrlen) == -1) {
|
||||
if (res)
|
||||
freeaddrinfo(res);
|
||||
close(socket);
|
||||
pthread_setcancelstate(cancel_state, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (res)
|
||||
freeaddrinfo(res);
|
||||
pthread_setcancelstate(cancel_state, NULL);
|
||||
|
||||
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &prev_rcv_tmout,
|
||||
sizeof(prev_rcv_tmout));
|
||||
setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &prev_snd_tmout,
|
||||
sizeof(prev_snd_tmout));
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
static int add_tcp_cache(struct rpki_vrf *rpki_vrf, const char *host,
|
||||
const char *port, const uint8_t preference,
|
||||
const char *bindaddr)
|
||||
|
@ -1116,16 +1330,20 @@ static int add_tcp_cache(struct rpki_vrf *rpki_vrf, const char *host,
|
|||
else
|
||||
tcp_config->bindaddr = NULL;
|
||||
|
||||
tcp_config->data = cache;
|
||||
tcp_config->new_socket = rpki_create_socket;
|
||||
rtr_socket = create_rtr_socket(tr_socket);
|
||||
|
||||
cache->rpki_vrf = rpki_vrf;
|
||||
cache->type = TCP;
|
||||
cache->tr_socket = tr_socket;
|
||||
cache->tr_config.tcp_config = tcp_config;
|
||||
cache->rtr_socket = rtr_socket;
|
||||
cache->preference = preference;
|
||||
|
||||
int ret = add_cache(cache, rpki_vrf);
|
||||
int ret = add_cache(cache);
|
||||
if (ret != SUCCESS) {
|
||||
tcp_config->data = NULL;
|
||||
free_cache(cache);
|
||||
}
|
||||
return ret;
|
||||
|
@ -1152,6 +1370,8 @@ static int add_ssh_cache(struct rpki_vrf *rpki_vrf, const char *host,
|
|||
ssh_config->bindaddr = XSTRDUP(MTYPE_BGP_RPKI_CACHE, bindaddr);
|
||||
else
|
||||
ssh_config->bindaddr = NULL;
|
||||
ssh_config->data = cache;
|
||||
ssh_config->new_socket = rpki_create_socket;
|
||||
|
||||
ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
|
||||
ssh_config->client_privkey_path =
|
||||
|
@ -1161,14 +1381,16 @@ static int add_ssh_cache(struct rpki_vrf *rpki_vrf, const char *host,
|
|||
|
||||
rtr_socket = create_rtr_socket(tr_socket);
|
||||
|
||||
cache->rpki_vrf = rpki_vrf;
|
||||
cache->type = SSH;
|
||||
cache->tr_socket = tr_socket;
|
||||
cache->tr_config.ssh_config = ssh_config;
|
||||
cache->rtr_socket = rtr_socket;
|
||||
cache->preference = preference;
|
||||
|
||||
int ret = add_cache(cache, rpki_vrf);
|
||||
int ret = add_cache(cache);
|
||||
if (ret != SUCCESS) {
|
||||
ssh_config->data = NULL;
|
||||
free_cache(cache);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#ifndef __BGP_RPKI_H__
|
||||
#define __BGP_RPKI_H__
|
||||
|
||||
extern struct zebra_privs_t bgpd_privs;
|
||||
|
||||
enum rpki_states {
|
||||
RPKI_NOT_BEING_USED,
|
||||
RPKI_VALID,
|
||||
|
|
Loading…
Reference in a new issue