ospf6_asbr.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:35k
源码类别:

网络

开发平台:

Unix_Linux

  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. #include <zebra.h>
  22. #include "log.h"
  23. #include "memory.h"
  24. #include "prefix.h"
  25. #include "command.h"
  26. #include "vty.h"
  27. #include "routemap.h"
  28. #include "table.h"
  29. #include "plist.h"
  30. #include "thread.h"
  31. #include "linklist.h"
  32. #include "ospf6_proto.h"
  33. #include "ospf6_lsa.h"
  34. #include "ospf6_lsdb.h"
  35. #include "ospf6_route.h"
  36. #include "ospf6_zebra.h"
  37. #include "ospf6_message.h"
  38. #include "ospf6_top.h"
  39. #include "ospf6_area.h"
  40. #include "ospf6_interface.h"
  41. #include "ospf6_neighbor.h"
  42. #include "ospf6_asbr.h"
  43. #include "ospf6_intra.h"
  44. #include "ospf6_flood.h"
  45. #include "ospf6d.h"
  46. unsigned char conf_debug_ospf6_asbr = 0;
  47. char *zroute_name[] =
  48. { "system", "kernel", "connected", "static",
  49.   "rip", "ripng", "ospf", "ospf6", "bgp", "unknown" };
  50. char *zroute_abname[] =
  51. { "X", "K", "C", "S", "R", "R", "O", "O", "B", "?" };
  52. #define ZROUTE_NAME(x)                                     
  53.   (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? zroute_name[(x)] :   
  54.    zroute_name[ZEBRA_ROUTE_MAX])
  55. #define ZROUTE_ABNAME(x)                                   
  56.   (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? zroute_abname[(x)] : 
  57.    zroute_abname[ZEBRA_ROUTE_MAX])
  58. /* AS External LSA origination */
  59. void
  60. ospf6_as_external_lsa_originate (struct ospf6_route *route)
  61. {
  62.   char buffer[OSPF6_MAX_LSASIZE];
  63.   struct ospf6_lsa_header *lsa_header;
  64.   struct ospf6_lsa *old, *lsa;
  65.   struct ospf6_as_external_lsa *as_external_lsa;
  66.   char buf[64];
  67.   caddr_t p;
  68.   /* find previous LSA */
  69.   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
  70.                            route->path.origin.id, ospf6->router_id,
  71.                            ospf6->lsdb);
  72.   if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL))
  73.     {
  74.       prefix2str (&route->prefix, buf, sizeof (buf));
  75.       zlog_info ("Originate AS-External-LSA for %s", buf);
  76.     }
  77.   /* prepare buffer */
  78.   memset (buffer, 0, sizeof (buffer));
  79.   lsa_header = (struct ospf6_lsa_header *) buffer;
  80.   as_external_lsa = (struct ospf6_as_external_lsa *)
  81.     ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
  82.   p = (caddr_t)
  83.     ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa));
  84.   /* Fill AS-External-LSA */
  85.   /* Metric type */
  86.   if (route->path.metric_type == 2)
  87.     SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
  88.   else
  89.     UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
  90.   /* forwarding address */
  91.   if (! IN6_IS_ADDR_UNSPECIFIED (&route->nexthop[0].address))
  92.     SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
  93.   else
  94.     UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
  95.   /* external route tag */
  96.   UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
  97.   /* Set metric */
  98.   OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);
  99.   /* prefixlen */
  100.   as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
  101.   /* PrefixOptions */
  102.   as_external_lsa->prefix.prefix_options = route->path.prefix_options;
  103.   /* don't use refer LS-type */
  104.   as_external_lsa->prefix.prefix_refer_lstype = htons (0);
  105.   /* set Prefix */
  106.   memcpy (p, &route->prefix.u.prefix6,
  107.           OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
  108.   ospf6_prefix_apply_mask (&as_external_lsa->prefix);
  109.   p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
  110.   /* Forwarding address */
  111.   if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
  112.     {
  113.       memcpy (p, &route->nexthop[0].address, sizeof (struct in6_addr));
  114.       p += sizeof (struct in6_addr);
  115.     }
  116.   /* External Route Tag */
  117.   if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
  118.     {
  119.       /* xxx */
  120.     }
  121.   /* Fill LSA Header */
  122.   lsa_header->age = 0;
  123.   lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
  124.   lsa_header->id = route->path.origin.id;
  125.   lsa_header->adv_router = ospf6->router_id;
  126.   lsa_header->seqnum =
  127.     ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
  128.                          lsa_header->adv_router, ospf6->lsdb);
  129.   lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
  130.   /* LSA checksum */
  131.   ospf6_lsa_checksum (lsa_header);
  132.   /* create LSA */
  133.   lsa = ospf6_lsa_create (lsa_header);
  134.   /* Originate */
  135.   ospf6_lsa_originate_process (lsa, ospf6);
  136. }
  137. void
  138. ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
  139. {
  140.   struct ospf6_as_external_lsa *external;
  141.   struct prefix asbr_id;
  142.   struct ospf6_route *asbr_entry, *route;
  143.   char buf[64];
  144.   int i;
  145.   external = (struct ospf6_as_external_lsa *)
  146.     OSPF6_LSA_HEADER_END (lsa->header);
  147.   if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  148.     zlog_info ("Calculate AS-External route for %s", lsa->name);
  149.   if (lsa->header->adv_router == ospf6->router_id)
  150.     {
  151.       if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  152.         zlog_info ("Ignore self-originated AS-External-LSA");
  153.       return;
  154.     }
  155.   if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
  156.     {
  157.       if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  158.         zlog_info ("Ignore LSA with LSInfinity Metric");
  159.       return;
  160.     }
  161.   ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
  162.   asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
  163.   if (asbr_entry == NULL ||
  164.       ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
  165.     {
  166.       if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  167.         {
  168.           prefix2str (&asbr_id, buf, sizeof (buf));
  169.           zlog_info ("ASBR entry not found: %s", buf);
  170.         }
  171.       return;
  172.     }
  173.   route = ospf6_route_create ();
  174.   route->type = OSPF6_DEST_TYPE_NETWORK;
  175.   route->prefix.family = AF_INET6;
  176.   route->prefix.prefixlen = external->prefix.prefix_length;
  177.   ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);
  178.   route->path.area_id = asbr_entry->path.area_id;
  179.   route->path.origin.type = lsa->header->type;
  180.   route->path.origin.id = lsa->header->id;
  181.   route->path.origin.adv_router = lsa->header->adv_router;
  182.   route->path.prefix_options = external->prefix.prefix_options;
  183.   if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
  184.     {
  185.       route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
  186.       route->path.metric_type = 2;
  187.       route->path.cost = asbr_entry->path.cost;
  188.       route->path.cost_e2 = OSPF6_ASBR_METRIC (external);
  189.     }
  190.   else
  191.     {
  192.       route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
  193.       route->path.metric_type = 1;
  194.       route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
  195.       route->path.cost_e2 = 0;
  196.     }
  197.   for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
  198.     ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);
  199.   if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  200.     {
  201.       prefix2str (&route->prefix, buf, sizeof (buf));
  202.       zlog_info ("AS-External route add: %s", buf);
  203.     }
  204.   ospf6_route_add (route, ospf6->route_table);
  205. }
  206. void
  207. ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa)
  208. {
  209.   struct ospf6_as_external_lsa *external;
  210.   struct prefix prefix;
  211.   struct ospf6_route *route;
  212.   char buf[64];
  213.   external = (struct ospf6_as_external_lsa *)
  214.     OSPF6_LSA_HEADER_END (lsa->header);
  215.   if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  216.     zlog_info ("Withdraw AS-External route for %s", lsa->name);
  217.   if (lsa->header->adv_router == ospf6->router_id)
  218.     {
  219.       if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  220.         zlog_info ("Ignore self-originated AS-External-LSA");
  221.       return;
  222.     }
  223.   memset (&prefix, 0, sizeof (struct prefix));
  224.   prefix.family = AF_INET6;
  225.   prefix.prefixlen = external->prefix.prefix_length;
  226.   ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix);
  227.   route = ospf6_route_lookup (&prefix, ospf6->route_table);
  228.   if (route == NULL)
  229.     {
  230.       if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  231.         {
  232.           prefix2str (&prefix, buf, sizeof (buf));
  233.           zlog_info ("AS-External route %s not found", buf);
  234.         }
  235.       return;
  236.     }
  237.   for (ospf6_route_lock (route);
  238.        route && ospf6_route_is_prefix (&prefix, route);
  239.        route = ospf6_route_next (route))
  240.     {
  241.       if (route->type != OSPF6_DEST_TYPE_NETWORK)
  242.         continue;
  243.       if (route->path.origin.type != lsa->header->type)
  244.         continue;
  245.       if (route->path.origin.id != lsa->header->id)
  246.         continue;
  247.       if (route->path.origin.adv_router != lsa->header->adv_router)
  248.         continue;
  249.       if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  250.         {
  251.           prefix2str (&route->prefix, buf, sizeof (buf));
  252.           zlog_info ("AS-External route remove: %s", buf);
  253.         }
  254.       ospf6_route_remove (route, ospf6->route_table);
  255.     }
  256. }
  257. void
  258. ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
  259. {
  260.   char buf[64];
  261.   struct ospf6_lsa *lsa;
  262.   u_int16_t type;
  263.   u_int32_t router;
  264.   if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  265.     {
  266.       ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf));
  267.       zlog_info ("New ASBR %s found", buf);
  268.     }
  269.   type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
  270.   router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
  271.   for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
  272.        lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
  273.     {
  274.       if (! OSPF6_LSA_IS_MAXAGE (lsa))
  275.         ospf6_asbr_lsa_add (lsa);
  276.     }
  277.   if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  278.     {
  279.       ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf));
  280.       zlog_info ("Calculation for new ASBR %s done", buf);
  281.     }
  282. }
  283. void
  284. ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
  285. {
  286.   char buf[64];
  287.   struct ospf6_lsa *lsa;
  288.   u_int16_t type;
  289.   u_int32_t router;
  290.   if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  291.     {
  292.       ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf));
  293.       zlog_info ("ASBR %s disappeared", buf);
  294.     }
  295.   type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
  296.   router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
  297.   for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
  298.        lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
  299.     ospf6_asbr_lsa_remove (lsa);
  300.   if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
  301.     {
  302.       ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf));
  303.       zlog_info ("Calculation for old ASBR %s done", buf);
  304.     }
  305. }
  306. /* redistribute function */
  307. void
  308. ospf6_asbr_routemap_set (int type, char *mapname)
  309. {
  310.   if (ospf6->rmap[type].name)
  311.     free (ospf6->rmap[type].name);
  312.   ospf6->rmap[type].name = strdup (mapname);
  313.   ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
  314. }
  315. void
  316. ospf6_asbr_routemap_unset (int type)
  317. {
  318.   if (ospf6->rmap[type].name)
  319.     free (ospf6->rmap[type].name);
  320.   ospf6->rmap[type].name = NULL;
  321.   ospf6->rmap[type].map = NULL;
  322. }
  323. void
  324. ospf6_asbr_routemap_update (char *mapname)
  325. {
  326.   int type;
  327.   if (ospf6 == NULL)
  328.     return;
  329.   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
  330.     {
  331.       if (ospf6->rmap[type].name)
  332.         ospf6->rmap[type].map =
  333.           route_map_lookup_by_name (ospf6->rmap[type].name);
  334.       else
  335.         ospf6->rmap[type].map = NULL;
  336.     }
  337. }
  338. int
  339. ospf6_asbr_is_asbr (struct ospf6 *o)
  340. {
  341.   return o->external_table->count;
  342. }
  343. void
  344. ospf6_asbr_redistribute_set (int type)
  345. {
  346.   ospf6_zebra_redistribute (type);
  347. }
  348. void
  349. ospf6_asbr_redistribute_unset (int type)
  350. {
  351.   struct ospf6_route *route;
  352.   struct ospf6_external_info *info;
  353.   ospf6_zebra_no_redistribute (type);
  354.   for (route = ospf6_route_head (ospf6->external_table); route;
  355.        route = ospf6_route_next (route))
  356.     {
  357.       info = route->route_option;
  358.       if (info->type != type)
  359.         continue;
  360.       ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
  361.                                       &route->prefix);
  362.     }
  363. }
  364. void
  365. ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
  366.                              u_int nexthop_num, struct in6_addr *nexthop)
  367. {
  368.   int ret;
  369.   struct ospf6_route troute;
  370.   struct ospf6_external_info tinfo;
  371.   struct ospf6_route *route, *match;
  372.   struct ospf6_external_info *info;
  373.   struct prefix prefix_id;
  374.   struct route_node *node;
  375.   char pbuf[64], ibuf[16];
  376.   listnode lnode;
  377.   struct ospf6_area *oa;
  378.   if (! ospf6_zebra_is_redistribute (type))
  379.     return;
  380.   if (IS_OSPF6_DEBUG_ASBR)
  381.     {
  382.       prefix2str (prefix, pbuf, sizeof (pbuf));
  383.       zlog_info ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
  384.     }
  385.   /* if route-map was specified but not found, do not advertise */
  386.   if (ospf6->rmap[type].name)
  387.     {
  388.       if (ospf6->rmap[type].map == NULL)
  389.         ospf6_asbr_routemap_update (NULL);
  390.       if (ospf6->rmap[type].map == NULL)
  391.         {
  392.           zlog_warn ("route-map "%s" not found, suppress redistributing",
  393.                      ospf6->rmap[type].name);
  394.           return;
  395.         }
  396.     }
  397.   /* apply route-map */
  398.   if (ospf6->rmap[type].map)
  399.     {
  400.       memset (&troute, 0, sizeof (troute));
  401.       memset (&tinfo, 0, sizeof (tinfo));
  402.       troute.route_option = &tinfo;
  403.       ret = route_map_apply (ospf6->rmap[type].map, prefix,
  404.                              RMAP_OSPF6, &troute);
  405.       if (ret != RMAP_MATCH)
  406.         {
  407.           if (IS_OSPF6_DEBUG_ASBR)
  408.             zlog_info ("Denied by route-map "%s"", ospf6->rmap[type].name);
  409.           return;
  410.         }
  411.     }
  412.   match = ospf6_route_lookup (prefix, ospf6->external_table);
  413.   if (match)
  414.     {
  415.       info = match->route_option;
  416.       /* copy result of route-map */
  417.       if (ospf6->rmap[type].map)
  418.         {
  419.           if (troute.path.metric_type)
  420.             match->path.metric_type = troute.path.metric_type;
  421.           if (troute.path.cost)
  422.             match->path.cost = troute.path.cost;
  423.           if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
  424.             memcpy (&info->forwarding, &tinfo.forwarding,
  425.                     sizeof (struct in6_addr));
  426.         }
  427.       info->type = type;
  428.       match->nexthop[0].ifindex = ifindex;
  429.       if (nexthop_num && nexthop)
  430.         memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
  431.       /* create/update binding in external_id_table */
  432.       prefix_id.family = AF_INET;
  433.       prefix_id.prefixlen = 32;
  434.       prefix_id.u.prefix4.s_addr = htonl (info->id);
  435.       node = route_node_get (ospf6->external_id_table, &prefix_id);
  436.       node->info = match;
  437.       if (IS_OSPF6_DEBUG_ASBR)
  438.         {
  439.           inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
  440.           zlog_info ("Advertise as AS-External Id:%s", ibuf);
  441.         }
  442.       match->path.origin.id = htonl (info->id);
  443.       ospf6_as_external_lsa_originate (match);
  444.       return;
  445.     }
  446.   /* create new entry */
  447.   route = ospf6_route_create ();
  448.   route->type = OSPF6_DEST_TYPE_NETWORK;
  449.   memcpy (&route->prefix, prefix, sizeof (struct prefix));
  450.   info = (struct ospf6_external_info *)
  451.     XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
  452.   memset (info, 0, sizeof (struct ospf6_external_info));
  453.   route->route_option = info;
  454.   info->id = ospf6->external_id++;
  455.   /* copy result of route-map */
  456.   if (ospf6->rmap[type].map)
  457.     {
  458.       if (troute.path.metric_type)
  459.         route->path.metric_type = troute.path.metric_type;
  460.       if (troute.path.cost)
  461.         route->path.cost = troute.path.cost;
  462.       if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
  463.         memcpy (&info->forwarding, &tinfo.forwarding,
  464.                 sizeof (struct in6_addr));
  465.     }
  466.   info->type = type;
  467.   route->nexthop[0].ifindex = ifindex;
  468.   if (nexthop_num && nexthop)
  469.     memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
  470.   /* create/update binding in external_id_table */
  471.   prefix_id.family = AF_INET;
  472.   prefix_id.prefixlen = 32;
  473.   prefix_id.u.prefix4.s_addr = htonl (info->id);
  474.   node = route_node_get (ospf6->external_id_table, &prefix_id);
  475.   node->info = route;
  476.   route = ospf6_route_add (route, ospf6->external_table);
  477.   route->route_option = info;
  478.   if (IS_OSPF6_DEBUG_ASBR)
  479.     {
  480.       inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
  481.       zlog_info ("Advertise as AS-External Id:%s", ibuf);
  482.     }
  483.   route->path.origin.id = htonl (info->id);
  484.   ospf6_as_external_lsa_originate (route);
  485.   /* Router-Bit (ASBR Flag) may have to be updated */
  486.   for (lnode = listhead (ospf6->area_list); lnode; nextnode (lnode))
  487.     {
  488.       oa = (struct ospf6_area *) getdata (lnode);
  489.       OSPF6_ROUTER_LSA_SCHEDULE (oa);
  490.     }
  491. }
  492. void
  493. ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
  494. {
  495.   struct ospf6_route *match;
  496.   struct ospf6_external_info *info = NULL;
  497.   struct route_node *node;
  498.   struct ospf6_lsa *lsa;
  499.   struct prefix prefix_id;
  500.   char pbuf[64], ibuf[16];
  501.   listnode lnode;
  502.   struct ospf6_area *oa;
  503.   match = ospf6_route_lookup (prefix, ospf6->external_table);
  504.   if (match == NULL)
  505.     {
  506.       if (IS_OSPF6_DEBUG_ASBR)
  507.         {
  508.           prefix2str (prefix, pbuf, sizeof (pbuf));
  509.           zlog_info ("No such route %s to withdraw", pbuf);
  510.         }
  511.       return;
  512.     }
  513.   info = match->route_option;
  514.   assert (info);
  515.   if (info->type != type)
  516.     {
  517.       if (IS_OSPF6_DEBUG_ASBR)
  518.         {
  519.           prefix2str (prefix, pbuf, sizeof (pbuf));
  520.           zlog_info ("Original protocol mismatch: %s", pbuf);
  521.         }
  522.       return;
  523.     }
  524.   if (IS_OSPF6_DEBUG_ASBR)
  525.     {
  526.       prefix2str (prefix, pbuf, sizeof (pbuf));
  527.       inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
  528.       zlog_info ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
  529.     }
  530.   lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
  531.                            htonl (info->id), ospf6->router_id, ospf6->lsdb);
  532.   if (lsa)
  533.     ospf6_lsa_purge (lsa);
  534.   /* remove binding in external_id_table */
  535.   prefix_id.family = AF_INET;
  536.   prefix_id.prefixlen = 32;
  537.   prefix_id.u.prefix4.s_addr = htonl (info->id);
  538.   node = route_node_lookup (ospf6->external_id_table, &prefix_id);
  539.   assert (node);
  540.   node->info = NULL;
  541.   route_unlock_node (node);
  542.   ospf6_route_remove (match, ospf6->external_table);
  543.   XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
  544.   /* Router-Bit (ASBR Flag) may have to be updated */
  545.   for (lnode = listhead (ospf6->area_list); lnode; nextnode (lnode))
  546.     {
  547.       oa = (struct ospf6_area *) getdata (lnode);
  548.       OSPF6_ROUTER_LSA_SCHEDULE (oa);
  549.     }
  550. }
  551. DEFUN (ospf6_redistribute,
  552.        ospf6_redistribute_cmd,
  553.        "redistribute (static|kernel|connected|ripng|bgp)",
  554.        "Redistributen"
  555.        "Static routen"
  556.        "Kernel routen"
  557.        "Connected routen"
  558.        "RIPng routen"
  559.        "BGP routen"
  560.       )
  561. {
  562.   int type = 0;
  563.   if (strncmp (argv[0], "sta", 3) == 0)
  564.     type = ZEBRA_ROUTE_STATIC;
  565.   else if (strncmp (argv[0], "ker", 3) == 0)
  566.     type = ZEBRA_ROUTE_KERNEL;
  567.   else if (strncmp (argv[0], "con", 3) == 0)
  568.     type = ZEBRA_ROUTE_CONNECT;
  569.   else if (strncmp (argv[0], "rip", 3) == 0)
  570.     type = ZEBRA_ROUTE_RIPNG;
  571.   else if (strncmp (argv[0], "bgp", 3) == 0)
  572.     type = ZEBRA_ROUTE_BGP;
  573.   ospf6_asbr_redistribute_unset (type);
  574.   ospf6_asbr_routemap_unset (type);
  575.   ospf6_asbr_redistribute_set (type);
  576.   return CMD_SUCCESS;
  577. }
  578. DEFUN (ospf6_redistribute_routemap,
  579.        ospf6_redistribute_routemap_cmd,
  580.        "redistribute (static|kernel|connected|ripng|bgp) route-map WORD",
  581.        "Redistributen"
  582.        "Static routesn"
  583.        "Kernel routen"
  584.        "Connected routen"
  585.        "RIPng routen"
  586.        "BGP routen"
  587.        "Route map referencen"
  588.        "Route map namen"
  589.       )
  590. {
  591.   int type = 0;
  592.   if (strncmp (argv[0], "sta", 3) == 0)
  593.     type = ZEBRA_ROUTE_STATIC;
  594.   else if (strncmp (argv[0], "ker", 3) == 0)
  595.     type = ZEBRA_ROUTE_KERNEL;
  596.   else if (strncmp (argv[0], "con", 3) == 0)
  597.     type = ZEBRA_ROUTE_CONNECT;
  598.   else if (strncmp (argv[0], "rip", 3) == 0)
  599.     type = ZEBRA_ROUTE_RIPNG;
  600.   else if (strncmp (argv[0], "bgp", 3) == 0)
  601.     type = ZEBRA_ROUTE_BGP;
  602.   ospf6_asbr_redistribute_unset (type);
  603.   ospf6_asbr_routemap_set (type, argv[1]);
  604.   ospf6_asbr_redistribute_set (type);
  605.   return CMD_SUCCESS;
  606. }
  607. DEFUN (no_ospf6_redistribute,
  608.        no_ospf6_redistribute_cmd,
  609.        "no redistribute (static|kernel|connected|ripng|bgp)",
  610.        NO_STR
  611.        "Redistributen"
  612.        "Static routen"
  613.        "Kernel routen"
  614.        "Connected routen"
  615.        "RIPng routen"
  616.        "BGP routen"
  617.       )
  618. {
  619.   int type = 0;
  620.   if (strncmp (argv[0], "sta", 3) == 0)
  621.     type = ZEBRA_ROUTE_STATIC;
  622.   else if (strncmp (argv[0], "ker", 3) == 0)
  623.     type = ZEBRA_ROUTE_KERNEL;
  624.   else if (strncmp (argv[0], "con", 3) == 0)
  625.     type = ZEBRA_ROUTE_CONNECT;
  626.   else if (strncmp (argv[0], "rip", 3) == 0)
  627.     type = ZEBRA_ROUTE_RIPNG;
  628.   else if (strncmp (argv[0], "bgp", 3) == 0)
  629.     type = ZEBRA_ROUTE_BGP;
  630.   ospf6_asbr_redistribute_unset (type);
  631.   ospf6_asbr_routemap_unset (type);
  632.   return CMD_SUCCESS;
  633. }
  634. int
  635. ospf6_redistribute_config_write (struct vty *vty)
  636. {
  637.   int type;
  638.   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
  639.     {
  640.       if (type == ZEBRA_ROUTE_OSPF6)
  641.         continue;
  642.       if (! ospf6_zebra_is_redistribute (type))
  643.         continue;
  644.       if (ospf6->rmap[type].name)
  645.         vty_out (vty, " redistribute %s route-map %s%s",
  646.                  ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
  647.       else
  648.         vty_out (vty, " redistribute %s%s",
  649.                  ZROUTE_NAME (type), VNL);
  650.     }
  651.   return 0;
  652. }
  653. void
  654. ospf6_redistribute_show_config (struct vty *vty)
  655. {
  656.   int type;
  657.   int nroute[ZEBRA_ROUTE_MAX];
  658.   int total;
  659.   struct ospf6_route *route;
  660.   struct ospf6_external_info *info;
  661.   total = 0;
  662.   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
  663.     nroute[type] = 0;
  664.   for (route = ospf6_route_head (ospf6->external_table); route;
  665.        route = ospf6_route_next (route))
  666.     {
  667.       info = route->route_option;
  668.       nroute[info->type]++;
  669.       total++;
  670.     }
  671.   vty_out (vty, "Redistributing External Routes from:%s", VNL);
  672.   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
  673.     {
  674.       if (type == ZEBRA_ROUTE_OSPF6)
  675.         continue;
  676.       if (! ospf6_zebra_is_redistribute (type))
  677.         continue;
  678.       if (ospf6->rmap[type].name)
  679.         vty_out (vty, "    %d: %s with route-map "%s"%s%s", nroute[type],
  680.                  ZROUTE_NAME (type), ospf6->rmap[type].name,
  681.                  (ospf6->rmap[type].map ? "" : " (not found !)"),
  682.                  VNL);
  683.       else
  684.         vty_out (vty, "    %d: %s%s", nroute[type],
  685.                  ZROUTE_NAME (type), VNL);
  686.     }
  687.   vty_out (vty, "Total %d routes%s", total, VNL);
  688. }
  689. /* Routemap Functions */
  690. route_map_result_t
  691. ospf6_routemap_rule_match_address_prefixlist (void *rule,
  692.                                               struct prefix *prefix,
  693.                                               route_map_object_t type,
  694.                                               void *object)
  695. {
  696.   struct prefix_list *plist;
  697.   if (type != RMAP_OSPF6)
  698.     return RMAP_NOMATCH;
  699.   plist = prefix_list_lookup (AFI_IP6, (char *) rule);
  700.   if (plist == NULL)
  701.     return RMAP_NOMATCH;
  702.   return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
  703.           RMAP_NOMATCH : RMAP_MATCH);
  704. }
  705. void *
  706. ospf6_routemap_rule_match_address_prefixlist_compile (char *arg)
  707. {
  708.   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  709. }
  710. void
  711. ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
  712. {
  713.   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  714. }
  715. struct route_map_rule_cmd
  716. ospf6_routemap_rule_match_address_prefixlist_cmd =
  717. {
  718.   "ipv6 address prefix-list",
  719.   ospf6_routemap_rule_match_address_prefixlist,
  720.   ospf6_routemap_rule_match_address_prefixlist_compile,
  721.   ospf6_routemap_rule_match_address_prefixlist_free,
  722. };
  723. route_map_result_t
  724. ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
  725.                                      route_map_object_t type, void *object)
  726. {
  727.   char *metric_type = rule;
  728.   struct ospf6_route *route = object;
  729.   if (type != RMAP_OSPF6)
  730.     return RMAP_OKAY;
  731.   if (strcmp (metric_type, "type-2") == 0)
  732.     route->path.metric_type = 2;
  733.   else
  734.     route->path.metric_type = 1;
  735.   return RMAP_OKAY;
  736. }
  737. void *
  738. ospf6_routemap_rule_set_metric_type_compile (char *arg)
  739. {
  740.   if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
  741.     return NULL;
  742.   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  743. }
  744. void
  745. ospf6_routemap_rule_set_metric_type_free (void *rule)
  746. {
  747.   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  748. }
  749. struct route_map_rule_cmd
  750. ospf6_routemap_rule_set_metric_type_cmd =
  751. {
  752.   "metric-type",
  753.   ospf6_routemap_rule_set_metric_type,
  754.   ospf6_routemap_rule_set_metric_type_compile,
  755.   ospf6_routemap_rule_set_metric_type_free,
  756. };
  757. route_map_result_t
  758. ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
  759.                                 route_map_object_t type, void *object)
  760. {
  761.   char *metric = rule;
  762.   struct ospf6_route *route = object;
  763.   if (type != RMAP_OSPF6)
  764.     return RMAP_OKAY;
  765.   route->path.cost = atoi (metric);
  766.   return RMAP_OKAY;
  767. }
  768. void *
  769. ospf6_routemap_rule_set_metric_compile (char *arg)
  770. {
  771.   u_int32_t metric;
  772.   char *endp;
  773.   metric = strtoul (arg, &endp, 0);
  774.   if (metric > LS_INFINITY || *endp != '')
  775.     return NULL;
  776.   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  777. }
  778. void
  779. ospf6_routemap_rule_set_metric_free (void *rule)
  780. {
  781.   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  782. }
  783. struct route_map_rule_cmd
  784. ospf6_routemap_rule_set_metric_cmd =
  785. {
  786.   "metric",
  787.   ospf6_routemap_rule_set_metric,
  788.   ospf6_routemap_rule_set_metric_compile,
  789.   ospf6_routemap_rule_set_metric_free,
  790. };
  791. route_map_result_t
  792. ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
  793.                                     route_map_object_t type, void *object)
  794. {
  795.   char *forwarding = rule;
  796.   struct ospf6_route *route = object;
  797.   struct ospf6_external_info *info = route->route_option;
  798.   if (type != RMAP_OSPF6)
  799.     return RMAP_OKAY;
  800.   if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
  801.     {
  802.       memset (&info->forwarding, 0, sizeof (struct in6_addr));
  803.       return RMAP_ERROR;
  804.     }
  805.   return RMAP_OKAY;
  806. }
  807. void *
  808. ospf6_routemap_rule_set_forwarding_compile (char *arg)
  809. {
  810.   struct in6_addr a;
  811.   if (inet_pton (AF_INET6, arg, &a) != 1)
  812.     return NULL;
  813.   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  814. }
  815. void
  816. ospf6_routemap_rule_set_forwarding_free (void *rule)
  817. {
  818.   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  819. }
  820. struct route_map_rule_cmd
  821. ospf6_routemap_rule_set_forwarding_cmd =
  822. {
  823.   "forwarding-address",
  824.   ospf6_routemap_rule_set_forwarding,
  825.   ospf6_routemap_rule_set_forwarding_compile,
  826.   ospf6_routemap_rule_set_forwarding_free,
  827. };
  828. int
  829. route_map_command_status (struct vty *vty, int ret)
  830. {
  831.   if (! ret)
  832.     return CMD_SUCCESS;
  833.   switch (ret)
  834.     {
  835.     case RMAP_RULE_MISSING:
  836.       vty_out (vty, "Can't find rule.%s", VNL);
  837.       break;
  838.     case RMAP_COMPILE_ERROR:
  839.       vty_out (vty, "Argument is malformed.%s", VNL);
  840.       break;
  841.     default:
  842.       vty_out (vty, "route-map add set failed.%s", VNL);
  843.       break;
  844.     }
  845.   return CMD_WARNING;
  846. }
  847. /* add "match address" */
  848. DEFUN (ospf6_routemap_match_address_prefixlist,
  849.        ospf6_routemap_match_address_prefixlist_cmd,
  850.        "match ipv6 address prefix-list WORD",
  851.        "Match valuesn"
  852.        IPV6_STR
  853.        "Match address of routen"
  854.        "Match entries of prefix-listsn"
  855.        "IPv6 prefix-list namen")
  856. {
  857.   int ret = route_map_add_match ((struct route_map_index *) vty->index,
  858.                                  "ipv6 address prefix-list", argv[0]);
  859.   return route_map_command_status (vty, ret);
  860. }
  861. /* delete "match address" */
  862. DEFUN (ospf6_routemap_no_match_address_prefixlist,
  863.        ospf6_routemap_no_match_address_prefixlist_cmd,
  864.        "no match ipv6 address prefix-list WORD",
  865.        NO_STR
  866.        "Match valuesn"
  867.        IPV6_STR
  868.        "Match address of routen"
  869.        "Match entries of prefix-listsn"
  870.        "IPv6 prefix-list namen")
  871. {
  872.   int ret = route_map_delete_match ((struct route_map_index *) vty->index,
  873.                                     "ipv6 address prefix-list", argv[0]);
  874.   return route_map_command_status (vty, ret);
  875. }
  876. /* add "set metric-type" */
  877. DEFUN (ospf6_routemap_set_metric_type,
  878.        ospf6_routemap_set_metric_type_cmd,
  879.        "set metric-type (type-1|type-2)",
  880.        "Set valuen"
  881.        "Type of metricn"
  882.        "OSPF6 external type 1 metricn"
  883.        "OSPF6 external type 2 metricn")
  884. {
  885.   int ret = route_map_add_set ((struct route_map_index *) vty->index,
  886.                                "metric-type", argv[0]);
  887.   return route_map_command_status (vty, ret);
  888. }
  889. /* delete "set metric-type" */
  890. DEFUN (ospf6_routemap_no_set_metric_type,
  891.        ospf6_routemap_no_set_metric_type_cmd,
  892.        "no set metric-type (type-1|type-2)",
  893.        NO_STR
  894.        "Set valuen"
  895.        "Type of metricn"
  896.        "OSPF6 external type 1 metricn"
  897.        "OSPF6 external type 2 metricn")
  898. {
  899.   int ret = route_map_delete_set ((struct route_map_index *) vty->index,
  900.                                   "metric-type", argv[0]);
  901.   return route_map_command_status (vty, ret);
  902. }
  903. /* add "set metric" */
  904. DEFUN (set_metric,
  905.        set_metric_cmd,
  906.        "set metric <0-4294967295>",
  907.        "Set valuen"
  908.        "Metric valuen"
  909.        "Metric valuen")
  910. {
  911.   int ret = route_map_add_set ((struct route_map_index *) vty->index,
  912.                                "metric", argv[0]);
  913.   return route_map_command_status (vty, ret);
  914. }
  915. /* delete "set metric" */
  916. DEFUN (no_set_metric,
  917.        no_set_metric_cmd,
  918.        "no set metric <0-4294967295>",
  919.        NO_STR
  920.        "Set valuen"
  921.        "Metricn"
  922.        "METRIC valuen")
  923. {
  924.   int ret = route_map_delete_set ((struct route_map_index *) vty->index,
  925.                                   "metric", argv[0]);
  926.   return route_map_command_status (vty, ret);
  927. }
  928. /* add "set forwarding-address" */
  929. DEFUN (ospf6_routemap_set_forwarding,
  930.        ospf6_routemap_set_forwarding_cmd,
  931.        "set forwarding-address X:X::X:X",
  932.        "Set valuen"
  933.        "Forwarding Addressn"
  934.        "IPv6 Addressn")
  935. {
  936.   int ret = route_map_add_set ((struct route_map_index *) vty->index,
  937.                                "forwarding-address", argv[0]);
  938.   return route_map_command_status (vty, ret);
  939. }
  940. /* delete "set forwarding-address" */
  941. DEFUN (ospf6_routemap_no_set_forwarding,
  942.        ospf6_routemap_no_set_forwarding_cmd,
  943.        "no set forwarding-address X:X::X:X",
  944.        NO_STR
  945.        "Set valuen"
  946.        "Forwarding Addressn"
  947.        "IPv6 Addressn")
  948. {
  949.   int ret = route_map_delete_set ((struct route_map_index *) vty->index,
  950.                                   "forwarding-address", argv[0]);
  951.   return route_map_command_status (vty, ret);
  952. }
  953. void
  954. ospf6_routemap_init ()
  955. {
  956.   route_map_init ();
  957.   route_map_init_vty ();
  958.   route_map_add_hook (ospf6_asbr_routemap_update);
  959.   route_map_delete_hook (ospf6_asbr_routemap_update);
  960.   route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
  961.   route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
  962.   route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
  963.   route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
  964.   /* Match address prefix-list */
  965.   install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
  966.   install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
  967.   /* ASE Metric Type (e.g. Type-1/Type-2) */
  968.   install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
  969.   install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
  970.   /* ASE Metric */
  971.   install_element (RMAP_NODE, &set_metric_cmd);
  972.   install_element (RMAP_NODE, &no_set_metric_cmd);
  973.   /* ASE Metric */
  974.   install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
  975.   install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
  976. }
  977. /* Display functions */
  978. int
  979. ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
  980. {
  981.   struct ospf6_as_external_lsa *external;
  982.   char buf[64];
  983.   struct in6_addr in6, *forwarding;
  984.   assert (lsa->header);
  985.   external = (struct ospf6_as_external_lsa *)
  986.     OSPF6_LSA_HEADER_END (lsa->header);
  987.   
  988.   /* bits */
  989.   snprintf (buf, sizeof (buf), "%c%c%c",
  990.     (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
  991.     (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
  992.     (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
  993.   vty_out (vty, "     Bits: %s%s", buf, VNL);
  994.   vty_out (vty, "     Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
  995.            VNL);
  996.   ospf6_prefix_options_printbuf (external->prefix.prefix_options,
  997.                                  buf, sizeof (buf));
  998.   vty_out (vty, "     Prefix Options: %s%s", buf,
  999.            VNL);
  1000.   vty_out (vty, "     Referenced LSType: %d%s",
  1001.            ntohs (external->prefix.prefix_refer_lstype),
  1002.            VNL);
  1003.   ospf6_prefix_in6_addr (&in6, &external->prefix);
  1004.   inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
  1005.   vty_out (vty, "     Prefix: %s/%d%s", buf,
  1006.            external->prefix.prefix_length, VNL);
  1007.   /* Forwarding-Address */
  1008.   if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
  1009.     {
  1010.       forwarding = (struct in6_addr *)
  1011.         ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
  1012.          OSPF6_PREFIX_SPACE (external->prefix.prefix_length));
  1013.       inet_ntop (AF_INET6, forwarding, buf, sizeof (buf));
  1014.       vty_out (vty, "     Forwarding-Address: %s%s", buf, VNL);
  1015.     }
  1016.   return 0;
  1017. }
  1018. void
  1019. ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
  1020. {
  1021.   struct ospf6_external_info *info = route->route_option;
  1022.   char prefix[64], id[16], forwarding[64];
  1023.   u_int32_t tmp_id;
  1024.   prefix2str (&route->prefix, prefix, sizeof (prefix));
  1025.   tmp_id = ntohl (info->id);
  1026.   inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
  1027.   if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
  1028.     inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
  1029.   else
  1030.     snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
  1031.               route->nexthop[0].ifindex);
  1032.   vty_out (vty, "%s %-32s %-15s type-%d %5lu %s%s",
  1033.            ZROUTE_ABNAME (info->type),
  1034.            prefix, id, route->path.metric_type,
  1035.            (u_long) (route->path.metric_type == 2 ?
  1036.                      route->path.cost_e2 : route->path.cost),
  1037.            forwarding, VNL);
  1038. }
  1039. DEFUN (show_ipv6_ospf6_redistribute,
  1040.        show_ipv6_ospf6_redistribute_cmd,
  1041.        "show ipv6 ospf6 redistribute",
  1042.        SHOW_STR
  1043.        IP6_STR
  1044.        OSPF6_STR
  1045.        "redistributing External informationn"
  1046.        )
  1047. {
  1048.   struct ospf6_route *route;
  1049.   ospf6_redistribute_show_config (vty);
  1050.   for (route = ospf6_route_head (ospf6->external_table); route;
  1051.        route = ospf6_route_next (route))
  1052.     ospf6_asbr_external_route_show (vty, route);
  1053.   return CMD_SUCCESS;
  1054. }
  1055. struct ospf6_lsa_handler as_external_handler =
  1056. {
  1057.   OSPF6_LSTYPE_AS_EXTERNAL,
  1058.   "AS-External",
  1059.   ospf6_as_external_lsa_show
  1060. };
  1061. void
  1062. ospf6_asbr_init ()
  1063. {
  1064.   ospf6_routemap_init ();
  1065.   ospf6_install_lsa_handler (&as_external_handler);
  1066.   install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
  1067.   install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
  1068.   install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
  1069.   install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
  1070.   install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
  1071. }
  1072. DEFUN (debug_ospf6_asbr,
  1073.        debug_ospf6_asbr_cmd,
  1074.        "debug ospf6 asbr",
  1075.        DEBUG_STR
  1076.        OSPF6_STR
  1077.        "Debug OSPFv3 ASBR functionn"
  1078.       )
  1079. {
  1080.   OSPF6_DEBUG_ASBR_ON ();
  1081.   return CMD_SUCCESS;
  1082. }
  1083. DEFUN (no_debug_ospf6_asbr,
  1084.        no_debug_ospf6_asbr_cmd,
  1085.        "no debug ospf6 asbr",
  1086.        NO_STR
  1087.        DEBUG_STR
  1088.        OSPF6_STR
  1089.        "Debug OSPFv3 ASBR functionn"
  1090.       )
  1091. {
  1092.   OSPF6_DEBUG_ASBR_OFF ();
  1093.   return CMD_SUCCESS;
  1094. }
  1095. int
  1096. config_write_ospf6_debug_asbr (struct vty *vty)
  1097. {
  1098.   if (IS_OSPF6_DEBUG_ASBR)
  1099.     vty_out (vty, "debug ospf6 asbr%s", VNL);
  1100.   return 0;
  1101. }
  1102. void
  1103. install_element_ospf6_debug_asbr ()
  1104. {
  1105.   install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
  1106.   install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
  1107.   install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
  1108.   install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
  1109. }