]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_network.c
isisd: warn if there is an MTU issue on circuits
[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{
40ee54a7 505 struct prefix *p, *sel, d;
718e3744 506 struct connected *connected;
52dc7ee6 507 struct listnode *node;
1727d2e2
DL
508 int common;
509
40ee54a7 510 sockunion2hostprefix (dst, &d);
1727d2e2
DL
511 sel = NULL;
512 common = -1;
718e3744 513
1eb8ef25 514 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
718e3744 515 {
1727d2e2 516 p = connected->address;
40ee54a7 517 if (p->family != d.family)
1727d2e2 518 continue;
40ee54a7 519 if (prefix_common_bits (p, &d) > common)
1727d2e2
DL
520 {
521 sel = p;
40ee54a7 522 common = prefix_common_bits (sel, &d);
1727d2e2 523 }
718e3744 524 }
1727d2e2 525
1727d2e2
DL
526 if (!sel)
527 return 1;
528
529 prefix2sockunion (sel, addr);
530 return 0;
718e3744 531}
532
533/* Update source selection. */
49067496 534static int
718e3744 535bgp_update_source (struct peer *peer)
536{
537 struct interface *ifp;
1727d2e2 538 union sockunion addr;
49067496 539 int ret = 0;
718e3744 540
dd793e4a
DW
541 sockunion_init (&addr);
542
718e3744 543 /* Source is specified with interface name. */
544 if (peer->update_if)
545 {
8dee0396 546 ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id);
718e3744 547 if (! ifp)
49067496 548 return -1;
718e3744 549
1727d2e2 550 if (bgp_update_address (ifp, &peer->su, &addr))
49067496 551 return -1;
718e3744 552
49067496 553 ret = sockunion_bind (peer->fd, &addr, 0, &addr);
718e3744 554 }
555
556 /* Source is specified with IP address. */
557 if (peer->update_source)
49067496
DS
558 ret = sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source);
559
560 return ret;
718e3744 561}
562
ed40466a
DS
563#define DATAPLANE_MARK 254 /* main table ID */
564
718e3744 565/* BGP try to connect to the peer. */
566int
567bgp_connect (struct peer *peer)
568{
569 unsigned int ifindex = 0;
570
a80beece
DS
571 if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer))
572 {
573 zlog_debug("Peer address not learnt: Returning from connect");
574 return 0;
575 }
718e3744 576 /* Make socket for the peer. */
eb821189 577 peer->fd = sockunion_socket (&peer->su);
578 if (peer->fd < 0)
718e3744 579 return -1;
580
48fc05fb
VK
581 set_nonblocking (peer->fd);
582
3374bef0
VK
583 /* Set socket send buffer size */
584 bgp_update_sock_send_buffer_size(peer->fd);
585
e5cc509c
DS
586 if (bgp_set_socket_ttl (peer, peer->fd) < 0)
587 return -1;
718e3744 588
eb821189 589 sockopt_reuseaddr (peer->fd);
590 sockopt_reuseport (peer->fd);
ed40466a
DS
591 if (sockopt_mark_default(peer->fd, DATAPLANE_MARK, &bgpd_privs) < 0)
592 zlog_warn("Unable to set mark on FD for peer %s, err=%s", peer->host,
593 safe_strerror(errno));
0df7c91f 594
1423c809 595#ifdef IPTOS_PREC_INTERNETCONTROL
5c88f19d
CL
596 if (bgpd_privs.change (ZPRIVS_RAISE))
597 zlog_err ("%s: could not raise privs", __func__);
1423c809
SH
598 if (sockunion_family (&peer->su) == AF_INET)
599 setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
6d0732c8
SH
600# ifdef HAVE_IPV6
601 else if (sockunion_family (&peer->su) == AF_INET6)
602 setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
603# endif
5c88f19d
CL
604 if (bgpd_privs.change (ZPRIVS_LOWER))
605 zlog_err ("%s: could not lower privs", __func__);
1423c809
SH
606#endif
607
0df7c91f
PJ
608 if (peer->password)
609 bgp_md5_set_connect (peer->fd, &peer->su, peer->password);
718e3744 610
611 /* Bind socket. */
612 bgp_bind (peer);
613
614 /* Update source bind. */
49067496
DS
615 if (bgp_update_source (peer) < 0)
616 {
617 return connect_error;
618 }
718e3744 619
620#ifdef HAVE_IPV6
a80beece 621 if (peer->conf_if || peer->ifname)
322e5964 622 ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname);
718e3744 623#endif /* HAVE_IPV6 */
624
16286195
DS
625 if (bgp_debug_neighbor_events(peer))
626 zlog_debug ("%s [Event] Connect start to %s fd %d",
627 peer->host, peer->host, peer->fd);
718e3744 628
629 /* Connect to the remote peer. */
eb821189 630 return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
718e3744 631}
632
633/* After TCP connection is established. Get local address and port. */
1ff9a340 634int
718e3744 635bgp_getsockname (struct peer *peer)
636{
637 if (peer->su_local)
638 {
22db9dec 639 sockunion_free (peer->su_local);
718e3744 640 peer->su_local = NULL;
641 }
642
643 if (peer->su_remote)
644 {
22db9dec 645 sockunion_free (peer->su_remote);
718e3744 646 peer->su_remote = NULL;
647 }
648
eb821189 649 peer->su_local = sockunion_getsockname (peer->fd);
1ff9a340 650 if (!peer->su_local) return -1;
eb821189 651 peer->su_remote = sockunion_getpeername (peer->fd);
1ff9a340 652 if (!peer->su_remote) return -1;
718e3744 653
e33a4880 654 if (bgp_nexthop_set (peer->su_local, peer->su_remote,
655 &peer->nexthop, peer))
656 {
657 zlog_err ("%s: nexthop_set failed, resetting connection - intf %p",
658 peer->host, peer->nexthop.ifp);
659 return -1;
660 }
1ff9a340
DS
661
662 return 0;
718e3744 663}
664
d023aec4
SH
665
666static int
667bgp_listener (int sock, struct sockaddr *sa, socklen_t salen)
668{
669 struct bgp_listener *listener;
670 int ret, en;
671
672 sockopt_reuseaddr (sock);
673 sockopt_reuseport (sock);
674
5c88f19d
CL
675 if (bgpd_privs.change (ZPRIVS_RAISE))
676 zlog_err ("%s: could not raise privs", __func__);
677
d023aec4
SH
678#ifdef IPTOS_PREC_INTERNETCONTROL
679 if (sa->sa_family == AF_INET)
680 setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
6d0732c8
SH
681# ifdef HAVE_IPV6
682 else if (sa->sa_family == AF_INET6)
683 setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL);
684# endif
d023aec4
SH
685#endif
686
ca051269 687 sockopt_v6only (sa->sa_family, sock);
d023aec4 688
d023aec4
SH
689 ret = bind (sock, sa, salen);
690 en = errno;
5c88f19d
CL
691 if (bgpd_privs.change (ZPRIVS_LOWER))
692 zlog_err ("%s: could not lower privs", __func__);
d023aec4
SH
693
694 if (ret < 0)
695 {
696 zlog_err ("bind: %s", safe_strerror (en));
697 return ret;
698 }
699
700 ret = listen (sock, 3);
701 if (ret < 0)
702 {
703 zlog_err ("listen: %s", safe_strerror (errno));
704 return ret;
705 }
706
707 listener = XMALLOC (MTYPE_BGP_LISTENER, sizeof(*listener));
708 listener->fd = sock;
709 memcpy(&listener->su, sa, salen);
9229d914 710 listener->thread = thread_add_read (bm->master, bgp_accept, listener, sock);
d023aec4
SH
711 listnode_add (bm->listen_sockets, listener);
712
713 return 0;
714}
715
718e3744 716/* IPv6 supported version of BGP server socket setup. */
1cbb5dfc 717#ifdef HAVE_IPV6
718e3744 718int
d023aec4 719bgp_socket (unsigned short port, const char *address)
718e3744 720{
718e3744 721 struct addrinfo *ainfo;
722 struct addrinfo *ainfo_save;
d023aec4
SH
723 static const struct addrinfo req = {
724 .ai_family = AF_UNSPEC,
725 .ai_flags = AI_PASSIVE,
726 .ai_socktype = SOCK_STREAM,
727 };
728 int ret, count;
718e3744 729 char port_str[BUFSIZ];
730
90b68769 731 snprintf (port_str, sizeof(port_str), "%d", port);
718e3744 732 port_str[sizeof (port_str) - 1] = '\0';
733
d023aec4 734 ret = getaddrinfo (address, port_str, &req, &ainfo_save);
718e3744 735 if (ret != 0)
736 {
737 zlog_err ("getaddrinfo: %s", gai_strerror (ret));
738 return -1;
739 }
740
d023aec4
SH
741 count = 0;
742 for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next)
718e3744 743 {
d023aec4
SH
744 int sock;
745
718e3744 746 if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
747 continue;
748
749 sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
750 if (sock < 0)
751 {
6099b3b5 752 zlog_err ("socket: %s", safe_strerror (errno));
718e3744 753 continue;
754 }
fa411a21
NH
755
756 /* if we intend to implement ttl-security, this socket needs ttl=255 */
757 sockopt_ttl (ainfo->ai_family, sock, MAXTTL);
758
d023aec4
SH
759 ret = bgp_listener (sock, ainfo->ai_addr, ainfo->ai_addrlen);
760 if (ret == 0)
761 ++count;
762 else
763 close(sock);
718e3744 764 }
718e3744 765 freeaddrinfo (ainfo_save);
d023aec4
SH
766 if (count == 0)
767 {
768 zlog_err ("%s: no usable addresses", __func__);
769 return -1;
770 }
718e3744 771
d023aec4 772 return 0;
718e3744 773}
774#else
775/* Traditional IPv4 only version. */
776int
d023aec4 777bgp_socket (unsigned short port, const char *address)
718e3744 778{
779 int sock;
780 int socklen;
781 struct sockaddr_in sin;
7a0ff1b2 782 int ret;
718e3744 783
784 sock = socket (AF_INET, SOCK_STREAM, 0);
785 if (sock < 0)
786 {
6099b3b5 787 zlog_err ("socket: %s", safe_strerror (errno));
718e3744 788 return sock;
789 }
790
fa411a21
NH
791 /* if we intend to implement ttl-security, this socket needs ttl=255 */
792 sockopt_ttl (AF_INET, sock, MAXTTL);
793
718e3744 794 memset (&sin, 0, sizeof (struct sockaddr_in));
718e3744 795 sin.sin_family = AF_INET;
796 sin.sin_port = htons (port);
797 socklen = sizeof (struct sockaddr_in);
3a02d1f7 798
90b68769 799 if (address && ((ret = inet_aton(address, &sin.sin_addr)) < 1))
3a02d1f7 800 {
90b68769
PJ
801 zlog_err("bgp_socket: could not parse ip address %s: %s",
802 address, safe_strerror (errno));
3a02d1f7
PJ
803 return ret;
804 }
6f0e3f6e 805#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
718e3744 806 sin.sin_len = socklen;
6f0e3f6e 807#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
718e3744 808
d023aec4 809 ret = bgp_listener (sock, (struct sockaddr *) &sin, socklen);
718e3744 810 if (ret < 0)
811 {
718e3744 812 close (sock);
813 return ret;
814 }
718e3744 815 return sock;
816}
1cbb5dfc 817#endif /* HAVE_IPV6 */
d023aec4
SH
818
819void
820bgp_close (void)
821{
822 struct listnode *node, *next;
823 struct bgp_listener *listener;
824
1ff9a340
DS
825 if (bm->listen_sockets == NULL)
826 return;
827
d023aec4
SH
828 for (ALL_LIST_ELEMENTS (bm->listen_sockets, node, next, listener))
829 {
830 thread_cancel (listener->thread);
831 close (listener->fd);
832 listnode_delete (bm->listen_sockets, listener);
833 XFREE (MTYPE_BGP_LISTENER, listener);
834 }
835}