1 /* BGP network related fucntions
2 * Copyright (C) 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "sockunion.h"
38 #include "lib_errors.h"
41 #include "bgpd/bgpd.h"
42 #include "bgpd/bgp_open.h"
43 #include "bgpd/bgp_fsm.h"
44 #include "bgpd/bgp_attr.h"
45 #include "bgpd/bgp_debug.h"
46 #include "bgpd/bgp_errors.h"
47 #include "bgpd/bgp_network.h"
48 #include "bgpd/bgp_zebra.h"
50 extern struct zebra_privs_t bgpd_privs
;
52 static char *bgp_get_bound_name(struct peer
*peer
);
54 /* BGP listening socket. */
58 struct thread
*thread
;
63 * Set MD5 key for the socket, for the given IPv4 peer address.
64 * If the password is NULL or zero-length, the option will be disabled.
66 static int bgp_md5_set_socket(int socket
, union sockunion
*su
,
67 uint16_t prefixlen
, const char *password
)
71 #if HAVE_DECL_TCP_MD5SIG
73 #endif /* HAVE_TCP_MD5SIG */
77 #if HAVE_DECL_TCP_MD5SIG
78 /* Ensure there is no extraneous port information. */
79 memcpy(&su2
, su
, sizeof(union sockunion
));
80 if (su2
.sa
.sa_family
== AF_INET
)
83 su2
.sin6
.sin6_port
= 0;
85 /* For addresses, use the non-extended signature functionality */
86 if ((su2
.sa
.sa_family
== AF_INET
&& prefixlen
== IPV4_MAX_PREFIXLEN
)
87 || (su2
.sa
.sa_family
== AF_INET6
88 && prefixlen
== IPV6_MAX_PREFIXLEN
))
89 ret
= sockopt_tcp_signature(socket
, &su2
, password
);
91 ret
= sockopt_tcp_signature_ext(socket
, &su2
, prefixlen
,
94 #endif /* HAVE_TCP_MD5SIG */
97 char sabuf
[SU_ADDRSTRLEN
];
98 sockunion2str(su
, sabuf
, sizeof(sabuf
));
104 "Unable to set TCP MD5 option on socket for peer %s (sock=%d): This platform does not support MD5 auth for prefixes",
110 "Unable to set TCP MD5 option on socket for peer %s (sock=%d): %s",
111 sabuf
, socket
, safe_strerror(en
));
118 /* Helper for bgp_connect */
119 static int bgp_md5_set_connect(int socket
, union sockunion
*su
,
120 uint16_t prefixlen
, const char *password
)
124 #if HAVE_DECL_TCP_MD5SIG
125 frr_elevate_privs(&bgpd_privs
) {
126 ret
= bgp_md5_set_socket(socket
, su
, prefixlen
, password
);
128 #endif /* HAVE_TCP_MD5SIG */
133 static int bgp_md5_set_password(struct peer
*peer
, const char *password
)
135 struct listnode
*node
;
137 struct bgp_listener
*listener
;
140 * Set or unset the password on the listen socket(s). Outbound
141 * connections are taken care of in bgp_connect() below.
143 frr_elevate_privs(&bgpd_privs
)
145 for (ALL_LIST_ELEMENTS_RO(bm
->listen_sockets
, node
, listener
))
146 if (listener
->su
.sa
.sa_family
147 == peer
->su
.sa
.sa_family
) {
149 peer
->su
.sa
.sa_family
== AF_INET
151 : IPV6_MAX_PREFIXLEN
;
153 ret
= bgp_md5_set_socket(listener
->fd
,
154 &peer
->su
, prefixlen
,
162 int bgp_md5_set_prefix(struct prefix
*p
, const char *password
)
166 struct listnode
*node
;
167 struct bgp_listener
*listener
;
169 /* Set or unset the password on the listen socket(s). */
170 frr_elevate_privs(&bgpd_privs
)
172 for (ALL_LIST_ELEMENTS_RO(bm
->listen_sockets
, node
, listener
))
173 if (listener
->su
.sa
.sa_family
== p
->family
) {
174 prefix2sockunion(p
, &su
);
175 ret
= bgp_md5_set_socket(listener
->fd
, &su
,
185 int bgp_md5_unset_prefix(struct prefix
*p
)
187 return bgp_md5_set_prefix(p
, NULL
);
190 int bgp_md5_set(struct peer
*peer
)
192 /* Set the password from listen socket. */
193 return bgp_md5_set_password(peer
, peer
->password
);
196 int bgp_md5_unset(struct peer
*peer
)
198 /* Unset the password from listen socket. */
199 return bgp_md5_set_password(peer
, NULL
);
202 int bgp_set_socket_ttl(struct peer
*peer
, int bgp_sock
)
204 char buf
[INET_ADDRSTRLEN
];
207 /* In case of peer is EBGP, we should set TTL for this connection. */
208 if (!peer
->gtsm_hops
&& (peer_sort(peer
) == BGP_PEER_EBGP
)) {
209 ret
= sockopt_ttl(peer
->su
.sa
.sa_family
, bgp_sock
, peer
->ttl
);
213 "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
215 inet_ntop(AF_INET
, &peer
->remote_id
, buf
,
220 } else if (peer
->gtsm_hops
) {
221 /* On Linux, setting minttl without setting ttl seems to mess
223 outgoing ttl. Therefore setting both.
225 ret
= sockopt_ttl(peer
->su
.sa
.sa_family
, bgp_sock
, MAXTTL
);
229 "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
231 inet_ntop(AF_INET
, &peer
->remote_id
, buf
,
236 ret
= sockopt_minttl(peer
->su
.sa
.sa_family
, bgp_sock
,
237 MAXTTL
+ 1 - peer
->gtsm_hops
);
241 "%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d",
243 inet_ntop(AF_INET
, &peer
->remote_id
, buf
,
254 * Obtain the BGP instance that the incoming connection should be processed
255 * against. This is important because more than one VRF could be using the
256 * same IP address space. The instance is got by obtaining the device to
257 * which the incoming connection is bound to. This could either be a VRF
258 * or it could be an interface, which in turn determines the VRF.
260 static int bgp_get_instance_for_inc_conn(int sock
, struct bgp
**bgp_inst
)
262 #ifndef SO_BINDTODEVICE
263 /* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here
264 * anyway since the assumption is that the interface name returned by
265 * getsockopt() is useful in identifying the VRF, particularly with
267 * VRF l3master device. The whole mechanism is specific to Linux, so...
268 * when other platforms add VRF support, this will need handling here as
269 * well. (or, some restructuring) */
270 *bgp_inst
= bgp_get_default();
274 char name
[VRF_NAMSIZ
+ 1];
275 socklen_t name_len
= VRF_NAMSIZ
;
278 struct listnode
*node
, *nnode
;
282 rc
= getsockopt(sock
, SOL_SOCKET
, SO_BINDTODEVICE
, name
, &name_len
);
284 #if defined(HAVE_CUMULUS)
285 flog_err(EC_LIB_SOCKET
,
286 "[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d",
287 safe_strerror(errno
), sock
);
293 *bgp_inst
= bgp_get_default();
294 return 0; /* default instance. */
297 /* First try match to instance; if that fails, check for interfaces. */
298 bgp
= bgp_lookup_by_name(name
);
300 if (!bgp
->vrf_id
) // unexpected
306 /* TODO - This will be optimized once interfaces move into the NS */
307 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
308 struct interface
*ifp
;
310 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VIEW
)
313 ifp
= if_lookup_by_name(name
, bgp
->vrf_id
);
320 /* We didn't match to either an instance or an interface. */
325 /* Accept bgp connection. */
326 static int bgp_accept(struct thread
*thread
)
331 struct bgp_listener
*listener
= THREAD_ARG(thread
);
334 char buf
[SU_ADDRSTRLEN
];
335 struct bgp
*bgp
= NULL
;
339 /* Register accept thread. */
340 accept_sock
= THREAD_FD(thread
);
341 if (accept_sock
< 0) {
342 flog_err_sys(EC_LIB_SOCKET
, "accept_sock is nevative value %d",
346 listener
->thread
= NULL
;
348 thread_add_read(bm
->master
, bgp_accept
, listener
, accept_sock
,
351 /* Accept client connection. */
352 bgp_sock
= sockunion_accept(accept_sock
, &su
);
354 flog_err_sys(EC_LIB_SOCKET
,
355 "[Error] BGP socket accept failed (%s)",
356 safe_strerror(errno
));
359 set_nonblocking(bgp_sock
);
361 /* Obtain BGP instance this connection is meant for.
362 * - if it is a VRF netns sock, then BGP is in listener structure
363 * - otherwise, the bgp instance need to be demultiplexed
367 else if (bgp_get_instance_for_inc_conn(bgp_sock
, &bgp
)) {
368 if (bgp_debug_neighbor_events(NULL
))
370 "[Event] Could not get instance for incoming conn from %s",
371 inet_sutop(&su
, buf
));
376 /* Set socket send buffer size */
377 setsockopt_so_sendbuf(bgp_sock
, BGP_SOCKET_SNDBUF_SIZE
);
379 /* Check remote IP address */
380 peer1
= peer_lookup(bgp
, &su
);
383 peer1
= peer_lookup_dynamic_neighbor(bgp
, &su
);
385 /* Dynamic neighbor has been created, let it proceed */
386 peer1
->fd
= bgp_sock
;
387 bgp_fsm_change_status(peer1
, Active
);
389 peer1
->t_start
); /* created in peer_create() */
391 if (peer_active(peer1
))
392 BGP_EVENT_ADD(peer1
, TCP_connection_open
);
399 if (bgp_debug_neighbor_events(NULL
)) {
401 "[Event] %s connection rejected - not configured"
402 " and not valid for dynamic",
403 inet_sutop(&su
, buf
));
409 if (CHECK_FLAG(peer1
->flags
, PEER_FLAG_SHUTDOWN
)) {
410 if (bgp_debug_neighbor_events(peer1
))
412 "[Event] connection from %s rejected due to admin shutdown",
413 inet_sutop(&su
, buf
));
419 * Do not accept incoming connections in Clearing state. This can result
420 * in incorect state transitions - e.g., the connection goes back to
421 * Established and then the Clearing_Completed event is generated. Also,
422 * block incoming connection in Deleted state.
424 if (peer1
->status
== Clearing
|| peer1
->status
== Deleted
) {
425 if (bgp_debug_neighbor_events(peer1
))
427 "[Event] Closing incoming conn for %s (%p) state %d",
428 peer1
->host
, peer1
, peer1
->status
);
433 /* Check that at least one AF is activated for the peer. */
434 if (!peer_active(peer1
)) {
435 if (bgp_debug_neighbor_events(peer1
))
437 "%s - incoming conn rejected - no AF activated for peer",
443 /* Do not try to reconnect if the peer reached maximum
444 * prefixes, restart timer is still running or the peer
447 if (BGP_PEER_START_SUPPRESSED(peer1
)) {
448 if (bgp_debug_neighbor_events(peer1
))
450 "[Event] Incoming BGP connection rejected from %s "
451 "due to maximum-prefix or shutdown",
457 if (bgp_debug_neighbor_events(peer1
))
458 zlog_debug("[Event] BGP connection from host %s fd %d",
459 inet_sutop(&su
, buf
), bgp_sock
);
461 if (peer1
->doppelganger
) {
462 /* We have an existing connection. Kill the existing one and run
465 if (bgp_debug_neighbor_events(peer1
))
467 "[Event] New active connection from peer %s, Killing"
468 " previous active connection",
470 peer_delete(peer1
->doppelganger
);
473 if (bgp_set_socket_ttl(peer1
, bgp_sock
) < 0)
474 if (bgp_debug_neighbor_events(peer1
))
476 "[Event] Unable to set min/max TTL on peer %s, Continuing",
479 peer
= peer_create(&su
, peer1
->conf_if
, peer1
->bgp
, peer1
->local_as
,
480 peer1
->as
, peer1
->as_type
, 0, 0, NULL
);
481 hash_release(peer
->bgp
->peerhash
, peer
);
482 hash_get(peer
->bgp
->peerhash
, peer
, hash_alloc_intern
);
484 peer_xfer_config(peer
, peer1
);
485 UNSET_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
);
487 peer
->doppelganger
= peer1
;
488 peer1
->doppelganger
= peer
;
490 vrf_bind(peer
->bgp
->vrf_id
, bgp_sock
, bgp_get_bound_name(peer
));
491 bgp_fsm_change_status(peer
, Active
);
492 BGP_TIMER_OFF(peer
->t_start
); /* created in peer_create() */
494 SET_FLAG(peer
->sflags
, PEER_STATUS_ACCEPT_PEER
);
496 /* Make dummy peer until read Open packet. */
497 if (peer1
->status
== Established
498 && CHECK_FLAG(peer1
->sflags
, PEER_STATUS_NSF_MODE
)) {
499 /* If we have an existing established connection with graceful
501 * capability announced with one or more address families, then
503 * existing established connection and move state to connect.
505 peer1
->last_reset
= PEER_DOWN_NSF_CLOSE_SESSION
;
506 SET_FLAG(peer1
->sflags
, PEER_STATUS_NSF_WAIT
);
507 bgp_event_update(peer1
, TCP_connection_closed
);
510 if (peer_active(peer
)) {
511 BGP_EVENT_ADD(peer
, TCP_connection_open
);
517 /* BGP socket bind. */
518 static char *bgp_get_bound_name(struct peer
*peer
)
525 if ((peer
->bgp
->vrf_id
== VRF_DEFAULT
) && !peer
->ifname
529 if (peer
->su
.sa
.sa_family
!= AF_INET
530 && peer
->su
.sa
.sa_family
!= AF_INET6
)
531 return NULL
; // unexpected
533 /* For IPv6 peering, interface (unnumbered or link-local with interface)
534 * takes precedence over VRF. For IPv4 peering, explicit interface or
535 * VRF are the situations to bind.
537 if (peer
->su
.sa
.sa_family
== AF_INET6
)
538 name
= (peer
->conf_if
? peer
->conf_if
539 : (peer
->ifname
? peer
->ifname
542 name
= peer
->ifname
? peer
->ifname
: peer
->bgp
->name
;
547 static int bgp_update_address(struct interface
*ifp
, const union sockunion
*dst
,
548 union sockunion
*addr
)
550 struct prefix
*p
, *sel
, d
;
551 struct connected
*connected
;
552 struct listnode
*node
;
555 sockunion2hostprefix(dst
, &d
);
559 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, connected
)) {
560 p
= connected
->address
;
561 if (p
->family
!= d
.family
)
563 if (prefix_common_bits(p
, &d
) > common
) {
565 common
= prefix_common_bits(sel
, &d
);
572 prefix2sockunion(sel
, addr
);
576 /* Update source selection. */
577 static int bgp_update_source(struct peer
*peer
)
579 struct interface
*ifp
;
580 union sockunion addr
;
583 sockunion_init(&addr
);
585 /* Source is specified with interface name. */
586 if (peer
->update_if
) {
587 ifp
= if_lookup_by_name(peer
->update_if
, peer
->bgp
->vrf_id
);
591 if (bgp_update_address(ifp
, &peer
->su
, &addr
))
594 ret
= sockunion_bind(peer
->fd
, &addr
, 0, &addr
);
597 /* Source is specified with IP address. */
598 if (peer
->update_source
)
599 ret
= sockunion_bind(peer
->fd
, peer
->update_source
, 0,
600 peer
->update_source
);
605 #define DATAPLANE_MARK 254 /* main table ID */
607 /* BGP try to connect to the peer. */
608 int bgp_connect(struct peer
*peer
)
610 assert(!CHECK_FLAG(peer
->thread_flags
, PEER_THREAD_WRITES_ON
));
611 assert(!CHECK_FLAG(peer
->thread_flags
, PEER_THREAD_READS_ON
));
612 ifindex_t ifindex
= 0;
614 if (peer
->conf_if
&& BGP_PEER_SU_UNSPEC(peer
)) {
615 zlog_debug("Peer address not learnt: Returning from connect");
618 frr_elevate_privs(&bgpd_privs
) {
619 /* Make socket for the peer. */
620 peer
->fd
= vrf_sockunion_socket(&peer
->su
, peer
->bgp
->vrf_id
,
621 bgp_get_bound_name(peer
));
626 set_nonblocking(peer
->fd
);
628 /* Set socket send buffer size */
629 setsockopt_so_sendbuf(peer
->fd
, BGP_SOCKET_SNDBUF_SIZE
);
631 if (bgp_set_socket_ttl(peer
, peer
->fd
) < 0)
634 sockopt_reuseaddr(peer
->fd
);
635 sockopt_reuseport(peer
->fd
);
636 if (sockopt_mark_default(peer
->fd
, DATAPLANE_MARK
, &bgpd_privs
) < 0)
637 flog_warn(EC_BGP_NO_SOCKOPT_MARK
,
638 "Unable to set mark on FD for peer %s, err=%s",
639 peer
->host
, safe_strerror(errno
));
641 #ifdef IPTOS_PREC_INTERNETCONTROL
642 frr_elevate_privs(&bgpd_privs
) {
643 if (sockunion_family(&peer
->su
) == AF_INET
)
644 setsockopt_ipv4_tos(peer
->fd
,
645 IPTOS_PREC_INTERNETCONTROL
);
646 else if (sockunion_family(&peer
->su
) == AF_INET6
)
647 setsockopt_ipv6_tclass(peer
->fd
,
648 IPTOS_PREC_INTERNETCONTROL
);
652 if (peer
->password
) {
653 uint16_t prefixlen
= peer
->su
.sa
.sa_family
== AF_INET
655 : IPV6_MAX_PREFIXLEN
;
657 bgp_md5_set_connect(peer
->fd
, &peer
->su
, prefixlen
,
661 /* Update source bind. */
662 if (bgp_update_source(peer
) < 0) {
663 return connect_error
;
666 if (peer
->conf_if
|| peer
->ifname
)
667 ifindex
= ifname2ifindex(peer
->conf_if
? peer
->conf_if
671 if (bgp_debug_neighbor_events(peer
))
672 zlog_debug("%s [Event] Connect start to %s fd %d", peer
->host
,
673 peer
->host
, peer
->fd
);
675 /* Connect to the remote peer. */
676 return sockunion_connect(peer
->fd
, &peer
->su
, htons(peer
->port
),
680 /* After TCP connection is established. Get local address and port. */
681 int bgp_getsockname(struct peer
*peer
)
683 if (peer
->su_local
) {
684 sockunion_free(peer
->su_local
);
685 peer
->su_local
= NULL
;
688 if (peer
->su_remote
) {
689 sockunion_free(peer
->su_remote
);
690 peer
->su_remote
= NULL
;
693 peer
->su_local
= sockunion_getsockname(peer
->fd
);
696 peer
->su_remote
= sockunion_getpeername(peer
->fd
);
697 if (!peer
->su_remote
)
700 if (!bgp_zebra_nexthop_set(peer
->su_local
, peer
->su_remote
,
701 &peer
->nexthop
, peer
)) {
702 flog_err(EC_BGP_NH_UPD
,
703 "%s: nexthop_set failed, resetting connection - intf %p",
704 peer
->host
, peer
->nexthop
.ifp
);
711 static int bgp_listener(int sock
, struct sockaddr
*sa
, socklen_t salen
,
714 struct bgp_listener
*listener
;
717 sockopt_reuseaddr(sock
);
718 sockopt_reuseport(sock
);
720 frr_elevate_privs(&bgpd_privs
) {
722 #ifdef IPTOS_PREC_INTERNETCONTROL
723 if (sa
->sa_family
== AF_INET
)
724 setsockopt_ipv4_tos(sock
, IPTOS_PREC_INTERNETCONTROL
);
725 else if (sa
->sa_family
== AF_INET6
)
726 setsockopt_ipv6_tclass(sock
,
727 IPTOS_PREC_INTERNETCONTROL
);
730 sockopt_v6only(sa
->sa_family
, sock
);
732 ret
= bind(sock
, sa
, salen
);
737 flog_err_sys(EC_LIB_SOCKET
, "bind: %s", safe_strerror(en
));
741 ret
= listen(sock
, SOMAXCONN
);
743 flog_err_sys(EC_LIB_SOCKET
, "listen: %s", safe_strerror(errno
));
747 listener
= XCALLOC(MTYPE_BGP_LISTENER
, sizeof(*listener
));
750 /* this socket needs a change of ns. record bgp back pointer */
751 if (bgp
->vrf_id
!= VRF_DEFAULT
&& vrf_is_backend_netns())
754 memcpy(&listener
->su
, sa
, salen
);
755 listener
->thread
= NULL
;
756 thread_add_read(bm
->master
, bgp_accept
, listener
, sock
,
758 listnode_add(bm
->listen_sockets
, listener
);
763 /* IPv6 supported version of BGP server socket setup. */
764 int bgp_socket(struct bgp
*bgp
, unsigned short port
, const char *address
)
766 struct addrinfo
*ainfo
;
767 struct addrinfo
*ainfo_save
;
768 static const struct addrinfo req
= {
769 .ai_family
= AF_UNSPEC
,
770 .ai_flags
= AI_PASSIVE
,
771 .ai_socktype
= SOCK_STREAM
,
774 char port_str
[BUFSIZ
];
776 snprintf(port_str
, sizeof(port_str
), "%d", port
);
777 port_str
[sizeof(port_str
) - 1] = '\0';
779 frr_elevate_privs(&bgpd_privs
) {
780 ret
= vrf_getaddrinfo(address
, port_str
, &req
, &ainfo_save
,
784 flog_err_sys(EC_LIB_SOCKET
, "getaddrinfo: %s",
788 if (bgp_option_check(BGP_OPT_NO_ZEBRA
) &&
789 bgp
->vrf_id
!= VRF_DEFAULT
) {
790 freeaddrinfo(ainfo_save
);
794 for (ainfo
= ainfo_save
; ainfo
; ainfo
= ainfo
->ai_next
) {
797 if (ainfo
->ai_family
!= AF_INET
&& ainfo
->ai_family
!= AF_INET6
)
800 frr_elevate_privs(&bgpd_privs
) {
801 sock
= vrf_socket(ainfo
->ai_family
,
803 ainfo
->ai_protocol
, bgp
->vrf_id
,
805 == BGP_INSTANCE_TYPE_VRF
806 ? bgp
->name
: NULL
));
809 flog_err_sys(EC_LIB_SOCKET
, "socket: %s",
810 safe_strerror(errno
));
814 /* if we intend to implement ttl-security, this socket needs
816 sockopt_ttl(ainfo
->ai_family
, sock
, MAXTTL
);
818 ret
= bgp_listener(sock
, ainfo
->ai_addr
, ainfo
->ai_addrlen
,
825 freeaddrinfo(ainfo_save
);
826 if (count
== 0 && bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
) {
829 "%s: no usable addresses please check other programs usage of specified port %d",
831 flog_err_sys(EC_LIB_SOCKET
, "%s: Program cannot continue",
839 /* this function closes vrf socket
840 * this should be called only for vrf socket with netns backend
842 void bgp_close_vrf_socket(struct bgp
*bgp
)
844 struct listnode
*node
, *next
;
845 struct bgp_listener
*listener
;
850 if (bm
->listen_sockets
== NULL
)
853 for (ALL_LIST_ELEMENTS(bm
->listen_sockets
, node
, next
, listener
)) {
854 if (listener
->bgp
== bgp
) {
855 thread_cancel(listener
->thread
);
857 listnode_delete(bm
->listen_sockets
, listener
);
858 XFREE(MTYPE_BGP_LISTENER
, listener
);
863 /* this function closes main socket
867 struct listnode
*node
, *next
;
868 struct bgp_listener
*listener
;
870 if (bm
->listen_sockets
== NULL
)
873 for (ALL_LIST_ELEMENTS(bm
->listen_sockets
, node
, next
, listener
)) {
876 thread_cancel(listener
->thread
);
878 listnode_delete(bm
->listen_sockets
, listener
);
879 XFREE(MTYPE_BGP_LISTENER
, listener
);