Annotation of embedaddon/quagga/ospf6d/ospf6_asbr.c, revision 1.1

1.1     ! misho       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: 
        !           451:       ret = route_map_apply (ospf6->rmap[type].map, prefix,
        !           452:                              RMAP_OSPF6, &troute);
        !           453:       if (ret == RMAP_DENYMATCH)
        !           454:         {
        !           455:           if (IS_OSPF6_DEBUG_ASBR)
        !           456:             zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
        !           457:           return;
        !           458:         }
        !           459:     }
        !           460: 
        !           461:   match = ospf6_route_lookup (prefix, ospf6->external_table);
        !           462:   if (match)
        !           463:     {
        !           464:       info = match->route_option;
        !           465: 
        !           466:       /* copy result of route-map */
        !           467:       if (ospf6->rmap[type].map)
        !           468:         {
        !           469:           if (troute.path.metric_type)
        !           470:             match->path.metric_type = troute.path.metric_type;
        !           471:           if (troute.path.cost)
        !           472:             match->path.cost = troute.path.cost;
        !           473:           if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
        !           474:             memcpy (&info->forwarding, &tinfo.forwarding,
        !           475:                     sizeof (struct in6_addr));
        !           476:         }
        !           477: 
        !           478:       info->type = type;
        !           479:       match->nexthop[0].ifindex = ifindex;
        !           480:       if (nexthop_num && nexthop)
        !           481:         memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
        !           482: 
        !           483:       /* create/update binding in external_id_table */
        !           484:       prefix_id.family = AF_INET;
        !           485:       prefix_id.prefixlen = 32;
        !           486:       prefix_id.u.prefix4.s_addr = htonl (info->id);
        !           487:       node = route_node_get (ospf6->external_id_table, &prefix_id);
        !           488:       node->info = match;
        !           489: 
        !           490:       if (IS_OSPF6_DEBUG_ASBR)
        !           491:         {
        !           492:           inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
        !           493:           zlog_debug ("Advertise as AS-External Id:%s", ibuf);
        !           494:         }
        !           495: 
        !           496:       match->path.origin.id = htonl (info->id);
        !           497:       ospf6_as_external_lsa_originate (match);
        !           498:       return;
        !           499:     }
        !           500: 
        !           501:   /* create new entry */
        !           502:   route = ospf6_route_create ();
        !           503:   route->type = OSPF6_DEST_TYPE_NETWORK;
        !           504:   memcpy (&route->prefix, prefix, sizeof (struct prefix));
        !           505: 
        !           506:   info = (struct ospf6_external_info *)
        !           507:     XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
        !           508:   route->route_option = info;
        !           509:   info->id = ospf6->external_id++;
        !           510: 
        !           511:   /* copy result of route-map */
        !           512:   if (ospf6->rmap[type].map)
        !           513:     {
        !           514:       if (troute.path.metric_type)
        !           515:         route->path.metric_type = troute.path.metric_type;
        !           516:       if (troute.path.cost)
        !           517:         route->path.cost = troute.path.cost;
        !           518:       if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
        !           519:         memcpy (&info->forwarding, &tinfo.forwarding,
        !           520:                 sizeof (struct in6_addr));
        !           521:     }
        !           522: 
        !           523:   info->type = type;
        !           524:   route->nexthop[0].ifindex = ifindex;
        !           525:   if (nexthop_num && nexthop)
        !           526:     memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
        !           527: 
        !           528:   /* create/update binding in external_id_table */
        !           529:   prefix_id.family = AF_INET;
        !           530:   prefix_id.prefixlen = 32;
        !           531:   prefix_id.u.prefix4.s_addr = htonl (info->id);
        !           532:   node = route_node_get (ospf6->external_id_table, &prefix_id);
        !           533:   node->info = route;
        !           534: 
        !           535:   route = ospf6_route_add (route, ospf6->external_table);
        !           536:   route->route_option = info;
        !           537: 
        !           538:   if (IS_OSPF6_DEBUG_ASBR)
        !           539:     {
        !           540:       inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
        !           541:       zlog_debug ("Advertise as AS-External Id:%s", ibuf);
        !           542:     }
        !           543: 
        !           544:   route->path.origin.id = htonl (info->id);
        !           545:   ospf6_as_external_lsa_originate (route);
        !           546: 
        !           547:   /* Router-Bit (ASBR Flag) may have to be updated */
        !           548:   for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
        !           549:     OSPF6_ROUTER_LSA_SCHEDULE (oa);
        !           550: }
        !           551: 
        !           552: void
        !           553: ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
        !           554: {
        !           555:   struct ospf6_route *match;
        !           556:   struct ospf6_external_info *info = NULL;
        !           557:   struct route_node *node;
        !           558:   struct ospf6_lsa *lsa;
        !           559:   struct prefix prefix_id;
        !           560:   char pbuf[64], ibuf[16];
        !           561:   struct listnode *lnode, *lnnode;
        !           562:   struct ospf6_area *oa;
        !           563: 
        !           564:   match = ospf6_route_lookup (prefix, ospf6->external_table);
        !           565:   if (match == NULL)
        !           566:     {
        !           567:       if (IS_OSPF6_DEBUG_ASBR)
        !           568:         {
        !           569:           prefix2str (prefix, pbuf, sizeof (pbuf));
        !           570:           zlog_debug ("No such route %s to withdraw", pbuf);
        !           571:         }
        !           572:       return;
        !           573:     }
        !           574: 
        !           575:   info = match->route_option;
        !           576:   assert (info);
        !           577: 
        !           578:   if (info->type != type)
        !           579:     {
        !           580:       if (IS_OSPF6_DEBUG_ASBR)
        !           581:         {
        !           582:           prefix2str (prefix, pbuf, sizeof (pbuf));
        !           583:           zlog_debug ("Original protocol mismatch: %s", pbuf);
        !           584:         }
        !           585:       return;
        !           586:     }
        !           587: 
        !           588:   if (IS_OSPF6_DEBUG_ASBR)
        !           589:     {
        !           590:       prefix2str (prefix, pbuf, sizeof (pbuf));
        !           591:       inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
        !           592:       zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
        !           593:     }
        !           594: 
        !           595:   lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
        !           596:                            htonl (info->id), ospf6->router_id, ospf6->lsdb);
        !           597:   if (lsa)
        !           598:     ospf6_lsa_purge (lsa);
        !           599: 
        !           600:   /* remove binding in external_id_table */
        !           601:   prefix_id.family = AF_INET;
        !           602:   prefix_id.prefixlen = 32;
        !           603:   prefix_id.u.prefix4.s_addr = htonl (info->id);
        !           604:   node = route_node_lookup (ospf6->external_id_table, &prefix_id);
        !           605:   assert (node);
        !           606:   node->info = NULL;
        !           607:   route_unlock_node (node);
        !           608: 
        !           609:   ospf6_route_remove (match, ospf6->external_table);
        !           610:   XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
        !           611: 
        !           612:   /* Router-Bit (ASBR Flag) may have to be updated */
        !           613:   for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
        !           614:     OSPF6_ROUTER_LSA_SCHEDULE (oa);
        !           615: }
        !           616: 
        !           617: DEFUN (ospf6_redistribute,
        !           618:        ospf6_redistribute_cmd,
        !           619:        "redistribute (static|kernel|connected|ripng|bgp)",
        !           620:        "Redistribute\n"
        !           621:        "Static route\n"
        !           622:        "Kernel route\n"
        !           623:        "Connected route\n"
        !           624:        "RIPng route\n"
        !           625:        "BGP route\n"
        !           626:       )
        !           627: {
        !           628:   int type = 0;
        !           629: 
        !           630:   if (strncmp (argv[0], "sta", 3) == 0)
        !           631:     type = ZEBRA_ROUTE_STATIC;
        !           632:   else if (strncmp (argv[0], "ker", 3) == 0)
        !           633:     type = ZEBRA_ROUTE_KERNEL;
        !           634:   else if (strncmp (argv[0], "con", 3) == 0)
        !           635:     type = ZEBRA_ROUTE_CONNECT;
        !           636:   else if (strncmp (argv[0], "rip", 3) == 0)
        !           637:     type = ZEBRA_ROUTE_RIPNG;
        !           638:   else if (strncmp (argv[0], "bgp", 3) == 0)
        !           639:     type = ZEBRA_ROUTE_BGP;
        !           640: 
        !           641:   ospf6_asbr_redistribute_unset (type);
        !           642:   ospf6_asbr_routemap_unset (type);
        !           643:   ospf6_asbr_redistribute_set (type);
        !           644:   return CMD_SUCCESS;
        !           645: }
        !           646: 
        !           647: DEFUN (ospf6_redistribute_routemap,
        !           648:        ospf6_redistribute_routemap_cmd,
        !           649:        "redistribute (static|kernel|connected|ripng|bgp) route-map WORD",
        !           650:        "Redistribute\n"
        !           651:        "Static routes\n"
        !           652:        "Kernel route\n"
        !           653:        "Connected route\n"
        !           654:        "RIPng route\n"
        !           655:        "BGP route\n"
        !           656:        "Route map reference\n"
        !           657:        "Route map name\n"
        !           658:       )
        !           659: {
        !           660:   int type = 0;
        !           661: 
        !           662:   if (strncmp (argv[0], "sta", 3) == 0)
        !           663:     type = ZEBRA_ROUTE_STATIC;
        !           664:   else if (strncmp (argv[0], "ker", 3) == 0)
        !           665:     type = ZEBRA_ROUTE_KERNEL;
        !           666:   else if (strncmp (argv[0], "con", 3) == 0)
        !           667:     type = ZEBRA_ROUTE_CONNECT;
        !           668:   else if (strncmp (argv[0], "rip", 3) == 0)
        !           669:     type = ZEBRA_ROUTE_RIPNG;
        !           670:   else if (strncmp (argv[0], "bgp", 3) == 0)
        !           671:     type = ZEBRA_ROUTE_BGP;
        !           672: 
        !           673:   ospf6_asbr_redistribute_unset (type);
        !           674:   ospf6_asbr_routemap_set (type, argv[1]);
        !           675:   ospf6_asbr_redistribute_set (type);
        !           676:   return CMD_SUCCESS;
        !           677: }
        !           678: 
        !           679: DEFUN (no_ospf6_redistribute,
        !           680:        no_ospf6_redistribute_cmd,
        !           681:        "no redistribute (static|kernel|connected|ripng|bgp)",
        !           682:        NO_STR
        !           683:        "Redistribute\n"
        !           684:        "Static route\n"
        !           685:        "Kernel route\n"
        !           686:        "Connected route\n"
        !           687:        "RIPng route\n"
        !           688:        "BGP route\n"
        !           689:       )
        !           690: {
        !           691:   int type = 0;
        !           692: 
        !           693:   if (strncmp (argv[0], "sta", 3) == 0)
        !           694:     type = ZEBRA_ROUTE_STATIC;
        !           695:   else if (strncmp (argv[0], "ker", 3) == 0)
        !           696:     type = ZEBRA_ROUTE_KERNEL;
        !           697:   else if (strncmp (argv[0], "con", 3) == 0)
        !           698:     type = ZEBRA_ROUTE_CONNECT;
        !           699:   else if (strncmp (argv[0], "rip", 3) == 0)
        !           700:     type = ZEBRA_ROUTE_RIPNG;
        !           701:   else if (strncmp (argv[0], "bgp", 3) == 0)
        !           702:     type = ZEBRA_ROUTE_BGP;
        !           703: 
        !           704:   ospf6_asbr_redistribute_unset (type);
        !           705:   ospf6_asbr_routemap_unset (type);
        !           706: 
        !           707:   return CMD_SUCCESS;
        !           708: }
        !           709: 
        !           710: int
        !           711: ospf6_redistribute_config_write (struct vty *vty)
        !           712: {
        !           713:   int type;
        !           714: 
        !           715:   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
        !           716:     {
        !           717:       if (type == ZEBRA_ROUTE_OSPF6)
        !           718:         continue;
        !           719:       if (! ospf6_zebra_is_redistribute (type))
        !           720:         continue;
        !           721: 
        !           722:       if (ospf6->rmap[type].name)
        !           723:         vty_out (vty, " redistribute %s route-map %s%s",
        !           724:                  ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
        !           725:       else
        !           726:         vty_out (vty, " redistribute %s%s",
        !           727:                  ZROUTE_NAME (type), VNL);
        !           728:     }
        !           729: 
        !           730:   return 0;
        !           731: }
        !           732: 
        !           733: static void
        !           734: ospf6_redistribute_show_config (struct vty *vty)
        !           735: {
        !           736:   int type;
        !           737:   int nroute[ZEBRA_ROUTE_MAX];
        !           738:   int total;
        !           739:   struct ospf6_route *route;
        !           740:   struct ospf6_external_info *info;
        !           741: 
        !           742:   total = 0;
        !           743:   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
        !           744:     nroute[type] = 0;
        !           745:   for (route = ospf6_route_head (ospf6->external_table); route;
        !           746:        route = ospf6_route_next (route))
        !           747:     {
        !           748:       info = route->route_option;
        !           749:       nroute[info->type]++;
        !           750:       total++;
        !           751:     }
        !           752: 
        !           753:   vty_out (vty, "Redistributing External Routes from:%s", VNL);
        !           754:   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
        !           755:     {
        !           756:       if (type == ZEBRA_ROUTE_OSPF6)
        !           757:         continue;
        !           758:       if (! ospf6_zebra_is_redistribute (type))
        !           759:         continue;
        !           760: 
        !           761:       if (ospf6->rmap[type].name)
        !           762:         vty_out (vty, "    %d: %s with route-map \"%s\"%s%s", nroute[type],
        !           763:                  ZROUTE_NAME (type), ospf6->rmap[type].name,
        !           764:                  (ospf6->rmap[type].map ? "" : " (not found !)"),
        !           765:                  VNL);
        !           766:       else
        !           767:         vty_out (vty, "    %d: %s%s", nroute[type],
        !           768:                  ZROUTE_NAME (type), VNL);
        !           769:     }
        !           770:   vty_out (vty, "Total %d routes%s", total, VNL);
        !           771: }
        !           772: 
        !           773: 
        !           774: 
        !           775: /* Routemap Functions */
        !           776: static route_map_result_t
        !           777: ospf6_routemap_rule_match_address_prefixlist (void *rule,
        !           778:                                               struct prefix *prefix,
        !           779:                                               route_map_object_t type,
        !           780:                                               void *object)
        !           781: {
        !           782:   struct prefix_list *plist;
        !           783: 
        !           784:   if (type != RMAP_OSPF6)
        !           785:     return RMAP_NOMATCH;
        !           786: 
        !           787:   plist = prefix_list_lookup (AFI_IP6, (char *) rule);
        !           788:   if (plist == NULL)
        !           789:     return RMAP_NOMATCH;
        !           790: 
        !           791:   return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
        !           792:           RMAP_NOMATCH : RMAP_MATCH);
        !           793: }
        !           794: 
        !           795: static void *
        !           796: ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
        !           797: {
        !           798:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
        !           799: }
        !           800: 
        !           801: static void
        !           802: ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
        !           803: {
        !           804:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           805: }
        !           806: 
        !           807: struct route_map_rule_cmd
        !           808: ospf6_routemap_rule_match_address_prefixlist_cmd =
        !           809: {
        !           810:   "ipv6 address prefix-list",
        !           811:   ospf6_routemap_rule_match_address_prefixlist,
        !           812:   ospf6_routemap_rule_match_address_prefixlist_compile,
        !           813:   ospf6_routemap_rule_match_address_prefixlist_free,
        !           814: };
        !           815: 
        !           816: static route_map_result_t
        !           817: ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
        !           818:                                      route_map_object_t type, void *object)
        !           819: {
        !           820:   char *metric_type = rule;
        !           821:   struct ospf6_route *route = object;
        !           822: 
        !           823:   if (type != RMAP_OSPF6)
        !           824:     return RMAP_OKAY;
        !           825: 
        !           826:   if (strcmp (metric_type, "type-2") == 0)
        !           827:     route->path.metric_type = 2;
        !           828:   else
        !           829:     route->path.metric_type = 1;
        !           830: 
        !           831:   return RMAP_OKAY;
        !           832: }
        !           833: 
        !           834: static void *
        !           835: ospf6_routemap_rule_set_metric_type_compile (const char *arg)
        !           836: {
        !           837:   if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
        !           838:     return NULL;
        !           839:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
        !           840: }
        !           841: 
        !           842: static void
        !           843: ospf6_routemap_rule_set_metric_type_free (void *rule)
        !           844: {
        !           845:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           846: }
        !           847: 
        !           848: struct route_map_rule_cmd
        !           849: ospf6_routemap_rule_set_metric_type_cmd =
        !           850: {
        !           851:   "metric-type",
        !           852:   ospf6_routemap_rule_set_metric_type,
        !           853:   ospf6_routemap_rule_set_metric_type_compile,
        !           854:   ospf6_routemap_rule_set_metric_type_free,
        !           855: };
        !           856: 
        !           857: static route_map_result_t
        !           858: ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
        !           859:                                 route_map_object_t type, void *object)
        !           860: {
        !           861:   char *metric = rule;
        !           862:   struct ospf6_route *route = object;
        !           863: 
        !           864:   if (type != RMAP_OSPF6)
        !           865:     return RMAP_OKAY;
        !           866: 
        !           867:   route->path.cost = atoi (metric);
        !           868:   return RMAP_OKAY;
        !           869: }
        !           870: 
        !           871: static void *
        !           872: ospf6_routemap_rule_set_metric_compile (const char *arg)
        !           873: {
        !           874:   u_int32_t metric;
        !           875:   char *endp;
        !           876:   metric = strtoul (arg, &endp, 0);
        !           877:   if (metric > LS_INFINITY || *endp != '\0')
        !           878:     return NULL;
        !           879:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
        !           880: }
        !           881: 
        !           882: static void
        !           883: ospf6_routemap_rule_set_metric_free (void *rule)
        !           884: {
        !           885:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           886: }
        !           887: 
        !           888: struct route_map_rule_cmd
        !           889: ospf6_routemap_rule_set_metric_cmd =
        !           890: {
        !           891:   "metric",
        !           892:   ospf6_routemap_rule_set_metric,
        !           893:   ospf6_routemap_rule_set_metric_compile,
        !           894:   ospf6_routemap_rule_set_metric_free,
        !           895: };
        !           896: 
        !           897: static route_map_result_t
        !           898: ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
        !           899:                                     route_map_object_t type, void *object)
        !           900: {
        !           901:   char *forwarding = rule;
        !           902:   struct ospf6_route *route = object;
        !           903:   struct ospf6_external_info *info = route->route_option;
        !           904: 
        !           905:   if (type != RMAP_OSPF6)
        !           906:     return RMAP_OKAY;
        !           907: 
        !           908:   if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
        !           909:     {
        !           910:       memset (&info->forwarding, 0, sizeof (struct in6_addr));
        !           911:       return RMAP_ERROR;
        !           912:     }
        !           913: 
        !           914:   return RMAP_OKAY;
        !           915: }
        !           916: 
        !           917: static void *
        !           918: ospf6_routemap_rule_set_forwarding_compile (const char *arg)
        !           919: {
        !           920:   struct in6_addr a;
        !           921:   if (inet_pton (AF_INET6, arg, &a) != 1)
        !           922:     return NULL;
        !           923:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
        !           924: }
        !           925: 
        !           926: static void
        !           927: ospf6_routemap_rule_set_forwarding_free (void *rule)
        !           928: {
        !           929:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           930: }
        !           931: 
        !           932: struct route_map_rule_cmd
        !           933: ospf6_routemap_rule_set_forwarding_cmd =
        !           934: {
        !           935:   "forwarding-address",
        !           936:   ospf6_routemap_rule_set_forwarding,
        !           937:   ospf6_routemap_rule_set_forwarding_compile,
        !           938:   ospf6_routemap_rule_set_forwarding_free,
        !           939: };
        !           940: 
        !           941: static int
        !           942: route_map_command_status (struct vty *vty, int ret)
        !           943: {
        !           944:   if (! ret)
        !           945:     return CMD_SUCCESS;
        !           946: 
        !           947:   switch (ret)
        !           948:     {
        !           949:     case RMAP_RULE_MISSING:
        !           950:       vty_out (vty, "Can't find rule.%s", VNL);
        !           951:       break;
        !           952:     case RMAP_COMPILE_ERROR:
        !           953:       vty_out (vty, "Argument is malformed.%s", VNL);
        !           954:       break;
        !           955:     default:
        !           956:       vty_out (vty, "route-map add set failed.%s", VNL);
        !           957:       break;
        !           958:     }
        !           959:   return CMD_WARNING;
        !           960: }
        !           961: 
        !           962: /* add "match address" */
        !           963: DEFUN (ospf6_routemap_match_address_prefixlist,
        !           964:        ospf6_routemap_match_address_prefixlist_cmd,
        !           965:        "match ipv6 address prefix-list WORD",
        !           966:        "Match values\n"
        !           967:        IPV6_STR
        !           968:        "Match address of route\n"
        !           969:        "Match entries of prefix-lists\n"
        !           970:        "IPv6 prefix-list name\n")
        !           971: {
        !           972:   int ret = route_map_add_match ((struct route_map_index *) vty->index,
        !           973:                                  "ipv6 address prefix-list", argv[0]);
        !           974:   return route_map_command_status (vty, ret);
        !           975: }
        !           976: 
        !           977: /* delete "match address" */
        !           978: DEFUN (ospf6_routemap_no_match_address_prefixlist,
        !           979:        ospf6_routemap_no_match_address_prefixlist_cmd,
        !           980:        "no match ipv6 address prefix-list WORD",
        !           981:        NO_STR
        !           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_delete_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: /* add "set metric-type" */
        !           994: DEFUN (ospf6_routemap_set_metric_type,
        !           995:        ospf6_routemap_set_metric_type_cmd,
        !           996:        "set metric-type (type-1|type-2)",
        !           997:        "Set value\n"
        !           998:        "Type of metric\n"
        !           999:        "OSPF6 external type 1 metric\n"
        !          1000:        "OSPF6 external type 2 metric\n")
        !          1001: {
        !          1002:   int ret = route_map_add_set ((struct route_map_index *) vty->index,
        !          1003:                                "metric-type", argv[0]);
        !          1004:   return route_map_command_status (vty, ret);
        !          1005: }
        !          1006: 
        !          1007: /* delete "set metric-type" */
        !          1008: DEFUN (ospf6_routemap_no_set_metric_type,
        !          1009:        ospf6_routemap_no_set_metric_type_cmd,
        !          1010:        "no set metric-type (type-1|type-2)",
        !          1011:        NO_STR
        !          1012:        "Set value\n"
        !          1013:        "Type of metric\n"
        !          1014:        "OSPF6 external type 1 metric\n"
        !          1015:        "OSPF6 external type 2 metric\n")
        !          1016: {
        !          1017:   int ret = route_map_delete_set ((struct route_map_index *) vty->index,
        !          1018:                                   "metric-type", argv[0]);
        !          1019:   return route_map_command_status (vty, ret);
        !          1020: }
        !          1021: 
        !          1022: /* add "set metric" */
        !          1023: DEFUN (set_metric,
        !          1024:        set_metric_cmd,
        !          1025:        "set metric <0-4294967295>",
        !          1026:        "Set value\n"
        !          1027:        "Metric value\n"
        !          1028:        "Metric value\n")
        !          1029: {
        !          1030:   int ret = route_map_add_set ((struct route_map_index *) vty->index,
        !          1031:                                "metric", argv[0]);
        !          1032:   return route_map_command_status (vty, ret);
        !          1033: }
        !          1034: 
        !          1035: /* delete "set metric" */
        !          1036: DEFUN (no_set_metric,
        !          1037:        no_set_metric_cmd,
        !          1038:        "no set metric <0-4294967295>",
        !          1039:        NO_STR
        !          1040:        "Set value\n"
        !          1041:        "Metric\n"
        !          1042:        "METRIC value\n")
        !          1043: {
        !          1044:   int ret = route_map_delete_set ((struct route_map_index *) vty->index,
        !          1045:                                   "metric", argv[0]);
        !          1046:   return route_map_command_status (vty, ret);
        !          1047: }
        !          1048: 
        !          1049: /* add "set forwarding-address" */
        !          1050: DEFUN (ospf6_routemap_set_forwarding,
        !          1051:        ospf6_routemap_set_forwarding_cmd,
        !          1052:        "set forwarding-address X:X::X:X",
        !          1053:        "Set value\n"
        !          1054:        "Forwarding Address\n"
        !          1055:        "IPv6 Address\n")
        !          1056: {
        !          1057:   int ret = route_map_add_set ((struct route_map_index *) vty->index,
        !          1058:                                "forwarding-address", argv[0]);
        !          1059:   return route_map_command_status (vty, ret);
        !          1060: }
        !          1061: 
        !          1062: /* delete "set forwarding-address" */
        !          1063: DEFUN (ospf6_routemap_no_set_forwarding,
        !          1064:        ospf6_routemap_no_set_forwarding_cmd,
        !          1065:        "no set forwarding-address X:X::X:X",
        !          1066:        NO_STR
        !          1067:        "Set value\n"
        !          1068:        "Forwarding Address\n"
        !          1069:        "IPv6 Address\n")
        !          1070: {
        !          1071:   int ret = route_map_delete_set ((struct route_map_index *) vty->index,
        !          1072:                                   "forwarding-address", argv[0]);
        !          1073:   return route_map_command_status (vty, ret);
        !          1074: }
        !          1075: 
        !          1076: static void
        !          1077: ospf6_routemap_init (void)
        !          1078: {
        !          1079:   route_map_init ();
        !          1080:   route_map_init_vty ();
        !          1081:   route_map_add_hook (ospf6_asbr_routemap_update);
        !          1082:   route_map_delete_hook (ospf6_asbr_routemap_update);
        !          1083: 
        !          1084:   route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
        !          1085:   route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
        !          1086:   route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
        !          1087:   route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
        !          1088: 
        !          1089:   /* Match address prefix-list */
        !          1090:   install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
        !          1091:   install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
        !          1092: 
        !          1093:   /* ASE Metric Type (e.g. Type-1/Type-2) */
        !          1094:   install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
        !          1095:   install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
        !          1096: 
        !          1097:   /* ASE Metric */
        !          1098:   install_element (RMAP_NODE, &set_metric_cmd);
        !          1099:   install_element (RMAP_NODE, &no_set_metric_cmd);
        !          1100: 
        !          1101:   /* ASE Metric */
        !          1102:   install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
        !          1103:   install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
        !          1104: }
        !          1105: 
        !          1106: 
        !          1107: /* Display functions */
        !          1108: static int
        !          1109: ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
        !          1110: {
        !          1111:   struct ospf6_as_external_lsa *external;
        !          1112:   char buf[64];
        !          1113:   struct in6_addr in6, *forwarding;
        !          1114: 
        !          1115:   assert (lsa->header);
        !          1116:   external = (struct ospf6_as_external_lsa *)
        !          1117:     OSPF6_LSA_HEADER_END (lsa->header);
        !          1118:   
        !          1119:   /* bits */
        !          1120:   snprintf (buf, sizeof (buf), "%c%c%c",
        !          1121:     (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
        !          1122:     (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
        !          1123:     (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
        !          1124: 
        !          1125:   vty_out (vty, "     Bits: %s%s", buf, VNL);
        !          1126:   vty_out (vty, "     Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
        !          1127:            VNL);
        !          1128: 
        !          1129:   ospf6_prefix_options_printbuf (external->prefix.prefix_options,
        !          1130:                                  buf, sizeof (buf));
        !          1131:   vty_out (vty, "     Prefix Options: %s%s", buf,
        !          1132:            VNL);
        !          1133: 
        !          1134:   vty_out (vty, "     Referenced LSType: %d%s",
        !          1135:            ntohs (external->prefix.prefix_refer_lstype),
        !          1136:            VNL);
        !          1137: 
        !          1138:   ospf6_prefix_in6_addr (&in6, &external->prefix);
        !          1139:   inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
        !          1140:   vty_out (vty, "     Prefix: %s/%d%s", buf,
        !          1141:            external->prefix.prefix_length, VNL);
        !          1142: 
        !          1143:   /* Forwarding-Address */
        !          1144:   if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
        !          1145:     {
        !          1146:       forwarding = (struct in6_addr *)
        !          1147:         ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
        !          1148:          OSPF6_PREFIX_SPACE (external->prefix.prefix_length));
        !          1149:       inet_ntop (AF_INET6, forwarding, buf, sizeof (buf));
        !          1150:       vty_out (vty, "     Forwarding-Address: %s%s", buf, VNL);
        !          1151:     }
        !          1152: 
        !          1153:   return 0;
        !          1154: }
        !          1155: 
        !          1156: static void
        !          1157: ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
        !          1158: {
        !          1159:   struct ospf6_external_info *info = route->route_option;
        !          1160:   char prefix[64], id[16], forwarding[64];
        !          1161:   u_int32_t tmp_id;
        !          1162: 
        !          1163:   prefix2str (&route->prefix, prefix, sizeof (prefix));
        !          1164:   tmp_id = ntohl (info->id);
        !          1165:   inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
        !          1166:   if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
        !          1167:     inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
        !          1168:   else
        !          1169:     snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
        !          1170:               route->nexthop[0].ifindex);
        !          1171: 
        !          1172:   vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
        !          1173:            zebra_route_char(info->type),
        !          1174:            prefix, id, route->path.metric_type,
        !          1175:            (u_long) (route->path.metric_type == 2 ?
        !          1176:                      route->path.cost_e2 : route->path.cost),
        !          1177:            forwarding, VNL);
        !          1178: }
        !          1179: 
        !          1180: DEFUN (show_ipv6_ospf6_redistribute,
        !          1181:        show_ipv6_ospf6_redistribute_cmd,
        !          1182:        "show ipv6 ospf6 redistribute",
        !          1183:        SHOW_STR
        !          1184:        IP6_STR
        !          1185:        OSPF6_STR
        !          1186:        "redistributing External information\n"
        !          1187:        )
        !          1188: {
        !          1189:   struct ospf6_route *route;
        !          1190: 
        !          1191:   ospf6_redistribute_show_config (vty);
        !          1192: 
        !          1193:   for (route = ospf6_route_head (ospf6->external_table); route;
        !          1194:        route = ospf6_route_next (route))
        !          1195:     ospf6_asbr_external_route_show (vty, route);
        !          1196: 
        !          1197:   return CMD_SUCCESS;
        !          1198: }
        !          1199: 
        !          1200: struct ospf6_lsa_handler as_external_handler =
        !          1201: {
        !          1202:   OSPF6_LSTYPE_AS_EXTERNAL,
        !          1203:   "AS-External",
        !          1204:   ospf6_as_external_lsa_show
        !          1205: };
        !          1206: 
        !          1207: void
        !          1208: ospf6_asbr_init (void)
        !          1209: {
        !          1210:   ospf6_routemap_init ();
        !          1211: 
        !          1212:   ospf6_install_lsa_handler (&as_external_handler);
        !          1213: 
        !          1214:   install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
        !          1215:   install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
        !          1216: 
        !          1217:   install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
        !          1218:   install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
        !          1219:   install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
        !          1220: }
        !          1221: 
        !          1222: void
        !          1223: ospf6_asbr_terminate (void)
        !          1224: {
        !          1225:   route_map_finish ();
        !          1226: }
        !          1227: 
        !          1228: DEFUN (debug_ospf6_asbr,
        !          1229:        debug_ospf6_asbr_cmd,
        !          1230:        "debug ospf6 asbr",
        !          1231:        DEBUG_STR
        !          1232:        OSPF6_STR
        !          1233:        "Debug OSPFv3 ASBR function\n"
        !          1234:       )
        !          1235: {
        !          1236:   OSPF6_DEBUG_ASBR_ON ();
        !          1237:   return CMD_SUCCESS;
        !          1238: }
        !          1239: 
        !          1240: DEFUN (no_debug_ospf6_asbr,
        !          1241:        no_debug_ospf6_asbr_cmd,
        !          1242:        "no debug ospf6 asbr",
        !          1243:        NO_STR
        !          1244:        DEBUG_STR
        !          1245:        OSPF6_STR
        !          1246:        "Debug OSPFv3 ASBR function\n"
        !          1247:       )
        !          1248: {
        !          1249:   OSPF6_DEBUG_ASBR_OFF ();
        !          1250:   return CMD_SUCCESS;
        !          1251: }
        !          1252: 
        !          1253: int
        !          1254: config_write_ospf6_debug_asbr (struct vty *vty)
        !          1255: {
        !          1256:   if (IS_OSPF6_DEBUG_ASBR)
        !          1257:     vty_out (vty, "debug ospf6 asbr%s", VNL);
        !          1258:   return 0;
        !          1259: }
        !          1260: 
        !          1261: void
        !          1262: install_element_ospf6_debug_asbr ()
        !          1263: {
        !          1264:   install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
        !          1265:   install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
        !          1266:   install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
        !          1267:   install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
        !          1268: }
        !          1269: 
        !          1270: 

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