]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_routes.c
Merge pull request #11721 from donaldsharp/build_checks
[mirror_frr.git] / staticd / static_routes.c
1 /*
2 * STATICd - route code
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * This program 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 Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include <zebra.h>
21
22 #include <lib/nexthop.h>
23 #include <lib/memory.h>
24 #include <lib/srcdest_table.h>
25 #include <lib/if.h>
26 #include <lib/vty.h>
27 #include <lib/vrf.h>
28 #include <lib/memory.h>
29
30 #include "printfrr.h"
31
32 #include "static_vrf.h"
33 #include "static_routes.h"
34 #include "static_zebra.h"
35 #include "static_debug.h"
36
37 DEFINE_MGROUP(STATIC, "staticd");
38
39 DEFINE_MTYPE_STATIC(STATIC, STATIC_ROUTE, "Static Route Info");
40 DEFINE_MTYPE_STATIC(STATIC, STATIC_PATH, "Static Path");
41 DEFINE_MTYPE_STATIC(STATIC, STATIC_NEXTHOP, "Static Nexthop");
42
43 void zebra_stable_node_cleanup(struct route_table *table,
44 struct route_node *node)
45 {
46 struct static_nexthop *nh;
47 struct static_path *pn;
48 struct static_route_info *si;
49 struct route_table *src_table;
50 struct route_node *src_node;
51 struct static_path *src_pn;
52 struct static_route_info *src_si;
53
54 si = node->info;
55
56 if (si) {
57 frr_each_safe(static_path_list, &si->path_list, pn) {
58 frr_each_safe(static_nexthop_list, &pn->nexthop_list,
59 nh) {
60 static_nexthop_list_del(&pn->nexthop_list, nh);
61 XFREE(MTYPE_STATIC_NEXTHOP, nh);
62 }
63 static_path_list_del(&si->path_list, pn);
64 XFREE(MTYPE_STATIC_PATH, pn);
65 }
66
67 /* clean up for dst table */
68 src_table = srcdest_srcnode_table(node);
69 if (src_table) {
70 /* This means the route_node is part of the top
71 * hierarchy and refers to a destination prefix.
72 */
73 for (src_node = route_top(src_table); src_node;
74 src_node = route_next(src_node)) {
75 src_si = src_node->info;
76
77 frr_each_safe(static_path_list,
78 &src_si->path_list, src_pn) {
79 frr_each_safe(static_nexthop_list,
80 &src_pn->nexthop_list,
81 nh) {
82 static_nexthop_list_del(
83 &src_pn->nexthop_list,
84 nh);
85 XFREE(MTYPE_STATIC_NEXTHOP, nh);
86 }
87 static_path_list_del(&src_si->path_list,
88 src_pn);
89 XFREE(MTYPE_STATIC_PATH, src_pn);
90 }
91
92 XFREE(MTYPE_STATIC_ROUTE, src_node->info);
93 }
94 }
95
96 XFREE(MTYPE_STATIC_ROUTE, node->info);
97 }
98 }
99
100 /* Install static path into rib. */
101 void static_install_path(struct static_path *pn)
102 {
103 struct static_nexthop *nh;
104
105 frr_each(static_nexthop_list, &pn->nexthop_list, nh)
106 static_zebra_nht_register(nh, true);
107
108 if (static_nexthop_list_count(&pn->nexthop_list))
109 static_zebra_route_add(pn, true);
110 }
111
112 /* Uninstall static path from RIB. */
113 static void static_uninstall_path(struct static_path *pn)
114 {
115 if (static_nexthop_list_count(&pn->nexthop_list))
116 static_zebra_route_add(pn, true);
117 else
118 static_zebra_route_add(pn, false);
119 }
120
121 struct route_node *static_add_route(afi_t afi, safi_t safi, struct prefix *p,
122 struct prefix_ipv6 *src_p,
123 struct static_vrf *svrf)
124 {
125 struct route_node *rn;
126 struct static_route_info *si;
127 struct route_table *stable = svrf->stable[afi][safi];
128
129 assert(stable);
130
131 /* Lookup static route prefix. */
132 rn = srcdest_rnode_get(stable, p, src_p);
133
134 si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route_info));
135
136 si->svrf = svrf;
137 si->safi = safi;
138 static_path_list_init(&(si->path_list));
139
140 rn->info = si;
141
142 return rn;
143 }
144
145 /* To delete the srcnodes */
146 static void static_del_src_route(struct route_node *rn)
147 {
148 struct static_path *pn;
149 struct static_route_info *si;
150
151 si = rn->info;
152
153 frr_each_safe(static_path_list, &si->path_list, pn) {
154 static_del_path(pn);
155 }
156
157 XFREE(MTYPE_STATIC_ROUTE, rn->info);
158 route_unlock_node(rn);
159 }
160
161 void static_del_route(struct route_node *rn)
162 {
163 struct static_path *pn;
164 struct static_route_info *si;
165 struct route_table *src_table;
166 struct route_node *src_node;
167
168 si = rn->info;
169
170 frr_each_safe(static_path_list, &si->path_list, pn) {
171 static_del_path(pn);
172 }
173
174 /* clean up for dst table */
175 src_table = srcdest_srcnode_table(rn);
176 if (src_table) {
177 /* This means the route_node is part of the top hierarchy
178 * and refers to a destination prefix.
179 */
180 for (src_node = route_top(src_table); src_node;
181 src_node = route_next(src_node)) {
182 static_del_src_route(src_node);
183 }
184 }
185 XFREE(MTYPE_STATIC_ROUTE, rn->info);
186 route_unlock_node(rn);
187 }
188
189 bool static_add_nexthop_validate(const char *nh_vrf_name,
190 enum static_nh_type type,
191 struct ipaddr *ipaddr)
192 {
193 struct vrf *vrf;
194
195 vrf = vrf_lookup_by_name(nh_vrf_name);
196 if (!vrf)
197 return true;
198
199 switch (type) {
200 case STATIC_IPV4_GATEWAY:
201 case STATIC_IPV4_GATEWAY_IFNAME:
202 if (if_address_is_local(&ipaddr->ipaddr_v4, AF_INET,
203 vrf->vrf_id))
204 return false;
205 break;
206 case STATIC_IPV6_GATEWAY:
207 case STATIC_IPV6_GATEWAY_IFNAME:
208 if (if_address_is_local(&ipaddr->ipaddr_v6, AF_INET6,
209 vrf->vrf_id))
210 return false;
211 break;
212 default:
213 break;
214 }
215
216 return true;
217 }
218
219 struct static_path *static_add_path(struct route_node *rn, uint32_t table_id,
220 uint8_t distance)
221 {
222 struct static_path *pn;
223 struct static_route_info *si;
224
225 route_lock_node(rn);
226
227 /* Make new static route structure. */
228 pn = XCALLOC(MTYPE_STATIC_PATH, sizeof(struct static_path));
229
230 pn->rn = rn;
231 pn->distance = distance;
232 pn->table_id = table_id;
233 static_nexthop_list_init(&(pn->nexthop_list));
234
235 si = rn->info;
236 static_path_list_add_head(&(si->path_list), pn);
237
238 return pn;
239 }
240
241 void static_del_path(struct static_path *pn)
242 {
243 struct route_node *rn = pn->rn;
244 struct static_route_info *si;
245 struct static_nexthop *nh;
246
247 si = rn->info;
248
249 static_path_list_del(&si->path_list, pn);
250
251 frr_each_safe(static_nexthop_list, &pn->nexthop_list, nh) {
252 static_delete_nexthop(nh);
253 }
254
255 route_unlock_node(rn);
256
257 XFREE(MTYPE_STATIC_PATH, pn);
258 }
259
260 struct static_nexthop *static_add_nexthop(struct static_path *pn,
261 enum static_nh_type type,
262 struct ipaddr *ipaddr,
263 const char *ifname,
264 const char *nh_vrf, uint32_t color)
265 {
266 struct route_node *rn = pn->rn;
267 struct static_nexthop *nh;
268 struct static_vrf *nh_svrf;
269 struct interface *ifp;
270 struct static_nexthop *cp;
271
272 route_lock_node(rn);
273
274 nh_svrf = static_vrf_lookup_by_name(nh_vrf);
275
276 /* Make new static route structure. */
277 nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop));
278
279 nh->pn = pn;
280
281 nh->type = type;
282 nh->color = color;
283
284 if (nh->type == STATIC_BLACKHOLE)
285 nh->bh_type = STATIC_BLACKHOLE_NULL;
286
287 nh->nh_vrf_id = nh_svrf ? nh_svrf->vrf->vrf_id : VRF_UNKNOWN;
288 strlcpy(nh->nh_vrfname, nh_vrf, sizeof(nh->nh_vrfname));
289
290 if (ifname)
291 strlcpy(nh->ifname, ifname, sizeof(nh->ifname));
292 nh->ifindex = IFINDEX_INTERNAL;
293
294 switch (type) {
295 case STATIC_IPV4_GATEWAY:
296 case STATIC_IPV4_GATEWAY_IFNAME:
297 nh->addr.ipv4 = ipaddr->ipaddr_v4;
298 break;
299 case STATIC_IPV6_GATEWAY:
300 case STATIC_IPV6_GATEWAY_IFNAME:
301 nh->addr.ipv6 = ipaddr->ipaddr_v6;
302 break;
303 default:
304 break;
305 }
306 /*
307 * Add new static route information to the tree with sort by
308 * gateway address.
309 */
310 frr_each(static_nexthop_list, &pn->nexthop_list, cp) {
311 if (nh->type == STATIC_IPV4_GATEWAY
312 && cp->type == STATIC_IPV4_GATEWAY) {
313 if (ntohl(nh->addr.ipv4.s_addr)
314 < ntohl(cp->addr.ipv4.s_addr))
315 break;
316 if (ntohl(nh->addr.ipv4.s_addr)
317 > ntohl(cp->addr.ipv4.s_addr))
318 continue;
319 }
320 }
321 static_nexthop_list_add_after(&(pn->nexthop_list), cp, nh);
322
323 if (nh->nh_vrf_id == VRF_UNKNOWN) {
324 zlog_warn(
325 "Static Route to %pFX not installed currently because dependent config not fully available",
326 &rn->p);
327 return nh;
328 }
329
330 /* check whether interface exists in system & install if it does */
331 switch (nh->type) {
332 case STATIC_IPV4_GATEWAY:
333 case STATIC_IPV6_GATEWAY:
334 case STATIC_BLACKHOLE:
335 break;
336 case STATIC_IPV4_GATEWAY_IFNAME:
337 case STATIC_IPV6_GATEWAY_IFNAME:
338 case STATIC_IFNAME:
339 ifp = if_lookup_by_name(ifname, nh->nh_vrf_id);
340 if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
341 nh->ifindex = ifp->ifindex;
342 else
343 zlog_warn(
344 "Static Route using %s interface not installed because the interface does not exist in specified vrf",
345 ifname);
346 break;
347 }
348
349 return nh;
350 }
351
352 void static_install_nexthop(struct static_nexthop *nh)
353 {
354 struct static_path *pn = nh->pn;
355 struct route_node *rn = pn->rn;
356 struct interface *ifp;
357
358 if (nh->nh_vrf_id == VRF_UNKNOWN) {
359 char nexthop_str[NEXTHOP_STR];
360
361 static_get_nh_str(nh, nexthop_str, sizeof(nexthop_str));
362 DEBUGD(&static_dbg_route,
363 "Static Route %pFX not installed for %s vrf %s is unknown",
364 &rn->p, nexthop_str, nh->nh_vrfname);
365 return;
366 }
367
368 /* check whether interface exists in system & install if it does */
369 switch (nh->type) {
370 case STATIC_IPV4_GATEWAY:
371 case STATIC_IPV6_GATEWAY:
372 static_zebra_nht_register(nh, true);
373 break;
374 case STATIC_IPV4_GATEWAY_IFNAME:
375 case STATIC_IPV6_GATEWAY_IFNAME:
376 static_zebra_nht_register(nh, true);
377 break;
378 case STATIC_BLACKHOLE:
379 static_install_path(pn);
380 break;
381 case STATIC_IFNAME:
382 ifp = if_lookup_by_name(nh->ifname, nh->nh_vrf_id);
383 if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
384 static_install_path(pn);
385
386 break;
387 }
388 }
389
390 void static_delete_nexthop(struct static_nexthop *nh)
391 {
392 struct static_path *pn = nh->pn;
393 struct route_node *rn = pn->rn;
394
395 static_nexthop_list_del(&(pn->nexthop_list), nh);
396
397 if (nh->nh_vrf_id == VRF_UNKNOWN)
398 goto EXIT;
399
400 static_zebra_nht_register(nh, false);
401 /*
402 * If we have other si nodes then route replace
403 * else delete the route
404 */
405 static_uninstall_path(pn);
406
407 EXIT:
408 route_unlock_node(rn);
409 /* Free static route configuration. */
410 XFREE(MTYPE_STATIC_NEXTHOP, nh);
411 }
412
413 static void static_ifindex_update_nh(struct interface *ifp, bool up,
414 struct route_node *rn,
415 struct static_path *pn,
416 struct static_nexthop *nh,
417 struct static_vrf *svrf, safi_t safi)
418 {
419 if (!nh->ifname[0])
420 return;
421 if (up) {
422 if (strcmp(nh->ifname, ifp->name))
423 return;
424 if (nh->nh_vrf_id != ifp->vrf->vrf_id)
425 return;
426 nh->ifindex = ifp->ifindex;
427 } else {
428 if (nh->ifindex != ifp->ifindex)
429 return;
430 if (nh->nh_vrf_id != ifp->vrf->vrf_id)
431 return;
432 nh->ifindex = IFINDEX_INTERNAL;
433 }
434
435 static_install_path(pn);
436 }
437
438 static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
439 safi_t safi)
440 {
441 struct route_table *stable;
442 struct route_node *rn;
443 struct static_nexthop *nh;
444 struct static_path *pn;
445 struct vrf *vrf;
446 struct static_route_info *si;
447
448 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
449 struct static_vrf *svrf;
450
451 svrf = vrf->info;
452
453 stable = static_vrf_static_table(afi, safi, svrf);
454 if (!stable)
455 continue;
456 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
457 si = static_route_info_from_rnode(rn);
458 if (!si)
459 continue;
460 frr_each(static_path_list, &si->path_list, pn) {
461 frr_each(static_nexthop_list,
462 &pn->nexthop_list, nh) {
463 static_ifindex_update_nh(ifp, up, rn,
464 pn, nh, svrf,
465 safi);
466 }
467 }
468 }
469 }
470 }
471
472 /*
473 * This function looks at a svrf's stable and notices if any of the
474 * nexthops we are using are part of the vrf coming up.
475 * If we are using them then cleanup the nexthop vrf id
476 * to be the new value and then re-installs them
477 *
478 *
479 * stable -> The table we are looking at.
480 * svrf -> The newly changed vrf.
481 * afi -> The afi to look at
482 * safi -> the safi to look at
483 */
484 static void static_fixup_vrf(struct static_vrf *svrf,
485 struct route_table *stable, afi_t afi, safi_t safi)
486 {
487 struct route_node *rn;
488 struct static_nexthop *nh;
489 struct interface *ifp;
490 struct static_path *pn;
491 struct static_route_info *si;
492
493 for (rn = route_top(stable); rn; rn = route_next(rn)) {
494 si = static_route_info_from_rnode(rn);
495 if (!si)
496 continue;
497 frr_each(static_path_list, &si->path_list, pn) {
498 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
499 if (strcmp(svrf->vrf->name, nh->nh_vrfname)
500 != 0)
501 continue;
502
503 nh->nh_vrf_id = svrf->vrf->vrf_id;
504 nh->nh_registered = false;
505 if (nh->ifindex) {
506 ifp = if_lookup_by_name(nh->ifname,
507 nh->nh_vrf_id);
508 if (ifp)
509 nh->ifindex = ifp->ifindex;
510 else
511 continue;
512 }
513
514 static_install_path(pn);
515 }
516 }
517 }
518 }
519
520 /*
521 * This function enables static routes in a svrf as it
522 * is coming up. It sets the new vrf_id as appropriate.
523 *
524 * svrf -> The svrf that is being brought up and enabled by the kernel
525 * stable -> The stable we are looking at.
526 * afi -> the afi in question
527 * safi -> the safi in question
528 */
529 static void static_enable_vrf(struct static_vrf *svrf,
530 struct route_table *stable, afi_t afi,
531 safi_t safi)
532 {
533 struct route_node *rn;
534 struct static_nexthop *nh;
535 struct interface *ifp;
536 struct static_path *pn;
537 struct static_route_info *si;
538
539 for (rn = route_top(stable); rn; rn = route_next(rn)) {
540 si = static_route_info_from_rnode(rn);
541 if (!si)
542 continue;
543 frr_each(static_path_list, &si->path_list, pn) {
544 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
545 if (nh->ifindex) {
546 ifp = if_lookup_by_name(nh->ifname,
547 nh->nh_vrf_id);
548 if (ifp)
549 nh->ifindex = ifp->ifindex;
550 else
551 continue;
552 }
553 if (nh->nh_vrf_id == VRF_UNKNOWN)
554 continue;
555 static_install_path(pn);
556 }
557 }
558 }
559 }
560
561 /*
562 * When a vrf is being enabled by the kernel, go through all the
563 * static routes in the system that use this vrf (both nexthops vrfs
564 * and the routes vrf )
565 *
566 * enable_svrf -> the vrf being enabled
567 */
568 void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
569 {
570 struct route_table *stable;
571 struct vrf *vrf;
572 afi_t afi;
573 safi_t safi;
574
575 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
576 struct static_vrf *svrf;
577
578 svrf = vrf->info;
579 /* Install any static routes configured for this VRF. */
580 FOREACH_AFI_SAFI (afi, safi) {
581 stable = svrf->stable[afi][safi];
582 if (!stable)
583 continue;
584
585 static_fixup_vrf(enable_svrf, stable, afi, safi);
586
587 if (enable_svrf == svrf)
588 static_enable_vrf(svrf, stable, afi, safi);
589 }
590 }
591 }
592
593 /*
594 * Look at the specified stable and if any of the routes in
595 * this table are using the svrf as the nexthop, uninstall
596 * those routes.
597 *
598 * svrf -> the vrf being disabled
599 * stable -> the table we need to look at.
600 * afi -> the afi in question
601 * safi -> the safi in question
602 */
603 static void static_cleanup_vrf(struct static_vrf *svrf,
604 struct route_table *stable,
605 afi_t afi, safi_t safi)
606 {
607 struct route_node *rn;
608 struct static_nexthop *nh;
609 struct static_path *pn;
610 struct static_route_info *si;
611
612 for (rn = route_top(stable); rn; rn = route_next(rn)) {
613 si = static_route_info_from_rnode(rn);
614 if (!si)
615 continue;
616 frr_each(static_path_list, &si->path_list, pn) {
617 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
618 if (strcmp(svrf->vrf->name, nh->nh_vrfname)
619 != 0)
620 continue;
621
622 static_uninstall_path(pn);
623 }
624 }
625 }
626 }
627
628 /*
629 * Look at all static routes in this table and uninstall
630 * them.
631 *
632 * stable -> The table to uninstall from
633 * afi -> The afi in question
634 * safi -> the safi in question
635 */
636 static void static_disable_vrf(struct route_table *stable,
637 afi_t afi, safi_t safi)
638 {
639 struct route_node *rn;
640 struct static_nexthop *nh;
641 struct static_path *pn;
642 struct static_route_info *si;
643
644 for (rn = route_top(stable); rn; rn = route_next(rn)) {
645 si = static_route_info_from_rnode(rn);
646 if (!si)
647 continue;
648 frr_each(static_path_list, &si->path_list, pn) {
649 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
650 static_uninstall_path(pn);
651 }
652 }
653 }
654 }
655
656 /*
657 * When the disable_svrf is shutdown by the kernel, we call
658 * this function and it cleans up all static routes using
659 * this vrf as a nexthop as well as all static routes
660 * in it's stables.
661 *
662 * disable_svrf - The vrf being disabled
663 */
664 void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
665 {
666 struct vrf *vrf;
667 afi_t afi;
668 safi_t safi;
669
670 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
671 struct static_vrf *svrf;
672
673 svrf = vrf->info;
674
675 /* Uninstall any static routes configured for this VRF. */
676 FOREACH_AFI_SAFI (afi, safi) {
677 struct route_table *stable;
678
679 stable = svrf->stable[afi][safi];
680 if (!stable)
681 continue;
682
683 static_cleanup_vrf(disable_svrf, stable, afi, safi);
684
685 if (disable_svrf == svrf)
686 static_disable_vrf(stable, afi, safi);
687 }
688 }
689 }
690
691 /*
692 * This function enables static routes when an interface it relies
693 * on in a different vrf is coming up.
694 *
695 * stable -> The stable we are looking at.
696 * ifp -> interface coming up
697 * afi -> the afi in question
698 * safi -> the safi in question
699 */
700 static void static_fixup_intf_nh(struct route_table *stable,
701 struct interface *ifp,
702 afi_t afi, safi_t safi)
703 {
704 struct route_node *rn;
705 struct static_nexthop *nh;
706 struct static_path *pn;
707 struct static_route_info *si;
708
709 for (rn = route_top(stable); rn; rn = route_next(rn)) {
710 si = static_route_info_from_rnode(rn);
711 if (!si)
712 continue;
713 frr_each(static_path_list, &si->path_list, pn) {
714 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
715 if (nh->nh_vrf_id != ifp->vrf->vrf_id)
716 continue;
717
718 if (nh->ifindex != ifp->ifindex)
719 continue;
720
721 static_install_path(pn);
722 }
723 }
724 }
725 }
726
727 /*
728 * This function enables static routes that rely on an interface in
729 * a different vrf when that interface comes up.
730 */
731 void static_install_intf_nh(struct interface *ifp)
732 {
733 struct route_table *stable;
734 struct vrf *vrf;
735 afi_t afi;
736 safi_t safi;
737
738 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
739 struct static_vrf *svrf = vrf->info;
740
741 /* Not needed if same vrf since happens naturally */
742 if (vrf->vrf_id == ifp->vrf->vrf_id)
743 continue;
744
745 /* Install any static routes configured for this interface. */
746 FOREACH_AFI_SAFI (afi, safi) {
747 stable = svrf->stable[afi][safi];
748 if (!stable)
749 continue;
750
751 static_fixup_intf_nh(stable, ifp, afi, safi);
752 }
753 }
754 }
755
756 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
757 void static_ifindex_update(struct interface *ifp, bool up)
758 {
759 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
760 static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
761 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
762 static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
763 }
764
765 void static_get_nh_type(enum static_nh_type stype, char *type, size_t size)
766 {
767 switch (stype) {
768 case STATIC_IFNAME:
769 strlcpy(type, "ifindex", size);
770 break;
771 case STATIC_IPV4_GATEWAY:
772 strlcpy(type, "ip4", size);
773 break;
774 case STATIC_IPV4_GATEWAY_IFNAME:
775 strlcpy(type, "ip4-ifindex", size);
776 break;
777 case STATIC_BLACKHOLE:
778 strlcpy(type, "blackhole", size);
779 break;
780 case STATIC_IPV6_GATEWAY:
781 strlcpy(type, "ip6", size);
782 break;
783 case STATIC_IPV6_GATEWAY_IFNAME:
784 strlcpy(type, "ip6-ifindex", size);
785 break;
786 };
787 }
788
789 struct stable_info *static_get_stable_info(struct route_node *rn)
790 {
791 struct route_table *table;
792
793 table = srcdest_rnode_table(rn);
794 return table->info;
795 }
796
797 void static_get_nh_str(struct static_nexthop *nh, char *nexthop, size_t size)
798 {
799 switch (nh->type) {
800 case STATIC_IFNAME:
801 snprintfrr(nexthop, size, "ifindex : %s", nh->ifname);
802 break;
803 case STATIC_IPV4_GATEWAY:
804 snprintfrr(nexthop, size, "ip4 : %pI4", &nh->addr.ipv4);
805 break;
806 case STATIC_IPV4_GATEWAY_IFNAME:
807 snprintfrr(nexthop, size, "ip4-ifindex : %pI4 : %s",
808 &nh->addr.ipv4, nh->ifname);
809 break;
810 case STATIC_BLACKHOLE:
811 snprintfrr(nexthop, size, "blackhole : %d", nh->bh_type);
812 break;
813 case STATIC_IPV6_GATEWAY:
814 snprintfrr(nexthop, size, "ip6 : %pI6", &nh->addr.ipv6);
815 break;
816 case STATIC_IPV6_GATEWAY_IFNAME:
817 snprintfrr(nexthop, size, "ip6-ifindex : %pI6 : %s",
818 &nh->addr.ipv6, nh->ifname);
819 break;
820 };
821 }