blob: 949159de8b5624073deec2d15f1187d5e25ff24f [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Redistribution Handler
2 * Copyright (C) 1998 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
22#include <zebra.h>
23
24#include "vector.h"
25#include "vty.h"
26#include "command.h"
27#include "prefix.h"
28#include "table.h"
29#include "stream.h"
30#include "zclient.h"
31#include "linklist.h"
32#include "log.h"
33
34#include "zebra/rib.h"
35#include "zebra/zserv.h"
36#include "zebra/redistribute.h"
37#include "zebra/debug.h"
hasso18a6dce2004-10-03 18:18:34 +000038#include "zebra/router-id.h"
paul718e3742002-12-13 20:15:29 +000039
paulb21b19c2003-06-15 01:28:29 +000040/* master zebra server structure */
41extern struct zebra_t zebrad;
42
ajs27da3982005-02-24 16:06:33 +000043static int
paul718e3742002-12-13 20:15:29 +000044zebra_check_addr (struct prefix *p)
45{
46 if (p->family == AF_INET)
47 {
48 u_int32_t addr;
49
50 addr = p->u.prefix4.s_addr;
51 addr = ntohl (addr);
52
53 if (IPV4_NET127 (addr) || IN_CLASSD (addr))
54 return 0;
55 }
56#ifdef HAVE_IPV6
57 if (p->family == AF_INET6)
58 {
59 if (IN6_IS_ADDR_LOOPBACK (&p->u.prefix6))
60 return 0;
61 if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
62 return 0;
63 }
64#endif /* HAVE_IPV6 */
65 return 1;
66}
67
ajs27da3982005-02-24 16:06:33 +000068static int
paul718e3742002-12-13 20:15:29 +000069is_default (struct prefix *p)
70{
71 if (p->family == AF_INET)
72 if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0)
73 return 1;
74#ifdef HAVE_IPV6
75#if 0 /* IPv6 default separation is now pending until protocol daemon
76 can handle that. */
77 if (p->family == AF_INET6)
78 if (IN6_IS_ADDR_UNSPECIFIED (&p->u.prefix6) && p->prefixlen == 0)
79 return 1;
80#endif /* 0 */
81#endif /* HAVE_IPV6 */
82 return 0;
83}
84
ajs27da3982005-02-24 16:06:33 +000085static void
paul718e3742002-12-13 20:15:29 +000086zebra_redistribute_default (struct zserv *client)
87{
88 struct prefix_ipv4 p;
89 struct route_table *table;
90 struct route_node *rn;
91 struct rib *newrib;
92#ifdef HAVE_IPV6
93 struct prefix_ipv6 p6;
94#endif /* HAVE_IPV6 */
95
96
97 /* Lookup default route. */
98 memset (&p, 0, sizeof (struct prefix_ipv4));
99 p.family = AF_INET;
100
101 /* Lookup table. */
102 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
103 if (table)
104 {
105 rn = route_node_lookup (table, (struct prefix *)&p);
106 if (rn)
107 {
108 for (newrib = rn->info; newrib; newrib = newrib->next)
109 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
110 && newrib->distance != DISTANCE_INFINITY)
paulb9df2d22004-05-09 09:09:59 +0000111 zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib);
paul718e3742002-12-13 20:15:29 +0000112 route_unlock_node (rn);
113 }
114 }
115
116#ifdef HAVE_IPV6
117 /* Lookup default route. */
118 memset (&p6, 0, sizeof (struct prefix_ipv6));
119 p6.family = AF_INET6;
120
121 /* Lookup table. */
122 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
123 if (table)
124 {
125 rn = route_node_lookup (table, (struct prefix *)&p6);
126 if (rn)
127 {
128 for (newrib = rn->info; newrib; newrib = newrib->next)
129 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
130 && newrib->distance != DISTANCE_INFINITY)
paulb9df2d22004-05-09 09:09:59 +0000131 zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib);
paul718e3742002-12-13 20:15:29 +0000132 route_unlock_node (rn);
133 }
134 }
135#endif /* HAVE_IPV6 */
136}
137
138/* Redistribute routes. */
ajs27da3982005-02-24 16:06:33 +0000139static void
paul718e3742002-12-13 20:15:29 +0000140zebra_redistribute (struct zserv *client, int type)
141{
142 struct rib *newrib;
143 struct route_table *table;
144 struct route_node *rn;
145
146 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
147 if (table)
148 for (rn = route_top (table); rn; rn = route_next (rn))
149 for (newrib = rn->info; newrib; newrib = newrib->next)
150 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
151 && newrib->type == type
152 && newrib->distance != DISTANCE_INFINITY
153 && zebra_check_addr (&rn->p))
paulb9df2d22004-05-09 09:09:59 +0000154 zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib);
paul718e3742002-12-13 20:15:29 +0000155
156#ifdef HAVE_IPV6
157 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
158 if (table)
159 for (rn = route_top (table); rn; rn = route_next (rn))
160 for (newrib = rn->info; newrib; newrib = newrib->next)
161 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
162 && newrib->type == type
163 && newrib->distance != DISTANCE_INFINITY
164 && zebra_check_addr (&rn->p))
paulb9df2d22004-05-09 09:09:59 +0000165 zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib);
paul718e3742002-12-13 20:15:29 +0000166#endif /* HAVE_IPV6 */
167}
168
paul718e3742002-12-13 20:15:29 +0000169void
170redistribute_add (struct prefix *p, struct rib *rib)
171{
hasso52dc7ee2004-09-23 19:18:23 +0000172 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000173 struct zserv *client;
174
paulb21b19c2003-06-15 01:28:29 +0000175 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000176 if ((client = getdata (node)) != NULL)
177 {
178 if (is_default (p))
179 {
180 if (client->redist_default || client->redist[rib->type])
181 {
182 if (p->family == AF_INET)
paulb9df2d22004-05-09 09:09:59 +0000183 zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000184#ifdef HAVE_IPV6
185 if (p->family == AF_INET6)
paulb9df2d22004-05-09 09:09:59 +0000186 zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000187#endif /* HAVE_IPV6 */
188 }
189 }
190 else if (client->redist[rib->type])
191 {
192 if (p->family == AF_INET)
paulb9df2d22004-05-09 09:09:59 +0000193 zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000194#ifdef HAVE_IPV6
195 if (p->family == AF_INET6)
paulb9df2d22004-05-09 09:09:59 +0000196 zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000197#endif /* HAVE_IPV6 */
198 }
199 }
200}
201
202void
203redistribute_delete (struct prefix *p, struct rib *rib)
204{
hasso52dc7ee2004-09-23 19:18:23 +0000205 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000206 struct zserv *client;
207
208 /* Add DISTANCE_INFINITY check. */
209 if (rib->distance == DISTANCE_INFINITY)
210 return;
211
paulb21b19c2003-06-15 01:28:29 +0000212 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000213 if ((client = getdata (node)) != NULL)
214 {
215 if (is_default (p))
216 {
217 if (client->redist_default || client->redist[rib->type])
218 {
219 if (p->family == AF_INET)
paulb9df2d22004-05-09 09:09:59 +0000220 zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000221#ifdef HAVE_IPV6
222 if (p->family == AF_INET6)
paulb9df2d22004-05-09 09:09:59 +0000223 zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000224#endif /* HAVE_IPV6 */
225 }
226 }
227 else if (client->redist[rib->type])
228 {
229 if (p->family == AF_INET)
paulb9df2d22004-05-09 09:09:59 +0000230 zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000231#ifdef HAVE_IPV6
232 if (p->family == AF_INET6)
paulb9df2d22004-05-09 09:09:59 +0000233 zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000234#endif /* HAVE_IPV6 */
235 }
236 }
237}
238
239void
240zebra_redistribute_add (int command, struct zserv *client, int length)
241{
242 int type;
243
244 type = stream_getc (client->ibuf);
245
246 switch (type)
247 {
248 case ZEBRA_ROUTE_KERNEL:
249 case ZEBRA_ROUTE_CONNECT:
250 case ZEBRA_ROUTE_STATIC:
251 case ZEBRA_ROUTE_RIP:
252 case ZEBRA_ROUTE_RIPNG:
253 case ZEBRA_ROUTE_OSPF:
254 case ZEBRA_ROUTE_OSPF6:
255 case ZEBRA_ROUTE_BGP:
256 if (! client->redist[type])
257 {
258 client->redist[type] = 1;
259 zebra_redistribute (client, type);
260 }
261 break;
262 default:
263 break;
264 }
265}
266
267void
268zebra_redistribute_delete (int command, struct zserv *client, int length)
269{
270 int type;
271
272 type = stream_getc (client->ibuf);
273
274 switch (type)
275 {
276 case ZEBRA_ROUTE_KERNEL:
277 case ZEBRA_ROUTE_CONNECT:
278 case ZEBRA_ROUTE_STATIC:
279 case ZEBRA_ROUTE_RIP:
280 case ZEBRA_ROUTE_RIPNG:
281 case ZEBRA_ROUTE_OSPF:
282 case ZEBRA_ROUTE_OSPF6:
283 case ZEBRA_ROUTE_BGP:
284 client->redist[type] = 0;
285 break;
286 default:
287 break;
288 }
289}
290
291void
292zebra_redistribute_default_add (int command, struct zserv *client, int length)
293{
294 client->redist_default = 1;
295 zebra_redistribute_default (client);
296}
297
298void
299zebra_redistribute_default_delete (int command, struct zserv *client,
300 int length)
301{
302 client->redist_default = 0;;
303}
304
305/* Interface up information. */
306void
307zebra_interface_up_update (struct interface *ifp)
308{
hasso52dc7ee2004-09-23 19:18:23 +0000309 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000310 struct zserv *client;
311
312 if (IS_ZEBRA_DEBUG_EVENT)
ajsb6178002004-12-07 21:12:56 +0000313 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000314
paulb21b19c2003-06-15 01:28:29 +0000315 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000316 if ((client = getdata (node)) != NULL)
paulb9df2d22004-05-09 09:09:59 +0000317 zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp);
paul718e3742002-12-13 20:15:29 +0000318}
319
320/* Interface down information. */
321void
322zebra_interface_down_update (struct interface *ifp)
323{
hasso52dc7ee2004-09-23 19:18:23 +0000324 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000325 struct zserv *client;
326
327 if (IS_ZEBRA_DEBUG_EVENT)
ajsb6178002004-12-07 21:12:56 +0000328 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000329
paulb21b19c2003-06-15 01:28:29 +0000330 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000331 if ((client = getdata (node)) != NULL)
paulb9df2d22004-05-09 09:09:59 +0000332 zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp);
paul718e3742002-12-13 20:15:29 +0000333}
334
335/* Interface information update. */
336void
337zebra_interface_add_update (struct interface *ifp)
338{
hasso52dc7ee2004-09-23 19:18:23 +0000339 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000340 struct zserv *client;
341
342 if (IS_ZEBRA_DEBUG_EVENT)
ajsb6178002004-12-07 21:12:56 +0000343 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADD %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000344
paulb21b19c2003-06-15 01:28:29 +0000345 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000346 if ((client = getdata (node)) != NULL)
347 if (client->ifinfo)
348 zsend_interface_add (client, ifp);
349}
350
paulc50ae8b2004-05-11 11:31:07 +0000351/*
352 * This function is only called when support for
353 * RTM_IFANNOUNCE or AF_NETLINK sockets (RTM_DELLINK message)
354 * is available. It is not called on Solaris.
355 */
356#if (defined(RTM_IFANNOUNCE) || defined(HAVE_NETLINK))
paul718e3742002-12-13 20:15:29 +0000357void
358zebra_interface_delete_update (struct interface *ifp)
359{
hasso52dc7ee2004-09-23 19:18:23 +0000360 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000361 struct zserv *client;
362
363 if (IS_ZEBRA_DEBUG_EVENT)
ajsb6178002004-12-07 21:12:56 +0000364 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000365
paulb21b19c2003-06-15 01:28:29 +0000366 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000367 if ((client = getdata (node)) != NULL)
368 if (client->ifinfo)
369 zsend_interface_delete (client, ifp);
370}
paulc50ae8b2004-05-11 11:31:07 +0000371#endif /* defined(RTM_IFANNOUNCE) || defined(HAVE_NETLINK) */
paul718e3742002-12-13 20:15:29 +0000372
373/* Interface address addition. */
374void
375zebra_interface_address_add_update (struct interface *ifp,
376 struct connected *ifc)
377{
hasso52dc7ee2004-09-23 19:18:23 +0000378 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000379 struct zserv *client;
380 struct prefix *p;
381 char buf[BUFSIZ];
382
383 if (IS_ZEBRA_DEBUG_EVENT)
384 {
385 p = ifc->address;
ajsb6178002004-12-07 21:12:56 +0000386 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s/%d on %s",
387 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
388 p->prefixlen, ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +0000389 }
390
hasso18a6dce2004-10-03 18:18:34 +0000391 router_id_add_address(ifc);
392
paulb21b19c2003-06-15 01:28:29 +0000393 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000394 if ((client = getdata (node)) != NULL)
395 if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
paulb9df2d22004-05-09 09:09:59 +0000396 zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000397}
398
399/* Interface address deletion. */
400void
401zebra_interface_address_delete_update (struct interface *ifp,
402 struct connected *ifc)
403{
hasso52dc7ee2004-09-23 19:18:23 +0000404 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000405 struct zserv *client;
406 struct prefix *p;
407 char buf[BUFSIZ];
408
409 if (IS_ZEBRA_DEBUG_EVENT)
410 {
411 p = ifc->address;
ajsb6178002004-12-07 21:12:56 +0000412 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s/%d on %s",
413 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
paul718e3742002-12-13 20:15:29 +0000414 p->prefixlen, ifc->ifp->name);
415 }
416
hasso18a6dce2004-10-03 18:18:34 +0000417 router_id_del_address(ifc);
418
paulb21b19c2003-06-15 01:28:29 +0000419 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000420 if ((client = getdata (node)) != NULL)
421 if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
paulb9df2d22004-05-09 09:09:59 +0000422 zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000423}