blob: 7dcddb7987831f79d1ad7e358245b968e42ff8f6 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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"
pauledd7c242003-06-04 13:59:38 +000030#include "privs.h"
paul718e3742002-12-13 20:15:29 +000031
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"
pauledd7c242003-06-04 13:59:38 +000037
38extern struct zebra_privs_t bgpd_privs;
39
paul718e3742002-12-13 20:15:29 +000040
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;
pauleb821182004-05-01 08:44:08 +000049 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +000050 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 {
ajs6099b3b2004-11-20 02:06:59 +000068 zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +000069 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 */
pauleb821182004-05-01 08:44:08 +000076 peer1 = peer_lookup (bgp, &su);
77 if (! peer1 || peer1->status == Idle)
paul718e3742002-12-13 20:15:29 +000078 {
79 if (BGP_DEBUG (events, EVENTS))
80 {
pauleb821182004-05-01 08:44:08 +000081 if (! peer1)
paul718e3742002-12-13 20:15:29 +000082 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. */
pauleb821182004-05-01 08:44:08 +000093 if (peer_sort (peer1) == BGP_PEER_EBGP)
94 sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl);
paul718e3742002-12-13 20:15:29 +000095
96 if (! bgp)
pauleb821182004-05-01 08:44:08 +000097 bgp = peer1->bgp;
paul718e3742002-12-13 20:15:29 +000098
pauleb821182004-05-01 08:44:08 +000099 /* 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;
112
113 /* Make peer's address string. */
114 sockunion2str (&su, buf, SU_ADDRSTRLEN);
115 peer->host = strdup (buf);
116 }
paul718e3742002-12-13 20:15:29 +0000117
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
paul98f51632004-10-25 14:19:15 +0000136 if ( bgpd_privs.change (ZPRIVS_RAISE) )
137 zlog_err ("bgp_bind: could not raise privs");
138
pauleb821182004-05-01 08:44:08 +0000139 ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE,
paul718e3742002-12-13 20:15:29 +0000140 &ifreq, sizeof (ifreq));
paul98f51632004-10-25 14:19:15 +0000141
142 if (bgpd_privs.change (ZPRIVS_LOWER) )
143 zlog_err ("bgp_bind: could not lower privs");
144
paul718e3742002-12-13 20:15:29 +0000145 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
154int
155bgp_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_SIN_LEN
163 local.sin_len = sizeof(struct sockaddr_in);
164#endif /* HAVE_SIN_LEN */
165 memcpy (&local.sin_addr, addr, sizeof (struct in_addr));
166
pauledd7c242003-06-04 13:59:38 +0000167 if ( bgpd_privs.change (ZPRIVS_RAISE) )
168 zlog_err ("bgp_bind_address: could not raise privs");
169
paul718e3742002-12-13 20:15:29 +0000170 ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in));
171 if (ret < 0)
172 ;
pauledd7c242003-06-04 13:59:38 +0000173
174 if (bgpd_privs.change (ZPRIVS_LOWER) )
175 zlog_err ("bgp_bind_address: could not lower privs");
176
paul718e3742002-12-13 20:15:29 +0000177 return 0;
178}
179
180struct in_addr *
181bgp_update_address (struct interface *ifp)
182{
183 struct prefix_ipv4 *p;
184 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +0000185 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000186
187 for (node = listhead (ifp->connected); node; nextnode (node))
188 {
189 connected = getdata (node);
190
191 p = (struct prefix_ipv4 *) connected->address;
192
193 if (p->family == AF_INET)
194 return &p->prefix;
195 }
196 return NULL;
197}
198
199/* Update source selection. */
200void
201bgp_update_source (struct peer *peer)
202{
203 struct interface *ifp;
204 struct in_addr *addr;
205
206 /* Source is specified with interface name. */
207 if (peer->update_if)
208 {
209 ifp = if_lookup_by_name (peer->update_if);
210 if (! ifp)
211 return;
212
213 addr = bgp_update_address (ifp);
214 if (! addr)
215 return;
216
pauleb821182004-05-01 08:44:08 +0000217 bgp_bind_address (peer->fd, addr);
paul718e3742002-12-13 20:15:29 +0000218 }
219
220 /* Source is specified with IP address. */
221 if (peer->update_source)
pauleb821182004-05-01 08:44:08 +0000222 sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source);
paul718e3742002-12-13 20:15:29 +0000223}
224
225/* BGP try to connect to the peer. */
226int
227bgp_connect (struct peer *peer)
228{
229 unsigned int ifindex = 0;
230
231 /* Make socket for the peer. */
pauleb821182004-05-01 08:44:08 +0000232 peer->fd = sockunion_socket (&peer->su);
233 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000234 return -1;
235
236 /* If we can get socket for the peer, adjest TTL and make connection. */
237 if (peer_sort (peer) == BGP_PEER_EBGP)
pauleb821182004-05-01 08:44:08 +0000238 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +0000239
pauleb821182004-05-01 08:44:08 +0000240 sockopt_reuseaddr (peer->fd);
241 sockopt_reuseport (peer->fd);
paul718e3742002-12-13 20:15:29 +0000242
243 /* Bind socket. */
244 bgp_bind (peer);
245
246 /* Update source bind. */
247 bgp_update_source (peer);
248
249#ifdef HAVE_IPV6
250 if (peer->ifname)
251 ifindex = if_nametoindex (peer->ifname);
252#endif /* HAVE_IPV6 */
253
254 if (BGP_DEBUG (events, EVENTS))
255 plog_info (peer->log, "%s [Event] Connect start to %s fd %d",
pauleb821182004-05-01 08:44:08 +0000256 peer->host, peer->host, peer->fd);
paul718e3742002-12-13 20:15:29 +0000257
258 /* Connect to the remote peer. */
pauleb821182004-05-01 08:44:08 +0000259 return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
paul718e3742002-12-13 20:15:29 +0000260}
261
262/* After TCP connection is established. Get local address and port. */
263void
264bgp_getsockname (struct peer *peer)
265{
266 if (peer->su_local)
267 {
268 XFREE (MTYPE_TMP, peer->su_local);
269 peer->su_local = NULL;
270 }
271
272 if (peer->su_remote)
273 {
274 XFREE (MTYPE_TMP, peer->su_remote);
275 peer->su_remote = NULL;
276 }
277
pauleb821182004-05-01 08:44:08 +0000278 peer->su_local = sockunion_getsockname (peer->fd);
279 peer->su_remote = sockunion_getpeername (peer->fd);
paul718e3742002-12-13 20:15:29 +0000280
281 bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
282}
283
284/* IPv6 supported version of BGP server socket setup. */
285#if defined (HAVE_IPV6) && ! defined (NRL)
286int
287bgp_socket (struct bgp *bgp, unsigned short port)
288{
gdt10d60ad2003-12-23 17:34:39 +0000289 int ret, en;
paul718e3742002-12-13 20:15:29 +0000290 struct addrinfo req;
291 struct addrinfo *ainfo;
292 struct addrinfo *ainfo_save;
293 int sock = 0;
294 char port_str[BUFSIZ];
295
296 memset (&req, 0, sizeof (struct addrinfo));
297
298 req.ai_flags = AI_PASSIVE;
299 req.ai_family = AF_UNSPEC;
300 req.ai_socktype = SOCK_STREAM;
301 sprintf (port_str, "%d", port);
302 port_str[sizeof (port_str) - 1] = '\0';
303
304 ret = getaddrinfo (NULL, port_str, &req, &ainfo);
305 if (ret != 0)
306 {
307 zlog_err ("getaddrinfo: %s", gai_strerror (ret));
308 return -1;
309 }
310
311 ainfo_save = ainfo;
312
313 do
314 {
315 if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
316 continue;
317
318 sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
319 if (sock < 0)
320 {
ajs6099b3b2004-11-20 02:06:59 +0000321 zlog_err ("socket: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000322 continue;
323 }
324
325 sockopt_reuseaddr (sock);
326 sockopt_reuseport (sock);
pauledd7c242003-06-04 13:59:38 +0000327
328 if (bgpd_privs.change (ZPRIVS_RAISE) )
329 zlog_err ("bgp_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +0000330
331 ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);
gdt10d60ad2003-12-23 17:34:39 +0000332 en = errno;
333 if (bgpd_privs.change (ZPRIVS_LOWER) )
334 zlog_err ("bgp_bind_address: could not lower privs");
335
paul718e3742002-12-13 20:15:29 +0000336 if (ret < 0)
337 {
ajs6099b3b2004-11-20 02:06:59 +0000338 zlog_err ("bind: %s", safe_strerror (en));
gdt10d60ad2003-12-23 17:34:39 +0000339 close(sock);
paul718e3742002-12-13 20:15:29 +0000340 continue;
341 }
pauledd7c242003-06-04 13:59:38 +0000342
paul718e3742002-12-13 20:15:29 +0000343 ret = listen (sock, 3);
344 if (ret < 0)
345 {
ajs6099b3b2004-11-20 02:06:59 +0000346 zlog_err ("listen: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000347 close (sock);
348 continue;
349 }
350
351 thread_add_read (master, bgp_accept, bgp, sock);
352 }
353 while ((ainfo = ainfo->ai_next) != NULL);
354
355 freeaddrinfo (ainfo_save);
356
357 return sock;
358}
359#else
360/* Traditional IPv4 only version. */
361int
362bgp_socket (struct bgp *bgp, unsigned short port)
363{
364 int sock;
365 int socklen;
366 struct sockaddr_in sin;
hasso4a1a2712004-02-12 15:41:38 +0000367 int ret, en;
paul718e3742002-12-13 20:15:29 +0000368
369 sock = socket (AF_INET, SOCK_STREAM, 0);
370 if (sock < 0)
371 {
ajs6099b3b2004-11-20 02:06:59 +0000372 zlog_err ("socket: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000373 return sock;
374 }
375
376 sockopt_reuseaddr (sock);
377 sockopt_reuseport (sock);
378
379 memset (&sin, 0, sizeof (struct sockaddr_in));
380
381 sin.sin_family = AF_INET;
382 sin.sin_port = htons (port);
383 socklen = sizeof (struct sockaddr_in);
384#ifdef HAVE_SIN_LEN
385 sin.sin_len = socklen;
386#endif /* HAVE_SIN_LEN */
387
pauledd7c242003-06-04 13:59:38 +0000388 if ( bgpd_privs.change (ZPRIVS_RAISE) )
389 zlog_err ("bgp_socket: could not raise privs");
390
paul718e3742002-12-13 20:15:29 +0000391 ret = bind (sock, (struct sockaddr *) &sin, socklen);
gdt10d60ad2003-12-23 17:34:39 +0000392 en = errno;
393
394 if (bgpd_privs.change (ZPRIVS_LOWER) )
395 zlog_err ("bgp_socket: could not lower privs");
396
paul718e3742002-12-13 20:15:29 +0000397 if (ret < 0)
398 {
ajs6099b3b2004-11-20 02:06:59 +0000399 zlog_err ("bind: %s", safe_strerror (en));
paul718e3742002-12-13 20:15:29 +0000400 close (sock);
401 return ret;
402 }
pauledd7c242003-06-04 13:59:38 +0000403
paul718e3742002-12-13 20:15:29 +0000404 ret = listen (sock, 3);
405 if (ret < 0)
406 {
ajs6099b3b2004-11-20 02:06:59 +0000407 zlog_err ("listen: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000408 close (sock);
409 return ret;
410 }
411
412 thread_add_read (bm->master, bgp_accept, bgp, sock);
413
414 return sock;
415}
416#endif /* HAVE_IPV6 && !NRL */