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

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

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