Annotation of embedaddon/quagga/ospf6d/ospf6_lsa.c, revision 1.1.1.2

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

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