Annotation of embedaddon/quagga/ospf6d/ospf6_lsa.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 other stuffs */
        !            25: #include "log.h"
        !            26: #include "linklist.h"
        !            27: #include "vector.h"
        !            28: #include "vty.h"
        !            29: #include "command.h"
        !            30: #include "memory.h"
        !            31: #include "thread.h"
        !            32: 
        !            33: #include "ospf6_proto.h"
        !            34: #include "ospf6_lsa.h"
        !            35: #include "ospf6_lsdb.h"
        !            36: #include "ospf6_message.h"
        !            37: 
        !            38: #include "ospf6_top.h"
        !            39: #include "ospf6_area.h"
        !            40: #include "ospf6_interface.h"
        !            41: #include "ospf6_neighbor.h"
        !            42: 
        !            43: #include "ospf6_flood.h"
        !            44: #include "ospf6d.h"
        !            45: 
        !            46: vector ospf6_lsa_handler_vector;
        !            47: 
        !            48: static int
        !            49: ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
        !            50: {
        !            51:   u_char *start, *end, *current;
        !            52:   char byte[4];
        !            53: 
        !            54:   start = (u_char *) lsa->header + sizeof (struct ospf6_lsa_header);
        !            55:   end = (u_char *) lsa->header + ntohs (lsa->header->length);
        !            56: 
        !            57:   vty_out (vty, "        Unknown contents:%s", VNL);
        !            58:   for (current = start; current < end; current ++)
        !            59:     {
        !            60:       if ((current - start) % 16 == 0)
        !            61:         vty_out (vty, "%s        ", VNL);
        !            62:       else if ((current - start) % 4 == 0)
        !            63:         vty_out (vty, " ");
        !            64: 
        !            65:       snprintf (byte, sizeof (byte), "%02x", *current);
        !            66:       vty_out (vty, "%s", byte);
        !            67:     }
        !            68: 
        !            69:   vty_out (vty, "%s%s", VNL, VNL);
        !            70:   return 0;
        !            71: }
        !            72: 
        !            73: struct ospf6_lsa_handler unknown_handler =
        !            74: {
        !            75:   OSPF6_LSTYPE_UNKNOWN,
        !            76:   "Unknown",
        !            77:   ospf6_unknown_lsa_show,
        !            78:   OSPF6_LSA_DEBUG,
        !            79: };
        !            80: 
        !            81: void
        !            82: ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler)
        !            83: {
        !            84:   /* type in handler is host byte order */
        !            85:   int index = handler->type & OSPF6_LSTYPE_FCODE_MASK;
        !            86:   vector_set_index (ospf6_lsa_handler_vector, index, handler);
        !            87: }
        !            88: 
        !            89: struct ospf6_lsa_handler *
        !            90: ospf6_get_lsa_handler (u_int16_t type)
        !            91: {
        !            92:   struct ospf6_lsa_handler *handler = NULL;
        !            93:   unsigned int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK;
        !            94: 
        !            95:   if (index >= vector_active (ospf6_lsa_handler_vector))
        !            96:     handler = &unknown_handler;
        !            97:   else
        !            98:     handler = vector_slot (ospf6_lsa_handler_vector, index);
        !            99: 
        !           100:   if (handler == NULL)
        !           101:     handler = &unknown_handler;
        !           102: 
        !           103:   return handler;
        !           104: }
        !           105: 
        !           106: const char *
        !           107: ospf6_lstype_name (u_int16_t type)
        !           108: {
        !           109:   static char buf[8];
        !           110:   struct ospf6_lsa_handler *handler;
        !           111: 
        !           112:   handler = ospf6_get_lsa_handler (type);
        !           113:   if (handler && handler != &unknown_handler)
        !           114:     return handler->name;
        !           115: 
        !           116:   snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
        !           117:   return buf;
        !           118: }
        !           119: 
        !           120: u_char
        !           121: ospf6_lstype_debug (u_int16_t type)
        !           122: {
        !           123:   struct ospf6_lsa_handler *handler;
        !           124:   handler = ospf6_get_lsa_handler (type);
        !           125:   return handler->debug;
        !           126: }
        !           127: 
        !           128: /* RFC2328: Section 13.2 */
        !           129: int
        !           130: ospf6_lsa_is_differ (struct ospf6_lsa *lsa1,
        !           131:                      struct ospf6_lsa *lsa2)
        !           132: {
        !           133:   int len;
        !           134: 
        !           135:   assert (OSPF6_LSA_IS_SAME (lsa1, lsa2));
        !           136: 
        !           137:   /* XXX, Options ??? */
        !           138: 
        !           139:   ospf6_lsa_age_current (lsa1);
        !           140:   ospf6_lsa_age_current (lsa2);
        !           141:   if (ntohs (lsa1->header->age) == MAXAGE &&
        !           142:       ntohs (lsa2->header->age) != MAXAGE)
        !           143:     return 1;
        !           144:   if (ntohs (lsa1->header->age) != MAXAGE &&
        !           145:       ntohs (lsa2->header->age) == MAXAGE)
        !           146:     return 1;
        !           147: 
        !           148:   /* compare body */
        !           149:   if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
        !           150:     return 1;
        !           151: 
        !           152:   len = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header);
        !           153:   return memcmp (lsa1->header + 1, lsa2->header + 1, len);
        !           154: }
        !           155: 
        !           156: int
        !           157: ospf6_lsa_is_changed (struct ospf6_lsa *lsa1,
        !           158:                       struct ospf6_lsa *lsa2)
        !           159: {
        !           160:   int length;
        !           161: 
        !           162:   if (OSPF6_LSA_IS_MAXAGE (lsa1) ^ OSPF6_LSA_IS_MAXAGE (lsa2))
        !           163:     return 1;
        !           164:   if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
        !           165:     return 1;
        !           166:   /* Going beyond LSA headers to compare the payload only makes sense, when both LSAs aren't header-only. */
        !           167:   if (CHECK_FLAG (lsa1->flag, OSPF6_LSA_HEADERONLY) != CHECK_FLAG (lsa2->flag, OSPF6_LSA_HEADERONLY))
        !           168:   {
        !           169:     zlog_warn ("%s: only one of two (%s, %s) LSAs compared is header-only", __func__, lsa1->name, lsa2->name);
        !           170:     return 1;
        !           171:   }
        !           172:   if (CHECK_FLAG (lsa1->flag, OSPF6_LSA_HEADERONLY))
        !           173:     return 0;
        !           174: 
        !           175:   length = OSPF6_LSA_SIZE (lsa1->header) - sizeof (struct ospf6_lsa_header);
        !           176:   /* Once upper layer verifies LSAs received, length underrun should become a warning. */
        !           177:   if (length <= 0)
        !           178:     return 0;
        !           179: 
        !           180:   return memcmp (OSPF6_LSA_HEADER_END (lsa1->header),
        !           181:                  OSPF6_LSA_HEADER_END (lsa2->header), length);
        !           182: }
        !           183: 
        !           184: /* ospf6 age functions */
        !           185: /* calculate birth */
        !           186: static void
        !           187: ospf6_lsa_age_set (struct ospf6_lsa *lsa)
        !           188: {
        !           189:   struct timeval now;
        !           190: 
        !           191:   assert (lsa && lsa->header);
        !           192: 
        !           193:   if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &now) < 0)
        !           194:     zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s",
        !           195:                safe_strerror (errno));
        !           196: 
        !           197:   lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age);
        !           198:   lsa->birth.tv_usec = now.tv_usec;
        !           199: 
        !           200:   return;
        !           201: }
        !           202: 
        !           203: /* this function calculates current age from its birth,
        !           204:    then update age field of LSA header. return value is current age */
        !           205: u_int16_t
        !           206: ospf6_lsa_age_current (struct ospf6_lsa *lsa)
        !           207: {
        !           208:   struct timeval now;
        !           209:   u_int32_t ulage;
        !           210:   u_int16_t age;
        !           211: 
        !           212:   assert (lsa);
        !           213:   assert (lsa->header);
        !           214: 
        !           215:   /* current time */
        !           216:   if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &now) < 0)
        !           217:     zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s",
        !           218:                safe_strerror (errno));
        !           219: 
        !           220:   if (ntohs (lsa->header->age) >= MAXAGE)
        !           221:     {
        !           222:       /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
        !           223:          relative time, we cannot compare against lsa birth time, so
        !           224:          we catch this special case here. */
        !           225:       lsa->header->age = htons (MAXAGE);
        !           226:       return MAXAGE;
        !           227:     }
        !           228:   /* calculate age */
        !           229:   ulage = now.tv_sec - lsa->birth.tv_sec;
        !           230: 
        !           231:   /* if over MAXAGE, set to it */
        !           232:   age = (ulage > MAXAGE ? MAXAGE : ulage);
        !           233: 
        !           234:   lsa->header->age = htons (age);
        !           235:   return age;
        !           236: }
        !           237: 
        !           238: /* update age field of LSA header with adding InfTransDelay */
        !           239: void
        !           240: ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
        !           241: {
        !           242:   unsigned short age;
        !           243: 
        !           244:   age = ospf6_lsa_age_current (lsa) + transdelay;
        !           245:   if (age > MAXAGE)
        !           246:     age = MAXAGE;
        !           247:   lsa->header->age = htons (age);
        !           248: }
        !           249: 
        !           250: void
        !           251: ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
        !           252: {
        !           253:   /* log */
        !           254:   if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))
        !           255:     zlog_debug ("LSA: Premature aging: %s", lsa->name);
        !           256: 
        !           257:   THREAD_OFF (lsa->expire);
        !           258:   THREAD_OFF (lsa->refresh);
        !           259: 
        !           260:   lsa->header->age = htons (MAXAGE);
        !           261:   thread_execute (master, ospf6_lsa_expire, lsa, 0);
        !           262: }
        !           263: 
        !           264: /* check which is more recent. if a is more recent, return -1;
        !           265:    if the same, return 0; otherwise(b is more recent), return 1 */
        !           266: int
        !           267: ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
        !           268: {
        !           269:   int seqnuma, seqnumb;
        !           270:   u_int16_t cksuma, cksumb;
        !           271:   u_int16_t agea, ageb;
        !           272: 
        !           273:   assert (a && a->header);
        !           274:   assert (b && b->header);
        !           275:   assert (OSPF6_LSA_IS_SAME (a, b));
        !           276: 
        !           277:   seqnuma = (int) ntohl (a->header->seqnum);
        !           278:   seqnumb = (int) ntohl (b->header->seqnum);
        !           279: 
        !           280:   /* compare by sequence number */
        !           281:   if (seqnuma > seqnumb)
        !           282:     return -1;
        !           283:   if (seqnuma < seqnumb)
        !           284:     return 1;
        !           285: 
        !           286:   /* Checksum */
        !           287:   cksuma = ntohs (a->header->checksum);
        !           288:   cksumb = ntohs (b->header->checksum);
        !           289:   if (cksuma > cksumb)
        !           290:     return -1;
        !           291:   if (cksuma < cksumb)
        !           292:     return 0;
        !           293: 
        !           294:   /* Update Age */
        !           295:   agea = ospf6_lsa_age_current (a);
        !           296:   ageb = ospf6_lsa_age_current (b);
        !           297: 
        !           298:   /* MaxAge check */
        !           299:   if (agea == MAXAGE && ageb != MAXAGE)
        !           300:     return -1;
        !           301:   else if (agea != MAXAGE && ageb == MAXAGE)
        !           302:     return 1;
        !           303: 
        !           304:   /* Age check */
        !           305:   if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
        !           306:     return 1;
        !           307:   else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
        !           308:     return -1;
        !           309: 
        !           310:   /* neither recent */
        !           311:   return 0;
        !           312: }
        !           313: 
        !           314: char *
        !           315: ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size)
        !           316: {
        !           317:   char id[16], adv_router[16];
        !           318:   inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
        !           319:   inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
        !           320:              sizeof (adv_router));
        !           321:   snprintf (buf, size, "[%s Id:%s Adv:%s]",
        !           322:             ospf6_lstype_name (lsa->header->type), id, adv_router);
        !           323:   return buf;
        !           324: }
        !           325: 
        !           326: void
        !           327: ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header)
        !           328: {
        !           329:   char id[16], adv_router[16];
        !           330:   inet_ntop (AF_INET, &header->id, id, sizeof (id));
        !           331:   inet_ntop (AF_INET, &header->adv_router, adv_router,
        !           332:              sizeof (adv_router));
        !           333:   zlog_debug ("    [%s Id:%s Adv:%s]",
        !           334:              ospf6_lstype_name (header->type), id, adv_router);
        !           335:   zlog_debug ("    Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
        !           336:              ntohs (header->age), (u_long) ntohl (header->seqnum),
        !           337:              ntohs (header->checksum), ntohs (header->length));
        !           338: }
        !           339: 
        !           340: void
        !           341: ospf6_lsa_header_print (struct ospf6_lsa *lsa)
        !           342: {
        !           343:   ospf6_lsa_age_current (lsa);
        !           344:   ospf6_lsa_header_print_raw (lsa->header);
        !           345: }
        !           346: 
        !           347: void
        !           348: ospf6_lsa_show_summary_header (struct vty *vty)
        !           349: {
        !           350:   vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
        !           351:            "Type", "LSId", "AdvRouter", "Age", "SeqNum",
        !           352:            "Cksm", "Len", "Duration", VNL);
        !           353: }
        !           354: 
        !           355: void
        !           356: ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
        !           357: {
        !           358:   char adv_router[16], id[16];
        !           359:   struct timeval now, res;
        !           360:   char duration[16];
        !           361: 
        !           362:   assert (lsa);
        !           363:   assert (lsa->header);
        !           364: 
        !           365:   inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
        !           366:   inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
        !           367:              sizeof (adv_router));
        !           368: 
        !           369:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
        !           370:   timersub (&now, &lsa->installed, &res);
        !           371:   timerstring (&res, duration, sizeof (duration));
        !           372: 
        !           373:   vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
        !           374:            ospf6_lstype_name (lsa->header->type),
        !           375:            id, adv_router, ospf6_lsa_age_current (lsa),
        !           376:            (u_long) ntohl (lsa->header->seqnum),
        !           377:            ntohs (lsa->header->checksum), ntohs (lsa->header->length),
        !           378:            duration, VNL);
        !           379: }
        !           380: 
        !           381: void
        !           382: ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
        !           383: {
        !           384:   u_char *start, *end, *current;
        !           385:   char byte[4];
        !           386: 
        !           387:   start = (u_char *) lsa->header;
        !           388:   end = (u_char *) lsa->header + ntohs (lsa->header->length);
        !           389: 
        !           390:   vty_out (vty, "%s", VNL);
        !           391:   vty_out (vty, "%s:%s", lsa->name, VNL);
        !           392: 
        !           393:   for (current = start; current < end; current ++)
        !           394:     {
        !           395:       if ((current - start) % 16 == 0)
        !           396:         vty_out (vty, "%s        ", VNL);
        !           397:       else if ((current - start) % 4 == 0)
        !           398:         vty_out (vty, " ");
        !           399: 
        !           400:       snprintf (byte, sizeof (byte), "%02x", *current);
        !           401:       vty_out (vty, "%s", byte);
        !           402:     }
        !           403: 
        !           404:   vty_out (vty, "%s%s", VNL, VNL);
        !           405:   return;
        !           406: }
        !           407: 
        !           408: void
        !           409: ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
        !           410: {
        !           411:   char adv_router[64], id[64];
        !           412: 
        !           413:   assert (lsa && lsa->header);
        !           414: 
        !           415:   inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
        !           416:   inet_ntop (AF_INET, &lsa->header->adv_router,
        !           417:              adv_router, sizeof (adv_router));
        !           418: 
        !           419:   vty_out (vty, "%s", VNL);
        !           420:   vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
        !           421:            ospf6_lstype_name (lsa->header->type), VNL);
        !           422:   vty_out (vty, "Link State ID: %s%s", id, VNL);
        !           423:   vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
        !           424:   vty_out (vty, "LS Sequence Number: %#010lx%s",
        !           425:            (u_long) ntohl (lsa->header->seqnum), VNL);
        !           426:   vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
        !           427:            ntohs (lsa->header->checksum),
        !           428:            ntohs (lsa->header->length), VNL);
        !           429:   vty_out (vty, "    Prev: %p This: %p Next: %p%s",
        !           430:            lsa->prev, lsa, lsa->next, VNL);
        !           431:   vty_out (vty, "%s", VNL);
        !           432:   return;
        !           433: }
        !           434: 
        !           435: void
        !           436: ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
        !           437: {
        !           438:   char adv_router[64], id[64];
        !           439:   struct ospf6_lsa_handler *handler;
        !           440: 
        !           441:   assert (lsa && lsa->header);
        !           442: 
        !           443:   inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
        !           444:   inet_ntop (AF_INET, &lsa->header->adv_router,
        !           445:              adv_router, sizeof (adv_router));
        !           446: 
        !           447:   vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
        !           448:            ospf6_lstype_name (lsa->header->type), VNL);
        !           449:   vty_out (vty, "Link State ID: %s%s", id, VNL);
        !           450:   vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
        !           451:   vty_out (vty, "LS Sequence Number: %#010lx%s",
        !           452:            (u_long) ntohl (lsa->header->seqnum), VNL);
        !           453:   vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
        !           454:            ntohs (lsa->header->checksum),
        !           455:            ntohs (lsa->header->length), VNL);
        !           456: 
        !           457:   handler = ospf6_get_lsa_handler (lsa->header->type);
        !           458:   if (handler->show == NULL)
        !           459:     handler = &unknown_handler;
        !           460:   (*handler->show) (vty, lsa);
        !           461: 
        !           462:   vty_out (vty, "%s", VNL);
        !           463: }
        !           464: 
        !           465: /* OSPFv3 LSA creation/deletion function */
        !           466: struct ospf6_lsa *
        !           467: ospf6_lsa_create (struct ospf6_lsa_header *header)
        !           468: {
        !           469:   struct ospf6_lsa *lsa = NULL;
        !           470:   struct ospf6_lsa_header *new_header = NULL;
        !           471:   u_int16_t lsa_size = 0;
        !           472: 
        !           473:   /* size of the entire LSA */
        !           474:   lsa_size = ntohs (header->length);   /* XXX vulnerable */
        !           475: 
        !           476:   /* allocate memory for this LSA */
        !           477:   new_header = (struct ospf6_lsa_header *)
        !           478:     XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
        !           479: 
        !           480:   /* copy LSA from original header */
        !           481:   memcpy (new_header, header, lsa_size);
        !           482: 
        !           483:   /* LSA information structure */
        !           484:   /* allocate memory */
        !           485:   lsa = (struct ospf6_lsa *)
        !           486:     XCALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
        !           487: 
        !           488:   lsa->header = (struct ospf6_lsa_header *) new_header;
        !           489: 
        !           490:   /* dump string */
        !           491:   ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
        !           492: 
        !           493:   /* calculate birth of this lsa */
        !           494:   ospf6_lsa_age_set (lsa);
        !           495: 
        !           496:   return lsa;
        !           497: }
        !           498: 
        !           499: struct ospf6_lsa *
        !           500: ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
        !           501: {
        !           502:   struct ospf6_lsa *lsa = NULL;
        !           503:   struct ospf6_lsa_header *new_header = NULL;
        !           504: 
        !           505:   /* allocate memory for this LSA */
        !           506:   new_header = (struct ospf6_lsa_header *)
        !           507:     XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
        !           508: 
        !           509:   /* copy LSA from original header */
        !           510:   memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
        !           511: 
        !           512:   /* LSA information structure */
        !           513:   /* allocate memory */
        !           514:   lsa = (struct ospf6_lsa *)
        !           515:     XCALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
        !           516: 
        !           517:   lsa->header = (struct ospf6_lsa_header *) new_header;
        !           518:   SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY);
        !           519: 
        !           520:   /* dump string */
        !           521:   ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
        !           522: 
        !           523:   /* calculate birth of this lsa */
        !           524:   ospf6_lsa_age_set (lsa);
        !           525: 
        !           526:   return lsa;
        !           527: }
        !           528: 
        !           529: void
        !           530: ospf6_lsa_delete (struct ospf6_lsa *lsa)
        !           531: {
        !           532:   assert (lsa->lock == 0);
        !           533: 
        !           534:   /* cancel threads */
        !           535:   THREAD_OFF (lsa->expire);
        !           536:   THREAD_OFF (lsa->refresh);
        !           537: 
        !           538:   /* do free */
        !           539:   XFREE (MTYPE_OSPF6_LSA, lsa->header);
        !           540:   XFREE (MTYPE_OSPF6_LSA, lsa);
        !           541: }
        !           542: 
        !           543: struct ospf6_lsa *
        !           544: ospf6_lsa_copy (struct ospf6_lsa *lsa)
        !           545: {
        !           546:   struct ospf6_lsa *copy = NULL;
        !           547: 
        !           548:   ospf6_lsa_age_current (lsa);
        !           549:   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
        !           550:     copy = ospf6_lsa_create_headeronly (lsa->header);
        !           551:   else
        !           552:     copy = ospf6_lsa_create (lsa->header);
        !           553:   assert (copy->lock == 0);
        !           554: 
        !           555:   copy->birth = lsa->birth;
        !           556:   copy->originated = lsa->originated;
        !           557:   copy->received = lsa->received;
        !           558:   copy->installed = lsa->installed;
        !           559:   copy->lsdb = lsa->lsdb;
        !           560: 
        !           561:   return copy;
        !           562: }
        !           563: 
        !           564: /* increment reference counter of struct ospf6_lsa */
        !           565: void
        !           566: ospf6_lsa_lock (struct ospf6_lsa *lsa)
        !           567: {
        !           568:   lsa->lock++;
        !           569:   return;
        !           570: }
        !           571: 
        !           572: /* decrement reference counter of struct ospf6_lsa */
        !           573: void
        !           574: ospf6_lsa_unlock (struct ospf6_lsa *lsa)
        !           575: {
        !           576:   /* decrement reference counter */
        !           577:   assert (lsa->lock > 0);
        !           578:   lsa->lock--;
        !           579: 
        !           580:   if (lsa->lock != 0)
        !           581:     return;
        !           582: 
        !           583:   ospf6_lsa_delete (lsa);
        !           584: }
        !           585: 
        !           586: 
        !           587: /* ospf6 lsa expiry */
        !           588: int
        !           589: ospf6_lsa_expire (struct thread *thread)
        !           590: {
        !           591:   struct ospf6_lsa *lsa;
        !           592: 
        !           593:   lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
        !           594: 
        !           595:   assert (lsa && lsa->header);
        !           596:   assert (OSPF6_LSA_IS_MAXAGE (lsa));
        !           597:   assert (! lsa->refresh);
        !           598: 
        !           599:   lsa->expire = (struct thread *) NULL;
        !           600: 
        !           601:   if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))
        !           602:     {
        !           603:       zlog_debug ("LSA Expire:");
        !           604:       ospf6_lsa_header_print (lsa);
        !           605:     }
        !           606: 
        !           607:   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
        !           608:     return 0;    /* dbexchange will do something ... */
        !           609: 
        !           610:   /* reflood lsa */
        !           611:   ospf6_flood (NULL, lsa);
        !           612: 
        !           613:   /* reinstall lsa */
        !           614:   ospf6_install_lsa (lsa);
        !           615: 
        !           616:   /* schedule maxage remover */
        !           617:   ospf6_maxage_remove (ospf6);
        !           618: 
        !           619:   return 0;
        !           620: }
        !           621: 
        !           622: int
        !           623: ospf6_lsa_refresh (struct thread *thread)
        !           624: {
        !           625:   struct ospf6_lsa *old, *self, *new;
        !           626:   struct ospf6_lsdb *lsdb_self;
        !           627: 
        !           628:   assert (thread);
        !           629:   old = (struct ospf6_lsa *) THREAD_ARG (thread);
        !           630:   assert (old && old->header);
        !           631: 
        !           632:   old->refresh = (struct thread *) NULL;
        !           633: 
        !           634:   lsdb_self = ospf6_get_scoped_lsdb_self (old);
        !           635:   self = ospf6_lsdb_lookup (old->header->type, old->header->id,
        !           636:                             old->header->adv_router, lsdb_self);
        !           637:   if (self == NULL)
        !           638:     {
        !           639:       if (IS_OSPF6_DEBUG_LSA_TYPE (old->header->type))
        !           640:         zlog_debug ("Refresh: could not find self LSA, flush %s", old->name);
        !           641:       ospf6_lsa_premature_aging (old);
        !           642:       return 0;
        !           643:     }
        !           644: 
        !           645:   /* Reset age, increment LS sequence number. */
        !           646:   self->header->age = htons (0);
        !           647:   self->header->seqnum =
        !           648:     ospf6_new_ls_seqnum (self->header->type, self->header->id,
        !           649:                          self->header->adv_router, old->lsdb);
        !           650:   ospf6_lsa_checksum (self->header);
        !           651: 
        !           652:   new = ospf6_lsa_create (self->header);
        !           653:   new->lsdb = old->lsdb;
        !           654:   new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
        !           655:                                    LS_REFRESH_TIME);
        !           656: 
        !           657:   /* store it in the LSDB for self-originated LSAs */
        !           658:   ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
        !           659: 
        !           660:   if (IS_OSPF6_DEBUG_LSA_TYPE (new->header->type))
        !           661:     {
        !           662:       zlog_debug ("LSA Refresh:");
        !           663:       ospf6_lsa_header_print (new);
        !           664:     }
        !           665: 
        !           666:   ospf6_flood_clear (old);
        !           667:   ospf6_flood (NULL, new);
        !           668:   ospf6_install_lsa (new);
        !           669: 
        !           670:   return 0;
        !           671: }
        !           672: 
        !           673: 
        !           674: 
        !           675: /* enhanced Fletcher checksum algorithm, RFC1008 7.2 */
        !           676: #define MODX                4102
        !           677: #define LSA_CHECKSUM_OFFSET   15
        !           678: 
        !           679: unsigned short
        !           680: ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
        !           681: {
        !           682:   u_char *sp, *ep, *p, *q;
        !           683:   int c0 = 0, c1 = 0;
        !           684:   int x, y;
        !           685:   u_int16_t length;
        !           686: 
        !           687:   lsa_header->checksum = 0;
        !           688:   length = ntohs (lsa_header->length) - 2;
        !           689:   sp = (u_char *) &lsa_header->type;
        !           690: 
        !           691:   for (ep = sp + length; sp < ep; sp = q)
        !           692:     {
        !           693:       q = sp + MODX;
        !           694:       if (q > ep)
        !           695:         q = ep;
        !           696:       for (p = sp; p < q; p++)
        !           697:         {
        !           698:           c0 += *p;
        !           699:           c1 += c0;
        !           700:         }
        !           701:       c0 %= 255;
        !           702:       c1 %= 255;
        !           703:     }
        !           704: 
        !           705:   /* r = (c1 << 8) + c0; */
        !           706:   x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
        !           707:   if (x <= 0)
        !           708:     x += 255;
        !           709:   y = 510 - c0 - x;
        !           710:   if (y > 255)
        !           711:     y -= 255;
        !           712: 
        !           713:   lsa_header->checksum = htons ((x << 8) + y);
        !           714: 
        !           715:   return (lsa_header->checksum);
        !           716: }
        !           717: 
        !           718: void
        !           719: ospf6_lsa_init (void)
        !           720: {
        !           721:   ospf6_lsa_handler_vector = vector_init (0);
        !           722:   ospf6_install_lsa_handler (&unknown_handler);
        !           723: }
        !           724: 
        !           725: void
        !           726: ospf6_lsa_terminate (void)
        !           727: {
        !           728:   vector_free (ospf6_lsa_handler_vector);
        !           729: }
        !           730: 
        !           731: static char *
        !           732: ospf6_lsa_handler_name (struct ospf6_lsa_handler *h)
        !           733: {
        !           734:   static char buf[64];
        !           735:   unsigned int i; 
        !           736:   unsigned int size = strlen (h->name);
        !           737: 
        !           738:   if (!strcmp(h->name, "Unknown") &&
        !           739:       h->type != OSPF6_LSTYPE_UNKNOWN)
        !           740:     {
        !           741:       snprintf (buf, sizeof (buf), "%#04hx", h->type);
        !           742:       return buf;
        !           743:     }
        !           744: 
        !           745:   for (i = 0; i < MIN (size, sizeof (buf)); i++)
        !           746:     {
        !           747:       if (! islower (h->name[i]))
        !           748:         buf[i] = tolower (h->name[i]);
        !           749:       else
        !           750:         buf[i] = h->name[i];
        !           751:     }
        !           752:   buf[size] = '\0';
        !           753:   return buf;
        !           754: }
        !           755: 
        !           756: DEFUN (debug_ospf6_lsa_type,
        !           757:        debug_ospf6_lsa_hex_cmd,
        !           758:        "debug ospf6 lsa XXXX/0xXXXX",
        !           759:        DEBUG_STR
        !           760:        OSPF6_STR
        !           761:        "Debug Link State Advertisements (LSAs)\n"
        !           762:        "Specify LS type as Hexadecimal\n"
        !           763:       )
        !           764: {
        !           765:   unsigned int i;
        !           766:   struct ospf6_lsa_handler *handler = NULL;
        !           767:   unsigned long val;
        !           768:   char *endptr = NULL;
        !           769:   u_int16_t type = 0;
        !           770: 
        !           771:   assert (argc);
        !           772: 
        !           773:   if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
        !           774:       (strlen (argv[0]) == 4))
        !           775:     {
        !           776:       val = strtoul (argv[0], &endptr, 16);
        !           777:       if (*endptr == '\0')
        !           778:         type = val;
        !           779:     }
        !           780: 
        !           781:   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
        !           782:     {
        !           783:       handler = vector_slot (ospf6_lsa_handler_vector, i);
        !           784:       if (handler == NULL)
        !           785:         continue;
        !           786:       if (type && handler->type == type)
        !           787:         break;
        !           788:       if (! strcasecmp (argv[0], handler->name))
        !           789:         break;
        !           790:       handler = NULL;
        !           791:     }
        !           792: 
        !           793:   if (type && handler == NULL)
        !           794:     {
        !           795:       handler = (struct ospf6_lsa_handler *)
        !           796:         malloc (sizeof (struct ospf6_lsa_handler));
        !           797:       memset (handler, 0, sizeof (struct ospf6_lsa_handler));
        !           798:       handler->type = type;
        !           799:       handler->name = "Unknown";
        !           800:       handler->show = ospf6_unknown_lsa_show;
        !           801:       vector_set_index (ospf6_lsa_handler_vector,
        !           802:                         handler->type & OSPF6_LSTYPE_FCODE_MASK, handler);
        !           803:     }
        !           804: 
        !           805:   if (handler == NULL)
        !           806:     handler = &unknown_handler;
        !           807: 
        !           808:   if (argc >= 2)
        !           809:     {
        !           810:       if (! strcmp (argv[1], "originate"))
        !           811:         SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
        !           812:       if (! strcmp (argv[1], "examin"))
        !           813:         SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
        !           814:       if (! strcmp (argv[1], "flooding"))
        !           815:         SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
        !           816:     }
        !           817:   else
        !           818:     SET_FLAG (handler->debug, OSPF6_LSA_DEBUG);
        !           819: 
        !           820:   return CMD_SUCCESS;
        !           821: }
        !           822: 
        !           823: DEFUN (no_debug_ospf6_lsa_type,
        !           824:        no_debug_ospf6_lsa_hex_cmd,
        !           825:        "no debug ospf6 lsa XXXX/0xXXXX",
        !           826:        NO_STR
        !           827:        DEBUG_STR
        !           828:        OSPF6_STR
        !           829:        "Debug Link State Advertisements (LSAs)\n"
        !           830:        "Specify LS type as Hexadecimal\n"
        !           831:       )
        !           832: {
        !           833:   u_int i;
        !           834:   struct ospf6_lsa_handler *handler = NULL;
        !           835:   unsigned long val;
        !           836:   char *endptr = NULL;
        !           837:   u_int16_t type = 0;
        !           838: 
        !           839:   assert (argc);
        !           840: 
        !           841:   if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
        !           842:       (strlen (argv[0]) == 4))
        !           843:     {
        !           844:       val = strtoul (argv[0], &endptr, 16);
        !           845:       if (*endptr == '\0')
        !           846:         type = val;
        !           847:     }
        !           848: 
        !           849:   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
        !           850:     {
        !           851:       handler = vector_slot (ospf6_lsa_handler_vector, i);
        !           852:       if (handler == NULL)
        !           853:         continue;
        !           854:       if (type && handler->type == type)
        !           855:         break;
        !           856:       if (! strcasecmp (argv[0], handler->name))
        !           857:         break;
        !           858:     }
        !           859: 
        !           860:   if (handler == NULL)
        !           861:     return CMD_SUCCESS;
        !           862: 
        !           863:   if (argc >= 2)
        !           864:     {
        !           865:       if (! strcmp (argv[1], "originate"))
        !           866:         UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
        !           867:       if (! strcmp (argv[1], "examin"))
        !           868:         UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
        !           869:       if (! strcmp (argv[1], "flooding"))
        !           870:         UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
        !           871:     }
        !           872:   else
        !           873:     UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG);
        !           874: 
        !           875:   if (handler->debug == 0 &&
        !           876:       !strcmp(handler->name, "Unknown") && type != OSPF6_LSTYPE_UNKNOWN)
        !           877:     {
        !           878:       free (handler);
        !           879:       vector_slot (ospf6_lsa_handler_vector, i) = NULL;
        !           880:     }
        !           881: 
        !           882:   return CMD_SUCCESS;
        !           883: }
        !           884: 
        !           885: struct cmd_element debug_ospf6_lsa_type_cmd;
        !           886: struct cmd_element debug_ospf6_lsa_type_detail_cmd;
        !           887: struct cmd_element no_debug_ospf6_lsa_type_cmd;
        !           888: struct cmd_element no_debug_ospf6_lsa_type_detail_cmd;
        !           889: 
        !           890: void
        !           891: install_element_ospf6_debug_lsa (void)
        !           892: {
        !           893:   u_int i;
        !           894:   struct ospf6_lsa_handler *handler;
        !           895: #define STRSIZE  256
        !           896: #define DOCSIZE  1024
        !           897:   static char strbuf[STRSIZE];
        !           898:   static char docbuf[DOCSIZE];
        !           899:   static char detail_strbuf[STRSIZE];
        !           900:   static char detail_docbuf[DOCSIZE];
        !           901:   char *str, *no_str;
        !           902:   char *doc, *no_doc;
        !           903: 
        !           904:   strbuf[0] = '\0';
        !           905:   no_str = &strbuf[strlen (strbuf)];
        !           906:   strncat (strbuf, "no ", STRSIZE - strlen (strbuf));
        !           907:   str = &strbuf[strlen (strbuf)];
        !           908: 
        !           909:   strncat (strbuf, "debug ospf6 lsa (", STRSIZE - strlen (strbuf));
        !           910:   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
        !           911:     {
        !           912:       handler = vector_slot (ospf6_lsa_handler_vector, i);
        !           913:       if (handler == NULL)
        !           914:         continue;
        !           915:       strncat (strbuf, ospf6_lsa_handler_name (handler),
        !           916:                STRSIZE - strlen (strbuf));
        !           917:       strncat (strbuf, "|", STRSIZE - strlen (strbuf));
        !           918:     }
        !           919:   strbuf[strlen (strbuf) - 1] = ')';
        !           920:   strbuf[strlen (strbuf)] = '\0';
        !           921: 
        !           922:   docbuf[0] = '\0';
        !           923:   no_doc = &docbuf[strlen (docbuf)];
        !           924:   strncat (docbuf, NO_STR, DOCSIZE - strlen (docbuf));
        !           925:   doc = &docbuf[strlen (docbuf)];
        !           926: 
        !           927:   strncat (docbuf, DEBUG_STR, DOCSIZE - strlen (docbuf));
        !           928:   strncat (docbuf, OSPF6_STR, DOCSIZE - strlen (docbuf));
        !           929:   strncat (docbuf, "Debug Link State Advertisements (LSAs)\n",
        !           930:            DOCSIZE - strlen (docbuf));
        !           931: 
        !           932:   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
        !           933:     {
        !           934:       handler = vector_slot (ospf6_lsa_handler_vector, i);
        !           935:       if (handler == NULL)
        !           936:         continue;
        !           937:       strncat (docbuf, "Debug ", DOCSIZE - strlen (docbuf));
        !           938:       strncat (docbuf, handler->name, DOCSIZE - strlen (docbuf));
        !           939:       strncat (docbuf, "-LSA\n", DOCSIZE - strlen (docbuf));
        !           940:     }
        !           941:   docbuf[strlen (docbuf)] = '\0';
        !           942: 
        !           943:   debug_ospf6_lsa_type_cmd.string = str;
        !           944:   debug_ospf6_lsa_type_cmd.func = debug_ospf6_lsa_type;
        !           945:   debug_ospf6_lsa_type_cmd.doc = doc;
        !           946: 
        !           947:   no_debug_ospf6_lsa_type_cmd.string = no_str;
        !           948:   no_debug_ospf6_lsa_type_cmd.func = no_debug_ospf6_lsa_type;
        !           949:   no_debug_ospf6_lsa_type_cmd.doc = no_doc;
        !           950: 
        !           951:   strncpy (detail_strbuf, strbuf, STRSIZE);
        !           952:   strncat (detail_strbuf, " (originate|examin|flooding)",
        !           953:            STRSIZE - strlen (detail_strbuf));
        !           954:   detail_strbuf[strlen (detail_strbuf)] = '\0';
        !           955:   no_str = &detail_strbuf[0];
        !           956:   str = &detail_strbuf[strlen ("no ")];
        !           957: 
        !           958:   strncpy (detail_docbuf, docbuf, DOCSIZE);
        !           959:   strncat (detail_docbuf, "Debug Originating LSA\n",
        !           960:            DOCSIZE - strlen (detail_docbuf));
        !           961:   strncat (detail_docbuf, "Debug Examining LSA\n",
        !           962:            DOCSIZE - strlen (detail_docbuf));
        !           963:   strncat (detail_docbuf, "Debug Flooding LSA\n",
        !           964:            DOCSIZE - strlen (detail_docbuf));
        !           965:   detail_docbuf[strlen (detail_docbuf)] = '\0';
        !           966:   no_doc = &detail_docbuf[0];
        !           967:   doc = &detail_docbuf[strlen (NO_STR)];
        !           968: 
        !           969:   debug_ospf6_lsa_type_detail_cmd.string = str;
        !           970:   debug_ospf6_lsa_type_detail_cmd.func = debug_ospf6_lsa_type;
        !           971:   debug_ospf6_lsa_type_detail_cmd.doc = doc;
        !           972: 
        !           973:   no_debug_ospf6_lsa_type_detail_cmd.string = no_str;
        !           974:   no_debug_ospf6_lsa_type_detail_cmd.func = no_debug_ospf6_lsa_type;
        !           975:   no_debug_ospf6_lsa_type_detail_cmd.doc = no_doc;
        !           976: 
        !           977:   install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
        !           978:   install_element (ENABLE_NODE, &debug_ospf6_lsa_type_cmd);
        !           979:   install_element (ENABLE_NODE, &debug_ospf6_lsa_type_detail_cmd);
        !           980:   install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
        !           981:   install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_cmd);
        !           982:   install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
        !           983:   install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
        !           984:   install_element (CONFIG_NODE, &debug_ospf6_lsa_type_cmd);
        !           985:   install_element (CONFIG_NODE, &debug_ospf6_lsa_type_detail_cmd);
        !           986:   install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
        !           987:   install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_cmd);
        !           988:   install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
        !           989: }
        !           990: 
        !           991: int
        !           992: config_write_ospf6_debug_lsa (struct vty *vty)
        !           993: {
        !           994:   u_int i;
        !           995:   struct ospf6_lsa_handler *handler;
        !           996: 
        !           997:   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
        !           998:     {
        !           999:       handler = vector_slot (ospf6_lsa_handler_vector, i);
        !          1000:       if (handler == NULL)
        !          1001:         continue;
        !          1002:       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG))
        !          1003:         vty_out (vty, "debug ospf6 lsa %s%s",
        !          1004:                  ospf6_lsa_handler_name (handler), VNL);
        !          1005:       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE))
        !          1006:         vty_out (vty, "debug ospf6 lsa %s originate%s",
        !          1007:                  ospf6_lsa_handler_name (handler), VNL);
        !          1008:       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN))
        !          1009:         vty_out (vty, "debug ospf6 lsa %s examin%s",
        !          1010:                  ospf6_lsa_handler_name (handler), VNL);
        !          1011:       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD))
        !          1012:         vty_out (vty, "debug ospf6 lsa %s flooding%s",
        !          1013:                  ospf6_lsa_handler_name (handler), VNL);
        !          1014:     }
        !          1015: 
        !          1016:   return 0;
        !          1017: }
        !          1018: 
        !          1019: 

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