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