]> git.proxmox.com Git - mirror_frr.git/blob - zebra/redistribute.c
Initial revision
[mirror_frr.git] / zebra / redistribute.c
1 /* 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
39 int
40 zebra_check_addr (struct prefix *p)
41 {
42 if (p->family == AF_INET)
43 {
44 u_int32_t addr;
45
46 addr = p->u.prefix4.s_addr;
47 addr = ntohl (addr);
48
49 if (IPV4_NET127 (addr) || IN_CLASSD (addr))
50 return 0;
51 }
52 #ifdef HAVE_IPV6
53 if (p->family == AF_INET6)
54 {
55 if (IN6_IS_ADDR_LOOPBACK (&p->u.prefix6))
56 return 0;
57 if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
58 return 0;
59 }
60 #endif /* HAVE_IPV6 */
61 return 1;
62 }
63
64 int
65 is_default (struct prefix *p)
66 {
67 if (p->family == AF_INET)
68 if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0)
69 return 1;
70 #ifdef HAVE_IPV6
71 #if 0 /* IPv6 default separation is now pending until protocol daemon
72 can handle that. */
73 if (p->family == AF_INET6)
74 if (IN6_IS_ADDR_UNSPECIFIED (&p->u.prefix6) && p->prefixlen == 0)
75 return 1;
76 #endif /* 0 */
77 #endif /* HAVE_IPV6 */
78 return 0;
79 }
80
81 void
82 zebra_redistribute_default (struct zserv *client)
83 {
84 struct prefix_ipv4 p;
85 struct route_table *table;
86 struct route_node *rn;
87 struct rib *newrib;
88 #ifdef HAVE_IPV6
89 struct prefix_ipv6 p6;
90 #endif /* HAVE_IPV6 */
91
92
93 /* Lookup default route. */
94 memset (&p, 0, sizeof (struct prefix_ipv4));
95 p.family = AF_INET;
96
97 /* Lookup table. */
98 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
99 if (table)
100 {
101 rn = route_node_lookup (table, (struct prefix *)&p);
102 if (rn)
103 {
104 for (newrib = rn->info; newrib; newrib = newrib->next)
105 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
106 && newrib->distance != DISTANCE_INFINITY)
107 zsend_ipv4_add_multipath (client, &rn->p, newrib);
108 route_unlock_node (rn);
109 }
110 }
111
112 #ifdef HAVE_IPV6
113 /* Lookup default route. */
114 memset (&p6, 0, sizeof (struct prefix_ipv6));
115 p6.family = AF_INET6;
116
117 /* Lookup table. */
118 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
119 if (table)
120 {
121 rn = route_node_lookup (table, (struct prefix *)&p6);
122 if (rn)
123 {
124 for (newrib = rn->info; newrib; newrib = newrib->next)
125 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
126 && newrib->distance != DISTANCE_INFINITY)
127 zsend_ipv6_add_multipath (client, &rn->p, newrib);
128 route_unlock_node (rn);
129 }
130 }
131 #endif /* HAVE_IPV6 */
132 }
133
134 /* Redistribute routes. */
135 void
136 zebra_redistribute (struct zserv *client, int type)
137 {
138 struct rib *newrib;
139 struct route_table *table;
140 struct route_node *rn;
141
142 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
143 if (table)
144 for (rn = route_top (table); rn; rn = route_next (rn))
145 for (newrib = rn->info; newrib; newrib = newrib->next)
146 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
147 && newrib->type == type
148 && newrib->distance != DISTANCE_INFINITY
149 && zebra_check_addr (&rn->p))
150 zsend_ipv4_add_multipath (client, &rn->p, newrib);
151
152 #ifdef HAVE_IPV6
153 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
154 if (table)
155 for (rn = route_top (table); rn; rn = route_next (rn))
156 for (newrib = rn->info; newrib; newrib = newrib->next)
157 if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
158 && newrib->type == type
159 && newrib->distance != DISTANCE_INFINITY
160 && zebra_check_addr (&rn->p))
161 zsend_ipv6_add_multipath (client, &rn->p, newrib);
162 #endif /* HAVE_IPV6 */
163 }
164
165 extern list client_list;
166
167 void
168 redistribute_add (struct prefix *p, struct rib *rib)
169 {
170 listnode node;
171 struct zserv *client;
172
173 for (node = listhead (client_list); node; nextnode (node))
174 if ((client = getdata (node)) != NULL)
175 {
176 if (is_default (p))
177 {
178 if (client->redist_default || client->redist[rib->type])
179 {
180 if (p->family == AF_INET)
181 zsend_ipv4_add_multipath (client, p, rib);
182 #ifdef HAVE_IPV6
183 if (p->family == AF_INET6)
184 zsend_ipv6_add_multipath (client, p, rib);
185 #endif /* HAVE_IPV6 */
186 }
187 }
188 else if (client->redist[rib->type])
189 {
190 if (p->family == AF_INET)
191 zsend_ipv4_add_multipath (client, p, rib);
192 #ifdef HAVE_IPV6
193 if (p->family == AF_INET6)
194 zsend_ipv6_add_multipath (client, p, rib);
195 #endif /* HAVE_IPV6 */
196 }
197 }
198 }
199
200 void
201 redistribute_delete (struct prefix *p, struct rib *rib)
202 {
203 listnode node;
204 struct zserv *client;
205
206 /* Add DISTANCE_INFINITY check. */
207 if (rib->distance == DISTANCE_INFINITY)
208 return;
209
210 for (node = listhead (client_list); node; nextnode (node))
211 if ((client = getdata (node)) != NULL)
212 {
213 if (is_default (p))
214 {
215 if (client->redist_default || client->redist[rib->type])
216 {
217 if (p->family == AF_INET)
218 zsend_ipv4_delete_multipath (client, p, rib);
219 #ifdef HAVE_IPV6
220 if (p->family == AF_INET6)
221 zsend_ipv6_delete_multipath (client, p, rib);
222 #endif /* HAVE_IPV6 */
223 }
224 }
225 else if (client->redist[rib->type])
226 {
227 if (p->family == AF_INET)
228 zsend_ipv4_delete_multipath (client, p, rib);
229 #ifdef HAVE_IPV6
230 if (p->family == AF_INET6)
231 zsend_ipv6_delete_multipath (client, p, rib);
232 #endif /* HAVE_IPV6 */
233 }
234 }
235 }
236
237 void
238 zebra_redistribute_add (int command, struct zserv *client, int length)
239 {
240 int type;
241
242 type = stream_getc (client->ibuf);
243
244 switch (type)
245 {
246 case ZEBRA_ROUTE_KERNEL:
247 case ZEBRA_ROUTE_CONNECT:
248 case ZEBRA_ROUTE_STATIC:
249 case ZEBRA_ROUTE_RIP:
250 case ZEBRA_ROUTE_RIPNG:
251 case ZEBRA_ROUTE_OSPF:
252 case ZEBRA_ROUTE_OSPF6:
253 case ZEBRA_ROUTE_BGP:
254 if (! client->redist[type])
255 {
256 client->redist[type] = 1;
257 zebra_redistribute (client, type);
258 }
259 break;
260 default:
261 break;
262 }
263 }
264
265 void
266 zebra_redistribute_delete (int command, struct zserv *client, int length)
267 {
268 int type;
269
270 type = stream_getc (client->ibuf);
271
272 switch (type)
273 {
274 case ZEBRA_ROUTE_KERNEL:
275 case ZEBRA_ROUTE_CONNECT:
276 case ZEBRA_ROUTE_STATIC:
277 case ZEBRA_ROUTE_RIP:
278 case ZEBRA_ROUTE_RIPNG:
279 case ZEBRA_ROUTE_OSPF:
280 case ZEBRA_ROUTE_OSPF6:
281 case ZEBRA_ROUTE_BGP:
282 client->redist[type] = 0;
283 break;
284 default:
285 break;
286 }
287 }
288
289 void
290 zebra_redistribute_default_add (int command, struct zserv *client, int length)
291 {
292 client->redist_default = 1;
293 zebra_redistribute_default (client);
294 }
295
296 void
297 zebra_redistribute_default_delete (int command, struct zserv *client,
298 int length)
299 {
300 client->redist_default = 0;;
301 }
302
303 /* Interface up information. */
304 void
305 zebra_interface_up_update (struct interface *ifp)
306 {
307 listnode node;
308 struct zserv *client;
309
310 if (IS_ZEBRA_DEBUG_EVENT)
311 zlog_info ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name);
312
313 for (node = listhead (client_list); node; nextnode (node))
314 if ((client = getdata (node)) != NULL)
315 zsend_interface_up (client, ifp);
316 }
317
318 /* Interface down information. */
319 void
320 zebra_interface_down_update (struct interface *ifp)
321 {
322 listnode node;
323 struct zserv *client;
324
325 if (IS_ZEBRA_DEBUG_EVENT)
326 zlog_info ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name);
327
328 for (node = listhead (client_list); node; nextnode (node))
329 if ((client = getdata (node)) != NULL)
330 zsend_interface_down (client, ifp);
331 }
332
333 /* Interface information update. */
334 void
335 zebra_interface_add_update (struct interface *ifp)
336 {
337 listnode node;
338 struct zserv *client;
339
340 if (IS_ZEBRA_DEBUG_EVENT)
341 zlog_info ("MESSAGE: ZEBRA_INTERFACE_ADD %s", ifp->name);
342
343 for (node = listhead (client_list); node; nextnode (node))
344 if ((client = getdata (node)) != NULL)
345 if (client->ifinfo)
346 zsend_interface_add (client, ifp);
347 }
348
349 void
350 zebra_interface_delete_update (struct interface *ifp)
351 {
352 listnode node;
353 struct zserv *client;
354
355 if (IS_ZEBRA_DEBUG_EVENT)
356 zlog_info ("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name);
357
358 for (node = listhead (client_list); node; nextnode (node))
359 if ((client = getdata (node)) != NULL)
360 if (client->ifinfo)
361 zsend_interface_delete (client, ifp);
362 }
363
364 /* Interface address addition. */
365 void
366 zebra_interface_address_add_update (struct interface *ifp,
367 struct connected *ifc)
368 {
369 listnode node;
370 struct zserv *client;
371 struct prefix *p;
372 char buf[BUFSIZ];
373
374 if (IS_ZEBRA_DEBUG_EVENT)
375 {
376 p = ifc->address;
377 zlog_info ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s/%d on %s",
378 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
379 p->prefixlen, ifc->ifp->name);
380 }
381
382 for (node = listhead (client_list); node; nextnode (node))
383 if ((client = getdata (node)) != NULL)
384 if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
385 zsend_interface_address_add (client, ifp, ifc);
386 }
387
388 /* Interface address deletion. */
389 void
390 zebra_interface_address_delete_update (struct interface *ifp,
391 struct connected *ifc)
392 {
393 listnode node;
394 struct zserv *client;
395 struct prefix *p;
396 char buf[BUFSIZ];
397
398 if (IS_ZEBRA_DEBUG_EVENT)
399 {
400 p = ifc->address;
401 zlog_info ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s/%d on %s",
402 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
403 p->prefixlen, ifc->ifp->name);
404 }
405
406 for (node = listhead (client_list); node; nextnode (node))
407 if ((client = getdata (node)) != NULL)
408 if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
409 zsend_interface_address_delete (client, ifp, ifc);
410 }