From 4122b697bbe16dc90a56e4d5597a203a7d31a494 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 17 Jan 2022 18:19:46 +0200 Subject: [PATCH] bgpd: Relax peer to be on the same host If the existing listener is the same as the peer, treat as self and reject. ``` exit1-debian-11# sh bgp listeners Name fd Address --------------------------- default 24 192.168.10.123 exit1-debian-11# con exit1-debian-11(config)# router bgp exit1-debian-11(config-router)# neighbor 192.168.10.123 remote-as external % Can not configure the local system as neighbor exit1-debian-11# sh bgp listeners Name fd Address --------------------------- default 24 0.0.0.0 default 25 :: exit1-debian-11# con exit1-debian-11(config)# router bgp exit1-debian-11(config-router)# neighbor 192.168.10.123 remote-as external % Can not configure the local system as neighbor exit1-debian-11(config-router)# exit1-debian-11# sh bgp listeners Name fd Address --------------------------- default 24 192.168.0.1 exit1-debian-11# con exit1-debian-11(config)# router bgp exit1-debian-11(config-router)# neighbor 192.168.10.123 remote-as external exit1-debian-11(config-router)# ``` Signed-off-by: Donatas Abraitis --- bgpd/bgp_network.c | 9 --------- bgpd/bgp_network.h | 8 ++++++++ bgpd/bgp_vty.c | 27 +++++++++++++++++++++++---- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 09abb69968..3fb7619ed1 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -52,15 +52,6 @@ extern struct zebra_privs_t bgpd_privs; static char *bgp_get_bound_name(struct peer *peer); -/* BGP listening socket. */ -struct bgp_listener { - int fd; - union sockunion su; - struct thread *thread; - struct bgp *bgp; - char *name; -}; - void bgp_dump_listener_info(struct vty *vty) { struct listnode *node; diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h index 0b5cc17523..22e34110bc 100644 --- a/bgpd/bgp_network.h +++ b/bgpd/bgp_network.h @@ -23,6 +23,14 @@ #define BGP_SOCKET_SNDBUF_SIZE 65536 +struct bgp_listener { + int fd; + union sockunion su; + struct thread *thread; + struct bgp *bgp; + char *name; +}; + extern void bgp_dump_listener_info(struct vty *vty); extern int bgp_socket(struct bgp *bgp, unsigned short port, const char *address); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index e07883865a..e851933315 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -54,6 +54,7 @@ #include "bgpd/bgp_errors.h" #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_nexthop.h" +#include "bgpd/bgp_network.h" #include "bgpd/bgp_open.h" #include "bgpd/bgp_regex.h" #include "bgpd/bgp_route.h" @@ -683,16 +684,34 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, static bool peer_address_self_check(struct bgp *bgp, union sockunion *su) { struct interface *ifp = NULL; + struct listnode *node; + struct bgp_listener *listener; + union sockunion all_su; - if (su->sa.sa_family == AF_INET) + if (su->sa.sa_family == AF_INET) { + str2sockunion("0.0.0.0", &all_su); ifp = if_lookup_by_ipv4_exact(&su->sin.sin_addr, bgp->vrf_id); - else if (su->sa.sa_family == AF_INET6) + } else if (su->sa.sa_family == AF_INET6) { + str2sockunion("::", &all_su); ifp = if_lookup_by_ipv6_exact(&su->sin6.sin6_addr, su->sin6.sin6_scope_id, bgp->vrf_id); + } - if (ifp) - return true; + if (ifp) { + for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener)) { + if (sockunion_family(su) != + sockunion_family(&listener->su)) + continue; + + /* If 0.0.0.0/:: is a listener, then treat as self and + * reject. + */ + if (!sockunion_cmp(&listener->su, su) || + !sockunion_cmp(&listener->su, &all_su)) + return true; + } + } return false; }