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"
32 #include "bgpd/bgpd.h"
33 #include "bgpd/bgp_fsm.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_debug.h"
36 #include "bgpd/bgp_network.h"
38 extern struct zebra_privs_t bgpd_privs
;
41 /* Accept bgp connection. */
43 bgp_accept (struct thread
*thread
)
51 char buf
[SU_ADDRSTRLEN
];
53 /* Regiser accept thread. */
54 accept_sock
= THREAD_FD (thread
);
55 bgp
= THREAD_ARG (thread
);
59 zlog_err ("accept_sock is nevative value %d", accept_sock
);
62 thread_add_read (master
, bgp_accept
, bgp
, accept_sock
);
64 /* Accept client connection. */
65 bgp_sock
= sockunion_accept (accept_sock
, &su
);
68 zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno
));
72 if (BGP_DEBUG (events
, EVENTS
))
73 zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su
, buf
));
75 /* Check remote IP address */
76 peer1
= peer_lookup (bgp
, &su
);
77 if (! peer1
|| peer1
->status
== Idle
)
79 if (BGP_DEBUG (events
, EVENTS
))
82 zlog_debug ("[Event] BGP connection IP address %s is not configured",
83 inet_sutop (&su
, buf
));
85 zlog_debug ("[Event] BGP connection IP address %s is Idle state",
86 inet_sutop (&su
, buf
));
92 /* In case of peer is EBGP, we should set TTL for this connection. */
93 if (peer_sort (peer1
) == BGP_PEER_EBGP
)
94 sockopt_ttl (peer1
->su
.sa
.sa_family
, bgp_sock
, peer1
->ttl
);
99 /* Make dummy peer until read Open packet. */
100 if (BGP_DEBUG (events
, EVENTS
))
101 zlog_debug ("[Event] Make dummy peer structure until read Open packet");
104 char buf
[SU_ADDRSTRLEN
+ 1];
106 peer
= peer_create_accept (bgp
);
107 SET_FLAG (peer
->sflags
, PEER_STATUS_ACCEPT_PEER
);
110 peer
->status
= Active
;
111 peer
->local_id
= peer1
->local_id
;
113 /* Make peer's address string. */
114 sockunion2str (&su
, buf
, SU_ADDRSTRLEN
);
115 peer
->host
= XSTRDUP (MTYPE_BGP_PEER_HOST
, buf
);
118 BGP_EVENT_ADD (peer
, TCP_connection_open
);
123 /* BGP socket bind. */
125 bgp_bind (struct peer
*peer
)
127 #ifdef SO_BINDTODEVICE
134 strncpy ((char *)&ifreq
.ifr_name
, peer
->ifname
, sizeof (ifreq
.ifr_name
));
136 if ( bgpd_privs
.change (ZPRIVS_RAISE
) )
137 zlog_err ("bgp_bind: could not raise privs");
139 ret
= setsockopt (peer
->fd
, SOL_SOCKET
, SO_BINDTODEVICE
,
140 &ifreq
, sizeof (ifreq
));
142 if (bgpd_privs
.change (ZPRIVS_LOWER
) )
143 zlog_err ("bgp_bind: could not lower privs");
147 zlog (peer
->log
, LOG_INFO
, "bind to interface %s failed", peer
->ifname
);
150 #endif /* SO_BINDTODEVICE */
155 bgp_bind_address (int sock
, struct in_addr
*addr
)
158 struct sockaddr_in local
;
160 memset (&local
, 0, sizeof (struct sockaddr_in
));
161 local
.sin_family
= AF_INET
;
162 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
163 local
.sin_len
= sizeof(struct sockaddr_in
);
164 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
165 memcpy (&local
.sin_addr
, addr
, sizeof (struct in_addr
));
167 if ( bgpd_privs
.change (ZPRIVS_RAISE
) )
168 zlog_err ("bgp_bind_address: could not raise privs");
170 ret
= bind (sock
, (struct sockaddr
*)&local
, sizeof (struct sockaddr_in
));
174 if (bgpd_privs
.change (ZPRIVS_LOWER
) )
175 zlog_err ("bgp_bind_address: could not lower privs");
180 static struct in_addr
*
181 bgp_update_address (struct interface
*ifp
)
183 struct prefix_ipv4
*p
;
184 struct connected
*connected
;
185 struct listnode
*node
;
187 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, connected
))
189 p
= (struct prefix_ipv4
*) connected
->address
;
191 if (p
->family
== AF_INET
)
197 /* Update source selection. */
199 bgp_update_source (struct peer
*peer
)
201 struct interface
*ifp
;
202 struct in_addr
*addr
;
204 /* Source is specified with interface name. */
207 ifp
= if_lookup_by_name (peer
->update_if
);
211 addr
= bgp_update_address (ifp
);
215 bgp_bind_address (peer
->fd
, addr
);
218 /* Source is specified with IP address. */
219 if (peer
->update_source
)
220 sockunion_bind (peer
->fd
, peer
->update_source
, 0, peer
->update_source
);
223 /* BGP try to connect to the peer. */
225 bgp_connect (struct peer
*peer
)
227 unsigned int ifindex
= 0;
229 /* Make socket for the peer. */
230 peer
->fd
= sockunion_socket (&peer
->su
);
234 /* If we can get socket for the peer, adjest TTL and make connection. */
235 if (peer_sort (peer
) == BGP_PEER_EBGP
)
236 sockopt_ttl (peer
->su
.sa
.sa_family
, peer
->fd
, peer
->ttl
);
238 sockopt_reuseaddr (peer
->fd
);
239 sockopt_reuseport (peer
->fd
);
244 /* Update source bind. */
245 bgp_update_source (peer
);
249 ifindex
= if_nametoindex (peer
->ifname
);
250 #endif /* HAVE_IPV6 */
252 if (BGP_DEBUG (events
, EVENTS
))
253 plog_debug (peer
->log
, "%s [Event] Connect start to %s fd %d",
254 peer
->host
, peer
->host
, peer
->fd
);
256 /* Connect to the remote peer. */
257 return sockunion_connect (peer
->fd
, &peer
->su
, htons (peer
->port
), ifindex
);
260 /* After TCP connection is established. Get local address and port. */
262 bgp_getsockname (struct peer
*peer
)
266 sockunion_free (peer
->su_local
);
267 peer
->su_local
= NULL
;
272 sockunion_free (peer
->su_remote
);
273 peer
->su_remote
= NULL
;
276 peer
->su_local
= sockunion_getsockname (peer
->fd
);
277 peer
->su_remote
= sockunion_getpeername (peer
->fd
);
279 bgp_nexthop_set (peer
->su_local
, peer
->su_remote
, &peer
->nexthop
, peer
);
282 /* IPv6 supported version of BGP server socket setup. */
283 #if defined (HAVE_IPV6) && ! defined (NRL)
285 bgp_socket (struct bgp
*bgp
, unsigned short port
)
289 struct addrinfo
*ainfo
;
290 struct addrinfo
*ainfo_save
;
292 char port_str
[BUFSIZ
];
294 memset (&req
, 0, sizeof (struct addrinfo
));
296 req
.ai_flags
= AI_PASSIVE
;
297 req
.ai_family
= AF_UNSPEC
;
298 req
.ai_socktype
= SOCK_STREAM
;
299 sprintf (port_str
, "%d", port
);
300 port_str
[sizeof (port_str
) - 1] = '\0';
302 ret
= getaddrinfo (NULL
, port_str
, &req
, &ainfo
);
305 zlog_err ("getaddrinfo: %s", gai_strerror (ret
));
313 if (ainfo
->ai_family
!= AF_INET
&& ainfo
->ai_family
!= AF_INET6
)
316 sock
= socket (ainfo
->ai_family
, ainfo
->ai_socktype
, ainfo
->ai_protocol
);
319 zlog_err ("socket: %s", safe_strerror (errno
));
323 sockopt_reuseaddr (sock
);
324 sockopt_reuseport (sock
);
326 if (bgpd_privs
.change (ZPRIVS_RAISE
) )
327 zlog_err ("bgp_socket: could not raise privs");
329 ret
= bind (sock
, ainfo
->ai_addr
, ainfo
->ai_addrlen
);
331 if (bgpd_privs
.change (ZPRIVS_LOWER
) )
332 zlog_err ("bgp_bind_address: could not lower privs");
336 zlog_err ("bind: %s", safe_strerror (en
));
341 ret
= listen (sock
, 3);
344 zlog_err ("listen: %s", safe_strerror (errno
));
349 thread_add_read (master
, bgp_accept
, bgp
, sock
);
351 while ((ainfo
= ainfo
->ai_next
) != NULL
);
353 freeaddrinfo (ainfo_save
);
358 /* Traditional IPv4 only version. */
360 bgp_socket (struct bgp
*bgp
, unsigned short port
)
364 struct sockaddr_in sin
;
367 sock
= socket (AF_INET
, SOCK_STREAM
, 0);
370 zlog_err ("socket: %s", safe_strerror (errno
));
374 sockopt_reuseaddr (sock
);
375 sockopt_reuseport (sock
);
377 memset (&sin
, 0, sizeof (struct sockaddr_in
));
379 sin
.sin_family
= AF_INET
;
380 sin
.sin_port
= htons (port
);
381 socklen
= sizeof (struct sockaddr_in
);
382 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
383 sin
.sin_len
= socklen
;
384 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
386 if ( bgpd_privs
.change (ZPRIVS_RAISE
) )
387 zlog_err ("bgp_socket: could not raise privs");
389 ret
= bind (sock
, (struct sockaddr
*) &sin
, socklen
);
392 if (bgpd_privs
.change (ZPRIVS_LOWER
) )
393 zlog_err ("bgp_socket: could not lower privs");
397 zlog_err ("bind: %s", safe_strerror (en
));
402 ret
= listen (sock
, 3);
405 zlog_err ("listen: %s", safe_strerror (errno
));
410 thread_add_read (bm
->master
, bgp_accept
, bgp
, sock
);
414 #endif /* HAVE_IPV6 && !NRL */