bgpd: associate listener with the appropriate bgp instance

When setting authentication on a BGP peer in a VRF the listener is
looked up from a global list. However there is no check that the
listener is the one associated with the VRF being configured. This
can result in the wrong listener beiong configured with a password,
leaving the intended listener in an open authentication state.
To simplify this lookup stash a pointer to the bgp instance in
the listener on creating (in the same way as is done for NS-based
VRFS).

Signed-off-by: Pat Ruddy <pat@voltanet.io>
This commit is contained in:
Pat Ruddy 2020-07-21 15:03:41 +01:00
parent 48a1bbdf76
commit a4faae3aac
3 changed files with 36 additions and 19 deletions

View File

@ -160,12 +160,26 @@ static int bgp_md5_set_password(struct peer *peer, const char *password)
*/
frr_with_privs(&bgpd_privs) {
for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener))
if (listener->su.sa.sa_family
== peer->su.sa.sa_family) {
if (listener->su.sa.sa_family ==
peer->su.sa.sa_family) {
uint16_t prefixlen =
peer->su.sa.sa_family == AF_INET
? IPV4_MAX_PREFIXLEN
: IPV6_MAX_PREFIXLEN;
? IPV4_MAX_PREFIXLEN
: IPV6_MAX_PREFIXLEN;
/*
* if we have stored a BGP vrf instance in the
* listener it must match the bgp instance in
* the peer otherwise the peer bgp instance
* must be the default vrf or a view instance
*/
if (!listener->bgp) {
if (peer->bgp->vrf_id != VRF_DEFAULT
&& peer->bgp->inst_type
!= BGP_INSTANCE_TYPE_VIEW)
continue;
} else if (listener->bgp != peer->bgp)
continue;
ret = bgp_md5_set_socket(listener->fd,
&peer->su, prefixlen,
@ -176,7 +190,7 @@ static int bgp_md5_set_password(struct peer *peer, const char *password)
return ret;
}
int bgp_md5_set_prefix(struct prefix *p, const char *password)
int bgp_md5_set_prefix(struct bgp *bgp, struct prefix *p, const char *password)
{
int ret = 0;
union sockunion su;
@ -186,7 +200,9 @@ int bgp_md5_set_prefix(struct prefix *p, const char *password)
/* Set or unset the password on the listen socket(s). */
frr_with_privs(&bgpd_privs) {
for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener))
if (listener->su.sa.sa_family == p->family) {
if (listener->su.sa.sa_family == p->family
&& ((bgp->vrf_id == VRF_DEFAULT)
|| (listener->bgp == bgp))) {
prefix2sockunion(p, &su);
ret = bgp_md5_set_socket(listener->fd, &su,
p->prefixlen,
@ -198,9 +214,9 @@ int bgp_md5_set_prefix(struct prefix *p, const char *password)
return ret;
}
int bgp_md5_unset_prefix(struct prefix *p)
int bgp_md5_unset_prefix(struct bgp *bgp, struct prefix *p)
{
return bgp_md5_set_prefix(p, NULL);
return bgp_md5_set_prefix(bgp, p, NULL);
}
int bgp_md5_set(struct peer *peer)
@ -812,8 +828,9 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
listener->fd = sock;
listener->name = XSTRDUP(MTYPE_BGP_LISTENER, bgp->name);
/* this socket needs a change of ns. record bgp back pointer */
if (bgp->vrf_id != VRF_DEFAULT && vrf_is_backend_netns())
/* this socket is in a vrf record bgp back pointer */
if (bgp->vrf_id != VRF_DEFAULT
&& bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
listener->bgp = bgp;
memcpy(&listener->su, sa, salen);

View File

@ -31,8 +31,9 @@ extern void bgp_close(void);
extern int bgp_connect(struct peer *);
extern int bgp_getsockname(struct peer *);
extern int bgp_md5_set_prefix(struct prefix *p, const char *password);
extern int bgp_md5_unset_prefix(struct prefix *p);
extern int bgp_md5_set_prefix(struct bgp *bgp, struct prefix *p,
const char *password);
extern int bgp_md5_unset_prefix(struct bgp *bgp, struct prefix *p);
extern int bgp_md5_set(struct peer *);
extern int bgp_md5_unset(struct peer *);
extern int bgp_set_socket_ttl(struct peer *, int fd);

View File

@ -2668,7 +2668,7 @@ int peer_group_listen_range_add(struct peer_group *group, struct prefix *range)
/* Update passwords for new ranges */
if (group->conf->password)
bgp_md5_set_prefix(prefix, group->conf->password);
bgp_md5_set_prefix(group->bgp, prefix, group->conf->password);
return 0;
}
@ -2715,7 +2715,7 @@ int peer_group_listen_range_del(struct peer_group *group, struct prefix *range)
/* Remove passwords for deleted ranges */
if (group->conf->password)
bgp_md5_unset_prefix(prefix);
bgp_md5_unset_prefix(group->bgp, prefix);
return 0;
}
@ -5621,9 +5621,9 @@ int peer_password_set(struct peer *peer, const char *password)
struct prefix *lr;
for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP], ln, lr))
bgp_md5_set_prefix(lr, password);
bgp_md5_set_prefix(peer->bgp, lr, password);
for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP6], ln, lr))
bgp_md5_set_prefix(lr, password);
bgp_md5_set_prefix(peer->bgp, lr, password);
return ret;
}
@ -5659,7 +5659,6 @@ int peer_password_unset(struct peer *peer)
/* Attempt to uninstall password on socket. */
if (!BGP_PEER_SU_UNSPEC(peer))
bgp_md5_unset(peer);
/* Skip peer-group mechanics for regular peers. */
return 0;
}
@ -5694,9 +5693,9 @@ int peer_password_unset(struct peer *peer)
struct prefix *lr;
for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP], ln, lr))
bgp_md5_unset_prefix(lr);
bgp_md5_unset_prefix(peer->bgp, lr);
for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP6], ln, lr))
bgp_md5_unset_prefix(lr);
bgp_md5_unset_prefix(peer->bgp, lr);
return 0;
}