Annotation of embedaddon/quagga/ospfd/ospf_packet.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * OSPF Sending and Receiving OSPF Packets.
        !             3:  * Copyright (C) 1999, 2000 Toshiaki Takada
        !             4:  *
        !             5:  * This file is part of GNU Zebra.
        !             6:  *
        !             7:  * GNU Zebra is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2, or (at your option) any
        !            10:  * later version.
        !            11:  *
        !            12:  * GNU Zebra is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            15:  * General Public License for more details.
        !            16:  *
        !            17:  * You should have received a copy of the GNU General Public License
        !            18:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
        !            19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            20:  * 02111-1307, USA.
        !            21:  */
        !            22: 
        !            23: #include <zebra.h>
        !            24: 
        !            25: #include "thread.h"
        !            26: #include "memory.h"
        !            27: #include "linklist.h"
        !            28: #include "prefix.h"
        !            29: #include "if.h"
        !            30: #include "table.h"
        !            31: #include "sockunion.h"
        !            32: #include "stream.h"
        !            33: #include "log.h"
        !            34: #include "sockopt.h"
        !            35: #include "checksum.h"
        !            36: #include "md5.h"
        !            37: 
        !            38: #include "ospfd/ospfd.h"
        !            39: #include "ospfd/ospf_network.h"
        !            40: #include "ospfd/ospf_interface.h"
        !            41: #include "ospfd/ospf_ism.h"
        !            42: #include "ospfd/ospf_asbr.h"
        !            43: #include "ospfd/ospf_lsa.h"
        !            44: #include "ospfd/ospf_lsdb.h"
        !            45: #include "ospfd/ospf_neighbor.h"
        !            46: #include "ospfd/ospf_nsm.h"
        !            47: #include "ospfd/ospf_packet.h"
        !            48: #include "ospfd/ospf_spf.h"
        !            49: #include "ospfd/ospf_flood.h"
        !            50: #include "ospfd/ospf_dump.h"
        !            51: 
        !            52: /* Packet Type String. */
        !            53: const char *ospf_packet_type_str[] =
        !            54: {
        !            55:   "unknown",
        !            56:   "Hello",
        !            57:   "Database Description",
        !            58:   "Link State Request",
        !            59:   "Link State Update",
        !            60:   "Link State Acknowledgment",
        !            61: };
        !            62: 
        !            63: /* OSPF authentication checking function */
        !            64: static int
        !            65: ospf_auth_type (struct ospf_interface *oi)
        !            66: {
        !            67:   int auth_type;
        !            68: 
        !            69:   if (OSPF_IF_PARAM (oi, auth_type) == OSPF_AUTH_NOTSET)
        !            70:     auth_type = oi->area->auth_type;
        !            71:   else
        !            72:     auth_type = OSPF_IF_PARAM (oi, auth_type);
        !            73: 
        !            74:   /* Handle case where MD5 key list is not configured aka Cisco */
        !            75:   if (auth_type == OSPF_AUTH_CRYPTOGRAPHIC &&
        !            76:       list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
        !            77:     return OSPF_AUTH_NULL;
        !            78:   
        !            79:   return auth_type;
        !            80: 
        !            81: }
        !            82: 
        !            83: struct ospf_packet *
        !            84: ospf_packet_new (size_t size)
        !            85: {
        !            86:   struct ospf_packet *new;
        !            87: 
        !            88:   new = XCALLOC (MTYPE_OSPF_PACKET, sizeof (struct ospf_packet));
        !            89:   new->s = stream_new (size);
        !            90: 
        !            91:   return new;
        !            92: }
        !            93: 
        !            94: void
        !            95: ospf_packet_free (struct ospf_packet *op)
        !            96: {
        !            97:   if (op->s)
        !            98:     stream_free (op->s);
        !            99: 
        !           100:   XFREE (MTYPE_OSPF_PACKET, op);
        !           101: 
        !           102:   op = NULL;
        !           103: }
        !           104: 
        !           105: struct ospf_fifo *
        !           106: ospf_fifo_new ()
        !           107: {
        !           108:   struct ospf_fifo *new;
        !           109: 
        !           110:   new = XCALLOC (MTYPE_OSPF_FIFO, sizeof (struct ospf_fifo));
        !           111:   return new;
        !           112: }
        !           113: 
        !           114: /* Add new packet to fifo. */
        !           115: void
        !           116: ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
        !           117: {
        !           118:   if (fifo->tail)
        !           119:     fifo->tail->next = op;
        !           120:   else
        !           121:     fifo->head = op;
        !           122: 
        !           123:   fifo->tail = op;
        !           124: 
        !           125:   fifo->count++;
        !           126: }
        !           127: 
        !           128: /* Add new packet to head of fifo. */
        !           129: static void
        !           130: ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op)
        !           131: {
        !           132:   op->next = fifo->head;
        !           133:   
        !           134:   if (fifo->tail == NULL)
        !           135:     fifo->tail = op;
        !           136:   
        !           137:   fifo->head = op;
        !           138:   
        !           139:   fifo->count++;
        !           140: }
        !           141: 
        !           142: /* Delete first packet from fifo. */
        !           143: struct ospf_packet *
        !           144: ospf_fifo_pop (struct ospf_fifo *fifo)
        !           145: {
        !           146:   struct ospf_packet *op;
        !           147: 
        !           148:   op = fifo->head;
        !           149: 
        !           150:   if (op)
        !           151:     {
        !           152:       fifo->head = op->next;
        !           153: 
        !           154:       if (fifo->head == NULL)
        !           155:        fifo->tail = NULL;
        !           156: 
        !           157:       fifo->count--;
        !           158:     }
        !           159: 
        !           160:   return op;
        !           161: }
        !           162: 
        !           163: /* Return first fifo entry. */
        !           164: struct ospf_packet *
        !           165: ospf_fifo_head (struct ospf_fifo *fifo)
        !           166: {
        !           167:   return fifo->head;
        !           168: }
        !           169: 
        !           170: /* Flush ospf packet fifo. */
        !           171: void
        !           172: ospf_fifo_flush (struct ospf_fifo *fifo)
        !           173: {
        !           174:   struct ospf_packet *op;
        !           175:   struct ospf_packet *next;
        !           176: 
        !           177:   for (op = fifo->head; op; op = next)
        !           178:     {
        !           179:       next = op->next;
        !           180:       ospf_packet_free (op);
        !           181:     }
        !           182:   fifo->head = fifo->tail = NULL;
        !           183:   fifo->count = 0;
        !           184: }
        !           185: 
        !           186: /* Free ospf packet fifo. */
        !           187: void
        !           188: ospf_fifo_free (struct ospf_fifo *fifo)
        !           189: {
        !           190:   ospf_fifo_flush (fifo);
        !           191: 
        !           192:   XFREE (MTYPE_OSPF_FIFO, fifo);
        !           193: }
        !           194: 
        !           195: void
        !           196: ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
        !           197: {
        !           198:   if (!oi->obuf)
        !           199:     {
        !           200:       zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
        !           201:               "destination %s) called with NULL obuf, ignoring "
        !           202:               "(please report this bug)!\n",
        !           203:               IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
        !           204:               ospf_packet_type_str[stream_getc_from(op->s, 1)],
        !           205:               inet_ntoa (op->dst));
        !           206:       return;
        !           207:     }
        !           208: 
        !           209:   /* Add packet to end of queue. */
        !           210:   ospf_fifo_push (oi->obuf, op);
        !           211: 
        !           212:   /* Debug of packet fifo*/
        !           213:   /* ospf_fifo_debug (oi->obuf); */
        !           214: }
        !           215: 
        !           216: static void
        !           217: ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op)
        !           218: {
        !           219:   if (!oi->obuf)
        !           220:     {
        !           221:       zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
        !           222:               "destination %s) called with NULL obuf, ignoring "
        !           223:               "(please report this bug)!\n",
        !           224:               IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
        !           225:               ospf_packet_type_str[stream_getc_from(op->s, 1)],
        !           226:               inet_ntoa (op->dst));
        !           227:       return;
        !           228:     }
        !           229: 
        !           230:   /* Add packet to head of queue. */
        !           231:   ospf_fifo_push_head (oi->obuf, op);
        !           232: 
        !           233:   /* Debug of packet fifo*/
        !           234:   /* ospf_fifo_debug (oi->obuf); */
        !           235: }
        !           236: 
        !           237: void
        !           238: ospf_packet_delete (struct ospf_interface *oi)
        !           239: {
        !           240:   struct ospf_packet *op;
        !           241:   
        !           242:   op = ospf_fifo_pop (oi->obuf);
        !           243: 
        !           244:   if (op)
        !           245:     ospf_packet_free (op);
        !           246: }
        !           247: 
        !           248: struct ospf_packet *
        !           249: ospf_packet_dup (struct ospf_packet *op)
        !           250: {
        !           251:   struct ospf_packet *new;
        !           252: 
        !           253:   if (stream_get_endp(op->s) != op->length)
        !           254:     /* XXX size_t */
        !           255:     zlog_warn ("ospf_packet_dup stream %lu ospf_packet %u size mismatch",
        !           256:               (u_long)STREAM_SIZE(op->s), op->length);
        !           257: 
        !           258:   /* Reserve space for MD5 authentication that may be added later. */
        !           259:   new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE);
        !           260:   stream_copy (new->s, op->s);
        !           261: 
        !           262:   new->dst = op->dst;
        !           263:   new->length = op->length;
        !           264: 
        !           265:   return new;
        !           266: }
        !           267: 
        !           268: /* XXX inline */
        !           269: static inline unsigned int
        !           270: ospf_packet_authspace (struct ospf_interface *oi)
        !           271: {
        !           272:   int auth = 0;
        !           273: 
        !           274:   if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC)
        !           275:     auth = OSPF_AUTH_MD5_SIZE;
        !           276: 
        !           277:   return auth;
        !           278: }
        !           279: 
        !           280: static unsigned int
        !           281: ospf_packet_max (struct ospf_interface *oi)
        !           282: {
        !           283:   int max;
        !           284: 
        !           285:   max = oi->ifp->mtu - ospf_packet_authspace(oi);
        !           286: 
        !           287:   max -= (OSPF_HEADER_SIZE + sizeof (struct ip));
        !           288: 
        !           289:   return max;
        !           290: }
        !           291: 
        !           292: 
        !           293: static int
        !           294: ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
        !           295:                        u_int16_t length)
        !           296: {
        !           297:   unsigned char *ibuf;
        !           298:   MD5_CTX ctx;
        !           299:   unsigned char digest[OSPF_AUTH_MD5_SIZE];
        !           300:   unsigned char *pdigest;
        !           301:   struct crypt_key *ck;
        !           302:   struct ospf_header *ospfh;
        !           303:   struct ospf_neighbor *nbr;
        !           304:   
        !           305: 
        !           306:   ibuf = STREAM_PNT (s);
        !           307:   ospfh = (struct ospf_header *) ibuf;
        !           308: 
        !           309:   /* Get pointer to the end of the packet. */
        !           310:   pdigest = ibuf + length;
        !           311: 
        !           312:   /* Get secret key. */
        !           313:   ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),
        !           314:                              ospfh->u.crypt.key_id);
        !           315:   if (ck == NULL)
        !           316:     {
        !           317:       zlog_warn ("interface %s: ospf_check_md5 no key %d",
        !           318:                 IF_NAME (oi), ospfh->u.crypt.key_id);
        !           319:       return 0;
        !           320:     }
        !           321: 
        !           322:   /* check crypto seqnum. */
        !           323:   nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id);
        !           324: 
        !           325:   if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(ospfh->u.crypt.crypt_seqnum))
        !           326:     {
        !           327:       zlog_warn ("interface %s: ospf_check_md5 bad sequence %d (expect %d)",
        !           328:                 IF_NAME (oi),
        !           329:                 ntohl(ospfh->u.crypt.crypt_seqnum),
        !           330:                 ntohl(nbr->crypt_seqnum));
        !           331:       return 0;
        !           332:     }
        !           333:       
        !           334:   /* Generate a digest for the ospf packet - their digest + our digest. */
        !           335:   memset(&ctx, 0, sizeof(ctx));
        !           336:   MD5Init(&ctx);
        !           337:   MD5Update(&ctx, ibuf, length);
        !           338:   MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);
        !           339:   MD5Final(digest, &ctx);
        !           340: 
        !           341:   /* compare the two */
        !           342:   if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
        !           343:     {
        !           344:       zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",
        !           345:                 IF_NAME (oi));
        !           346:       return 0;
        !           347:     }
        !           348: 
        !           349:   /* save neighbor's crypt_seqnum */
        !           350:   if (nbr)
        !           351:     nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
        !           352:   return 1;
        !           353: }
        !           354: 
        !           355: /* This function is called from ospf_write(), it will detect the
        !           356:    authentication scheme and if it is MD5, it will change the sequence
        !           357:    and update the MD5 digest. */
        !           358: static int
        !           359: ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
        !           360: {
        !           361:   struct ospf_header *ospfh;
        !           362:   unsigned char digest[OSPF_AUTH_MD5_SIZE];
        !           363:   MD5_CTX ctx;
        !           364:   void *ibuf;
        !           365:   u_int32_t t;
        !           366:   struct crypt_key *ck;
        !           367:   const u_int8_t *auth_key;
        !           368: 
        !           369:   ibuf = STREAM_DATA (op->s);
        !           370:   ospfh = (struct ospf_header *) ibuf;
        !           371: 
        !           372:   if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
        !           373:     return 0;
        !           374: 
        !           375:   /* We do this here so when we dup a packet, we don't have to
        !           376:      waste CPU rewriting other headers.
        !           377:      
        !           378:      Note that quagga_time /deliberately/ is not used here */
        !           379:   t = (time(NULL) & 0xFFFFFFFF);
        !           380:   if (t > oi->crypt_seqnum)
        !           381:     oi->crypt_seqnum = t;
        !           382:   else
        !           383:     oi->crypt_seqnum++;
        !           384:   
        !           385:   ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum); 
        !           386: 
        !           387:   /* Get MD5 Authentication key from auth_key list. */
        !           388:   if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
        !           389:     auth_key = (const u_int8_t *) "";
        !           390:   else
        !           391:     {
        !           392:       ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
        !           393:       auth_key = ck->auth_key;
        !           394:     }
        !           395: 
        !           396:   /* Generate a digest for the entire packet + our secret key. */
        !           397:   memset(&ctx, 0, sizeof(ctx));
        !           398:   MD5Init(&ctx);
        !           399:   MD5Update(&ctx, ibuf, ntohs (ospfh->length));
        !           400:   MD5Update(&ctx, auth_key, OSPF_AUTH_MD5_SIZE);
        !           401:   MD5Final(digest, &ctx);
        !           402: 
        !           403:   /* Append md5 digest to the end of the stream. */
        !           404:   stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
        !           405: 
        !           406:   /* We do *NOT* increment the OSPF header length. */
        !           407:   op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE;
        !           408: 
        !           409:   if (stream_get_endp(op->s) != op->length)
        !           410:     /* XXX size_t */
        !           411:     zlog_warn("ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u",
        !           412:              (u_long)stream_get_endp(op->s), op->length);
        !           413: 
        !           414:   return OSPF_AUTH_MD5_SIZE;
        !           415: }
        !           416: 
        !           417: 
        !           418: static int
        !           419: ospf_ls_req_timer (struct thread *thread)
        !           420: {
        !           421:   struct ospf_neighbor *nbr;
        !           422: 
        !           423:   nbr = THREAD_ARG (thread);
        !           424:   nbr->t_ls_req = NULL;
        !           425: 
        !           426:   /* Send Link State Request. */
        !           427:   if (ospf_ls_request_count (nbr))
        !           428:     ospf_ls_req_send (nbr);
        !           429: 
        !           430:   /* Set Link State Request retransmission timer. */
        !           431:   OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
        !           432: 
        !           433:   return 0;
        !           434: }
        !           435: 
        !           436: void
        !           437: ospf_ls_req_event (struct ospf_neighbor *nbr)
        !           438: {
        !           439:   if (nbr->t_ls_req)
        !           440:     {
        !           441:       thread_cancel (nbr->t_ls_req);
        !           442:       nbr->t_ls_req = NULL;
        !           443:     }
        !           444:   nbr->t_ls_req = thread_add_event (master, ospf_ls_req_timer, nbr, 0);
        !           445: }
        !           446: 
        !           447: /* Cyclic timer function.  Fist registered in ospf_nbr_new () in
        !           448:    ospf_neighbor.c  */
        !           449: int
        !           450: ospf_ls_upd_timer (struct thread *thread)
        !           451: {
        !           452:   struct ospf_neighbor *nbr;
        !           453: 
        !           454:   nbr = THREAD_ARG (thread);
        !           455:   nbr->t_ls_upd = NULL;
        !           456: 
        !           457:   /* Send Link State Update. */
        !           458:   if (ospf_ls_retransmit_count (nbr) > 0)
        !           459:     {
        !           460:       struct list *update;
        !           461:       struct ospf_lsdb *lsdb;
        !           462:       int i;
        !           463:       int retransmit_interval;
        !           464: 
        !           465:       retransmit_interval = OSPF_IF_PARAM (nbr->oi, retransmit_interval);
        !           466: 
        !           467:       lsdb = &nbr->ls_rxmt;
        !           468:       update = list_new ();
        !           469: 
        !           470:       for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
        !           471:        {
        !           472:          struct route_table *table = lsdb->type[i].db;
        !           473:          struct route_node *rn;
        !           474:          
        !           475:          for (rn = route_top (table); rn; rn = route_next (rn))
        !           476:            {
        !           477:              struct ospf_lsa *lsa;
        !           478:              
        !           479:              if ((lsa = rn->info) != NULL)
        !           480:                /* Don't retransmit an LSA if we received it within
        !           481:                  the last RxmtInterval seconds - this is to allow the
        !           482:                  neighbour a chance to acknowledge the LSA as it may
        !           483:                  have ben just received before the retransmit timer
        !           484:                  fired.  This is a small tweak to what is in the RFC,
        !           485:                  but it will cut out out a lot of retransmit traffic
        !           486:                  - MAG */
        !           487:                if (tv_cmp (tv_sub (recent_relative_time (), lsa->tv_recv), 
        !           488:                            int2tv (retransmit_interval)) >= 0)
        !           489:                  listnode_add (update, rn->info);
        !           490:            }
        !           491:        }
        !           492: 
        !           493:       if (listcount (update) > 0)
        !           494:        ospf_ls_upd_send (nbr, update, OSPF_SEND_PACKET_DIRECT);
        !           495:       list_delete (update);
        !           496:     }
        !           497: 
        !           498:   /* Set LS Update retransmission timer. */
        !           499:   OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
        !           500: 
        !           501:   return 0;
        !           502: }
        !           503: 
        !           504: int
        !           505: ospf_ls_ack_timer (struct thread *thread)
        !           506: {
        !           507:   struct ospf_interface *oi;
        !           508: 
        !           509:   oi = THREAD_ARG (thread);
        !           510:   oi->t_ls_ack = NULL;
        !           511: 
        !           512:   /* Send Link State Acknowledgment. */
        !           513:   if (listcount (oi->ls_ack) > 0)
        !           514:     ospf_ls_ack_send_delayed (oi);
        !           515: 
        !           516:   /* Set LS Ack timer. */
        !           517:   OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
        !           518: 
        !           519:   return 0;
        !           520: }
        !           521: 
        !           522: #ifdef WANT_OSPF_WRITE_FRAGMENT
        !           523: static void
        !           524: ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph, 
        !           525:                   struct msghdr *msg, unsigned int maxdatasize, 
        !           526:                   unsigned int mtu, int flags, u_char type)
        !           527: {
        !           528: #define OSPF_WRITE_FRAG_SHIFT 3
        !           529:   u_int16_t offset;
        !           530:   struct iovec *iovp;
        !           531:   int ret;
        !           532: 
        !           533:   assert ( op->length == stream_get_endp(op->s) );
        !           534:   assert (msg->msg_iovlen == 2);
        !           535: 
        !           536:   /* we can but try.
        !           537:    *
        !           538:    * SunOS, BSD and BSD derived kernels likely will clear ip_id, as
        !           539:    * well as the IP_MF flag, making this all quite pointless.
        !           540:    *
        !           541:    * However, for a system on which IP_MF is left alone, and ip_id left
        !           542:    * alone or else which sets same ip_id for each fragment this might
        !           543:    * work, eg linux.
        !           544:    *
        !           545:    * XXX-TODO: It would be much nicer to have the kernel's use their
        !           546:    * existing fragmentation support to do this for us. Bugs/RFEs need to
        !           547:    * be raised against the various kernels.
        !           548:    */
        !           549:   
        !           550:   /* set More Frag */
        !           551:   iph->ip_off |= IP_MF;
        !           552:   
        !           553:   /* ip frag offset is expressed in units of 8byte words */
        !           554:   offset = maxdatasize >> OSPF_WRITE_FRAG_SHIFT;
        !           555:   
        !           556:   iovp = &msg->msg_iov[1];
        !           557:   
        !           558:   while ( (stream_get_endp(op->s) - stream_get_getp (op->s)) 
        !           559:          > maxdatasize )
        !           560:     {
        !           561:       /* data length of this frag is to next offset value */
        !           562:       iovp->iov_len = offset << OSPF_WRITE_FRAG_SHIFT;
        !           563:       iph->ip_len = iovp->iov_len + sizeof (struct ip);
        !           564:       assert (iph->ip_len <= mtu);
        !           565: 
        !           566:       sockopt_iphdrincl_swab_htosys (iph);
        !           567: 
        !           568:       ret = sendmsg (fd, msg, flags);
        !           569:       
        !           570:       sockopt_iphdrincl_swab_systoh (iph);
        !           571:       
        !           572:       if (ret < 0)
        !           573:         zlog_warn ("*** ospf_write_frags: sendmsg failed to %s,"
        !           574:                   " id %d, off %d, len %d, mtu %u failed with %s",
        !           575:                   inet_ntoa (iph->ip_dst),
        !           576:                   iph->ip_id,
        !           577:                   iph->ip_off,
        !           578:                   iph->ip_len,
        !           579:                   mtu,
        !           580:                   safe_strerror (errno));
        !           581:       
        !           582:       if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
        !           583:         {
        !           584:           zlog_debug ("ospf_write_frags: sent id %d, off %d, len %d to %s\n",
        !           585:                      iph->ip_id, iph->ip_off, iph->ip_len,
        !           586:                      inet_ntoa (iph->ip_dst));
        !           587:           if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
        !           588:             {
        !           589:               zlog_debug ("-----------------IP Header Dump----------------------");
        !           590:               ospf_ip_header_dump (iph);
        !           591:               zlog_debug ("-----------------------------------------------------");
        !           592:             }
        !           593:         }
        !           594:       
        !           595:       iph->ip_off += offset;
        !           596:       stream_forward_getp (op->s, iovp->iov_len);
        !           597:       iovp->iov_base = STREAM_PNT (op->s); 
        !           598:     }
        !           599:     
        !           600:   /* setup for final fragment */
        !           601:   iovp->iov_len = stream_get_endp(op->s) - stream_get_getp (op->s);
        !           602:   iph->ip_len = iovp->iov_len + sizeof (struct ip);
        !           603:   iph->ip_off &= (~IP_MF);
        !           604: }
        !           605: #endif /* WANT_OSPF_WRITE_FRAGMENT */
        !           606: 
        !           607: static int
        !           608: ospf_write (struct thread *thread)
        !           609: {
        !           610:   struct ospf *ospf = THREAD_ARG (thread);
        !           611:   struct ospf_interface *oi;
        !           612:   struct ospf_packet *op;
        !           613:   struct sockaddr_in sa_dst;
        !           614:   struct ip iph;
        !           615:   struct msghdr msg;
        !           616:   struct iovec iov[2];
        !           617:   u_char type;
        !           618:   int ret;
        !           619:   int flags = 0;
        !           620:   struct listnode *node;
        !           621: #ifdef WANT_OSPF_WRITE_FRAGMENT
        !           622:   static u_int16_t ipid = 0;
        !           623: #endif /* WANT_OSPF_WRITE_FRAGMENT */
        !           624:   u_int16_t maxdatasize;
        !           625: #define OSPF_WRITE_IPHL_SHIFT 2
        !           626:   
        !           627:   ospf->t_write = NULL;
        !           628: 
        !           629:   node = listhead (ospf->oi_write_q);
        !           630:   assert (node);
        !           631:   oi = listgetdata (node);
        !           632:   assert (oi);
        !           633: 
        !           634: #ifdef WANT_OSPF_WRITE_FRAGMENT
        !           635:   /* seed ipid static with low order bits of time */
        !           636:   if (ipid == 0)
        !           637:     ipid = (time(NULL) & 0xffff);
        !           638: #endif /* WANT_OSPF_WRITE_FRAGMENT */
        !           639: 
        !           640:   /* convenience - max OSPF data per packet,
        !           641:    * and reliability - not more data, than our
        !           642:    * socket can accept
        !           643:    */
        !           644:   maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) -
        !           645:     sizeof (struct ip);
        !           646:   
        !           647:   /* Get one packet from queue. */
        !           648:   op = ospf_fifo_head (oi->obuf);
        !           649:   assert (op);
        !           650:   assert (op->length >= OSPF_HEADER_SIZE);
        !           651: 
        !           652:   if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
        !           653:       || op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
        !           654:       ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
        !           655:     
        !           656:   /* Rewrite the md5 signature & update the seq */
        !           657:   ospf_make_md5_digest (oi, op);
        !           658: 
        !           659:   /* Retrieve OSPF packet type. */
        !           660:   stream_set_getp (op->s, 1);
        !           661:   type = stream_getc (op->s);
        !           662:   
        !           663:   /* reset get pointer */
        !           664:   stream_set_getp (op->s, 0);
        !           665: 
        !           666:   memset (&iph, 0, sizeof (struct ip));
        !           667:   memset (&sa_dst, 0, sizeof (sa_dst));
        !           668:   
        !           669:   sa_dst.sin_family = AF_INET;
        !           670: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
        !           671:   sa_dst.sin_len = sizeof(sa_dst);
        !           672: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
        !           673:   sa_dst.sin_addr = op->dst;
        !           674:   sa_dst.sin_port = htons (0);
        !           675: 
        !           676:   /* Set DONTROUTE flag if dst is unicast. */
        !           677:   if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
        !           678:     if (!IN_MULTICAST (htonl (op->dst.s_addr)))
        !           679:       flags = MSG_DONTROUTE;
        !           680: 
        !           681:   iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT;
        !           682:   /* it'd be very strange for header to not be 4byte-word aligned but.. */
        !           683:   if ( sizeof (struct ip) 
        !           684:         > (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) )
        !           685:     iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */
        !           686:   
        !           687:   iph.ip_v = IPVERSION;
        !           688:   iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
        !           689:   iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
        !           690: 
        !           691: #if defined(__DragonFly__)
        !           692:   /*
        !           693:    * DragonFly's raw socket expects ip_len/ip_off in network byte order.
        !           694:    */
        !           695:   iph.ip_len = htons(iph.ip_len);
        !           696: #endif
        !           697: 
        !           698: #ifdef WANT_OSPF_WRITE_FRAGMENT
        !           699:   /* XXX-MT: not thread-safe at all..
        !           700:    * XXX: this presumes this is only programme sending OSPF packets 
        !           701:    * otherwise, no guarantee ipid will be unique
        !           702:    */
        !           703:   iph.ip_id = ++ipid;
        !           704: #endif /* WANT_OSPF_WRITE_FRAGMENT */
        !           705: 
        !           706:   iph.ip_off = 0;
        !           707:   if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !           708:     iph.ip_ttl = OSPF_VL_IP_TTL;
        !           709:   else
        !           710:     iph.ip_ttl = OSPF_IP_TTL;
        !           711:   iph.ip_p = IPPROTO_OSPFIGP;
        !           712:   iph.ip_sum = 0;
        !           713:   iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
        !           714:   iph.ip_dst.s_addr = op->dst.s_addr;
        !           715: 
        !           716:   memset (&msg, 0, sizeof (msg));
        !           717:   msg.msg_name = (caddr_t) &sa_dst;
        !           718:   msg.msg_namelen = sizeof (sa_dst); 
        !           719:   msg.msg_iov = iov;
        !           720:   msg.msg_iovlen = 2;
        !           721:   iov[0].iov_base = (char*)&iph;
        !           722:   iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
        !           723:   iov[1].iov_base = STREAM_PNT (op->s);
        !           724:   iov[1].iov_len = op->length;
        !           725:   
        !           726:   /* Sadly we can not rely on kernels to fragment packets because of either
        !           727:    * IP_HDRINCL and/or multicast destination being set.
        !           728:    */
        !           729: #ifdef WANT_OSPF_WRITE_FRAGMENT
        !           730:   if ( op->length > maxdatasize )
        !           731:     ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize, 
        !           732:                       oi->ifp->mtu, flags, type);
        !           733: #endif /* WANT_OSPF_WRITE_FRAGMENT */
        !           734: 
        !           735:   /* send final fragment (could be first) */
        !           736:   sockopt_iphdrincl_swab_htosys (&iph);
        !           737:   ret = sendmsg (ospf->fd, &msg, flags);
        !           738:   sockopt_iphdrincl_swab_systoh (&iph);
        !           739:   
        !           740:   if (ret < 0)
        !           741:     zlog_warn ("*** sendmsg in ospf_write failed to %s, "
        !           742:               "id %d, off %d, len %d, interface %s, mtu %u: %s",
        !           743:               inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
        !           744:               oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
        !           745: 
        !           746:   /* Show debug sending packet. */
        !           747:   if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
        !           748:     {
        !           749:       if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
        !           750:        {
        !           751:          zlog_debug ("-----------------------------------------------------");
        !           752:          ospf_ip_header_dump (&iph);
        !           753:          stream_set_getp (op->s, 0);
        !           754:          ospf_packet_dump (op->s);
        !           755:        }
        !           756: 
        !           757:       zlog_debug ("%s sent to [%s] via [%s].",
        !           758:                 ospf_packet_type_str[type], inet_ntoa (op->dst),
        !           759:                 IF_NAME (oi));
        !           760: 
        !           761:       if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
        !           762:        zlog_debug ("-----------------------------------------------------");
        !           763:     }
        !           764: 
        !           765:   /* Now delete packet from queue. */
        !           766:   ospf_packet_delete (oi);
        !           767: 
        !           768:   if (ospf_fifo_head (oi->obuf) == NULL)
        !           769:     {
        !           770:       oi->on_write_q = 0;
        !           771:       list_delete_node (ospf->oi_write_q, node);
        !           772:     }
        !           773:   
        !           774:   /* If packets still remain in queue, call write thread. */
        !           775:   if (!list_isempty (ospf->oi_write_q))
        !           776:     ospf->t_write =                                              
        !           777:       thread_add_write (master, ospf_write, ospf, ospf->fd);
        !           778: 
        !           779:   return 0;
        !           780: }
        !           781: 
        !           782: /* OSPF Hello message read -- RFC2328 Section 10.5. */
        !           783: static void
        !           784: ospf_hello (struct ip *iph, struct ospf_header *ospfh,
        !           785:            struct stream * s, struct ospf_interface *oi, int size)
        !           786: {
        !           787:   struct ospf_hello *hello;
        !           788:   struct ospf_neighbor *nbr;
        !           789:   int old_state;
        !           790:   struct prefix p;
        !           791: 
        !           792:   /* increment statistics. */
        !           793:   oi->hello_in++;
        !           794: 
        !           795:   hello = (struct ospf_hello *) STREAM_PNT (s);
        !           796: 
        !           797:   /* If Hello is myself, silently discard. */
        !           798:   if (IPV4_ADDR_SAME (&ospfh->router_id, &oi->ospf->router_id))
        !           799:     {
        !           800:       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
        !           801:         {
        !           802:           zlog_debug ("ospf_header[%s/%s]: selforiginated, "
        !           803:                      "dropping.",
        !           804:                      ospf_packet_type_str[ospfh->type],
        !           805:                      inet_ntoa (iph->ip_src));
        !           806:         }
        !           807:       return;
        !           808:     }
        !           809: 
        !           810:   /* get neighbor prefix. */
        !           811:   p.family = AF_INET;
        !           812:   p.prefixlen = ip_masklen (hello->network_mask);
        !           813:   p.u.prefix4 = iph->ip_src;
        !           814: 
        !           815:   /* Compare network mask. */
        !           816:   /* Checking is ignored for Point-to-Point and Virtual link. */
        !           817:   if (oi->type != OSPF_IFTYPE_POINTOPOINT 
        !           818:       && oi->type != OSPF_IFTYPE_VIRTUALLINK)
        !           819:     if (oi->address->prefixlen != p.prefixlen)
        !           820:       {
        !           821:        zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch on %s (configured prefix length is %d, but hello packet indicates %d).",
        !           822:                   inet_ntoa(ospfh->router_id), IF_NAME(oi),
        !           823:                   (int)oi->address->prefixlen, (int)p.prefixlen);
        !           824:        return;
        !           825:       }
        !           826: 
        !           827:   /* Compare Router Dead Interval. */
        !           828:   if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval))
        !           829:     {
        !           830:       zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch "
        !           831:                 "(expected %u, but received %u).",
        !           832:                 inet_ntoa(ospfh->router_id),
        !           833:                 OSPF_IF_PARAM(oi, v_wait), ntohl(hello->dead_interval));
        !           834:       return;
        !           835:     }
        !           836: 
        !           837:   /* Compare Hello Interval - ignored if fast-hellos are set. */
        !           838:   if (OSPF_IF_PARAM (oi, fast_hello) == 0)
        !           839:     {
        !           840:       if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
        !           841:         {
        !           842:           zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch "
        !           843:                     "(expected %u, but received %u).",
        !           844:                     inet_ntoa(ospfh->router_id),
        !           845:                     OSPF_IF_PARAM(oi, v_hello), ntohs(hello->hello_interval));
        !           846:           return;
        !           847:         }
        !           848:     }
        !           849:   
        !           850:   if (IS_DEBUG_OSPF_EVENT)
        !           851:     zlog_debug ("Packet %s [Hello:RECV]: Options %s",
        !           852:               inet_ntoa (ospfh->router_id),
        !           853:               ospf_options_dump (hello->options));
        !           854: 
        !           855:   /* Compare options. */
        !           856: #define REJECT_IF_TBIT_ON      1 /* XXX */
        !           857: #ifdef REJECT_IF_TBIT_ON
        !           858:   if (CHECK_FLAG (hello->options, OSPF_OPTION_T))
        !           859:     {
        !           860:       /*
        !           861:        * This router does not support non-zero TOS.
        !           862:        * Drop this Hello packet not to establish neighbor relationship.
        !           863:        */
        !           864:       zlog_warn ("Packet %s [Hello:RECV]: T-bit on, drop it.",
        !           865:                 inet_ntoa (ospfh->router_id));
        !           866:       return;
        !           867:     }
        !           868: #endif /* REJECT_IF_TBIT_ON */
        !           869: 
        !           870: #ifdef HAVE_OPAQUE_LSA
        !           871:   if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)
        !           872:       && CHECK_FLAG (hello->options, OSPF_OPTION_O))
        !           873:     {
        !           874:       /*
        !           875:        * This router does know the correct usage of O-bit
        !           876:        * the bit should be set in DD packet only.
        !           877:        */
        !           878:       zlog_warn ("Packet %s [Hello:RECV]: O-bit abuse?",
        !           879:                 inet_ntoa (ospfh->router_id));
        !           880: #ifdef STRICT_OBIT_USAGE_CHECK
        !           881:       return;                                     /* Reject this packet. */
        !           882: #else /* STRICT_OBIT_USAGE_CHECK */
        !           883:       UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */
        !           884: #endif /* STRICT_OBIT_USAGE_CHECK */
        !           885:     }
        !           886: #endif /* HAVE_OPAQUE_LSA */
        !           887: 
        !           888:   /* new for NSSA is to ensure that NP is on and E is off */
        !           889: 
        !           890:   if (oi->area->external_routing == OSPF_AREA_NSSA) 
        !           891:     {
        !           892:       if (! (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_NP)
        !           893:             && CHECK_FLAG (hello->options, OSPF_OPTION_NP)
        !           894:             && ! CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E)
        !           895:             && ! CHECK_FLAG (hello->options, OSPF_OPTION_E)))
        !           896:        {
        !           897:          zlog_warn ("NSSA-Packet-%s[Hello:RECV]: my options: %x, his options %x", inet_ntoa (ospfh->router_id), OPTIONS (oi), hello->options);
        !           898:          return;
        !           899:        }
        !           900:       if (IS_DEBUG_OSPF_NSSA)
        !           901:         zlog_debug ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
        !           902:     }
        !           903:   else    
        !           904:     /* The setting of the E-bit found in the Hello Packet's Options
        !           905:        field must match this area's ExternalRoutingCapability A
        !           906:        mismatch causes processing to stop and the packet to be
        !           907:        dropped. The setting of the rest of the bits in the Hello
        !           908:        Packet's Options field should be ignored. */
        !           909:     if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) !=
        !           910:        CHECK_FLAG (hello->options, OSPF_OPTION_E))
        !           911:       {
        !           912:        zlog_warn ("Packet %s [Hello:RECV]: my options: %x, his options %x",
        !           913:                   inet_ntoa(ospfh->router_id), OPTIONS (oi), hello->options);
        !           914:        return;
        !           915:       }
        !           916:   
        !           917:   /* get neighbour struct */
        !           918:   nbr = ospf_nbr_get (oi, ospfh, iph, &p);
        !           919: 
        !           920:   /* neighbour must be valid, ospf_nbr_get creates if none existed */
        !           921:   assert (nbr);
        !           922: 
        !           923:   old_state = nbr->state;
        !           924: 
        !           925:   /* Add event to thread. */
        !           926:   OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
        !           927: 
        !           928:   /*  RFC2328  Section 9.5.1
        !           929:       If the router is not eligible to become Designated Router,
        !           930:       (snip)   It      must also send an Hello Packet in reply to an
        !           931:       Hello Packet received from any eligible neighbor (other than
        !           932:       the      current Designated Router and Backup Designated Router).  */
        !           933:   if (oi->type == OSPF_IFTYPE_NBMA)
        !           934:     if (PRIORITY(oi) == 0 && hello->priority > 0
        !           935:        && IPV4_ADDR_CMP(&DR(oi),  &iph->ip_src)
        !           936:        && IPV4_ADDR_CMP(&BDR(oi), &iph->ip_src))
        !           937:       OSPF_NSM_TIMER_ON (nbr->t_hello_reply, ospf_hello_reply_timer,
        !           938:                         OSPF_HELLO_REPLY_DELAY);
        !           939: 
        !           940:   /* on NBMA network type, it happens to receive bidirectional Hello packet
        !           941:      without advance 1-Way Received event.
        !           942:      To avoid incorrect DR-seletion, raise 1-Way Received event.*/
        !           943:   if (oi->type == OSPF_IFTYPE_NBMA &&
        !           944:       (old_state == NSM_Down || old_state == NSM_Attempt))
        !           945:     {
        !           946:       OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
        !           947:       nbr->priority = hello->priority;
        !           948:       nbr->d_router = hello->d_router;
        !           949:       nbr->bd_router = hello->bd_router;
        !           950:       return;
        !           951:     }
        !           952: 
        !           953:   if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
        !           954:                              size - OSPF_HELLO_MIN_SIZE))
        !           955:     {
        !           956:       OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_TwoWayReceived);
        !           957:       nbr->options |= hello->options;
        !           958:     }
        !           959:   else
        !           960:     {
        !           961:       OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
        !           962:       /* Set neighbor information. */
        !           963:       nbr->priority = hello->priority;
        !           964:       nbr->d_router = hello->d_router;
        !           965:       nbr->bd_router = hello->bd_router;
        !           966:       return;
        !           967:     }
        !           968: 
        !           969:   /* If neighbor itself declares DR and no BDR exists,
        !           970:      cause event BackupSeen */
        !           971:   if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router))
        !           972:     if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting)
        !           973:       OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
        !           974: 
        !           975:   /* neighbor itself declares BDR. */
        !           976:   if (oi->state == ISM_Waiting &&
        !           977:       IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router))
        !           978:     OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
        !           979: 
        !           980:   /* had not previously. */
        !           981:   if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) &&
        !           982:        IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) ||
        !           983:       (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) &&
        !           984:        IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router)))
        !           985:     OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
        !           986: 
        !           987:   /* had not previously. */
        !           988:   if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) &&
        !           989:        IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) ||
        !           990:       (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) &&
        !           991:        IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router)))
        !           992:     OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
        !           993: 
        !           994:   /* Neighbor priority check. */
        !           995:   if (nbr->priority >= 0 && nbr->priority != hello->priority)
        !           996:     OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
        !           997: 
        !           998:   /* Set neighbor information. */
        !           999:   nbr->priority = hello->priority;
        !          1000:   nbr->d_router = hello->d_router;
        !          1001:   nbr->bd_router = hello->bd_router;
        !          1002: }
        !          1003: 
        !          1004: /* Save DD flags/options/Seqnum received. */
        !          1005: static void
        !          1006: ospf_db_desc_save_current (struct ospf_neighbor *nbr,
        !          1007:                           struct ospf_db_desc *dd)
        !          1008: {
        !          1009:   nbr->last_recv.flags = dd->flags;
        !          1010:   nbr->last_recv.options = dd->options;
        !          1011:   nbr->last_recv.dd_seqnum = ntohl (dd->dd_seqnum);
        !          1012: }
        !          1013: 
        !          1014: /* Process rest of DD packet. */
        !          1015: static void
        !          1016: ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
        !          1017:                   struct ospf_neighbor *nbr, struct ospf_db_desc *dd,
        !          1018:                   u_int16_t size)
        !          1019: {
        !          1020:   struct ospf_lsa *new, *find;
        !          1021:   struct lsa_header *lsah;
        !          1022: 
        !          1023:   stream_forward_getp (s, OSPF_DB_DESC_MIN_SIZE);
        !          1024:   for (size -= OSPF_DB_DESC_MIN_SIZE;
        !          1025:        size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE) 
        !          1026:     {
        !          1027:       lsah = (struct lsa_header *) STREAM_PNT (s);
        !          1028:       stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
        !          1029: 
        !          1030:       /* Unknown LS type. */
        !          1031:       if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
        !          1032:        {
        !          1033:          zlog_warn ("Packet [DD:RECV]: Unknown LS type %d.", lsah->type);
        !          1034:          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
        !          1035:          return;
        !          1036:        }
        !          1037: 
        !          1038: #ifdef HAVE_OPAQUE_LSA
        !          1039:       if (IS_OPAQUE_LSA (lsah->type)
        !          1040:       &&  ! CHECK_FLAG (nbr->options, OSPF_OPTION_O))
        !          1041:         {
        !          1042:           zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
        !          1043:           OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
        !          1044:           return;
        !          1045:         }
        !          1046: #endif /* HAVE_OPAQUE_LSA */
        !          1047: 
        !          1048:       switch (lsah->type)
        !          1049:         {
        !          1050:         case OSPF_AS_EXTERNAL_LSA:
        !          1051: #ifdef HAVE_OPAQUE_LSA
        !          1052:        case OSPF_OPAQUE_AS_LSA:
        !          1053: #endif /* HAVE_OPAQUE_LSA */
        !          1054:           /* Check for stub area.  Reject if AS-External from stub but
        !          1055:              allow if from NSSA. */
        !          1056:           if (oi->area->external_routing == OSPF_AREA_STUB)
        !          1057:             {
        !          1058:               zlog_warn ("Packet [DD:RECV]: LSA[Type%d:%s] from %s area.",
        !          1059:                          lsah->type, inet_ntoa (lsah->id),
        !          1060:                          (oi->area->external_routing == OSPF_AREA_STUB) ?\
        !          1061:                          "STUB" : "NSSA");
        !          1062:               OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
        !          1063:               return;
        !          1064:             }
        !          1065:           break;
        !          1066:        default:
        !          1067:          break;
        !          1068:         }
        !          1069: 
        !          1070:       /* Create LS-request object. */
        !          1071:       new = ospf_ls_request_new (lsah);
        !          1072: 
        !          1073:       /* Lookup received LSA, then add LS request list. */
        !          1074:       find = ospf_lsa_lookup_by_header (oi->area, lsah);
        !          1075:       
        !          1076:       /* ospf_lsa_more_recent is fine with NULL pointers */
        !          1077:       switch (ospf_lsa_more_recent (find, new))
        !          1078:         {
        !          1079:           case -1:
        !          1080:             /* Neighbour has a more recent LSA, we must request it */
        !          1081:             ospf_ls_request_add (nbr, new);
        !          1082:           case 0:
        !          1083:             /* If we have a copy of this LSA, it's either less recent
        !          1084:              * and we're requesting it from neighbour (the case above), or
        !          1085:              * it's as recent and we both have same copy (this case).
        !          1086:              *
        !          1087:              * In neither of these two cases is there any point in
        !          1088:              * describing our copy of the LSA to the neighbour in a
        !          1089:              * DB-Summary packet, if we're still intending to do so.
        !          1090:              *
        !          1091:              * See: draft-ogier-ospf-dbex-opt-00.txt, describing the
        !          1092:              * backward compatible optimisation to OSPF DB Exchange /
        !          1093:              * DB Description process implemented here.
        !          1094:              */
        !          1095:             if (find)
        !          1096:               ospf_lsdb_delete (&nbr->db_sum, find);
        !          1097:             ospf_lsa_discard (new);
        !          1098:             break;
        !          1099:           default:
        !          1100:             /* We have the more recent copy, nothing specific to do:
        !          1101:              * - no need to request neighbours stale copy
        !          1102:              * - must leave DB summary list copy alone
        !          1103:              */
        !          1104:             if (IS_DEBUG_OSPF_EVENT)
        !          1105:               zlog_debug ("Packet [DD:RECV]: LSA received Type %d, "
        !          1106:                          "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
        !          1107:             ospf_lsa_discard (new);
        !          1108:         }
        !          1109:     }
        !          1110: 
        !          1111:   /* Master */
        !          1112:   if (IS_SET_DD_MS (nbr->dd_flags))
        !          1113:     {
        !          1114:       nbr->dd_seqnum++;
        !          1115: 
        !          1116:       /* Both sides have no More, then we're done with Exchange */
        !          1117:       if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
        !          1118:        OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
        !          1119:       else
        !          1120:        ospf_db_desc_send (nbr);
        !          1121:     }
        !          1122:   /* Slave */
        !          1123:   else
        !          1124:     {
        !          1125:       nbr->dd_seqnum = ntohl (dd->dd_seqnum);
        !          1126: 
        !          1127:       /* Send DD packet in reply. 
        !          1128:        * 
        !          1129:        * Must be done to acknowledge the Master's DD, regardless of
        !          1130:        * whether we have more LSAs ourselves to describe.
        !          1131:        *
        !          1132:        * This function will clear the 'More' bit, if after this DD
        !          1133:        * we have no more LSAs to describe to the master..
        !          1134:        */
        !          1135:       ospf_db_desc_send (nbr);
        !          1136:       
        !          1137:       /* Slave can raise ExchangeDone now, if master is also done */
        !          1138:       if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
        !          1139:        OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
        !          1140:     }
        !          1141:   
        !          1142:   /* Save received neighbor values from DD. */
        !          1143:   ospf_db_desc_save_current (nbr, dd);
        !          1144: }
        !          1145: 
        !          1146: static int
        !          1147: ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
        !          1148: {
        !          1149:   /* Is DD duplicated? */
        !          1150:   if (dd->options == nbr->last_recv.options &&
        !          1151:       dd->flags == nbr->last_recv.flags &&
        !          1152:       dd->dd_seqnum == htonl (nbr->last_recv.dd_seqnum))
        !          1153:     return 1;
        !          1154: 
        !          1155:   return 0;
        !          1156: }
        !          1157: 
        !          1158: /* OSPF Database Description message read -- RFC2328 Section 10.6. */
        !          1159: static void
        !          1160: ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
        !          1161:              struct stream *s, struct ospf_interface *oi, u_int16_t size)
        !          1162: {
        !          1163:   struct ospf_db_desc *dd;
        !          1164:   struct ospf_neighbor *nbr;
        !          1165: 
        !          1166:   /* Increment statistics. */
        !          1167:   oi->db_desc_in++;
        !          1168: 
        !          1169:   dd = (struct ospf_db_desc *) STREAM_PNT (s);
        !          1170: 
        !          1171:   nbr = ospf_nbr_lookup (oi, iph, ospfh);
        !          1172:   if (nbr == NULL)
        !          1173:     {
        !          1174:       zlog_warn ("Packet[DD]: Unknown Neighbor %s",
        !          1175:                 inet_ntoa (ospfh->router_id));
        !          1176:       return;
        !          1177:     }
        !          1178: 
        !          1179:   /* Check MTU. */
        !          1180:   if ((OSPF_IF_PARAM (oi, mtu_ignore) == 0) && 
        !          1181:       (ntohs (dd->mtu) > oi->ifp->mtu))
        !          1182:     {
        !          1183:       zlog_warn ("Packet[DD]: Neighbor %s MTU %u is larger than [%s]'s MTU %u",
        !          1184:                 inet_ntoa (nbr->router_id), ntohs (dd->mtu),
        !          1185:                 IF_NAME (oi), oi->ifp->mtu);
        !          1186:       return;
        !          1187:     }
        !          1188: 
        !          1189:   /* 
        !          1190:    * XXX HACK by Hasso Tepper. Setting N/P bit in NSSA area DD packets is not
        !          1191:    * required. In fact at least JunOS sends DD packets with P bit clear. 
        !          1192:    * Until proper solution is developped, this hack should help.
        !          1193:    *
        !          1194:    * Update: According to the RFCs, N bit is specified /only/ for Hello
        !          1195:    * options, unfortunately its use in DD options is not specified. Hence some
        !          1196:    * implementations follow E-bit semantics and set it in DD options, and some
        !          1197:    * treat it as unspecified and hence follow the directive "default for 
        !          1198:    * options is clear", ie unset.
        !          1199:    *
        !          1200:    * Reset the flag, as ospfd follows E-bit semantics.
        !          1201:    */
        !          1202:   if ( (oi->area->external_routing == OSPF_AREA_NSSA)
        !          1203:        && (CHECK_FLAG (nbr->options, OSPF_OPTION_NP))
        !          1204:        && (!CHECK_FLAG (dd->options, OSPF_OPTION_NP)) )
        !          1205:     {
        !          1206:       if (IS_DEBUG_OSPF_EVENT) 
        !          1207:         zlog_debug ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options",
        !          1208:                     inet_ntoa (nbr->router_id) );
        !          1209:       SET_FLAG (dd->options, OSPF_OPTION_NP);
        !          1210:     }
        !          1211: 
        !          1212: #ifdef REJECT_IF_TBIT_ON
        !          1213:   if (CHECK_FLAG (dd->options, OSPF_OPTION_T))
        !          1214:     {
        !          1215:       /*
        !          1216:        * In Hello protocol, optional capability must have checked
        !          1217:        * to prevent this T-bit enabled router be my neighbor.
        !          1218:        */
        !          1219:       zlog_warn ("Packet[DD]: Neighbor %s: T-bit on?", inet_ntoa (nbr->router_id));
        !          1220:       return;
        !          1221:     }
        !          1222: #endif /* REJECT_IF_TBIT_ON */
        !          1223: 
        !          1224: #ifdef HAVE_OPAQUE_LSA
        !          1225:   if (CHECK_FLAG (dd->options, OSPF_OPTION_O)
        !          1226:       && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
        !          1227:     {
        !          1228:       /*
        !          1229:        * This node is not configured to handle O-bit, for now.
        !          1230:        * Clear it to ignore unsupported capability proposed by neighbor.
        !          1231:        */
        !          1232:       UNSET_FLAG (dd->options, OSPF_OPTION_O);
        !          1233:     }
        !          1234: #endif /* HAVE_OPAQUE_LSA */
        !          1235: 
        !          1236:   /* Add event to thread. */
        !          1237:   OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
        !          1238: 
        !          1239:   /* Process DD packet by neighbor status. */
        !          1240:   switch (nbr->state)
        !          1241:     {
        !          1242:     case NSM_Down:
        !          1243:     case NSM_Attempt:
        !          1244:     case NSM_TwoWay:
        !          1245:       zlog_warn ("Packet[DD]: Neighbor %s state is %s, packet discarded.",
        !          1246:                 inet_ntoa(nbr->router_id),
        !          1247:                 LOOKUP (ospf_nsm_state_msg, nbr->state));
        !          1248:       break;
        !          1249:     case NSM_Init:
        !          1250:       OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
        !          1251:       /* If the new state is ExStart, the processing of the current
        !          1252:         packet should then continue in this new state by falling
        !          1253:         through to case ExStart below.  */
        !          1254:       if (nbr->state != NSM_ExStart)
        !          1255:        break;
        !          1256:     case NSM_ExStart:
        !          1257:       /* Initial DBD */
        !          1258:       if ((IS_SET_DD_ALL (dd->flags) == OSPF_DD_FLAG_ALL) &&
        !          1259:          (size == OSPF_DB_DESC_MIN_SIZE))
        !          1260:        {
        !          1261:          if (IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) > 0)
        !          1262:            {
        !          1263:              /* We're Slave---obey */
        !          1264:              zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Slave).",
        !          1265:                         inet_ntoa(nbr->router_id));
        !          1266:              nbr->dd_seqnum = ntohl (dd->dd_seqnum);
        !          1267:              
        !          1268:              /* Reset I/MS */
        !          1269:              UNSET_FLAG (nbr->dd_flags, (OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I));
        !          1270:            }
        !          1271:          else
        !          1272:            {
        !          1273:              /* We're Master, ignore the initial DBD from Slave */
        !          1274:              zlog_info ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
        !          1275:                         "ignoring.", inet_ntoa(nbr->router_id));
        !          1276:              break;
        !          1277:            }
        !          1278:        }
        !          1279:       /* Ack from the Slave */
        !          1280:       else if (!IS_SET_DD_MS (dd->flags) && !IS_SET_DD_I (dd->flags) &&
        !          1281:               ntohl (dd->dd_seqnum) == nbr->dd_seqnum &&
        !          1282:               IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) < 0)
        !          1283:        {
        !          1284:          zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Master).",
        !          1285:                     inet_ntoa(nbr->router_id));
        !          1286:           /* Reset I, leaving MS */
        !          1287:           UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_I);
        !          1288:        }
        !          1289:       else
        !          1290:        {
        !          1291:          zlog_warn ("Packet[DD]: Neighbor %s Negotiation fails.",
        !          1292:                     inet_ntoa(nbr->router_id));
        !          1293:          break;
        !          1294:        }
        !          1295:       
        !          1296:       /* This is where the real Options are saved */
        !          1297:       nbr->options = dd->options;
        !          1298: 
        !          1299: #ifdef HAVE_OPAQUE_LSA
        !          1300:       if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
        !          1301:         {
        !          1302:           if (IS_DEBUG_OSPF_EVENT)
        !          1303:             zlog_debug ("Neighbor[%s] is %sOpaque-capable.",
        !          1304:                       inet_ntoa (nbr->router_id),
        !          1305:                       CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT ");
        !          1306: 
        !          1307:           if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)
        !          1308:           &&  IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
        !          1309:             {
        !          1310:               zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; "
        !          1311:                          "Opaque-LSAs cannot be reliably advertised "
        !          1312:                          "in this network.",
        !          1313:                          inet_ntoa (nbr->router_id));
        !          1314:               /* This situation is undesirable, but not a real error. */
        !          1315:             }
        !          1316:         }
        !          1317: #endif /* HAVE_OPAQUE_LSA */
        !          1318: 
        !          1319:       OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone);
        !          1320: 
        !          1321:       /* continue processing rest of packet. */
        !          1322:       ospf_db_desc_proc (s, oi, nbr, dd, size);
        !          1323:       break;
        !          1324:     case NSM_Exchange:
        !          1325:       if (ospf_db_desc_is_dup (dd, nbr))
        !          1326:        {
        !          1327:          if (IS_SET_DD_MS (nbr->dd_flags))
        !          1328:            /* Master: discard duplicated DD packet. */
        !          1329:            zlog_info ("Packet[DD] (Master): Neighbor %s packet duplicated.",
        !          1330:                       inet_ntoa (nbr->router_id));
        !          1331:          else
        !          1332:            /* Slave: cause to retransmit the last Database Description. */
        !          1333:            {
        !          1334:              zlog_info ("Packet[DD] [Slave]: Neighbor %s packet duplicated.",
        !          1335:                         inet_ntoa (nbr->router_id));
        !          1336:              ospf_db_desc_resend (nbr);
        !          1337:            }
        !          1338:          break;
        !          1339:        }
        !          1340: 
        !          1341:       /* Otherwise DD packet should be checked. */
        !          1342:       /* Check Master/Slave bit mismatch */
        !          1343:       if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags))
        !          1344:        {
        !          1345:          zlog_warn ("Packet[DD]: Neighbor %s MS-bit mismatch.",
        !          1346:                     inet_ntoa(nbr->router_id));
        !          1347:          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
        !          1348:          if (IS_DEBUG_OSPF_EVENT)
        !          1349:            zlog_debug ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
        !          1350:                        dd->flags, nbr->dd_flags);
        !          1351:          break;
        !          1352:        }
        !          1353: 
        !          1354:       /* Check initialize bit is set. */
        !          1355:       if (IS_SET_DD_I (dd->flags))
        !          1356:        {
        !          1357:          zlog_info ("Packet[DD]: Neighbor %s I-bit set.",
        !          1358:                     inet_ntoa(nbr->router_id));
        !          1359:          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
        !          1360:          break;
        !          1361:        }
        !          1362: 
        !          1363:       /* Check DD Options. */
        !          1364:       if (dd->options != nbr->options)
        !          1365:        {
        !          1366: #ifdef ORIGINAL_CODING
        !          1367:          /* Save the new options for debugging */
        !          1368:          nbr->options = dd->options;
        !          1369: #endif /* ORIGINAL_CODING */
        !          1370:          zlog_warn ("Packet[DD]: Neighbor %s options mismatch.",
        !          1371:                     inet_ntoa(nbr->router_id));
        !          1372:          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
        !          1373:          break;
        !          1374:        }
        !          1375: 
        !          1376:       /* Check DD sequence number. */
        !          1377:       if ((IS_SET_DD_MS (nbr->dd_flags) &&
        !          1378:           ntohl (dd->dd_seqnum) != nbr->dd_seqnum) ||
        !          1379:          (!IS_SET_DD_MS (nbr->dd_flags) &&
        !          1380:           ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1))
        !          1381:        {
        !          1382:          zlog_warn ("Packet[DD]: Neighbor %s sequence number mismatch.",
        !          1383:                     inet_ntoa(nbr->router_id));
        !          1384:          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
        !          1385:          break;
        !          1386:        }
        !          1387: 
        !          1388:       /* Continue processing rest of packet. */
        !          1389:       ospf_db_desc_proc (s, oi, nbr, dd, size);
        !          1390:       break;
        !          1391:     case NSM_Loading:
        !          1392:     case NSM_Full:
        !          1393:       if (ospf_db_desc_is_dup (dd, nbr))
        !          1394:        {
        !          1395:          if (IS_SET_DD_MS (nbr->dd_flags))
        !          1396:            {
        !          1397:              /* Master should discard duplicate DD packet. */
        !          1398:              zlog_info ("Packet[DD]: Neighbor %s duplicated, "
        !          1399:                         "packet discarded.",
        !          1400:                        inet_ntoa(nbr->router_id));
        !          1401:              break;
        !          1402:            }
        !          1403:          else
        !          1404:            {
        !          1405:              struct timeval t, now;
        !          1406:              quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
        !          1407:              t = tv_sub (now, nbr->last_send_ts);
        !          1408:              if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)
        !          1409:                {
        !          1410:                  /* In states Loading and Full the slave must resend
        !          1411:                     its last Database Description packet in response to
        !          1412:                     duplicate Database Description packets received
        !          1413:                     from the master.  For this reason the slave must
        !          1414:                     wait RouterDeadInterval seconds before freeing the
        !          1415:                     last Database Description packet.  Reception of a
        !          1416:                     Database Description packet from the master after
        !          1417:                     this interval will generate a SeqNumberMismatch
        !          1418:                     neighbor event. RFC2328 Section 10.8 */
        !          1419:                  ospf_db_desc_resend (nbr);
        !          1420:                  break;
        !          1421:                }
        !          1422:            }
        !          1423:        }
        !          1424: 
        !          1425:       OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
        !          1426:       break;
        !          1427:     default:
        !          1428:       zlog_warn ("Packet[DD]: Neighbor %s NSM illegal status %u.",
        !          1429:                 inet_ntoa(nbr->router_id), nbr->state);
        !          1430:       break;
        !          1431:     }
        !          1432: }
        !          1433: 
        !          1434: #define OSPF_LSA_KEY_SIZE       12 /* type(4) + id(4) + ar(4) */
        !          1435: 
        !          1436: /* OSPF Link State Request Read -- RFC2328 Section 10.7. */
        !          1437: static void
        !          1438: ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
        !          1439:             struct stream *s, struct ospf_interface *oi, u_int16_t size)
        !          1440: {
        !          1441:   struct ospf_neighbor *nbr;
        !          1442:   u_int32_t ls_type;
        !          1443:   struct in_addr ls_id;
        !          1444:   struct in_addr adv_router;
        !          1445:   struct ospf_lsa *find;
        !          1446:   struct list *ls_upd;
        !          1447:   unsigned int length;
        !          1448: 
        !          1449:   /* Increment statistics. */
        !          1450:   oi->ls_req_in++;
        !          1451: 
        !          1452:   nbr = ospf_nbr_lookup (oi, iph, ospfh);
        !          1453:   if (nbr == NULL)
        !          1454:     {
        !          1455:       zlog_warn ("Link State Request: Unknown Neighbor %s.",
        !          1456:                 inet_ntoa (ospfh->router_id));
        !          1457:       return;
        !          1458:     }
        !          1459: 
        !          1460:   /* Add event to thread. */
        !          1461:   OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
        !          1462: 
        !          1463:   /* Neighbor State should be Exchange or later. */
        !          1464:   if (nbr->state != NSM_Exchange &&
        !          1465:       nbr->state != NSM_Loading &&
        !          1466:       nbr->state != NSM_Full)
        !          1467:     {
        !          1468:       zlog_warn ("Link State Request received from %s: "
        !          1469:                 "Neighbor state is %s, packet discarded.",
        !          1470:                 inet_ntoa (ospfh->router_id),
        !          1471:                 LOOKUP (ospf_nsm_state_msg, nbr->state));
        !          1472:       return;
        !          1473:     }
        !          1474: 
        !          1475:   /* Send Link State Update for ALL requested LSAs. */
        !          1476:   ls_upd = list_new ();
        !          1477:   length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
        !          1478: 
        !          1479:   while (size >= OSPF_LSA_KEY_SIZE)
        !          1480:     {
        !          1481:       /* Get one slice of Link State Request. */
        !          1482:       ls_type = stream_getl (s);
        !          1483:       ls_id.s_addr = stream_get_ipv4 (s);
        !          1484:       adv_router.s_addr = stream_get_ipv4 (s);
        !          1485: 
        !          1486:       /* Verify LSA type. */
        !          1487:       if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA)
        !          1488:        {
        !          1489:          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
        !          1490:          list_delete (ls_upd);
        !          1491:          return;
        !          1492:        }
        !          1493: 
        !          1494:       /* Search proper LSA in LSDB. */
        !          1495:       find = ospf_lsa_lookup (oi->area, ls_type, ls_id, adv_router);
        !          1496:       if (find == NULL)
        !          1497:        {
        !          1498:          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
        !          1499:          list_delete (ls_upd);
        !          1500:          return;
        !          1501:        }
        !          1502: 
        !          1503:       /* Packet overflows MTU size, send immediately. */
        !          1504:       if (length + ntohs (find->data->length) > ospf_packet_max (oi))
        !          1505:        {
        !          1506:          if (oi->type == OSPF_IFTYPE_NBMA)
        !          1507:            ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
        !          1508:          else
        !          1509:            ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
        !          1510: 
        !          1511:          /* Only remove list contents.  Keep ls_upd. */
        !          1512:          list_delete_all_node (ls_upd);
        !          1513: 
        !          1514:          length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
        !          1515:        }
        !          1516: 
        !          1517:       /* Append LSA to update list. */
        !          1518:       listnode_add (ls_upd, find);
        !          1519:       length += ntohs (find->data->length);
        !          1520: 
        !          1521:       size -= OSPF_LSA_KEY_SIZE;
        !          1522:     }
        !          1523: 
        !          1524:   /* Send rest of Link State Update. */
        !          1525:   if (listcount (ls_upd) > 0)
        !          1526:     {
        !          1527:       if (oi->type == OSPF_IFTYPE_NBMA)
        !          1528:        ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
        !          1529:       else
        !          1530:        ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
        !          1531: 
        !          1532:       list_delete (ls_upd);
        !          1533:     }
        !          1534:   else
        !          1535:     list_free (ls_upd);
        !          1536: }
        !          1537: 
        !          1538: /* Get the list of LSAs from Link State Update packet.
        !          1539:    And process some validation -- RFC2328 Section 13. (1)-(2). */
        !          1540: static struct list *
        !          1541: ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
        !          1542:                       struct ospf_interface *oi, size_t size)
        !          1543: {
        !          1544:   u_int16_t count, sum;
        !          1545:   u_int32_t length;
        !          1546:   struct lsa_header *lsah;
        !          1547:   struct ospf_lsa *lsa;
        !          1548:   struct list *lsas;
        !          1549: 
        !          1550:   lsas = list_new ();
        !          1551: 
        !          1552:   count = stream_getl (s);
        !          1553:   size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */
        !          1554: 
        !          1555:   for (; size >= OSPF_LSA_HEADER_SIZE && count > 0;
        !          1556:        size -= length, stream_forward_getp (s, length), count--)
        !          1557:     {
        !          1558:       lsah = (struct lsa_header *) STREAM_PNT (s);
        !          1559:       length = ntohs (lsah->length);
        !          1560: 
        !          1561:       if (length > size)
        !          1562:        {
        !          1563:          zlog_warn ("Link State Update: LSA length exceeds packet size.");
        !          1564:          break;
        !          1565:        }
        !          1566: 
        !          1567:       /* Validate the LSA's LS checksum. */
        !          1568:       sum = lsah->checksum;
        !          1569:       if (sum != ospf_lsa_checksum (lsah))
        !          1570:        {
        !          1571:          zlog_warn ("Link State Update: LSA checksum error %x, %x.",
        !          1572:                     sum, lsah->checksum);
        !          1573:          continue;
        !          1574:        }
        !          1575: 
        !          1576:       /* Examine the LSA's LS type. */
        !          1577:       if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
        !          1578:        {
        !          1579:          zlog_warn ("Link State Update: Unknown LS type %d", lsah->type);
        !          1580:          continue;
        !          1581:        }
        !          1582: 
        !          1583:       /*
        !          1584:        * What if the received LSA's age is greater than MaxAge?
        !          1585:        * Treat it as a MaxAge case -- endo.
        !          1586:        */
        !          1587:       if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE)
        !          1588:         lsah->ls_age = htons (OSPF_LSA_MAXAGE);
        !          1589: 
        !          1590: #ifdef HAVE_OPAQUE_LSA
        !          1591:       if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
        !          1592:         {
        !          1593: #ifdef STRICT_OBIT_USAGE_CHECK
        !          1594:          if ((IS_OPAQUE_LSA(lsah->type) &&
        !          1595:                ! CHECK_FLAG (lsah->options, OSPF_OPTION_O))
        !          1596:          ||  (! IS_OPAQUE_LSA(lsah->type) &&
        !          1597:                CHECK_FLAG (lsah->options, OSPF_OPTION_O)))
        !          1598:             {
        !          1599:               /*
        !          1600:                * This neighbor must know the exact usage of O-bit;
        !          1601:                * the bit will be set in Type-9,10,11 LSAs only.
        !          1602:                */
        !          1603:               zlog_warn ("LSA[Type%d:%s]: O-bit abuse?", lsah->type, inet_ntoa (lsah->id));
        !          1604:               continue;
        !          1605:             }
        !          1606: #endif /* STRICT_OBIT_USAGE_CHECK */
        !          1607: 
        !          1608:           /* Do not take in AS External Opaque-LSAs if we are a stub. */
        !          1609:           if (lsah->type == OSPF_OPAQUE_AS_LSA
        !          1610:              && nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) 
        !          1611:             {
        !          1612:               if (IS_DEBUG_OSPF_EVENT)
        !          1613:                 zlog_debug ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));
        !          1614:               continue;
        !          1615:             }
        !          1616:         }
        !          1617:       else if (IS_OPAQUE_LSA(lsah->type))
        !          1618:         {
        !          1619:           zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
        !          1620:           continue;
        !          1621:         }
        !          1622: #endif /* HAVE_OPAQUE_LSA */
        !          1623: 
        !          1624:       /* Create OSPF LSA instance. */
        !          1625:       lsa = ospf_lsa_new ();
        !          1626: 
        !          1627:       /* We may wish to put some error checking if type NSSA comes in
        !          1628:          and area not in NSSA mode */
        !          1629:       switch (lsah->type)
        !          1630:         {
        !          1631:         case OSPF_AS_EXTERNAL_LSA:
        !          1632: #ifdef HAVE_OPAQUE_LSA
        !          1633:         case OSPF_OPAQUE_AS_LSA:
        !          1634:           lsa->area = NULL;
        !          1635:           break;
        !          1636:         case OSPF_OPAQUE_LINK_LSA:
        !          1637:           lsa->oi = oi; /* Remember incoming interface for flooding control. */
        !          1638:           /* Fallthrough */
        !          1639: #endif /* HAVE_OPAQUE_LSA */
        !          1640:         default:
        !          1641:           lsa->area = oi->area;
        !          1642:           break;
        !          1643:         }
        !          1644: 
        !          1645:       lsa->data = ospf_lsa_data_new (length);
        !          1646:       memcpy (lsa->data, lsah, length);
        !          1647: 
        !          1648:       if (IS_DEBUG_OSPF_EVENT)
        !          1649:        zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update",
        !          1650:                  lsa->data->type, inet_ntoa (lsa->data->id), lsa);
        !          1651:       listnode_add (lsas, lsa);
        !          1652:     }
        !          1653: 
        !          1654:   return lsas;
        !          1655: }
        !          1656: 
        !          1657: /* Cleanup Update list. */
        !          1658: static void
        !          1659: ospf_upd_list_clean (struct list *lsas)
        !          1660: {
        !          1661:   struct listnode *node, *nnode;
        !          1662:   struct ospf_lsa *lsa;
        !          1663: 
        !          1664:   for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
        !          1665:     ospf_lsa_discard (lsa);
        !          1666: 
        !          1667:   list_delete (lsas);
        !          1668: }
        !          1669: 
        !          1670: /* OSPF Link State Update message read -- RFC2328 Section 13. */
        !          1671: static void
        !          1672: ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
        !          1673:             struct stream *s, struct ospf_interface *oi, u_int16_t size)
        !          1674: {
        !          1675:   struct ospf_neighbor *nbr;
        !          1676:   struct list *lsas;
        !          1677:   struct listnode *node, *nnode;
        !          1678:   struct ospf_lsa *lsa = NULL;
        !          1679:   /* unsigned long ls_req_found = 0; */
        !          1680: 
        !          1681:   /* Dis-assemble the stream, update each entry, re-encapsulate for flooding */
        !          1682: 
        !          1683:   /* Increment statistics. */
        !          1684:   oi->ls_upd_in++;
        !          1685: 
        !          1686:   /* Check neighbor. */
        !          1687:   nbr = ospf_nbr_lookup (oi, iph, ospfh);
        !          1688:   if (nbr == NULL)
        !          1689:     {
        !          1690:       zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s",
        !          1691:                 inet_ntoa (ospfh->router_id), IF_NAME (oi));
        !          1692:       return;
        !          1693:     }
        !          1694: 
        !          1695:   /* Add event to thread. */
        !          1696:   OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
        !          1697: 
        !          1698:   /* Check neighbor state. */
        !          1699:   if (nbr->state < NSM_Exchange)
        !          1700:     {
        !          1701:       zlog_warn ("Link State Update: "
        !          1702:                 "Neighbor[%s] state %s is less than Exchange",
        !          1703:                 inet_ntoa (ospfh->router_id),
        !          1704:                 LOOKUP(ospf_nsm_state_msg, nbr->state));
        !          1705:       return;
        !          1706:     }
        !          1707: 
        !          1708:   /* Get list of LSAs from Link State Update packet. - Also perorms Stages 
        !          1709:    * 1 (validate LSA checksum) and 2 (check for LSA consistent type) 
        !          1710:    * of section 13. 
        !          1711:    */
        !          1712:   lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);
        !          1713: 
        !          1714: #ifdef HAVE_OPAQUE_LSA
        !          1715:   /*
        !          1716:    * If self-originated Opaque-LSAs that have flooded before restart
        !          1717:    * are contained in the received LSUpd message, corresponding LSReq
        !          1718:    * messages to be sent may have to be modified.
        !          1719:    * To eliminate possible race conditions such that flushing and normal
        !          1720:    * updating for the same LSA would take place alternately, this trick
        !          1721:    * must be done before entering to the loop below.
        !          1722:    */
        !          1723:    /* XXX: Why is this Opaque specific? Either our core code is deficient
        !          1724:     * and this should be fixed generally, or Opaque is inventing strawman
        !          1725:     * problems */
        !          1726:    ospf_opaque_adjust_lsreq (nbr, lsas);
        !          1727: #endif /* HAVE_OPAQUE_LSA */
        !          1728: 
        !          1729: #define DISCARD_LSA(L,N) {\
        !          1730:         if (IS_DEBUG_OSPF_EVENT) \
        !          1731:           zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \
        !          1732:         ospf_lsa_discard (L); \
        !          1733:        continue; }
        !          1734: 
        !          1735:   /* Process each LSA received in the one packet. */
        !          1736:   for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
        !          1737:     {
        !          1738:       struct ospf_lsa *ls_ret, *current;
        !          1739:       int ret = 1;
        !          1740: 
        !          1741:       if (IS_DEBUG_OSPF_NSSA)
        !          1742:        {
        !          1743:          char buf1[INET_ADDRSTRLEN];
        !          1744:          char buf2[INET_ADDRSTRLEN];
        !          1745:          char buf3[INET_ADDRSTRLEN];
        !          1746: 
        !          1747:          zlog_debug("LSA Type-%d from %s, ID: %s, ADV: %s",
        !          1748:                  lsa->data->type,
        !          1749:                  inet_ntop (AF_INET, &ospfh->router_id,
        !          1750:                             buf1, INET_ADDRSTRLEN),
        !          1751:                  inet_ntop (AF_INET, &lsa->data->id,
        !          1752:                             buf2, INET_ADDRSTRLEN),
        !          1753:                  inet_ntop (AF_INET, &lsa->data->adv_router,
        !          1754:                             buf3, INET_ADDRSTRLEN));
        !          1755:        }
        !          1756: 
        !          1757:       listnode_delete (lsas, lsa); /* We don't need it in list anymore */
        !          1758: 
        !          1759:       /* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */
        !          1760: 
        !          1761:       /* LSA Type  - Done above by ospf_ls_upd_list_lsa() */
        !          1762:    
        !          1763:       /* Do not take in AS External LSAs if we are a stub or NSSA. */
        !          1764: 
        !          1765:       /* Do not take in AS NSSA if this neighbor and we are not NSSA */
        !          1766: 
        !          1767:       /* Do take in Type-7's if we are an NSSA  */ 
        !          1768:  
        !          1769:       /* If we are also an ABR, later translate them to a Type-5 packet */
        !          1770:  
        !          1771:       /* Later, an NSSA Re-fresh can Re-fresh Type-7's and an ABR will
        !          1772:         translate them to a separate Type-5 packet.  */
        !          1773: 
        !          1774:       if (lsa->data->type == OSPF_AS_EXTERNAL_LSA)
        !          1775:         /* Reject from STUB or NSSA */
        !          1776:         if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) 
        !          1777:          {
        !          1778:            if (IS_DEBUG_OSPF_NSSA)
        !          1779:              zlog_debug("Incoming External LSA Discarded: We are NSSA/STUB Area");
        !          1780:            DISCARD_LSA (lsa, 1);
        !          1781:          }
        !          1782: 
        !          1783:       if (lsa->data->type == OSPF_AS_NSSA_LSA)
        !          1784:        if (nbr->oi->area->external_routing != OSPF_AREA_NSSA)
        !          1785:          {
        !          1786:            if (IS_DEBUG_OSPF_NSSA)
        !          1787:              zlog_debug("Incoming NSSA LSA Discarded:  Not NSSA Area");
        !          1788:            DISCARD_LSA (lsa,2);
        !          1789:          }
        !          1790: 
        !          1791:       /* Find the LSA in the current database. */
        !          1792: 
        !          1793:       current = ospf_lsa_lookup_by_header (oi->area, lsa->data);
        !          1794: 
        !          1795:       /* If the LSA's LS age is equal to MaxAge, and there is currently
        !          1796:         no instance of the LSA in the router's link state database,
        !          1797:         and none of router's neighbors are in states Exchange or Loading,
        !          1798:         then take the following actions. */
        !          1799: 
        !          1800:       if (IS_LSA_MAXAGE (lsa) && !current &&
        !          1801:          (ospf_nbr_count (oi, NSM_Exchange) +
        !          1802:           ospf_nbr_count (oi, NSM_Loading)) == 0)
        !          1803:        {
        !          1804:          /* Response Link State Acknowledgment. */
        !          1805:          ospf_ls_ack_send (nbr, lsa);
        !          1806: 
        !          1807:          /* Discard LSA. */      
        !          1808:          zlog_info ("Link State Update[%s]: LS age is equal to MaxAge.",
        !          1809:                     dump_lsa_key(lsa));
        !          1810:           DISCARD_LSA (lsa, 3);
        !          1811:        }
        !          1812: 
        !          1813: #ifdef HAVE_OPAQUE_LSA
        !          1814:       if (IS_OPAQUE_LSA (lsa->data->type)
        !          1815:       &&  IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id))
        !          1816:         {
        !          1817:           /*
        !          1818:            * Even if initial flushing seems to be completed, there might
        !          1819:            * be a case that self-originated LSA with MaxAge still remain
        !          1820:            * in the routing domain.
        !          1821:            * Just send an LSAck message to cease retransmission.
        !          1822:            */
        !          1823:           if (IS_LSA_MAXAGE (lsa))
        !          1824:             {
        !          1825:               zlog_warn ("LSA[%s]: Boomerang effect?", dump_lsa_key (lsa));
        !          1826:               ospf_ls_ack_send (nbr, lsa);
        !          1827:               ospf_lsa_discard (lsa);
        !          1828: 
        !          1829:               if (current != NULL && ! IS_LSA_MAXAGE (current))
        !          1830:                 ospf_opaque_lsa_refresh_schedule (current);
        !          1831:               continue;
        !          1832:             }
        !          1833: 
        !          1834:           /*
        !          1835:            * If an instance of self-originated Opaque-LSA is not found
        !          1836:            * in the LSDB, there are some possible cases here.
        !          1837:            *
        !          1838:            * 1) This node lost opaque-capability after restart.
        !          1839:            * 2) Else, a part of opaque-type is no more supported.
        !          1840:            * 3) Else, a part of opaque-id is no more supported.
        !          1841:            *
        !          1842:            * Anyway, it is still this node's responsibility to flush it.
        !          1843:            * Otherwise, the LSA instance remains in the routing domain
        !          1844:            * until its age reaches to MaxAge.
        !          1845:            */
        !          1846:           /* XXX: We should deal with this for *ALL* LSAs, not just opaque */
        !          1847:           if (current == NULL)
        !          1848:             {
        !          1849:               if (IS_DEBUG_OSPF_EVENT)
        !          1850:                 zlog_debug ("LSA[%s]: Previously originated Opaque-LSA,"
        !          1851:                             "not found in the LSDB.", dump_lsa_key (lsa));
        !          1852: 
        !          1853:               SET_FLAG (lsa->flags, OSPF_LSA_SELF);
        !          1854:               
        !          1855:               ospf_opaque_self_originated_lsa_received (nbr, lsa);
        !          1856:               ospf_ls_ack_send (nbr, lsa);
        !          1857:               
        !          1858:               continue;
        !          1859:             }
        !          1860:         }
        !          1861: #endif /* HAVE_OPAQUE_LSA */
        !          1862: 
        !          1863:       /* It might be happen that received LSA is self-originated network LSA, but
        !          1864:        * router ID is cahnged. So, we should check if LSA is a network-LSA whose
        !          1865:        * Link State ID is one of the router's own IP interface addresses but whose
        !          1866:        * Advertising Router is not equal to the router's own Router ID
        !          1867:        * According to RFC 2328 12.4.2 and 13.4 this LSA should be flushed.
        !          1868:        */
        !          1869: 
        !          1870:       if(lsa->data->type == OSPF_NETWORK_LSA)
        !          1871:       {
        !          1872:         struct listnode *oinode, *oinnode;
        !          1873:         struct ospf_interface *out_if;
        !          1874:         int Flag = 0;
        !          1875: 
        !          1876:         for (ALL_LIST_ELEMENTS (oi->ospf->oiflist, oinode, oinnode, out_if))
        !          1877:         {
        !          1878:           if(out_if == NULL)
        !          1879:             break;
        !          1880: 
        !          1881:           if((IPV4_ADDR_SAME(&out_if->address->u.prefix4, &lsa->data->id)) &&
        !          1882:               (!(IPV4_ADDR_SAME(&oi->ospf->router_id, &lsa->data->adv_router))))
        !          1883:           {
        !          1884:             if(out_if->network_lsa_self)
        !          1885:             {
        !          1886:               ospf_lsa_flush_area(lsa,out_if->area);
        !          1887:               if(IS_DEBUG_OSPF_EVENT)
        !          1888:                 zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d",
        !          1889:                             lsa, (int) lsa->data->type);
        !          1890:               ospf_lsa_discard (lsa);
        !          1891:               Flag = 1;
        !          1892:             }
        !          1893:             break;
        !          1894:           }
        !          1895:         }
        !          1896:         if(Flag)
        !          1897:           continue;
        !          1898:       }
        !          1899: 
        !          1900:       /* (5) Find the instance of this LSA that is currently contained
        !          1901:         in the router's link state database.  If there is no
        !          1902:         database copy, or the received LSA is more recent than
        !          1903:         the database copy the following steps must be performed. */
        !          1904: 
        !          1905:       if (current == NULL ||
        !          1906:          (ret = ospf_lsa_more_recent (current, lsa)) < 0)
        !          1907:        {
        !          1908:          /* Actual flooding procedure. */
        !          1909:          if (ospf_flood (oi->ospf, nbr, current, lsa) < 0)  /* Trap NSSA later. */
        !          1910:            DISCARD_LSA (lsa, 4);
        !          1911:          continue;
        !          1912:        }
        !          1913: 
        !          1914:       /* (6) Else, If there is an instance of the LSA on the sending
        !          1915:         neighbor's Link state request list, an error has occurred in
        !          1916:         the Database Exchange process.  In this case, restart the
        !          1917:         Database Exchange process by generating the neighbor event
        !          1918:         BadLSReq for the sending neighbor and stop processing the
        !          1919:         Link State Update packet. */
        !          1920: 
        !          1921:       if (ospf_ls_request_lookup (nbr, lsa))
        !          1922:        {
        !          1923:          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
        !          1924:          zlog_warn("LSA[%s] instance exists on Link state request list",
        !          1925:                    dump_lsa_key(lsa));
        !          1926: 
        !          1927:          /* Clean list of LSAs. */
        !          1928:           ospf_upd_list_clean (lsas);
        !          1929:          /* this lsa is not on lsas list already. */
        !          1930:          ospf_lsa_discard (lsa);
        !          1931:          return;
        !          1932:        }
        !          1933: 
        !          1934:       /* If the received LSA is the same instance as the database copy
        !          1935:         (i.e., neither one is more recent) the following two steps
        !          1936:         should be performed: */
        !          1937: 
        !          1938:       if (ret == 0)
        !          1939:        {
        !          1940:          /* If the LSA is listed in the Link state retransmission list
        !          1941:             for the receiving adjacency, the router itself is expecting
        !          1942:             an acknowledgment for this LSA.  The router should treat the
        !          1943:             received LSA as an acknowledgment by removing the LSA from
        !          1944:             the Link state retransmission list.  This is termed an
        !          1945:             "implied acknowledgment". */
        !          1946: 
        !          1947:          ls_ret = ospf_ls_retransmit_lookup (nbr, lsa);
        !          1948: 
        !          1949:          if (ls_ret != NULL)
        !          1950:            {
        !          1951:              ospf_ls_retransmit_delete (nbr, ls_ret);
        !          1952: 
        !          1953:              /* Delayed acknowledgment sent if advertisement received
        !          1954:                 from Designated Router, otherwise do nothing. */
        !          1955:              if (oi->state == ISM_Backup)
        !          1956:                if (NBR_IS_DR (nbr))
        !          1957:                  listnode_add (oi->ls_ack, ospf_lsa_lock (lsa));
        !          1958: 
        !          1959:               DISCARD_LSA (lsa, 5);
        !          1960:            }
        !          1961:          else
        !          1962:            /* Acknowledge the receipt of the LSA by sending a
        !          1963:               Link State Acknowledgment packet back out the receiving
        !          1964:               interface. */
        !          1965:            {
        !          1966:              ospf_ls_ack_send (nbr, lsa);
        !          1967:              DISCARD_LSA (lsa, 6);
        !          1968:            }
        !          1969:        }
        !          1970: 
        !          1971:       /* The database copy is more recent.  If the database copy
        !          1972:         has LS age equal to MaxAge and LS sequence number equal to
        !          1973:         MaxSequenceNumber, simply discard the received LSA without
        !          1974:         acknowledging it. (In this case, the LSA's LS sequence number is
        !          1975:         wrapping, and the MaxSequenceNumber LSA must be completely
        !          1976:         flushed before any new LSA instance can be introduced). */
        !          1977: 
        !          1978:       else if (ret > 0)  /* Database copy is more recent */
        !          1979:        { 
        !          1980:          if (IS_LSA_MAXAGE (current) &&
        !          1981:              current->data->ls_seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))
        !          1982:            {
        !          1983:              DISCARD_LSA (lsa, 7);
        !          1984:            }
        !          1985:          /* Otherwise, as long as the database copy has not been sent in a
        !          1986:             Link State Update within the last MinLSArrival seconds, send the
        !          1987:             database copy back to the sending neighbor, encapsulated within
        !          1988:             a Link State Update Packet. The Link State Update Packet should
        !          1989:             be sent directly to the neighbor. In so doing, do not put the
        !          1990:             database copy of the LSA on the neighbor's link state
        !          1991:             retransmission list, and do not acknowledge the received (less
        !          1992:             recent) LSA instance. */
        !          1993:          else
        !          1994:            {
        !          1995:              struct timeval now;
        !          1996:              
        !          1997:              quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
        !          1998:              
        !          1999:              if (tv_cmp (tv_sub (now, current->tv_orig), 
        !          2000:                          int2tv (OSPF_MIN_LS_ARRIVAL)) >= 0)
        !          2001:                /* Trap NSSA type later.*/
        !          2002:                ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
        !          2003:              DISCARD_LSA (lsa, 8);
        !          2004:            }
        !          2005:        }
        !          2006:     }
        !          2007: #undef DISCARD_LSA
        !          2008: 
        !          2009:   assert (listcount (lsas) == 0);
        !          2010:   list_delete (lsas);
        !          2011: }
        !          2012: 
        !          2013: /* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
        !          2014: static void
        !          2015: ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
        !          2016:             struct stream *s, struct ospf_interface *oi, u_int16_t size)
        !          2017: {
        !          2018:   struct ospf_neighbor *nbr;
        !          2019:   
        !          2020:   /* increment statistics. */
        !          2021:   oi->ls_ack_in++;
        !          2022: 
        !          2023:   nbr = ospf_nbr_lookup (oi, iph, ospfh);
        !          2024:   if (nbr == NULL)
        !          2025:     {
        !          2026:       zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.",
        !          2027:                 inet_ntoa (ospfh->router_id));
        !          2028:       return;
        !          2029:     }
        !          2030: 
        !          2031:   /* Add event to thread. */
        !          2032:   OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
        !          2033: 
        !          2034:   if (nbr->state < NSM_Exchange)
        !          2035:     {
        !          2036:       zlog_warn ("Link State Acknowledgment: "
        !          2037:                 "Neighbor[%s] state %s is less than Exchange",
        !          2038:                 inet_ntoa (ospfh->router_id),
        !          2039:                 LOOKUP(ospf_nsm_state_msg, nbr->state));
        !          2040:       return;
        !          2041:     }
        !          2042:   
        !          2043:   while (size >= OSPF_LSA_HEADER_SIZE)
        !          2044:     {
        !          2045:       struct ospf_lsa *lsa, *lsr;
        !          2046: 
        !          2047:       lsa = ospf_lsa_new ();
        !          2048:       lsa->data = (struct lsa_header *) STREAM_PNT (s);
        !          2049: 
        !          2050:       /* lsah = (struct lsa_header *) STREAM_PNT (s); */
        !          2051:       size -= OSPF_LSA_HEADER_SIZE;
        !          2052:       stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
        !          2053: 
        !          2054:       if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)
        !          2055:        {
        !          2056:          lsa->data = NULL;
        !          2057:          ospf_lsa_discard (lsa);
        !          2058:          continue;
        !          2059:        }
        !          2060: 
        !          2061:       lsr = ospf_ls_retransmit_lookup (nbr, lsa);
        !          2062: 
        !          2063:       if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
        !          2064:         {
        !          2065: #ifdef HAVE_OPAQUE_LSA
        !          2066:           if (IS_OPAQUE_LSA (lsr->data->type))
        !          2067:             ospf_opaque_ls_ack_received (nbr, lsr);
        !          2068: #endif /* HAVE_OPAQUE_LSA */
        !          2069: 
        !          2070:           ospf_ls_retransmit_delete (nbr, lsr);
        !          2071:         }
        !          2072: 
        !          2073:       lsa->data = NULL;
        !          2074:       ospf_lsa_discard (lsa);
        !          2075:     }
        !          2076: 
        !          2077:   return;
        !          2078: }
        !          2079: 
        !          2080: static struct stream *
        !          2081: ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
        !          2082: {
        !          2083:   int ret;
        !          2084:   struct ip *iph;
        !          2085:   u_int16_t ip_len;
        !          2086:   unsigned int ifindex = 0;
        !          2087:   struct iovec iov;
        !          2088:   /* Header and data both require alignment. */
        !          2089:   char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
        !          2090:   struct msghdr msgh;
        !          2091: 
        !          2092:   memset (&msgh, 0, sizeof (struct msghdr));
        !          2093:   msgh.msg_iov = &iov;
        !          2094:   msgh.msg_iovlen = 1;
        !          2095:   msgh.msg_control = (caddr_t) buff;
        !          2096:   msgh.msg_controllen = sizeof (buff);
        !          2097:   
        !          2098:   ret = stream_recvmsg (ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE+1);
        !          2099:   if (ret < 0)
        !          2100:     {
        !          2101:       zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
        !          2102:       return NULL;
        !          2103:     }
        !          2104:   if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */
        !          2105:     {
        !          2106:       zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
        !          2107:                "(ip header size is %u)",
        !          2108:                ret, (u_int)sizeof(iph));
        !          2109:       return NULL;
        !          2110:     }
        !          2111:   
        !          2112:   /* Note that there should not be alignment problems with this assignment
        !          2113:      because this is at the beginning of the stream data buffer. */
        !          2114:   iph = (struct ip *) STREAM_DATA(ibuf);
        !          2115:   sockopt_iphdrincl_swab_systoh (iph);
        !          2116:   
        !          2117:   ip_len = iph->ip_len;
        !          2118:   
        !          2119: #if !defined(GNU_LINUX) && (OpenBSD < 200311)
        !          2120:   /*
        !          2121:    * Kernel network code touches incoming IP header parameters,
        !          2122:    * before protocol specific processing.
        !          2123:    *
        !          2124:    *   1) Convert byteorder to host representation.
        !          2125:    *      --> ip_len, ip_id, ip_off
        !          2126:    *
        !          2127:    *   2) Adjust ip_len to strip IP header size!
        !          2128:    *      --> If user process receives entire IP packet via RAW
        !          2129:    *          socket, it must consider adding IP header size to
        !          2130:    *          the "ip_len" field of "ip" structure.
        !          2131:    *
        !          2132:    * For more details, see <netinet/ip_input.c>.
        !          2133:    */
        !          2134:   ip_len = ip_len + (iph->ip_hl << 2);
        !          2135: #endif
        !          2136:   
        !          2137: #if defined(__DragonFly__)
        !          2138:   /*
        !          2139:    * in DragonFly's raw socket, ip_len/ip_off are read 
        !          2140:    * in network byte order.
        !          2141:    * As OpenBSD < 200311 adjust ip_len to strip IP header size!
        !          2142:    */
        !          2143:   ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2);
        !          2144: #endif
        !          2145: 
        !          2146:   ifindex = getsockopt_ifindex (AF_INET, &msgh);
        !          2147:   
        !          2148:   *ifp = if_lookup_by_index (ifindex);
        !          2149: 
        !          2150:   if (ret != ip_len)
        !          2151:     {
        !          2152:       zlog_warn ("ospf_recv_packet read length mismatch: ip_len is %d, "
        !          2153:                         "but recvmsg returned %d", ip_len, ret);
        !          2154:       return NULL;
        !          2155:     }
        !          2156:   
        !          2157:   return ibuf;
        !          2158: }
        !          2159: 
        !          2160: static struct ospf_interface *
        !          2161: ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp, 
        !          2162:                          struct ip *iph, struct ospf_header *ospfh)
        !          2163: {
        !          2164:   struct ospf_interface *rcv_oi;
        !          2165:   struct ospf_vl_data *vl_data;
        !          2166:   struct ospf_area *vl_area;
        !          2167:   struct listnode *node;
        !          2168: 
        !          2169:   if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) ||
        !          2170:       !OSPF_IS_AREA_BACKBONE (ospfh))
        !          2171:     return NULL;
        !          2172: 
        !          2173:   /* look for local OSPF interface matching the destination
        !          2174:    * to determine Area ID. We presume therefore the destination address
        !          2175:    * is unique, or at least (for "unnumbered" links), not used in other 
        !          2176:    * areas
        !          2177:    */
        !          2178:   if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL, 
        !          2179:                                               iph->ip_dst)) == NULL)
        !          2180:     return NULL;
        !          2181: 
        !          2182:   for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
        !          2183:     {
        !          2184:       vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id);
        !          2185:       if (!vl_area)
        !          2186:        continue;
        !          2187:       
        !          2188:       if (OSPF_AREA_SAME (&vl_area, &rcv_oi->area) &&
        !          2189:          IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id))
        !          2190:        {
        !          2191:          if (IS_DEBUG_OSPF_EVENT)
        !          2192:            zlog_debug ("associating packet with %s",
        !          2193:                       IF_NAME (vl_data->vl_oi));
        !          2194:          if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP))
        !          2195:            {
        !          2196:              if (IS_DEBUG_OSPF_EVENT)
        !          2197:                zlog_debug ("This VL is not up yet, sorry");
        !          2198:              return NULL;
        !          2199:            }
        !          2200:          
        !          2201:          return vl_data->vl_oi;
        !          2202:        }
        !          2203:     }
        !          2204: 
        !          2205:   if (IS_DEBUG_OSPF_EVENT)
        !          2206:     zlog_debug ("couldn't find any VL to associate the packet with");
        !          2207:   
        !          2208:   return NULL;
        !          2209: }
        !          2210: 
        !          2211: static inline int
        !          2212: ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
        !          2213: {
        !          2214:   /* Check match the Area ID of the receiving interface. */
        !          2215:   if (OSPF_AREA_SAME (&oi->area, &ospfh))
        !          2216:     return 1;
        !          2217: 
        !          2218:   return 0;
        !          2219: }
        !          2220: 
        !          2221: /* Unbound socket will accept any Raw IP packets if proto is matched.
        !          2222:    To prevent it, compare src IP address and i/f address with masking
        !          2223:    i/f network mask. */
        !          2224: static int
        !          2225: ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
        !          2226: {
        !          2227:   struct in_addr mask, me, him;
        !          2228: 
        !          2229:   if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
        !          2230:       oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !          2231:     return 1;
        !          2232: 
        !          2233:   masklen2ip (oi->address->prefixlen, &mask);
        !          2234: 
        !          2235:   me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
        !          2236:   him.s_addr = ip_src.s_addr & mask.s_addr;
        !          2237: 
        !          2238:  if (IPV4_ADDR_SAME (&me, &him))
        !          2239:    return 1;
        !          2240: 
        !          2241:  return 0;
        !          2242: }
        !          2243: 
        !          2244: static int
        !          2245: ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
        !          2246:                 struct ospf_header *ospfh)
        !          2247: {
        !          2248:   int ret = 0;
        !          2249:   struct crypt_key *ck;
        !          2250: 
        !          2251:   switch (ntohs (ospfh->auth_type))
        !          2252:     {
        !          2253:     case OSPF_AUTH_NULL:
        !          2254:       ret = 1;
        !          2255:       break;
        !          2256:     case OSPF_AUTH_SIMPLE:
        !          2257:       if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
        !          2258:        ret = 1;
        !          2259:       else
        !          2260:        ret = 0;
        !          2261:       break;
        !          2262:     case OSPF_AUTH_CRYPTOGRAPHIC:
        !          2263:       if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL)
        !          2264:        {
        !          2265:          ret = 0;
        !          2266:          break;
        !          2267:        }
        !          2268:       
        !          2269:       /* This is very basic, the digest processing is elsewhere */
        !          2270:       if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE && 
        !          2271:           ospfh->u.crypt.key_id == ck->key_id &&
        !          2272:           ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf))
        !          2273:         ret = 1;
        !          2274:       else
        !          2275:         ret = 0;
        !          2276:       break;
        !          2277:     default:
        !          2278:       ret = 0;
        !          2279:       break;
        !          2280:     }
        !          2281: 
        !          2282:   return ret;
        !          2283: }
        !          2284: 
        !          2285: static int
        !          2286: ospf_check_sum (struct ospf_header *ospfh)
        !          2287: {
        !          2288:   u_int32_t ret;
        !          2289:   u_int16_t sum;
        !          2290: 
        !          2291:   /* clear auth_data for checksum. */
        !          2292:   memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
        !          2293: 
        !          2294:   /* keep checksum and clear. */
        !          2295:   sum = ospfh->checksum;
        !          2296:   memset (&ospfh->checksum, 0, sizeof (u_int16_t));
        !          2297: 
        !          2298:   /* calculate checksum. */
        !          2299:   ret = in_cksum (ospfh, ntohs (ospfh->length));
        !          2300: 
        !          2301:   if (ret != sum)
        !          2302:     {
        !          2303:       zlog_info ("ospf_check_sum(): checksum mismatch, my %X, his %X",
        !          2304:                 ret, sum);
        !          2305:       return 0;
        !          2306:     }
        !          2307: 
        !          2308:   return 1;
        !          2309: }
        !          2310: 
        !          2311: /* OSPF Header verification. */
        !          2312: static int
        !          2313: ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
        !          2314:                    struct ip *iph, struct ospf_header *ospfh)
        !          2315: {
        !          2316:   /* check version. */
        !          2317:   if (ospfh->version != OSPF_VERSION)
        !          2318:     {
        !          2319:       zlog_warn ("interface %s: ospf_read version number mismatch.",
        !          2320:                 IF_NAME (oi));
        !          2321:       return -1;
        !          2322:     }
        !          2323: 
        !          2324:   /* Valid OSPFv2 packet types are 1 through 5 inclusive. */
        !          2325:   if (ospfh->type < 1 || ospfh->type > 5)
        !          2326:   {
        !          2327:     zlog_warn ("interface %s: invalid packet type %u", IF_NAME (oi), ospfh->type);
        !          2328:     return -1;
        !          2329:   }
        !          2330: 
        !          2331:   /* Check Area ID. */
        !          2332:   if (!ospf_check_area_id (oi, ospfh))
        !          2333:     {
        !          2334:       zlog_warn ("interface %s: ospf_read invalid Area ID %s.",
        !          2335:                 IF_NAME (oi), inet_ntoa (ospfh->area_id));
        !          2336:       return -1;
        !          2337:     }
        !          2338: 
        !          2339:   /* Check network mask, Silently discarded. */
        !          2340:   if (! ospf_check_network_mask (oi, iph->ip_src))
        !          2341:     {
        !          2342:       zlog_warn ("interface %s: ospf_read network address is not same [%s]",
        !          2343:                 IF_NAME (oi), inet_ntoa (iph->ip_src));
        !          2344:       return -1;
        !          2345:     }
        !          2346: 
        !          2347:   /* Check authentication. */
        !          2348:   if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
        !          2349:     {
        !          2350:       zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d",
        !          2351:                 IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type));
        !          2352:       return -1;
        !          2353:     }
        !          2354: 
        !          2355:   if (! ospf_check_auth (oi, ibuf, ospfh))
        !          2356:     {
        !          2357:       zlog_warn ("interface %s: ospf_read authentication failed.",
        !          2358:                 IF_NAME (oi));
        !          2359:       return -1;
        !          2360:     }
        !          2361: 
        !          2362:   /* if check sum is invalid, packet is discarded. */
        !          2363:   if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
        !          2364:     {
        !          2365:       if (! ospf_check_sum (ospfh))
        !          2366:        {
        !          2367:          zlog_warn ("interface %s: ospf_read packet checksum error %s",
        !          2368:                     IF_NAME (oi), inet_ntoa (ospfh->router_id));
        !          2369:          return -1;
        !          2370:        }
        !          2371:     }
        !          2372:   else
        !          2373:     {
        !          2374:       if (ospfh->checksum != 0)
        !          2375:        return -1;
        !          2376:       if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)
        !          2377:        {
        !          2378:          zlog_warn ("interface %s: ospf_read md5 authentication failed.",
        !          2379:                     IF_NAME (oi));
        !          2380:          return -1;
        !          2381:        }
        !          2382:     }
        !          2383: 
        !          2384:   return 0;
        !          2385: }
        !          2386: 
        !          2387: /* Starting point of packet process function. */
        !          2388: int
        !          2389: ospf_read (struct thread *thread)
        !          2390: {
        !          2391:   int ret;
        !          2392:   struct stream *ibuf;
        !          2393:   struct ospf *ospf;
        !          2394:   struct ospf_interface *oi;
        !          2395:   struct ip *iph;
        !          2396:   struct ospf_header *ospfh;
        !          2397:   u_int16_t length;
        !          2398:   struct interface *ifp;
        !          2399: 
        !          2400:   /* first of all get interface pointer. */
        !          2401:   ospf = THREAD_ARG (thread);
        !          2402: 
        !          2403:   /* prepare for next packet. */
        !          2404:   ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
        !          2405: 
        !          2406:   /* read OSPF packet. */
        !          2407:   stream_reset(ospf->ibuf);
        !          2408:   if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
        !          2409:     return -1;
        !          2410:   
        !          2411:   /* Note that there should not be alignment problems with this assignment
        !          2412:      because this is at the beginning of the stream data buffer. */
        !          2413:   iph = (struct ip *) STREAM_DATA (ibuf);
        !          2414:   /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */
        !          2415: 
        !          2416:   if (ifp == NULL)
        !          2417:     /* Handle cases where the platform does not support retrieving the ifindex,
        !          2418:        and also platforms (such as Solaris 8) that claim to support ifindex
        !          2419:        retrieval but do not. */
        !          2420:     ifp = if_lookup_address (iph->ip_src);
        !          2421:   
        !          2422:   if (ifp == NULL)
        !          2423:     return 0;
        !          2424: 
        !          2425:   /* IP Header dump. */
        !          2426:     if (IS_DEBUG_OSPF_PACKET(0, RECV))
        !          2427:            ospf_ip_header_dump (iph);
        !          2428: 
        !          2429:   /* Self-originated packet should be discarded silently. */
        !          2430:   if (ospf_if_lookup_by_local_addr (ospf, NULL, iph->ip_src))
        !          2431:     {
        !          2432:       if (IS_DEBUG_OSPF_PACKET (0, RECV))
        !          2433:         {
        !          2434:           zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
        !          2435:                      inet_ntoa (iph->ip_src));
        !          2436:         }
        !          2437:       return 0;
        !          2438:     }
        !          2439: 
        !          2440:   /* Advance from IP header to OSPF header (iph->ip_hl has been verified
        !          2441:      by ospf_recv_packet() to be correct). */
        !          2442:   stream_forward_getp (ibuf, iph->ip_hl * 4);
        !          2443: 
        !          2444:   /* Make sure the OSPF header is really there. */
        !          2445:   if (stream_get_endp (ibuf) - stream_get_getp (ibuf) < OSPF_HEADER_SIZE)
        !          2446:   {
        !          2447:     zlog_debug ("ospf_read: ignored OSPF packet with undersized (%u bytes) header",
        !          2448:                 stream_get_endp (ibuf) - stream_get_getp (ibuf));
        !          2449:     return -1;
        !          2450:   }
        !          2451: 
        !          2452:   /* Now it is safe to access all fields of OSPF packet header. */
        !          2453:   ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
        !          2454: 
        !          2455:   /* associate packet with ospf interface */
        !          2456:   oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp);
        !          2457: 
        !          2458:   /* ospf_verify_header() relies on a valid "oi" and thus can be called only
        !          2459:      after the passive/backbone/other checks below are passed. These checks
        !          2460:      in turn access the fields of unverified "ospfh" structure for their own
        !          2461:      purposes and must remain very accurate in doing this. */
        !          2462: 
        !          2463:   /* If incoming interface is passive one, ignore it. */
        !          2464:   if (oi && OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
        !          2465:     {
        !          2466:       char buf[3][INET_ADDRSTRLEN];
        !          2467: 
        !          2468:       if (IS_DEBUG_OSPF_EVENT)
        !          2469:        zlog_debug ("ignoring packet from router %s sent to %s, "
        !          2470:                    "received on a passive interface, %s",
        !          2471:                    inet_ntop(AF_INET, &ospfh->router_id, buf[0], sizeof(buf[0])),
        !          2472:                    inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
        !          2473:                    inet_ntop(AF_INET, &oi->address->u.prefix4,
        !          2474:                              buf[2], sizeof(buf[2])));
        !          2475: 
        !          2476:       if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
        !          2477:        {
        !          2478:          /* Try to fix multicast membership.
        !          2479:           * Some OS:es may have problems in this area,
        !          2480:           * make sure it is removed.
        !          2481:           */
        !          2482:          OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
        !          2483:          ospf_if_set_multicast(oi);
        !          2484:        }
        !          2485:       return 0;
        !          2486:   }
        !          2487: 
        !          2488: 
        !          2489:   /* if no local ospf_interface, 
        !          2490:    * or header area is backbone but ospf_interface is not
        !          2491:    * check for VLINK interface
        !          2492:    */
        !          2493:   if ( (oi == NULL) ||
        !          2494:       (OSPF_IS_AREA_ID_BACKBONE(ospfh->area_id)
        !          2495:       && !OSPF_IS_AREA_ID_BACKBONE(oi->area->area_id))
        !          2496:      )
        !          2497:     {
        !          2498:       if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
        !          2499:         {
        !          2500:           if (IS_DEBUG_OSPF_EVENT)
        !          2501:             zlog_debug ("Packet from [%s] received on link %s"
        !          2502:                         " but no ospf_interface",
        !          2503:                         inet_ntoa (iph->ip_src), ifp->name);
        !          2504:           return 0;
        !          2505:         }
        !          2506:     }
        !          2507: 
        !          2508:   /* else it must be a local ospf interface, check it was received on 
        !          2509:    * correct link 
        !          2510:    */
        !          2511:   else if (oi->ifp != ifp)
        !          2512:     {
        !          2513:       if (IS_DEBUG_OSPF_EVENT)
        !          2514:         zlog_warn ("Packet from [%s] received on wrong link %s",
        !          2515:                    inet_ntoa (iph->ip_src), ifp->name); 
        !          2516:       return 0;
        !          2517:     }
        !          2518:   else if (oi->state == ISM_Down)
        !          2519:     {
        !          2520:       char buf[2][INET_ADDRSTRLEN];
        !          2521:       zlog_warn ("Ignoring packet from %s to %s received on interface that is "
        !          2522:                 "down [%s]; interface flags are %s",
        !          2523:                 inet_ntop(AF_INET, &iph->ip_src, buf[0], sizeof(buf[0])),
        !          2524:                 inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
        !          2525:                 ifp->name, if_flag_dump(ifp->flags));
        !          2526:       /* Fix multicast memberships? */
        !          2527:       if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
        !          2528:         OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
        !          2529:       else if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS))
        !          2530:        OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
        !          2531:       if (oi->multicast_memberships)
        !          2532:        ospf_if_set_multicast(oi);
        !          2533:       return 0;
        !          2534:     }
        !          2535: 
        !          2536:   /*
        !          2537:    * If the received packet is destined for AllDRouters, the packet
        !          2538:    * should be accepted only if the received ospf interface state is
        !          2539:    * either DR or Backup -- endo.
        !          2540:    */
        !          2541:   if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS)
        !          2542:   && (oi->state != ISM_DR && oi->state != ISM_Backup))
        !          2543:     {
        !          2544:       zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)",
        !          2545:                  inet_ntoa (iph->ip_src), IF_NAME (oi),
        !          2546:                  LOOKUP (ospf_ism_state_msg, oi->state));
        !          2547:       /* Try to fix multicast membership. */
        !          2548:       SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
        !          2549:       ospf_if_set_multicast(oi);
        !          2550:       return 0;
        !          2551:     }
        !          2552: 
        !          2553:   /* Verify more OSPF header fields. */
        !          2554:   ret = ospf_verify_header (ibuf, oi, iph, ospfh);
        !          2555:   if (ret < 0)
        !          2556:   {
        !          2557:     if (IS_DEBUG_OSPF_PACKET (0, RECV))
        !          2558:       zlog_debug ("ospf_read[%s]: Header check failed, "
        !          2559:                   "dropping.",
        !          2560:                   inet_ntoa (iph->ip_src));
        !          2561:     return ret;
        !          2562:   }
        !          2563: 
        !          2564:   /* Show debug receiving packet. */
        !          2565:   if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
        !          2566:     {
        !          2567:       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
        !          2568:         {
        !          2569:           zlog_debug ("-----------------------------------------------------");
        !          2570:           ospf_packet_dump (ibuf);
        !          2571:         }
        !          2572: 
        !          2573:       zlog_debug ("%s received from [%s] via [%s]",
        !          2574:                  ospf_packet_type_str[ospfh->type],
        !          2575:                  inet_ntoa (ospfh->router_id), IF_NAME (oi));
        !          2576:       zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));
        !          2577:       zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));
        !          2578: 
        !          2579:       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
        !          2580:        zlog_debug ("-----------------------------------------------------");
        !          2581:   }
        !          2582: 
        !          2583:   stream_forward_getp (ibuf, OSPF_HEADER_SIZE);
        !          2584: 
        !          2585:   /* Adjust size to message length. */
        !          2586:   length = ntohs (ospfh->length) - OSPF_HEADER_SIZE;
        !          2587: 
        !          2588:   /* Read rest of the packet and call each sort of packet routine. */
        !          2589:   switch (ospfh->type)
        !          2590:     {
        !          2591:     case OSPF_MSG_HELLO:
        !          2592:       ospf_hello (iph, ospfh, ibuf, oi, length);
        !          2593:       break;
        !          2594:     case OSPF_MSG_DB_DESC:
        !          2595:       ospf_db_desc (iph, ospfh, ibuf, oi, length);
        !          2596:       break;
        !          2597:     case OSPF_MSG_LS_REQ:
        !          2598:       ospf_ls_req (iph, ospfh, ibuf, oi, length);
        !          2599:       break;
        !          2600:     case OSPF_MSG_LS_UPD:
        !          2601:       ospf_ls_upd (iph, ospfh, ibuf, oi, length);
        !          2602:       break;
        !          2603:     case OSPF_MSG_LS_ACK:
        !          2604:       ospf_ls_ack (iph, ospfh, ibuf, oi, length);
        !          2605:       break;
        !          2606:     default:
        !          2607:       zlog (NULL, LOG_WARNING,
        !          2608:            "interface %s: OSPF packet header type %d is illegal",
        !          2609:            IF_NAME (oi), ospfh->type);
        !          2610:       break;
        !          2611:     }
        !          2612: 
        !          2613:   return 0;
        !          2614: }
        !          2615: 
        !          2616: /* Make OSPF header. */
        !          2617: static void
        !          2618: ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
        !          2619: {
        !          2620:   struct ospf_header *ospfh;
        !          2621: 
        !          2622:   ospfh = (struct ospf_header *) STREAM_DATA (s);
        !          2623: 
        !          2624:   ospfh->version = (u_char) OSPF_VERSION;
        !          2625:   ospfh->type = (u_char) type;
        !          2626: 
        !          2627:   ospfh->router_id = oi->ospf->router_id;
        !          2628: 
        !          2629:   ospfh->checksum = 0;
        !          2630:   ospfh->area_id = oi->area->area_id;
        !          2631:   ospfh->auth_type = htons (ospf_auth_type (oi));
        !          2632: 
        !          2633:   memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
        !          2634: 
        !          2635:   stream_forward_endp (s, OSPF_HEADER_SIZE);
        !          2636: }
        !          2637: 
        !          2638: /* Make Authentication Data. */
        !          2639: static int
        !          2640: ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
        !          2641: {
        !          2642:   struct crypt_key *ck;
        !          2643: 
        !          2644:   switch (ospf_auth_type (oi))
        !          2645:     {
        !          2646:     case OSPF_AUTH_NULL:
        !          2647:       /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
        !          2648:       break;
        !          2649:     case OSPF_AUTH_SIMPLE:
        !          2650:       memcpy (ospfh->u.auth_data, OSPF_IF_PARAM (oi, auth_simple),
        !          2651:              OSPF_AUTH_SIMPLE_SIZE);
        !          2652:       break;
        !          2653:     case OSPF_AUTH_CRYPTOGRAPHIC:
        !          2654:       /* If key is not set, then set 0. */
        !          2655:       if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
        !          2656:        {
        !          2657:          ospfh->u.crypt.zero = 0;
        !          2658:          ospfh->u.crypt.key_id = 0;
        !          2659:          ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
        !          2660:        }
        !          2661:       else
        !          2662:        {
        !          2663:          ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
        !          2664:          ospfh->u.crypt.zero = 0;
        !          2665:          ospfh->u.crypt.key_id = ck->key_id;
        !          2666:          ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
        !          2667:        }
        !          2668:       /* note: the seq is done in ospf_make_md5_digest() */
        !          2669:       break;
        !          2670:     default:
        !          2671:       /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
        !          2672:       break;
        !          2673:     }
        !          2674: 
        !          2675:   return 0;
        !          2676: }
        !          2677: 
        !          2678: /* Fill rest of OSPF header. */
        !          2679: static void
        !          2680: ospf_fill_header (struct ospf_interface *oi,
        !          2681:                  struct stream *s, u_int16_t length)
        !          2682: {
        !          2683:   struct ospf_header *ospfh;
        !          2684: 
        !          2685:   ospfh = (struct ospf_header *) STREAM_DATA (s);
        !          2686: 
        !          2687:   /* Fill length. */
        !          2688:   ospfh->length = htons (length);
        !          2689: 
        !          2690:   /* Calculate checksum. */
        !          2691:   if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
        !          2692:     ospfh->checksum = in_cksum (ospfh, length);
        !          2693:   else
        !          2694:     ospfh->checksum = 0;
        !          2695: 
        !          2696:   /* Add Authentication Data. */
        !          2697:   ospf_make_auth (oi, ospfh);
        !          2698: }
        !          2699: 
        !          2700: static int
        !          2701: ospf_make_hello (struct ospf_interface *oi, struct stream *s)
        !          2702: {
        !          2703:   struct ospf_neighbor *nbr;
        !          2704:   struct route_node *rn;
        !          2705:   u_int16_t length = OSPF_HELLO_MIN_SIZE;
        !          2706:   struct in_addr mask;
        !          2707:   unsigned long p;
        !          2708:   int flag = 0;
        !          2709: 
        !          2710:   /* Set netmask of interface. */
        !          2711:   if (oi->type != OSPF_IFTYPE_POINTOPOINT &&
        !          2712:       oi->type != OSPF_IFTYPE_VIRTUALLINK)
        !          2713:     masklen2ip (oi->address->prefixlen, &mask);
        !          2714:   else
        !          2715:     memset ((char *) &mask, 0, sizeof (struct in_addr));
        !          2716:   stream_put_ipv4 (s, mask.s_addr);
        !          2717: 
        !          2718:   /* Set Hello Interval. */
        !          2719:   if (OSPF_IF_PARAM (oi, fast_hello) == 0)
        !          2720:     stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
        !          2721:   else
        !          2722:     stream_putw (s, 0); /* hello-interval of 0 for fast-hellos */
        !          2723: 
        !          2724:   if (IS_DEBUG_OSPF_EVENT)
        !          2725:     zlog_debug ("make_hello: options: %x, int: %s",
        !          2726:               OPTIONS(oi), IF_NAME (oi));
        !          2727: 
        !          2728:   /* Set Options. */
        !          2729:   stream_putc (s, OPTIONS (oi));
        !          2730: 
        !          2731:   /* Set Router Priority. */
        !          2732:   stream_putc (s, PRIORITY (oi));
        !          2733: 
        !          2734:   /* Set Router Dead Interval. */
        !          2735:   stream_putl (s, OSPF_IF_PARAM (oi, v_wait));
        !          2736: 
        !          2737:   /* Set Designated Router. */
        !          2738:   stream_put_ipv4 (s, DR (oi).s_addr);
        !          2739: 
        !          2740:   p = stream_get_endp (s);
        !          2741: 
        !          2742:   /* Set Backup Designated Router. */
        !          2743:   stream_put_ipv4 (s, BDR (oi).s_addr);
        !          2744: 
        !          2745:   /* Add neighbor seen. */
        !          2746:   for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
        !          2747:     if ((nbr = rn->info))
        !          2748:       if (nbr->router_id.s_addr != 0)  /* Ignore 0.0.0.0 node. */
        !          2749:        if (nbr->state != NSM_Attempt)  /* Ignore Down neighbor. */
        !          2750:        if (nbr->state != NSM_Down)     /* This is myself for DR election. */
        !          2751:          if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
        !          2752:            {
        !          2753:              /* Check neighbor is sane? */
        !          2754:              if (nbr->d_router.s_addr != 0
        !          2755:                  && IPV4_ADDR_SAME (&nbr->d_router, &oi->address->u.prefix4)
        !          2756:                  && IPV4_ADDR_SAME (&nbr->bd_router, &oi->address->u.prefix4))
        !          2757:                flag = 1;
        !          2758: 
        !          2759:              stream_put_ipv4 (s, nbr->router_id.s_addr);
        !          2760:              length += 4;
        !          2761:            }
        !          2762: 
        !          2763:   /* Let neighbor generate BackupSeen. */
        !          2764:   if (flag == 1)
        !          2765:     stream_putl_at (s, p, 0); /* ipv4 address, normally */
        !          2766: 
        !          2767:   return length;
        !          2768: }
        !          2769: 
        !          2770: static int
        !          2771: ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
        !          2772:                   struct stream *s)
        !          2773: {
        !          2774:   struct ospf_lsa *lsa;
        !          2775:   u_int16_t length = OSPF_DB_DESC_MIN_SIZE;
        !          2776:   u_char options;
        !          2777:   unsigned long pp;
        !          2778:   int i;
        !          2779:   struct ospf_lsdb *lsdb;
        !          2780:   
        !          2781:   /* Set Interface MTU. */
        !          2782:   if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !          2783:     stream_putw (s, 0);
        !          2784:   else
        !          2785:     stream_putw (s, oi->ifp->mtu);
        !          2786: 
        !          2787:   /* Set Options. */
        !          2788:   options = OPTIONS (oi);
        !          2789: #ifdef HAVE_OPAQUE_LSA
        !          2790:   if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
        !          2791:     {
        !          2792:       if (IS_SET_DD_I (nbr->dd_flags)
        !          2793:       ||  CHECK_FLAG (nbr->options, OSPF_OPTION_O))
        !          2794:         /*
        !          2795:          * Set O-bit in the outgoing DD packet for capablity negotiation,
        !          2796:          * if one of following case is applicable. 
        !          2797:          *
        !          2798:          * 1) WaitTimer expiration event triggered the neighbor state to
        !          2799:          *    change to Exstart, but no (valid) DD packet has received
        !          2800:          *    from the neighbor yet.
        !          2801:          *
        !          2802:          * 2) At least one DD packet with O-bit on has received from the
        !          2803:          *    neighbor.
        !          2804:          */
        !          2805:         SET_FLAG (options, OSPF_OPTION_O);
        !          2806:     }
        !          2807: #endif /* HAVE_OPAQUE_LSA */
        !          2808:   stream_putc (s, options);
        !          2809: 
        !          2810:   /* DD flags */
        !          2811:   pp = stream_get_endp (s);
        !          2812:   stream_putc (s, nbr->dd_flags);
        !          2813: 
        !          2814:   /* Set DD Sequence Number. */
        !          2815:   stream_putl (s, nbr->dd_seqnum);
        !          2816: 
        !          2817:   /* shortcut unneeded walk of (empty) summary LSDBs */
        !          2818:   if (ospf_db_summary_isempty (nbr))
        !          2819:     goto empty;
        !          2820: 
        !          2821:   /* Describe LSA Header from Database Summary List. */
        !          2822:   lsdb = &nbr->db_sum;
        !          2823: 
        !          2824:   for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
        !          2825:     {
        !          2826:       struct route_table *table = lsdb->type[i].db;
        !          2827:       struct route_node *rn;
        !          2828: 
        !          2829:       for (rn = route_top (table); rn; rn = route_next (rn))
        !          2830:        if ((lsa = rn->info) != NULL)
        !          2831:          {
        !          2832: #ifdef HAVE_OPAQUE_LSA
        !          2833:             if (IS_OPAQUE_LSA (lsa->data->type)
        !          2834:             && (! CHECK_FLAG (options, OSPF_OPTION_O)))
        !          2835:               {
        !          2836:                 /* Suppress advertising opaque-informations. */
        !          2837:                 /* Remove LSA from DB summary list. */
        !          2838:                 ospf_lsdb_delete (lsdb, lsa);
        !          2839:                 continue;
        !          2840:               }
        !          2841: #endif /* HAVE_OPAQUE_LSA */
        !          2842: 
        !          2843:            if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
        !          2844:              {
        !          2845:                struct lsa_header *lsah;
        !          2846:                u_int16_t ls_age;
        !          2847:                
        !          2848:                /* DD packet overflows interface MTU. */
        !          2849:                if (length + OSPF_LSA_HEADER_SIZE > ospf_packet_max (oi))
        !          2850:                  break;
        !          2851:                
        !          2852:                /* Keep pointer to LS age. */
        !          2853:                lsah = (struct lsa_header *) (STREAM_DATA (s) +
        !          2854:                                              stream_get_endp (s));
        !          2855:                
        !          2856:                /* Proceed stream pointer. */
        !          2857:                stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
        !          2858:                length += OSPF_LSA_HEADER_SIZE;
        !          2859:                
        !          2860:                /* Set LS age. */
        !          2861:                ls_age = LS_AGE (lsa);
        !          2862:                lsah->ls_age = htons (ls_age);
        !          2863:                
        !          2864:              }
        !          2865:            
        !          2866:            /* Remove LSA from DB summary list. */
        !          2867:            ospf_lsdb_delete (lsdb, lsa);
        !          2868:          }
        !          2869:     }
        !          2870: 
        !          2871:   /* Update 'More' bit */
        !          2872:   if (ospf_db_summary_isempty (nbr))
        !          2873:     {
        !          2874: empty:
        !          2875:       if (nbr->state >= NSM_Exchange)
        !          2876:         {
        !          2877:           UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_M);
        !          2878:           /* Rewrite DD flags */
        !          2879:           stream_putc_at (s, pp, nbr->dd_flags);
        !          2880:         }
        !          2881:       else
        !          2882:         {
        !          2883:           assert (IS_SET_DD_M(nbr->dd_flags));
        !          2884:         }
        !          2885:     }
        !          2886:   return length;
        !          2887: }
        !          2888: 
        !          2889: static int
        !          2890: ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
        !          2891:                       unsigned long delta, struct ospf_neighbor *nbr,
        !          2892:                       struct ospf_lsa *lsa)
        !          2893: {
        !          2894:   struct ospf_interface *oi;
        !          2895: 
        !          2896:   oi = nbr->oi;
        !          2897: 
        !          2898:   /* LS Request packet overflows interface MTU. */
        !          2899:   if (*length + delta > ospf_packet_max(oi))
        !          2900:     return 0;
        !          2901: 
        !          2902:   stream_putl (s, lsa->data->type);
        !          2903:   stream_put_ipv4 (s, lsa->data->id.s_addr);
        !          2904:   stream_put_ipv4 (s, lsa->data->adv_router.s_addr);
        !          2905:   
        !          2906:   ospf_lsa_unlock (&nbr->ls_req_last);
        !          2907:   nbr->ls_req_last = ospf_lsa_lock (lsa);
        !          2908:   
        !          2909:   *length += 12;
        !          2910:   return 1;
        !          2911: }
        !          2912: 
        !          2913: static int
        !          2914: ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
        !          2915: {
        !          2916:   struct ospf_lsa *lsa;
        !          2917:   u_int16_t length = OSPF_LS_REQ_MIN_SIZE;
        !          2918:   unsigned long delta = stream_get_endp(s)+12;
        !          2919:   struct route_table *table;
        !          2920:   struct route_node *rn;
        !          2921:   int i;
        !          2922:   struct ospf_lsdb *lsdb;
        !          2923: 
        !          2924:   lsdb = &nbr->ls_req;
        !          2925: 
        !          2926:   for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
        !          2927:     {
        !          2928:       table = lsdb->type[i].db;
        !          2929:       for (rn = route_top (table); rn; rn = route_next (rn))
        !          2930:        if ((lsa = (rn->info)) != NULL)
        !          2931:          if (ospf_make_ls_req_func (s, &length, delta, nbr, lsa) == 0)
        !          2932:            {
        !          2933:              route_unlock_node (rn);
        !          2934:              break;
        !          2935:            }
        !          2936:     }
        !          2937:   return length;
        !          2938: }
        !          2939: 
        !          2940: static int
        !          2941: ls_age_increment (struct ospf_lsa *lsa, int delay)
        !          2942: {
        !          2943:   int age;
        !          2944: 
        !          2945:   age = IS_LSA_MAXAGE (lsa) ? OSPF_LSA_MAXAGE : LS_AGE (lsa) + delay;
        !          2946: 
        !          2947:   return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age);
        !          2948: }
        !          2949: 
        !          2950: static int
        !          2951: ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream *s)
        !          2952: {
        !          2953:   struct ospf_lsa *lsa;
        !          2954:   struct listnode *node;
        !          2955:   u_int16_t length = 0;
        !          2956:   unsigned int size_noauth;
        !          2957:   unsigned long delta = stream_get_endp (s);
        !          2958:   unsigned long pp;
        !          2959:   int count = 0;
        !          2960: 
        !          2961:   if (IS_DEBUG_OSPF_EVENT)
        !          2962:     zlog_debug ("ospf_make_ls_upd: Start");
        !          2963: 
        !          2964:   pp = stream_get_endp (s);
        !          2965:   stream_forward_endp (s, OSPF_LS_UPD_MIN_SIZE);
        !          2966:   length += OSPF_LS_UPD_MIN_SIZE;
        !          2967: 
        !          2968:   /* Calculate amount of packet usable for data. */
        !          2969:   size_noauth = stream_get_size(s) - ospf_packet_authspace(oi);
        !          2970: 
        !          2971:   while ((node = listhead (update)) != NULL)
        !          2972:     {
        !          2973:       struct lsa_header *lsah;
        !          2974:       u_int16_t ls_age;
        !          2975: 
        !          2976:       if (IS_DEBUG_OSPF_EVENT)
        !          2977:         zlog_debug ("ospf_make_ls_upd: List Iteration");
        !          2978: 
        !          2979:       lsa = listgetdata (node);
        !          2980: 
        !          2981:       assert (lsa->data);
        !          2982: 
        !          2983:       /* Will it fit? */
        !          2984:       if (length + delta + ntohs (lsa->data->length) > size_noauth)
        !          2985:         break;
        !          2986: 
        !          2987:       /* Keep pointer to LS age. */
        !          2988:       lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_endp (s));
        !          2989: 
        !          2990:       /* Put LSA to Link State Request. */
        !          2991:       stream_put (s, lsa->data, ntohs (lsa->data->length));
        !          2992: 
        !          2993:       /* Set LS age. */
        !          2994:       /* each hop must increment an lsa_age by transmit_delay 
        !          2995:          of OSPF interface */
        !          2996:       ls_age = ls_age_increment (lsa, OSPF_IF_PARAM (oi, transmit_delay));
        !          2997:       lsah->ls_age = htons (ls_age);
        !          2998: 
        !          2999:       length += ntohs (lsa->data->length);
        !          3000:       count++;
        !          3001: 
        !          3002:       list_delete_node (update, node);
        !          3003:       ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
        !          3004:     }
        !          3005: 
        !          3006:   /* Now set #LSAs. */
        !          3007:   stream_putl_at (s, pp, count);
        !          3008: 
        !          3009:   if (IS_DEBUG_OSPF_EVENT)
        !          3010:     zlog_debug ("ospf_make_ls_upd: Stop");
        !          3011:   return length;
        !          3012: }
        !          3013: 
        !          3014: static int
        !          3015: ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
        !          3016: {
        !          3017:   struct listnode *node, *nnode;
        !          3018:   u_int16_t length = OSPF_LS_ACK_MIN_SIZE;
        !          3019:   unsigned long delta = stream_get_endp(s) + 24;
        !          3020:   struct ospf_lsa *lsa;
        !          3021: 
        !          3022:   for (ALL_LIST_ELEMENTS (ack, node, nnode, lsa))
        !          3023:     {
        !          3024:       assert (lsa);
        !          3025:       
        !          3026:       if (length + delta > ospf_packet_max (oi))
        !          3027:        break;
        !          3028:       
        !          3029:       stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
        !          3030:       length += OSPF_LSA_HEADER_SIZE;
        !          3031:       
        !          3032:       listnode_delete (ack, lsa);
        !          3033:       ospf_lsa_unlock (&lsa); /* oi->ls_ack_direct.ls_ack */
        !          3034:     }
        !          3035:   
        !          3036:   return length;
        !          3037: }
        !          3038: 
        !          3039: static void
        !          3040: ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr)
        !          3041: {
        !          3042:   struct ospf_packet *op;
        !          3043:   u_int16_t length = OSPF_HEADER_SIZE;
        !          3044: 
        !          3045:   op = ospf_packet_new (oi->ifp->mtu);
        !          3046: 
        !          3047:   /* Prepare OSPF common header. */
        !          3048:   ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
        !          3049: 
        !          3050:   /* Prepare OSPF Hello body. */
        !          3051:   length += ospf_make_hello (oi, op->s);
        !          3052: 
        !          3053:   /* Fill OSPF header. */
        !          3054:   ospf_fill_header (oi, op->s, length);
        !          3055: 
        !          3056:   /* Set packet length. */
        !          3057:   op->length = length;
        !          3058: 
        !          3059:   op->dst.s_addr = addr;
        !          3060: 
        !          3061:   /* Add packet to the top of the interface output queue, so that they
        !          3062:    * can't get delayed by things like long queues of LS Update packets
        !          3063:    */
        !          3064:   ospf_packet_add_top (oi, op);
        !          3065: 
        !          3066:   /* Hook thread to write packet. */
        !          3067:   OSPF_ISM_WRITE_ON (oi->ospf);
        !          3068: }
        !          3069: 
        !          3070: static void
        !          3071: ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
        !          3072: {
        !          3073:   struct ospf_interface *oi;
        !          3074: 
        !          3075:   oi = nbr_nbma->oi;
        !          3076:   assert(oi);
        !          3077: 
        !          3078:   /* If this is passive interface, do not send OSPF Hello. */
        !          3079:   if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
        !          3080:     return;
        !          3081: 
        !          3082:   if (oi->type != OSPF_IFTYPE_NBMA)
        !          3083:     return;
        !          3084: 
        !          3085:   if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
        !          3086:     return;
        !          3087: 
        !          3088:   if (PRIORITY(oi) == 0)
        !          3089:     return;
        !          3090: 
        !          3091:   if (nbr_nbma->priority == 0
        !          3092:       && oi->state != ISM_DR && oi->state != ISM_Backup)
        !          3093:     return;
        !          3094: 
        !          3095:   ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr);
        !          3096: }
        !          3097: 
        !          3098: int
        !          3099: ospf_poll_timer (struct thread *thread)
        !          3100: {
        !          3101:   struct ospf_nbr_nbma *nbr_nbma;
        !          3102: 
        !          3103:   nbr_nbma = THREAD_ARG (thread);
        !          3104:   nbr_nbma->t_poll = NULL;
        !          3105: 
        !          3106:   if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
        !          3107:     zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Poll timer expire)",
        !          3108:     IF_NAME (nbr_nbma->oi), inet_ntoa (nbr_nbma->addr));
        !          3109: 
        !          3110:   ospf_poll_send (nbr_nbma);
        !          3111: 
        !          3112:   if (nbr_nbma->v_poll > 0)
        !          3113:     OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
        !          3114:                        nbr_nbma->v_poll);
        !          3115: 
        !          3116:   return 0;
        !          3117: }
        !          3118: 
        !          3119: 
        !          3120: int
        !          3121: ospf_hello_reply_timer (struct thread *thread)
        !          3122: {
        !          3123:   struct ospf_neighbor *nbr;
        !          3124: 
        !          3125:   nbr = THREAD_ARG (thread);
        !          3126:   nbr->t_hello_reply = NULL;
        !          3127: 
        !          3128:   assert (nbr->oi);
        !          3129: 
        !          3130:   if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
        !          3131:     zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
        !          3132:          IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
        !          3133: 
        !          3134:   ospf_hello_send_sub (nbr->oi, nbr->address.u.prefix4.s_addr);
        !          3135: 
        !          3136:   return 0;
        !          3137: }
        !          3138: 
        !          3139: /* Send OSPF Hello. */
        !          3140: void
        !          3141: ospf_hello_send (struct ospf_interface *oi)
        !          3142: {
        !          3143:   /* If this is passive interface, do not send OSPF Hello. */
        !          3144:   if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
        !          3145:     return;
        !          3146: 
        !          3147:   if (oi->type == OSPF_IFTYPE_NBMA)
        !          3148:     {
        !          3149:       struct ospf_neighbor *nbr;
        !          3150:       struct route_node *rn;
        !          3151: 
        !          3152:       for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
        !          3153:        if ((nbr = rn->info))
        !          3154:          if (nbr != oi->nbr_self)
        !          3155:            if (nbr->state != NSM_Down)
        !          3156:              {
        !          3157:                /*  RFC 2328  Section 9.5.1
        !          3158:                    If the router is not eligible to become Designated Router,
        !          3159:                    it must periodically send Hello Packets to both the
        !          3160:                    Designated Router and the Backup Designated Router (if they
        !          3161:                    exist).  */
        !          3162:                if (PRIORITY(oi) == 0 &&
        !          3163:                    IPV4_ADDR_CMP(&DR(oi),  &nbr->address.u.prefix4) &&
        !          3164:                    IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
        !          3165:                  continue;
        !          3166: 
        !          3167:                /*  If the router is eligible to become Designated Router, it
        !          3168:                    must periodically send Hello Packets to all neighbors that
        !          3169:                    are also eligible. In addition, if the router is itself the
        !          3170:                    Designated Router or Backup Designated Router, it must also
        !          3171:                    send periodic Hello Packets to all other neighbors. */
        !          3172: 
        !          3173:                if (nbr->priority == 0 && oi->state == ISM_DROther)
        !          3174:                  continue;
        !          3175:                /* if oi->state == Waiting, send hello to all neighbors */
        !          3176:                ospf_hello_send_sub (oi, nbr->address.u.prefix4.s_addr);
        !          3177:              }
        !          3178:     }
        !          3179:   else
        !          3180:     {
        !          3181:       /* Decide destination address. */
        !          3182:       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !          3183:         ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr);
        !          3184:       else
        !          3185:         ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS));
        !          3186:     }
        !          3187: }
        !          3188: 
        !          3189: /* Send OSPF Database Description. */
        !          3190: void
        !          3191: ospf_db_desc_send (struct ospf_neighbor *nbr)
        !          3192: {
        !          3193:   struct ospf_interface *oi;
        !          3194:   struct ospf_packet *op;
        !          3195:   u_int16_t length = OSPF_HEADER_SIZE;
        !          3196: 
        !          3197:   oi = nbr->oi;
        !          3198:   op = ospf_packet_new (oi->ifp->mtu);
        !          3199: 
        !          3200:   /* Prepare OSPF common header. */
        !          3201:   ospf_make_header (OSPF_MSG_DB_DESC, oi, op->s);
        !          3202: 
        !          3203:   /* Prepare OSPF Database Description body. */
        !          3204:   length += ospf_make_db_desc (oi, nbr, op->s);
        !          3205: 
        !          3206:   /* Fill OSPF header. */
        !          3207:   ospf_fill_header (oi, op->s, length);
        !          3208: 
        !          3209:   /* Set packet length. */
        !          3210:   op->length = length;
        !          3211: 
        !          3212:   /* Decide destination address. */
        !          3213:   if (oi->type == OSPF_IFTYPE_POINTOPOINT) 
        !          3214:     op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
        !          3215:   else
        !          3216:     op->dst = nbr->address.u.prefix4;
        !          3217: 
        !          3218:   /* Add packet to the interface output queue. */
        !          3219:   ospf_packet_add (oi, op);
        !          3220: 
        !          3221:   /* Hook thread to write packet. */
        !          3222:   OSPF_ISM_WRITE_ON (oi->ospf);
        !          3223: 
        !          3224:   /* Remove old DD packet, then copy new one and keep in neighbor structure. */
        !          3225:   if (nbr->last_send)
        !          3226:     ospf_packet_free (nbr->last_send);
        !          3227:   nbr->last_send = ospf_packet_dup (op);
        !          3228:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &nbr->last_send_ts);
        !          3229: }
        !          3230: 
        !          3231: /* Re-send Database Description. */
        !          3232: void
        !          3233: ospf_db_desc_resend (struct ospf_neighbor *nbr)
        !          3234: {
        !          3235:   struct ospf_interface *oi;
        !          3236: 
        !          3237:   oi = nbr->oi;
        !          3238: 
        !          3239:   /* Add packet to the interface output queue. */
        !          3240:   ospf_packet_add (oi, ospf_packet_dup (nbr->last_send));
        !          3241: 
        !          3242:   /* Hook thread to write packet. */
        !          3243:   OSPF_ISM_WRITE_ON (oi->ospf);
        !          3244: }
        !          3245: 
        !          3246: /* Send Link State Request. */
        !          3247: void
        !          3248: ospf_ls_req_send (struct ospf_neighbor *nbr)
        !          3249: {
        !          3250:   struct ospf_interface *oi;
        !          3251:   struct ospf_packet *op;
        !          3252:   u_int16_t length = OSPF_HEADER_SIZE;
        !          3253: 
        !          3254:   oi = nbr->oi;
        !          3255:   op = ospf_packet_new (oi->ifp->mtu);
        !          3256: 
        !          3257:   /* Prepare OSPF common header. */
        !          3258:   ospf_make_header (OSPF_MSG_LS_REQ, oi, op->s);
        !          3259: 
        !          3260:   /* Prepare OSPF Link State Request body. */
        !          3261:   length += ospf_make_ls_req (nbr, op->s);
        !          3262:   if (length == OSPF_HEADER_SIZE)
        !          3263:     {
        !          3264:       ospf_packet_free (op);
        !          3265:       return;
        !          3266:     }
        !          3267: 
        !          3268:   /* Fill OSPF header. */
        !          3269:   ospf_fill_header (oi, op->s, length);
        !          3270: 
        !          3271:   /* Set packet length. */
        !          3272:   op->length = length;
        !          3273: 
        !          3274:   /* Decide destination address. */
        !          3275:   if (oi->type == OSPF_IFTYPE_POINTOPOINT) 
        !          3276:     op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
        !          3277:   else
        !          3278:     op->dst = nbr->address.u.prefix4;
        !          3279: 
        !          3280:   /* Add packet to the interface output queue. */
        !          3281:   ospf_packet_add (oi, op);
        !          3282: 
        !          3283:   /* Hook thread to write packet. */
        !          3284:   OSPF_ISM_WRITE_ON (oi->ospf);
        !          3285: 
        !          3286:   /* Add Link State Request Retransmission Timer. */
        !          3287:   OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
        !          3288: }
        !          3289: 
        !          3290: /* Send Link State Update with an LSA. */
        !          3291: void
        !          3292: ospf_ls_upd_send_lsa (struct ospf_neighbor *nbr, struct ospf_lsa *lsa,
        !          3293:                      int flag)
        !          3294: {
        !          3295:   struct list *update;
        !          3296: 
        !          3297:   update = list_new ();
        !          3298: 
        !          3299:   listnode_add (update, lsa);
        !          3300:   ospf_ls_upd_send (nbr, update, flag);
        !          3301: 
        !          3302:   list_delete (update);
        !          3303: }
        !          3304: 
        !          3305: /* Determine size for packet. Must be at least big enough to accomodate next
        !          3306:  * LSA on list, which may be bigger than MTU size.
        !          3307:  *
        !          3308:  * Return pointer to new ospf_packet
        !          3309:  * NULL if we can not allocate, eg because LSA is bigger than imposed limit
        !          3310:  * on packet sizes (in which case offending LSA is deleted from update list)
        !          3311:  */
        !          3312: static struct ospf_packet *
        !          3313: ospf_ls_upd_packet_new (struct list *update, struct ospf_interface *oi)
        !          3314: {
        !          3315:   struct ospf_lsa *lsa;
        !          3316:   struct listnode *ln;
        !          3317:   size_t size;
        !          3318:   static char warned = 0;
        !          3319: 
        !          3320:   lsa = listgetdata((ln = listhead (update)));
        !          3321:   assert (lsa->data);
        !          3322: 
        !          3323:   if ((OSPF_LS_UPD_MIN_SIZE + ntohs (lsa->data->length))
        !          3324:       > ospf_packet_max (oi))
        !          3325:     {
        !          3326:       if (!warned)
        !          3327:         {
        !          3328:           zlog_warn ("ospf_ls_upd_packet_new: oversized LSA encountered!"
        !          3329:                      "will need to fragment. Not optimal. Try divide up"
        !          3330:                      " your network with areas. Use 'debug ospf packet send'"
        !          3331:                      " to see details, or look at 'show ip ospf database ..'");
        !          3332:           warned = 1;
        !          3333:         }
        !          3334: 
        !          3335:       if (IS_DEBUG_OSPF_PACKET (0, SEND))
        !          3336:         zlog_debug ("ospf_ls_upd_packet_new: oversized LSA id:%s,"
        !          3337:                    " %d bytes originated by %s, will be fragmented!",
        !          3338:                    inet_ntoa (lsa->data->id),
        !          3339:                    ntohs (lsa->data->length),
        !          3340:                    inet_ntoa (lsa->data->adv_router));
        !          3341: 
        !          3342:       /* 
        !          3343:        * Allocate just enough to fit this LSA only, to avoid including other
        !          3344:        * LSAs in fragmented LSA Updates.
        !          3345:        */
        !          3346:       size = ntohs (lsa->data->length) + (oi->ifp->mtu - ospf_packet_max (oi))
        !          3347:              + OSPF_LS_UPD_MIN_SIZE;
        !          3348:     }
        !          3349:   else
        !          3350:     size = oi->ifp->mtu;
        !          3351: 
        !          3352:   if (size > OSPF_MAX_PACKET_SIZE)
        !          3353:     {
        !          3354:       zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s too big,"
        !          3355:                  " %d bytes, packet size %ld, dropping it completely."
        !          3356:                  " OSPF routing is broken!",
        !          3357:                  inet_ntoa (lsa->data->id), ntohs (lsa->data->length),
        !          3358:                  (long int) size);
        !          3359:       list_delete_node (update, ln);
        !          3360:       return NULL;
        !          3361:     }
        !          3362: 
        !          3363:   /* IP header is built up separately by ospf_write(). This means, that we must
        !          3364:    * reduce the "affordable" size just calculated by length of an IP header.
        !          3365:    * This makes sure, that even if we manage to fill the payload with LSA data
        !          3366:    * completely, the final packet (our data plus IP header) still fits into
        !          3367:    * outgoing interface MTU. This correction isn't really meaningful for an
        !          3368:    * oversized LSA, but for consistency the correction is done for both cases.
        !          3369:    *
        !          3370:    * P.S. OSPF_MAX_PACKET_SIZE above already includes IP header size
        !          3371:    */
        !          3372:   return ospf_packet_new (size - sizeof (struct ip));
        !          3373: }
        !          3374: 
        !          3375: static void
        !          3376: ospf_ls_upd_queue_send (struct ospf_interface *oi, struct list *update,
        !          3377:                        struct in_addr addr)
        !          3378: {
        !          3379:   struct ospf_packet *op;
        !          3380:   u_int16_t length = OSPF_HEADER_SIZE;
        !          3381: 
        !          3382:   if (IS_DEBUG_OSPF_EVENT)
        !          3383:     zlog_debug ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
        !          3384:   
        !          3385:   op = ospf_ls_upd_packet_new (update, oi);
        !          3386: 
        !          3387:   /* Prepare OSPF common header. */
        !          3388:   ospf_make_header (OSPF_MSG_LS_UPD, oi, op->s);
        !          3389: 
        !          3390:   /* Prepare OSPF Link State Update body.
        !          3391:    * Includes Type-7 translation. 
        !          3392:    */
        !          3393:   length += ospf_make_ls_upd (oi, update, op->s);
        !          3394: 
        !          3395:   /* Fill OSPF header. */
        !          3396:   ospf_fill_header (oi, op->s, length);
        !          3397: 
        !          3398:   /* Set packet length. */
        !          3399:   op->length = length;
        !          3400: 
        !          3401:   /* Decide destination address. */
        !          3402:   if (oi->type == OSPF_IFTYPE_POINTOPOINT) 
        !          3403:     op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
        !          3404:   else
        !          3405:     op->dst.s_addr = addr.s_addr;
        !          3406: 
        !          3407:   /* Add packet to the interface output queue. */
        !          3408:   ospf_packet_add (oi, op);
        !          3409: 
        !          3410:   /* Hook thread to write packet. */
        !          3411:   OSPF_ISM_WRITE_ON (oi->ospf);
        !          3412: }
        !          3413: 
        !          3414: static int
        !          3415: ospf_ls_upd_send_queue_event (struct thread *thread)
        !          3416: {
        !          3417:   struct ospf_interface *oi = THREAD_ARG(thread);
        !          3418:   struct route_node *rn;
        !          3419:   struct route_node *rnext;
        !          3420:   struct list *update;
        !          3421:   char again = 0;
        !          3422:   
        !          3423:   oi->t_ls_upd_event = NULL;
        !          3424: 
        !          3425:   if (IS_DEBUG_OSPF_EVENT)
        !          3426:     zlog_debug ("ospf_ls_upd_send_queue start");
        !          3427: 
        !          3428:   for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext)
        !          3429:     {
        !          3430:       rnext = route_next (rn);
        !          3431:       
        !          3432:       if (rn->info == NULL)
        !          3433:         continue;
        !          3434:       
        !          3435:       update = (struct list *)rn->info;
        !          3436: 
        !          3437:       ospf_ls_upd_queue_send (oi, update, rn->p.u.prefix4);
        !          3438:       
        !          3439:       /* list might not be empty. */
        !          3440:       if (listcount(update) == 0)
        !          3441:         {
        !          3442:           list_delete (rn->info);
        !          3443:           rn->info = NULL;
        !          3444:           route_unlock_node (rn);
        !          3445:         }
        !          3446:       else
        !          3447:         again = 1;
        !          3448:     }
        !          3449: 
        !          3450:   if (again != 0)
        !          3451:     {
        !          3452:       if (IS_DEBUG_OSPF_EVENT)
        !          3453:         zlog_debug ("ospf_ls_upd_send_queue: update lists not cleared,"
        !          3454:                    " %d nodes to try again, raising new event", again);
        !          3455:       oi->t_ls_upd_event = 
        !          3456:         thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
        !          3457:     }
        !          3458: 
        !          3459:   if (IS_DEBUG_OSPF_EVENT)
        !          3460:     zlog_debug ("ospf_ls_upd_send_queue stop");
        !          3461:   
        !          3462:   return 0;
        !          3463: }
        !          3464: 
        !          3465: void
        !          3466: ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
        !          3467: {
        !          3468:   struct ospf_interface *oi;
        !          3469:   struct ospf_lsa *lsa;
        !          3470:   struct prefix_ipv4 p;
        !          3471:   struct route_node *rn;
        !          3472:   struct listnode *node;
        !          3473:   
        !          3474:   oi = nbr->oi;
        !          3475: 
        !          3476:   p.family = AF_INET;
        !          3477:   p.prefixlen = IPV4_MAX_BITLEN;
        !          3478:   
        !          3479:   /* Decide destination address. */
        !          3480:   if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !          3481:     p.prefix = oi->vl_data->peer_addr;
        !          3482:   else if (oi->type == OSPF_IFTYPE_POINTOPOINT) 
        !          3483:      p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
        !          3484:   else if (flag == OSPF_SEND_PACKET_DIRECT)
        !          3485:      p.prefix = nbr->address.u.prefix4;
        !          3486:   else if (oi->state == ISM_DR || oi->state == ISM_Backup)
        !          3487:      p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
        !          3488:   else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
        !          3489:      p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
        !          3490:   else
        !          3491:      p.prefix.s_addr = htonl (OSPF_ALLDROUTERS);
        !          3492: 
        !          3493:   if (oi->type == OSPF_IFTYPE_NBMA)
        !          3494:     {
        !          3495:       if (flag == OSPF_SEND_PACKET_INDIRECT)
        !          3496:        zlog_warn ("* LS-Update is directly sent on NBMA network.");
        !          3497:       if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr))
        !          3498:        zlog_warn ("* LS-Update is sent to myself.");
        !          3499:     }
        !          3500: 
        !          3501:   rn = route_node_get (oi->ls_upd_queue, (struct prefix *) &p);
        !          3502: 
        !          3503:   if (rn->info == NULL)
        !          3504:     rn->info = list_new ();
        !          3505: 
        !          3506:   for (ALL_LIST_ELEMENTS_RO (update, node, lsa))
        !          3507:     listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */
        !          3508: 
        !          3509:   if (oi->t_ls_upd_event == NULL)
        !          3510:     oi->t_ls_upd_event =
        !          3511:       thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
        !          3512: }
        !          3513: 
        !          3514: static void
        !          3515: ospf_ls_ack_send_list (struct ospf_interface *oi, struct list *ack,
        !          3516:                       struct in_addr dst)
        !          3517: {
        !          3518:   struct ospf_packet *op;
        !          3519:   u_int16_t length = OSPF_HEADER_SIZE;
        !          3520: 
        !          3521:   op = ospf_packet_new (oi->ifp->mtu);
        !          3522: 
        !          3523:   /* Prepare OSPF common header. */
        !          3524:   ospf_make_header (OSPF_MSG_LS_ACK, oi, op->s);
        !          3525: 
        !          3526:   /* Prepare OSPF Link State Acknowledgment body. */
        !          3527:   length += ospf_make_ls_ack (oi, ack, op->s);
        !          3528: 
        !          3529:   /* Fill OSPF header. */
        !          3530:   ospf_fill_header (oi, op->s, length);
        !          3531: 
        !          3532:   /* Set packet length. */
        !          3533:   op->length = length;
        !          3534: 
        !          3535:   /* Set destination IP address. */
        !          3536:   op->dst = dst;
        !          3537:   
        !          3538:   /* Add packet to the interface output queue. */
        !          3539:   ospf_packet_add (oi, op);
        !          3540: 
        !          3541:   /* Hook thread to write packet. */
        !          3542:   OSPF_ISM_WRITE_ON (oi->ospf);
        !          3543: }
        !          3544: 
        !          3545: static int
        !          3546: ospf_ls_ack_send_event (struct thread *thread)
        !          3547: {
        !          3548:   struct ospf_interface *oi = THREAD_ARG (thread);
        !          3549: 
        !          3550:   oi->t_ls_ack_direct = NULL;
        !          3551:   
        !          3552:   while (listcount (oi->ls_ack_direct.ls_ack))
        !          3553:     ospf_ls_ack_send_list (oi, oi->ls_ack_direct.ls_ack,
        !          3554:                           oi->ls_ack_direct.dst);
        !          3555: 
        !          3556:   return 0;
        !          3557: }
        !          3558: 
        !          3559: void
        !          3560: ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
        !          3561: {
        !          3562:   struct ospf_interface *oi = nbr->oi;
        !          3563: 
        !          3564:   if (listcount (oi->ls_ack_direct.ls_ack) == 0)
        !          3565:     oi->ls_ack_direct.dst = nbr->address.u.prefix4;
        !          3566:   
        !          3567:   listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa));
        !          3568:   
        !          3569:   if (oi->t_ls_ack_direct == NULL)
        !          3570:     oi->t_ls_ack_direct =
        !          3571:       thread_add_event (master, ospf_ls_ack_send_event, oi, 0);
        !          3572: }
        !          3573: 
        !          3574: /* Send Link State Acknowledgment delayed. */
        !          3575: void
        !          3576: ospf_ls_ack_send_delayed (struct ospf_interface *oi)
        !          3577: {
        !          3578:   struct in_addr dst;
        !          3579:   
        !          3580:   /* Decide destination address. */
        !          3581:   /* RFC2328 Section 13.5                           On non-broadcast
        !          3582:        networks, delayed Link State Acknowledgment packets must be
        !          3583:        unicast separately over each adjacency (i.e., neighbor whose
        !          3584:        state is >= Exchange).  */
        !          3585:   if (oi->type == OSPF_IFTYPE_NBMA)
        !          3586:     {
        !          3587:       struct ospf_neighbor *nbr;
        !          3588:       struct route_node *rn;
        !          3589: 
        !          3590:       for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
        !          3591:        if ((nbr = rn->info) != NULL)
        !          3592:          if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
        !          3593:            while (listcount (oi->ls_ack))
        !          3594:              ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4);
        !          3595:       return;
        !          3596:     }
        !          3597:   if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !          3598:     dst.s_addr = oi->vl_data->peer_addr.s_addr;
        !          3599:   else if (oi->state == ISM_DR || oi->state == ISM_Backup)
        !          3600:     dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
        !          3601:   else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
        !          3602:     dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
        !          3603:   else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
        !          3604:     dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
        !          3605:   else
        !          3606:     dst.s_addr = htonl (OSPF_ALLDROUTERS);
        !          3607: 
        !          3608:   while (listcount (oi->ls_ack))
        !          3609:     ospf_ls_ack_send_list (oi, oi->ls_ack, dst);
        !          3610: }

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