File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospf6d / ospf6_asbr.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:28 2012 UTC (11 years, 9 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, HEAD
quagga

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

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