]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_asbr.c
ospf6d: add support for route tags
[mirror_frr.git] / ospf6d / ospf6_asbr.c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
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
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23
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"
34
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"
41
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"
50
51 unsigned char conf_debug_ospf6_asbr = 0;
52
53 #define ZROUTE_NAME(x) zebra_route_string(x)
54
55 /* AS External LSA origination */
56 static void
57 ospf6_as_external_lsa_originate (struct ospf6_route *route)
58 {
59 char buffer[OSPF6_MAX_LSASIZE];
60 struct ospf6_lsa_header *lsa_header;
61 struct ospf6_lsa *lsa;
62 struct ospf6_external_info *info = route->route_option;
63
64 struct ospf6_as_external_lsa *as_external_lsa;
65 char buf[PREFIX2STR_BUFFER];
66 caddr_t p;
67
68 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL))
69 {
70 prefix2str (&route->prefix, buf, sizeof (buf));
71 zlog_debug ("Originate AS-External-LSA for %s", buf);
72 }
73
74 /* prepare buffer */
75 memset (buffer, 0, sizeof (buffer));
76 lsa_header = (struct ospf6_lsa_header *) buffer;
77 as_external_lsa = (struct ospf6_as_external_lsa *)
78 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
79 p = (caddr_t)
80 ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa));
81
82 /* Fill AS-External-LSA */
83 /* Metric type */
84 if (route->path.metric_type == 2)
85 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
86 else
87 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
88
89 /* forwarding address */
90 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
91 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
92 else
93 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
94
95 /* external route tag */
96 if (info->tag)
97 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
98 else
99 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
100
101 /* Set metric */
102 OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);
103
104 /* prefixlen */
105 as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
106
107 /* PrefixOptions */
108 as_external_lsa->prefix.prefix_options = route->path.prefix_options;
109
110 /* don't use refer LS-type */
111 as_external_lsa->prefix.prefix_refer_lstype = htons (0);
112
113 /* set Prefix */
114 memcpy (p, &route->prefix.u.prefix6,
115 OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
116 ospf6_prefix_apply_mask (&as_external_lsa->prefix);
117 p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
118
119 /* Forwarding address */
120 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
121 {
122 memcpy (p, &info->forwarding, sizeof (struct in6_addr));
123 p += sizeof (struct in6_addr);
124 }
125
126 /* External Route Tag */
127 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
128 {
129 route_tag_t network_order = htonl(info->tag);
130
131 memcpy (p, &network_order, sizeof(network_order));
132 p += sizeof(network_order);
133 }
134
135 /* Fill LSA Header */
136 lsa_header->age = 0;
137 lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
138 lsa_header->id = route->path.origin.id;
139 lsa_header->adv_router = ospf6->router_id;
140 lsa_header->seqnum =
141 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
142 lsa_header->adv_router, ospf6->lsdb);
143 lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
144
145 /* LSA checksum */
146 ospf6_lsa_checksum (lsa_header);
147
148 /* create LSA */
149 lsa = ospf6_lsa_create (lsa_header);
150
151 /* Originate */
152 ospf6_lsa_originate_process (lsa, ospf6);
153 }
154
155 static route_tag_t
156 ospf6_as_external_lsa_get_tag (struct ospf6_lsa *lsa)
157 {
158 struct ospf6_as_external_lsa *external;
159 ptrdiff_t tag_offset;
160 route_tag_t network_order;
161
162 if (!lsa)
163 return 0;
164
165 external = (struct ospf6_as_external_lsa *)
166 OSPF6_LSA_HEADER_END (lsa->header);
167
168 if (!CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
169 return 0;
170
171 tag_offset = sizeof(*external) + OSPF6_PREFIX_SPACE(external->prefix.prefix_length);
172 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
173 tag_offset += sizeof(struct in6_addr);
174
175 memcpy(&network_order, (caddr_t)external + tag_offset, sizeof(network_order));
176 return ntohl(network_order);
177 }
178
179 void
180 ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
181 {
182 struct ospf6_as_external_lsa *external;
183 struct prefix asbr_id;
184 struct ospf6_route *asbr_entry, *route;
185 char buf[PREFIX2STR_BUFFER];
186
187 external = (struct ospf6_as_external_lsa *)
188 OSPF6_LSA_HEADER_END (lsa->header);
189
190 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
191 zlog_debug ("Calculate AS-External route for %s", lsa->name);
192
193 if (lsa->header->adv_router == ospf6->router_id)
194 {
195 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
196 zlog_debug ("Ignore self-originated AS-External-LSA");
197 return;
198 }
199
200 if (OSPF6_ASBR_METRIC (external) == OSPF_LS_INFINITY)
201 {
202 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
203 zlog_debug ("Ignore LSA with LSInfinity Metric");
204 return;
205 }
206
207 if (CHECK_FLAG(external->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU))
208 {
209 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
210 zlog_debug ("Ignore LSA with NU bit set Metric");
211 return;
212 }
213
214 ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
215 asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
216 if (asbr_entry == NULL ||
217 ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
218 {
219 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
220 {
221 prefix2str (&asbr_id, buf, sizeof (buf));
222 zlog_debug ("ASBR entry not found: %s", buf);
223 }
224 return;
225 }
226
227 route = ospf6_route_create ();
228 route->type = OSPF6_DEST_TYPE_NETWORK;
229 route->prefix.family = AF_INET6;
230 route->prefix.prefixlen = external->prefix.prefix_length;
231 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);
232
233 route->path.area_id = asbr_entry->path.area_id;
234 route->path.origin.type = lsa->header->type;
235 route->path.origin.id = lsa->header->id;
236 route->path.origin.adv_router = lsa->header->adv_router;
237
238 route->path.prefix_options = external->prefix.prefix_options;
239 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
240 {
241 route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
242 route->path.metric_type = 2;
243 route->path.cost = asbr_entry->path.cost;
244 route->path.u.cost_e2 = OSPF6_ASBR_METRIC (external);
245 }
246 else
247 {
248 route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
249 route->path.metric_type = 1;
250 route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
251 route->path.u.cost_e2 = 0;
252 }
253
254 route->path.tag = ospf6_as_external_lsa_get_tag (lsa);
255
256 ospf6_route_copy_nexthops (route, asbr_entry);
257
258 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
259 {
260 prefix2str (&route->prefix, buf, sizeof (buf));
261 zlog_debug ("AS-External route add: %s", buf);
262 }
263
264 ospf6_route_add (route, ospf6->route_table);
265 }
266
267 void
268 ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa)
269 {
270 struct ospf6_as_external_lsa *external;
271 struct prefix prefix;
272 struct ospf6_route *route, *nroute;
273 char buf[PREFIX2STR_BUFFER];
274
275 external = (struct ospf6_as_external_lsa *)
276 OSPF6_LSA_HEADER_END (lsa->header);
277
278 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
279 zlog_debug ("Withdraw AS-External route for %s", lsa->name);
280
281 if (lsa->header->adv_router == ospf6->router_id)
282 {
283 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
284 zlog_debug ("Ignore self-originated AS-External-LSA");
285 return;
286 }
287
288 memset (&prefix, 0, sizeof (struct prefix));
289 prefix.family = AF_INET6;
290 prefix.prefixlen = external->prefix.prefix_length;
291 ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix);
292
293 route = ospf6_route_lookup (&prefix, ospf6->route_table);
294 if (route == NULL)
295 {
296 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
297 {
298 prefix2str (&prefix, buf, sizeof (buf));
299 zlog_debug ("AS-External route %s not found", buf);
300 }
301 return;
302 }
303
304 for (ospf6_route_lock (route);
305 route && ospf6_route_is_prefix (&prefix, route);
306 route = nroute)
307 {
308 nroute = ospf6_route_next (route);
309 if (route->type != OSPF6_DEST_TYPE_NETWORK)
310 continue;
311 if (route->path.origin.type != lsa->header->type)
312 continue;
313 if (route->path.origin.id != lsa->header->id)
314 continue;
315 if (route->path.origin.adv_router != lsa->header->adv_router)
316 continue;
317
318 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
319 {
320 prefix2str (&route->prefix, buf, sizeof (buf));
321 zlog_debug ("AS-External route remove: %s", buf);
322 }
323 ospf6_route_remove (route, ospf6->route_table);
324 }
325 if (route != NULL)
326 ospf6_route_unlock (route);
327 }
328
329 void
330 ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
331 {
332 struct ospf6_lsa *lsa;
333 u_int16_t type;
334 u_int32_t router;
335
336 if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
337 {
338 char buf[16];
339 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
340 buf, sizeof (buf));
341 zlog_info ("ignore non-best path: lsentry %s add", buf);
342 return;
343 }
344
345 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
346 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
347 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
348 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
349 {
350 if (! OSPF6_LSA_IS_MAXAGE (lsa))
351 ospf6_asbr_lsa_add (lsa);
352 }
353 }
354
355 void
356 ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
357 {
358 struct ospf6_lsa *lsa;
359 u_int16_t type;
360 u_int32_t router;
361
362 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
363 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
364 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
365 lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
366 ospf6_asbr_lsa_remove (lsa);
367 }
368
369
370
371 /* redistribute function */
372
373 static void
374 ospf6_asbr_routemap_set (int type, const char *mapname)
375 {
376 if (ospf6->rmap[type].name)
377 free (ospf6->rmap[type].name);
378 ospf6->rmap[type].name = strdup (mapname);
379 ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
380 }
381
382 static void
383 ospf6_asbr_routemap_unset (int type)
384 {
385 if (ospf6->rmap[type].name)
386 free (ospf6->rmap[type].name);
387 ospf6->rmap[type].name = NULL;
388 ospf6->rmap[type].map = NULL;
389 }
390
391 static void
392 ospf6_asbr_routemap_update (const char *mapname)
393 {
394 int type;
395
396 if (ospf6 == NULL)
397 return;
398
399 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
400 {
401 if (ospf6->rmap[type].name)
402 ospf6->rmap[type].map =
403 route_map_lookup_by_name (ospf6->rmap[type].name);
404 else
405 ospf6->rmap[type].map = NULL;
406 }
407 }
408
409 int
410 ospf6_asbr_is_asbr (struct ospf6 *o)
411 {
412 return o->external_table->count;
413 }
414
415 static void
416 ospf6_asbr_redistribute_set (int type)
417 {
418 ospf6_zebra_redistribute (type);
419 }
420
421 static void
422 ospf6_asbr_redistribute_unset (int type)
423 {
424 struct ospf6_route *route;
425 struct ospf6_external_info *info;
426
427 ospf6_zebra_no_redistribute (type);
428
429 for (route = ospf6_route_head (ospf6->external_table); route;
430 route = ospf6_route_next (route))
431 {
432 info = route->route_option;
433 if (info->type != type)
434 continue;
435
436 ospf6_asbr_redistribute_remove (info->type, 0, &route->prefix);
437 }
438
439 ospf6_asbr_routemap_unset (type);
440 }
441
442 /* When an area is unstubified, flood all the external LSAs in the area */
443 void
444 ospf6_asbr_send_externals_to_area (struct ospf6_area *oa)
445 {
446 struct ospf6_lsa *lsa;
447
448 for (lsa = ospf6_lsdb_head (oa->ospf6->lsdb); lsa;
449 lsa = ospf6_lsdb_next (lsa))
450 {
451 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL)
452 {
453 zlog_debug ("%s: Flooding AS-External LSA %s\n", __func__, lsa->name);
454 ospf6_flood_area (NULL, lsa, oa);
455 }
456 }
457 }
458
459 void
460 ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix,
461 u_int nexthop_num, struct in6_addr *nexthop, route_tag_t tag)
462 {
463 int ret;
464 struct ospf6_route troute;
465 struct ospf6_external_info tinfo;
466 struct ospf6_route *route, *match;
467 struct ospf6_external_info *info;
468 struct prefix prefix_id;
469 struct route_node *node;
470 char pbuf[PREFIX2STR_BUFFER], ibuf[16];
471 struct listnode *lnode, *lnnode;
472 struct ospf6_area *oa;
473
474 if (! ospf6_zebra_is_redistribute (type))
475 return;
476
477 if (IS_OSPF6_DEBUG_ASBR)
478 {
479 prefix2str (prefix, pbuf, sizeof (pbuf));
480 zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
481 }
482
483 /* if route-map was specified but not found, do not advertise */
484 if (ospf6->rmap[type].name)
485 {
486 if (ospf6->rmap[type].map == NULL)
487 ospf6_asbr_routemap_update (NULL);
488 if (ospf6->rmap[type].map == NULL)
489 {
490 zlog_warn ("route-map \"%s\" not found, suppress redistributing",
491 ospf6->rmap[type].name);
492 return;
493 }
494 }
495
496 /* apply route-map */
497 if (ospf6->rmap[type].map)
498 {
499 memset (&troute, 0, sizeof (troute));
500 memset (&tinfo, 0, sizeof (tinfo));
501 troute.route_option = &tinfo;
502 tinfo.ifindex = ifindex;
503 tinfo.tag = tag;
504
505 ret = route_map_apply (ospf6->rmap[type].map, prefix,
506 RMAP_OSPF6, &troute);
507 if (ret == RMAP_DENYMATCH)
508 {
509 if (IS_OSPF6_DEBUG_ASBR)
510 zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
511 return;
512 }
513 }
514
515 match = ospf6_route_lookup (prefix, ospf6->external_table);
516 if (match)
517 {
518 info = match->route_option;
519
520 /* copy result of route-map */
521 if (ospf6->rmap[type].map)
522 {
523 if (troute.path.metric_type)
524 match->path.metric_type = troute.path.metric_type;
525 if (troute.path.cost)
526 match->path.cost = troute.path.cost;
527 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
528 memcpy (&info->forwarding, &tinfo.forwarding,
529 sizeof (struct in6_addr));
530 info->tag = tinfo.tag;
531 }
532 else
533 {
534 /* If there is no route-map, simply update the tag */
535 info->tag = tag;
536 }
537
538 info->type = type;
539
540 if (nexthop_num && nexthop)
541 ospf6_route_add_nexthop (match, ifindex, nexthop);
542 else
543 ospf6_route_add_nexthop (match, ifindex, NULL);
544
545 /* create/update binding in external_id_table */
546 prefix_id.family = AF_INET;
547 prefix_id.prefixlen = 32;
548 prefix_id.u.prefix4.s_addr = htonl (info->id);
549 node = route_node_get (ospf6->external_id_table, &prefix_id);
550 node->info = match;
551
552 if (IS_OSPF6_DEBUG_ASBR)
553 {
554 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
555 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
556 }
557
558 match->path.origin.id = htonl (info->id);
559 ospf6_as_external_lsa_originate (match);
560 return;
561 }
562
563 /* create new entry */
564 route = ospf6_route_create ();
565 route->type = OSPF6_DEST_TYPE_NETWORK;
566 memcpy (&route->prefix, prefix, sizeof (struct prefix));
567
568 info = (struct ospf6_external_info *)
569 XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
570 route->route_option = info;
571 info->id = ospf6->external_id++;
572
573 /* copy result of route-map */
574 if (ospf6->rmap[type].map)
575 {
576 if (troute.path.metric_type)
577 route->path.metric_type = troute.path.metric_type;
578 if (troute.path.cost)
579 route->path.cost = troute.path.cost;
580 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
581 memcpy (&info->forwarding, &tinfo.forwarding,
582 sizeof (struct in6_addr));
583 info->tag = tinfo.tag;
584 }
585 else
586 {
587 /* If there is no route-map, simply set the tag */
588 info->tag = tag;
589 }
590
591 info->type = type;
592 if (nexthop_num && nexthop)
593 ospf6_route_add_nexthop (route, ifindex, nexthop);
594 else
595 ospf6_route_add_nexthop (route, ifindex, NULL);
596
597 /* create/update binding in external_id_table */
598 prefix_id.family = AF_INET;
599 prefix_id.prefixlen = 32;
600 prefix_id.u.prefix4.s_addr = htonl (info->id);
601 node = route_node_get (ospf6->external_id_table, &prefix_id);
602 node->info = route;
603
604 route = ospf6_route_add (route, ospf6->external_table);
605 route->route_option = info;
606
607 if (IS_OSPF6_DEBUG_ASBR)
608 {
609 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
610 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
611 }
612
613 route->path.origin.id = htonl (info->id);
614 ospf6_as_external_lsa_originate (route);
615
616 /* Router-Bit (ASBR Flag) may have to be updated */
617 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
618 OSPF6_ROUTER_LSA_SCHEDULE (oa);
619 }
620
621 void
622 ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex,
623 struct prefix *prefix)
624 {
625 struct ospf6_route *match;
626 struct ospf6_external_info *info = NULL;
627 struct route_node *node;
628 struct ospf6_lsa *lsa;
629 struct prefix prefix_id;
630 char pbuf[PREFIX2STR_BUFFER], ibuf[16];
631 struct listnode *lnode, *lnnode;
632 struct ospf6_area *oa;
633
634 match = ospf6_route_lookup (prefix, ospf6->external_table);
635 if (match == NULL)
636 {
637 if (IS_OSPF6_DEBUG_ASBR)
638 {
639 prefix2str (prefix, pbuf, sizeof (pbuf));
640 zlog_debug ("No such route %s to withdraw", pbuf);
641 }
642 return;
643 }
644
645 info = match->route_option;
646 assert (info);
647
648 if (info->type != type)
649 {
650 if (IS_OSPF6_DEBUG_ASBR)
651 {
652 prefix2str (prefix, pbuf, sizeof (pbuf));
653 zlog_debug ("Original protocol mismatch: %s", pbuf);
654 }
655 return;
656 }
657
658 if (IS_OSPF6_DEBUG_ASBR)
659 {
660 prefix2str (prefix, pbuf, sizeof (pbuf));
661 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
662 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
663 }
664
665 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
666 htonl (info->id), ospf6->router_id, ospf6->lsdb);
667 if (lsa)
668 ospf6_lsa_purge (lsa);
669
670 /* remove binding in external_id_table */
671 prefix_id.family = AF_INET;
672 prefix_id.prefixlen = 32;
673 prefix_id.u.prefix4.s_addr = htonl (info->id);
674 node = route_node_lookup (ospf6->external_id_table, &prefix_id);
675 assert (node);
676 node->info = NULL;
677 route_unlock_node (node);
678
679 ospf6_route_remove (match, ospf6->external_table);
680 XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
681
682 /* Router-Bit (ASBR Flag) may have to be updated */
683 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
684 OSPF6_ROUTER_LSA_SCHEDULE (oa);
685 }
686
687 DEFUN (ospf6_redistribute,
688 ospf6_redistribute_cmd,
689 "redistribute " QUAGGA_REDIST_STR_OSPF6D,
690 "Redistribute\n"
691 QUAGGA_REDIST_HELP_STR_OSPF6D
692 )
693 {
694 int type;
695
696 type = proto_redistnum(AFI_IP6, argv[0]);
697 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
698 return CMD_WARNING;
699
700 ospf6_asbr_redistribute_unset (type);
701 ospf6_asbr_redistribute_set (type);
702 return CMD_SUCCESS;
703 }
704
705 DEFUN (ospf6_redistribute_routemap,
706 ospf6_redistribute_routemap_cmd,
707 "redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
708 "Redistribute\n"
709 QUAGGA_REDIST_HELP_STR_OSPF6D
710 "Route map reference\n"
711 "Route map name\n"
712 )
713 {
714 int type;
715
716 type = proto_redistnum(AFI_IP6, argv[0]);
717 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
718 return CMD_WARNING;
719
720 ospf6_asbr_redistribute_unset (type);
721 ospf6_asbr_routemap_set (type, argv[1]);
722 ospf6_asbr_redistribute_set (type);
723 return CMD_SUCCESS;
724 }
725
726 DEFUN (no_ospf6_redistribute,
727 no_ospf6_redistribute_cmd,
728 "no redistribute " QUAGGA_REDIST_STR_OSPF6D,
729 NO_STR
730 "Redistribute\n"
731 QUAGGA_REDIST_HELP_STR_OSPF6D
732 )
733 {
734 int type;
735
736 type = proto_redistnum(AFI_IP6, argv[0]);
737 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
738 return CMD_WARNING;
739
740 ospf6_asbr_redistribute_unset (type);
741
742 return CMD_SUCCESS;
743 }
744
745 ALIAS (no_ospf6_redistribute,
746 no_ospf6_redistribute_route_map_cmd,
747 "no redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
748 NO_STR
749 "Redistribute\n"
750 QUAGGA_REDIST_HELP_STR_OSPF6D
751 "Route map reference\n"
752 "Route map name\n")
753
754 int
755 ospf6_redistribute_config_write (struct vty *vty)
756 {
757 int type;
758
759 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
760 {
761 if (type == ZEBRA_ROUTE_OSPF6)
762 continue;
763 if (! ospf6_zebra_is_redistribute (type))
764 continue;
765
766 if (ospf6->rmap[type].name)
767 vty_out (vty, " redistribute %s route-map %s%s",
768 ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
769 else
770 vty_out (vty, " redistribute %s%s",
771 ZROUTE_NAME (type), VNL);
772 }
773
774 return 0;
775 }
776
777 static void
778 ospf6_redistribute_show_config (struct vty *vty)
779 {
780 int type;
781 int nroute[ZEBRA_ROUTE_MAX];
782 int total;
783 struct ospf6_route *route;
784 struct ospf6_external_info *info;
785
786 total = 0;
787 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
788 nroute[type] = 0;
789 for (route = ospf6_route_head (ospf6->external_table); route;
790 route = ospf6_route_next (route))
791 {
792 info = route->route_option;
793 nroute[info->type]++;
794 total++;
795 }
796
797 vty_out (vty, "Redistributing External Routes from:%s", VNL);
798 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
799 {
800 if (type == ZEBRA_ROUTE_OSPF6)
801 continue;
802 if (! ospf6_zebra_is_redistribute (type))
803 continue;
804
805 if (ospf6->rmap[type].name)
806 vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
807 ZROUTE_NAME (type), ospf6->rmap[type].name,
808 (ospf6->rmap[type].map ? "" : " (not found !)"),
809 VNL);
810 else
811 vty_out (vty, " %d: %s%s", nroute[type],
812 ZROUTE_NAME (type), VNL);
813 }
814 vty_out (vty, "Total %d routes%s", total, VNL);
815 }
816
817
818
819 /* Routemap Functions */
820 static route_map_result_t
821 ospf6_routemap_rule_match_address_prefixlist (void *rule,
822 struct prefix *prefix,
823 route_map_object_t type,
824 void *object)
825 {
826 struct prefix_list *plist;
827
828 if (type != RMAP_OSPF6)
829 return RMAP_NOMATCH;
830
831 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
832 if (plist == NULL)
833 return RMAP_NOMATCH;
834
835 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
836 RMAP_NOMATCH : RMAP_MATCH);
837 }
838
839 static void *
840 ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
841 {
842 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
843 }
844
845 static void
846 ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
847 {
848 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
849 }
850
851 struct route_map_rule_cmd
852 ospf6_routemap_rule_match_address_prefixlist_cmd =
853 {
854 "ipv6 address prefix-list",
855 ospf6_routemap_rule_match_address_prefixlist,
856 ospf6_routemap_rule_match_address_prefixlist_compile,
857 ospf6_routemap_rule_match_address_prefixlist_free,
858 };
859
860 /* `match interface IFNAME' */
861 /* Match function should return 1 if match is success else return
862 zero. */
863 static route_map_result_t
864 ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix,
865 route_map_object_t type, void *object)
866 {
867 struct interface *ifp;
868 struct ospf6_external_info *ei;
869
870 if (type == RMAP_OSPF6)
871 {
872 ei = ((struct ospf6_route *) object)->route_option;
873 ifp = if_lookup_by_name ((char *)rule);
874
875 if (ifp != NULL
876 && ei->ifindex == ifp->ifindex)
877 return RMAP_MATCH;
878 }
879
880 return RMAP_NOMATCH;
881 }
882
883 /* Route map `interface' match statement. `arg' should be
884 interface name. */
885 static void *
886 ospf6_routemap_rule_match_interface_compile (const char *arg)
887 {
888 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
889 }
890
891 /* Free route map's compiled `interface' value. */
892 static void
893 ospf6_routemap_rule_match_interface_free (void *rule)
894 {
895 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
896 }
897
898 /* Route map commands for interface matching. */
899 struct route_map_rule_cmd
900 ospf6_routemap_rule_match_interface_cmd =
901 {
902 "interface",
903 ospf6_routemap_rule_match_interface,
904 ospf6_routemap_rule_match_interface_compile,
905 ospf6_routemap_rule_match_interface_free
906 };
907
908 /* Match function for matching route tags */
909 static route_map_result_t
910 ospf6_routemap_rule_match_tag (void *rule, struct prefix *prefix,
911 route_map_object_t type, void *object)
912 {
913 route_tag_t *tag = rule;
914 struct ospf6_route *route = object;
915 struct ospf6_external_info *info = route->route_option;
916
917 if (type == RMAP_OSPF6 && info->tag == *tag)
918 return RMAP_MATCH;
919
920 return RMAP_NOMATCH;
921 }
922
923 static struct route_map_rule_cmd
924 ospf6_routemap_rule_match_tag_cmd =
925 {
926 "tag",
927 ospf6_routemap_rule_match_tag,
928 route_map_rule_tag_compile,
929 route_map_rule_tag_free,
930 };
931
932 static route_map_result_t
933 ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
934 route_map_object_t type, void *object)
935 {
936 char *metric_type = rule;
937 struct ospf6_route *route = object;
938
939 if (type != RMAP_OSPF6)
940 return RMAP_OKAY;
941
942 if (strcmp (metric_type, "type-2") == 0)
943 route->path.metric_type = 2;
944 else
945 route->path.metric_type = 1;
946
947 return RMAP_OKAY;
948 }
949
950 static void *
951 ospf6_routemap_rule_set_metric_type_compile (const char *arg)
952 {
953 if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
954 return NULL;
955 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
956 }
957
958 static void
959 ospf6_routemap_rule_set_metric_type_free (void *rule)
960 {
961 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
962 }
963
964 struct route_map_rule_cmd
965 ospf6_routemap_rule_set_metric_type_cmd =
966 {
967 "metric-type",
968 ospf6_routemap_rule_set_metric_type,
969 ospf6_routemap_rule_set_metric_type_compile,
970 ospf6_routemap_rule_set_metric_type_free,
971 };
972
973 static route_map_result_t
974 ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
975 route_map_object_t type, void *object)
976 {
977 char *metric = rule;
978 struct ospf6_route *route = object;
979
980 if (type != RMAP_OSPF6)
981 return RMAP_OKAY;
982
983 route->path.cost = atoi (metric);
984 return RMAP_OKAY;
985 }
986
987 static void *
988 ospf6_routemap_rule_set_metric_compile (const char *arg)
989 {
990 u_int32_t metric;
991 char *endp;
992 metric = strtoul (arg, &endp, 0);
993 if (metric > OSPF_LS_INFINITY || *endp != '\0')
994 return NULL;
995 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
996 }
997
998 static void
999 ospf6_routemap_rule_set_metric_free (void *rule)
1000 {
1001 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1002 }
1003
1004 struct route_map_rule_cmd
1005 ospf6_routemap_rule_set_metric_cmd =
1006 {
1007 "metric",
1008 ospf6_routemap_rule_set_metric,
1009 ospf6_routemap_rule_set_metric_compile,
1010 ospf6_routemap_rule_set_metric_free,
1011 };
1012
1013 static route_map_result_t
1014 ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
1015 route_map_object_t type, void *object)
1016 {
1017 char *forwarding = rule;
1018 struct ospf6_route *route = object;
1019 struct ospf6_external_info *info = route->route_option;
1020
1021 if (type != RMAP_OSPF6)
1022 return RMAP_OKAY;
1023
1024 if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
1025 {
1026 memset (&info->forwarding, 0, sizeof (struct in6_addr));
1027 return RMAP_ERROR;
1028 }
1029
1030 return RMAP_OKAY;
1031 }
1032
1033 static void *
1034 ospf6_routemap_rule_set_forwarding_compile (const char *arg)
1035 {
1036 struct in6_addr a;
1037 if (inet_pton (AF_INET6, arg, &a) != 1)
1038 return NULL;
1039 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1040 }
1041
1042 static void
1043 ospf6_routemap_rule_set_forwarding_free (void *rule)
1044 {
1045 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1046 }
1047
1048 struct route_map_rule_cmd
1049 ospf6_routemap_rule_set_forwarding_cmd =
1050 {
1051 "forwarding-address",
1052 ospf6_routemap_rule_set_forwarding,
1053 ospf6_routemap_rule_set_forwarding_compile,
1054 ospf6_routemap_rule_set_forwarding_free,
1055 };
1056
1057 static route_map_result_t
1058 ospf6_routemap_rule_set_tag (void *rule, struct prefix *prefix,
1059 route_map_object_t type, void *object)
1060 {
1061 route_tag_t *tag = rule;
1062 struct ospf6_route *route = object;
1063 struct ospf6_external_info *info = route->route_option;
1064
1065 if (type != RMAP_OSPF6)
1066 return RMAP_OKAY;
1067
1068 info->tag = *tag;
1069 return RMAP_OKAY;
1070 }
1071
1072 static struct route_map_rule_cmd
1073 ospf6_routemap_rule_set_tag_cmd =
1074 {
1075 "tag",
1076 ospf6_routemap_rule_set_tag,
1077 route_map_rule_tag_compile,
1078 route_map_rule_tag_free,
1079 };
1080
1081 static int
1082 route_map_command_status (struct vty *vty, int ret)
1083 {
1084 if (! ret)
1085 return CMD_SUCCESS;
1086
1087 switch (ret)
1088 {
1089 case RMAP_RULE_MISSING:
1090 vty_out (vty, "OSPF6 Can't find rule.%s", VNL);
1091 break;
1092 case RMAP_COMPILE_ERROR:
1093 vty_out (vty, "OSPF6 Argument is malformed.%s", VNL);
1094 break;
1095 default:
1096 vty_out (vty, "OSPF6 route-map add set failed.%s", VNL);
1097 break;
1098 }
1099 return CMD_WARNING;
1100 }
1101
1102 /* add "match address" */
1103 DEFUN (ospf6_routemap_match_address_prefixlist,
1104 ospf6_routemap_match_address_prefixlist_cmd,
1105 "match ipv6 address prefix-list WORD",
1106 "Match values\n"
1107 IPV6_STR
1108 "Match address of route\n"
1109 "Match entries of prefix-lists\n"
1110 "IPv6 prefix-list name\n")
1111 {
1112 int ret = route_map_add_match ((struct route_map_index *) vty->index,
1113 "ipv6 address prefix-list", argv[0]);
1114 return route_map_command_status (vty, ret);
1115 }
1116
1117 /* delete "match address" */
1118 DEFUN (ospf6_routemap_no_match_address_prefixlist,
1119 ospf6_routemap_no_match_address_prefixlist_cmd,
1120 "no match ipv6 address prefix-list WORD",
1121 NO_STR
1122 "Match values\n"
1123 IPV6_STR
1124 "Match address of route\n"
1125 "Match entries of prefix-lists\n"
1126 "IPv6 prefix-list name\n")
1127 {
1128 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1129 "ipv6 address prefix-list", argv[0]);
1130 return route_map_command_status (vty, ret);
1131 }
1132
1133 /* "match interface" */
1134 DEFUN (ospf6_routemap_match_interface,
1135 ospf6_routemap_match_interface_cmd,
1136 "match interface WORD",
1137 MATCH_STR
1138 "Match first hop interface of route\n"
1139 "Interface name\n")
1140 {
1141 return route_map_add_match ((struct route_map_index *) vty->index,
1142 "interface", argv[0]);
1143 }
1144
1145 /* "no match interface WORD" */
1146 DEFUN (ospf6_routemap_no_match_interface,
1147 ospf6_routemap_no_match_interface_cmd,
1148 "no match interface",
1149 NO_STR
1150 MATCH_STR
1151 "Match first hop interface of route\n")
1152 {
1153 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1154 "interface", (argc == 0) ? NULL : argv[0]);
1155 return route_map_command_status (vty, ret);
1156 }
1157
1158 ALIAS (ospf6_routemap_no_match_interface,
1159 ospf6_routemap_no_match_interface_val_cmd,
1160 "no match interface WORD",
1161 NO_STR
1162 MATCH_STR
1163 "Match first hop interface of route\n"
1164 "Interface name\n")
1165
1166 /* add "match tag" */
1167 DEFUN (ospf6_routemap_match_tag,
1168 ospf6_routemap_match_tag_cmd,
1169 "match tag <1-4294967295>",
1170 MATCH_STR
1171 "Tag value for routing protocol\n"
1172 "Tag value\n")
1173 {
1174 int ret = route_map_add_match ((struct route_map_index *) vty->index,
1175 "tag", argv[0]);
1176 return route_map_command_status (vty, ret);
1177 }
1178
1179 /* delete "match tag" */
1180 DEFUN (ospf6_routemap_no_match_tag,
1181 ospf6_routemap_no_match_tag_cmd,
1182 "no match tag",
1183 NO_STR
1184 MATCH_STR
1185 "Tag value for routing protocol\n")
1186 {
1187 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1188 "tag", argc ? argv[0] : NULL);
1189 return route_map_command_status (vty, ret);
1190 }
1191
1192 ALIAS (ospf6_routemap_no_match_tag,
1193 ospf6_routemap_no_match_tag_val_cmd,
1194 "no match tag <1-4294967295>",
1195 NO_STR
1196 MATCH_STR
1197 "Tag value for routing protocol\n"
1198 "Tag value\n")
1199
1200 /* add "set metric-type" */
1201 DEFUN (ospf6_routemap_set_metric_type,
1202 ospf6_routemap_set_metric_type_cmd,
1203 "set metric-type (type-1|type-2)",
1204 "Set value\n"
1205 "Type of metric\n"
1206 "OSPF6 external type 1 metric\n"
1207 "OSPF6 external type 2 metric\n")
1208 {
1209 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1210 "metric-type", argv[0]);
1211 return route_map_command_status (vty, ret);
1212 }
1213
1214 /* delete "set metric-type" */
1215 DEFUN (ospf6_routemap_no_set_metric_type,
1216 ospf6_routemap_no_set_metric_type_cmd,
1217 "no set metric-type (type-1|type-2)",
1218 NO_STR
1219 "Set value\n"
1220 "Type of metric\n"
1221 "OSPF6 external type 1 metric\n"
1222 "OSPF6 external type 2 metric\n")
1223 {
1224 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1225 "metric-type", argv[0]);
1226 return route_map_command_status (vty, ret);
1227 }
1228
1229 /* add "set metric" */
1230 DEFUN (set_metric,
1231 set_metric_cmd,
1232 "set metric <0-4294967295>",
1233 "Set value\n"
1234 "Metric value\n"
1235 "Metric value\n")
1236 {
1237 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1238 "metric", argv[0]);
1239 return route_map_command_status (vty, ret);
1240 }
1241
1242 /* delete "set metric" */
1243 DEFUN (no_set_metric,
1244 no_set_metric_cmd,
1245 "no set metric",
1246 NO_STR
1247 SET_STR
1248 "Metric value for destination routing protocol\n")
1249 {
1250 int ret = 0;
1251
1252 if (argc == 0)
1253 ret = route_map_delete_set ((struct route_map_index *) vty->index,
1254 "metric", NULL);
1255 else
1256 ret = route_map_delete_set ((struct route_map_index *) vty->index,
1257 "metric", argv[0]);
1258 return route_map_command_status (vty, ret);
1259 }
1260
1261 ALIAS (no_set_metric,
1262 no_set_metric_val_cmd,
1263 "no set metric <0-4294967295>",
1264 NO_STR
1265 SET_STR
1266 "Metric value for destination routing protocol\n"
1267 "Metric value\n")
1268
1269 /* add "set forwarding-address" */
1270 DEFUN (ospf6_routemap_set_forwarding,
1271 ospf6_routemap_set_forwarding_cmd,
1272 "set forwarding-address X:X::X:X",
1273 "Set value\n"
1274 "Forwarding Address\n"
1275 "IPv6 Address\n")
1276 {
1277 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1278 "forwarding-address", argv[0]);
1279 return route_map_command_status (vty, ret);
1280 }
1281
1282 /* delete "set forwarding-address" */
1283 DEFUN (ospf6_routemap_no_set_forwarding,
1284 ospf6_routemap_no_set_forwarding_cmd,
1285 "no set forwarding-address X:X::X:X",
1286 NO_STR
1287 "Set value\n"
1288 "Forwarding Address\n"
1289 "IPv6 Address\n")
1290 {
1291 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1292 "forwarding-address", argv[0]);
1293 return route_map_command_status (vty, ret);
1294 }
1295
1296 /* add "set tag" */
1297 DEFUN (ospf6_routemap_set_tag,
1298 ospf6_routemap_set_tag_cmd,
1299 "set tag <1-4294967295>",
1300 "Set value\n"
1301 "Tag value for routing protocol\n"
1302 "Tag value\n")
1303 {
1304 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1305 "tag", argv[0]);
1306 return route_map_command_status (vty, ret);
1307 }
1308
1309 /* delete "set tag" */
1310 DEFUN (ospf6_routemap_no_set_tag,
1311 ospf6_routemap_no_set_tag_cmd,
1312 "no set tag",
1313 NO_STR
1314 "Set value\n"
1315 "Tag value for routing protocol\n")
1316 {
1317 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1318 "tag", argc ? argv[0] : NULL);
1319 return route_map_command_status (vty, ret);
1320 }
1321
1322 ALIAS (ospf6_routemap_no_set_tag,
1323 ospf6_routemap_no_set_tag_val_cmd,
1324 "no set tag <1-4294967295>",
1325 NO_STR
1326 "Set value\n"
1327 "Tag value for routing protocol\n"
1328 "Tag value\n")
1329
1330 static void
1331 ospf6_routemap_init (void)
1332 {
1333 route_map_init ();
1334 route_map_init_vty ();
1335 route_map_add_hook (ospf6_asbr_routemap_update);
1336 route_map_delete_hook (ospf6_asbr_routemap_update);
1337
1338 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
1339 route_map_install_match (&ospf6_routemap_rule_match_interface_cmd);
1340 route_map_install_match (&ospf6_routemap_rule_match_tag_cmd);
1341
1342 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
1343 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
1344 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
1345 route_map_install_set (&ospf6_routemap_rule_set_tag_cmd);
1346
1347 /* Match address prefix-list */
1348 install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
1349 install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
1350
1351 /* Match interface */
1352 install_element (RMAP_NODE, &ospf6_routemap_match_interface_cmd);
1353 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_cmd);
1354 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_val_cmd);
1355
1356 /* Match tag */
1357 install_element (RMAP_NODE, &ospf6_routemap_match_tag_cmd);
1358 install_element (RMAP_NODE, &ospf6_routemap_no_match_tag_cmd);
1359 install_element (RMAP_NODE, &ospf6_routemap_no_match_tag_val_cmd);
1360
1361 /* ASE Metric Type (e.g. Type-1/Type-2) */
1362 install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1363 install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
1364
1365 /* ASE Metric */
1366 install_element (RMAP_NODE, &set_metric_cmd);
1367 install_element (RMAP_NODE, &no_set_metric_cmd);
1368 install_element (RMAP_NODE, &no_set_metric_val_cmd);
1369
1370 /* Forwarding address */
1371 install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1372 install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
1373
1374 /* Tag */
1375 install_element (RMAP_NODE, &ospf6_routemap_set_tag_cmd);
1376 install_element (RMAP_NODE, &ospf6_routemap_no_set_tag_cmd);
1377 install_element (RMAP_NODE, &ospf6_routemap_no_set_tag_val_cmd);
1378 }
1379
1380
1381 /* Display functions */
1382 static char *
1383 ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
1384 int buflen, int pos)
1385 {
1386 struct ospf6_as_external_lsa *external;
1387 struct in6_addr in6;
1388 int prefix_length = 0;
1389
1390 if (lsa)
1391 {
1392 external = (struct ospf6_as_external_lsa *)
1393 OSPF6_LSA_HEADER_END (lsa->header);
1394
1395 if (pos == 0)
1396 {
1397 ospf6_prefix_in6_addr (&in6, &external->prefix);
1398 prefix_length = external->prefix.prefix_length;
1399 }
1400 else {
1401 in6 = *((struct in6_addr *)
1402 ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
1403 OSPF6_PREFIX_SPACE (external->prefix.prefix_length)));
1404 }
1405 if (buf)
1406 {
1407 inet_ntop (AF_INET6, &in6, buf, buflen);
1408 if (prefix_length)
1409 sprintf (&buf[strlen(buf)], "/%d", prefix_length);
1410 }
1411 }
1412 return (buf);
1413 }
1414
1415 static int
1416 ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1417 {
1418 struct ospf6_as_external_lsa *external;
1419 char buf[64];
1420
1421 assert (lsa->header);
1422 external = (struct ospf6_as_external_lsa *)
1423 OSPF6_LSA_HEADER_END (lsa->header);
1424
1425 /* bits */
1426 snprintf (buf, sizeof (buf), "%c%c%c",
1427 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
1428 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
1429 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
1430
1431 vty_out (vty, " Bits: %s%s", buf, VNL);
1432 vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
1433 VNL);
1434
1435 ospf6_prefix_options_printbuf (external->prefix.prefix_options,
1436 buf, sizeof (buf));
1437 vty_out (vty, " Prefix Options: %s%s", buf,
1438 VNL);
1439
1440 vty_out (vty, " Referenced LSType: %d%s",
1441 ntohs (external->prefix.prefix_refer_lstype),
1442 VNL);
1443
1444 vty_out (vty, " Prefix: %s%s",
1445 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0), VNL);
1446
1447 /* Forwarding-Address */
1448 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
1449 {
1450 vty_out (vty, " Forwarding-Address: %s%s",
1451 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1),
1452 VNL);
1453 }
1454
1455 /* Tag */
1456 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
1457 {
1458 vty_out (vty, " Tag: %"ROUTE_TAG_PRI"%s",
1459 ospf6_as_external_lsa_get_tag (lsa), VNL);
1460 }
1461
1462 return 0;
1463 }
1464
1465 static void
1466 ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
1467 {
1468 struct ospf6_external_info *info = route->route_option;
1469 char prefix[PREFIX2STR_BUFFER], id[16], forwarding[64];
1470 u_int32_t tmp_id;
1471
1472 prefix2str (&route->prefix, prefix, sizeof (prefix));
1473 tmp_id = ntohl (info->id);
1474 inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
1475 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
1476 inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
1477 else
1478 snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
1479 ospf6_route_get_first_nh_index (route));
1480
1481 vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
1482 zebra_route_char(info->type),
1483 prefix, id, route->path.metric_type,
1484 (u_long) (route->path.metric_type == 2 ?
1485 route->path.u.cost_e2 : route->path.cost),
1486 forwarding, VNL);
1487 }
1488
1489 DEFUN (show_ipv6_ospf6_redistribute,
1490 show_ipv6_ospf6_redistribute_cmd,
1491 "show ipv6 ospf6 redistribute",
1492 SHOW_STR
1493 IP6_STR
1494 OSPF6_STR
1495 "redistributing External information\n"
1496 )
1497 {
1498 struct ospf6_route *route;
1499
1500 OSPF6_CMD_CHECK_RUNNING ();
1501
1502 ospf6_redistribute_show_config (vty);
1503
1504 for (route = ospf6_route_head (ospf6->external_table); route;
1505 route = ospf6_route_next (route))
1506 ospf6_asbr_external_route_show (vty, route);
1507
1508 return CMD_SUCCESS;
1509 }
1510
1511 struct ospf6_lsa_handler as_external_handler =
1512 {
1513 OSPF6_LSTYPE_AS_EXTERNAL,
1514 "AS-External",
1515 "ASE",
1516 ospf6_as_external_lsa_show,
1517 ospf6_as_external_lsa_get_prefix_str
1518 };
1519
1520 void
1521 ospf6_asbr_init (void)
1522 {
1523 ospf6_routemap_init ();
1524
1525 ospf6_install_lsa_handler (&as_external_handler);
1526
1527 install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
1528 install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
1529
1530 install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1531 install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1532 install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
1533 install_element (OSPF6_NODE, &no_ospf6_redistribute_route_map_cmd);
1534 }
1535
1536 void
1537 ospf6_asbr_redistribute_reset (void)
1538 {
1539 int type;
1540
1541 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
1542 {
1543 if (type == ZEBRA_ROUTE_OSPF6)
1544 continue;
1545 if (ospf6_zebra_is_redistribute (type))
1546 ospf6_asbr_redistribute_unset(type);
1547 }
1548 }
1549
1550 void
1551 ospf6_asbr_terminate (void)
1552 {
1553 route_map_finish ();
1554 }
1555
1556 DEFUN (debug_ospf6_asbr,
1557 debug_ospf6_asbr_cmd,
1558 "debug ospf6 asbr",
1559 DEBUG_STR
1560 OSPF6_STR
1561 "Debug OSPFv3 ASBR function\n"
1562 )
1563 {
1564 OSPF6_DEBUG_ASBR_ON ();
1565 return CMD_SUCCESS;
1566 }
1567
1568 DEFUN (no_debug_ospf6_asbr,
1569 no_debug_ospf6_asbr_cmd,
1570 "no debug ospf6 asbr",
1571 NO_STR
1572 DEBUG_STR
1573 OSPF6_STR
1574 "Debug OSPFv3 ASBR function\n"
1575 )
1576 {
1577 OSPF6_DEBUG_ASBR_OFF ();
1578 return CMD_SUCCESS;
1579 }
1580
1581 int
1582 config_write_ospf6_debug_asbr (struct vty *vty)
1583 {
1584 if (IS_OSPF6_DEBUG_ASBR)
1585 vty_out (vty, "debug ospf6 asbr%s", VNL);
1586 return 0;
1587 }
1588
1589 void
1590 install_element_ospf6_debug_asbr ()
1591 {
1592 install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
1593 install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1594 install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
1595 install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
1596 }
1597
1598