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