File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospf6d / ospf6_lsa.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:39 2013 UTC (10 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

    1: /*
    2:  * Copyright (C) 2003 Yasuhiro Ohara
    3:  *
    4:  * This file is part of GNU Zebra.
    5:  *
    6:  * GNU Zebra is free software; you can redistribute it and/or modify it
    7:  * under the terms of the GNU General Public License as published by the
    8:  * Free Software Foundation; either version 2, or (at your option) any
    9:  * later version.
   10:  *
   11:  * GNU Zebra is distributed in the hope that it will be useful, but
   12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU General Public License
   17:  * along with GNU Zebra; see the file COPYING.  If not, write to the 
   18:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
   19:  * Boston, MA 02111-1307, USA.  
   20:  */
   21: 
   22: #include <zebra.h>
   23: 
   24: /* Include other stuffs */
   25: #include "log.h"
   26: #include "linklist.h"
   27: #include "vector.h"
   28: #include "vty.h"
   29: #include "command.h"
   30: #include "memory.h"
   31: #include "thread.h"
   32: #include "checksum.h"
   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: 
  676: /* Fletcher Checksum -- Refer to RFC1008. */
  677: 
  678: /* All the offsets are zero-based. The offsets in the RFC1008 are
  679:    one-based. */
  680: unsigned short
  681: ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
  682: {
  683:   u_char *buffer = (u_char *) &lsa_header->type;
  684:   int type_offset = buffer - (u_char *) &lsa_header->age; /* should be 2 */
  685: 
  686:   /* Skip the AGE field */
  687:   u_int16_t len = ntohs(lsa_header->length) - type_offset;
  688: 
  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);
  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>