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