File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospf6d / ospf6_message.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:12 2016 UTC (8 years 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 "memory.h"
   25: #include "log.h"
   26: #include "vty.h"
   27: #include "command.h"
   28: #include "thread.h"
   29: #include "linklist.h"
   30: 
   31: #include "ospf6_proto.h"
   32: #include "ospf6_lsa.h"
   33: #include "ospf6_lsdb.h"
   34: #include "ospf6_network.h"
   35: #include "ospf6_message.h"
   36: 
   37: #include "ospf6_top.h"
   38: #include "ospf6_area.h"
   39: #include "ospf6_neighbor.h"
   40: #include "ospf6_interface.h"
   41: 
   42: /* for structures and macros ospf6_lsa_examin() needs */
   43: #include "ospf6_abr.h"
   44: #include "ospf6_asbr.h"
   45: #include "ospf6_intra.h"
   46: 
   47: #include "ospf6_flood.h"
   48: #include "ospf6d.h"
   49: 
   50: #include <netinet/ip6.h>
   51: 
   52: unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
   53: static const struct message ospf6_message_type_str [] =
   54: {
   55:   { OSPF6_MESSAGE_TYPE_HELLO,    "Hello"    },
   56:   { OSPF6_MESSAGE_TYPE_DBDESC,   "DbDesc"   },
   57:   { OSPF6_MESSAGE_TYPE_LSREQ,    "LSReq"    },
   58:   { OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate" },
   59:   { OSPF6_MESSAGE_TYPE_LSACK,    "LSAck"    },
   60: };
   61: static const size_t ospf6_message_type_str_max = array_size(ospf6_message_type_str);
   62: 
   63: /* Minimum (besides the standard OSPF packet header) lengths for OSPF
   64:    packets of particular types, offset is the "type" field. */
   65: const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
   66: {
   67:   0,
   68:   OSPF6_HELLO_MIN_SIZE,
   69:   OSPF6_DB_DESC_MIN_SIZE,
   70:   OSPF6_LS_REQ_MIN_SIZE,
   71:   OSPF6_LS_UPD_MIN_SIZE,
   72:   OSPF6_LS_ACK_MIN_SIZE
   73: };
   74: 
   75: /* Minimum (besides the standard LSA header) lengths for LSAs of particular
   76:    types, offset is the "LSA function code" portion of "LSA type" field. */
   77: const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
   78: {
   79:   0,
   80:   /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
   81:   /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
   82:   /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
   83:   /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
   84:   /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
   85:   /* 0x2006 */ 0,
   86:   /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
   87:   /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
   88:   /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
   89: };
   90: 
   91: /* print functions */
   92: 
   93: static void
   94: ospf6_header_print (struct ospf6_header *oh)
   95: {
   96:   char router_id[16], area_id[16];
   97:   inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
   98:   inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
   99: 
  100:   zlog_debug ("    OSPFv%d Type:%d Len:%hu Router-ID:%s",
  101:              oh->version, oh->type, ntohs (oh->length), router_id);
  102:   zlog_debug ("    Area-ID:%s Cksum:%hx Instance-ID:%d",
  103:              area_id, ntohs (oh->checksum), oh->instance_id);
  104: }
  105: 
  106: void
  107: ospf6_hello_print (struct ospf6_header *oh)
  108: {
  109:   struct ospf6_hello *hello;
  110:   char options[16];
  111:   char drouter[16], bdrouter[16], neighbor[16];
  112:   char *p;
  113: 
  114:   ospf6_header_print (oh);
  115:   assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
  116: 
  117:   hello = (struct ospf6_hello *)
  118:     ((caddr_t) oh + sizeof (struct ospf6_header));
  119: 
  120:   inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
  121:   inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
  122:   ospf6_options_printbuf (hello->options, options, sizeof (options));
  123: 
  124:   zlog_debug ("    I/F-Id:%ld Priority:%d Option:%s",
  125:              (u_long) ntohl (hello->interface_id), hello->priority, options);
  126:   zlog_debug ("    HelloInterval:%hu DeadInterval:%hu",
  127:              ntohs (hello->hello_interval), ntohs (hello->dead_interval));
  128:   zlog_debug ("    DR:%s BDR:%s", drouter, bdrouter);
  129: 
  130:   for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
  131:        p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
  132:        p += sizeof (u_int32_t))
  133:     {
  134:       inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
  135:       zlog_debug ("    Neighbor: %s", neighbor);
  136:     }
  137: 
  138:   assert (p == OSPF6_MESSAGE_END (oh));
  139: }
  140: 
  141: void
  142: ospf6_dbdesc_print (struct ospf6_header *oh)
  143: {
  144:   struct ospf6_dbdesc *dbdesc;
  145:   char options[16];
  146:   char *p;
  147: 
  148:   ospf6_header_print (oh);
  149:   assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
  150: 
  151:   dbdesc = (struct ospf6_dbdesc *)
  152:     ((caddr_t) oh + sizeof (struct ospf6_header));
  153: 
  154:   ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
  155: 
  156:   zlog_debug ("    MBZ: %#x Option: %s IfMTU: %hu",
  157:              dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
  158:   zlog_debug ("    MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
  159:              dbdesc->reserved2,
  160:              (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
  161:              (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
  162:              (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
  163:              (u_long) ntohl (dbdesc->seqnum));
  164: 
  165:   for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
  166:        p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
  167:        p += sizeof (struct ospf6_lsa_header))
  168:     ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
  169: 
  170:   assert (p == OSPF6_MESSAGE_END (oh));
  171: }
  172: 
  173: void
  174: ospf6_lsreq_print (struct ospf6_header *oh)
  175: {
  176:   char id[16], adv_router[16];
  177:   char *p;
  178: 
  179:   ospf6_header_print (oh);
  180:   assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
  181: 
  182:   for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
  183:        p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
  184:        p += sizeof (struct ospf6_lsreq_entry))
  185:     {
  186:       struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
  187:       inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
  188:       inet_ntop (AF_INET, &e->id, id, sizeof (id));
  189:       zlog_debug ("    [%s Id:%s Adv:%s]",
  190:                  ospf6_lstype_name (e->type), id, adv_router);
  191:     }
  192: 
  193:   assert (p == OSPF6_MESSAGE_END (oh));
  194: }
  195: 
  196: void
  197: ospf6_lsupdate_print (struct ospf6_header *oh)
  198: {
  199:   struct ospf6_lsupdate *lsupdate;
  200:   u_long num;
  201:   char *p;
  202: 
  203:   ospf6_header_print (oh);
  204:   assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
  205: 
  206:   lsupdate = (struct ospf6_lsupdate *)
  207:     ((caddr_t) oh + sizeof (struct ospf6_header));
  208: 
  209:   num = ntohl (lsupdate->lsa_number);
  210:   zlog_debug ("    Number of LSA: %ld", num);
  211: 
  212:   for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
  213:        p < OSPF6_MESSAGE_END (oh) &&
  214:        p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
  215:        p += OSPF6_LSA_SIZE (p))
  216:     {
  217:       ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
  218:     }
  219: 
  220:   assert (p == OSPF6_MESSAGE_END (oh));
  221: }
  222: 
  223: void
  224: ospf6_lsack_print (struct ospf6_header *oh)
  225: {
  226:   char *p;
  227: 
  228:   ospf6_header_print (oh);
  229:   assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
  230: 
  231:   for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
  232:        p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
  233:        p += sizeof (struct ospf6_lsa_header))
  234:     ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
  235: 
  236:   assert (p == OSPF6_MESSAGE_END (oh));
  237: }
  238: 
  239: static void
  240: ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
  241:                   struct ospf6_interface *oi, struct ospf6_header *oh)
  242: {
  243:   struct ospf6_hello *hello;
  244:   struct ospf6_neighbor *on;
  245:   char *p;
  246:   int twoway = 0;
  247:   int neighborchange = 0;
  248:   int backupseen = 0;
  249: 
  250:   hello = (struct ospf6_hello *)
  251:     ((caddr_t) oh + sizeof (struct ospf6_header));
  252: 
  253:   /* HelloInterval check */
  254:   if (ntohs (hello->hello_interval) != oi->hello_interval)
  255:     {
  256:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  257:         zlog_debug ("HelloInterval mismatch");
  258:       return;
  259:     }
  260: 
  261:   /* RouterDeadInterval check */
  262:   if (ntohs (hello->dead_interval) != oi->dead_interval)
  263:     {
  264:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  265:         zlog_debug ("RouterDeadInterval mismatch");
  266:       return;
  267:     }
  268: 
  269:   /* E-bit check */
  270:   if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
  271:       OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
  272:     {
  273:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  274:         zlog_debug ("E-bit mismatch");
  275:       return;
  276:     }
  277: 
  278:   /* Find neighbor, create if not exist */
  279:   on = ospf6_neighbor_lookup (oh->router_id, oi);
  280:   if (on == NULL)
  281:     {
  282:       on = ospf6_neighbor_create (oh->router_id, oi);
  283:       on->prev_drouter = on->drouter = hello->drouter;
  284:       on->prev_bdrouter = on->bdrouter = hello->bdrouter;
  285:       on->priority = hello->priority;
  286:     }
  287: 
  288:   /* always override neighbor's source address and ifindex */
  289:   on->ifindex = ntohl (hello->interface_id);
  290:   memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
  291: 
  292:   /* TwoWay check */
  293:   for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
  294:        p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
  295:        p += sizeof (u_int32_t))
  296:     {
  297:       u_int32_t *router_id = (u_int32_t *) p;
  298: 
  299:       if (*router_id == oi->area->ospf6->router_id)
  300:         twoway++;
  301:     }
  302: 
  303:   assert (p == OSPF6_MESSAGE_END (oh));
  304: 
  305:   /* RouterPriority check */
  306:   if (on->priority != hello->priority)
  307:     {
  308:       on->priority = hello->priority;
  309:       neighborchange++;
  310:     }
  311: 
  312:   /* DR check */
  313:   if (on->drouter != hello->drouter)
  314:     {
  315:       on->prev_drouter = on->drouter;
  316:       on->drouter = hello->drouter;
  317:       if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
  318:         neighborchange++;
  319:     }
  320: 
  321:   /* BDR check */
  322:   if (on->bdrouter != hello->bdrouter)
  323:     {
  324:       on->prev_bdrouter = on->bdrouter;
  325:       on->bdrouter = hello->bdrouter;
  326:       if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
  327:         neighborchange++;
  328:     }
  329: 
  330:   /* BackupSeen check */
  331:   if (oi->state == OSPF6_INTERFACE_WAITING)
  332:     {
  333:       if (hello->bdrouter == on->router_id)
  334:         backupseen++;
  335:       else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
  336:         backupseen++;
  337:     }
  338: 
  339:   /* Execute neighbor events */
  340:   thread_execute (master, hello_received, on, 0);
  341:   if (twoway)
  342:     thread_execute (master, twoway_received, on, 0);
  343:   else
  344:     thread_execute (master, oneway_received, on, 0);
  345: 
  346:   /* Schedule interface events */
  347:   if (backupseen)
  348:     thread_add_event (master, backup_seen, oi, 0);
  349:   if (neighborchange)
  350:     thread_add_event (master, neighbor_change, oi, 0);
  351: }
  352: 
  353: static void
  354: ospf6_dbdesc_recv_master (struct ospf6_header *oh,
  355:                           struct ospf6_neighbor *on)
  356: {
  357:   struct ospf6_dbdesc *dbdesc;
  358:   char *p;
  359: 
  360:   dbdesc = (struct ospf6_dbdesc *)
  361:     ((caddr_t) oh + sizeof (struct ospf6_header));
  362: 
  363:   if (on->state < OSPF6_NEIGHBOR_INIT)
  364:     {
  365:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  366:         zlog_debug ("Neighbor state less than Init, ignore");
  367:       return;
  368:     }
  369: 
  370:   switch (on->state)
  371:     {
  372:     case OSPF6_NEIGHBOR_TWOWAY:
  373:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  374:         zlog_debug ("Neighbor state is 2-Way, ignore");
  375:       return;
  376: 
  377:     case OSPF6_NEIGHBOR_INIT:
  378:       thread_execute (master, twoway_received, on, 0);
  379:       if (on->state != OSPF6_NEIGHBOR_EXSTART)
  380:         {
  381:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  382:             zlog_debug ("Neighbor state is not ExStart, ignore");
  383:           return;
  384:         }
  385:       /* else fall through to ExStart */
  386: 
  387:     case OSPF6_NEIGHBOR_EXSTART:
  388:       /* if neighbor obeys us as our slave, schedule negotiation_done
  389:          and process LSA Headers. Otherwise, ignore this message */
  390:       if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
  391:           ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
  392:           ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
  393:         {
  394:           /* execute NegotiationDone */
  395:           thread_execute (master, negotiation_done, on, 0);
  396: 
  397:           /* Record neighbor options */
  398:           memcpy (on->options, dbdesc->options, sizeof (on->options));
  399:         }
  400:       else
  401:         {
  402:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  403:             zlog_debug ("Negotiation failed");
  404:           return;
  405:         }
  406:       /* fall through to exchange */
  407: 
  408:     case OSPF6_NEIGHBOR_EXCHANGE:
  409:       if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
  410:         {
  411:           /* Duplicated DatabaseDescription is dropped by master */
  412:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  413:             zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
  414:           return;
  415:         }
  416: 
  417:       if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
  418:         {
  419:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  420:             zlog_debug ("Master/Slave bit mismatch");
  421:           thread_add_event (master, seqnumber_mismatch, on, 0);
  422:           return;
  423:         }
  424: 
  425:       if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
  426:         {
  427:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  428:             zlog_debug ("Initialize bit mismatch");
  429:           thread_add_event (master, seqnumber_mismatch, on, 0);
  430:           return;
  431:         }
  432: 
  433:       if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
  434:         {
  435:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  436:             zlog_debug ("Option field mismatch");
  437:           thread_add_event (master, seqnumber_mismatch, on, 0);
  438:           return;
  439:         }
  440: 
  441:       if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
  442:         {
  443:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  444:             zlog_debug ("Sequence number mismatch (%#lx expected)",
  445:                        (u_long) on->dbdesc_seqnum);
  446:           thread_add_event (master, seqnumber_mismatch, on, 0);
  447:           return;
  448:         }
  449:       break;
  450: 
  451:     case OSPF6_NEIGHBOR_LOADING:
  452:     case OSPF6_NEIGHBOR_FULL:
  453:       if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
  454:         {
  455:           /* Duplicated DatabaseDescription is dropped by master */
  456:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  457:             zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
  458:           return;
  459:         }
  460: 
  461:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  462:         zlog_debug ("Not duplicate dbdesc in state %s",
  463: 		    ospf6_neighbor_state_str[on->state]);
  464:       thread_add_event (master, seqnumber_mismatch, on, 0);
  465:       return;
  466: 
  467:     default:
  468:       assert (0);
  469:       break;
  470:     }
  471: 
  472:   /* Process LSA headers */
  473:   for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
  474:        p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
  475:        p += sizeof (struct ospf6_lsa_header))
  476:     {
  477:       struct ospf6_lsa *his, *mine;
  478:       struct ospf6_lsdb *lsdb = NULL;
  479: 
  480:       his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
  481: 
  482:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  483:         zlog_debug ("%s", his->name);
  484: 
  485:       switch (OSPF6_LSA_SCOPE (his->header->type))
  486:         {
  487:         case OSPF6_SCOPE_LINKLOCAL:
  488:           lsdb = on->ospf6_if->lsdb;
  489:           break;
  490:         case OSPF6_SCOPE_AREA:
  491:           lsdb = on->ospf6_if->area->lsdb;
  492:           break;
  493:         case OSPF6_SCOPE_AS:
  494:           lsdb = on->ospf6_if->area->ospf6->lsdb;
  495:           break;
  496:         case OSPF6_SCOPE_RESERVED:
  497:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  498:             zlog_debug ("Ignoring LSA of reserved scope");
  499:           ospf6_lsa_delete (his);
  500:           continue;
  501:           break;
  502:         }
  503: 
  504:       if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
  505:           IS_AREA_STUB (on->ospf6_if->area))
  506:         {
  507:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  508:             zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
  509:           ospf6_lsa_delete (his);
  510:           thread_add_event (master, seqnumber_mismatch, on, 0);
  511:           return;
  512:         }
  513: 
  514:       mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
  515:                                 his->header->adv_router, lsdb);
  516:       if (mine == NULL)
  517:         {
  518:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  519:             zlog_debug ("Add request (No database copy)");
  520:           ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
  521:         }
  522:       else if (ospf6_lsa_compare (his, mine) < 0)
  523:         {
  524:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  525:             zlog_debug ("Add request (Received MoreRecent)");
  526:           ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
  527:         }
  528:       else
  529:         {
  530:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  531:             zlog_debug ("Discard (Existing MoreRecent)");
  532:         }
  533:       ospf6_lsa_delete (his);
  534:     }
  535: 
  536:   assert (p == OSPF6_MESSAGE_END (oh));
  537: 
  538:   /* Increment sequence number */
  539:   on->dbdesc_seqnum ++;
  540: 
  541:   /* schedule send lsreq */
  542:   if (on->request_list->count && (on->thread_send_lsreq == NULL))
  543:     on->thread_send_lsreq =
  544:       thread_add_event (master, ospf6_lsreq_send, on, 0);
  545: 
  546:   THREAD_OFF (on->thread_send_dbdesc);
  547: 
  548:   /* More bit check */
  549:   if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
  550:       ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
  551:     thread_add_event (master, exchange_done, on, 0);
  552:   else
  553:     on->thread_send_dbdesc =
  554:       thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
  555: 
  556:   /* save last received dbdesc */
  557:   memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
  558: }
  559: 
  560: static void
  561: ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
  562:                          struct ospf6_neighbor *on)
  563: {
  564:   struct ospf6_dbdesc *dbdesc;
  565:   char *p;
  566: 
  567:   dbdesc = (struct ospf6_dbdesc *)
  568:     ((caddr_t) oh + sizeof (struct ospf6_header));
  569: 
  570:   if (on->state < OSPF6_NEIGHBOR_INIT)
  571:     {
  572:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  573:         zlog_debug ("Neighbor state less than Init, ignore");
  574:       return;
  575:     }
  576: 
  577:   switch (on->state)
  578:     {
  579:     case OSPF6_NEIGHBOR_TWOWAY:
  580:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  581:         zlog_debug ("Neighbor state is 2-Way, ignore");
  582:       return;
  583: 
  584:     case OSPF6_NEIGHBOR_INIT:
  585:       thread_execute (master, twoway_received, on, 0);
  586:       if (on->state != OSPF6_NEIGHBOR_EXSTART)
  587:         {
  588:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  589:             zlog_debug ("Neighbor state is not ExStart, ignore");
  590:           return;
  591:         }
  592:       /* else fall through to ExStart */
  593: 
  594:     case OSPF6_NEIGHBOR_EXSTART:
  595:       /* If the neighbor is Master, act as Slave. Schedule negotiation_done
  596:          and process LSA Headers. Otherwise, ignore this message */
  597:       if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
  598:           CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
  599:           CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
  600:           ntohs (oh->length) == sizeof (struct ospf6_header) +
  601:                                 sizeof (struct ospf6_dbdesc))
  602:         {
  603:           /* set the master/slave bit to slave */
  604:           UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
  605: 
  606:           /* set the DD sequence number to one specified by master */
  607:           on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
  608: 
  609:           /* schedule NegotiationDone */
  610:           thread_execute (master, negotiation_done, on, 0);
  611: 
  612:           /* Record neighbor options */
  613:           memcpy (on->options, dbdesc->options, sizeof (on->options));
  614:         }
  615:       else
  616:         {
  617:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  618:             zlog_debug ("Negotiation failed");
  619:           return;
  620:         }
  621:       break;
  622: 
  623:     case OSPF6_NEIGHBOR_EXCHANGE:
  624:       if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
  625:         {
  626:           /* Duplicated DatabaseDescription causes slave to retransmit */
  627:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  628:             zlog_debug ("Duplicated dbdesc causes retransmit");
  629:           THREAD_OFF (on->thread_send_dbdesc);
  630:           on->thread_send_dbdesc =
  631:             thread_add_event (master, ospf6_dbdesc_send, on, 0);
  632:           return;
  633:         }
  634: 
  635:       if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
  636:         {
  637:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  638:             zlog_debug ("Master/Slave bit mismatch");
  639:           thread_add_event (master, seqnumber_mismatch, on, 0);
  640:           return;
  641:         }
  642: 
  643:       if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
  644:         {
  645:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  646:             zlog_debug ("Initialize bit mismatch");
  647:           thread_add_event (master, seqnumber_mismatch, on, 0);
  648:           return;
  649:         }
  650: 
  651:       if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
  652:         {
  653:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  654:             zlog_debug ("Option field mismatch");
  655:           thread_add_event (master, seqnumber_mismatch, on, 0);
  656:           return;
  657:         }
  658: 
  659:       if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
  660:         {
  661:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  662:             zlog_debug ("Sequence number mismatch (%#lx expected)",
  663: 			(u_long) on->dbdesc_seqnum + 1);
  664:           thread_add_event (master, seqnumber_mismatch, on, 0);
  665:           return;
  666:         }
  667:       break;
  668: 
  669:     case OSPF6_NEIGHBOR_LOADING:
  670:     case OSPF6_NEIGHBOR_FULL:
  671:       if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
  672:         {
  673:           /* Duplicated DatabaseDescription causes slave to retransmit */
  674:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  675:             zlog_debug ("Duplicated dbdesc causes retransmit");
  676:           THREAD_OFF (on->thread_send_dbdesc);
  677:           on->thread_send_dbdesc =
  678:             thread_add_event (master, ospf6_dbdesc_send, on, 0);
  679:           return;
  680:         }
  681: 
  682:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  683:         zlog_debug ("Not duplicate dbdesc in state %s",
  684: 		    ospf6_neighbor_state_str[on->state]);
  685:       thread_add_event (master, seqnumber_mismatch, on, 0);
  686:       return;
  687: 
  688:     default:
  689:       assert (0);
  690:       break;
  691:     }
  692: 
  693:   /* Process LSA headers */
  694:   for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
  695:        p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
  696:        p += sizeof (struct ospf6_lsa_header))
  697:     {
  698:       struct ospf6_lsa *his, *mine;
  699:       struct ospf6_lsdb *lsdb = NULL;
  700: 
  701:       his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
  702: 
  703:       switch (OSPF6_LSA_SCOPE (his->header->type))
  704:         {
  705:         case OSPF6_SCOPE_LINKLOCAL:
  706:           lsdb = on->ospf6_if->lsdb;
  707:           break;
  708:         case OSPF6_SCOPE_AREA:
  709:           lsdb = on->ospf6_if->area->lsdb;
  710:           break;
  711:         case OSPF6_SCOPE_AS:
  712:           lsdb = on->ospf6_if->area->ospf6->lsdb;
  713:           break;
  714:         case OSPF6_SCOPE_RESERVED:
  715:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  716:             zlog_debug ("Ignoring LSA of reserved scope");
  717:           ospf6_lsa_delete (his);
  718:           continue;
  719:           break;
  720:         }
  721: 
  722:       if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
  723:           IS_AREA_STUB (on->ospf6_if->area))
  724:         {
  725:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  726:             zlog_debug ("E-bit mismatch with LSA Headers");
  727:           ospf6_lsa_delete (his);
  728:           thread_add_event (master, seqnumber_mismatch, on, 0);
  729:           return;
  730:         }
  731: 
  732:       mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
  733:                                 his->header->adv_router, lsdb);
  734:       if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
  735:         {
  736:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  737:             zlog_debug ("Add request-list: %s", his->name);
  738:           ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
  739:         }
  740:       ospf6_lsa_delete (his);
  741:     }
  742: 
  743:   assert (p == OSPF6_MESSAGE_END (oh));
  744: 
  745:   /* Set sequence number to Master's */
  746:   on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
  747: 
  748:   /* schedule send lsreq */
  749:   if ((on->thread_send_lsreq == NULL) &&
  750:       (on->request_list->count))
  751:     on->thread_send_lsreq =
  752:       thread_add_event (master, ospf6_lsreq_send, on, 0);
  753: 
  754:   THREAD_OFF (on->thread_send_dbdesc);
  755:   on->thread_send_dbdesc =
  756:     thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
  757: 
  758:   /* save last received dbdesc */
  759:   memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
  760: }
  761: 
  762: static void
  763: ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
  764:                    struct ospf6_interface *oi, struct ospf6_header *oh)
  765: {
  766:   struct ospf6_neighbor *on;
  767:   struct ospf6_dbdesc *dbdesc;
  768: 
  769:   on = ospf6_neighbor_lookup (oh->router_id, oi);
  770:   if (on == NULL)
  771:     {
  772:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  773:         zlog_debug ("Neighbor not found, ignore");
  774:       return;
  775:     }
  776: 
  777:   dbdesc = (struct ospf6_dbdesc *)
  778:     ((caddr_t) oh + sizeof (struct ospf6_header));
  779: 
  780:   /* Interface MTU check */
  781:   if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
  782:     {
  783:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  784:         zlog_debug ("I/F MTU mismatch");
  785:       return;
  786:     }
  787: 
  788:   if (dbdesc->reserved1 || dbdesc->reserved2)
  789:     {
  790:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  791:         zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
  792: 		    on->name);
  793:       dbdesc->reserved1 = 0;
  794:       dbdesc->reserved2 = 0;
  795:     }
  796: 
  797:   if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
  798:     ospf6_dbdesc_recv_master (oh, on);
  799:   else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
  800:     ospf6_dbdesc_recv_slave (oh, on);
  801:   else
  802:     {
  803:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  804:         zlog_debug ("Can't decide which is master, ignore");
  805:     }
  806: }
  807: 
  808: static void
  809: ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
  810:                   struct ospf6_interface *oi, struct ospf6_header *oh)
  811: {
  812:   struct ospf6_neighbor *on;
  813:   char *p;
  814:   struct ospf6_lsreq_entry *e;
  815:   struct ospf6_lsdb *lsdb = NULL;
  816:   struct ospf6_lsa *lsa;
  817: 
  818:   on = ospf6_neighbor_lookup (oh->router_id, oi);
  819:   if (on == NULL)
  820:     {
  821:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  822:         zlog_debug ("Neighbor not found, ignore");
  823:       return;
  824:     }
  825: 
  826:   if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
  827:       on->state != OSPF6_NEIGHBOR_LOADING &&
  828:       on->state != OSPF6_NEIGHBOR_FULL)
  829:     {
  830:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  831:         zlog_debug ("Neighbor state less than Exchange, ignore");
  832:       return;
  833:     }
  834: 
  835:   /* Process each request */
  836:   for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
  837:        p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
  838:        p += sizeof (struct ospf6_lsreq_entry))
  839:     {
  840:       e = (struct ospf6_lsreq_entry *) p;
  841: 
  842:       switch (OSPF6_LSA_SCOPE (e->type))
  843:         {
  844:         case OSPF6_SCOPE_LINKLOCAL:
  845:           lsdb = on->ospf6_if->lsdb;
  846:           break;
  847:         case OSPF6_SCOPE_AREA:
  848:           lsdb = on->ospf6_if->area->lsdb;
  849:           break;
  850:         case OSPF6_SCOPE_AS:
  851:           lsdb = on->ospf6_if->area->ospf6->lsdb;
  852:           break;
  853:         default:
  854:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  855:             zlog_debug ("Ignoring LSA of reserved scope");
  856:           continue;
  857:           break;
  858:         }
  859: 
  860:       /* Find database copy */
  861:       lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
  862:       if (lsa == NULL)
  863:         {
  864:           char id[16], adv_router[16];
  865:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
  866:             {
  867:               inet_ntop (AF_INET, &e->id, id, sizeof (id));
  868:               inet_ntop (AF_INET, &e->adv_router, adv_router,
  869:                      sizeof (adv_router));
  870:               zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
  871: 			  ospf6_lstype_name (e->type), id, adv_router);
  872:             }
  873:           thread_add_event (master, bad_lsreq, on, 0);
  874:           return;
  875:         }
  876: 
  877:       ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
  878:     }
  879: 
  880:   assert (p == OSPF6_MESSAGE_END (oh));
  881: 
  882:   /* schedule send lsupdate */
  883:   THREAD_OFF (on->thread_send_lsupdate);
  884:   on->thread_send_lsupdate =
  885:     thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
  886: }
  887: 
  888: /* Verify, that the specified memory area contains exactly N valid IPv6
  889:    prefixes as specified by RFC5340, A.4.1. */
  890: static unsigned
  891: ospf6_prefixes_examin
  892: (
  893:   struct ospf6_prefix *current, /* start of buffer    */
  894:   unsigned length,
  895:   const u_int32_t req_num_pfxs  /* always compared with the actual number of prefixes */
  896: )
  897: {
  898:   u_char requested_pfx_bytes;
  899:   u_int32_t real_num_pfxs = 0;
  900: 
  901:   while (length)
  902:   {
  903:     if (length < OSPF6_PREFIX_MIN_SIZE)
  904:     {
  905:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
  906:         zlog_debug ("%s: undersized IPv6 prefix header", __func__);
  907:       return MSG_NG;
  908:     }
  909:     /* safe to look deeper */
  910:     if (current->prefix_length > IPV6_MAX_BITLEN)
  911:     {
  912:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
  913:         zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
  914:       return MSG_NG;
  915:     }
  916:     /* covers both fixed- and variable-sized fields */
  917:     requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
  918:     if (requested_pfx_bytes > length)
  919:     {
  920:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
  921:         zlog_debug ("%s: undersized IPv6 prefix", __func__);
  922:       return MSG_NG;
  923:     }
  924:     /* next prefix */
  925:     length -= requested_pfx_bytes;
  926:     current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
  927:     real_num_pfxs++;
  928:   }
  929:   if (real_num_pfxs != req_num_pfxs)
  930:   {
  931:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
  932:       zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
  933:                   __func__, req_num_pfxs, real_num_pfxs);
  934:     return MSG_NG;
  935:   }
  936:   return MSG_OK;
  937: }
  938: 
  939: /* Verify an LSA to have a valid length and dispatch further (where
  940:    appropriate) to check if the contents, including nested IPv6 prefixes,
  941:    is properly sized/aligned within the LSA. Note that this function gets
  942:    LSA type in network byte order, uses in host byte order and passes to
  943:    ospf6_lstype_name() in network byte order again. */
  944: static unsigned
  945: ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
  946: {
  947:   struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
  948:   struct ospf6_as_external_lsa *as_external_lsa;
  949:   struct ospf6_link_lsa *link_lsa;
  950:   unsigned exp_length;
  951:   u_int8_t ltindex;
  952:   u_int16_t lsatype;
  953: 
  954:   /* In case an additional minimum length constraint is defined for current
  955:      LSA type, make sure that this constraint is met. */
  956:   lsatype = ntohs (lsah->type);
  957:   ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
  958:   if
  959:   (
  960:     ltindex < OSPF6_LSTYPE_SIZE &&
  961:     ospf6_lsa_minlen[ltindex] &&
  962:     lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
  963:   )
  964:   {
  965:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
  966:       zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
  967:     return MSG_NG;
  968:   }
  969:   switch (lsatype)
  970:   {
  971:   case OSPF6_LSTYPE_ROUTER:
  972:     /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
  973:        by N>=0 interface descriptions. */
  974:     if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
  975:     {
  976:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
  977:         zlog_debug ("%s: interface description alignment error", __func__);
  978:       return MSG_NG;
  979:     }
  980:     break;
  981:   case OSPF6_LSTYPE_NETWORK:
  982:     /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
  983:        followed by N>=0 attached router descriptions. */
  984:     if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
  985:     {
  986:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
  987:         zlog_debug ("%s: router description alignment error", __func__);
  988:       return MSG_NG;
  989:     }
  990:     break;
  991:   case OSPF6_LSTYPE_INTER_PREFIX:
  992:     /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
  993:        followed by 3-4 fields of a single IPv6 prefix. */
  994:     if (headeronly)
  995:       break;
  996:     return ospf6_prefixes_examin
  997:     (
  998:       (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
  999:       lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
 1000:       1
 1001:     );
 1002:   case OSPF6_LSTYPE_INTER_ROUTER:
 1003:     /* RFC5340 A.4.6, fixed-size LSA. */
 1004:     if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
 1005:     {
 1006:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1007:         zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
 1008:       return MSG_NG;
 1009:     }
 1010:     break;
 1011:   case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
 1012:   case OSPF6_LSTYPE_TYPE_7:
 1013:     /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
 1014:        followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
 1015:        16 bytes of forwarding address, 4 bytes of external route tag,
 1016:        4 bytes of referenced link state ID. */
 1017:     if (headeronly)
 1018:       break;
 1019:     as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
 1020:     exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
 1021:     /* To find out if the last optional field (Referenced Link State ID) is
 1022:        assumed in this LSA, we need to access fixed fields of the IPv6
 1023:        prefix before ospf6_prefix_examin() confirms its sizing. */
 1024:     if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
 1025:     {
 1026:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1027:         zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
 1028:       return MSG_NG;
 1029:     }
 1030:     /* forwarding address */
 1031:     if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
 1032:       exp_length += 16;
 1033:     /* external route tag */
 1034:     if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
 1035:       exp_length += 4;
 1036:     /* referenced link state ID */
 1037:     if (as_external_lsa->prefix.u._prefix_referenced_lstype)
 1038:       exp_length += 4;
 1039:     /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
 1040:        this check does not include any IPv6 prefix fields. */
 1041:     if (exp_length > lsalen)
 1042:     {
 1043:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1044:         zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
 1045:       return MSG_NG;
 1046:     }
 1047:     /* The last call completely covers the remainder (IPv6 prefix). */
 1048:     return ospf6_prefixes_examin
 1049:     (
 1050:       (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
 1051:       lsalen - exp_length,
 1052:       1
 1053:     );
 1054:   case OSPF6_LSTYPE_LINK:
 1055:     /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
 1056:        by N>=0 IPv6 prefix blocks (with N declared beforehand). */
 1057:     if (headeronly)
 1058:       break;
 1059:     link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
 1060:     return ospf6_prefixes_examin
 1061:     (
 1062:       (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
 1063:       lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
 1064:       ntohl (link_lsa->prefix_num) /* 32 bits */
 1065:     );
 1066:   case OSPF6_LSTYPE_INTRA_PREFIX:
 1067:   /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
 1068:      followed by N>=0 IPv6 prefixes (with N declared beforehand). */
 1069:     if (headeronly)
 1070:       break;
 1071:     intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
 1072:     return ospf6_prefixes_examin
 1073:     (
 1074:       (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
 1075:       lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
 1076:       ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
 1077:     );
 1078:   }
 1079:   /* No additional validation is possible for unknown LSA types, which are
 1080:      themselves valid in OPSFv3, hence the default decision is to accept. */
 1081:   return MSG_OK;
 1082: }
 1083: 
 1084: /* Verify if the provided input buffer is a valid sequence of LSAs. This
 1085:    includes verification of LSA blocks length/alignment and dispatching
 1086:    of deeper-level checks. */
 1087: static unsigned
 1088: ospf6_lsaseq_examin
 1089: (
 1090:   struct ospf6_lsa_header *lsah, /* start of buffered data */
 1091:   size_t length,
 1092:   const u_char headeronly,
 1093:   /* When declared_num_lsas is not 0, compare it to the real number of LSAs
 1094:      and treat the difference as an error. */
 1095:   const u_int32_t declared_num_lsas
 1096: )
 1097: {
 1098:   u_int32_t counted_lsas = 0;
 1099: 
 1100:   while (length)
 1101:   {
 1102:     u_int16_t lsalen;
 1103:     if (length < OSPF6_LSA_HEADER_SIZE)
 1104:     {
 1105:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1106:         zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
 1107:                     __func__, length, counted_lsas);
 1108:       return MSG_NG;
 1109:     }
 1110:     /* save on ntohs() calls here and in the LSA validator */
 1111:     lsalen = OSPF6_LSA_SIZE (lsah);
 1112:     if (lsalen < OSPF6_LSA_HEADER_SIZE)
 1113:     {
 1114:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1115:         zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
 1116:                     __func__, counted_lsas, lsalen);
 1117:       return MSG_NG;
 1118:     }
 1119:     if (headeronly)
 1120:     {
 1121:       /* less checks here and in ospf6_lsa_examin() */
 1122:       if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
 1123:       {
 1124:         if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1125:           zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
 1126:                       ospf6_lstype_name (lsah->type), counted_lsas);
 1127:         return MSG_NG;
 1128:       }
 1129:       lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
 1130:       length -= OSPF6_LSA_HEADER_SIZE;
 1131:     }
 1132:     else
 1133:     {
 1134:       /* make sure the input buffer is deep enough before further checks */
 1135:       if (lsalen > length)
 1136:       {
 1137:         if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1138:           zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
 1139:                       __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
 1140:         return MSG_NG;
 1141:       }
 1142:       if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
 1143:       {
 1144:         if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1145:           zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
 1146:                       ospf6_lstype_name (lsah->type), counted_lsas);
 1147:         return MSG_NG;
 1148:       }
 1149:       lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
 1150:       length -= lsalen;
 1151:     }
 1152:     counted_lsas++;
 1153:   }
 1154: 
 1155:   if (declared_num_lsas && counted_lsas != declared_num_lsas)
 1156:   {
 1157:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1158:       zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
 1159:                   __func__, declared_num_lsas, counted_lsas);
 1160:     return MSG_NG;
 1161:   }
 1162:   return MSG_OK;
 1163: }
 1164: 
 1165: /* Verify a complete OSPF packet for proper sizing/alignment. */
 1166: static unsigned
 1167: ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
 1168: {
 1169:   struct ospf6_lsupdate *lsupd;
 1170:   unsigned test;
 1171: 
 1172:   /* length, 1st approximation */
 1173:   if (bytesonwire < OSPF6_HEADER_SIZE)
 1174:   {
 1175:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1176:       zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
 1177:     return MSG_NG;
 1178:   }
 1179:   /* Now it is safe to access header fields. */
 1180:   if (bytesonwire != ntohs (oh->length))
 1181:   {
 1182:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1183:       zlog_debug ("%s: packet length error (%u real, %u declared)",
 1184:                   __func__, bytesonwire, ntohs (oh->length));
 1185:     return MSG_NG;
 1186:   }
 1187:   /* version check */
 1188:   if (oh->version != OSPFV3_VERSION)
 1189:   {
 1190:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1191:       zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
 1192:     return MSG_NG;
 1193:   }
 1194:   /* length, 2nd approximation */
 1195:   if
 1196:   (
 1197:     oh->type < OSPF6_MESSAGE_TYPE_ALL &&
 1198:     ospf6_packet_minlen[oh->type] &&
 1199:     bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
 1200:   )
 1201:   {
 1202:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1203:       zlog_debug ("%s: undersized (%u B) %s packet", __func__,
 1204:                   bytesonwire, LOOKUP (ospf6_message_type_str, oh->type));
 1205:     return MSG_NG;
 1206:   }
 1207:   /* type-specific deeper validation */
 1208:   switch (oh->type)
 1209:   {
 1210:   case OSPF6_MESSAGE_TYPE_HELLO:
 1211:     /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
 1212:        by N>=0 router-IDs. */
 1213:     if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
 1214:       return MSG_OK;
 1215:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1216:       zlog_debug ("%s: alignment error in %s packet",
 1217:                   __func__, LOOKUP (ospf6_message_type_str, oh->type));
 1218:     return MSG_NG;
 1219:   case OSPF6_MESSAGE_TYPE_DBDESC:
 1220:     /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
 1221:        by N>=0 header-only LSAs. */
 1222:     test = ospf6_lsaseq_examin
 1223:     (
 1224:       (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
 1225:       bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
 1226:       1,
 1227:       0
 1228:     );
 1229:     break;
 1230:   case OSPF6_MESSAGE_TYPE_LSREQ:
 1231:     /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
 1232:     if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
 1233:       return MSG_OK;
 1234:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1235:       zlog_debug ("%s: alignment error in %s packet",
 1236:                   __func__, LOOKUP (ospf6_message_type_str, oh->type));
 1237:     return MSG_NG;
 1238:   case OSPF6_MESSAGE_TYPE_LSUPDATE:
 1239:     /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
 1240:        by N>=0 full LSAs (with N declared beforehand). */
 1241:     lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
 1242:     test = ospf6_lsaseq_examin
 1243:     (
 1244:       (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
 1245:       bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
 1246:       0,
 1247:       ntohl (lsupd->lsa_number) /* 32 bits */
 1248:     );
 1249:     break;
 1250:   case OSPF6_MESSAGE_TYPE_LSACK:
 1251:     /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
 1252:     test = ospf6_lsaseq_examin
 1253:     (
 1254:       (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
 1255:       bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
 1256:       1,
 1257:       0
 1258:     );
 1259:     break;
 1260:   default:
 1261:     if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1262:       zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
 1263:     return MSG_NG;
 1264:   }
 1265:   if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1266:     zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type));
 1267:   return test;
 1268: }
 1269: 
 1270: /* Verify particular fields of otherwise correct received OSPF packet to
 1271:    meet the requirements of RFC. */
 1272: static int
 1273: ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
 1274: {
 1275:   char buf[2][INET_ADDRSTRLEN];
 1276: 
 1277:   if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
 1278:     return MSG_NG;
 1279: 
 1280:   /* Area-ID check */
 1281:   if (oh->area_id != oi->area->area_id)
 1282:   {
 1283:     if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1284:     {
 1285:       if (oh->area_id == OSPF_AREA_BACKBONE)
 1286:         zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
 1287:       else
 1288:         zlog_debug
 1289:         (
 1290:           "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
 1291:           inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
 1292:           inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
 1293:          );
 1294:     }
 1295:     return MSG_NG;
 1296:   }
 1297: 
 1298:   /* Instance-ID check */
 1299:   if (oh->instance_id != oi->instance_id)
 1300:   {
 1301:     if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1302:       zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
 1303:     return MSG_NG;
 1304:   }
 1305: 
 1306:   /* Router-ID check */
 1307:   if (oh->router_id == oi->area->ospf6->router_id)
 1308:   {
 1309:     zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
 1310:     return MSG_NG;
 1311:   }
 1312:   return MSG_OK;
 1313: }
 1314: 
 1315: static void
 1316: ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
 1317:                      struct ospf6_interface *oi, struct ospf6_header *oh)
 1318: {
 1319:   struct ospf6_neighbor *on;
 1320:   struct ospf6_lsupdate *lsupdate;
 1321:   char *p;
 1322: 
 1323:   on = ospf6_neighbor_lookup (oh->router_id, oi);
 1324:   if (on == NULL)
 1325:     {
 1326:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1327:         zlog_debug ("Neighbor not found, ignore");
 1328:       return;
 1329:     }
 1330: 
 1331:   if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
 1332:       on->state != OSPF6_NEIGHBOR_LOADING &&
 1333:       on->state != OSPF6_NEIGHBOR_FULL)
 1334:     {
 1335:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1336:         zlog_debug ("Neighbor state less than Exchange, ignore");
 1337:       return;
 1338:     }
 1339: 
 1340:   lsupdate = (struct ospf6_lsupdate *)
 1341:     ((caddr_t) oh + sizeof (struct ospf6_header));
 1342: 
 1343:   /* Process LSAs */
 1344:   for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
 1345:        p < OSPF6_MESSAGE_END (oh) &&
 1346:        p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
 1347:        p += OSPF6_LSA_SIZE (p))
 1348:     {
 1349:       ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
 1350:     }
 1351: 
 1352:   assert (p == OSPF6_MESSAGE_END (oh));
 1353: 
 1354: }
 1355: 
 1356: static void
 1357: ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
 1358:                   struct ospf6_interface *oi, struct ospf6_header *oh)
 1359: {
 1360:   struct ospf6_neighbor *on;
 1361:   char *p;
 1362:   struct ospf6_lsa *his, *mine;
 1363:   struct ospf6_lsdb *lsdb = NULL;
 1364: 
 1365:   assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
 1366: 
 1367:   on = ospf6_neighbor_lookup (oh->router_id, oi);
 1368:   if (on == NULL)
 1369:     {
 1370:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1371:         zlog_debug ("Neighbor not found, ignore");
 1372:       return;
 1373:     }
 1374: 
 1375:   if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
 1376:       on->state != OSPF6_NEIGHBOR_LOADING &&
 1377:       on->state != OSPF6_NEIGHBOR_FULL)
 1378:     {
 1379:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1380:         zlog_debug ("Neighbor state less than Exchange, ignore");
 1381:       return;
 1382:     }
 1383: 
 1384:   for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
 1385:        p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
 1386:        p += sizeof (struct ospf6_lsa_header))
 1387:     {
 1388:       his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
 1389: 
 1390:       switch (OSPF6_LSA_SCOPE (his->header->type))
 1391:         {
 1392:         case OSPF6_SCOPE_LINKLOCAL:
 1393:           lsdb = on->ospf6_if->lsdb;
 1394:           break;
 1395:         case OSPF6_SCOPE_AREA:
 1396:           lsdb = on->ospf6_if->area->lsdb;
 1397:           break;
 1398:         case OSPF6_SCOPE_AS:
 1399:           lsdb = on->ospf6_if->area->ospf6->lsdb;
 1400:           break;
 1401:         case OSPF6_SCOPE_RESERVED:
 1402:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1403:             zlog_debug ("Ignoring LSA of reserved scope");
 1404:           ospf6_lsa_delete (his);
 1405:           continue;
 1406:           break;
 1407:         }
 1408: 
 1409:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1410:         zlog_debug ("%s acknowledged by %s", his->name, on->name);
 1411: 
 1412:       /* Find database copy */
 1413:       mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
 1414:                                 his->header->adv_router, lsdb);
 1415:       if (mine == NULL)
 1416:         {
 1417:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1418:             zlog_debug ("No database copy");
 1419:           ospf6_lsa_delete (his);
 1420:           continue;
 1421:         }
 1422: 
 1423:       /* Check if the LSA is on his retrans-list */
 1424:       mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
 1425:                                 his->header->adv_router, on->retrans_list);
 1426:       if (mine == NULL)
 1427:         {
 1428:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1429:             zlog_debug ("Not on %s's retrans-list", on->name);
 1430:           ospf6_lsa_delete (his);
 1431:           continue;
 1432:         }
 1433: 
 1434:       if (ospf6_lsa_compare (his, mine) != 0)
 1435:         {
 1436:           /* Log this questionable acknowledgement,
 1437:              and examine the next one. */
 1438:           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1439:             zlog_debug ("Questionable acknowledgement");
 1440:           ospf6_lsa_delete (his);
 1441:           continue;
 1442:         }
 1443: 
 1444:       if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1445:         zlog_debug ("Acknowledged, remove from %s's retrans-list",
 1446: 		    on->name);
 1447: 
 1448:       ospf6_decrement_retrans_count (mine);
 1449:       if (OSPF6_LSA_IS_MAXAGE (mine))
 1450:         ospf6_maxage_remove (on->ospf6_if->area->ospf6);
 1451:       ospf6_lsdb_remove (mine, on->retrans_list);
 1452:       ospf6_lsa_delete (his);
 1453:     }
 1454: 
 1455:   assert (p == OSPF6_MESSAGE_END (oh));
 1456: }
 1457: 
 1458: static u_char *recvbuf = NULL;
 1459: static u_char *sendbuf = NULL;
 1460: static unsigned int iobuflen = 0;
 1461: 
 1462: int
 1463: ospf6_iobuf_size (unsigned int size)
 1464: {
 1465:   u_char *recvnew, *sendnew;
 1466: 
 1467:   if (size <= iobuflen)
 1468:     return iobuflen;
 1469: 
 1470:   recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
 1471:   sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
 1472:   if (recvnew == NULL || sendnew == NULL)
 1473:     {
 1474:       if (recvnew)
 1475:         XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
 1476:       if (sendnew)
 1477:         XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
 1478:       zlog_debug ("Could not allocate I/O buffer of size %d.", size);
 1479:       return iobuflen;
 1480:     }
 1481: 
 1482:   if (recvbuf)
 1483:     XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
 1484:   if (sendbuf)
 1485:     XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
 1486:   recvbuf = recvnew;
 1487:   sendbuf = sendnew;
 1488:   iobuflen = size;
 1489: 
 1490:   return iobuflen;
 1491: }
 1492: 
 1493: void
 1494: ospf6_message_terminate (void)
 1495: {
 1496:   if (recvbuf)
 1497:     {
 1498:       XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
 1499:       recvbuf = NULL;
 1500:     }
 1501: 
 1502:   if (sendbuf)
 1503:     {
 1504:       XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
 1505:       sendbuf = NULL;
 1506:     }
 1507: 
 1508:   iobuflen = 0;
 1509: }
 1510: 
 1511: int
 1512: ospf6_receive (struct thread *thread)
 1513: {
 1514:   int sockfd;
 1515:   unsigned int len;
 1516:   char srcname[64], dstname[64];
 1517:   struct in6_addr src, dst;
 1518:   ifindex_t ifindex;
 1519:   struct iovec iovector[2];
 1520:   struct ospf6_interface *oi;
 1521:   struct ospf6_header *oh;
 1522: 
 1523:   /* add next read thread */
 1524:   sockfd = THREAD_FD (thread);
 1525:   thread_add_read (master, ospf6_receive, NULL, sockfd);
 1526: 
 1527:   /* initialize */
 1528:   memset (&src, 0, sizeof (src));
 1529:   memset (&dst, 0, sizeof (dst));
 1530:   ifindex = 0;
 1531:   memset (recvbuf, 0, iobuflen);
 1532:   iovector[0].iov_base = recvbuf;
 1533:   iovector[0].iov_len = iobuflen;
 1534:   iovector[1].iov_base = NULL;
 1535:   iovector[1].iov_len = 0;
 1536: 
 1537:   /* receive message */
 1538:   len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
 1539:   if (len > iobuflen)
 1540:     {
 1541:       zlog_err ("Excess message read");
 1542:       return 0;
 1543:     }
 1544: 
 1545:   oi = ospf6_interface_lookup_by_ifindex (ifindex);
 1546:   if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
 1547:     {
 1548:       zlog_debug ("Message received on disabled interface");
 1549:       return 0;
 1550:     }
 1551:   if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
 1552:     {
 1553:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 1554:         zlog_debug ("%s: Ignore message on passive interface %s",
 1555:                     __func__, oi->interface->name);
 1556:       return 0;
 1557:     }
 1558: 
 1559:   oh = (struct ospf6_header *) recvbuf;
 1560:   if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
 1561:     return 0;
 1562: 
 1563:   /* Being here means, that no sizing/alignment issues were detected in
 1564:      the input packet. This renders the additional checks performed below
 1565:      and also in the type-specific dispatching functions a dead code,
 1566:      which can be dismissed in a cleanup-focused review round later. */
 1567: 
 1568:   /* Log */
 1569:   if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
 1570:     {
 1571:       inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
 1572:       inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
 1573:       zlog_debug ("%s received on %s",
 1574:                  LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
 1575:       zlog_debug ("    src: %s", srcname);
 1576:       zlog_debug ("    dst: %s", dstname);
 1577: 
 1578:       switch (oh->type)
 1579:         {
 1580:           case OSPF6_MESSAGE_TYPE_HELLO:
 1581:             ospf6_hello_print (oh);
 1582:             break;
 1583:           case OSPF6_MESSAGE_TYPE_DBDESC:
 1584:             ospf6_dbdesc_print (oh);
 1585:             break;
 1586:           case OSPF6_MESSAGE_TYPE_LSREQ:
 1587:             ospf6_lsreq_print (oh);
 1588:             break;
 1589:           case OSPF6_MESSAGE_TYPE_LSUPDATE:
 1590:             ospf6_lsupdate_print (oh);
 1591:             break;
 1592:           case OSPF6_MESSAGE_TYPE_LSACK:
 1593:             ospf6_lsack_print (oh);
 1594:             break;
 1595:           default:
 1596:             assert (0);
 1597:         }
 1598:     }
 1599: 
 1600:   switch (oh->type)
 1601:     {
 1602:       case OSPF6_MESSAGE_TYPE_HELLO:
 1603:         ospf6_hello_recv (&src, &dst, oi, oh);
 1604:         break;
 1605: 
 1606:       case OSPF6_MESSAGE_TYPE_DBDESC:
 1607:         ospf6_dbdesc_recv (&src, &dst, oi, oh);
 1608:         break;
 1609: 
 1610:       case OSPF6_MESSAGE_TYPE_LSREQ:
 1611:         ospf6_lsreq_recv (&src, &dst, oi, oh);
 1612:         break;
 1613: 
 1614:       case OSPF6_MESSAGE_TYPE_LSUPDATE:
 1615:         ospf6_lsupdate_recv (&src, &dst, oi, oh);
 1616:         break;
 1617: 
 1618:       case OSPF6_MESSAGE_TYPE_LSACK:
 1619:         ospf6_lsack_recv (&src, &dst, oi, oh);
 1620:         break;
 1621: 
 1622:       default:
 1623:         assert (0);
 1624:     }
 1625: 
 1626:   return 0;
 1627: }
 1628: 
 1629: static void
 1630: ospf6_send (struct in6_addr *src, struct in6_addr *dst,
 1631:             struct ospf6_interface *oi, struct ospf6_header *oh)
 1632: {
 1633:   unsigned int len;
 1634:   char srcname[64], dstname[64];
 1635:   struct iovec iovector[2];
 1636: 
 1637:   /* initialize */
 1638:   iovector[0].iov_base = (caddr_t) oh;
 1639:   iovector[0].iov_len = ntohs (oh->length);
 1640:   iovector[1].iov_base = NULL;
 1641:   iovector[1].iov_len = 0;
 1642: 
 1643:   /* fill OSPF header */
 1644:   oh->version = OSPFV3_VERSION;
 1645:   /* message type must be set before */
 1646:   /* message length must be set before */
 1647:   oh->router_id = oi->area->ospf6->router_id;
 1648:   oh->area_id = oi->area->area_id;
 1649:   /* checksum is calculated by kernel */
 1650:   oh->instance_id = oi->instance_id;
 1651:   oh->reserved = 0;
 1652: 
 1653:   /* Log */
 1654:   if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
 1655:     {
 1656:       inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
 1657:       if (src)
 1658:         inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
 1659:       else
 1660:         memset (srcname, 0, sizeof (srcname));
 1661:       zlog_debug ("%s send on %s",
 1662:                  LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
 1663:       zlog_debug ("    src: %s", srcname);
 1664:       zlog_debug ("    dst: %s", dstname);
 1665: 
 1666:       switch (oh->type)
 1667:         {
 1668:           case OSPF6_MESSAGE_TYPE_HELLO:
 1669:             ospf6_hello_print (oh);
 1670:             break;
 1671:           case OSPF6_MESSAGE_TYPE_DBDESC:
 1672:             ospf6_dbdesc_print (oh);
 1673:             break;
 1674:           case OSPF6_MESSAGE_TYPE_LSREQ:
 1675:             ospf6_lsreq_print (oh);
 1676:             break;
 1677:           case OSPF6_MESSAGE_TYPE_LSUPDATE:
 1678:             ospf6_lsupdate_print (oh);
 1679:             break;
 1680:           case OSPF6_MESSAGE_TYPE_LSACK:
 1681:             ospf6_lsack_print (oh);
 1682:             break;
 1683:           default:
 1684:             zlog_debug ("Unknown message");
 1685:             assert (0);
 1686:             break;
 1687:         }
 1688:     }
 1689: 
 1690:   /* send message */
 1691:   len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
 1692:   if (len != ntohs (oh->length))
 1693:     zlog_err ("Could not send entire message");
 1694: }
 1695: 
 1696: static uint32_t
 1697: ospf6_packet_max(struct ospf6_interface *oi)
 1698: {
 1699:   assert (oi->ifmtu > sizeof (struct ip6_hdr));
 1700:   return oi->ifmtu - (sizeof (struct ip6_hdr));
 1701: }
 1702: 
 1703: int
 1704: ospf6_hello_send (struct thread *thread)
 1705: {
 1706:   struct ospf6_interface *oi;
 1707:   struct ospf6_header *oh;
 1708:   struct ospf6_hello *hello;
 1709:   u_char *p;
 1710:   struct listnode *node, *nnode;
 1711:   struct ospf6_neighbor *on;
 1712: 
 1713:   oi = (struct ospf6_interface *) THREAD_ARG (thread);
 1714:   oi->thread_send_hello = (struct thread *) NULL;
 1715: 
 1716:   if (oi->state <= OSPF6_INTERFACE_DOWN)
 1717:     {
 1718:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
 1719:         zlog_debug ("Unable to send Hello on down interface %s",
 1720:                    oi->interface->name);
 1721:       return 0;
 1722:     }
 1723: 
 1724:   if (iobuflen == 0)
 1725:     {
 1726:       zlog_debug ("Unable to send Hello on interface %s iobuflen is 0",
 1727:                  oi->interface->name);
 1728:       return 0;
 1729:     }
 1730: 
 1731:   /* set next thread */
 1732:   oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
 1733:                                             oi, oi->hello_interval);
 1734: 
 1735:   memset (sendbuf, 0, iobuflen);
 1736:   oh = (struct ospf6_header *) sendbuf;
 1737:   hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
 1738: 
 1739:   hello->interface_id = htonl (oi->interface->ifindex);
 1740:   hello->priority = oi->priority;
 1741:   hello->options[0] = oi->area->options[0];
 1742:   hello->options[1] = oi->area->options[1];
 1743:   hello->options[2] = oi->area->options[2];
 1744:   hello->hello_interval = htons (oi->hello_interval);
 1745:   hello->dead_interval = htons (oi->dead_interval);
 1746:   hello->drouter = oi->drouter;
 1747:   hello->bdrouter = oi->bdrouter;
 1748: 
 1749:   p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
 1750: 
 1751:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
 1752:     {
 1753:       if (on->state < OSPF6_NEIGHBOR_INIT)
 1754:         continue;
 1755: 
 1756:       if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
 1757:         {
 1758:           if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
 1759:             zlog_debug ("sending Hello message: exceeds I/F MTU");
 1760:           break;
 1761:         }
 1762: 
 1763:       memcpy (p, &on->router_id, sizeof (u_int32_t));
 1764:       p += sizeof (u_int32_t);
 1765:     }
 1766: 
 1767:   oh->type = OSPF6_MESSAGE_TYPE_HELLO;
 1768:   oh->length = htons (p - sendbuf);
 1769: 
 1770:   ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
 1771:   return 0;
 1772: }
 1773: 
 1774: int
 1775: ospf6_dbdesc_send (struct thread *thread)
 1776: {
 1777:   struct ospf6_neighbor *on;
 1778:   struct ospf6_header *oh;
 1779:   struct ospf6_dbdesc *dbdesc;
 1780:   u_char *p;
 1781:   struct ospf6_lsa *lsa;
 1782:   struct in6_addr *dst;
 1783: 
 1784:   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
 1785:   on->thread_send_dbdesc = (struct thread *) NULL;
 1786: 
 1787:   if (on->state < OSPF6_NEIGHBOR_EXSTART)
 1788:     {
 1789:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
 1790:         zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
 1791: 		    on->name, ospf6_neighbor_state_str[on->state]);
 1792:       return 0;
 1793:     }
 1794: 
 1795:   /* set next thread if master */
 1796:   if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
 1797:     on->thread_send_dbdesc =
 1798:       thread_add_timer (master, ospf6_dbdesc_send, on,
 1799:                         on->ospf6_if->rxmt_interval);
 1800: 
 1801:   memset (sendbuf, 0, iobuflen);
 1802:   oh = (struct ospf6_header *) sendbuf;
 1803:   dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
 1804:                                    sizeof (struct ospf6_header));
 1805: 
 1806:   /* if this is initial one, initialize sequence number for DbDesc */
 1807:   if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) &&
 1808:       (on->dbdesc_seqnum == 0))
 1809:     {
 1810:       struct timeval tv;
 1811:       if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
 1812:         tv.tv_sec = 1;
 1813:       on->dbdesc_seqnum = tv.tv_sec;
 1814:     }
 1815: 
 1816:   dbdesc->options[0] = on->ospf6_if->area->options[0];
 1817:   dbdesc->options[1] = on->ospf6_if->area->options[1];
 1818:   dbdesc->options[2] = on->ospf6_if->area->options[2];
 1819:   dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
 1820:   dbdesc->bits = on->dbdesc_bits;
 1821:   dbdesc->seqnum = htonl (on->dbdesc_seqnum);
 1822: 
 1823:   /* if this is not initial one, set LSA headers in dbdesc */
 1824:   p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
 1825:   if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
 1826:     {
 1827:       for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
 1828:            lsa = ospf6_lsdb_next (lsa))
 1829:         {
 1830:           ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
 1831: 
 1832:           /* MTU check */
 1833:           if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
 1834:               ospf6_packet_max(on->ospf6_if))
 1835:             {
 1836:               ospf6_lsdb_lsa_unlock (lsa);
 1837:               break;
 1838:             }
 1839:           memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
 1840:           p += sizeof (struct ospf6_lsa_header);
 1841:         }
 1842:     }
 1843: 
 1844:   oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
 1845:   oh->length = htons (p - sendbuf);
 1846: 
 1847: 
 1848:   if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
 1849:     dst = &allspfrouters6;
 1850:   else
 1851:     dst = &on->linklocal_addr;
 1852: 
 1853:   ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
 1854: 
 1855:   return 0;
 1856: }
 1857: 
 1858: int
 1859: ospf6_dbdesc_send_newone (struct thread *thread)
 1860: {
 1861:   struct ospf6_neighbor *on;
 1862:   struct ospf6_lsa *lsa;
 1863:   unsigned int size = 0;
 1864: 
 1865:   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
 1866:   ospf6_lsdb_remove_all (on->dbdesc_list);
 1867: 
 1868:   /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
 1869:      so that ospf6_send_dbdesc () can send those LSAs */
 1870:   size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
 1871:   for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
 1872:        lsa = ospf6_lsdb_next (lsa))
 1873:     {
 1874:       if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
 1875:         {
 1876:           ospf6_lsdb_lsa_unlock (lsa);
 1877:           break;
 1878:         }
 1879: 
 1880:       ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
 1881:       ospf6_lsdb_remove (lsa, on->summary_list);
 1882:       size += sizeof (struct ospf6_lsa_header);
 1883:     }
 1884: 
 1885:   if (on->summary_list->count == 0)
 1886:     UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
 1887: 
 1888:   /* If slave, More bit check must be done here */
 1889:   if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
 1890:       ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
 1891:       ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
 1892:     thread_add_event (master, exchange_done, on, 0);
 1893: 
 1894:   thread_execute (master, ospf6_dbdesc_send, on, 0);
 1895:   return 0;
 1896: }
 1897: 
 1898: int
 1899: ospf6_lsreq_send (struct thread *thread)
 1900: {
 1901:   struct ospf6_neighbor *on;
 1902:   struct ospf6_header *oh;
 1903:   struct ospf6_lsreq_entry *e;
 1904:   u_char *p;
 1905:   struct ospf6_lsa *lsa, *last_req;
 1906: 
 1907:   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
 1908:   on->thread_send_lsreq = (struct thread *) NULL;
 1909: 
 1910:   /* LSReq will be sent only in ExStart or Loading */
 1911:   if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
 1912:       on->state != OSPF6_NEIGHBOR_LOADING)
 1913:     {
 1914:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
 1915:         zlog_debug ("Quit to send LSReq to neighbor %s state %s",
 1916: 		    on->name, ospf6_neighbor_state_str[on->state]);
 1917:       return 0;
 1918:     }
 1919: 
 1920:   /* schedule loading_done if request list is empty */
 1921:   if (on->request_list->count == 0)
 1922:     {
 1923:       thread_add_event (master, loading_done, on, 0);
 1924:       return 0;
 1925:     }
 1926: 
 1927:   memset (sendbuf, 0, iobuflen);
 1928:   oh = (struct ospf6_header *) sendbuf;
 1929:   last_req = NULL;
 1930: 
 1931:   /* set Request entries in lsreq */
 1932:   p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
 1933:   for (lsa = ospf6_lsdb_head (on->request_list); lsa;
 1934:        lsa = ospf6_lsdb_next (lsa))
 1935:     {
 1936:       /* MTU check */
 1937:       if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
 1938:         {
 1939:           ospf6_lsdb_lsa_unlock (lsa);
 1940:           break;
 1941:         }
 1942: 
 1943:       e = (struct ospf6_lsreq_entry *) p;
 1944:       e->type = lsa->header->type;
 1945:       e->id = lsa->header->id;
 1946:       e->adv_router = lsa->header->adv_router;
 1947:       p += sizeof (struct ospf6_lsreq_entry);
 1948:       last_req = lsa;
 1949:     }
 1950: 
 1951:   if (last_req != NULL)
 1952:     {
 1953:       if (on->last_ls_req != NULL)
 1954: 	{
 1955: 	  ospf6_lsa_unlock (on->last_ls_req);
 1956: 	}
 1957:       ospf6_lsa_lock (last_req);
 1958:       on->last_ls_req = last_req;
 1959:     }
 1960: 
 1961:   oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
 1962:   oh->length = htons (p - sendbuf);
 1963: 
 1964:   if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
 1965:     ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
 1966:               on->ospf6_if, oh);
 1967:   else
 1968:     ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
 1969: 		on->ospf6_if, oh);
 1970: 
 1971:   /* set next thread */
 1972:   if (on->request_list->count != 0)
 1973:     {
 1974:       on->thread_send_lsreq =
 1975: 	thread_add_timer (master, ospf6_lsreq_send, on,
 1976: 			  on->ospf6_if->rxmt_interval);
 1977:     }
 1978: 
 1979:   return 0;
 1980: }
 1981: 
 1982: int
 1983: ospf6_lsupdate_send_neighbor (struct thread *thread)
 1984: {
 1985:   struct ospf6_neighbor *on;
 1986:   struct ospf6_header *oh;
 1987:   struct ospf6_lsupdate *lsupdate;
 1988:   u_char *p;
 1989:   int lsa_cnt;
 1990:   struct ospf6_lsa *lsa;
 1991: 
 1992:   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
 1993:   on->thread_send_lsupdate = (struct thread *) NULL;
 1994: 
 1995:   if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
 1996:     zlog_debug ("LSUpdate to neighbor %s", on->name);
 1997: 
 1998:   if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
 1999:     {
 2000:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
 2001:         zlog_debug ("Quit to send (neighbor state %s)",
 2002: 		    ospf6_neighbor_state_str[on->state]);
 2003:       return 0;
 2004:     }
 2005: 
 2006:   memset (sendbuf, 0, iobuflen);
 2007:   oh = (struct ospf6_header *) sendbuf;
 2008:   lsupdate = (struct ospf6_lsupdate *)
 2009:     ((caddr_t) oh + sizeof (struct ospf6_header));
 2010: 
 2011:   p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
 2012:   lsa_cnt = 0;
 2013: 
 2014:   /* lsupdate_list lists those LSA which doesn't need to be
 2015:      retransmitted. remove those from the list */
 2016:   for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
 2017:        lsa = ospf6_lsdb_next (lsa))
 2018:     {
 2019:       /* MTU check */
 2020:       if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
 2021: 	   > ospf6_packet_max(on->ospf6_if))
 2022: 	{
 2023: 	  ospf6_lsdb_lsa_unlock (lsa);
 2024: 	  break;
 2025: 	}
 2026: 
 2027:       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
 2028:       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
 2029:       p += OSPF6_LSA_SIZE (lsa->header);
 2030:       lsa_cnt++;
 2031: 
 2032:       assert (lsa->lock == 2);
 2033:       ospf6_lsdb_remove (lsa, on->lsupdate_list);
 2034:     }
 2035: 
 2036:   if (lsa_cnt)
 2037:     {
 2038:       oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
 2039:       oh->length = htons (p - sendbuf);
 2040:       lsupdate->lsa_number = htonl (lsa_cnt);
 2041: 
 2042:       if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
 2043: 	  (on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
 2044: 	  (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
 2045: 	ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
 2046: 		    on->ospf6_if, oh);
 2047:       else
 2048: 	ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
 2049: 		    on->ospf6_if, oh);
 2050:     }
 2051: 
 2052:   /* The addresses used for retransmissions are different from those sent the
 2053:      first time and so we need to separate them here.
 2054:   */
 2055:   memset (sendbuf, 0, iobuflen);
 2056:   oh = (struct ospf6_header *) sendbuf;
 2057:   lsupdate = (struct ospf6_lsupdate *)
 2058:     ((caddr_t) oh + sizeof (struct ospf6_header));
 2059:   p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
 2060:   lsa_cnt = 0;
 2061: 
 2062:   for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
 2063:        lsa = ospf6_lsdb_next (lsa))
 2064:     {
 2065:       /* MTU check */
 2066:       if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
 2067: 	   > ospf6_packet_max(on->ospf6_if))
 2068: 	{
 2069: 	  ospf6_lsdb_lsa_unlock (lsa);
 2070: 	  break;
 2071: 	}
 2072: 
 2073:       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
 2074:       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
 2075:       p += OSPF6_LSA_SIZE (lsa->header);
 2076:       lsa_cnt++;
 2077:     }
 2078: 
 2079:   if (lsa_cnt)
 2080:     {
 2081:       oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
 2082:       oh->length = htons (p - sendbuf);
 2083:       lsupdate->lsa_number = htonl (lsa_cnt);
 2084: 
 2085:       if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
 2086: 	ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
 2087: 		    on->ospf6_if, oh);
 2088:       else
 2089: 	ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
 2090: 		    on->ospf6_if, oh);
 2091:     }
 2092: 
 2093:   if (on->lsupdate_list->count != 0)
 2094:     on->thread_send_lsupdate =
 2095:       thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
 2096:   else if (on->retrans_list->count != 0)
 2097:     on->thread_send_lsupdate =
 2098:       thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
 2099: 			on->ospf6_if->rxmt_interval);
 2100:   return 0;
 2101: }
 2102: 
 2103: int
 2104: ospf6_lsupdate_send_interface (struct thread *thread)
 2105: {
 2106:   struct ospf6_interface *oi;
 2107:   struct ospf6_header *oh;
 2108:   struct ospf6_lsupdate *lsupdate;
 2109:   u_char *p;
 2110:   int lsa_cnt;
 2111:   struct ospf6_lsa *lsa;
 2112: 
 2113:   oi = (struct ospf6_interface *) THREAD_ARG (thread);
 2114:   oi->thread_send_lsupdate = (struct thread *) NULL;
 2115: 
 2116:   if (oi->state <= OSPF6_INTERFACE_WAITING)
 2117:     {
 2118:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
 2119:         zlog_debug ("Quit to send LSUpdate to interface %s state %s",
 2120: 		    oi->interface->name, ospf6_interface_state_str[oi->state]);
 2121:       return 0;
 2122:     }
 2123: 
 2124:   /* if we have nothing to send, return */
 2125:   if (oi->lsupdate_list->count == 0)
 2126:     return 0;
 2127: 
 2128:   memset (sendbuf, 0, iobuflen);
 2129:   oh = (struct ospf6_header *) sendbuf;
 2130:   lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
 2131: 				       sizeof (struct ospf6_header));
 2132: 
 2133:   p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
 2134:   lsa_cnt = 0;
 2135: 
 2136:   for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
 2137:        lsa = ospf6_lsdb_next (lsa))
 2138:     {
 2139:       /* MTU check */
 2140:       if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
 2141: 	   > ospf6_packet_max(oi))
 2142: 	{
 2143: 	  ospf6_lsdb_lsa_unlock (lsa);
 2144: 	  break;
 2145: 	}
 2146: 
 2147:       ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
 2148:       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
 2149:       p += OSPF6_LSA_SIZE (lsa->header);
 2150:       lsa_cnt++;
 2151: 
 2152:       assert (lsa->lock == 2);
 2153:       ospf6_lsdb_remove (lsa, oi->lsupdate_list);
 2154:     }
 2155: 
 2156:   if (lsa_cnt)
 2157:     {
 2158:       lsupdate->lsa_number = htonl (lsa_cnt);
 2159: 
 2160:       oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
 2161:       oh->length = htons (p - sendbuf);
 2162: 
 2163:       if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
 2164: 	  (oi->state == OSPF6_INTERFACE_DR) ||
 2165: 	  (oi->state == OSPF6_INTERFACE_BDR))
 2166: 	ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
 2167:       else
 2168: 	ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
 2169: 
 2170:     }
 2171: 
 2172:   if (oi->lsupdate_list->count > 0)
 2173:     {
 2174:       oi->thread_send_lsupdate =
 2175:         thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
 2176:     }
 2177: 
 2178:   return 0;
 2179: }
 2180: 
 2181: int
 2182: ospf6_lsack_send_neighbor (struct thread *thread)
 2183: {
 2184:   struct ospf6_neighbor *on;
 2185:   struct ospf6_header *oh;
 2186:   u_char *p;
 2187:   struct ospf6_lsa *lsa;
 2188:   int lsa_cnt = 0;
 2189: 
 2190:   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
 2191:   on->thread_send_lsack = (struct thread *) NULL;
 2192: 
 2193:   if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
 2194:     {
 2195:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
 2196:         zlog_debug ("Quit to send LSAck to neighbor %s state %s",
 2197: 		    on->name, ospf6_neighbor_state_str[on->state]);
 2198:       return 0;
 2199:     }
 2200: 
 2201:   /* if we have nothing to send, return */
 2202:   if (on->lsack_list->count == 0)
 2203:     return 0;
 2204: 
 2205:   memset (sendbuf, 0, iobuflen);
 2206:   oh = (struct ospf6_header *) sendbuf;
 2207: 
 2208:   p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
 2209: 
 2210:   for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
 2211:        lsa = ospf6_lsdb_next (lsa))
 2212:     {
 2213:       /* MTU check */
 2214:       if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
 2215: 	{
 2216: 	  /* if we run out of packet size/space here,
 2217: 	     better to try again soon. */
 2218: 	  THREAD_OFF (on->thread_send_lsack);
 2219: 	  on->thread_send_lsack =
 2220: 	    thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
 2221: 
 2222: 	  ospf6_lsdb_lsa_unlock (lsa);
 2223: 	  break;
 2224: 	}
 2225: 
 2226:       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
 2227:       memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
 2228:       p += sizeof (struct ospf6_lsa_header);
 2229: 
 2230:       assert (lsa->lock == 2);
 2231:       ospf6_lsdb_remove (lsa, on->lsack_list);
 2232:       lsa_cnt++;
 2233:     }
 2234: 
 2235:   if (lsa_cnt)
 2236:     {
 2237:       oh->type = OSPF6_MESSAGE_TYPE_LSACK;
 2238:       oh->length = htons (p - sendbuf);
 2239: 
 2240:       ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
 2241: 		  on->ospf6_if, oh);
 2242:     }
 2243: 
 2244:   if (on->thread_send_lsack == NULL && on->lsack_list->count > 0)
 2245:     {
 2246:       on->thread_send_lsack =
 2247:         thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
 2248:     }
 2249: 
 2250:   return 0;
 2251: }
 2252: 
 2253: int
 2254: ospf6_lsack_send_interface (struct thread *thread)
 2255: {
 2256:   struct ospf6_interface *oi;
 2257:   struct ospf6_header *oh;
 2258:   u_char *p;
 2259:   struct ospf6_lsa *lsa;
 2260:   int lsa_cnt = 0;
 2261: 
 2262:   oi = (struct ospf6_interface *) THREAD_ARG (thread);
 2263:   oi->thread_send_lsack = (struct thread *) NULL;
 2264: 
 2265:   if (oi->state <= OSPF6_INTERFACE_WAITING)
 2266:     {
 2267:       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
 2268:         zlog_debug ("Quit to send LSAck to interface %s state %s",
 2269: 		    oi->interface->name, ospf6_interface_state_str[oi->state]);
 2270:       return 0;
 2271:     }
 2272: 
 2273:   /* if we have nothing to send, return */
 2274:   if (oi->lsack_list->count == 0)
 2275:     return 0;
 2276: 
 2277:   memset (sendbuf, 0, iobuflen);
 2278:   oh = (struct ospf6_header *) sendbuf;
 2279: 
 2280:   p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
 2281: 
 2282:   for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
 2283:        lsa = ospf6_lsdb_next (lsa))
 2284:     {
 2285:       /* MTU check */
 2286:       if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
 2287: 	{
 2288: 	  /* if we run out of packet size/space here,
 2289: 	     better to try again soon. */
 2290: 	  THREAD_OFF (oi->thread_send_lsack);
 2291: 	  oi->thread_send_lsack =
 2292: 	    thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
 2293: 
 2294: 	  ospf6_lsdb_lsa_unlock (lsa);
 2295: 	  break;
 2296: 	}
 2297: 
 2298:       ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
 2299:       memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
 2300:       p += sizeof (struct ospf6_lsa_header);
 2301: 
 2302:       assert (lsa->lock == 2);
 2303:       ospf6_lsdb_remove (lsa, oi->lsack_list);
 2304:       lsa_cnt++;
 2305:     }
 2306: 
 2307:   if (lsa_cnt)
 2308:     {
 2309:       oh->type = OSPF6_MESSAGE_TYPE_LSACK;
 2310:       oh->length = htons (p - sendbuf);
 2311: 
 2312:       if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
 2313: 	  (oi->state == OSPF6_INTERFACE_DR) ||
 2314: 	  (oi->state == OSPF6_INTERFACE_BDR))
 2315: 	ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
 2316:       else
 2317: 	ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
 2318:     }
 2319: 
 2320:   if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
 2321:     {
 2322:       oi->thread_send_lsack =
 2323:         thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
 2324:     }
 2325: 
 2326:   return 0;
 2327: }
 2328: 
 2329: 
 2330: /* Commands */
 2331: DEFUN (debug_ospf6_message,
 2332:        debug_ospf6_message_cmd,
 2333:        "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
 2334:        DEBUG_STR
 2335:        OSPF6_STR
 2336:        "Debug OSPFv3 message\n"
 2337:        "Debug Unknown message\n"
 2338:        "Debug Hello message\n"
 2339:        "Debug Database Description message\n"
 2340:        "Debug Link State Request message\n"
 2341:        "Debug Link State Update message\n"
 2342:        "Debug Link State Acknowledgement message\n"
 2343:        "Debug All message\n"
 2344:        )
 2345: {
 2346:   unsigned char level = 0;
 2347:   int type = 0;
 2348:   int i;
 2349: 
 2350:   assert (argc > 0);
 2351: 
 2352:   /* check type */
 2353:   if (! strncmp (argv[0], "u", 1))
 2354:     type = OSPF6_MESSAGE_TYPE_UNKNOWN;
 2355:   else if (! strncmp (argv[0], "h", 1))
 2356:     type = OSPF6_MESSAGE_TYPE_HELLO;
 2357:   else if (! strncmp (argv[0], "d", 1))
 2358:     type = OSPF6_MESSAGE_TYPE_DBDESC;
 2359:   else if (! strncmp (argv[0], "lsr", 3))
 2360:     type = OSPF6_MESSAGE_TYPE_LSREQ;
 2361:   else if (! strncmp (argv[0], "lsu", 3))
 2362:     type = OSPF6_MESSAGE_TYPE_LSUPDATE;
 2363:   else if (! strncmp (argv[0], "lsa", 3))
 2364:     type = OSPF6_MESSAGE_TYPE_LSACK;
 2365:   else if (! strncmp (argv[0], "a", 1))
 2366:     type = OSPF6_MESSAGE_TYPE_ALL;
 2367: 
 2368:   if (argc == 1)
 2369:     level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
 2370:   else if (! strncmp (argv[1], "s", 1))
 2371:     level = OSPF6_DEBUG_MESSAGE_SEND;
 2372:   else if (! strncmp (argv[1], "r", 1))
 2373:     level = OSPF6_DEBUG_MESSAGE_RECV;
 2374: 
 2375:   if (type == OSPF6_MESSAGE_TYPE_ALL)
 2376:     {
 2377:       for (i = 0; i < 6; i++)
 2378:         OSPF6_DEBUG_MESSAGE_ON (i, level);
 2379:     }
 2380:   else
 2381:     OSPF6_DEBUG_MESSAGE_ON (type, level);
 2382: 
 2383:   return CMD_SUCCESS;
 2384: }
 2385: 
 2386: ALIAS (debug_ospf6_message,
 2387:        debug_ospf6_message_sendrecv_cmd,
 2388:        "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
 2389:        DEBUG_STR
 2390:        OSPF6_STR
 2391:        "Debug OSPFv3 message\n"
 2392:        "Debug Unknown message\n"
 2393:        "Debug Hello message\n"
 2394:        "Debug Database Description message\n"
 2395:        "Debug Link State Request message\n"
 2396:        "Debug Link State Update message\n"
 2397:        "Debug Link State Acknowledgement message\n"
 2398:        "Debug All message\n"
 2399:        "Debug only sending message\n"
 2400:        "Debug only receiving message\n"
 2401:        )
 2402: 
 2403: 
 2404: DEFUN (no_debug_ospf6_message,
 2405:        no_debug_ospf6_message_cmd,
 2406:        "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
 2407:        NO_STR
 2408:        DEBUG_STR
 2409:        OSPF6_STR
 2410:        "Debug OSPFv3 message\n"
 2411:        "Debug Unknown message\n"
 2412:        "Debug Hello message\n"
 2413:        "Debug Database Description message\n"
 2414:        "Debug Link State Request message\n"
 2415:        "Debug Link State Update message\n"
 2416:        "Debug Link State Acknowledgement message\n"
 2417:        "Debug All message\n"
 2418:        )
 2419: {
 2420:   unsigned char level = 0;
 2421:   int type = 0;
 2422:   int i;
 2423: 
 2424:   assert (argc > 0);
 2425: 
 2426:   /* check type */
 2427:   if (! strncmp (argv[0], "u", 1))
 2428:     type = OSPF6_MESSAGE_TYPE_UNKNOWN;
 2429:   else if (! strncmp (argv[0], "h", 1))
 2430:     type = OSPF6_MESSAGE_TYPE_HELLO;
 2431:   else if (! strncmp (argv[0], "d", 1))
 2432:     type = OSPF6_MESSAGE_TYPE_DBDESC;
 2433:   else if (! strncmp (argv[0], "lsr", 3))
 2434:     type = OSPF6_MESSAGE_TYPE_LSREQ;
 2435:   else if (! strncmp (argv[0], "lsu", 3))
 2436:     type = OSPF6_MESSAGE_TYPE_LSUPDATE;
 2437:   else if (! strncmp (argv[0], "lsa", 3))
 2438:     type = OSPF6_MESSAGE_TYPE_LSACK;
 2439:   else if (! strncmp (argv[0], "a", 1))
 2440:     type = OSPF6_MESSAGE_TYPE_ALL;
 2441: 
 2442:   if (argc == 1)
 2443:     level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
 2444:   else if (! strncmp (argv[1], "s", 1))
 2445:     level = OSPF6_DEBUG_MESSAGE_SEND;
 2446:   else if (! strncmp (argv[1], "r", 1))
 2447:     level = OSPF6_DEBUG_MESSAGE_RECV;
 2448: 
 2449:   if (type == OSPF6_MESSAGE_TYPE_ALL)
 2450:     {
 2451:       for (i = 0; i < 6; i++)
 2452:         OSPF6_DEBUG_MESSAGE_OFF (i, level);
 2453:     }
 2454:   else
 2455:     OSPF6_DEBUG_MESSAGE_OFF (type, level);
 2456: 
 2457:   return CMD_SUCCESS;
 2458: }
 2459: 
 2460: ALIAS (no_debug_ospf6_message,
 2461:        no_debug_ospf6_message_sendrecv_cmd,
 2462:        "no debug ospf6 message "
 2463:        "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
 2464:        NO_STR
 2465:        DEBUG_STR
 2466:        OSPF6_STR
 2467:        "Debug OSPFv3 message\n"
 2468:        "Debug Unknown message\n"
 2469:        "Debug Hello message\n"
 2470:        "Debug Database Description message\n"
 2471:        "Debug Link State Request message\n"
 2472:        "Debug Link State Update message\n"
 2473:        "Debug Link State Acknowledgement message\n"
 2474:        "Debug All message\n"
 2475:        "Debug only sending message\n"
 2476:        "Debug only receiving message\n"
 2477:        )
 2478: 
 2479: int
 2480: config_write_ospf6_debug_message (struct vty *vty)
 2481: {
 2482:   const char *type_str[] = {"unknown", "hello", "dbdesc",
 2483:                       "lsreq", "lsupdate", "lsack"};
 2484:   unsigned char s = 0, r = 0;
 2485:   int i;
 2486: 
 2487:   for (i = 0; i < 6; i++)
 2488:     {
 2489:       if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
 2490:         s |= 1 << i;
 2491:       if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
 2492:         r |= 1 << i;
 2493:     }
 2494: 
 2495:   if (s == 0x3f && r == 0x3f)
 2496:     {
 2497:       vty_out (vty, "debug ospf6 message all%s", VNL);
 2498:       return 0;
 2499:     }
 2500: 
 2501:   if (s == 0x3f && r == 0)
 2502:     {
 2503:       vty_out (vty, "debug ospf6 message all send%s", VNL);
 2504:       return 0;
 2505:     }
 2506:   else if (s == 0 && r == 0x3f)
 2507:     {
 2508:       vty_out (vty, "debug ospf6 message all recv%s", VNL);
 2509:       return 0;
 2510:     }
 2511: 
 2512:   /* Unknown message is logged by default */
 2513:   if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
 2514:       ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 2515:     vty_out (vty, "no debug ospf6 message unknown%s", VNL);
 2516:   else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
 2517:     vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
 2518:   else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
 2519:     vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
 2520: 
 2521:   for (i = 1; i < 6; i++)
 2522:     {
 2523:       if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
 2524:           IS_OSPF6_DEBUG_MESSAGE (i, RECV))
 2525:         vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
 2526:       else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
 2527:         vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
 2528:                  VNL);
 2529:       else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
 2530:         vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
 2531:                  VNL);
 2532:     }
 2533: 
 2534:   return 0;
 2535: }
 2536: 
 2537: void
 2538: install_element_ospf6_debug_message (void)
 2539: {
 2540:   install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
 2541:   install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
 2542:   install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
 2543:   install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
 2544:   install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
 2545:   install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
 2546:   install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
 2547:   install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
 2548: }
 2549: 
 2550: 

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