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