]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_network.c
[autoconf] bugs 162,303,178: Fix 'present but can not be compiled' warnings
[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 "memory.h"
26 #include "log.h"
27 #include "if.h"
28 #include "prefix.h"
29 #include "command.h"
30 #include "privs.h"
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"
37
38 extern struct zebra_privs_t bgpd_privs;
39
40 \f
41 /* Accept bgp connection. */
42 static int
43 bgp_accept (struct thread *thread)
44 {
45 int bgp_sock;
46 int accept_sock;
47 union sockunion su;
48 struct peer *peer;
49 struct peer *peer1;
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)", safe_strerror (errno));
69 return -1;
70 }
71
72 if (BGP_DEBUG (events, EVENTS))
73 zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
74
75 /* Check remote IP address */
76 peer1 = peer_lookup (bgp, &su);
77 if (! peer1 || peer1->status == Idle)
78 {
79 if (BGP_DEBUG (events, EVENTS))
80 {
81 if (! peer1)
82 zlog_debug ("[Event] BGP connection IP address %s is not configured",
83 inet_sutop (&su, buf));
84 else
85 zlog_debug ("[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. */
93 if (peer_sort (peer1) == BGP_PEER_EBGP)
94 sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl);
95
96 if (! bgp)
97 bgp = peer1->bgp;
98
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");
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;
112
113 /* Make peer's address string. */
114 sockunion2str (&su, buf, SU_ADDRSTRLEN);
115 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
116 }
117
118 BGP_EVENT_ADD (peer, TCP_connection_open);
119
120 return 0;
121 }
122
123 /* BGP socket bind. */
124 static int
125 bgp_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
136 if ( bgpd_privs.change (ZPRIVS_RAISE) )
137 zlog_err ("bgp_bind: could not raise privs");
138
139 ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE,
140 &ifreq, sizeof (ifreq));
141
142 if (bgpd_privs.change (ZPRIVS_LOWER) )
143 zlog_err ("bgp_bind: could not lower privs");
144
145 if (ret < 0)
146 {
147 zlog (peer->log, LOG_INFO, "bind to interface %s failed", peer->ifname);
148 return ret;
149 }
150 #endif /* SO_BINDTODEVICE */
151 return 0;
152 }
153
154 static int
155 bgp_bind_address (int sock, struct in_addr *addr)
156 {
157 int ret;
158 struct sockaddr_in local;
159
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));
166
167 if ( bgpd_privs.change (ZPRIVS_RAISE) )
168 zlog_err ("bgp_bind_address: could not raise privs");
169
170 ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in));
171 if (ret < 0)
172 ;
173
174 if (bgpd_privs.change (ZPRIVS_LOWER) )
175 zlog_err ("bgp_bind_address: could not lower privs");
176
177 return 0;
178 }
179
180 static struct in_addr *
181 bgp_update_address (struct interface *ifp)
182 {
183 struct prefix_ipv4 *p;
184 struct connected *connected;
185 struct listnode *node;
186
187 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
188 {
189 p = (struct prefix_ipv4 *) connected->address;
190
191 if (p->family == AF_INET)
192 return &p->prefix;
193 }
194 return NULL;
195 }
196
197 /* Update source selection. */
198 static void
199 bgp_update_source (struct peer *peer)
200 {
201 struct interface *ifp;
202 struct in_addr *addr;
203
204 /* Source is specified with interface name. */
205 if (peer->update_if)
206 {
207 ifp = if_lookup_by_name (peer->update_if);
208 if (! ifp)
209 return;
210
211 addr = bgp_update_address (ifp);
212 if (! addr)
213 return;
214
215 bgp_bind_address (peer->fd, addr);
216 }
217
218 /* Source is specified with IP address. */
219 if (peer->update_source)
220 sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source);
221 }
222
223 /* BGP try to connect to the peer. */
224 int
225 bgp_connect (struct peer *peer)
226 {
227 unsigned int ifindex = 0;
228
229 /* Make socket for the peer. */
230 peer->fd = sockunion_socket (&peer->su);
231 if (peer->fd < 0)
232 return -1;
233
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);
237
238 sockopt_reuseaddr (peer->fd);
239 sockopt_reuseport (peer->fd);
240
241 /* Bind socket. */
242 bgp_bind (peer);
243
244 /* Update source bind. */
245 bgp_update_source (peer);
246
247 #ifdef HAVE_IPV6
248 if (peer->ifname)
249 ifindex = if_nametoindex (peer->ifname);
250 #endif /* HAVE_IPV6 */
251
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);
255
256 /* Connect to the remote peer. */
257 return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
258 }
259
260 /* After TCP connection is established. Get local address and port. */
261 void
262 bgp_getsockname (struct peer *peer)
263 {
264 if (peer->su_local)
265 {
266 sockunion_free (peer->su_local);
267 peer->su_local = NULL;
268 }
269
270 if (peer->su_remote)
271 {
272 sockunion_free (peer->su_remote);
273 peer->su_remote = NULL;
274 }
275
276 peer->su_local = sockunion_getsockname (peer->fd);
277 peer->su_remote = sockunion_getpeername (peer->fd);
278
279 bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
280 }
281
282 /* IPv6 supported version of BGP server socket setup. */
283 #if defined (HAVE_IPV6) && ! defined (NRL)
284 int
285 bgp_socket (struct bgp *bgp, unsigned short port)
286 {
287 int ret, en;
288 struct addrinfo req;
289 struct addrinfo *ainfo;
290 struct addrinfo *ainfo_save;
291 int sock = 0;
292 char port_str[BUFSIZ];
293
294 memset (&req, 0, sizeof (struct addrinfo));
295
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';
301
302 ret = getaddrinfo (NULL, port_str, &req, &ainfo);
303 if (ret != 0)
304 {
305 zlog_err ("getaddrinfo: %s", gai_strerror (ret));
306 return -1;
307 }
308
309 ainfo_save = ainfo;
310
311 do
312 {
313 if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
314 continue;
315
316 sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
317 if (sock < 0)
318 {
319 zlog_err ("socket: %s", safe_strerror (errno));
320 continue;
321 }
322
323 sockopt_reuseaddr (sock);
324 sockopt_reuseport (sock);
325
326 if (bgpd_privs.change (ZPRIVS_RAISE) )
327 zlog_err ("bgp_socket: could not raise privs");
328
329 ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);
330 en = errno;
331 if (bgpd_privs.change (ZPRIVS_LOWER) )
332 zlog_err ("bgp_bind_address: could not lower privs");
333
334 if (ret < 0)
335 {
336 zlog_err ("bind: %s", safe_strerror (en));
337 close(sock);
338 continue;
339 }
340
341 ret = listen (sock, 3);
342 if (ret < 0)
343 {
344 zlog_err ("listen: %s", safe_strerror (errno));
345 close (sock);
346 continue;
347 }
348
349 thread_add_read (master, bgp_accept, bgp, sock);
350 }
351 while ((ainfo = ainfo->ai_next) != NULL);
352
353 freeaddrinfo (ainfo_save);
354
355 return sock;
356 }
357 #else
358 /* Traditional IPv4 only version. */
359 int
360 bgp_socket (struct bgp *bgp, unsigned short port)
361 {
362 int sock;
363 int socklen;
364 struct sockaddr_in sin;
365 int ret, en;
366
367 sock = socket (AF_INET, SOCK_STREAM, 0);
368 if (sock < 0)
369 {
370 zlog_err ("socket: %s", safe_strerror (errno));
371 return sock;
372 }
373
374 sockopt_reuseaddr (sock);
375 sockopt_reuseport (sock);
376
377 memset (&sin, 0, sizeof (struct sockaddr_in));
378
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 */
385
386 if ( bgpd_privs.change (ZPRIVS_RAISE) )
387 zlog_err ("bgp_socket: could not raise privs");
388
389 ret = bind (sock, (struct sockaddr *) &sin, socklen);
390 en = errno;
391
392 if (bgpd_privs.change (ZPRIVS_LOWER) )
393 zlog_err ("bgp_socket: could not lower privs");
394
395 if (ret < 0)
396 {
397 zlog_err ("bind: %s", safe_strerror (en));
398 close (sock);
399 return ret;
400 }
401
402 ret = listen (sock, 3);
403 if (ret < 0)
404 {
405 zlog_err ("listen: %s", safe_strerror (errno));
406 close (sock);
407 return ret;
408 }
409
410 thread_add_read (bm->master, bgp_accept, bgp, sock);
411
412 return sock;
413 }
414 #endif /* HAVE_IPV6 && !NRL */