From a4faae3aacb9336338ad6f2a6df2fa3ebec3d7ca Mon Sep 17 00:00:00 2001 From: Pat Ruddy Date: Tue, 21 Jul 2020 15:03:41 +0100 Subject: [PATCH] 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 --- bgpd/bgp_network.c | 37 +++++++++++++++++++++++++++---------- bgpd/bgp_network.h | 5 +++-- bgpd/bgpd.c | 13 ++++++------- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index c324f259ba..cae11ae7bd 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -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); diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h index 018efbc08e..0b5cc17523 100644 --- a/bgpd/bgp_network.h +++ b/bgpd/bgp_network.h @@ -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); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index aade3f0404..c19f707727 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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; }