]>
Commit | Line | Data |
---|---|---|
718e3744 | 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" | |
18a6dce6 | 38 | #include "zebra/router-id.h" |
718e3744 | 39 | |
244c1cdc DS |
40 | #define ZEBRA_PTM_SUPPORT |
41 | ||
42 | ||
b21b19c5 | 43 | /* master zebra server structure */ |
44 | extern struct zebra_t zebrad; | |
45 | ||
7a4bb9c5 DS |
46 | /* array holding redistribute info about table redistribution */ |
47 | /* bit AFI is set if that AFI is redistributing routes from this table */ | |
48 | static u_char zebra_import_table_used[ZEBRA_KERNEL_TABLE_MAX]; | |
49 | static u_int32_t zebra_import_table_distance[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; | |
50 | ||
51 | int | |
52 | is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id) | |
53 | { | |
54 | if (is_zebra_valid_kernel_table(table_id)) | |
55 | { | |
56 | if (CHECK_FLAG(zebra_import_table_used[table_id], (u_char)afi)) | |
57 | return 1; | |
58 | else | |
59 | return 0; | |
60 | } | |
61 | ||
62 | return 0; | |
63 | } | |
64 | ||
27da3988 | 65 | static int |
718e3744 | 66 | is_default (struct prefix *p) |
67 | { | |
68 | if (p->family == AF_INET) | |
69 | if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0) | |
70 | return 1; | |
71 | #ifdef HAVE_IPV6 | |
72 | #if 0 /* IPv6 default separation is now pending until protocol daemon | |
73 | can handle that. */ | |
74 | if (p->family == AF_INET6) | |
75 | if (IN6_IS_ADDR_UNSPECIFIED (&p->u.prefix6) && p->prefixlen == 0) | |
76 | return 1; | |
77 | #endif /* 0 */ | |
78 | #endif /* HAVE_IPV6 */ | |
79 | return 0; | |
80 | } | |
81 | ||
27da3988 | 82 | static void |
718e3744 | 83 | zebra_redistribute_default (struct zserv *client) |
84 | { | |
85 | struct prefix_ipv4 p; | |
86 | struct route_table *table; | |
87 | struct route_node *rn; | |
88 | struct rib *newrib; | |
89 | #ifdef HAVE_IPV6 | |
90 | struct prefix_ipv6 p6; | |
91 | #endif /* HAVE_IPV6 */ | |
92 | ||
93 | ||
94 | /* Lookup default route. */ | |
95 | memset (&p, 0, sizeof (struct prefix_ipv4)); | |
96 | p.family = AF_INET; | |
97 | ||
98 | /* Lookup table. */ | |
99 | table = vrf_table (AFI_IP, SAFI_UNICAST, 0); | |
100 | if (table) | |
101 | { | |
102 | rn = route_node_lookup (table, (struct prefix *)&p); | |
103 | if (rn) | |
104 | { | |
9fd92e3c | 105 | RNODE_FOREACH_RIB (rn, newrib) |
718e3744 | 106 | if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) |
107 | && newrib->distance != DISTANCE_INFINITY) | |
b9df2d25 | 108 | zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib); |
718e3744 | 109 | route_unlock_node (rn); |
110 | } | |
111 | } | |
112 | ||
113 | #ifdef HAVE_IPV6 | |
114 | /* Lookup default route. */ | |
115 | memset (&p6, 0, sizeof (struct prefix_ipv6)); | |
116 | p6.family = AF_INET6; | |
117 | ||
118 | /* Lookup table. */ | |
119 | table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); | |
120 | if (table) | |
121 | { | |
122 | rn = route_node_lookup (table, (struct prefix *)&p6); | |
123 | if (rn) | |
124 | { | |
9fd92e3c | 125 | RNODE_FOREACH_RIB (rn, newrib) |
718e3744 | 126 | if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) |
127 | && newrib->distance != DISTANCE_INFINITY) | |
b9df2d25 | 128 | zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib); |
718e3744 | 129 | route_unlock_node (rn); |
130 | } | |
131 | } | |
132 | #endif /* HAVE_IPV6 */ | |
133 | } | |
134 | ||
135 | /* Redistribute routes. */ | |
27da3988 | 136 | static void |
7c8ff89e | 137 | zebra_redistribute (struct zserv *client, int type, u_short instance) |
718e3744 | 138 | { |
139 | struct rib *newrib; | |
140 | struct route_table *table; | |
141 | struct route_node *rn; | |
142 | ||
143 | table = vrf_table (AFI_IP, SAFI_UNICAST, 0); | |
144 | if (table) | |
145 | for (rn = route_top (table); rn; rn = route_next (rn)) | |
9fd92e3c | 146 | RNODE_FOREACH_RIB (rn, newrib) |
718e3744 | 147 | if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) |
7c8ff89e DS |
148 | && newrib->type == type |
149 | && newrib->instance == instance | |
718e3744 | 150 | && newrib->distance != DISTANCE_INFINITY |
151 | && zebra_check_addr (&rn->p)) | |
04b02fda DS |
152 | { |
153 | client->redist_v4_add_cnt++; | |
154 | zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib); | |
155 | } | |
718e3744 | 156 | |
157 | #ifdef HAVE_IPV6 | |
158 | table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); | |
159 | if (table) | |
160 | for (rn = route_top (table); rn; rn = route_next (rn)) | |
9fd92e3c | 161 | RNODE_FOREACH_RIB (rn, newrib) |
718e3744 | 162 | if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) |
7c8ff89e DS |
163 | && newrib->type == type |
164 | && newrib->instance == instance | |
718e3744 | 165 | && newrib->distance != DISTANCE_INFINITY |
166 | && zebra_check_addr (&rn->p)) | |
04b02fda DS |
167 | { |
168 | client->redist_v6_add_cnt++; | |
169 | zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib); | |
170 | } | |
718e3744 | 171 | #endif /* HAVE_IPV6 */ |
172 | } | |
173 | ||
718e3744 | 174 | void |
175 | redistribute_add (struct prefix *p, struct rib *rib) | |
176 | { | |
1eb8ef25 | 177 | struct listnode *node, *nnode; |
718e3744 | 178 | struct zserv *client; |
179 | ||
1eb8ef25 | 180 | for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) |
181 | { | |
182 | if (is_default (p)) | |
183 | { | |
8bb0831e DS |
184 | if ((p->family == AF_INET) && |
185 | (client->redist_default || | |
186 | redist_check_instance(&client->redist[AFI_IP][rib->type], | |
187 | rib->instance))) | |
188 | { | |
189 | client->redist_v4_add_cnt++; | |
190 | zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib); | |
191 | } | |
718e3744 | 192 | #ifdef HAVE_IPV6 |
8bb0831e DS |
193 | if ((p->family == AF_INET6) && |
194 | (client->redist_default || | |
195 | redist_check_instance(&client->redist[AFI_IP6][rib->type], | |
196 | rib->instance))) | |
197 | { | |
198 | client->redist_v6_add_cnt++; | |
199 | zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib); | |
200 | } | |
718e3744 | 201 | #endif /* HAVE_IPV6 */ |
1eb8ef25 | 202 | } |
8bb0831e | 203 | else |
1eb8ef25 | 204 | { |
8bb0831e DS |
205 | if ((p->family == AF_INET) && |
206 | redist_check_instance(&client->redist[AFI_IP][rib->type], | |
207 | rib->instance)) | |
04b02fda DS |
208 | { |
209 | client->redist_v4_add_cnt++; | |
8bb0831e DS |
210 | zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib); |
211 | } | |
718e3744 | 212 | #ifdef HAVE_IPV6 |
8bb0831e DS |
213 | if ((p->family == AF_INET6) && |
214 | redist_check_instance(&client->redist[AFI_IP6][rib->type], | |
215 | rib->instance)) | |
216 | { | |
217 | client->redist_v6_add_cnt++; | |
218 | zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib); | |
219 | } | |
718e3744 | 220 | #endif /* HAVE_IPV6 */ |
1eb8ef25 | 221 | } |
222 | } | |
718e3744 | 223 | } |
224 | ||
225 | void | |
226 | redistribute_delete (struct prefix *p, struct rib *rib) | |
227 | { | |
1eb8ef25 | 228 | struct listnode *node, *nnode; |
718e3744 | 229 | struct zserv *client; |
230 | ||
231 | /* Add DISTANCE_INFINITY check. */ | |
232 | if (rib->distance == DISTANCE_INFINITY) | |
233 | return; | |
234 | ||
1eb8ef25 | 235 | for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) |
236 | { | |
237 | if (is_default (p)) | |
238 | { | |
8bb0831e DS |
239 | if ((p->family == AF_INET) && |
240 | (client->redist_default || | |
241 | redist_check_instance(&client->redist[AFI_IP][rib->type], | |
242 | rib->instance))) | |
243 | zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, | |
1eb8ef25 | 244 | rib); |
718e3744 | 245 | #ifdef HAVE_IPV6 |
8bb0831e DS |
246 | if ((p->family == AF_INET6) && |
247 | (client->redist_default || | |
248 | redist_check_instance(&client->redist[AFI_IP6][rib->type], | |
249 | rib->instance))) | |
250 | zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, | |
1eb8ef25 | 251 | rib); |
252 | #endif /* HAVE_IPV6 */ | |
1eb8ef25 | 253 | } |
8bb0831e DS |
254 | else |
255 | { | |
256 | if ((p->family == AF_INET) && | |
257 | redist_check_instance(&client->redist[AFI_IP][rib->type], | |
258 | rib->instance)) | |
259 | zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, | |
260 | rib); | |
718e3744 | 261 | #ifdef HAVE_IPV6 |
8bb0831e DS |
262 | if ((p->family == AF_INET6) && |
263 | redist_check_instance(&client->redist[AFI_IP6][rib->type], | |
264 | rib->instance)) | |
265 | zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, | |
266 | rib); | |
1eb8ef25 | 267 | #endif /* HAVE_IPV6 */ |
268 | } | |
269 | } | |
718e3744 | 270 | } |
271 | ||
272 | void | |
273 | zebra_redistribute_add (int command, struct zserv *client, int length) | |
274 | { | |
8bb0831e | 275 | afi_t afi; |
718e3744 | 276 | int type; |
7c8ff89e | 277 | u_short instance; |
718e3744 | 278 | |
8bb0831e | 279 | afi = stream_getc (client->ibuf); |
718e3744 | 280 | type = stream_getc (client->ibuf); |
7c8ff89e | 281 | instance = stream_getw (client->ibuf); |
718e3744 | 282 | |
ebf08631 DL |
283 | if (type == 0 || type >= ZEBRA_ROUTE_MAX) |
284 | return; | |
285 | ||
8bb0831e | 286 | if (!redist_check_instance(&client->redist[afi][type], instance)) |
718e3744 | 287 | { |
8bb0831e | 288 | redist_add_instance(&client->redist[afi][type], instance); |
7c8ff89e | 289 | zebra_redistribute (client, type, instance); |
718e3744 | 290 | } |
ebf08631 | 291 | } |
718e3744 | 292 | |
293 | void | |
294 | zebra_redistribute_delete (int command, struct zserv *client, int length) | |
295 | { | |
8bb0831e | 296 | afi_t afi; |
718e3744 | 297 | int type; |
7c8ff89e | 298 | u_short instance; |
718e3744 | 299 | |
8bb0831e | 300 | afi = stream_getc (client->ibuf); |
718e3744 | 301 | type = stream_getc (client->ibuf); |
7c8ff89e | 302 | instance = stream_getw (client->ibuf); |
718e3744 | 303 | |
ebf08631 DL |
304 | if (type == 0 || type >= ZEBRA_ROUTE_MAX) |
305 | return; | |
306 | ||
8bb0831e | 307 | if (redist_check_instance(&client->redist[afi][type], instance)) |
7c8ff89e | 308 | { |
8bb0831e | 309 | redist_del_instance(&client->redist[afi][type], instance); |
7c8ff89e DS |
310 | //Pending: why no reaction here? |
311 | } | |
ebf08631 | 312 | } |
718e3744 | 313 | |
314 | void | |
315 | zebra_redistribute_default_add (int command, struct zserv *client, int length) | |
316 | { | |
317 | client->redist_default = 1; | |
318 | zebra_redistribute_default (client); | |
319 | } | |
320 | ||
321 | void | |
322 | zebra_redistribute_default_delete (int command, struct zserv *client, | |
323 | int length) | |
324 | { | |
325 | client->redist_default = 0;; | |
326 | } | |
327 | ||
328 | /* Interface up information. */ | |
329 | void | |
330 | zebra_interface_up_update (struct interface *ifp) | |
331 | { | |
1eb8ef25 | 332 | struct listnode *node, *nnode; |
718e3744 | 333 | struct zserv *client; |
334 | ||
335 | if (IS_ZEBRA_DEBUG_EVENT) | |
b6178002 | 336 | zlog_debug ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name); |
718e3744 | 337 | |
244c1cdc DS |
338 | if (ifp->ptm_status || !ifp->ptm_enable) { |
339 | for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) | |
04b02fda DS |
340 | { |
341 | zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp); | |
342 | } | |
244c1cdc | 343 | } |
718e3744 | 344 | } |
345 | ||
346 | /* Interface down information. */ | |
347 | void | |
348 | zebra_interface_down_update (struct interface *ifp) | |
349 | { | |
1eb8ef25 | 350 | struct listnode *node, *nnode; |
718e3744 | 351 | struct zserv *client; |
352 | ||
353 | if (IS_ZEBRA_DEBUG_EVENT) | |
b6178002 | 354 | zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name); |
718e3744 | 355 | |
1eb8ef25 | 356 | for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) |
04b02fda DS |
357 | { |
358 | zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp); | |
359 | } | |
718e3744 | 360 | } |
361 | ||
362 | /* Interface information update. */ | |
363 | void | |
364 | zebra_interface_add_update (struct interface *ifp) | |
365 | { | |
1eb8ef25 | 366 | struct listnode *node, *nnode; |
718e3744 | 367 | struct zserv *client; |
368 | ||
369 | if (IS_ZEBRA_DEBUG_EVENT) | |
b6178002 | 370 | zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADD %s", ifp->name); |
718e3744 | 371 | |
1eb8ef25 | 372 | for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) |
373 | if (client->ifinfo) | |
04b02fda DS |
374 | { |
375 | client->ifadd_cnt++; | |
376 | zsend_interface_add (client, ifp); | |
377 | } | |
718e3744 | 378 | } |
379 | ||
380 | void | |
381 | zebra_interface_delete_update (struct interface *ifp) | |
382 | { | |
1eb8ef25 | 383 | struct listnode *node, *nnode; |
718e3744 | 384 | struct zserv *client; |
385 | ||
386 | if (IS_ZEBRA_DEBUG_EVENT) | |
b6178002 | 387 | zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name); |
718e3744 | 388 | |
1eb8ef25 | 389 | for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) |
390 | if (client->ifinfo) | |
04b02fda DS |
391 | { |
392 | client->ifdel_cnt++; | |
393 | zsend_interface_delete (client, ifp); | |
394 | } | |
718e3744 | 395 | } |
396 | ||
397 | /* Interface address addition. */ | |
398 | void | |
399 | zebra_interface_address_add_update (struct interface *ifp, | |
400 | struct connected *ifc) | |
401 | { | |
1eb8ef25 | 402 | struct listnode *node, *nnode; |
718e3744 | 403 | struct zserv *client; |
404 | struct prefix *p; | |
718e3744 | 405 | |
406 | if (IS_ZEBRA_DEBUG_EVENT) | |
407 | { | |
81cce018 SH |
408 | char buf[INET6_ADDRSTRLEN]; |
409 | ||
718e3744 | 410 | p = ifc->address; |
b6178002 | 411 | zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s/%d on %s", |
81cce018 | 412 | inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN), |
b6178002 | 413 | p->prefixlen, ifc->ifp->name); |
718e3744 | 414 | } |
415 | ||
c7df92de CF |
416 | if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) |
417 | zlog_warn("WARNING: advertising address to clients that is not yet usable."); | |
418 | ||
18a6dce6 | 419 | router_id_add_address(ifc); |
420 | ||
1eb8ef25 | 421 | for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) |
422 | if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) | |
04b02fda DS |
423 | { |
424 | client->connected_rt_add_cnt++; | |
425 | zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, ifp, ifc); | |
426 | } | |
718e3744 | 427 | } |
428 | ||
429 | /* Interface address deletion. */ | |
430 | void | |
431 | zebra_interface_address_delete_update (struct interface *ifp, | |
432 | struct connected *ifc) | |
433 | { | |
1eb8ef25 | 434 | struct listnode *node, *nnode; |
718e3744 | 435 | struct zserv *client; |
436 | struct prefix *p; | |
718e3744 | 437 | |
438 | if (IS_ZEBRA_DEBUG_EVENT) | |
439 | { | |
81cce018 SH |
440 | char buf[INET6_ADDRSTRLEN]; |
441 | ||
718e3744 | 442 | p = ifc->address; |
b6178002 | 443 | zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s/%d on %s", |
81cce018 | 444 | inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN), |
718e3744 | 445 | p->prefixlen, ifc->ifp->name); |
446 | } | |
447 | ||
18a6dce6 | 448 | router_id_del_address(ifc); |
449 | ||
1eb8ef25 | 450 | for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) |
451 | if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) | |
04b02fda DS |
452 | { |
453 | client->connected_rt_del_cnt++; | |
454 | zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, ifc); | |
455 | } | |
718e3744 | 456 | } |
d5a5c8f0 | 457 | |
7a4bb9c5 DS |
458 | int |
459 | zebra_add_import_table_entry (struct route_node *rn, struct rib *rib) | |
460 | { | |
461 | struct rib *newrib; | |
462 | struct prefix_ipv4 p4; | |
463 | struct nexthop *nhop; | |
464 | struct in_addr *gate; | |
465 | ||
466 | if (rn->p.family == AF_INET) | |
467 | { | |
468 | p4.family = AF_INET; | |
469 | p4.prefixlen = rn->p.prefixlen; | |
470 | p4.prefix = rn->p.u.prefix4; | |
471 | ||
472 | if (rib->nexthop_num == 1) | |
473 | { | |
474 | nhop = rib->nexthop; | |
475 | if ((nhop->type == NEXTHOP_TYPE_IFINDEX) || | |
476 | (nhop->type == NEXTHOP_TYPE_IFNAME)) | |
477 | gate = NULL; | |
478 | else | |
479 | gate = &nhop->gate.ipv4; | |
480 | ||
481 | rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4, | |
482 | gate, &nhop->src.ipv4, | |
483 | nhop->ifindex, zebrad.rtm_table_default, | |
484 | rib->metric, | |
485 | zebra_import_table_distance[AFI_IP][rib->table], | |
486 | SAFI_UNICAST); | |
487 | } | |
488 | else if (rib->nexthop_num > 1) | |
489 | { | |
490 | newrib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); | |
491 | newrib->type = ZEBRA_ROUTE_TABLE; | |
492 | newrib->distance = zebra_import_table_distance[AFI_IP][rib->table]; | |
493 | newrib->flags = rib->flags; | |
494 | newrib->metric = rib->metric; | |
495 | newrib->table = zebrad.rtm_table_default; | |
496 | newrib->nexthop_num = 0; | |
497 | newrib->uptime = time(NULL); | |
498 | newrib->instance = rib->table; | |
499 | ||
500 | /* Assuming these routes are never recursive */ | |
501 | for (nhop = rib->nexthop; nhop; nhop = nhop->next) | |
502 | copy_nexthops(newrib, nhop); | |
503 | ||
504 | rib_add_ipv4_multipath(&p4, newrib, SAFI_UNICAST); | |
505 | } | |
506 | } | |
507 | /* DD: Add IPv6 code */ | |
508 | return 0; | |
509 | } | |
510 | ||
511 | int | |
512 | zebra_del_import_table_entry (struct route_node *rn, struct rib *rib) | |
513 | { | |
514 | struct prefix_ipv4 p4; | |
515 | ||
516 | if (rn->p.family == AF_INET) | |
517 | { | |
518 | p4.family = AF_INET; | |
519 | p4.prefixlen = rn->p.prefixlen; | |
520 | p4.prefix = rn->p.u.prefix4; | |
521 | ||
522 | rib_delete_ipv4(ZEBRA_ROUTE_TABLE, rib->table, rib->flags, &p4, NULL, | |
523 | 0, zebrad.rtm_table_default, SAFI_UNICAST); | |
524 | } | |
525 | /* DD: Add IPv6 code */ | |
526 | ||
527 | return 0; | |
528 | } | |
529 | ||
530 | /* Assuming no one calls this with the main routing table */ | |
531 | int | |
532 | zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, int add) | |
533 | { | |
534 | struct route_table *table; | |
535 | struct rib *rib; | |
536 | struct route_node *rn; | |
537 | ||
538 | if (!is_zebra_valid_kernel_table(table_id) || | |
539 | ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default))) | |
540 | return (-1); | |
541 | ||
542 | if (afi >= AFI_MAX) | |
543 | return (-1); | |
544 | ||
545 | table = vrf_other_route_table(afi, table_id, 0); | |
546 | if (table == NULL) | |
547 | { | |
548 | return 0; | |
549 | } | |
550 | else if (IS_ZEBRA_DEBUG_RIB) | |
551 | { | |
552 | zlog_debug ("%s routes from table %d", | |
553 | add ? "Importing" : "Unimporting", table_id); | |
554 | } | |
555 | ||
556 | if (add) | |
557 | { | |
558 | SET_FLAG(zebra_import_table_used[table_id], afi); | |
559 | zebra_import_table_distance[afi][table_id] = distance; | |
560 | } | |
561 | else | |
562 | { | |
563 | UNSET_FLAG(zebra_import_table_used[table_id], (u_char)afi); | |
564 | zebra_import_table_distance[afi][table_id] = ZEBRA_TABLE_DISTANCE_DEFAULT; | |
565 | } | |
566 | ||
567 | for (rn = route_top(table); rn; rn = route_next(rn)) | |
568 | { | |
569 | /* For each entry in the non-default routing table, | |
570 | * add the entry in the main table | |
571 | */ | |
572 | if (!rn->info) | |
573 | continue; | |
574 | ||
575 | RNODE_FOREACH_RIB (rn, rib) | |
576 | { | |
577 | if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) | |
578 | continue; | |
579 | break; | |
580 | } | |
581 | ||
582 | if (!rib) | |
583 | continue; | |
584 | ||
4e3afb14 DS |
585 | if (((afi == AFI_IP) && (rn->p.family == AF_INET)) || |
586 | ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) | |
7a4bb9c5 DS |
587 | { |
588 | if (add) | |
589 | zebra_add_import_table_entry (rn, rib); | |
590 | else | |
591 | zebra_del_import_table_entry (rn, rib); | |
592 | } | |
593 | } | |
594 | return 0; | |
595 | } | |
596 | ||
597 | int | |
598 | zebra_import_table_config (struct vty *vty) | |
599 | { | |
600 | int i; | |
601 | afi_t afi; | |
602 | int write = 0; | |
603 | char afi_str[AFI_MAX][6] = {"", "ip", "ipv6"}; | |
604 | ||
605 | for (afi = AFI_IP; afi < AFI_MAX; afi++) | |
606 | { | |
607 | for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) | |
608 | { | |
609 | if (is_zebra_import_table_enabled(afi, i)) | |
610 | { | |
611 | if (zebra_import_table_distance[afi][i] != ZEBRA_TABLE_DISTANCE_DEFAULT) | |
612 | { | |
613 | vty_out(vty, "%s import-table %d distance %d%s", afi_str[afi], | |
614 | i, zebra_import_table_distance[afi][i], VTY_NEWLINE); | |
615 | } | |
616 | else | |
617 | { | |
618 | vty_out(vty, "%s import-table %d%s", afi_str[afi], i, | |
619 | VTY_NEWLINE); | |
620 | } | |
621 | write = 1; | |
622 | } | |
623 | } | |
624 | } | |
625 | ||
626 | return write; | |
627 | } |