File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospf6d / ospf6_lsa.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:11 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    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:   "Unk",
   79:   ospf6_unknown_lsa_show,
   80:   NULL,
   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: 
  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: 
  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);
  158:   if (ntohs (lsa1->header->age) == OSPF_LSA_MAXAGE &&
  159:       ntohs (lsa2->header->age) != OSPF_LSA_MAXAGE)
  160:     return 1;
  161:   if (ntohs (lsa1->header->age) != OSPF_LSA_MAXAGE &&
  162:       ntohs (lsa2->header->age) == OSPF_LSA_MAXAGE)
  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: 
  237:   if (ntohs (lsa->header->age) >= OSPF_LSA_MAXAGE)
  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. */
  242:       lsa->header->age = htons (OSPF_LSA_MAXAGE);
  243:       return OSPF_LSA_MAXAGE;
  244:     }
  245:   /* calculate age */
  246:   ulage = now.tv_sec - lsa->birth.tv_sec;
  247: 
  248:   /* if over MAXAGE, set to it */
  249:   age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
  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;
  262:   if (age > OSPF_LSA_MAXAGE)
  263:     age = OSPF_LSA_MAXAGE;
  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: 
  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);
  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: {
  309:   int32_t seqnuma, seqnumb;
  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: 
  317:   seqnuma = (int32_t) ntohl (a->header->seqnum);
  318:   seqnumb = (int32_t) ntohl (b->header->seqnum);
  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 */
  339:   if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
  340:     return -1;
  341:   else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
  342:     return 1;
  343: 
  344:   /* Age check */
  345:   if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
  346:     return 1;
  347:   else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
  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: {
  390:   vty_out (vty, "%-4s %-15s%-15s%4s %8s %30s%s",
  391:            "Type", "LSId", "AdvRouter", "Age", "SeqNum",
  392:            "Payload", VNL);
  393: }
  394: 
  395: void
  396: ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
  397: {
  398:   char adv_router[16], id[16];
  399:   int type;
  400:   struct ospf6_lsa_handler *handler;
  401:   char buf[64], tmpbuf[80];
  402:   int cnt = 0;
  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: 
  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:     }
  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);
  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);
  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;
  507:   struct timeval now, res;
  508:   char duration[16];
  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: 
  516:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
  517:   timersub (&now, &lsa->installed, &res);
  518:   timerstring (&res, duration, sizeof (duration));
  519: 
  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);
  529:   vty_out (vty, "Duration: %s%s", duration, VNL);
  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;
  634:   copy->rn = NULL;
  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: 
  661: 
  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: 
  688:   /* reflood lsa */
  689:   ospf6_flood (NULL, lsa);
  690: 
  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,
  730:                                    OSPF_LS_REFRESH_TIME);
  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);
  742:   ospf6_flood (NULL, new);
  743: 
  744:   return 0;
  745: }
  746: 
  747: 
  748: 
  749: /* Fletcher Checksum -- Refer to RFC1008. */
  750: 
  751: /* All the offsets are zero-based. The offsets in the RFC1008 are
  752:    one-based. */
  753: unsigned short
  754: ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
  755: {
  756:   u_char *buffer = (u_char *) &lsa_header->type;
  757:   int type_offset = buffer - (u_char *) &lsa_header->age; /* should be 2 */
  758: 
  759:   /* Skip the AGE field */
  760:   u_int16_t len = ntohs(lsa_header->length) - type_offset;
  761: 
  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);
  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: }
  793: 
  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: 
  801:   if (!strcmp(h->name, "unknown") &&
  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:     {
  810:       if (! islower ((unsigned char)h->name[i]))
  811:         buf[i] = tolower ((unsigned char)h->name[i]);
  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,
  821:        "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
  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;
  838:       if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
  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);
  852:       if (! strcmp (argv[1], "examine"))
  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: 
  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: 
  872: DEFUN (no_debug_ospf6_lsa_type,
  873:        no_debug_ospf6_lsa_hex_cmd,
  874:        "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
  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;
  892:       if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
  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);
  905:       if (! strcmp (argv[1], "examine"))
  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: 
  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:       )
  925: 
  926: void
  927: install_element_ospf6_debug_lsa (void)
  928: {
  929:   install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
  930:   install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_detail_cmd);
  931:   install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
  932:   install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
  933:   install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
  934:   install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_detail_cmd);
  935:   install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
  936:   install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
  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))
  957:         vty_out (vty, "debug ospf6 lsa %s examine%s",
  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>