1 /* BGP network related fucntions
2 Copyright (C) 1999 Kunihiro Ishiguro
4 This file is part of GNU Zebra.
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
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.
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
24 #include "sockunion.h"
31 #include "bgpd/bgpd.h"
32 #include "bgpd/bgp_fsm.h"
33 #include "bgpd/bgp_attr.h"
34 #include "bgpd/bgp_debug.h"
35 #include "bgpd/bgp_network.h"
37 #ifdef HAVE_TCP_SIGNATURE
38 #include "bgpd/bgp_tcpsig.h"
39 #endif /* HAVE_TCP_SIGNATURE */
42 /* Accept bgp connection. */
44 bgp_accept (struct thread
*thread
)
52 char buf
[SU_ADDRSTRLEN
];
54 /* Regiser accept thread. */
55 accept_sock
= THREAD_FD (thread
);
56 bgp
= THREAD_ARG (thread
);
60 zlog_err ("accept_sock is nevative value %d", accept_sock
);
63 thread_add_read (master
, bgp_accept
, bgp
, accept_sock
);
65 /* Accept client connection. */
66 bgp_sock
= sockunion_accept (accept_sock
, &su
);
69 zlog_err ("[Error] BGP socket accept failed (%s)", strerror (errno
));
73 if (BGP_DEBUG (events
, EVENTS
))
74 zlog_info ("[Event] BGP connection from host %s", inet_sutop (&su
, buf
));
76 /* Check remote IP address */
77 peer1
= peer_lookup (bgp
, &su
);
78 if (! peer1
|| peer1
->status
== Idle
)
80 if (BGP_DEBUG (events
, EVENTS
))
83 zlog_info ("[Event] BGP connection IP address %s is not configured",
84 inet_sutop (&su
, buf
));
86 zlog_info ("[Event] BGP connection IP address %s is Idle state",
87 inet_sutop (&su
, buf
));
93 /* In case of peer is EBGP, we should set TTL for this connection. */
94 if (peer_sort (peer1
) == BGP_PEER_EBGP
)
95 sockopt_ttl (peer1
->su
.sa
.sa_family
, bgp_sock
, peer1
->ttl
);
100 /* Make dummy peer until read Open packet. */
101 if (BGP_DEBUG (events
, EVENTS
))
102 zlog_info ("[Event] Make dummy peer structure until read Open packet");
105 char buf
[SU_ADDRSTRLEN
+ 1];
107 peer
= peer_create_accept (bgp
);
108 SET_FLAG (peer
->sflags
, PEER_STATUS_ACCEPT_PEER
);
111 peer
->status
= Active
;
112 peer
->local_id
= peer1
->local_id
;
114 /* Make peer's address string. */
115 sockunion2str (&su
, buf
, SU_ADDRSTRLEN
);
116 peer
->host
= strdup (buf
);
119 BGP_EVENT_ADD (peer
, TCP_connection_open
);
124 /* BGP socket bind. */
126 bgp_bind (struct peer
*peer
)
128 #ifdef SO_BINDTODEVICE
135 strncpy ((char *)&ifreq
.ifr_name
, peer
->ifname
, sizeof (ifreq
.ifr_name
));
137 ret
= setsockopt (peer
->fd
, SOL_SOCKET
, SO_BINDTODEVICE
,
138 &ifreq
, sizeof (ifreq
));
141 zlog (peer
->log
, LOG_INFO
, "bind to interface %s failed", peer
->ifname
);
144 #endif /* SO_BINDTODEVICE */
149 bgp_bind_address (int sock
, struct in_addr
*addr
)
152 struct sockaddr_in local
;
154 memset (&local
, 0, sizeof (struct sockaddr_in
));
155 local
.sin_family
= AF_INET
;
157 local
.sin_len
= sizeof(struct sockaddr_in
);
158 #endif /* HAVE_SIN_LEN */
159 memcpy (&local
.sin_addr
, addr
, sizeof (struct in_addr
));
161 ret
= bind (sock
, (struct sockaddr
*)&local
, sizeof (struct sockaddr_in
));
168 bgp_update_address (struct interface
*ifp
)
170 struct prefix_ipv4
*p
;
171 struct connected
*connected
;
174 for (node
= listhead (ifp
->connected
); node
; nextnode (node
))
176 connected
= getdata (node
);
178 p
= (struct prefix_ipv4
*) connected
->address
;
180 if (p
->family
== AF_INET
)
186 /* Update source selection. */
188 bgp_update_source (struct peer
*peer
)
190 struct interface
*ifp
;
191 struct in_addr
*addr
;
193 /* Source is specified with interface name. */
196 ifp
= if_lookup_by_name (peer
->update_if
);
200 addr
= bgp_update_address (ifp
);
204 bgp_bind_address (peer
->fd
, addr
);
207 /* Source is specified with IP address. */
208 if (peer
->update_source
)
209 sockunion_bind (peer
->fd
, peer
->update_source
, 0, peer
->update_source
);
212 /* BGP try to connect to the peer. */
214 bgp_connect (struct peer
*peer
)
216 unsigned int ifindex
= 0;
218 /* Make socket for the peer. */
219 peer
->fd
= sockunion_socket (&peer
->su
);
223 /* If we can get socket for the peer, adjest TTL and make connection. */
224 if (peer_sort (peer
) == BGP_PEER_EBGP
)
225 sockopt_ttl (peer
->su
.sa
.sa_family
, peer
->fd
, peer
->ttl
);
227 sockopt_reuseaddr (peer
->fd
);
228 sockopt_reuseport (peer
->fd
);
233 /* Update source bind. */
234 bgp_update_source (peer
);
238 ifindex
= if_nametoindex (peer
->ifname
);
239 #endif /* HAVE_IPV6 */
241 if (BGP_DEBUG (events
, EVENTS
))
242 plog_info (peer
->log
, "%s [Event] Connect start to %s fd %d",
243 peer
->host
, peer
->host
, peer
->fd
);
245 #ifdef HAVE_TCP_SIGNATURE
246 if (CHECK_FLAG (peer
->flags
, PEER_FLAG_PASSWORD
))
247 bgp_tcpsig_set (peer
->fd
, peer
);
248 #endif /* HAVE_TCP_SIGNATURE */
250 /* Connect to the remote peer. */
251 return sockunion_connect (peer
->fd
, &peer
->su
, htons (peer
->port
), ifindex
);
254 /* After TCP connection is established. Get local address and port. */
256 bgp_getsockname (struct peer
*peer
)
260 XFREE (MTYPE_TMP
, peer
->su_local
);
261 peer
->su_local
= NULL
;
266 XFREE (MTYPE_TMP
, peer
->su_remote
);
267 peer
->su_remote
= NULL
;
270 peer
->su_local
= sockunion_getsockname (peer
->fd
);
271 peer
->su_remote
= sockunion_getpeername (peer
->fd
);
273 bgp_nexthop_set (peer
->su_local
, peer
->su_remote
, &peer
->nexthop
, peer
);
276 /* IPv6 supported version of BGP server socket setup. */
277 #if defined (HAVE_IPV6) && ! defined (NRL)
279 bgp_socket (struct bgp
*bgp
, unsigned short port
)
283 struct addrinfo
*ainfo
;
284 struct addrinfo
*ainfo_save
;
286 char port_str
[BUFSIZ
];
288 memset (&req
, 0, sizeof (struct addrinfo
));
290 req
.ai_flags
= AI_PASSIVE
;
291 req
.ai_family
= AF_UNSPEC
;
292 req
.ai_socktype
= SOCK_STREAM
;
293 sprintf (port_str
, "%d", port
);
294 port_str
[sizeof (port_str
) - 1] = '\0';
296 ret
= getaddrinfo (NULL
, port_str
, &req
, &ainfo
);
299 zlog_err ("getaddrinfo: %s", gai_strerror (ret
));
307 if (ainfo
->ai_family
!= AF_INET
&& ainfo
->ai_family
!= AF_INET6
)
310 sock
= socket (ainfo
->ai_family
, ainfo
->ai_socktype
, ainfo
->ai_protocol
);
313 zlog_err ("socket: %s", strerror (errno
));
317 sockopt_reuseaddr (sock
);
318 sockopt_reuseport (sock
);
320 ret
= bind (sock
, ainfo
->ai_addr
, ainfo
->ai_addrlen
);
323 zlog_err ("bind: %s", strerror (errno
));
327 ret
= listen (sock
, 3);
330 zlog_err ("listen: %s", strerror (errno
));
335 #ifdef HAVE_TCP_SIGNATURE
336 #ifdef HAVE_LINUX_TCP_SIGNATURE
338 #endif /* HAVE_LINUX_TCP_SIGNATURE */
339 #ifdef HAVE_OPENBSD_TCP_SIGNATURE
340 bgp_tcpsig_set (sock
, 0);
342 #endif /* HAVE_OPENBSD_TCP_SIGNATURE */
343 #endif /* HAVE_TCP_SIGNATURE */
345 thread_add_read (master
, bgp_accept
, bgp
, sock
);
347 while ((ainfo
= ainfo
->ai_next
) != NULL
);
349 freeaddrinfo (ainfo_save
);
354 /* Traditional IPv4 only version. */
356 bgp_socket (struct bgp
*bgp
, unsigned short port
)
360 struct sockaddr_in sin
;
363 sock
= socket (AF_INET
, SOCK_STREAM
, 0);
366 zlog_err ("socket: %s", strerror (errno
));
370 sockopt_reuseaddr (sock
);
371 sockopt_reuseport (sock
);
373 memset (&sin
, 0, sizeof (struct sockaddr_in
));
375 sin
.sin_family
= AF_INET
;
376 sin
.sin_port
= htons (port
);
377 socklen
= sizeof (struct sockaddr_in
);
379 sin
.sin_len
= socklen
;
380 #endif /* HAVE_SIN_LEN */
382 ret
= bind (sock
, (struct sockaddr
*) &sin
, socklen
);
385 zlog_err ("bind: %s", strerror (errno
));
389 ret
= listen (sock
, 3);
392 zlog_err ("listen: %s", strerror (errno
));
396 #ifdef HAVE_TCP_SIGNATURE
397 #ifdef HAVE_LINUX_TCP_SIGNATURE
399 #endif /* HAVE_LINUX_TCP_SIGNATURE */
400 #ifdef HAVE_OPENBSD_TCP_SIGNATURE
401 bgp_tcpsig_set (sock
, 0);
403 #endif /* HAVE_OPENBSD_TCP_SIGNATURE */
404 #endif /* HAVE_TCP_SIGNATURE */
406 thread_add_read (bm
->master
, bgp_accept
, bgp
, sock
);
410 #endif /* HAVE_IPV6 && !NRL */