blob: ae61a4488edeae6f5828e23b83f9926be2f66438 [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"
38
paulb21b19c2003-06-15 01:28:29 +000039/* master zebra server structure */
40extern struct zebra_t zebrad;
41
paul718e3742002-12-13 20:15:29 +000042int
43zebra_check_addr (struct prefix *p)
44{
45 if (p->family == AF_INET)
46 {
47 u_int32_t addr;
48
49 addr = p->u.prefix4.s_addr;
50 addr = ntohl (addr);
51
52 if (IPV4_NET127 (addr) || IN_CLASSD (addr))
53 return 0;
54 }
55#ifdef HAVE_IPV6
56 if (p->family == AF_INET6)
57 {
58 if (IN6_IS_ADDR_LOOPBACK (&p->u.prefix6))
59 return 0;
60 if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
61 return 0;
62 }
63#endif /* HAVE_IPV6 */
64 return 1;
65}
66
67int
68is_default (struct prefix *p)
69{
70 if (p->family == AF_INET)
71 if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0)
72 return 1;
73#ifdef HAVE_IPV6
74#if 0 /* IPv6 default separation is now pending until protocol daemon
75 can handle that. */
76 if (p->family == AF_INET6)
77 if (IN6_IS_ADDR_UNSPECIFIED (&p->u.prefix6) && p->prefixlen == 0)
78 return 1;
79#endif /* 0 */
80#endif /* HAVE_IPV6 */
81 return 0;
82}
83
84void
85zebra_redistribute_default (struct zserv *client)
86{
87 struct prefix_ipv4 p;
88 struct route_table *table;
89 struct route_node *rn;
90 struct rib *newrib;
91#ifdef HAVE_IPV6
92 struct prefix_ipv6 p6;
93#endif /* HAVE_IPV6 */
94
95
96 /* Lookup default route. */
97 memset (&p, 0, sizeof (struct prefix_ipv4));
98 p.family = AF_INET;
99
100 /* Lookup table. */
101 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
102 if (table)
103 {
104 rn = route_node_lookup (table, (struct prefix *)&p);
105 if (rn)
106 {
107 for (newrib = rn->info; newrib; newrib = newrib->next)
108 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
109 && newrib->distance != DISTANCE_INFINITY)
paulb9df2d22004-05-09 09:09:59 +0000110 zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib);
paul718e3742002-12-13 20:15:29 +0000111 route_unlock_node (rn);
112 }
113 }
114
115#ifdef HAVE_IPV6
116 /* Lookup default route. */
117 memset (&p6, 0, sizeof (struct prefix_ipv6));
118 p6.family = AF_INET6;
119
120 /* Lookup table. */
121 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
122 if (table)
123 {
124 rn = route_node_lookup (table, (struct prefix *)&p6);
125 if (rn)
126 {
127 for (newrib = rn->info; newrib; newrib = newrib->next)
128 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
129 && newrib->distance != DISTANCE_INFINITY)
paulb9df2d22004-05-09 09:09:59 +0000130 zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib);
paul718e3742002-12-13 20:15:29 +0000131 route_unlock_node (rn);
132 }
133 }
134#endif /* HAVE_IPV6 */
135}
136
137/* Redistribute routes. */
138void
139zebra_redistribute (struct zserv *client, int type)
140{
141 struct rib *newrib;
142 struct route_table *table;
143 struct route_node *rn;
144
145 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
146 if (table)
147 for (rn = route_top (table); rn; rn = route_next (rn))
148 for (newrib = rn->info; newrib; newrib = newrib->next)
149 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
150 && newrib->type == type
151 && newrib->distance != DISTANCE_INFINITY
152 && zebra_check_addr (&rn->p))
paulb9df2d22004-05-09 09:09:59 +0000153 zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib);
paul718e3742002-12-13 20:15:29 +0000154
155#ifdef HAVE_IPV6
156 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
157 if (table)
158 for (rn = route_top (table); rn; rn = route_next (rn))
159 for (newrib = rn->info; newrib; newrib = newrib->next)
160 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
161 && newrib->type == type
162 && newrib->distance != DISTANCE_INFINITY
163 && zebra_check_addr (&rn->p))
paulb9df2d22004-05-09 09:09:59 +0000164 zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib);
paul718e3742002-12-13 20:15:29 +0000165#endif /* HAVE_IPV6 */
166}
167
paul718e3742002-12-13 20:15:29 +0000168void
169redistribute_add (struct prefix *p, struct rib *rib)
170{
171 listnode node;
172 struct zserv *client;
173
paulb21b19c2003-06-15 01:28:29 +0000174 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000175 if ((client = getdata (node)) != NULL)
176 {
177 if (is_default (p))
178 {
179 if (client->redist_default || client->redist[rib->type])
180 {
181 if (p->family == AF_INET)
paulb9df2d22004-05-09 09:09:59 +0000182 zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000183#ifdef HAVE_IPV6
184 if (p->family == AF_INET6)
paulb9df2d22004-05-09 09:09:59 +0000185 zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000186#endif /* HAVE_IPV6 */
187 }
188 }
189 else if (client->redist[rib->type])
190 {
191 if (p->family == AF_INET)
paulb9df2d22004-05-09 09:09:59 +0000192 zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000193#ifdef HAVE_IPV6
194 if (p->family == AF_INET6)
paulb9df2d22004-05-09 09:09:59 +0000195 zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000196#endif /* HAVE_IPV6 */
197 }
198 }
199}
200
201void
202redistribute_delete (struct prefix *p, struct rib *rib)
203{
204 listnode node;
205 struct zserv *client;
206
207 /* Add DISTANCE_INFINITY check. */
208 if (rib->distance == DISTANCE_INFINITY)
209 return;
210
paulb21b19c2003-06-15 01:28:29 +0000211 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000212 if ((client = getdata (node)) != NULL)
213 {
214 if (is_default (p))
215 {
216 if (client->redist_default || client->redist[rib->type])
217 {
218 if (p->family == AF_INET)
paulb9df2d22004-05-09 09:09:59 +0000219 zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000220#ifdef HAVE_IPV6
221 if (p->family == AF_INET6)
paulb9df2d22004-05-09 09:09:59 +0000222 zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000223#endif /* HAVE_IPV6 */
224 }
225 }
226 else if (client->redist[rib->type])
227 {
228 if (p->family == AF_INET)
paulb9df2d22004-05-09 09:09:59 +0000229 zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000230#ifdef HAVE_IPV6
231 if (p->family == AF_INET6)
paulb9df2d22004-05-09 09:09:59 +0000232 zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, rib);
paul718e3742002-12-13 20:15:29 +0000233#endif /* HAVE_IPV6 */
234 }
235 }
236}
237
238void
239zebra_redistribute_add (int command, struct zserv *client, int length)
240{
241 int type;
242
243 type = stream_getc (client->ibuf);
244
245 switch (type)
246 {
247 case ZEBRA_ROUTE_KERNEL:
248 case ZEBRA_ROUTE_CONNECT:
249 case ZEBRA_ROUTE_STATIC:
250 case ZEBRA_ROUTE_RIP:
251 case ZEBRA_ROUTE_RIPNG:
252 case ZEBRA_ROUTE_OSPF:
253 case ZEBRA_ROUTE_OSPF6:
254 case ZEBRA_ROUTE_BGP:
255 if (! client->redist[type])
256 {
257 client->redist[type] = 1;
258 zebra_redistribute (client, type);
259 }
260 break;
261 default:
262 break;
263 }
264}
265
266void
267zebra_redistribute_delete (int command, struct zserv *client, int length)
268{
269 int type;
270
271 type = stream_getc (client->ibuf);
272
273 switch (type)
274 {
275 case ZEBRA_ROUTE_KERNEL:
276 case ZEBRA_ROUTE_CONNECT:
277 case ZEBRA_ROUTE_STATIC:
278 case ZEBRA_ROUTE_RIP:
279 case ZEBRA_ROUTE_RIPNG:
280 case ZEBRA_ROUTE_OSPF:
281 case ZEBRA_ROUTE_OSPF6:
282 case ZEBRA_ROUTE_BGP:
283 client->redist[type] = 0;
284 break;
285 default:
286 break;
287 }
288}
289
290void
291zebra_redistribute_default_add (int command, struct zserv *client, int length)
292{
293 client->redist_default = 1;
294 zebra_redistribute_default (client);
295}
296
297void
298zebra_redistribute_default_delete (int command, struct zserv *client,
299 int length)
300{
301 client->redist_default = 0;;
302}
303
304/* Interface up information. */
305void
306zebra_interface_up_update (struct interface *ifp)
307{
308 listnode node;
309 struct zserv *client;
310
311 if (IS_ZEBRA_DEBUG_EVENT)
312 zlog_info ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name);
313
paulb21b19c2003-06-15 01:28:29 +0000314 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000315 if ((client = getdata (node)) != NULL)
paulb9df2d22004-05-09 09:09:59 +0000316 zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp);
paul718e3742002-12-13 20:15:29 +0000317}
318
319/* Interface down information. */
320void
321zebra_interface_down_update (struct interface *ifp)
322{
323 listnode node;
324 struct zserv *client;
325
326 if (IS_ZEBRA_DEBUG_EVENT)
327 zlog_info ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name);
328
paulb21b19c2003-06-15 01:28:29 +0000329 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000330 if ((client = getdata (node)) != NULL)
paulb9df2d22004-05-09 09:09:59 +0000331 zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp);
paul718e3742002-12-13 20:15:29 +0000332}
333
334/* Interface information update. */
335void
336zebra_interface_add_update (struct interface *ifp)
337{
338 listnode node;
339 struct zserv *client;
340
341 if (IS_ZEBRA_DEBUG_EVENT)
342 zlog_info ("MESSAGE: ZEBRA_INTERFACE_ADD %s", ifp->name);
343
paulb21b19c2003-06-15 01:28:29 +0000344 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000345 if ((client = getdata (node)) != NULL)
346 if (client->ifinfo)
347 zsend_interface_add (client, ifp);
348}
349
350void
351zebra_interface_delete_update (struct interface *ifp)
352{
353 listnode node;
354 struct zserv *client;
355
356 if (IS_ZEBRA_DEBUG_EVENT)
357 zlog_info ("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name);
358
paulb21b19c2003-06-15 01:28:29 +0000359 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000360 if ((client = getdata (node)) != NULL)
361 if (client->ifinfo)
362 zsend_interface_delete (client, ifp);
363}
364
365/* Interface address addition. */
366void
367zebra_interface_address_add_update (struct interface *ifp,
368 struct connected *ifc)
369{
370 listnode node;
371 struct zserv *client;
372 struct prefix *p;
373 char buf[BUFSIZ];
374
375 if (IS_ZEBRA_DEBUG_EVENT)
376 {
377 p = ifc->address;
378 zlog_info ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s/%d on %s",
379 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
380 p->prefixlen, ifc->ifp->name);
381 }
382
paulb21b19c2003-06-15 01:28:29 +0000383 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000384 if ((client = getdata (node)) != NULL)
385 if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
paulb9df2d22004-05-09 09:09:59 +0000386 zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000387}
388
389/* Interface address deletion. */
390void
391zebra_interface_address_delete_update (struct interface *ifp,
392 struct connected *ifc)
393{
394 listnode node;
395 struct zserv *client;
396 struct prefix *p;
397 char buf[BUFSIZ];
398
399 if (IS_ZEBRA_DEBUG_EVENT)
400 {
401 p = ifc->address;
402 zlog_info ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s/%d on %s",
403 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
404 p->prefixlen, ifc->ifp->name);
405 }
406
paulb21b19c2003-06-15 01:28:29 +0000407 for (node = listhead (zebrad.client_list); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000408 if ((client = getdata (node)) != NULL)
409 if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
paulb9df2d22004-05-09 09:09:59 +0000410 zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000411}