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