Annotation of embedaddon/quagga/ospf6d/ospf6_lsa.c, revision 1.1.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>