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" 25#include "memory.h" 26#include "log.h" 27#include "if.h" 28#include "prefix.h" 29#include "command.h" 30 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" 36 37/* Accept bgp connection. */ 38static int 39bgp_accept (struct thread *thread) 40{ 41 int bgp_sock; 42 int accept_sock; 43 union sockunion su; 44 struct peer *peer; 45 struct peer *peer1; 46 struct bgp *bgp; 47 char buf[SU_ADDRSTRLEN]; 48 49 /* Regiser accept thread. */ 50 accept_sock = THREAD_FD (thread); 51 bgp = THREAD_ARG (thread); 52 53 if (accept_sock < 0) 54 { 55 zlog_err ("accept_sock is nevative value %d", accept_sock); 56 return -1; 57 } 58 thread_add_read (master, bgp_accept, bgp, accept_sock); 59 60 /* Accept client connection. */ 61 bgp_sock = sockunion_accept (accept_sock, &su); 62 if (bgp_sock < 0) 63 { 64 zlog_err ("[Error] BGP socket accept failed (%s)", strerror (errno)); 65 return -1; 66 } 67 68 if (BGP_DEBUG (events, EVENTS)) 69 zlog_info ("[Event] BGP connection from host %s", inet_sutop (&su, buf)); 70 71 /* Check remote IP address */ 72 peer1 = peer_lookup (bgp, &su); 73 if (! peer1 || peer1->status == Idle) 74 { 75 if (BGP_DEBUG (events, EVENTS)) 76 { 77 if (! peer1) 78 zlog_info ("[Event] BGP connection IP address %s is not configured", 79 inet_sutop (&su, buf)); 80 else 81 zlog_info ("[Event] BGP connection IP address %s is Idle state", 82 inet_sutop (&su, buf)); 83 } 84 close (bgp_sock); 85 return -1; 86 } 87 88 /* In case of peer is EBGP, we should set TTL for this connection. */ 89 if (peer_sort (peer1) == BGP_PEER_EBGP) 90 sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl); 91 92 if (! bgp) 93 bgp = peer1->bgp; 94 95 /* Make dummy peer until read Open packet. */ 96 if (BGP_DEBUG (events, EVENTS)) 97 zlog_info ("[Event] Make dummy peer structure until read Open packet"); 98 99 { 100 char buf[SU_ADDRSTRLEN + 1]; 101 102 peer = peer_create_accept (bgp); 103 SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER); 104 peer->su = su; 105 peer->fd = bgp_sock; 106 peer->status = Active; 107 peer->local_id = peer1->local_id; 108 109 /* Make peer's address string. */ 110 sockunion2str (&su, buf, SU_ADDRSTRLEN); 111 peer->host = strdup (buf); 112 } 113 114 BGP_EVENT_ADD (peer, TCP_connection_open); 115 116 return 0; 117} 118 119/* BGP socket bind. */ 120int 121bgp_bind (struct peer *peer) 122{ 123#ifdef SO_BINDTODEVICE 124 int ret; 125 struct ifreq ifreq; 126 127 if (! peer->ifname) 128 return 0; 129 130 strncpy ((char *)&ifreq.ifr_name, peer->ifname, sizeof (ifreq.ifr_name)); 131 132 ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE, 133 &ifreq, sizeof (ifreq)); 134 if (ret < 0) 135 { 136 zlog (peer->log, LOG_INFO, "bind to interface %s failed", peer->ifname); 137 return ret; 138 } 139#endif /* SO_BINDTODEVICE */ 140 return 0; 141} 142 143int 144bgp_bind_address (int sock, struct in_addr *addr) 145{ 146 int ret; 147 struct sockaddr_in local; 148 149 memset (&local, 0, sizeof (struct sockaddr_in)); 150 local.sin_family = AF_INET; 151#ifdef HAVE_SIN_LEN 152 local.sin_len = sizeof(struct sockaddr_in); 153#endif /* HAVE_SIN_LEN */ 154 memcpy (&local.sin_addr, addr, sizeof (struct in_addr)); 155 156 ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in)); 157 if (ret < 0) 158 ; 159 return 0; 160} 161 162struct in_addr * 163bgp_update_address (struct interface *ifp) 164{ 165 struct prefix_ipv4 *p; 166 struct connected *connected; 167 listnode node; 168 169 for (node = listhead (ifp->connected); node; nextnode (node)) 170 { 171 connected = getdata (node); 172 173 p = (struct prefix_ipv4 *) connected->address; 174 175 if (p->family == AF_INET) 176 return &p->prefix; 177 } 178 return NULL; 179} 180 181/* Update source selection. */ 182void 183bgp_update_source (struct peer *peer) 184{ 185 struct interface *ifp; 186 struct in_addr *addr; 187 188 /* Source is specified with interface name. */ 189 if (peer->update_if) 190 { 191 ifp = if_lookup_by_name (peer->update_if); 192 if (! ifp) 193 return; 194 195 addr = bgp_update_address (ifp); 196 if (! addr) 197 return; 198 199 bgp_bind_address (peer->fd, addr); 200 } 201 202 /* Source is specified with IP address. */ 203 if (peer->update_source) 204 sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source); 205} 206 207/* BGP try to connect to the peer. */ 208int 209bgp_connect (struct peer *peer) 210{ 211 unsigned int ifindex = 0; 212 213 /* Make socket for the peer. */ 214 peer->fd = sockunion_socket (&peer->su); 215 if (peer->fd < 0) 216 return -1; 217 218 /* If we can get socket for the peer, adjest TTL and make connection. */ 219 if (peer_sort (peer) == BGP_PEER_EBGP) 220 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl); 221 222 sockopt_reuseaddr (peer->fd); 223 sockopt_reuseport (peer->fd); 224 225 /* Bind socket. */ 226 bgp_bind (peer); 227 228 /* Update source bind. */ 229 bgp_update_source (peer); 230 231#ifdef HAVE_IPV6 232 if (peer->ifname) 233 ifindex = if_nametoindex (peer->ifname); 234#endif /* HAVE_IPV6 */ 235 236 if (BGP_DEBUG (events, EVENTS)) 237 plog_info (peer->log, "%s [Event] Connect start to %s fd %d", 238 peer->host, peer->host, peer->fd); 239 240 /* Connect to the remote peer. */ 241 return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex); 242} 243 244/* After TCP connection is established. Get local address and port. */ 245void 246bgp_getsockname (struct peer *peer) 247{ 248 if (peer->su_local) 249 { 250 XFREE (MTYPE_TMP, peer->su_local); 251 peer->su_local = NULL; 252 } 253 254 if (peer->su_remote) 255 { 256 XFREE (MTYPE_TMP, peer->su_remote); 257 peer->su_remote = NULL; 258 } 259 260 peer->su_local = sockunion_getsockname (peer->fd); 261 peer->su_remote = sockunion_getpeername (peer->fd); 262 263 bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer); 264} 265 266/* IPv6 supported version of BGP server socket setup. */ 267#if defined (HAVE_IPV6) && ! defined (NRL) 268int 269bgp_socket (struct bgp *bgp, unsigned short port) 270{ 271 int ret; 272 struct addrinfo req; 273 struct addrinfo *ainfo; 274 struct addrinfo *ainfo_save; 275 int sock = 0; 276 char port_str[BUFSIZ]; 277 278 memset (&req, 0, sizeof (struct addrinfo)); 279 280 req.ai_flags = AI_PASSIVE; 281 req.ai_family = AF_UNSPEC; 282 req.ai_socktype = SOCK_STREAM; 283 sprintf (port_str, "%d", port); 284 port_str[sizeof (port_str) - 1] = '\0'; 285 286 ret = getaddrinfo (NULL, port_str, &req, &ainfo); 287 if (ret != 0) 288 { 289 zlog_err ("getaddrinfo: %s", gai_strerror (ret)); 290 return -1; 291 } 292 293 ainfo_save = ainfo; 294 295 do 296 { 297 if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6) 298 continue; 299 300 sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol); 301 if (sock < 0) 302 { 303 zlog_err ("socket: %s", strerror (errno)); 304 continue; 305 } 306 307 sockopt_reuseaddr (sock); 308 sockopt_reuseport (sock); 309 310 ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen); 311 if (ret < 0) 312 { 313 zlog_err ("bind: %s", strerror (errno)); 314 close (sock); 315 continue; 316 } 317 ret = listen (sock, 3); 318 if (ret < 0) 319 { 320 zlog_err ("listen: %s", strerror (errno)); 321 close (sock); 322 continue; 323 } 324 325 thread_add_read (master, bgp_accept, bgp, sock); 326 } 327 while ((ainfo = ainfo->ai_next) != NULL); 328 329 freeaddrinfo (ainfo_save); 330 331 return sock; 332} 333#else 334/* Traditional IPv4 only version. */ 335int 336bgp_socket (struct bgp *bgp, unsigned short port) 337{ 338 int sock; 339 int socklen; 340 struct sockaddr_in sin; 341 int ret; 342 343 sock = socket (AF_INET, SOCK_STREAM, 0); 344 if (sock < 0) 345 { 346 zlog_err ("socket: %s", strerror (errno)); 347 return sock; 348 } 349 350 sockopt_reuseaddr (sock); 351 sockopt_reuseport (sock); 352 353 memset (&sin, 0, sizeof (struct sockaddr_in)); 354 355 sin.sin_family = AF_INET; 356 sin.sin_port = htons (port); 357 socklen = sizeof (struct sockaddr_in); 358#ifdef HAVE_SIN_LEN 359 sin.sin_len = socklen; 360#endif /* HAVE_SIN_LEN */ 361 362 ret = bind (sock, (struct sockaddr *) &sin, socklen); 363 if (ret < 0) 364 { 365 zlog_err ("bind: %s", strerror (errno)); 366 close (sock); 367 return ret; 368 } 369 ret = listen (sock, 3); 370 if (ret < 0) 371 { 372 zlog_err ("listen: %s", strerror (errno)); 373 close (sock); 374 return ret; 375 } 376 377 thread_add_read (bm->master, bgp_accept, bgp, sock); 378 379 return sock; 380} 381#endif /* HAVE_IPV6 && !NRL */ 382