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