]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_network.c
bgpd, lib, zebra: Convert LIB_ERR_PRIVILEGES
[mirror_frr.git] / bgpd / bgp_network.c
1 /* BGP network related fucntions
2 * Copyright (C) 1999 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
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
9 * later version.
10 *
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.
15 *
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
19 */
20
21 #include <zebra.h>
22
23 #include "thread.h"
24 #include "sockunion.h"
25 #include "sockopt.h"
26 #include "memory.h"
27 #include "log.h"
28 #include "if.h"
29 #include "prefix.h"
30 #include "command.h"
31 #include "privs.h"
32 #include "linklist.h"
33 #include "network.h"
34 #include "queue.h"
35 #include "hash.h"
36 #include "filter.h"
37 #include "ns.h"
38 #include "lib_errors.h"
39
40 #include "bgpd/bgpd.h"
41 #include "bgpd/bgp_open.h"
42 #include "bgpd/bgp_fsm.h"
43 #include "bgpd/bgp_attr.h"
44 #include "bgpd/bgp_debug.h"
45 #include "bgpd/bgp_network.h"
46
47 extern struct zebra_privs_t bgpd_privs;
48
49 static char *bgp_get_bound_name(struct peer *peer);
50
51 /* BGP listening socket. */
52 struct bgp_listener {
53 int fd;
54 union sockunion su;
55 struct thread *thread;
56 struct bgp *bgp;
57 };
58
59 /*
60 * Set MD5 key for the socket, for the given IPv4 peer address.
61 * If the password is NULL or zero-length, the option will be disabled.
62 */
63 static int bgp_md5_set_socket(int socket, union sockunion *su,
64 const char *password)
65 {
66 int ret = -1;
67 int en = ENOSYS;
68 #if HAVE_DECL_TCP_MD5SIG
69 union sockunion su2;
70 #endif /* HAVE_TCP_MD5SIG */
71
72 assert(socket >= 0);
73
74 #if HAVE_DECL_TCP_MD5SIG
75 /* Ensure there is no extraneous port information. */
76 memcpy(&su2, su, sizeof(union sockunion));
77 if (su2.sa.sa_family == AF_INET)
78 su2.sin.sin_port = 0;
79 else
80 su2.sin6.sin6_port = 0;
81 ret = sockopt_tcp_signature(socket, &su2, password);
82 en = errno;
83 #endif /* HAVE_TCP_MD5SIG */
84
85 if (ret < 0)
86 zlog_warn("can't set TCP_MD5SIG option on socket %d: %s",
87 socket, safe_strerror(en));
88
89 return ret;
90 }
91
92 /* Helper for bgp_connect */
93 static int bgp_md5_set_connect(int socket, union sockunion *su,
94 const char *password)
95 {
96 int ret = -1;
97
98 #if HAVE_DECL_TCP_MD5SIG
99 if (bgpd_privs.change(ZPRIVS_RAISE)) {
100 zlog_err("%s: could not raise privs", __func__);
101 return ret;
102 }
103
104 ret = bgp_md5_set_socket(socket, su, password);
105
106 if (bgpd_privs.change(ZPRIVS_LOWER))
107 zlog_err("%s: could not lower privs", __func__);
108 #endif /* HAVE_TCP_MD5SIG */
109
110 return ret;
111 }
112
113 static int bgp_md5_set_password(struct peer *peer, const char *password)
114 {
115 struct listnode *node;
116 int ret = 0;
117 struct bgp_listener *listener;
118
119 if (bgpd_privs.change(ZPRIVS_RAISE)) {
120 zlog_err("%s: could not raise privs", __func__);
121 return -1;
122 }
123
124 /* Set or unset the password on the listen socket(s). Outbound
125 * connections
126 * are taken care of in bgp_connect() below.
127 */
128 for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener))
129 if (listener->su.sa.sa_family == peer->su.sa.sa_family) {
130 ret = bgp_md5_set_socket(listener->fd, &peer->su,
131 password);
132 break;
133 }
134
135 if (bgpd_privs.change(ZPRIVS_LOWER))
136 zlog_err("%s: could not lower privs", __func__);
137
138 return ret;
139 }
140
141 int bgp_md5_set(struct peer *peer)
142 {
143 /* Set the password from listen socket. */
144 return bgp_md5_set_password(peer, peer->password);
145 }
146
147 int bgp_md5_unset(struct peer *peer)
148 {
149 /* Unset the password from listen socket. */
150 return bgp_md5_set_password(peer, NULL);
151 }
152
153 int bgp_set_socket_ttl(struct peer *peer, int bgp_sock)
154 {
155 char buf[INET_ADDRSTRLEN];
156 int ret = 0;
157
158 /* In case of peer is EBGP, we should set TTL for this connection. */
159 if (!peer->gtsm_hops && (peer_sort(peer) == BGP_PEER_EBGP)) {
160 ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, peer->ttl);
161 if (ret) {
162 zlog_err(
163 "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
164 __func__, inet_ntop(AF_INET, &peer->remote_id,
165 buf, sizeof(buf)),
166 errno);
167 return ret;
168 }
169 } else if (peer->gtsm_hops) {
170 /* On Linux, setting minttl without setting ttl seems to mess
171 with the
172 outgoing ttl. Therefore setting both.
173 */
174 ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, MAXTTL);
175 if (ret) {
176 zlog_err(
177 "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
178 __func__, inet_ntop(AF_INET, &peer->remote_id,
179 buf, sizeof(buf)),
180 errno);
181 return ret;
182 }
183 ret = sockopt_minttl(peer->su.sa.sa_family, bgp_sock,
184 MAXTTL + 1 - peer->gtsm_hops);
185 if (ret) {
186 zlog_err(
187 "%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d",
188 __func__, inet_ntop(AF_INET, &peer->remote_id,
189 buf, sizeof(buf)),
190 errno);
191 return ret;
192 }
193 }
194
195 return ret;
196 }
197
198 /*
199 * Obtain the BGP instance that the incoming connection should be processed
200 * against. This is important because more than one VRF could be using the
201 * same IP address space. The instance is got by obtaining the device to
202 * which the incoming connection is bound to. This could either be a VRF
203 * or it could be an interface, which in turn determines the VRF.
204 */
205 static int bgp_get_instance_for_inc_conn(int sock, struct bgp **bgp_inst)
206 {
207 #ifndef SO_BINDTODEVICE
208 /* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here
209 * anyway since the assumption is that the interface name returned by
210 * getsockopt() is useful in identifying the VRF, particularly with
211 * Linux's
212 * VRF l3master device. The whole mechanism is specific to Linux, so...
213 * when other platforms add VRF support, this will need handling here as
214 * well. (or, some restructuring) */
215 *bgp_inst = bgp_get_default();
216 return !*bgp_inst;
217
218 #else
219 char name[VRF_NAMSIZ + 1];
220 socklen_t name_len = VRF_NAMSIZ;
221 struct bgp *bgp;
222 int rc;
223 struct listnode *node, *nnode;
224
225 *bgp_inst = NULL;
226 name[0] = '\0';
227 rc = getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, name, &name_len);
228 if (rc != 0) {
229 #if defined(HAVE_CUMULUS)
230 zlog_err("[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d",
231 safe_strerror(errno), sock);
232 return -1;
233 #endif
234 }
235
236 if (!strlen(name)) {
237 *bgp_inst = bgp_get_default();
238 return 0; /* default instance. */
239 }
240
241 /* First try match to instance; if that fails, check for interfaces. */
242 bgp = bgp_lookup_by_name(name);
243 if (bgp) {
244 if (!bgp->vrf_id) // unexpected
245 return -1;
246 *bgp_inst = bgp;
247 return 0;
248 }
249
250 /* TODO - This will be optimized once interfaces move into the NS */
251 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
252 struct interface *ifp;
253
254 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
255 continue;
256
257 ifp = if_lookup_by_name(name, bgp->vrf_id);
258 if (ifp) {
259 *bgp_inst = bgp;
260 return 0;
261 }
262 }
263
264 /* We didn't match to either an instance or an interface. */
265 return -1;
266 #endif
267 }
268
269 /* Accept bgp connection. */
270 static int bgp_accept(struct thread *thread)
271 {
272 int bgp_sock;
273 int accept_sock;
274 union sockunion su;
275 struct bgp_listener *listener = THREAD_ARG(thread);
276 struct peer *peer;
277 struct peer *peer1;
278 char buf[SU_ADDRSTRLEN];
279 struct bgp *bgp = NULL;
280
281 sockunion_init(&su);
282
283 /* Register accept thread. */
284 accept_sock = THREAD_FD(thread);
285 if (accept_sock < 0) {
286 zlog_err("accept_sock is nevative value %d", accept_sock);
287 return -1;
288 }
289 listener->thread = NULL;
290
291 thread_add_read(bm->master, bgp_accept, listener, accept_sock,
292 &listener->thread);
293
294 /* Accept client connection. */
295 bgp_sock = sockunion_accept(accept_sock, &su);
296 if (bgp_sock < 0) {
297 zlog_err("[Error] BGP socket accept failed (%s)",
298 safe_strerror(errno));
299 return -1;
300 }
301 set_nonblocking(bgp_sock);
302
303 /* Obtain BGP instance this connection is meant for.
304 * - if it is a VRF netns sock, then BGP is in listener structure
305 * - otherwise, the bgp instance need to be demultiplexed
306 */
307 if (listener->bgp)
308 bgp = listener->bgp;
309 else if (bgp_get_instance_for_inc_conn(bgp_sock, &bgp)) {
310 if (bgp_debug_neighbor_events(NULL))
311 zlog_debug(
312 "[Event] Could not get instance for incoming conn from %s",
313 inet_sutop(&su, buf));
314 close(bgp_sock);
315 return -1;
316 }
317
318 /* Set socket send buffer size */
319 setsockopt_so_sendbuf(bgp_sock, BGP_SOCKET_SNDBUF_SIZE);
320
321 /* Check remote IP address */
322 peer1 = peer_lookup(bgp, &su);
323
324 if (!peer1) {
325 peer1 = peer_lookup_dynamic_neighbor(bgp, &su);
326 if (peer1) {
327 /* Dynamic neighbor has been created, let it proceed */
328 peer1->fd = bgp_sock;
329 bgp_fsm_change_status(peer1, Active);
330 BGP_TIMER_OFF(
331 peer1->t_start); /* created in peer_create() */
332
333 if (peer_active(peer1))
334 BGP_EVENT_ADD(peer1, TCP_connection_open);
335
336 return 0;
337 }
338 }
339
340 if (!peer1) {
341 if (bgp_debug_neighbor_events(NULL)) {
342 zlog_debug(
343 "[Event] %s connection rejected - not configured"
344 " and not valid for dynamic",
345 inet_sutop(&su, buf));
346 }
347 close(bgp_sock);
348 return -1;
349 }
350
351 if (CHECK_FLAG(peer1->flags, PEER_FLAG_SHUTDOWN)) {
352 if (bgp_debug_neighbor_events(peer1))
353 zlog_debug(
354 "[Event] connection from %s rejected due to admin shutdown",
355 inet_sutop(&su, buf));
356 close(bgp_sock);
357 return -1;
358 }
359
360 /*
361 * Do not accept incoming connections in Clearing state. This can result
362 * in incorect state transitions - e.g., the connection goes back to
363 * Established and then the Clearing_Completed event is generated. Also,
364 * block incoming connection in Deleted state.
365 */
366 if (peer1->status == Clearing || peer1->status == Deleted) {
367 if (bgp_debug_neighbor_events(peer1))
368 zlog_debug(
369 "[Event] Closing incoming conn for %s (%p) state %d",
370 peer1->host, peer1, peer1->status);
371 close(bgp_sock);
372 return -1;
373 }
374
375 /* Check that at least one AF is activated for the peer. */
376 if (!peer_active(peer1)) {
377 if (bgp_debug_neighbor_events(peer1))
378 zlog_debug(
379 "%s - incoming conn rejected - no AF activated for peer",
380 peer1->host);
381 close(bgp_sock);
382 return -1;
383 }
384
385 if (bgp_debug_neighbor_events(peer1))
386 zlog_debug("[Event] BGP connection from host %s fd %d",
387 inet_sutop(&su, buf), bgp_sock);
388
389 if (peer1->doppelganger) {
390 /* We have an existing connection. Kill the existing one and run
391 with this one.
392 */
393 if (bgp_debug_neighbor_events(peer1))
394 zlog_debug(
395 "[Event] New active connection from peer %s, Killing"
396 " previous active connection",
397 peer1->host);
398 peer_delete(peer1->doppelganger);
399 }
400
401 if (bgp_set_socket_ttl(peer1, bgp_sock) < 0)
402 if (bgp_debug_neighbor_events(peer1))
403 zlog_debug(
404 "[Event] Unable to set min/max TTL on peer %s, Continuing",
405 peer1->host);
406
407 peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as,
408 peer1->as, peer1->as_type, 0, 0, NULL);
409 peer->su = su;
410 hash_release(peer->bgp->peerhash, peer);
411 hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
412
413 peer_xfer_config(peer, peer1);
414 UNSET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
415
416 peer->doppelganger = peer1;
417 peer1->doppelganger = peer;
418 peer->fd = bgp_sock;
419 vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer));
420 bgp_fsm_change_status(peer, Active);
421 BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */
422
423 SET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
424
425 /* Make dummy peer until read Open packet. */
426 if (peer1->status == Established
427 && CHECK_FLAG(peer1->sflags, PEER_STATUS_NSF_MODE)) {
428 /* If we have an existing established connection with graceful
429 * restart
430 * capability announced with one or more address families, then
431 * drop
432 * existing established connection and move state to connect.
433 */
434 peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
435 SET_FLAG(peer1->sflags, PEER_STATUS_NSF_WAIT);
436 bgp_event_update(peer1, TCP_connection_closed);
437 }
438
439 if (peer_active(peer)) {
440 BGP_EVENT_ADD(peer, TCP_connection_open);
441 }
442
443 return 0;
444 }
445
446 /* BGP socket bind. */
447 static char *bgp_get_bound_name(struct peer *peer)
448 {
449 char *name = NULL;
450
451 if (!peer)
452 return NULL;
453
454 if ((peer->bgp->vrf_id == VRF_DEFAULT) && !peer->ifname
455 && !peer->conf_if)
456 return NULL;
457
458 if (peer->su.sa.sa_family != AF_INET
459 && peer->su.sa.sa_family != AF_INET6)
460 return NULL; // unexpected
461
462 /* For IPv6 peering, interface (unnumbered or link-local with interface)
463 * takes precedence over VRF. For IPv4 peering, explicit interface or
464 * VRF are the situations to bind.
465 */
466 if (peer->su.sa.sa_family == AF_INET6)
467 name = (peer->conf_if ? peer->conf_if
468 : (peer->ifname ? peer->ifname
469 : peer->bgp->name));
470 else
471 name = peer->ifname ? peer->ifname : peer->bgp->name;
472
473 return name;
474 }
475
476 static int bgp_update_address(struct interface *ifp, const union sockunion *dst,
477 union sockunion *addr)
478 {
479 struct prefix *p, *sel, d;
480 struct connected *connected;
481 struct listnode *node;
482 int common;
483
484 sockunion2hostprefix(dst, &d);
485 sel = NULL;
486 common = -1;
487
488 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
489 p = connected->address;
490 if (p->family != d.family)
491 continue;
492 if (prefix_common_bits(p, &d) > common) {
493 sel = p;
494 common = prefix_common_bits(sel, &d);
495 }
496 }
497
498 if (!sel)
499 return 1;
500
501 prefix2sockunion(sel, addr);
502 return 0;
503 }
504
505 /* Update source selection. */
506 static int bgp_update_source(struct peer *peer)
507 {
508 struct interface *ifp;
509 union sockunion addr;
510 int ret = 0;
511
512 sockunion_init(&addr);
513
514 /* Source is specified with interface name. */
515 if (peer->update_if) {
516 ifp = if_lookup_by_name(peer->update_if, peer->bgp->vrf_id);
517 if (!ifp)
518 return -1;
519
520 if (bgp_update_address(ifp, &peer->su, &addr))
521 return -1;
522
523 ret = sockunion_bind(peer->fd, &addr, 0, &addr);
524 }
525
526 /* Source is specified with IP address. */
527 if (peer->update_source)
528 ret = sockunion_bind(peer->fd, peer->update_source, 0,
529 peer->update_source);
530
531 return ret;
532 }
533
534 #define DATAPLANE_MARK 254 /* main table ID */
535
536 /* BGP try to connect to the peer. */
537 int bgp_connect(struct peer *peer)
538 {
539 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
540 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
541 ifindex_t ifindex = 0;
542
543 if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) {
544 zlog_debug("Peer address not learnt: Returning from connect");
545 return 0;
546 }
547 if (bgpd_privs.change(ZPRIVS_RAISE))
548 zlog_ferr(LIB_ERR_PRIVILEGES, "Can't raise privileges");
549 /* Make socket for the peer. */
550 peer->fd = vrf_sockunion_socket(&peer->su, peer->bgp->vrf_id,
551 bgp_get_bound_name(peer));
552 if (bgpd_privs.change(ZPRIVS_LOWER))
553 zlog_ferr(LIB_ERR_PRIVILEGES, "Can't lower privileges");
554 if (peer->fd < 0)
555 return -1;
556
557 set_nonblocking(peer->fd);
558
559 /* Set socket send buffer size */
560 setsockopt_so_sendbuf(peer->fd, BGP_SOCKET_SNDBUF_SIZE);
561
562 if (bgp_set_socket_ttl(peer, peer->fd) < 0)
563 return -1;
564
565 sockopt_reuseaddr(peer->fd);
566 sockopt_reuseport(peer->fd);
567 if (sockopt_mark_default(peer->fd, DATAPLANE_MARK, &bgpd_privs) < 0)
568 zlog_warn("Unable to set mark on FD for peer %s, err=%s",
569 peer->host, safe_strerror(errno));
570
571 #ifdef IPTOS_PREC_INTERNETCONTROL
572 if (bgpd_privs.change(ZPRIVS_RAISE))
573 zlog_err("%s: could not raise privs", __func__);
574 if (sockunion_family(&peer->su) == AF_INET)
575 setsockopt_ipv4_tos(peer->fd, IPTOS_PREC_INTERNETCONTROL);
576 else if (sockunion_family(&peer->su) == AF_INET6)
577 setsockopt_ipv6_tclass(peer->fd, IPTOS_PREC_INTERNETCONTROL);
578 if (bgpd_privs.change(ZPRIVS_LOWER))
579 zlog_err("%s: could not lower privs", __func__);
580 #endif
581
582 if (peer->password)
583 bgp_md5_set_connect(peer->fd, &peer->su, peer->password);
584
585 /* Update source bind. */
586 if (bgp_update_source(peer) < 0) {
587 return connect_error;
588 }
589
590 if (peer->conf_if || peer->ifname)
591 ifindex = ifname2ifindex(peer->conf_if ? peer->conf_if
592 : peer->ifname,
593 peer->bgp->vrf_id);
594
595 if (bgp_debug_neighbor_events(peer))
596 zlog_debug("%s [Event] Connect start to %s fd %d", peer->host,
597 peer->host, peer->fd);
598
599 /* Connect to the remote peer. */
600 return sockunion_connect(peer->fd, &peer->su, htons(peer->port),
601 ifindex);
602 }
603
604 /* After TCP connection is established. Get local address and port. */
605 int bgp_getsockname(struct peer *peer)
606 {
607 if (peer->su_local) {
608 sockunion_free(peer->su_local);
609 peer->su_local = NULL;
610 }
611
612 if (peer->su_remote) {
613 sockunion_free(peer->su_remote);
614 peer->su_remote = NULL;
615 }
616
617 peer->su_local = sockunion_getsockname(peer->fd);
618 if (!peer->su_local)
619 return -1;
620 peer->su_remote = sockunion_getpeername(peer->fd);
621 if (!peer->su_remote)
622 return -1;
623
624 if (bgp_nexthop_set(peer->su_local, peer->su_remote, &peer->nexthop,
625 peer)) {
626 #if defined(HAVE_CUMULUS)
627 zlog_err(
628 "%s: nexthop_set failed, resetting connection - intf %p",
629 peer->host, peer->nexthop.ifp);
630 return -1;
631 #endif
632 }
633 return 0;
634 }
635
636
637 static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
638 struct bgp *bgp)
639 {
640 struct bgp_listener *listener;
641 int ret, en;
642
643 sockopt_reuseaddr(sock);
644 sockopt_reuseport(sock);
645
646 if (bgpd_privs.change(ZPRIVS_RAISE))
647 zlog_err("%s: could not raise privs", __func__);
648
649 #ifdef IPTOS_PREC_INTERNETCONTROL
650 if (sa->sa_family == AF_INET)
651 setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL);
652 else if (sa->sa_family == AF_INET6)
653 setsockopt_ipv6_tclass(sock, IPTOS_PREC_INTERNETCONTROL);
654 #endif
655
656 sockopt_v6only(sa->sa_family, sock);
657
658 ret = bind(sock, sa, salen);
659 en = errno;
660 if (bgpd_privs.change(ZPRIVS_LOWER))
661 zlog_err("%s: could not lower privs", __func__);
662
663 if (ret < 0) {
664 zlog_err("bind: %s", safe_strerror(en));
665 return ret;
666 }
667
668 ret = listen(sock, SOMAXCONN);
669 if (ret < 0) {
670 zlog_err("listen: %s", safe_strerror(errno));
671 return ret;
672 }
673
674 listener = XCALLOC(MTYPE_BGP_LISTENER, sizeof(*listener));
675 listener->fd = sock;
676
677 /* this socket needs a change of ns. record bgp back pointer */
678 if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(bgp->vrf_id))
679 listener->bgp = bgp;
680
681 memcpy(&listener->su, sa, salen);
682 listener->thread = NULL;
683 thread_add_read(bm->master, bgp_accept, listener, sock,
684 &listener->thread);
685 listnode_add(bm->listen_sockets, listener);
686
687 return 0;
688 }
689
690 /* IPv6 supported version of BGP server socket setup. */
691 int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
692 {
693 struct addrinfo *ainfo;
694 struct addrinfo *ainfo_save;
695 static const struct addrinfo req = {
696 .ai_family = AF_UNSPEC,
697 .ai_flags = AI_PASSIVE,
698 .ai_socktype = SOCK_STREAM,
699 };
700 int ret, count;
701 char port_str[BUFSIZ];
702
703 snprintf(port_str, sizeof(port_str), "%d", port);
704 port_str[sizeof(port_str) - 1] = '\0';
705
706 if (bgpd_privs.change(ZPRIVS_RAISE))
707 zlog_ferr(LIB_ERR_PRIVILEGES, "Can't raise privileges");
708 ret = vrf_getaddrinfo(address, port_str, &req, &ainfo_save,
709 bgp->vrf_id);
710 if (bgpd_privs.change(ZPRIVS_LOWER))
711 zlog_ferr(LIB_ERR_PRIVILEGES, "Can't lower privileges");
712 if (ret != 0) {
713 zlog_err("getaddrinfo: %s", gai_strerror(ret));
714 return -1;
715 }
716
717 count = 0;
718 for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next) {
719 int sock;
720
721 if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
722 continue;
723
724 if (bgpd_privs.change(ZPRIVS_RAISE))
725 zlog_ferr(LIB_ERR_PRIVILEGES, "Can't raise privileges");
726 sock = vrf_socket(ainfo->ai_family, ainfo->ai_socktype,
727 ainfo->ai_protocol, bgp->vrf_id,
728 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ?
729 bgp->name : NULL));
730 if (bgpd_privs.change(ZPRIVS_LOWER))
731 zlog_ferr(LIB_ERR_PRIVILEGES, "Can't lower privileges");
732 if (sock < 0) {
733 zlog_err("socket: %s", safe_strerror(errno));
734 continue;
735 }
736
737 /* if we intend to implement ttl-security, this socket needs
738 * ttl=255 */
739 sockopt_ttl(ainfo->ai_family, sock, MAXTTL);
740
741 ret = bgp_listener(sock, ainfo->ai_addr, ainfo->ai_addrlen,
742 bgp);
743 if (ret == 0)
744 ++count;
745 else
746 close(sock);
747 }
748 freeaddrinfo(ainfo_save);
749 if (count == 0 && bgp->inst_type != BGP_INSTANCE_TYPE_VRF) {
750 zlog_err(
751 "%s: no usable addresses please check other programs usage of specified port %d",
752 __func__, port);
753 zlog_err("%s: Program cannot continue", __func__);
754 exit(-1);
755 }
756
757 return 0;
758 }
759
760 /* this function closes vrf socket
761 * this should be called only for vrf socket with netns backend
762 */
763 void bgp_close_vrf_socket(struct bgp *bgp)
764 {
765 struct listnode *node, *next;
766 struct bgp_listener *listener;
767
768 if (!bgp)
769 return;
770
771 if (bm->listen_sockets == NULL)
772 return;
773
774 for (ALL_LIST_ELEMENTS(bm->listen_sockets, node, next, listener)) {
775 if (listener->bgp == bgp) {
776 thread_cancel(listener->thread);
777 close(listener->fd);
778 listnode_delete(bm->listen_sockets, listener);
779 XFREE(MTYPE_BGP_LISTENER, listener);
780 }
781 }
782 }
783
784 /* this function closes main socket
785 */
786 void bgp_close(void)
787 {
788 struct listnode *node, *next;
789 struct bgp_listener *listener;
790
791 if (bm->listen_sockets == NULL)
792 return;
793
794 for (ALL_LIST_ELEMENTS(bm->listen_sockets, node, next, listener)) {
795 if (listener->bgp)
796 continue;
797 thread_cancel(listener->thread);
798 close(listener->fd);
799 listnode_delete(bm->listen_sockets, listener);
800 XFREE(MTYPE_BGP_LISTENER, listener);
801 }
802 }