File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospf6d / ospf6_asbr.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:11 2016 UTC (7 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>