]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_network.c
Merge pull request #3811 from AkhileshSamineni/show_bgp_ipv6_summary_fix
[mirror_frr.git] / bgpd / bgp_network.c
CommitLineData
718e3744 1/* BGP network related fucntions
896014f4
DL
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 */
718e3744 20
21#include <zebra.h>
22
23#include "thread.h"
24#include "sockunion.h"
0df7c91f 25#include "sockopt.h"
718e3744 26#include "memory.h"
27#include "log.h"
28#include "if.h"
29#include "prefix.h"
30#include "command.h"
edd7c245 31#include "privs.h"
0df7c91f 32#include "linklist.h"
fdbc8e77 33#include "network.h"
3f9c7369 34#include "queue.h"
66e373ae 35#include "hash.h"
039f3a34 36#include "filter.h"
61cf4b37 37#include "ns.h"
174482ef 38#include "lib_errors.h"
d75681db 39#include "nexthop.h"
718e3744 40
41#include "bgpd/bgpd.h"
1ff9a340 42#include "bgpd/bgp_open.h"
718e3744 43#include "bgpd/bgp_fsm.h"
44#include "bgpd/bgp_attr.h"
45#include "bgpd/bgp_debug.h"
14454c9f 46#include "bgpd/bgp_errors.h"
718e3744 47#include "bgpd/bgp_network.h"
d75681db 48#include "bgpd/bgp_zebra.h"
edd7c245 49
50extern struct zebra_privs_t bgpd_privs;
51
97896a91 52static char *bgp_get_bound_name(struct peer *peer);
f2345335 53
d023aec4 54/* BGP listening socket. */
d62a17ae 55struct bgp_listener {
56 int fd;
57 union sockunion su;
58 struct thread *thread;
61cf4b37 59 struct bgp *bgp;
d023aec4 60};
6b0655a2 61
0df7c91f
PJ
62/*
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.
65 */
d62a17ae 66static int bgp_md5_set_socket(int socket, union sockunion *su,
67 const char *password)
0df7c91f 68{
d62a17ae 69 int ret = -1;
70 int en = ENOSYS;
ea8b7c71 71#if HAVE_DECL_TCP_MD5SIG
d62a17ae 72 union sockunion su2;
ea8b7c71 73#endif /* HAVE_TCP_MD5SIG */
d62a17ae 74
75 assert(socket >= 0);
76
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)
81 su2.sin.sin_port = 0;
82 else
83 su2.sin6.sin6_port = 0;
84 ret = sockopt_tcp_signature(socket, &su2, password);
85 en = errno;
0df7c91f 86#endif /* HAVE_TCP_MD5SIG */
0df7c91f 87
d62a17ae 88 if (ret < 0)
89 zlog_warn("can't set TCP_MD5SIG option on socket %d: %s",
90 socket, safe_strerror(en));
91
92 return ret;
0df7c91f
PJ
93}
94
95/* Helper for bgp_connect */
d62a17ae 96static int bgp_md5_set_connect(int socket, union sockunion *su,
97 const char *password)
0df7c91f 98{
d62a17ae 99 int ret = -1;
100
101#if HAVE_DECL_TCP_MD5SIG
6bb30c2c
DL
102 frr_elevate_privs(&bgpd_privs) {
103 ret = bgp_md5_set_socket(socket, su, password);
d62a17ae 104 }
0df7c91f 105#endif /* HAVE_TCP_MD5SIG */
d62a17ae 106
107 return ret;
0df7c91f
PJ
108}
109
d62a17ae 110static int bgp_md5_set_password(struct peer *peer, const char *password)
0df7c91f 111{
d62a17ae 112 struct listnode *node;
113 int ret = 0;
114 struct bgp_listener *listener;
115
6bb30c2c 116 frr_elevate_privs(&bgpd_privs) {
d62a17ae 117 /* Set or unset the password on the listen socket(s). Outbound
6bb30c2c 118 * connections are taken care of in bgp_connect() below.
d62a17ae 119 */
6bb30c2c
DL
120 for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener))
121 if (listener->su.sa.sa_family
122 == peer->su.sa.sa_family) {
123 ret = bgp_md5_set_socket(listener->fd,
124 &peer->su, password);
125 break;
126 }
127 }
d62a17ae 128 return ret;
0df7c91f 129}
3374bef0 130
d62a17ae 131int bgp_md5_set(struct peer *peer)
89ca90fa 132{
d62a17ae 133 /* Set the password from listen socket. */
134 return bgp_md5_set_password(peer, peer->password);
89ca90fa 135}
136
d62a17ae 137int bgp_md5_unset(struct peer *peer)
89ca90fa 138{
d62a17ae 139 /* Unset the password from listen socket. */
140 return bgp_md5_set_password(peer, NULL);
89ca90fa 141}
142
d62a17ae 143int bgp_set_socket_ttl(struct peer *peer, int bgp_sock)
ef0b0c3e 144{
d62a17ae 145 char buf[INET_ADDRSTRLEN];
146 int ret = 0;
147
148 /* In case of peer is EBGP, we should set TTL for this connection. */
149 if (!peer->gtsm_hops && (peer_sort(peer) == BGP_PEER_EBGP)) {
150 ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, peer->ttl);
151 if (ret) {
af4c2728 152 flog_err(
02705213 153 LIB_ERR_SOCKET,
d62a17ae 154 "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
14454c9f
DS
155 __func__,
156 inet_ntop(AF_INET, &peer->remote_id, buf,
157 sizeof(buf)),
d62a17ae 158 errno);
159 return ret;
160 }
161 } else if (peer->gtsm_hops) {
162 /* On Linux, setting minttl without setting ttl seems to mess
163 with the
164 outgoing ttl. Therefore setting both.
165 */
166 ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, MAXTTL);
167 if (ret) {
af4c2728 168 flog_err(
02705213 169 LIB_ERR_SOCKET,
d62a17ae 170 "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
14454c9f
DS
171 __func__,
172 inet_ntop(AF_INET, &peer->remote_id, buf,
173 sizeof(buf)),
d62a17ae 174 errno);
175 return ret;
176 }
177 ret = sockopt_minttl(peer->su.sa.sa_family, bgp_sock,
178 MAXTTL + 1 - peer->gtsm_hops);
179 if (ret) {
af4c2728 180 flog_err(
02705213 181 LIB_ERR_SOCKET,
d62a17ae 182 "%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d",
14454c9f
DS
183 __func__,
184 inet_ntop(AF_INET, &peer->remote_id, buf,
185 sizeof(buf)),
d62a17ae 186 errno);
187 return ret;
188 }
189 }
190
191 return ret;
ef0b0c3e
DL
192}
193
8dee0396 194/*
195 * Obtain the BGP instance that the incoming connection should be processed
196 * against. This is important because more than one VRF could be using the
197 * same IP address space. The instance is got by obtaining the device to
198 * which the incoming connection is bound to. This could either be a VRF
199 * or it could be an interface, which in turn determines the VRF.
200 */
d62a17ae 201static int bgp_get_instance_for_inc_conn(int sock, struct bgp **bgp_inst)
8dee0396 202{
120c6587 203#ifndef SO_BINDTODEVICE
d62a17ae 204 /* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here
205 * anyway since the assumption is that the interface name returned by
206 * getsockopt() is useful in identifying the VRF, particularly with
207 * Linux's
208 * VRF l3master device. The whole mechanism is specific to Linux, so...
209 * when other platforms add VRF support, this will need handling here as
210 * well. (or, some restructuring) */
211 *bgp_inst = bgp_get_default();
212 return !*bgp_inst;
120c6587
DL
213
214#else
d62a17ae 215 char name[VRF_NAMSIZ + 1];
216 socklen_t name_len = VRF_NAMSIZ;
217 struct bgp *bgp;
218 int rc;
219 struct listnode *node, *nnode;
220
221 *bgp_inst = NULL;
222 name[0] = '\0';
223 rc = getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, name, &name_len);
224 if (rc != 0) {
225#if defined(HAVE_CUMULUS)
af4c2728 226 flog_err(
02705213 227 LIB_ERR_SOCKET,
14454c9f
DS
228 "[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d",
229 safe_strerror(errno), sock);
d62a17ae 230 return -1;
b5826a12 231#endif
d62a17ae 232 }
233
234 if (!strlen(name)) {
235 *bgp_inst = bgp_get_default();
236 return 0; /* default instance. */
237 }
238
239 /* First try match to instance; if that fails, check for interfaces. */
240 bgp = bgp_lookup_by_name(name);
241 if (bgp) {
242 if (!bgp->vrf_id) // unexpected
243 return -1;
244 *bgp_inst = bgp;
245 return 0;
246 }
247
248 /* TODO - This will be optimized once interfaces move into the NS */
249 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
250 struct interface *ifp;
251
252 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
253 continue;
254
255 ifp = if_lookup_by_name(name, bgp->vrf_id);
256 if (ifp) {
257 *bgp_inst = bgp;
258 return 0;
259 }
260 }
261
262 /* We didn't match to either an instance or an interface. */
263 return -1;
120c6587 264#endif
8dee0396 265}
266
718e3744 267/* Accept bgp connection. */
d62a17ae 268static int bgp_accept(struct thread *thread)
718e3744 269{
d62a17ae 270 int bgp_sock;
271 int accept_sock;
272 union sockunion su;
273 struct bgp_listener *listener = THREAD_ARG(thread);
274 struct peer *peer;
275 struct peer *peer1;
276 char buf[SU_ADDRSTRLEN];
277 struct bgp *bgp = NULL;
278
279 sockunion_init(&su);
280
281 /* Register accept thread. */
282 accept_sock = THREAD_FD(thread);
283 if (accept_sock < 0) {
09c866e3
QY
284 flog_err_sys(LIB_ERR_SOCKET, "accept_sock is nevative value %d",
285 accept_sock);
d62a17ae 286 return -1;
287 }
288 listener->thread = NULL;
61cf4b37 289
d62a17ae 290 thread_add_read(bm->master, bgp_accept, listener, accept_sock,
291 &listener->thread);
292
293 /* Accept client connection. */
294 bgp_sock = sockunion_accept(accept_sock, &su);
295 if (bgp_sock < 0) {
09c866e3
QY
296 flog_err_sys(LIB_ERR_SOCKET,
297 "[Error] BGP socket accept failed (%s)",
298 safe_strerror(errno));
d62a17ae 299 return -1;
300 }
301 set_nonblocking(bgp_sock);
302
61cf4b37
PG
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)) {
d62a17ae 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;
97896a91 419 vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer));
d62a17ae 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;
718e3744 444}
445
446/* BGP socket bind. */
97896a91 447static char *bgp_get_bound_name(struct peer *peer)
718e3744 448{
d62a17ae 449 char *name = NULL;
450
a2bce1c8
DS
451 if (!peer)
452 return NULL;
453
996c9314
LB
454 if ((peer->bgp->vrf_id == VRF_DEFAULT) && !peer->ifname
455 && !peer->conf_if)
97896a91
PG
456 return NULL;
457
d62a17ae 458 if (peer->su.sa.sa_family != AF_INET
459 && peer->su.sa.sa_family != AF_INET6)
97896a91 460 return NULL; // unexpected
d62a17ae 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
97896a91 473 return name;
718e3744 474}
475
d62a17ae 476static int bgp_update_address(struct interface *ifp, const union sockunion *dst,
477 union sockunion *addr)
718e3744 478{
d62a17ae 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;
718e3744 503}
504
505/* Update source selection. */
d62a17ae 506static int bgp_update_source(struct peer *peer)
718e3744 507{
d62a17ae 508 struct interface *ifp;
509 union sockunion addr;
510 int ret = 0;
718e3744 511
d62a17ae 512 sockunion_init(&addr);
dd793e4a 513
d62a17ae 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;
718e3744 519
d62a17ae 520 if (bgp_update_address(ifp, &peer->su, &addr))
521 return -1;
718e3744 522
d62a17ae 523 ret = sockunion_bind(peer->fd, &addr, 0, &addr);
524 }
718e3744 525
d62a17ae 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);
49067496 530
d62a17ae 531 return ret;
718e3744 532}
533
ed40466a
DS
534#define DATAPLANE_MARK 254 /* main table ID */
535
718e3744 536/* BGP try to connect to the peer. */
d62a17ae 537int bgp_connect(struct peer *peer)
718e3744 538{
b750b0ba
QY
539 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
540 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
d62a17ae 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 }
01b9e3fd 547 frr_elevate_privs(&bgpd_privs) {
d62a17ae 548 /* Make socket for the peer. */
01b9e3fd
DL
549 peer->fd = vrf_sockunion_socket(&peer->su, peer->bgp->vrf_id,
550 bgp_get_bound_name(peer));
551 }
d62a17ae 552 if (peer->fd < 0)
553 return -1;
554
555 set_nonblocking(peer->fd);
556
557 /* Set socket send buffer size */
558 setsockopt_so_sendbuf(peer->fd, BGP_SOCKET_SNDBUF_SIZE);
559
560 if (bgp_set_socket_ttl(peer, peer->fd) < 0)
561 return -1;
562
563 sockopt_reuseaddr(peer->fd);
564 sockopt_reuseport(peer->fd);
565 if (sockopt_mark_default(peer->fd, DATAPLANE_MARK, &bgpd_privs) < 0)
566 zlog_warn("Unable to set mark on FD for peer %s, err=%s",
567 peer->host, safe_strerror(errno));
568
1423c809 569#ifdef IPTOS_PREC_INTERNETCONTROL
01b9e3fd
DL
570 frr_elevate_privs(&bgpd_privs) {
571 if (sockunion_family(&peer->su) == AF_INET)
633fc9b1
DL
572 setsockopt_ipv4_tos(peer->fd,
573 IPTOS_PREC_INTERNETCONTROL);
01b9e3fd 574 else if (sockunion_family(&peer->su) == AF_INET6)
633fc9b1
DL
575 setsockopt_ipv6_tclass(peer->fd,
576 IPTOS_PREC_INTERNETCONTROL);
01b9e3fd 577 }
1423c809
SH
578#endif
579
d62a17ae 580 if (peer->password)
581 bgp_md5_set_connect(peer->fd, &peer->su, peer->password);
718e3744 582
d62a17ae 583 /* Update source bind. */
584 if (bgp_update_source(peer) < 0) {
585 return connect_error;
586 }
718e3744 587
d62a17ae 588 if (peer->conf_if || peer->ifname)
589 ifindex = ifname2ifindex(peer->conf_if ? peer->conf_if
590 : peer->ifname,
591 peer->bgp->vrf_id);
718e3744 592
d62a17ae 593 if (bgp_debug_neighbor_events(peer))
594 zlog_debug("%s [Event] Connect start to %s fd %d", peer->host,
595 peer->host, peer->fd);
718e3744 596
d62a17ae 597 /* Connect to the remote peer. */
598 return sockunion_connect(peer->fd, &peer->su, htons(peer->port),
599 ifindex);
718e3744 600}
601
602/* After TCP connection is established. Get local address and port. */
d62a17ae 603int bgp_getsockname(struct peer *peer)
718e3744 604{
d62a17ae 605 if (peer->su_local) {
606 sockunion_free(peer->su_local);
607 peer->su_local = NULL;
608 }
609
610 if (peer->su_remote) {
611 sockunion_free(peer->su_remote);
612 peer->su_remote = NULL;
613 }
614
615 peer->su_local = sockunion_getsockname(peer->fd);
616 if (!peer->su_local)
617 return -1;
618 peer->su_remote = sockunion_getpeername(peer->fd);
619 if (!peer->su_remote)
620 return -1;
621
d75681db
DS
622 if (!bgp_zebra_nexthop_set(peer->su_local, peer->su_remote,
623 &peer->nexthop, peer)) {
624 flog_err(BGP_ERR_NH_UPD,
625 "%s: nexthop_set failed, resetting connection - intf %p",
626 peer->host, peer->nexthop.ifp);
d62a17ae 627 return -1;
d62a17ae 628 }
d62a17ae 629 return 0;
718e3744 630}
631
d023aec4 632
61cf4b37
PG
633static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
634 struct bgp *bgp)
d023aec4 635{
d62a17ae 636 struct bgp_listener *listener;
637 int ret, en;
d023aec4 638
d62a17ae 639 sockopt_reuseaddr(sock);
640 sockopt_reuseport(sock);
d023aec4 641
01b9e3fd 642 frr_elevate_privs(&bgpd_privs) {
5c88f19d 643
d023aec4 644#ifdef IPTOS_PREC_INTERNETCONTROL
01b9e3fd
DL
645 if (sa->sa_family == AF_INET)
646 setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL);
647 else if (sa->sa_family == AF_INET6)
633fc9b1
DL
648 setsockopt_ipv6_tclass(sock,
649 IPTOS_PREC_INTERNETCONTROL);
d023aec4
SH
650#endif
651
01b9e3fd 652 sockopt_v6only(sa->sa_family, sock);
d62a17ae 653
01b9e3fd
DL
654 ret = bind(sock, sa, salen);
655 en = errno;
656 }
d62a17ae 657
658 if (ret < 0) {
09c866e3 659 flog_err_sys(LIB_ERR_SOCKET, "bind: %s", safe_strerror(en));
d62a17ae 660 return ret;
661 }
662
48522088 663 ret = listen(sock, SOMAXCONN);
d62a17ae 664 if (ret < 0) {
09c866e3
QY
665 flog_err_sys(LIB_ERR_SOCKET, "listen: %s",
666 safe_strerror(errno));
d62a17ae 667 return ret;
668 }
669
61cf4b37 670 listener = XCALLOC(MTYPE_BGP_LISTENER, sizeof(*listener));
d62a17ae 671 listener->fd = sock;
61cf4b37
PG
672
673 /* this socket needs a change of ns. record bgp back pointer */
3d4c0b49
PG
674 if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(
675 vrf_lookup_by_id(bgp->vrf_id)))
61cf4b37
PG
676 listener->bgp = bgp;
677
d62a17ae 678 memcpy(&listener->su, sa, salen);
679 listener->thread = NULL;
680 thread_add_read(bm->master, bgp_accept, listener, sock,
681 &listener->thread);
682 listnode_add(bm->listen_sockets, listener);
683
684 return 0;
d023aec4
SH
685}
686
718e3744 687/* IPv6 supported version of BGP server socket setup. */
61cf4b37 688int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
718e3744 689{
d62a17ae 690 struct addrinfo *ainfo;
691 struct addrinfo *ainfo_save;
692 static const struct addrinfo req = {
693 .ai_family = AF_UNSPEC,
694 .ai_flags = AI_PASSIVE,
695 .ai_socktype = SOCK_STREAM,
696 };
697 int ret, count;
698 char port_str[BUFSIZ];
699
700 snprintf(port_str, sizeof(port_str), "%d", port);
701 port_str[sizeof(port_str) - 1] = '\0';
702
01b9e3fd
DL
703 frr_elevate_privs(&bgpd_privs) {
704 ret = vrf_getaddrinfo(address, port_str, &req, &ainfo_save,
705 bgp->vrf_id);
706 }
d62a17ae 707 if (ret != 0) {
09c866e3
QY
708 flog_err_sys(LIB_ERR_SOCKET, "getaddrinfo: %s",
709 gai_strerror(ret));
d62a17ae 710 return -1;
711 }
712
713 count = 0;
714 for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next) {
715 int sock;
716
717 if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
718 continue;
719
01b9e3fd
DL
720 frr_elevate_privs(&bgpd_privs) {
721 sock = vrf_socket(ainfo->ai_family,
722 ainfo->ai_socktype,
723 ainfo->ai_protocol, bgp->vrf_id,
633fc9b1
DL
724 (bgp->inst_type
725 == BGP_INSTANCE_TYPE_VRF
726 ? bgp->name : NULL));
01b9e3fd 727 }
d62a17ae 728 if (sock < 0) {
09c866e3
QY
729 flog_err_sys(LIB_ERR_SOCKET, "socket: %s",
730 safe_strerror(errno));
d62a17ae 731 continue;
732 }
733
734 /* if we intend to implement ttl-security, this socket needs
735 * ttl=255 */
736 sockopt_ttl(ainfo->ai_family, sock, MAXTTL);
737
996c9314
LB
738 ret = bgp_listener(sock, ainfo->ai_addr, ainfo->ai_addrlen,
739 bgp);
d62a17ae 740 if (ret == 0)
741 ++count;
742 else
743 close(sock);
744 }
745 freeaddrinfo(ainfo_save);
06969768 746 if (count == 0 && bgp->inst_type != BGP_INSTANCE_TYPE_VRF) {
af4c2728 747 flog_err(
02705213 748 LIB_ERR_SOCKET,
996c9314
LB
749 "%s: no usable addresses please check other programs usage of specified port %d",
750 __func__, port);
09c866e3
QY
751 flog_err_sys(LIB_ERR_SOCKET, "%s: Program cannot continue",
752 __func__);
b3b78f6e 753 exit(-1);
d62a17ae 754 }
755
756 return 0;
718e3744 757}
d023aec4 758
e5619c28
PG
759/* this function closes vrf socket
760 * this should be called only for vrf socket with netns backend
761 */
762void bgp_close_vrf_socket(struct bgp *bgp)
763{
764 struct listnode *node, *next;
765 struct bgp_listener *listener;
766
767 if (!bgp)
768 return;
769
770 if (bm->listen_sockets == NULL)
771 return;
772
773 for (ALL_LIST_ELEMENTS(bm->listen_sockets, node, next, listener)) {
774 if (listener->bgp == bgp) {
775 thread_cancel(listener->thread);
776 close(listener->fd);
777 listnode_delete(bm->listen_sockets, listener);
778 XFREE(MTYPE_BGP_LISTENER, listener);
779 }
780 }
781}
782
783/* this function closes main socket
784 */
d62a17ae 785void bgp_close(void)
d023aec4 786{
d62a17ae 787 struct listnode *node, *next;
788 struct bgp_listener *listener;
789
790 if (bm->listen_sockets == NULL)
791 return;
792
793 for (ALL_LIST_ELEMENTS(bm->listen_sockets, node, next, listener)) {
e5619c28
PG
794 if (listener->bgp)
795 continue;
d62a17ae 796 thread_cancel(listener->thread);
797 close(listener->fd);
798 listnode_delete(bm->listen_sockets, listener);
799 XFREE(MTYPE_BGP_LISTENER, listener);
800 }
d023aec4 801}