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