Bug #362 is fixed now.
[jleu-quagga.git] / ospf6d / ospf6_asbr.c
blob1b6ccbd999a1961e02d0e3a5b181ffdf8ef15c0d
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
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.
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.
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
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #include <zebra.h>
24 #include "log.h"
25 #include "memory.h"
26 #include "prefix.h"
27 #include "command.h"
28 #include "vty.h"
29 #include "routemap.h"
30 #include "table.h"
31 #include "plist.h"
32 #include "thread.h"
33 #include "linklist.h"
35 #include "ospf6_proto.h"
36 #include "ospf6_lsa.h"
37 #include "ospf6_lsdb.h"
38 #include "ospf6_route.h"
39 #include "ospf6_zebra.h"
40 #include "ospf6_message.h"
42 #include "ospf6_top.h"
43 #include "ospf6_area.h"
44 #include "ospf6_interface.h"
45 #include "ospf6_neighbor.h"
46 #include "ospf6_asbr.h"
47 #include "ospf6_intra.h"
48 #include "ospf6_flood.h"
49 #include "ospf6d.h"
51 unsigned char conf_debug_ospf6_asbr = 0;
53 #define ZROUTE_NAME(x) zebra_route_string(x)
55 /* AS External LSA origination */
56 void
57 ospf6_as_external_lsa_originate (struct ospf6_route *route)
59 char buffer[OSPF6_MAX_LSASIZE];
60 struct ospf6_lsa_header *lsa_header;
61 struct ospf6_lsa *old, *lsa;
62 struct ospf6_external_info *info = route->route_option;
64 struct ospf6_as_external_lsa *as_external_lsa;
65 char buf[64];
66 caddr_t p;
68 /* find previous LSA */
69 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
70 route->path.origin.id, ospf6->router_id,
71 ospf6->lsdb);
73 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL))
75 prefix2str (&route->prefix, buf, sizeof (buf));
76 zlog_debug ("Originate AS-External-LSA for %s", buf);
79 /* prepare buffer */
80 memset (buffer, 0, sizeof (buffer));
81 lsa_header = (struct ospf6_lsa_header *) buffer;
82 as_external_lsa = (struct ospf6_as_external_lsa *)
83 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
84 p = (caddr_t)
85 ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa));
87 /* Fill AS-External-LSA */
88 /* Metric type */
89 if (route->path.metric_type == 2)
90 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
91 else
92 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
94 /* forwarding address */
95 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
96 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
97 else
98 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
100 /* external route tag */
101 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
103 /* Set metric */
104 OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);
106 /* prefixlen */
107 as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
109 /* PrefixOptions */
110 as_external_lsa->prefix.prefix_options = route->path.prefix_options;
112 /* don't use refer LS-type */
113 as_external_lsa->prefix.prefix_refer_lstype = htons (0);
115 /* set Prefix */
116 memcpy (p, &route->prefix.u.prefix6,
117 OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
118 ospf6_prefix_apply_mask (&as_external_lsa->prefix);
119 p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
121 /* Forwarding address */
122 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
124 memcpy (p, &info->forwarding, sizeof (struct in6_addr));
125 p += sizeof (struct in6_addr);
128 /* External Route Tag */
129 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
131 /* xxx */
134 /* Fill LSA Header */
135 lsa_header->age = 0;
136 lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
137 lsa_header->id = route->path.origin.id;
138 lsa_header->adv_router = ospf6->router_id;
139 lsa_header->seqnum =
140 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
141 lsa_header->adv_router, ospf6->lsdb);
142 lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
144 /* LSA checksum */
145 ospf6_lsa_checksum (lsa_header);
147 /* create LSA */
148 lsa = ospf6_lsa_create (lsa_header);
150 /* Originate */
151 ospf6_lsa_originate_process (lsa, ospf6);
155 void
156 ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
158 struct ospf6_as_external_lsa *external;
159 struct prefix asbr_id;
160 struct ospf6_route *asbr_entry, *route;
161 char buf[64];
162 int i;
164 external = (struct ospf6_as_external_lsa *)
165 OSPF6_LSA_HEADER_END (lsa->header);
167 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
168 zlog_debug ("Calculate AS-External route for %s", lsa->name);
170 if (lsa->header->adv_router == ospf6->router_id)
172 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
173 zlog_debug ("Ignore self-originated AS-External-LSA");
174 return;
177 if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
179 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
180 zlog_debug ("Ignore LSA with LSInfinity Metric");
181 return;
184 ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
185 asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
186 if (asbr_entry == NULL ||
187 ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
189 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
191 prefix2str (&asbr_id, buf, sizeof (buf));
192 zlog_debug ("ASBR entry not found: %s", buf);
194 return;
197 route = ospf6_route_create ();
198 route->type = OSPF6_DEST_TYPE_NETWORK;
199 route->prefix.family = AF_INET6;
200 route->prefix.prefixlen = external->prefix.prefix_length;
201 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);
203 route->path.area_id = asbr_entry->path.area_id;
204 route->path.origin.type = lsa->header->type;
205 route->path.origin.id = lsa->header->id;
206 route->path.origin.adv_router = lsa->header->adv_router;
208 route->path.prefix_options = external->prefix.prefix_options;
209 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
211 route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
212 route->path.metric_type = 2;
213 route->path.cost = asbr_entry->path.cost;
214 route->path.cost_e2 = OSPF6_ASBR_METRIC (external);
216 else
218 route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
219 route->path.metric_type = 1;
220 route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
221 route->path.cost_e2 = 0;
224 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
225 ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);
227 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
229 prefix2str (&route->prefix, buf, sizeof (buf));
230 zlog_debug ("AS-External route add: %s", buf);
233 ospf6_route_add (route, ospf6->route_table);
236 void
237 ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa)
239 struct ospf6_as_external_lsa *external;
240 struct prefix prefix;
241 struct ospf6_route *route;
242 char buf[64];
244 external = (struct ospf6_as_external_lsa *)
245 OSPF6_LSA_HEADER_END (lsa->header);
247 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
248 zlog_debug ("Withdraw AS-External route for %s", lsa->name);
250 if (lsa->header->adv_router == ospf6->router_id)
252 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
253 zlog_debug ("Ignore self-originated AS-External-LSA");
254 return;
257 memset (&prefix, 0, sizeof (struct prefix));
258 prefix.family = AF_INET6;
259 prefix.prefixlen = external->prefix.prefix_length;
260 ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix);
262 route = ospf6_route_lookup (&prefix, ospf6->route_table);
263 if (route == NULL)
265 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
267 prefix2str (&prefix, buf, sizeof (buf));
268 zlog_debug ("AS-External route %s not found", buf);
270 return;
273 for (ospf6_route_lock (route);
274 route && ospf6_route_is_prefix (&prefix, route);
275 route = ospf6_route_next (route))
277 if (route->type != OSPF6_DEST_TYPE_NETWORK)
278 continue;
279 if (route->path.origin.type != lsa->header->type)
280 continue;
281 if (route->path.origin.id != lsa->header->id)
282 continue;
283 if (route->path.origin.adv_router != lsa->header->adv_router)
284 continue;
286 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
288 prefix2str (&route->prefix, buf, sizeof (buf));
289 zlog_debug ("AS-External route remove: %s", buf);
291 ospf6_route_remove (route, ospf6->route_table);
295 void
296 ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
298 struct ospf6_lsa *lsa;
299 u_int16_t type;
300 u_int32_t router;
302 if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
304 char buf[16];
305 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
306 buf, sizeof (buf));
307 zlog_info ("ignore non-best path: lsentry %s add", buf);
308 return;
311 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
312 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
313 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
314 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
316 if (! OSPF6_LSA_IS_MAXAGE (lsa))
317 ospf6_asbr_lsa_add (lsa);
321 void
322 ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
324 struct ospf6_lsa *lsa;
325 u_int16_t type;
326 u_int32_t router;
328 if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
330 char buf[16];
331 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
332 buf, sizeof (buf));
333 zlog_info ("ignore non-best path: lsentry %s remove", buf);
334 return;
337 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
338 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
339 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
340 lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
341 ospf6_asbr_lsa_remove (lsa);
346 /* redistribute function */
348 void
349 ospf6_asbr_routemap_set (int type, const char *mapname)
351 if (ospf6->rmap[type].name)
352 free (ospf6->rmap[type].name);
353 ospf6->rmap[type].name = strdup (mapname);
354 ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
357 void
358 ospf6_asbr_routemap_unset (int type)
360 if (ospf6->rmap[type].name)
361 free (ospf6->rmap[type].name);
362 ospf6->rmap[type].name = NULL;
363 ospf6->rmap[type].map = NULL;
366 void
367 ospf6_asbr_routemap_update (const char *mapname)
369 int type;
371 if (ospf6 == NULL)
372 return;
374 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
376 if (ospf6->rmap[type].name)
377 ospf6->rmap[type].map =
378 route_map_lookup_by_name (ospf6->rmap[type].name);
379 else
380 ospf6->rmap[type].map = NULL;
385 ospf6_asbr_is_asbr (struct ospf6 *o)
387 return o->external_table->count;
390 void
391 ospf6_asbr_redistribute_set (int type)
393 ospf6_zebra_redistribute (type);
396 void
397 ospf6_asbr_redistribute_unset (int type)
399 struct ospf6_route *route;
400 struct ospf6_external_info *info;
402 ospf6_zebra_no_redistribute (type);
404 for (route = ospf6_route_head (ospf6->external_table); route;
405 route = ospf6_route_next (route))
407 info = route->route_option;
408 if (info->type != type)
409 continue;
411 ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
412 &route->prefix);
416 void
417 ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
418 u_int nexthop_num, struct in6_addr *nexthop)
420 int ret;
421 struct ospf6_route troute;
422 struct ospf6_external_info tinfo;
423 struct ospf6_route *route, *match;
424 struct ospf6_external_info *info;
425 struct prefix prefix_id;
426 struct route_node *node;
427 char pbuf[64], ibuf[16];
428 struct listnode *lnode, *lnnode;
429 struct ospf6_area *oa;
431 if (! ospf6_zebra_is_redistribute (type))
432 return;
434 if (IS_OSPF6_DEBUG_ASBR)
436 prefix2str (prefix, pbuf, sizeof (pbuf));
437 zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
440 /* if route-map was specified but not found, do not advertise */
441 if (ospf6->rmap[type].name)
443 if (ospf6->rmap[type].map == NULL)
444 ospf6_asbr_routemap_update (NULL);
445 if (ospf6->rmap[type].map == NULL)
447 zlog_warn ("route-map \"%s\" not found, suppress redistributing",
448 ospf6->rmap[type].name);
449 return;
453 /* apply route-map */
454 if (ospf6->rmap[type].map)
456 memset (&troute, 0, sizeof (troute));
457 memset (&tinfo, 0, sizeof (tinfo));
458 troute.route_option = &tinfo;
460 ret = route_map_apply (ospf6->rmap[type].map, prefix,
461 RMAP_OSPF6, &troute);
462 if (ret == RMAP_DENYMATCH)
464 if (IS_OSPF6_DEBUG_ASBR)
465 zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
466 return;
470 match = ospf6_route_lookup (prefix, ospf6->external_table);
471 if (match)
473 info = match->route_option;
475 /* copy result of route-map */
476 if (ospf6->rmap[type].map)
478 if (troute.path.metric_type)
479 match->path.metric_type = troute.path.metric_type;
480 if (troute.path.cost)
481 match->path.cost = troute.path.cost;
482 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
483 memcpy (&info->forwarding, &tinfo.forwarding,
484 sizeof (struct in6_addr));
487 info->type = type;
488 match->nexthop[0].ifindex = ifindex;
489 if (nexthop_num && nexthop)
490 memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
492 /* create/update binding in external_id_table */
493 prefix_id.family = AF_INET;
494 prefix_id.prefixlen = 32;
495 prefix_id.u.prefix4.s_addr = htonl (info->id);
496 node = route_node_get (ospf6->external_id_table, &prefix_id);
497 node->info = match;
499 if (IS_OSPF6_DEBUG_ASBR)
501 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
502 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
505 match->path.origin.id = htonl (info->id);
506 ospf6_as_external_lsa_originate (match);
507 return;
510 /* create new entry */
511 route = ospf6_route_create ();
512 route->type = OSPF6_DEST_TYPE_NETWORK;
513 memcpy (&route->prefix, prefix, sizeof (struct prefix));
515 info = (struct ospf6_external_info *)
516 XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
517 memset (info, 0, sizeof (struct ospf6_external_info));
518 route->route_option = info;
519 info->id = ospf6->external_id++;
521 /* copy result of route-map */
522 if (ospf6->rmap[type].map)
524 if (troute.path.metric_type)
525 route->path.metric_type = troute.path.metric_type;
526 if (troute.path.cost)
527 route->path.cost = troute.path.cost;
528 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
529 memcpy (&info->forwarding, &tinfo.forwarding,
530 sizeof (struct in6_addr));
533 info->type = type;
534 route->nexthop[0].ifindex = ifindex;
535 if (nexthop_num && nexthop)
536 memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
538 /* create/update binding in external_id_table */
539 prefix_id.family = AF_INET;
540 prefix_id.prefixlen = 32;
541 prefix_id.u.prefix4.s_addr = htonl (info->id);
542 node = route_node_get (ospf6->external_id_table, &prefix_id);
543 node->info = route;
545 route = ospf6_route_add (route, ospf6->external_table);
546 route->route_option = info;
548 if (IS_OSPF6_DEBUG_ASBR)
550 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
551 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
554 route->path.origin.id = htonl (info->id);
555 ospf6_as_external_lsa_originate (route);
557 /* Router-Bit (ASBR Flag) may have to be updated */
558 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
559 OSPF6_ROUTER_LSA_SCHEDULE (oa);
562 void
563 ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
565 struct ospf6_route *match;
566 struct ospf6_external_info *info = NULL;
567 struct route_node *node;
568 struct ospf6_lsa *lsa;
569 struct prefix prefix_id;
570 char pbuf[64], ibuf[16];
571 struct listnode *lnode, *lnnode;
572 struct ospf6_area *oa;
574 match = ospf6_route_lookup (prefix, ospf6->external_table);
575 if (match == NULL)
577 if (IS_OSPF6_DEBUG_ASBR)
579 prefix2str (prefix, pbuf, sizeof (pbuf));
580 zlog_debug ("No such route %s to withdraw", pbuf);
582 return;
585 info = match->route_option;
586 assert (info);
588 if (info->type != type)
590 if (IS_OSPF6_DEBUG_ASBR)
592 prefix2str (prefix, pbuf, sizeof (pbuf));
593 zlog_debug ("Original protocol mismatch: %s", pbuf);
595 return;
598 if (IS_OSPF6_DEBUG_ASBR)
600 prefix2str (prefix, pbuf, sizeof (pbuf));
601 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
602 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
605 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
606 htonl (info->id), ospf6->router_id, ospf6->lsdb);
607 if (lsa)
608 ospf6_lsa_purge (lsa);
610 /* remove binding in external_id_table */
611 prefix_id.family = AF_INET;
612 prefix_id.prefixlen = 32;
613 prefix_id.u.prefix4.s_addr = htonl (info->id);
614 node = route_node_lookup (ospf6->external_id_table, &prefix_id);
615 assert (node);
616 node->info = NULL;
617 route_unlock_node (node);
619 ospf6_route_remove (match, ospf6->external_table);
620 XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
622 /* Router-Bit (ASBR Flag) may have to be updated */
623 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
624 OSPF6_ROUTER_LSA_SCHEDULE (oa);
627 DEFUN (ospf6_redistribute,
628 ospf6_redistribute_cmd,
629 "redistribute (static|kernel|connected|ripng|bgp)",
630 "Redistribute\n"
631 "Static route\n"
632 "Kernel route\n"
633 "Connected route\n"
634 "RIPng route\n"
635 "BGP route\n"
638 int type = 0;
640 if (strncmp (argv[0], "sta", 3) == 0)
641 type = ZEBRA_ROUTE_STATIC;
642 else if (strncmp (argv[0], "ker", 3) == 0)
643 type = ZEBRA_ROUTE_KERNEL;
644 else if (strncmp (argv[0], "con", 3) == 0)
645 type = ZEBRA_ROUTE_CONNECT;
646 else if (strncmp (argv[0], "rip", 3) == 0)
647 type = ZEBRA_ROUTE_RIPNG;
648 else if (strncmp (argv[0], "bgp", 3) == 0)
649 type = ZEBRA_ROUTE_BGP;
651 ospf6_asbr_redistribute_unset (type);
652 ospf6_asbr_routemap_unset (type);
653 ospf6_asbr_redistribute_set (type);
654 return CMD_SUCCESS;
657 DEFUN (ospf6_redistribute_routemap,
658 ospf6_redistribute_routemap_cmd,
659 "redistribute (static|kernel|connected|ripng|bgp) route-map WORD",
660 "Redistribute\n"
661 "Static routes\n"
662 "Kernel route\n"
663 "Connected route\n"
664 "RIPng route\n"
665 "BGP route\n"
666 "Route map reference\n"
667 "Route map name\n"
670 int type = 0;
672 if (strncmp (argv[0], "sta", 3) == 0)
673 type = ZEBRA_ROUTE_STATIC;
674 else if (strncmp (argv[0], "ker", 3) == 0)
675 type = ZEBRA_ROUTE_KERNEL;
676 else if (strncmp (argv[0], "con", 3) == 0)
677 type = ZEBRA_ROUTE_CONNECT;
678 else if (strncmp (argv[0], "rip", 3) == 0)
679 type = ZEBRA_ROUTE_RIPNG;
680 else if (strncmp (argv[0], "bgp", 3) == 0)
681 type = ZEBRA_ROUTE_BGP;
683 ospf6_asbr_redistribute_unset (type);
684 ospf6_asbr_routemap_set (type, argv[1]);
685 ospf6_asbr_redistribute_set (type);
686 return CMD_SUCCESS;
689 DEFUN (no_ospf6_redistribute,
690 no_ospf6_redistribute_cmd,
691 "no redistribute (static|kernel|connected|ripng|bgp)",
692 NO_STR
693 "Redistribute\n"
694 "Static route\n"
695 "Kernel route\n"
696 "Connected route\n"
697 "RIPng route\n"
698 "BGP route\n"
701 int type = 0;
703 if (strncmp (argv[0], "sta", 3) == 0)
704 type = ZEBRA_ROUTE_STATIC;
705 else if (strncmp (argv[0], "ker", 3) == 0)
706 type = ZEBRA_ROUTE_KERNEL;
707 else if (strncmp (argv[0], "con", 3) == 0)
708 type = ZEBRA_ROUTE_CONNECT;
709 else if (strncmp (argv[0], "rip", 3) == 0)
710 type = ZEBRA_ROUTE_RIPNG;
711 else if (strncmp (argv[0], "bgp", 3) == 0)
712 type = ZEBRA_ROUTE_BGP;
714 ospf6_asbr_redistribute_unset (type);
715 ospf6_asbr_routemap_unset (type);
717 return CMD_SUCCESS;
721 ospf6_redistribute_config_write (struct vty *vty)
723 int type;
725 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
727 if (type == ZEBRA_ROUTE_OSPF6)
728 continue;
729 if (! ospf6_zebra_is_redistribute (type))
730 continue;
732 if (ospf6->rmap[type].name)
733 vty_out (vty, " redistribute %s route-map %s%s",
734 ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
735 else
736 vty_out (vty, " redistribute %s%s",
737 ZROUTE_NAME (type), VNL);
740 return 0;
743 void
744 ospf6_redistribute_show_config (struct vty *vty)
746 int type;
747 int nroute[ZEBRA_ROUTE_MAX];
748 int total;
749 struct ospf6_route *route;
750 struct ospf6_external_info *info;
752 total = 0;
753 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
754 nroute[type] = 0;
755 for (route = ospf6_route_head (ospf6->external_table); route;
756 route = ospf6_route_next (route))
758 info = route->route_option;
759 nroute[info->type]++;
760 total++;
763 vty_out (vty, "Redistributing External Routes from:%s", VNL);
764 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
766 if (type == ZEBRA_ROUTE_OSPF6)
767 continue;
768 if (! ospf6_zebra_is_redistribute (type))
769 continue;
771 if (ospf6->rmap[type].name)
772 vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
773 ZROUTE_NAME (type), ospf6->rmap[type].name,
774 (ospf6->rmap[type].map ? "" : " (not found !)"),
775 VNL);
776 else
777 vty_out (vty, " %d: %s%s", nroute[type],
778 ZROUTE_NAME (type), VNL);
780 vty_out (vty, "Total %d routes%s", total, VNL);
785 /* Routemap Functions */
786 route_map_result_t
787 ospf6_routemap_rule_match_address_prefixlist (void *rule,
788 struct prefix *prefix,
789 route_map_object_t type,
790 void *object)
792 struct prefix_list *plist;
794 if (type != RMAP_OSPF6)
795 return RMAP_NOMATCH;
797 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
798 if (plist == NULL)
799 return RMAP_NOMATCH;
801 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
802 RMAP_NOMATCH : RMAP_MATCH);
805 void *
806 ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
808 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
811 void
812 ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
814 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
817 struct route_map_rule_cmd
818 ospf6_routemap_rule_match_address_prefixlist_cmd =
820 "ipv6 address prefix-list",
821 ospf6_routemap_rule_match_address_prefixlist,
822 ospf6_routemap_rule_match_address_prefixlist_compile,
823 ospf6_routemap_rule_match_address_prefixlist_free,
826 route_map_result_t
827 ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
828 route_map_object_t type, void *object)
830 char *metric_type = rule;
831 struct ospf6_route *route = object;
833 if (type != RMAP_OSPF6)
834 return RMAP_OKAY;
836 if (strcmp (metric_type, "type-2") == 0)
837 route->path.metric_type = 2;
838 else
839 route->path.metric_type = 1;
841 return RMAP_OKAY;
844 void *
845 ospf6_routemap_rule_set_metric_type_compile (const char *arg)
847 if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
848 return NULL;
849 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
852 void
853 ospf6_routemap_rule_set_metric_type_free (void *rule)
855 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
858 struct route_map_rule_cmd
859 ospf6_routemap_rule_set_metric_type_cmd =
861 "metric-type",
862 ospf6_routemap_rule_set_metric_type,
863 ospf6_routemap_rule_set_metric_type_compile,
864 ospf6_routemap_rule_set_metric_type_free,
867 route_map_result_t
868 ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
869 route_map_object_t type, void *object)
871 char *metric = rule;
872 struct ospf6_route *route = object;
874 if (type != RMAP_OSPF6)
875 return RMAP_OKAY;
877 route->path.cost = atoi (metric);
878 return RMAP_OKAY;
881 void *
882 ospf6_routemap_rule_set_metric_compile (const char *arg)
884 u_int32_t metric;
885 char *endp;
886 metric = strtoul (arg, &endp, 0);
887 if (metric > LS_INFINITY || *endp != '\0')
888 return NULL;
889 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
892 void
893 ospf6_routemap_rule_set_metric_free (void *rule)
895 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
898 struct route_map_rule_cmd
899 ospf6_routemap_rule_set_metric_cmd =
901 "metric",
902 ospf6_routemap_rule_set_metric,
903 ospf6_routemap_rule_set_metric_compile,
904 ospf6_routemap_rule_set_metric_free,
907 route_map_result_t
908 ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
909 route_map_object_t type, void *object)
911 char *forwarding = rule;
912 struct ospf6_route *route = object;
913 struct ospf6_external_info *info = route->route_option;
915 if (type != RMAP_OSPF6)
916 return RMAP_OKAY;
918 if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
920 memset (&info->forwarding, 0, sizeof (struct in6_addr));
921 return RMAP_ERROR;
924 return RMAP_OKAY;
927 void *
928 ospf6_routemap_rule_set_forwarding_compile (const char *arg)
930 struct in6_addr a;
931 if (inet_pton (AF_INET6, arg, &a) != 1)
932 return NULL;
933 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
936 void
937 ospf6_routemap_rule_set_forwarding_free (void *rule)
939 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
942 struct route_map_rule_cmd
943 ospf6_routemap_rule_set_forwarding_cmd =
945 "forwarding-address",
946 ospf6_routemap_rule_set_forwarding,
947 ospf6_routemap_rule_set_forwarding_compile,
948 ospf6_routemap_rule_set_forwarding_free,
952 route_map_command_status (struct vty *vty, int ret)
954 if (! ret)
955 return CMD_SUCCESS;
957 switch (ret)
959 case RMAP_RULE_MISSING:
960 vty_out (vty, "Can't find rule.%s", VNL);
961 break;
962 case RMAP_COMPILE_ERROR:
963 vty_out (vty, "Argument is malformed.%s", VNL);
964 break;
965 default:
966 vty_out (vty, "route-map add set failed.%s", VNL);
967 break;
969 return CMD_WARNING;
972 /* add "match address" */
973 DEFUN (ospf6_routemap_match_address_prefixlist,
974 ospf6_routemap_match_address_prefixlist_cmd,
975 "match ipv6 address prefix-list WORD",
976 "Match values\n"
977 IPV6_STR
978 "Match address of route\n"
979 "Match entries of prefix-lists\n"
980 "IPv6 prefix-list name\n")
982 int ret = route_map_add_match ((struct route_map_index *) vty->index,
983 "ipv6 address prefix-list", argv[0]);
984 return route_map_command_status (vty, ret);
987 /* delete "match address" */
988 DEFUN (ospf6_routemap_no_match_address_prefixlist,
989 ospf6_routemap_no_match_address_prefixlist_cmd,
990 "no match ipv6 address prefix-list WORD",
991 NO_STR
992 "Match values\n"
993 IPV6_STR
994 "Match address of route\n"
995 "Match entries of prefix-lists\n"
996 "IPv6 prefix-list name\n")
998 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
999 "ipv6 address prefix-list", argv[0]);
1000 return route_map_command_status (vty, ret);
1003 /* add "set metric-type" */
1004 DEFUN (ospf6_routemap_set_metric_type,
1005 ospf6_routemap_set_metric_type_cmd,
1006 "set metric-type (type-1|type-2)",
1007 "Set value\n"
1008 "Type of metric\n"
1009 "OSPF6 external type 1 metric\n"
1010 "OSPF6 external type 2 metric\n")
1012 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1013 "metric-type", argv[0]);
1014 return route_map_command_status (vty, ret);
1017 /* delete "set metric-type" */
1018 DEFUN (ospf6_routemap_no_set_metric_type,
1019 ospf6_routemap_no_set_metric_type_cmd,
1020 "no set metric-type (type-1|type-2)",
1021 NO_STR
1022 "Set value\n"
1023 "Type of metric\n"
1024 "OSPF6 external type 1 metric\n"
1025 "OSPF6 external type 2 metric\n")
1027 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1028 "metric-type", argv[0]);
1029 return route_map_command_status (vty, ret);
1032 /* add "set metric" */
1033 DEFUN (set_metric,
1034 set_metric_cmd,
1035 "set metric <0-4294967295>",
1036 "Set value\n"
1037 "Metric value\n"
1038 "Metric value\n")
1040 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1041 "metric", argv[0]);
1042 return route_map_command_status (vty, ret);
1045 /* delete "set metric" */
1046 DEFUN (no_set_metric,
1047 no_set_metric_cmd,
1048 "no set metric <0-4294967295>",
1049 NO_STR
1050 "Set value\n"
1051 "Metric\n"
1052 "METRIC value\n")
1054 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1055 "metric", argv[0]);
1056 return route_map_command_status (vty, ret);
1059 /* add "set forwarding-address" */
1060 DEFUN (ospf6_routemap_set_forwarding,
1061 ospf6_routemap_set_forwarding_cmd,
1062 "set forwarding-address X:X::X:X",
1063 "Set value\n"
1064 "Forwarding Address\n"
1065 "IPv6 Address\n")
1067 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1068 "forwarding-address", argv[0]);
1069 return route_map_command_status (vty, ret);
1072 /* delete "set forwarding-address" */
1073 DEFUN (ospf6_routemap_no_set_forwarding,
1074 ospf6_routemap_no_set_forwarding_cmd,
1075 "no set forwarding-address X:X::X:X",
1076 NO_STR
1077 "Set value\n"
1078 "Forwarding Address\n"
1079 "IPv6 Address\n")
1081 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1082 "forwarding-address", argv[0]);
1083 return route_map_command_status (vty, ret);
1086 void
1087 ospf6_routemap_init ()
1089 route_map_init ();
1090 route_map_init_vty ();
1091 route_map_add_hook (ospf6_asbr_routemap_update);
1092 route_map_delete_hook (ospf6_asbr_routemap_update);
1094 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
1095 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
1096 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
1097 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
1099 /* Match address prefix-list */
1100 install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
1101 install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
1103 /* ASE Metric Type (e.g. Type-1/Type-2) */
1104 install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1105 install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
1107 /* ASE Metric */
1108 install_element (RMAP_NODE, &set_metric_cmd);
1109 install_element (RMAP_NODE, &no_set_metric_cmd);
1111 /* ASE Metric */
1112 install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1113 install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
1117 /* Display functions */
1119 ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1121 struct ospf6_as_external_lsa *external;
1122 char buf[64];
1123 struct in6_addr in6, *forwarding;
1125 assert (lsa->header);
1126 external = (struct ospf6_as_external_lsa *)
1127 OSPF6_LSA_HEADER_END (lsa->header);
1129 /* bits */
1130 snprintf (buf, sizeof (buf), "%c%c%c",
1131 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
1132 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
1133 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
1135 vty_out (vty, " Bits: %s%s", buf, VNL);
1136 vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
1137 VNL);
1139 ospf6_prefix_options_printbuf (external->prefix.prefix_options,
1140 buf, sizeof (buf));
1141 vty_out (vty, " Prefix Options: %s%s", buf,
1142 VNL);
1144 vty_out (vty, " Referenced LSType: %d%s",
1145 ntohs (external->prefix.prefix_refer_lstype),
1146 VNL);
1148 ospf6_prefix_in6_addr (&in6, &external->prefix);
1149 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
1150 vty_out (vty, " Prefix: %s/%d%s", buf,
1151 external->prefix.prefix_length, VNL);
1153 /* Forwarding-Address */
1154 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
1156 forwarding = (struct in6_addr *)
1157 ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
1158 OSPF6_PREFIX_SPACE (external->prefix.prefix_length));
1159 inet_ntop (AF_INET6, forwarding, buf, sizeof (buf));
1160 vty_out (vty, " Forwarding-Address: %s%s", buf, VNL);
1163 return 0;
1166 void
1167 ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
1169 struct ospf6_external_info *info = route->route_option;
1170 char prefix[64], id[16], forwarding[64];
1171 u_int32_t tmp_id;
1173 prefix2str (&route->prefix, prefix, sizeof (prefix));
1174 tmp_id = ntohl (info->id);
1175 inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
1176 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
1177 inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
1178 else
1179 snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
1180 route->nexthop[0].ifindex);
1182 vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
1183 zebra_route_char(info->type),
1184 prefix, id, route->path.metric_type,
1185 (u_long) (route->path.metric_type == 2 ?
1186 route->path.cost_e2 : route->path.cost),
1187 forwarding, VNL);
1190 DEFUN (show_ipv6_ospf6_redistribute,
1191 show_ipv6_ospf6_redistribute_cmd,
1192 "show ipv6 ospf6 redistribute",
1193 SHOW_STR
1194 IP6_STR
1195 OSPF6_STR
1196 "redistributing External information\n"
1199 struct ospf6_route *route;
1201 ospf6_redistribute_show_config (vty);
1203 for (route = ospf6_route_head (ospf6->external_table); route;
1204 route = ospf6_route_next (route))
1205 ospf6_asbr_external_route_show (vty, route);
1207 return CMD_SUCCESS;
1210 struct ospf6_lsa_handler as_external_handler =
1212 OSPF6_LSTYPE_AS_EXTERNAL,
1213 "AS-External",
1214 ospf6_as_external_lsa_show
1217 void
1218 ospf6_asbr_init ()
1220 ospf6_routemap_init ();
1222 ospf6_install_lsa_handler (&as_external_handler);
1224 install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
1225 install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
1227 install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1228 install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1229 install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
1233 DEFUN (debug_ospf6_asbr,
1234 debug_ospf6_asbr_cmd,
1235 "debug ospf6 asbr",
1236 DEBUG_STR
1237 OSPF6_STR
1238 "Debug OSPFv3 ASBR function\n"
1241 OSPF6_DEBUG_ASBR_ON ();
1242 return CMD_SUCCESS;
1245 DEFUN (no_debug_ospf6_asbr,
1246 no_debug_ospf6_asbr_cmd,
1247 "no debug ospf6 asbr",
1248 NO_STR
1249 DEBUG_STR
1250 OSPF6_STR
1251 "Debug OSPFv3 ASBR function\n"
1254 OSPF6_DEBUG_ASBR_OFF ();
1255 return CMD_SUCCESS;
1259 config_write_ospf6_debug_asbr (struct vty *vty)
1261 if (IS_OSPF6_DEBUG_ASBR)
1262 vty_out (vty, "debug ospf6 asbr%s", VNL);
1263 return 0;
1266 void
1267 install_element_ospf6_debug_asbr ()
1269 install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
1270 install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1271 install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
1272 install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);