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