Annotation of embedaddon/quagga/isisd/isis_pdu.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * IS-IS Rout(e)ing protocol - isis_pdu.c   
        !             3:  *                             PDU processing
        !             4:  *
        !             5:  * Copyright (C) 2001,2002   Sampo Saaristo
        !             6:  *                           Tampere University of Technology      
        !             7:  *                           Institute of Communications Engineering
        !             8:  *
        !             9:  * This program is free software; you can redistribute it and/or modify it 
        !            10:  * under the terms of the GNU General Public Licenseas published by the Free 
        !            11:  * Software Foundation; either version 2 of the License, or (at your option) 
        !            12:  * any later version.
        !            13:  *
        !            14:  * This program is distributed in the hope that it will be useful,but WITHOUT 
        !            15:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
        !            17:  * more details.
        !            18: 
        !            19:  * You should have received a copy of the GNU General Public License along 
        !            20:  * with this program; if not, write to the Free Software Foundation, Inc., 
        !            21:  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
        !            22:  */
        !            23: 
        !            24: #include <zebra.h>
        !            25: 
        !            26: #include "memory.h"
        !            27: #include "thread.h"
        !            28: #include "linklist.h"
        !            29: #include "log.h"
        !            30: #include "stream.h"
        !            31: #include "vty.h"
        !            32: #include "hash.h"
        !            33: #include "prefix.h"
        !            34: #include "if.h"
        !            35: #include "checksum.h"
        !            36: 
        !            37: #include "isisd/dict.h"
        !            38: #include "isisd/include-netbsd/iso.h"
        !            39: #include "isisd/isis_constants.h"
        !            40: #include "isisd/isis_common.h"
        !            41: #include "isisd/isis_adjacency.h"
        !            42: #include "isisd/isis_circuit.h"
        !            43: #include "isisd/isis_network.h"
        !            44: #include "isisd/isis_misc.h"
        !            45: #include "isisd/isis_dr.h"
        !            46: #include "isisd/isis_flags.h"
        !            47: #include "isisd/isis_tlv.h"
        !            48: #include "isisd/isisd.h"
        !            49: #include "isisd/isis_dynhn.h"
        !            50: #include "isisd/isis_lsp.h"
        !            51: #include "isisd/isis_pdu.h"
        !            52: #include "isisd/iso_checksum.h"
        !            53: #include "isisd/isis_csm.h"
        !            54: #include "isisd/isis_events.h"
        !            55: 
        !            56: extern struct thread_master *master;
        !            57: extern struct isis *isis;
        !            58: 
        !            59: #define ISIS_MINIMUM_FIXED_HDR_LEN 15
        !            60: #define ISIS_MIN_PDU_LEN           13  /* partial seqnum pdu with id_len=2 */
        !            61: 
        !            62: #ifndef PNBBY
        !            63: #define PNBBY 8
        !            64: #endif /* PNBBY */
        !            65: 
        !            66: /* Utility mask array. */
        !            67: static const u_char maskbit[] = {
        !            68:   0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
        !            69: };
        !            70: 
        !            71: /*
        !            72:  * HELPER FUNCS
        !            73:  */
        !            74: 
        !            75: /*
        !            76:  * Compares two sets of area addresses
        !            77:  */
        !            78: static int
        !            79: area_match (struct list *left, struct list *right)
        !            80: {
        !            81:   struct area_addr *addr1, *addr2;
        !            82:   struct listnode *node1, *node2;
        !            83: 
        !            84:   for (ALL_LIST_ELEMENTS_RO (left, node1, addr1))
        !            85:   {
        !            86:     for (ALL_LIST_ELEMENTS_RO (right, node2, addr2))
        !            87:     {
        !            88:       if (addr1->addr_len == addr2->addr_len &&
        !            89:          !memcmp (addr1->area_addr, addr2->area_addr, (int) addr1->addr_len))
        !            90:        return 1;               /* match */
        !            91:     }
        !            92:   }
        !            93: 
        !            94:   return 0;                    /* mismatch */
        !            95: }
        !            96: 
        !            97: /*
        !            98:  * Check if ip2 is in the ip1's network (function like Prefix.h:prefix_match() )
        !            99:  * param ip1            the IS interface ip address structure
        !           100:  * param ip2            the IIH's ip address
        !           101:  * return  0            the IIH's IP is not in the IS's subnetwork
        !           102:  *         1            the IIH's IP is in the IS's subnetwork
        !           103:  */
        !           104: static int
        !           105: ip_same_subnet (struct prefix_ipv4 *ip1, struct in_addr *ip2)
        !           106: {
        !           107:   u_char *addr1, *addr2;
        !           108:   int shift, offset, offsetloop;
        !           109:   int len;
        !           110: 
        !           111:   addr1 = (u_char *) & ip1->prefix.s_addr;
        !           112:   addr2 = (u_char *) & ip2->s_addr;
        !           113:   len = ip1->prefixlen;
        !           114: 
        !           115:   shift = len % PNBBY;
        !           116:   offsetloop = offset = len / PNBBY;
        !           117: 
        !           118:   while (offsetloop--)
        !           119:     if (addr1[offsetloop] != addr2[offsetloop])
        !           120:       return 0;
        !           121: 
        !           122:   if (shift)
        !           123:     if (maskbit[shift] & (addr1[offset] ^ addr2[offset]))
        !           124:       return 0;
        !           125: 
        !           126:   return 1;                    /* match  */
        !           127: }
        !           128: 
        !           129: /*
        !           130:  * Compares two set of ip addresses
        !           131:  * param left     the local interface's ip addresses
        !           132:  * param right    the iih interface's ip address
        !           133:  * return         0   no match;
        !           134:  *                1   match;
        !           135:  */
        !           136: static int
        !           137: ip_match (struct list *left, struct list *right)
        !           138: {
        !           139:   struct prefix_ipv4 *ip1;
        !           140:   struct in_addr *ip2;
        !           141:   struct listnode *node1, *node2;
        !           142: 
        !           143:   if ((left == NULL) || (right == NULL))
        !           144:     return 0;
        !           145:   
        !           146:   for (ALL_LIST_ELEMENTS_RO (left, node1, ip1))
        !           147:   {
        !           148:     for (ALL_LIST_ELEMENTS_RO (right, node2, ip2))
        !           149:     {
        !           150:       if (ip_same_subnet (ip1, ip2))
        !           151:        {
        !           152:          return 1;             /* match */
        !           153:        }
        !           154:     }
        !           155: 
        !           156:   }
        !           157:   return 0;
        !           158: }
        !           159: 
        !           160: /*
        !           161:  * Checks whether we should accept a PDU of given level 
        !           162:  */
        !           163: static int
        !           164: accept_level (int level, int circuit_t)
        !           165: {
        !           166:   int retval = ((circuit_t & level) == level); /* simple approach */
        !           167: 
        !           168:   return retval;
        !           169: }
        !           170: 
        !           171: int
        !           172: authentication_check (struct isis_passwd *one, struct isis_passwd *theother)
        !           173: {
        !           174:   if (one->type != theother->type)
        !           175:     {
        !           176:       zlog_warn ("Unsupported authentication type %d", theother->type);
        !           177:       return 1;                        /* Auth fail (different authentication types) */
        !           178:     }
        !           179:   switch (one->type)
        !           180:     {
        !           181:     case ISIS_PASSWD_TYPE_CLEARTXT:
        !           182:       if (one->len != theother->len)
        !           183:        return 1;               /* Auth fail () - passwd len mismatch */
        !           184:       return memcmp (one->passwd, theother->passwd, one->len);
        !           185:       break;
        !           186:     default:
        !           187:       zlog_warn ("Unsupported authentication type");
        !           188:       break;
        !           189:     }
        !           190:   return 0;                    /* Auth pass */
        !           191: }
        !           192: 
        !           193: /*
        !           194:  * Processing helper functions
        !           195:  */
        !           196: static void
        !           197: tlvs_to_adj_nlpids (struct tlvs *tlvs, struct isis_adjacency *adj)
        !           198: {
        !           199:   int i;
        !           200:   struct nlpids *tlv_nlpids;
        !           201: 
        !           202:   if (tlvs->nlpids)
        !           203:     {
        !           204: 
        !           205:       tlv_nlpids = tlvs->nlpids;
        !           206: 
        !           207:       adj->nlpids.count = tlv_nlpids->count;
        !           208: 
        !           209:       for (i = 0; i < tlv_nlpids->count; i++)
        !           210:        {
        !           211:          adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i];
        !           212:        }
        !           213:     }
        !           214: }
        !           215: 
        !           216: static void
        !           217: del_ip_addr (void *val)
        !           218: {
        !           219:   XFREE (MTYPE_ISIS_TMP, val);
        !           220: }
        !           221: 
        !           222: static void
        !           223: tlvs_to_adj_ipv4_addrs (struct tlvs *tlvs, struct isis_adjacency *adj)
        !           224: {
        !           225:   struct listnode *node;
        !           226:   struct in_addr *ipv4_addr, *malloced;
        !           227: 
        !           228:   if (adj->ipv4_addrs)
        !           229:     {
        !           230:       adj->ipv4_addrs->del = del_ip_addr;
        !           231:       list_delete (adj->ipv4_addrs);
        !           232:     }
        !           233:   adj->ipv4_addrs = list_new ();
        !           234:   if (tlvs->ipv4_addrs)
        !           235:     {
        !           236:       for (ALL_LIST_ELEMENTS_RO (tlvs->ipv4_addrs, node, ipv4_addr))
        !           237:       {
        !           238:        malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in_addr));
        !           239:        memcpy (malloced, ipv4_addr, sizeof (struct in_addr));
        !           240:        listnode_add (adj->ipv4_addrs, malloced);
        !           241:       }
        !           242:     }
        !           243: }
        !           244: 
        !           245: #ifdef HAVE_IPV6
        !           246: static void
        !           247: tlvs_to_adj_ipv6_addrs (struct tlvs *tlvs, struct isis_adjacency *adj)
        !           248: {
        !           249:   struct listnode *node;
        !           250:   struct in6_addr *ipv6_addr, *malloced;
        !           251: 
        !           252:   if (adj->ipv6_addrs)
        !           253:     {
        !           254:       adj->ipv6_addrs->del = del_ip_addr;
        !           255:       list_delete (adj->ipv6_addrs);
        !           256:     }
        !           257:   adj->ipv6_addrs = list_new ();
        !           258:   if (tlvs->ipv6_addrs)
        !           259:     {
        !           260:       for (ALL_LIST_ELEMENTS_RO (tlvs->ipv6_addrs, node, ipv6_addr))
        !           261:       {
        !           262:        malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in6_addr));
        !           263:        memcpy (malloced, ipv6_addr, sizeof (struct in6_addr));
        !           264:        listnode_add (adj->ipv6_addrs, malloced);
        !           265:       }
        !           266:     }
        !           267: 
        !           268: }
        !           269: #endif /* HAVE_IPV6 */
        !           270: 
        !           271: /*
        !           272:  *  RECEIVE SIDE                           
        !           273:  */
        !           274: 
        !           275: /*
        !           276:  * Process P2P IIH
        !           277:  * ISO - 10589
        !           278:  * Section 8.2.5 - Receiving point-to-point IIH PDUs
        !           279:  *
        !           280:  */
        !           281: static int
        !           282: process_p2p_hello (struct isis_circuit *circuit)
        !           283: {
        !           284:   int retval = ISIS_OK;
        !           285:   struct isis_p2p_hello_hdr *hdr;
        !           286:   struct isis_adjacency *adj;
        !           287:   u_int32_t expected = 0, found;
        !           288:   struct tlvs tlvs;
        !           289: 
        !           290:   if ((stream_get_endp (circuit->rcv_stream) -
        !           291:        stream_get_getp (circuit->rcv_stream)) < ISIS_P2PHELLO_HDRLEN)
        !           292:     {
        !           293:       zlog_warn ("Packet too short");
        !           294:       return ISIS_WARNING;
        !           295:     }
        !           296: 
        !           297:   /* 8.2.5.1 PDU acceptance tests */
        !           298: 
        !           299:   /* 8.2.5.1 a) external domain untrue */
        !           300:   /* FIXME: not useful at all?         */
        !           301: 
        !           302:   /* 8.2.5.1 b) ID Length mismatch */
        !           303:   /* checked at the handle_pdu     */
        !           304: 
        !           305:   /* 8.2.5.2 IIH PDU Processing */
        !           306: 
        !           307:   /* 8.2.5.2 a) 1) Maximum Area Addresses */
        !           308:   /* Already checked, and can also be ommited */
        !           309: 
        !           310:   /*
        !           311:    * Get the header
        !           312:    */
        !           313:   hdr = (struct isis_p2p_hello_hdr *) STREAM_PNT (circuit->rcv_stream);
        !           314:   circuit->rcv_stream->getp += ISIS_P2PHELLO_HDRLEN;
        !           315: 
        !           316:   /*  hdr.circuit_t = stream_getc (stream);
        !           317:      stream_get (hdr.source_id, stream, ISIS_SYS_ID_LEN);
        !           318:      hdr.hold_time = stream_getw (stream);
        !           319:      hdr.pdu_len   = stream_getw (stream);
        !           320:      hdr.local_id  = stream_getc (stream); */
        !           321: 
        !           322:   /*
        !           323:    * My interpertation of the ISO, if no adj exists we will create one for 
        !           324:    * the circuit
        !           325:    */
        !           326: 
        !           327:   if (isis->debugs & DEBUG_ADJ_PACKETS)
        !           328:     {
        !           329:       zlog_debug ("ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s,"
        !           330:                  " cir id %02d, length %d",
        !           331:                  circuit->area->area_tag, circuit->interface->name,
        !           332:                  circuit_t2string (circuit->circuit_is_type),
        !           333:                  circuit->circuit_id, ntohs (hdr->pdu_len));
        !           334:     }
        !           335: 
        !           336:   adj = circuit->u.p2p.neighbor;
        !           337:   if (!adj)
        !           338:     {
        !           339:       adj = isis_new_adj (hdr->source_id, NULL, 0, circuit);
        !           340:       if (adj == NULL)
        !           341:        return ISIS_ERROR;
        !           342:       circuit->u.p2p.neighbor = adj;
        !           343:       isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
        !           344:       adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
        !           345:     }
        !           346: 
        !           347:   /* 8.2.6 Monitoring point-to-point adjacencies */
        !           348:   adj->hold_time = ntohs (hdr->hold_time);
        !           349:   adj->last_upd = time (NULL);
        !           350: 
        !           351:   /*
        !           352:    * Lets get the TLVS now
        !           353:    */
        !           354:   expected |= TLVFLAG_AREA_ADDRS;
        !           355:   expected |= TLVFLAG_AUTH_INFO;
        !           356:   expected |= TLVFLAG_NLPID;
        !           357:   expected |= TLVFLAG_IPV4_ADDR;
        !           358:   expected |= TLVFLAG_IPV6_ADDR;
        !           359: 
        !           360:   retval = parse_tlvs (circuit->area->area_tag,
        !           361:                       STREAM_PNT (circuit->rcv_stream),
        !           362:                       ntohs (hdr->pdu_len) - ISIS_P2PHELLO_HDRLEN
        !           363:                       - ISIS_FIXED_HDR_LEN, &expected, &found, &tlvs);
        !           364: 
        !           365:   if (retval > ISIS_WARNING)
        !           366:     {
        !           367:       free_tlvs (&tlvs);
        !           368:       return retval;
        !           369:     };
        !           370: 
        !           371:   /* 8.2.5.1 c) Authentication */
        !           372:   if (circuit->passwd.type)
        !           373:     {
        !           374:       if (!(found & TLVFLAG_AUTH_INFO) ||
        !           375:          authentication_check (&circuit->passwd, &tlvs.auth_info))
        !           376:        {
        !           377:          isis_event_auth_failure (circuit->area->area_tag,
        !           378:                                   "P2P hello authentication failure",
        !           379:                                   hdr->source_id);
        !           380:          return ISIS_OK;
        !           381:        }
        !           382:     }
        !           383: 
        !           384:   /* we do this now because the adj may not survive till the end... */
        !           385: 
        !           386:   /* we need to copy addresses to the adj */
        !           387:   tlvs_to_adj_ipv4_addrs (&tlvs, adj);
        !           388: 
        !           389: #ifdef HAVE_IPV6
        !           390:   tlvs_to_adj_ipv6_addrs (&tlvs, adj);
        !           391: #endif /* HAVE_IPV6 */
        !           392: 
        !           393:   /* lets take care of the expiry */
        !           394:   THREAD_TIMER_OFF (adj->t_expire);
        !           395:   THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
        !           396:                   (long) adj->hold_time);
        !           397: 
        !           398:   /* 8.2.5.2 a) a match was detected */
        !           399:   if (area_match (circuit->area->area_addrs, tlvs.area_addrs))
        !           400:     {
        !           401:       /* 8.2.5.2 a) 2) If the system is L1 - table 5 */
        !           402:       if (circuit->area->is_type == IS_LEVEL_1)
        !           403:        {
        !           404:          switch (hdr->circuit_t)
        !           405:            {
        !           406:            case IS_LEVEL_1:
        !           407:            case IS_LEVEL_1_AND_2:
        !           408:              if (adj->adj_state != ISIS_ADJ_UP)
        !           409:                {
        !           410:                  /* (4) adj state up */
        !           411:                  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
        !           412:                  /* (5) adj usage level 1 */
        !           413:                  adj->adj_usage = ISIS_ADJ_LEVEL1;
        !           414:                }
        !           415:              else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
        !           416:                {
        !           417:                  ;             /* accept */
        !           418:                }
        !           419:              break;
        !           420:            case IS_LEVEL_2:
        !           421:              if (adj->adj_state != ISIS_ADJ_UP)
        !           422:                {
        !           423:                  /* (7) reject - wrong system type event */
        !           424:                  zlog_warn ("wrongSystemType");
        !           425:                  return ISIS_WARNING;  /* Reject */
        !           426:                }
        !           427:              else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
        !           428:                {
        !           429:                  /* (6) down - wrong system */
        !           430:                  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
        !           431:                }
        !           432:              break;
        !           433:            }
        !           434:        }
        !           435: 
        !           436:       /* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */
        !           437:       if (circuit->area->is_type == IS_LEVEL_1_AND_2)
        !           438:        {
        !           439:          switch (hdr->circuit_t)
        !           440:            {
        !           441:            case IS_LEVEL_1:
        !           442:              if (adj->adj_state != ISIS_ADJ_UP)
        !           443:                {
        !           444:                  /* (6) adj state up */
        !           445:                  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
        !           446:                  /* (7) adj usage level 1 */
        !           447:                  adj->adj_usage = ISIS_ADJ_LEVEL1;
        !           448:                }
        !           449:              else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
        !           450:                {
        !           451:                  ;             /* accept */
        !           452:                }
        !           453:              else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
        !           454:                       (adj->adj_usage == ISIS_ADJ_LEVEL2))
        !           455:                {
        !           456:                  /* (8) down - wrong system */
        !           457:                  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
        !           458:                }
        !           459:              break;
        !           460:            case IS_LEVEL_2:
        !           461:              if (adj->adj_state != ISIS_ADJ_UP)
        !           462:                {
        !           463:                  /* (6) adj state up */
        !           464:                  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
        !           465:                  /* (9) adj usage level 2 */
        !           466:                  adj->adj_usage = ISIS_ADJ_LEVEL2;
        !           467:                }
        !           468:              else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
        !           469:                       (adj->adj_usage == ISIS_ADJ_LEVEL1AND2))
        !           470:                {
        !           471:                  /* (8) down - wrong system */
        !           472:                  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
        !           473:                }
        !           474:              else if (adj->adj_usage == ISIS_ADJ_LEVEL2)
        !           475:                {
        !           476:                  ;             /* Accept */
        !           477:                }
        !           478:              break;
        !           479:            case IS_LEVEL_1_AND_2:
        !           480:              if (adj->adj_state != ISIS_ADJ_UP)
        !           481:                {
        !           482:                  /* (6) adj state up */
        !           483:                  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
        !           484:                  /* (10) adj usage level 1 */
        !           485:                  adj->adj_usage = ISIS_ADJ_LEVEL1AND2;
        !           486:                }
        !           487:              else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
        !           488:                       (adj->adj_usage == ISIS_ADJ_LEVEL2))
        !           489:                {
        !           490:                  /* (8) down - wrong system */
        !           491:                  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
        !           492:                }
        !           493:              else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
        !           494:                {
        !           495:                  ;             /* Accept */
        !           496:                }
        !           497:              break;
        !           498:            }
        !           499:        }
        !           500: 
        !           501:       /* 8.2.5.2 a) 4) If the system is L2 - table 7 */
        !           502:       if (circuit->area->is_type == IS_LEVEL_2)
        !           503:        {
        !           504:          switch (hdr->circuit_t)
        !           505:            {
        !           506:            case IS_LEVEL_1:
        !           507:              if (adj->adj_state != ISIS_ADJ_UP)
        !           508:                {
        !           509:                  /* (5) reject - wrong system type event */
        !           510:                  zlog_warn ("wrongSystemType");
        !           511:                  return ISIS_WARNING;  /* Reject */
        !           512:                }
        !           513:              else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
        !           514:                       (adj->adj_usage == ISIS_ADJ_LEVEL2))
        !           515:                {
        !           516:                  /* (6) down - wrong system */
        !           517:                  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
        !           518:                }
        !           519:              break;
        !           520:            case IS_LEVEL_1_AND_2:
        !           521:            case IS_LEVEL_2:
        !           522:              if (adj->adj_state != ISIS_ADJ_UP)
        !           523:                {
        !           524:                  /* (7) adj state up */
        !           525:                  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
        !           526:                  /* (8) adj usage level 2 */
        !           527:                  adj->adj_usage = ISIS_ADJ_LEVEL2;
        !           528:                }
        !           529:              else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
        !           530:                {
        !           531:                  /* (6) down - wrong system */
        !           532:                  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
        !           533:                }
        !           534:              else if (adj->adj_usage == ISIS_ADJ_LEVEL2)
        !           535:                {
        !           536:                  ;             /* Accept */
        !           537:                }
        !           538:              break;
        !           539:            }
        !           540:        }
        !           541:     }
        !           542:   /* 8.2.5.2 b) if no match was detected */
        !           543:   else
        !           544:     {
        !           545:       if (circuit->area->is_type == IS_LEVEL_1)
        !           546:        {
        !           547:          /* 8.2.5.2 b) 1) is_type L1 and adj is not up */
        !           548:          if (adj->adj_state != ISIS_ADJ_UP)
        !           549:            {
        !           550:              isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
        !           551:              /* 8.2.5.2 b) 2)is_type L1 and adj is up */
        !           552:            }
        !           553:          else
        !           554:            {
        !           555:              isis_adj_state_change (adj, ISIS_ADJ_DOWN,
        !           556:                                     "Down - Area Mismatch");
        !           557:            }
        !           558:        }
        !           559:       /* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */
        !           560:       else
        !           561:        {
        !           562:          switch (hdr->circuit_t)
        !           563:            {
        !           564:            case IS_LEVEL_1:
        !           565:              if (adj->adj_state != ISIS_ADJ_UP)
        !           566:                {
        !           567:                  /* (6) reject - Area Mismatch event */
        !           568:                  zlog_warn ("AreaMismatch");
        !           569:                  return ISIS_WARNING;  /* Reject */
        !           570:                }
        !           571:              else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
        !           572:                {
        !           573:                  /* (7) down - area mismatch */
        !           574:                  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
        !           575: 
        !           576:                }
        !           577:              else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
        !           578:                       (adj->adj_usage == ISIS_ADJ_LEVEL2))
        !           579:                {
        !           580:                  /* (7) down - wrong system */
        !           581:                  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
        !           582:                }
        !           583:              break;
        !           584:            case IS_LEVEL_1_AND_2:
        !           585:            case IS_LEVEL_2:
        !           586:              if (adj->adj_state != ISIS_ADJ_UP)
        !           587:                {
        !           588:                  /* (8) adj state up */
        !           589:                  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
        !           590:                  /* (9) adj usage level 2 */
        !           591:                  adj->adj_usage = ISIS_ADJ_LEVEL2;
        !           592:                }
        !           593:              else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
        !           594:                {
        !           595:                  /* (7) down - wrong system */
        !           596:                  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
        !           597:                }
        !           598:              else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
        !           599:                {
        !           600:                  if (hdr->circuit_t == IS_LEVEL_2)
        !           601:                    {
        !           602:                      /* (7) down - wrong system */
        !           603:                      isis_adj_state_change (adj, ISIS_ADJ_DOWN,
        !           604:                                             "Wrong System");
        !           605:                    }
        !           606:                  else
        !           607:                    {
        !           608:                      /* (7) down - area mismatch */
        !           609:                      isis_adj_state_change (adj, ISIS_ADJ_DOWN,
        !           610:                                             "Area Mismatch");
        !           611:                    }
        !           612:                }
        !           613:              else if (adj->adj_usage == ISIS_ADJ_LEVEL2)
        !           614:                {
        !           615:                  ;             /* Accept */
        !           616:                }
        !           617:              break;
        !           618:            }
        !           619:        }
        !           620:     }
        !           621:   /* 8.2.5.2 c) if the action was up - comparing circuit IDs */
        !           622:   /* FIXME - Missing parts */
        !           623: 
        !           624:   /* some of my own understanding of the ISO, why the heck does
        !           625:    * it not say what should I change the system_type to...
        !           626:    */
        !           627:   switch (adj->adj_usage)
        !           628:     {
        !           629:     case ISIS_ADJ_LEVEL1:
        !           630:       adj->sys_type = ISIS_SYSTYPE_L1_IS;
        !           631:       break;
        !           632:     case ISIS_ADJ_LEVEL2:
        !           633:       adj->sys_type = ISIS_SYSTYPE_L2_IS;
        !           634:       break;
        !           635:     case ISIS_ADJ_LEVEL1AND2:
        !           636:       adj->sys_type = ISIS_SYSTYPE_L2_IS;
        !           637:       break;
        !           638:     case ISIS_ADJ_NONE:
        !           639:       adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
        !           640:       break;
        !           641:     }
        !           642: 
        !           643:   adj->circuit_t = hdr->circuit_t;
        !           644:   adj->level = hdr->circuit_t;
        !           645: 
        !           646:   free_tlvs (&tlvs);
        !           647: 
        !           648:   return retval;
        !           649: }
        !           650: 
        !           651: /*
        !           652:  * Process IS-IS LAN Level 1/2 Hello PDU
        !           653:  */
        !           654: static int
        !           655: process_lan_hello (int level, struct isis_circuit *circuit, u_char * ssnpa)
        !           656: {
        !           657:   int retval = ISIS_OK;
        !           658:   struct isis_lan_hello_hdr hdr;
        !           659:   struct isis_adjacency *adj;
        !           660:   u_int32_t expected = 0, found;
        !           661:   struct tlvs tlvs;
        !           662:   u_char *snpa;
        !           663:   struct listnode *node;
        !           664: 
        !           665:   if ((stream_get_endp (circuit->rcv_stream) -
        !           666:        stream_get_getp (circuit->rcv_stream)) < ISIS_LANHELLO_HDRLEN)
        !           667:     {
        !           668:       zlog_warn ("Packet too short");
        !           669:       return ISIS_WARNING;
        !           670:     }
        !           671: 
        !           672:   if (circuit->ext_domain)
        !           673:     {
        !           674:       zlog_debug ("level %d LAN Hello received over circuit with "
        !           675:                  "externalDomain = true", level);
        !           676:       return ISIS_WARNING;
        !           677:     }
        !           678: 
        !           679:   if (!accept_level (level, circuit->circuit_is_type))
        !           680:     {
        !           681:       if (isis->debugs & DEBUG_ADJ_PACKETS)
        !           682:        {
        !           683:          zlog_debug ("ISIS-Adj (%s): Interface level mismatch, %s",
        !           684:                      circuit->area->area_tag, circuit->interface->name);
        !           685:        }
        !           686:       return ISIS_WARNING;
        !           687:     }
        !           688: 
        !           689: #if 0
        !           690:   /* Cisco's debug message compatability */
        !           691:   if (!accept_level (level, circuit->area->is_type))
        !           692:     {
        !           693:       if (isis->debugs & DEBUG_ADJ_PACKETS)
        !           694:        {
        !           695:          zlog_debug ("ISIS-Adj (%s): is type mismatch",
        !           696:                      circuit->area->area_tag);
        !           697:        }
        !           698:       return ISIS_WARNING;
        !           699:     }
        !           700: #endif
        !           701:   /*
        !           702:    * Fill the header
        !           703:    */
        !           704:   hdr.circuit_t = stream_getc (circuit->rcv_stream);
        !           705:   stream_get (hdr.source_id, circuit->rcv_stream, ISIS_SYS_ID_LEN);
        !           706:   hdr.hold_time = stream_getw (circuit->rcv_stream);
        !           707:   hdr.pdu_len = stream_getw (circuit->rcv_stream);
        !           708:   hdr.prio = stream_getc (circuit->rcv_stream);
        !           709:   stream_get (hdr.lan_id, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1);
        !           710: 
        !           711:   if (hdr.circuit_t != IS_LEVEL_1 && hdr.circuit_t != IS_LEVEL_2 &&
        !           712:       hdr.circuit_t != IS_LEVEL_1_AND_2)
        !           713:     {
        !           714:       zlog_warn ("Level %d LAN Hello with Circuit Type %d", level,
        !           715:                 hdr.circuit_t);
        !           716:       return ISIS_ERROR;
        !           717:     }
        !           718:   /*
        !           719:    * Then get the tlvs
        !           720:    */
        !           721:   expected |= TLVFLAG_AUTH_INFO;
        !           722:   expected |= TLVFLAG_AREA_ADDRS;
        !           723:   expected |= TLVFLAG_LAN_NEIGHS;
        !           724:   expected |= TLVFLAG_NLPID;
        !           725:   expected |= TLVFLAG_IPV4_ADDR;
        !           726:   expected |= TLVFLAG_IPV6_ADDR;
        !           727: 
        !           728:   retval = parse_tlvs (circuit->area->area_tag,
        !           729:                       STREAM_PNT (circuit->rcv_stream),
        !           730:                       hdr.pdu_len - ISIS_LANHELLO_HDRLEN -
        !           731:                       ISIS_FIXED_HDR_LEN, &expected, &found, &tlvs);
        !           732: 
        !           733:   if (retval > ISIS_WARNING)
        !           734:     {
        !           735:       zlog_warn ("parse_tlvs() failed");
        !           736:       goto out;
        !           737:     }
        !           738: 
        !           739:   if (!(found & TLVFLAG_AREA_ADDRS))
        !           740:     {
        !           741:       zlog_warn ("No Area addresses TLV in Level %d LAN IS to IS hello",
        !           742:                 level);
        !           743:       retval = ISIS_WARNING;
        !           744:       goto out;
        !           745:     }
        !           746: 
        !           747:   if (circuit->passwd.type)
        !           748:     {
        !           749:       if (!(found & TLVFLAG_AUTH_INFO) ||
        !           750:          authentication_check (&circuit->passwd, &tlvs.auth_info))
        !           751:        {
        !           752:          isis_event_auth_failure (circuit->area->area_tag,
        !           753:                                   "LAN hello authentication failure",
        !           754:                                   hdr.source_id);
        !           755:          retval = ISIS_WARNING;
        !           756:          goto out;
        !           757:        }
        !           758:     }
        !           759: 
        !           760:   /*
        !           761:    * Accept the level 1 adjacency only if a match between local and
        !           762:    * remote area addresses is found
        !           763:    */
        !           764:   if (level == 1 && !area_match (circuit->area->area_addrs, tlvs.area_addrs))
        !           765:     {
        !           766:       if (isis->debugs & DEBUG_ADJ_PACKETS)
        !           767:        {
        !           768:          zlog_debug ("ISIS-Adj (%s): Area mismatch, level %d IIH on %s",
        !           769:                      circuit->area->area_tag, level,
        !           770:                      circuit->interface->name);
        !           771:        }
        !           772:       retval = ISIS_OK;
        !           773:       goto out;
        !           774:     }
        !           775: 
        !           776:   /* 
        !           777:    * it's own IIH PDU - discard silently 
        !           778:    */
        !           779:   if (!memcmp (circuit->u.bc.snpa, ssnpa, ETH_ALEN))
        !           780:     {
        !           781:       zlog_debug ("ISIS-Adj (%s): it's own IIH PDU - discarded",
        !           782:                  circuit->area->area_tag);
        !           783: 
        !           784:       retval = ISIS_OK;
        !           785:       goto out;
        !           786:     }
        !           787: 
        !           788:   /*
        !           789:    * check if it's own interface ip match iih ip addrs
        !           790:    */
        !           791:   if (!(found & TLVFLAG_IPV4_ADDR)
        !           792:       || !ip_match (circuit->ip_addrs, tlvs.ipv4_addrs))
        !           793:     {
        !           794:       zlog_debug
        !           795:        ("ISIS-Adj: No usable IP interface addresses in LAN IIH from %s\n",
        !           796:         circuit->interface->name);
        !           797:       retval = ISIS_WARNING;
        !           798:       goto out;
        !           799:     }
        !           800: 
        !           801:   adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]);
        !           802:   if (!adj)
        !           803:     {
        !           804:       /*
        !           805:        * Do as in 8.4.2.5
        !           806:        */
        !           807:       adj = isis_new_adj (hdr.source_id, ssnpa, level, circuit);
        !           808:       if (adj == NULL)
        !           809:        {
        !           810:          retval = ISIS_ERROR;
        !           811:          goto out;
        !           812:        }
        !           813: 
        !           814:       adj->level = level;
        !           815:       isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
        !           816: 
        !           817:       if (level == 1)
        !           818:        {
        !           819:          adj->sys_type = ISIS_SYSTYPE_L1_IS;
        !           820:        }
        !           821:       else
        !           822:        {
        !           823:          adj->sys_type = ISIS_SYSTYPE_L2_IS;
        !           824:        }
        !           825:       list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
        !           826:       isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
        !           827:                                 circuit->u.bc.lan_neighs[level - 1]);
        !           828:     }
        !           829: 
        !           830:   if(adj->dis_record[level-1].dis==ISIS_IS_DIS)
        !           831:     switch (level)
        !           832:       {
        !           833:       case 1:
        !           834:        if (memcmp (circuit->u.bc.l1_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1))
        !           835:          {
        !           836:            thread_add_event (master, isis_event_dis_status_change, circuit, 0);
        !           837:            memcpy (&circuit->u.bc.l1_desig_is, hdr.lan_id,
        !           838:                    ISIS_SYS_ID_LEN + 1);
        !           839:          }
        !           840:        break;
        !           841:       case 2:
        !           842:        if (memcmp (circuit->u.bc.l2_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1))
        !           843:          {
        !           844:            thread_add_event (master, isis_event_dis_status_change, circuit, 0);
        !           845:            memcpy (&circuit->u.bc.l2_desig_is, hdr.lan_id,
        !           846:                    ISIS_SYS_ID_LEN + 1);
        !           847:          }
        !           848:        break;
        !           849:       }
        !           850: 
        !           851:   adj->hold_time = hdr.hold_time;
        !           852:   adj->last_upd = time (NULL);
        !           853:   adj->prio[level - 1] = hdr.prio;
        !           854: 
        !           855:   memcpy (adj->lanid, hdr.lan_id, ISIS_SYS_ID_LEN + 1);
        !           856: 
        !           857:   /* which protocol are spoken ??? */
        !           858:   if (found & TLVFLAG_NLPID)
        !           859:     tlvs_to_adj_nlpids (&tlvs, adj);
        !           860: 
        !           861:   /* we need to copy addresses to the adj */
        !           862:   if (found & TLVFLAG_IPV4_ADDR)
        !           863:     tlvs_to_adj_ipv4_addrs (&tlvs, adj);
        !           864: 
        !           865: #ifdef HAVE_IPV6
        !           866:   if (found & TLVFLAG_IPV6_ADDR)
        !           867:     tlvs_to_adj_ipv6_addrs (&tlvs, adj);
        !           868: #endif /* HAVE_IPV6 */
        !           869: 
        !           870:   adj->circuit_t = hdr.circuit_t;
        !           871: 
        !           872:   /* lets take care of the expiry */
        !           873:   THREAD_TIMER_OFF (adj->t_expire);
        !           874:   THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
        !           875:                   (long) adj->hold_time);
        !           876: 
        !           877:   /*
        !           878:    * If the snpa for this circuit is found from LAN Neighbours TLV
        !           879:    * we have two-way communication -> adjacency can be put to state "up"
        !           880:    */
        !           881: 
        !           882:   if (found & TLVFLAG_LAN_NEIGHS)
        !           883:     {
        !           884:       if (adj->adj_state != ISIS_ADJ_UP)
        !           885:        {
        !           886:          for (ALL_LIST_ELEMENTS_RO (tlvs.lan_neighs, node, snpa))
        !           887:            if (!memcmp (snpa, circuit->u.bc.snpa, ETH_ALEN))
        !           888:            {
        !           889:              isis_adj_state_change (adj, ISIS_ADJ_UP,
        !           890:                                     "own SNPA found in LAN Neighbours TLV");
        !           891:            }
        !           892:        }
        !           893:     }
        !           894: 
        !           895: out:
        !           896:   /* DEBUG_ADJ_PACKETS */
        !           897:   if (isis->debugs & DEBUG_ADJ_PACKETS)
        !           898:     {
        !           899:       /* FIXME: is this place right? fix missing info */
        !           900:       zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, "
        !           901:                  "cirID %u, length %ld",
        !           902:                  circuit->area->area_tag,
        !           903:                  level, snpa_print (ssnpa), circuit->interface->name,
        !           904:                  circuit_t2string (circuit->circuit_is_type),
        !           905:                  circuit->circuit_id,
        !           906:                  /* FIXME: use %z when we stop supporting old compilers. */
        !           907:                  (unsigned long) stream_get_endp (circuit->rcv_stream));
        !           908:     }
        !           909: 
        !           910:   free_tlvs (&tlvs);
        !           911: 
        !           912:   return retval;
        !           913: }
        !           914: 
        !           915: /*
        !           916:  * Process Level 1/2 Link State
        !           917:  * ISO - 10589
        !           918:  * Section 7.3.15.1 - Action on receipt of a link state PDU
        !           919:  */
        !           920: static int
        !           921: process_lsp (int level, struct isis_circuit *circuit, u_char * ssnpa)
        !           922: {
        !           923:   struct isis_link_state_hdr *hdr;
        !           924:   struct isis_adjacency *adj = NULL;
        !           925:   struct isis_lsp *lsp, *lsp0 = NULL;
        !           926:   int retval = ISIS_OK, comp = 0;
        !           927:   u_char lspid[ISIS_SYS_ID_LEN + 2];
        !           928:   struct isis_passwd *passwd;
        !           929: 
        !           930:   /* Sanity check - FIXME: move to correct place */
        !           931:   if ((stream_get_endp (circuit->rcv_stream) -
        !           932:        stream_get_getp (circuit->rcv_stream)) < ISIS_LSP_HDR_LEN)
        !           933:     {
        !           934:       zlog_warn ("Packet too short");
        !           935:       return ISIS_WARNING;
        !           936:     }
        !           937: 
        !           938:   /* Reference the header   */
        !           939:   hdr = (struct isis_link_state_hdr *) STREAM_PNT (circuit->rcv_stream);
        !           940: 
        !           941:   if (isis->debugs & DEBUG_UPDATE_PACKETS)
        !           942:     {
        !           943:       zlog_debug ("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, "
        !           944:                  "lifetime %us, len %lu, on %s",
        !           945:                  circuit->area->area_tag,
        !           946:                  level,
        !           947:                  rawlspid_print (hdr->lsp_id),
        !           948:                  ntohl (hdr->seq_num),
        !           949:                  ntohs (hdr->checksum),
        !           950:                  ntohs (hdr->rem_lifetime),
        !           951:                  /* FIXME: use %z when we stop supporting old compilers. */
        !           952:                  (unsigned long) stream_get_endp (circuit->rcv_stream), 
        !           953:                  circuit->interface->name);
        !           954:     }
        !           955: 
        !           956:   assert (ntohs (hdr->pdu_len) > ISIS_LSP_HDR_LEN);
        !           957: 
        !           958:   /* Checksum sanity check - FIXME: move to correct place */
        !           959:   /* 12 = sysid+pdu+remtime */
        !           960:   if (iso_csum_verify (STREAM_PNT (circuit->rcv_stream) + 4,
        !           961:                       ntohs (hdr->pdu_len) - 12, &hdr->checksum))
        !           962:     {
        !           963:       zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x",
        !           964:                  circuit->area->area_tag,
        !           965:                  rawlspid_print (hdr->lsp_id), ntohs (hdr->checksum));
        !           966: 
        !           967:       return ISIS_WARNING;
        !           968:     }
        !           969: 
        !           970:   /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */
        !           971:   if (circuit->ext_domain)
        !           972:     {
        !           973:       zlog_debug
        !           974:        ("ISIS-Upd (%s): LSP %s received at level %d over circuit with "
        !           975:         "externalDomain = true", circuit->area->area_tag,
        !           976:         rawlspid_print (hdr->lsp_id), level);
        !           977: 
        !           978:       return ISIS_WARNING;
        !           979:     }
        !           980: 
        !           981:   /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */
        !           982:   if (!accept_level (level, circuit->circuit_is_type))
        !           983:     {
        !           984:       zlog_debug ("ISIS-Upd (%s): LSP %s received at level %d over circuit of"
        !           985:                  " type %s",
        !           986:                  circuit->area->area_tag,
        !           987:                  rawlspid_print (hdr->lsp_id),
        !           988:                  level, circuit_t2string (circuit->circuit_is_type));
        !           989: 
        !           990:       return ISIS_WARNING;
        !           991:     }
        !           992: 
        !           993:   /* 7.3.15.1 a) 4 - need to make sure IDLength matches */
        !           994: 
        !           995:   /* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use 3 */
        !           996: 
        !           997:   /* 7.3.15.1 a) 7 - password check */
        !           998:   (level == ISIS_LEVEL1) ? (passwd = &circuit->area->area_passwd) :
        !           999:     (passwd = &circuit->area->domain_passwd);
        !          1000:   if (passwd->type)
        !          1001:     {
        !          1002:       if (isis_lsp_authinfo_check (circuit->rcv_stream, circuit->area,
        !          1003:                                   ntohs (hdr->pdu_len), passwd))
        !          1004:        {
        !          1005:          isis_event_auth_failure (circuit->area->area_tag,
        !          1006:                                   "LSP authentication failure", hdr->lsp_id);
        !          1007:          return ISIS_WARNING;
        !          1008:        }
        !          1009:     }
        !          1010:   /* Find the LSP in our database and compare it to this Link State header */
        !          1011:   lsp = lsp_search (hdr->lsp_id, circuit->area->lspdb[level - 1]);
        !          1012:   if (lsp)
        !          1013:     comp = lsp_compare (circuit->area->area_tag, lsp, hdr->seq_num,
        !          1014:                        hdr->checksum, hdr->rem_lifetime);
        !          1015:   if (lsp && (lsp->own_lsp
        !          1016: #ifdef TOPOLOGY_GENERATE
        !          1017:              || lsp->from_topology
        !          1018: #endif /* TOPOLOGY_GENERATE */
        !          1019:       ))
        !          1020:     goto dontcheckadj;
        !          1021: 
        !          1022:   /* 7.3.15.1 a) 6 - Must check that we have an adjacency of the same level  */
        !          1023:   /* for broadcast circuits, snpa should be compared */
        !          1024:   /* FIXME : Point To Point */
        !          1025: 
        !          1026:   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
        !          1027:     {
        !          1028:       adj = isis_adj_lookup_snpa (ssnpa, circuit->u.bc.adjdb[level - 1]);
        !          1029:       if (!adj)
        !          1030:        {
        !          1031:          zlog_debug ("(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, "
        !          1032:                      "lifetime %us on %s",
        !          1033:                      circuit->area->area_tag,
        !          1034:                      rawlspid_print (hdr->lsp_id),
        !          1035:                      ntohl (hdr->seq_num),
        !          1036:                      ntohs (hdr->checksum),
        !          1037:                      ntohs (hdr->rem_lifetime), circuit->interface->name);
        !          1038:          return ISIS_WARNING;  /* Silently discard */
        !          1039:        }
        !          1040:     }
        !          1041: 
        !          1042:   /* for non broadcast, we just need to find same level adj */
        !          1043:   else
        !          1044:     {
        !          1045:       /* If no adj, or no sharing of level */
        !          1046:       if (!circuit->u.p2p.neighbor)
        !          1047:        {
        !          1048:          return ISIS_OK;       /* Silently discard */
        !          1049:        }
        !          1050:       else
        !          1051:        {
        !          1052:          if (((level == 1) &&
        !          1053:               (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL2)) ||
        !          1054:              ((level == 2) &&
        !          1055:               (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL1)))
        !          1056:            return ISIS_WARNING;        /* Silently discard */
        !          1057:        }
        !          1058:     }
        !          1059: dontcheckadj:
        !          1060:   /* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented  */
        !          1061: 
        !          1062:   /* 7.3.15.1 a) 8 - Passwords for level 2 - not implemented  */
        !          1063: 
        !          1064:   /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented  FIXME: do it */
        !          1065: 
        !          1066:   /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */
        !          1067:   if (hdr->rem_lifetime == 0)
        !          1068:     {
        !          1069:       if (!lsp)
        !          1070:        {
        !          1071:          /* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't save */
        !          1072:          /* only needed on explicit update, eg - p2p */
        !          1073:          if (circuit->circ_type == CIRCUIT_T_P2P)
        !          1074:            ack_lsp (hdr, circuit, level);
        !          1075:          return retval;        /* FIXME: do we need a purge? */
        !          1076:        }
        !          1077:       else
        !          1078:        {
        !          1079:          if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))
        !          1080:            {
        !          1081:              /* LSP by some other system -> do 7.3.16.4 b) */
        !          1082:              /* 7.3.16.4 b) 1)  */
        !          1083:              if (comp == LSP_NEWER)
        !          1084:                {
        !          1085:                  lsp_update (lsp, hdr, circuit->rcv_stream, circuit->area,
        !          1086:                              level);
        !          1087:                  /* ii */
        !          1088:                  ISIS_FLAGS_SET_ALL (lsp->SRMflags);
        !          1089:                  /* iii */
        !          1090:                  ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
        !          1091:                  /* v */
        !          1092:                  ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */
        !          1093:                  /* iv */
        !          1094:                  if (circuit->circ_type != CIRCUIT_T_BROADCAST)
        !          1095:                    ISIS_SET_FLAG (lsp->SSNflags, circuit);
        !          1096: 
        !          1097:                }               /* 7.3.16.4 b) 2) */
        !          1098:              else if (comp == LSP_EQUAL)
        !          1099:                {
        !          1100:                  /* i */
        !          1101:                  ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
        !          1102:                  /* ii */
        !          1103:                  if (circuit->circ_type != CIRCUIT_T_BROADCAST)
        !          1104:                    ISIS_SET_FLAG (lsp->SSNflags, circuit);
        !          1105:                }               /* 7.3.16.4 b) 3) */
        !          1106:              else
        !          1107:                {
        !          1108:                  ISIS_SET_FLAG (lsp->SRMflags, circuit);
        !          1109:                  ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
        !          1110:                }
        !          1111:            }
        !          1112:          else
        !          1113:            {
        !          1114:              /* our own LSP -> 7.3.16.4 c) */
        !          1115:              if (LSP_PSEUDO_ID (lsp->lsp_header->lsp_id) !=
        !          1116:                  circuit->circuit_id
        !          1117:                  || (LSP_PSEUDO_ID (lsp->lsp_header->lsp_id) ==
        !          1118:                      circuit->circuit_id
        !          1119:                      && circuit->u.bc.is_dr[level - 1] == 1))
        !          1120:                {
        !          1121:                  lsp->lsp_header->seq_num = htonl (ntohl (hdr->seq_num) + 1);
        !          1122:                  if (isis->debugs & DEBUG_UPDATE_PACKETS)
        !          1123:                    zlog_debug ("LSP LEN: %d",
        !          1124:                                ntohs (lsp->lsp_header->pdu_len));
        !          1125:                  fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
        !          1126:                                   ntohs (lsp->lsp_header->pdu_len) - 12, 12);
        !          1127:                  ISIS_FLAGS_SET_ALL (lsp->SRMflags);
        !          1128:                  if (isis->debugs & DEBUG_UPDATE_PACKETS)
        !          1129:                    zlog_debug ("ISIS-Upd (%s): (1) re-originating LSP %s new "
        !          1130:                                "seq 0x%08x", circuit->area->area_tag,
        !          1131:                                rawlspid_print (hdr->lsp_id),
        !          1132:                                ntohl (lsp->lsp_header->seq_num));
        !          1133:                  lsp->lsp_header->rem_lifetime =
        !          1134:                    htons (isis_jitter
        !          1135:                           (circuit->area->max_lsp_lifetime[level - 1],
        !          1136:                            MAX_AGE_JITTER));
        !          1137:                }
        !          1138:              else
        !          1139:                {
        !          1140:                  /* Got purge for own pseudo-lsp, and we are not DR  */
        !          1141:                  lsp_purge_dr (lsp->lsp_header->lsp_id, circuit, level);
        !          1142:                }
        !          1143:            }
        !          1144:        }
        !          1145:       return retval;
        !          1146:     }
        !          1147:   /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a 
        !          1148:    * purge */
        !          1149:   if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
        !          1150:     {
        !          1151:       if (!lsp)
        !          1152:        {
        !          1153:          /* 7.3.16.4: initiate a purge */
        !          1154:          lsp_purge_non_exist (hdr, circuit->area);
        !          1155:          return ISIS_OK;
        !          1156:        }
        !          1157:       /* 7.3.15.1 d) - If this is our own lsp and we have it */
        !          1158: 
        !          1159:       /* In 7.3.16.1, If an Intermediate system R somewhere in the domain
        !          1160:        * has information that the current sequence number for source S is
        !          1161:        * "greater" than that held by S, ... */
        !          1162: 
        !          1163:       else if (ntohl (hdr->seq_num) > ntohl (lsp->lsp_header->seq_num))
        !          1164:        {
        !          1165:          /* 7.3.16.1  */
        !          1166:          lsp->lsp_header->seq_num = htonl (ntohl (hdr->seq_num) + 1);
        !          1167: 
        !          1168:          fletcher_checksum (STREAM_DATA (lsp->pdu) + 12,
        !          1169:                           ntohs (lsp->lsp_header->pdu_len) - 12, 12);
        !          1170: 
        !          1171:          ISIS_FLAGS_SET_ALL (lsp->SRMflags);
        !          1172:          if (isis->debugs & DEBUG_UPDATE_PACKETS)
        !          1173:            zlog_debug ("ISIS-Upd (%s): (2) re-originating LSP %s new seq "
        !          1174:                        "0x%08x", circuit->area->area_tag,
        !          1175:                        rawlspid_print (hdr->lsp_id),
        !          1176:                        ntohl (lsp->lsp_header->seq_num));
        !          1177:          lsp->lsp_header->rem_lifetime =
        !          1178:            htons (isis_jitter
        !          1179:                   (circuit->area->max_lsp_lifetime[level - 1],
        !          1180:                    MAX_AGE_JITTER));
        !          1181:        }
        !          1182:     }
        !          1183:   else
        !          1184:     {
        !          1185:       /* 7.3.15.1 e) - This lsp originated on another system */
        !          1186: 
        !          1187:       /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */
        !          1188:       if ((!lsp || comp == LSP_NEWER))
        !          1189:        {
        !          1190:          /* i */
        !          1191:          if (lsp)
        !          1192:            {
        !          1193: #ifdef EXTREME_DEBUG
        !          1194:              zlog_debug ("level %d number is - %ld", level,
        !          1195:                          circuit->area->lspdb[level - 1]->dict_nodecount);
        !          1196: #endif /* EXTREME DEBUG */
        !          1197:              lsp_search_and_destroy (hdr->lsp_id,
        !          1198:                                      circuit->area->lspdb[level - 1]);
        !          1199:              /* exists, so we overwrite */
        !          1200: #ifdef EXTREME_DEBUG
        !          1201:              zlog_debug ("level %d number is - %ld", level,
        !          1202:                          circuit->area->lspdb[level - 1]->dict_nodecount);
        !          1203: #endif /* EXTREME DEBUG */
        !          1204:            }
        !          1205:          /*
        !          1206:           * If this lsp is a frag, need to see if we have zero lsp present
        !          1207:           */
        !          1208:          if (LSP_FRAGMENT (hdr->lsp_id) != 0)
        !          1209:            {
        !          1210:              memcpy (lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1);
        !          1211:              LSP_FRAGMENT (lspid) = 0;
        !          1212:              lsp0 = lsp_search (lspid, circuit->area->lspdb[level - 1]);
        !          1213:              if (!lsp0)
        !          1214:                {
        !          1215:                  zlog_debug ("Got lsp frag, while zero lsp not database");
        !          1216:                  return ISIS_OK;
        !          1217:                }
        !          1218:            }
        !          1219:          lsp =
        !          1220:            lsp_new_from_stream_ptr (circuit->rcv_stream,
        !          1221:                                     ntohs (hdr->pdu_len), lsp0,
        !          1222:                                     circuit->area);
        !          1223:          lsp->level = level;
        !          1224:          lsp->adj = adj;
        !          1225:          lsp_insert (lsp, circuit->area->lspdb[level - 1]);
        !          1226:          /* ii */
        !          1227:          ISIS_FLAGS_SET_ALL (lsp->SRMflags);
        !          1228:          /* iii */
        !          1229:          ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
        !          1230: 
        !          1231:          /* iv */
        !          1232:          if (circuit->circ_type != CIRCUIT_T_BROADCAST)
        !          1233:            ISIS_SET_FLAG (lsp->SSNflags, circuit);
        !          1234:          /* FIXME: v) */
        !          1235:        }
        !          1236:       /* 7.3.15.1 e) 2) LSP equal to the one in db */
        !          1237:       else if (comp == LSP_EQUAL)
        !          1238:        {
        !          1239:          ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
        !          1240:          lsp_update (lsp, hdr, circuit->rcv_stream, circuit->area, level);
        !          1241:          if (circuit->circ_type != CIRCUIT_T_BROADCAST)
        !          1242:            {
        !          1243:              ISIS_SET_FLAG (lsp->SSNflags, circuit);
        !          1244:            }
        !          1245:        }
        !          1246:       /* 7.3.15.1 e) 3) LSP older than the one in db */
        !          1247:       else
        !          1248:        {
        !          1249:          ISIS_SET_FLAG (lsp->SRMflags, circuit);
        !          1250:          ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
        !          1251:        }
        !          1252:     }
        !          1253:   if (lsp)
        !          1254:     lsp->adj = adj;
        !          1255:   return retval;
        !          1256: }
        !          1257: 
        !          1258: /*
        !          1259:  * Process Sequence Numbers
        !          1260:  * ISO - 10589
        !          1261:  * Section 7.3.15.2 - Action on receipt of a sequence numbers PDU
        !          1262:  */
        !          1263: 
        !          1264: static int
        !          1265: process_snp (int snp_type, int level, struct isis_circuit *circuit,
        !          1266:             u_char * ssnpa)
        !          1267: {
        !          1268:   int retval = ISIS_OK;
        !          1269:   int cmp, own_lsp;
        !          1270:   char typechar = ' ';
        !          1271:   int len;
        !          1272:   struct isis_adjacency *adj;
        !          1273:   struct isis_complete_seqnum_hdr *chdr = NULL;
        !          1274:   struct isis_partial_seqnum_hdr *phdr = NULL;
        !          1275:   uint32_t found = 0, expected = 0;
        !          1276:   struct isis_lsp *lsp;
        !          1277:   struct lsp_entry *entry;
        !          1278:   struct listnode *node, *nnode;
        !          1279:   struct listnode *node2, *nnode2;
        !          1280:   struct tlvs tlvs;
        !          1281:   struct list *lsp_list = NULL;
        !          1282:   struct isis_passwd *passwd;
        !          1283: 
        !          1284:   if (snp_type == ISIS_SNP_CSNP_FLAG)
        !          1285:     {
        !          1286:       /* getting the header info */
        !          1287:       typechar = 'C';
        !          1288:       chdr =
        !          1289:        (struct isis_complete_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream);
        !          1290:       circuit->rcv_stream->getp += ISIS_CSNP_HDRLEN;
        !          1291:       len = ntohs (chdr->pdu_len);
        !          1292:       if (len < ISIS_CSNP_HDRLEN)
        !          1293:        {
        !          1294:          zlog_warn ("Received a CSNP with bogus length!");
        !          1295:          return ISIS_OK;
        !          1296:        }
        !          1297:     }
        !          1298:   else
        !          1299:     {
        !          1300:       typechar = 'P';
        !          1301:       phdr =
        !          1302:        (struct isis_partial_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream);
        !          1303:       circuit->rcv_stream->getp += ISIS_PSNP_HDRLEN;
        !          1304:       len = ntohs (phdr->pdu_len);
        !          1305:       if (len < ISIS_PSNP_HDRLEN)
        !          1306:        {
        !          1307:          zlog_warn ("Received a CSNP with bogus length!");
        !          1308:          return ISIS_OK;
        !          1309:        }
        !          1310:     }
        !          1311: 
        !          1312:   /* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */
        !          1313:   if (circuit->ext_domain)
        !          1314:     {
        !          1315: 
        !          1316:       zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, "
        !          1317:                  "skipping: circuit externalDomain = true",
        !          1318:                  circuit->area->area_tag,
        !          1319:                  level, typechar, circuit->interface->name);
        !          1320: 
        !          1321:       return ISIS_OK;
        !          1322:     }
        !          1323: 
        !          1324:   /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */
        !          1325:   if (!accept_level (level, circuit->circuit_is_type))
        !          1326:     {
        !          1327: 
        !          1328:       zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, "
        !          1329:                  "skipping: circuit type %s does not match level %d",
        !          1330:                  circuit->area->area_tag,
        !          1331:                  level,
        !          1332:                  typechar,
        !          1333:                  circuit->interface->name,
        !          1334:                  circuit_t2string (circuit->circuit_is_type), level);
        !          1335: 
        !          1336:       return ISIS_OK;
        !          1337:     }
        !          1338: 
        !          1339:   /* 7.3.15.2 a) 4 - not applicable for CSNP  only PSNPs on broadcast */
        !          1340:   if ((snp_type == ISIS_SNP_PSNP_FLAG) &&
        !          1341:       (circuit->circ_type == CIRCUIT_T_BROADCAST))
        !          1342:     {
        !          1343:       if (!circuit->u.bc.is_dr[level - 1])
        !          1344:        {
        !          1345: 
        !          1346:          zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, "
        !          1347:                      "skipping: we are not the DIS",
        !          1348:                      circuit->area->area_tag,
        !          1349:                      level,
        !          1350:                      typechar, snpa_print (ssnpa), circuit->interface->name);
        !          1351: 
        !          1352:          return ISIS_OK;
        !          1353:        }
        !          1354:     }
        !          1355: 
        !          1356:   /* 7.3.15.2 a) 5 - need to make sure IDLength matches - already checked */
        !          1357: 
        !          1358:   /* 7.3.15.2 a) 6 - maximum area match, can be ommited since we only use 3
        !          1359:    * - already checked */
        !          1360: 
        !          1361:   /* 7.3.15.2 a) 7 - Must check that we have an adjacency of the same level  */
        !          1362:   /* for broadcast circuits, snpa should be compared */
        !          1363:   /* FIXME : Do we need to check SNPA? */
        !          1364:   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
        !          1365:     {
        !          1366:       if (snp_type == ISIS_SNP_CSNP_FLAG)
        !          1367:        {
        !          1368:          adj =
        !          1369:            isis_adj_lookup (chdr->source_id, circuit->u.bc.adjdb[level - 1]);
        !          1370:        }
        !          1371:       else
        !          1372:        {
        !          1373:          /* a psnp on a broadcast, how lovely of Juniper :) */
        !          1374:          adj =
        !          1375:            isis_adj_lookup (phdr->source_id, circuit->u.bc.adjdb[level - 1]);
        !          1376:        }
        !          1377:       if (!adj)
        !          1378:        return ISIS_OK;         /* Silently discard */
        !          1379:     }
        !          1380:   else
        !          1381:     {
        !          1382:       if (!circuit->u.p2p.neighbor)
        !          1383:        return ISIS_OK;         /* Silently discard */
        !          1384:     }
        !          1385: 
        !          1386:   /* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented  */
        !          1387: 
        !          1388:   /* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented  */
        !          1389: 
        !          1390:   memset (&tlvs, 0, sizeof (struct tlvs));
        !          1391: 
        !          1392:   /* parse the SNP */
        !          1393:   expected |= TLVFLAG_LSP_ENTRIES;
        !          1394:   expected |= TLVFLAG_AUTH_INFO;
        !          1395:   retval = parse_tlvs (circuit->area->area_tag,
        !          1396:                       STREAM_PNT (circuit->rcv_stream),
        !          1397:                       len - circuit->rcv_stream->getp,
        !          1398:                       &expected, &found, &tlvs);
        !          1399: 
        !          1400:   if (retval > ISIS_WARNING)
        !          1401:     {
        !          1402:       zlog_warn ("something went very wrong processing SNP");
        !          1403:       free_tlvs (&tlvs);
        !          1404:       return retval;
        !          1405:     }
        !          1406: 
        !          1407:   if (level == 1)
        !          1408:     passwd = &circuit->area->area_passwd;
        !          1409:   else
        !          1410:     passwd = &circuit->area->domain_passwd;
        !          1411: 
        !          1412:   if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV))
        !          1413:     {
        !          1414:       if (passwd->type)
        !          1415:        {
        !          1416:          if (!(found & TLVFLAG_AUTH_INFO) ||
        !          1417:              authentication_check (passwd, &tlvs.auth_info))
        !          1418:            {
        !          1419:              isis_event_auth_failure (circuit->area->area_tag,
        !          1420:                                       "SNP authentication" " failure",
        !          1421:                                       phdr ? phdr->source_id : chdr->source_id);
        !          1422:              return ISIS_OK;
        !          1423:            }
        !          1424:        }
        !          1425:     }
        !          1426: 
        !          1427:   /* debug isis snp-packets */
        !          1428:   if (isis->debugs & DEBUG_SNP_PACKETS)
        !          1429:     {
        !          1430:       zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s",
        !          1431:                  circuit->area->area_tag,
        !          1432:                  level,
        !          1433:                  typechar, snpa_print (ssnpa), circuit->interface->name);
        !          1434:       if (tlvs.lsp_entries)
        !          1435:        {
        !          1436:          for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry))
        !          1437:          {
        !          1438:            zlog_debug ("ISIS-Snp (%s):         %cSNP entry %s, seq 0x%08x,"
        !          1439:                        " cksum 0x%04x, lifetime %us",
        !          1440:                        circuit->area->area_tag,
        !          1441:                        typechar,
        !          1442:                        rawlspid_print (entry->lsp_id),
        !          1443:                        ntohl (entry->seq_num),
        !          1444:                        ntohs (entry->checksum), ntohs (entry->rem_lifetime));
        !          1445:          }
        !          1446:        }
        !          1447:     }
        !          1448: 
        !          1449:   /* 7.3.15.2 b) Actions on LSP_ENTRIES reported */
        !          1450:   if (tlvs.lsp_entries)
        !          1451:     {
        !          1452:       for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry))
        !          1453:       {
        !          1454:        lsp = lsp_search (entry->lsp_id, circuit->area->lspdb[level - 1]);
        !          1455:        own_lsp = !memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
        !          1456:        if (lsp)
        !          1457:          {
        !          1458:            /* 7.3.15.2 b) 1) is this LSP newer */
        !          1459:            cmp = lsp_compare (circuit->area->area_tag, lsp, entry->seq_num,
        !          1460:                               entry->checksum, entry->rem_lifetime);
        !          1461:            /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p */
        !          1462:            if (cmp == LSP_EQUAL)
        !          1463:              {
        !          1464:                if (circuit->circ_type != CIRCUIT_T_BROADCAST)
        !          1465:                  ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
        !          1466:                /* 7.3.15.2 b) 3) if it is older, clear SSN and set SRM */
        !          1467:              }
        !          1468:            else if (cmp == LSP_OLDER)
        !          1469:              {
        !          1470:                ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
        !          1471:                ISIS_SET_FLAG (lsp->SRMflags, circuit);
        !          1472:              }
        !          1473:            else
        !          1474:              {
        !          1475:                /* 7.3.15.2 b) 4) if it is newer, set SSN and clear SRM
        !          1476:                 * on p2p */
        !          1477:                if (own_lsp)
        !          1478:                  {
        !          1479:                    lsp_inc_seqnum (lsp, ntohl (entry->seq_num));
        !          1480:                    ISIS_SET_FLAG (lsp->SRMflags, circuit);
        !          1481:                  }
        !          1482:                else
        !          1483:                  {
        !          1484:                    ISIS_SET_FLAG (lsp->SSNflags, circuit);
        !          1485:                    if (circuit->circ_type != CIRCUIT_T_BROADCAST)
        !          1486:                      ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
        !          1487:                  }
        !          1488:              }
        !          1489:          }
        !          1490:        else
        !          1491:          {
        !          1492:            /* 7.3.15.2 b) 5) if it was not found, and all of those are not 0, 
        !          1493:             * insert it and set SSN on it */
        !          1494:            if (entry->rem_lifetime && entry->checksum && entry->seq_num &&
        !          1495:                memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))
        !          1496:              {
        !          1497:                lsp = lsp_new (entry->lsp_id, ntohs (entry->rem_lifetime),
        !          1498:                               0, 0, entry->checksum, level);
        !          1499:                lsp_insert (lsp, circuit->area->lspdb[level - 1]);
        !          1500:                ISIS_SET_FLAG (lsp->SSNflags, circuit);
        !          1501:              }
        !          1502:          }
        !          1503:       }
        !          1504:     }
        !          1505: 
        !          1506:   /* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported */
        !          1507:   if (snp_type == ISIS_SNP_CSNP_FLAG)
        !          1508:     {
        !          1509:       /*
        !          1510:        * Build a list from our own LSP db bounded with start_ and stop_lsp_id
        !          1511:        */
        !          1512:       lsp_list = list_new ();
        !          1513:       lsp_build_list_nonzero_ht (chdr->start_lsp_id, chdr->stop_lsp_id,
        !          1514:                                 lsp_list, circuit->area->lspdb[level - 1]);
        !          1515: 
        !          1516:       /* Fixme: Find a better solution */
        !          1517:       if (tlvs.lsp_entries)
        !          1518:        {
        !          1519:          for (ALL_LIST_ELEMENTS (tlvs.lsp_entries, node, nnode, entry))
        !          1520:          {
        !          1521:            for (ALL_LIST_ELEMENTS (lsp_list, node2, nnode2, lsp))
        !          1522:            {
        !          1523:              if (lsp_id_cmp (lsp->lsp_header->lsp_id, entry->lsp_id) == 0)
        !          1524:                {
        !          1525:                  list_delete_node (lsp_list, node2);
        !          1526:                  break;
        !          1527:                }
        !          1528:            }
        !          1529:          }
        !          1530:        }
        !          1531:       /* on remaining LSPs we set SRM (neighbor knew not of) */
        !          1532:       for (ALL_LIST_ELEMENTS_RO (lsp_list, node, lsp))
        !          1533:       {
        !          1534:        ISIS_SET_FLAG (lsp->SRMflags, circuit);
        !          1535:       }
        !          1536:       /* lets free it */
        !          1537:       list_free (lsp_list);
        !          1538:     }
        !          1539: 
        !          1540:   free_tlvs (&tlvs);
        !          1541:   return retval;
        !          1542: }
        !          1543: 
        !          1544: static int
        !          1545: process_csnp (int level, struct isis_circuit *circuit, u_char * ssnpa)
        !          1546: {
        !          1547:   /* Sanity check - FIXME: move to correct place */
        !          1548:   if ((stream_get_endp (circuit->rcv_stream) -
        !          1549:        stream_get_getp (circuit->rcv_stream)) < ISIS_CSNP_HDRLEN)
        !          1550:     {
        !          1551:       zlog_warn ("Packet too short ( < %d)", ISIS_CSNP_HDRLEN);
        !          1552:       return ISIS_WARNING;
        !          1553:     }
        !          1554: 
        !          1555:   return process_snp (ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa);
        !          1556: }
        !          1557: 
        !          1558: static int
        !          1559: process_psnp (int level, struct isis_circuit *circuit, u_char * ssnpa)
        !          1560: {
        !          1561:   if ((stream_get_endp (circuit->rcv_stream) -
        !          1562:        stream_get_getp (circuit->rcv_stream)) < ISIS_PSNP_HDRLEN)
        !          1563:     {
        !          1564:       zlog_warn ("Packet too short");
        !          1565:       return ISIS_WARNING;
        !          1566:     }
        !          1567: 
        !          1568:   return process_snp (ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa);
        !          1569: }
        !          1570: 
        !          1571: /*
        !          1572:  * Process ISH
        !          1573:  * ISO - 10589
        !          1574:  * Section 8.2.2 - Receiving ISH PDUs by an intermediate system
        !          1575:  * FIXME: sample packet dump, need to figure 0x81 - looks like NLPid
        !          1576:  *           0x82      0x15    0x01    0x00    0x04    0x01    0x2c    0x59
        !          1577:  *           0x38      0x08    0x47    0x00    0x01    0x00    0x02    0x00
        !          1578:  *           0x03      0x00    0x81    0x01    0xcc
        !          1579:  */
        !          1580: static int
        !          1581: process_is_hello (struct isis_circuit *circuit)
        !          1582: {
        !          1583:   struct isis_adjacency *adj;
        !          1584:   int retval = ISIS_OK;
        !          1585:   u_char neigh_len;
        !          1586:   u_char *sysid;
        !          1587: 
        !          1588:   /* In this point in time we are not yet able to handle is_hellos
        !          1589:    * on lan - Sorry juniper...
        !          1590:    */
        !          1591:   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
        !          1592:     return retval;
        !          1593: 
        !          1594:   neigh_len = stream_getc (circuit->rcv_stream);
        !          1595:   sysid = STREAM_PNT (circuit->rcv_stream) + neigh_len - 1 - ISIS_SYS_ID_LEN;
        !          1596:   adj = circuit->u.p2p.neighbor;
        !          1597:   if (!adj)
        !          1598:     {
        !          1599:       /* 8.2.2 */
        !          1600:       adj = isis_new_adj (sysid, NULL, 0, circuit);
        !          1601:       if (adj == NULL)
        !          1602:        return ISIS_ERROR;
        !          1603: 
        !          1604:       isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
        !          1605:       adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
        !          1606:       circuit->u.p2p.neighbor = adj;
        !          1607:     }
        !          1608:   /* 8.2.2 a) */
        !          1609:   if ((adj->adj_state == ISIS_ADJ_UP) && memcmp (adj->sysid, sysid,
        !          1610:                                                 ISIS_SYS_ID_LEN))
        !          1611:     {
        !          1612:       /* 8.2.2 a) 1) FIXME: adjStateChange(down) event */
        !          1613:       /* 8.2.2 a) 2) delete the adj */
        !          1614:       XFREE (MTYPE_ISIS_ADJACENCY, adj);
        !          1615:       /* 8.2.2 a) 3) create a new adj */
        !          1616:       adj = isis_new_adj (sysid, NULL, 0, circuit);
        !          1617:       if (adj == NULL)
        !          1618:        return ISIS_ERROR;
        !          1619: 
        !          1620:       /* 8.2.2 a) 3) i */
        !          1621:       isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
        !          1622:       /* 8.2.2 a) 3) ii */
        !          1623:       adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
        !          1624:       /* 8.2.2 a) 4) quite meaningless */
        !          1625:     }
        !          1626:   /* 8.2.2 b) ignore on condition */
        !          1627:   if ((adj->adj_state == ISIS_ADJ_INITIALIZING) &&
        !          1628:       (adj->sys_type == ISIS_SYSTYPE_IS))
        !          1629:     {
        !          1630:       /* do nothing */
        !          1631:     }
        !          1632:   else
        !          1633:     {
        !          1634:       /* 8.2.2 c) respond with a p2p IIH */
        !          1635:       send_hello (circuit, 1);
        !          1636:     }
        !          1637:   /* 8.2.2 d) type is IS */
        !          1638:   adj->sys_type = ISIS_SYSTYPE_IS;
        !          1639:   /* 8.2.2 e) FIXME: Circuit type of? */
        !          1640: 
        !          1641:   return retval;
        !          1642: }
        !          1643: 
        !          1644: /*
        !          1645:  * PDU Dispatcher
        !          1646:  */
        !          1647: 
        !          1648: static int
        !          1649: isis_handle_pdu (struct isis_circuit *circuit, u_char * ssnpa)
        !          1650: {
        !          1651:   struct isis_fixed_hdr *hdr;
        !          1652:   struct esis_fixed_hdr *esis_hdr;
        !          1653: 
        !          1654:   int retval = ISIS_OK;
        !          1655: 
        !          1656:   /*
        !          1657:    * Let's first read data from stream to the header
        !          1658:    */
        !          1659:   hdr = (struct isis_fixed_hdr *) STREAM_DATA (circuit->rcv_stream);
        !          1660: 
        !          1661:   if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS))
        !          1662:     {
        !          1663:       zlog_warn ("Not an IS-IS or ES-IS packet IDRP=%02x", hdr->idrp);
        !          1664:       return ISIS_ERROR;
        !          1665:     }
        !          1666: 
        !          1667:   /* now we need to know if this is an ISO 9542 packet and
        !          1668:    * take real good care of it, waaa!
        !          1669:    */
        !          1670:   if (hdr->idrp == ISO9542_ESIS)
        !          1671:     {
        !          1672:       esis_hdr = (struct esis_fixed_hdr *) STREAM_DATA (circuit->rcv_stream);
        !          1673:       stream_set_getp (circuit->rcv_stream, ESIS_FIXED_HDR_LEN);
        !          1674:       /* FIXME: Need to do some acceptence tests */
        !          1675:       /* example length... */
        !          1676:       switch (esis_hdr->pdu_type)
        !          1677:        {
        !          1678:        case ESH_PDU:
        !          1679:          /* FIXME */
        !          1680:          break;
        !          1681:        case ISH_PDU:
        !          1682:          zlog_debug ("AN ISH PDU!!");
        !          1683:          retval = process_is_hello (circuit);
        !          1684:          break;
        !          1685:        default:
        !          1686:          return ISIS_ERROR;
        !          1687:        }
        !          1688:       return retval;
        !          1689:     }
        !          1690:   else
        !          1691:     {
        !          1692:       stream_set_getp (circuit->rcv_stream, ISIS_FIXED_HDR_LEN);
        !          1693:     }
        !          1694:   /*
        !          1695:    * and then process it
        !          1696:    */
        !          1697: 
        !          1698:   if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN)
        !          1699:     {
        !          1700:       zlog_err ("Fixed header length = %d", hdr->length);
        !          1701:       return ISIS_ERROR;
        !          1702:     }
        !          1703: 
        !          1704:   if (hdr->version1 != 1)
        !          1705:     {
        !          1706:       zlog_warn ("Unsupported ISIS version %u", hdr->version1);
        !          1707:       return ISIS_WARNING;
        !          1708:     }
        !          1709:   /* either 6 or 0 */
        !          1710:   if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN))
        !          1711:     {
        !          1712:       zlog_err
        !          1713:        ("IDFieldLengthMismatch: ID Length field in a received PDU  %u, "
        !          1714:         "while the parameter for this IS is %u", hdr->id_len,
        !          1715:         ISIS_SYS_ID_LEN);
        !          1716:       return ISIS_ERROR;
        !          1717:     }
        !          1718: 
        !          1719:   if (hdr->version2 != 1)
        !          1720:     {
        !          1721:       zlog_warn ("Unsupported ISIS version %u", hdr->version2);
        !          1722:       return ISIS_WARNING;
        !          1723:     }
        !          1724:   /* either 3 or 0 */
        !          1725:   if ((hdr->max_area_addrs != 0)
        !          1726:       && (hdr->max_area_addrs != isis->max_area_addrs))
        !          1727:     {
        !          1728:       zlog_err ("maximumAreaAddressesMismatch: maximumAreaAdresses in a "
        !          1729:                "received PDU %u while the parameter for this IS is %u",
        !          1730:                hdr->max_area_addrs, isis->max_area_addrs);
        !          1731:       return ISIS_ERROR;
        !          1732:     }
        !          1733: 
        !          1734:   switch (hdr->pdu_type)
        !          1735:     {
        !          1736:     case L1_LAN_HELLO:
        !          1737:       retval = process_lan_hello (ISIS_LEVEL1, circuit, ssnpa);
        !          1738:       break;
        !          1739:     case L2_LAN_HELLO:
        !          1740:       retval = process_lan_hello (ISIS_LEVEL2, circuit, ssnpa);
        !          1741:       break;
        !          1742:     case P2P_HELLO:
        !          1743:       retval = process_p2p_hello (circuit);
        !          1744:       break;
        !          1745:     case L1_LINK_STATE:
        !          1746:       retval = process_lsp (ISIS_LEVEL1, circuit, ssnpa);
        !          1747:       break;
        !          1748:     case L2_LINK_STATE:
        !          1749:       retval = process_lsp (ISIS_LEVEL2, circuit, ssnpa);
        !          1750:       break;
        !          1751:     case L1_COMPLETE_SEQ_NUM:
        !          1752:       retval = process_csnp (ISIS_LEVEL1, circuit, ssnpa);
        !          1753:       break;
        !          1754:     case L2_COMPLETE_SEQ_NUM:
        !          1755:       retval = process_csnp (ISIS_LEVEL2, circuit, ssnpa);
        !          1756:       break;
        !          1757:     case L1_PARTIAL_SEQ_NUM:
        !          1758:       retval = process_psnp (ISIS_LEVEL1, circuit, ssnpa);
        !          1759:       break;
        !          1760:     case L2_PARTIAL_SEQ_NUM:
        !          1761:       retval = process_psnp (ISIS_LEVEL2, circuit, ssnpa);
        !          1762:       break;
        !          1763:     default:
        !          1764:       return ISIS_ERROR;
        !          1765:     }
        !          1766: 
        !          1767:   return retval;
        !          1768: }
        !          1769: 
        !          1770: #ifdef GNU_LINUX
        !          1771: int
        !          1772: isis_receive (struct thread *thread)
        !          1773: {
        !          1774:   struct isis_circuit *circuit;
        !          1775:   u_char ssnpa[ETH_ALEN];
        !          1776:   int retval;
        !          1777: 
        !          1778:   /*
        !          1779:    * Get the circuit 
        !          1780:    */
        !          1781:   circuit = THREAD_ARG (thread);
        !          1782:   assert (circuit);
        !          1783: 
        !          1784:   if (!circuit->area)
        !          1785:     return ISIS_OK;
        !          1786: 
        !          1787:   if (circuit->rcv_stream == NULL)
        !          1788:     circuit->rcv_stream = stream_new (ISO_MTU (circuit));
        !          1789:   else
        !          1790:     stream_reset (circuit->rcv_stream);
        !          1791: 
        !          1792:   retval = circuit->rx (circuit, ssnpa);
        !          1793:   circuit->t_read = NULL;
        !          1794: 
        !          1795:   if (retval == ISIS_OK)
        !          1796:     retval = isis_handle_pdu (circuit, ssnpa);
        !          1797: 
        !          1798:   /* 
        !          1799:    * prepare for next packet. 
        !          1800:    */
        !          1801:   THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit,
        !          1802:                  circuit->fd);
        !          1803: 
        !          1804:   return retval;
        !          1805: }
        !          1806: 
        !          1807: #else
        !          1808: int
        !          1809: isis_receive (struct thread *thread)
        !          1810: {
        !          1811:   struct isis_circuit *circuit;
        !          1812:   u_char ssnpa[ETH_ALEN];
        !          1813:   int retval;
        !          1814: 
        !          1815:   /*
        !          1816:    * Get the circuit 
        !          1817:    */
        !          1818:   circuit = THREAD_ARG (thread);
        !          1819:   assert (circuit);
        !          1820: 
        !          1821:   circuit->t_read = NULL;
        !          1822: 
        !          1823:   if (circuit->rcv_stream == NULL)
        !          1824:     circuit->rcv_stream = stream_new (ISO_MTU (circuit));
        !          1825:   else
        !          1826:     stream_reset (circuit->rcv_stream);
        !          1827: 
        !          1828:   retval = circuit->rx (circuit, ssnpa);
        !          1829: 
        !          1830:   if (retval == ISIS_OK)
        !          1831:     retval = isis_handle_pdu (circuit, ssnpa);
        !          1832: 
        !          1833:   /* 
        !          1834:    * prepare for next packet. 
        !          1835:    */
        !          1836:   circuit->t_read = thread_add_timer_msec (master, isis_receive, circuit,
        !          1837:                                           listcount
        !          1838:                                           (circuit->area->circuit_list) *
        !          1839:                                           100);
        !          1840: 
        !          1841:   return retval;
        !          1842: }
        !          1843: 
        !          1844: #endif
        !          1845: 
        !          1846:  /* filling of the fixed isis header */
        !          1847: void
        !          1848: fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type)
        !          1849: {
        !          1850:   memset (hdr, 0, sizeof (struct isis_fixed_hdr));
        !          1851: 
        !          1852:   hdr->idrp = ISO10589_ISIS;
        !          1853: 
        !          1854:   switch (pdu_type)
        !          1855:     {
        !          1856:     case L1_LAN_HELLO:
        !          1857:     case L2_LAN_HELLO:
        !          1858:       hdr->length = ISIS_LANHELLO_HDRLEN;
        !          1859:       break;
        !          1860:     case P2P_HELLO:
        !          1861:       hdr->length = ISIS_P2PHELLO_HDRLEN;
        !          1862:       break;
        !          1863:     case L1_LINK_STATE:
        !          1864:     case L2_LINK_STATE:
        !          1865:       hdr->length = ISIS_LSP_HDR_LEN;
        !          1866:       break;
        !          1867:     case L1_COMPLETE_SEQ_NUM:
        !          1868:     case L2_COMPLETE_SEQ_NUM:
        !          1869:       hdr->length = ISIS_CSNP_HDRLEN;
        !          1870:       break;
        !          1871:     case L1_PARTIAL_SEQ_NUM:
        !          1872:     case L2_PARTIAL_SEQ_NUM:
        !          1873:       hdr->length = ISIS_PSNP_HDRLEN;
        !          1874:       break;
        !          1875:     default:
        !          1876:       zlog_warn ("fill_fixed_hdr(): unknown pdu type %d", pdu_type);
        !          1877:       return;
        !          1878:     }
        !          1879:   hdr->length += ISIS_FIXED_HDR_LEN;
        !          1880:   hdr->pdu_type = pdu_type;
        !          1881:   hdr->version1 = 1;
        !          1882:   hdr->id_len = 0;             /* ISIS_SYS_ID_LEN -  0==6 */
        !          1883:   hdr->version2 = 1;
        !          1884:   hdr->max_area_addrs = 0;     /* isis->max_area_addrs -  0==3 */
        !          1885: }
        !          1886: 
        !          1887: /*
        !          1888:  * SEND SIDE                             
        !          1889:  */
        !          1890: static void
        !          1891: fill_fixed_hdr_andstream (struct isis_fixed_hdr *hdr, u_char pdu_type,
        !          1892:                          struct stream *stream)
        !          1893: {
        !          1894:   fill_fixed_hdr (hdr, pdu_type);
        !          1895: 
        !          1896:   stream_putc (stream, hdr->idrp);
        !          1897:   stream_putc (stream, hdr->length);
        !          1898:   stream_putc (stream, hdr->version1);
        !          1899:   stream_putc (stream, hdr->id_len);
        !          1900:   stream_putc (stream, hdr->pdu_type);
        !          1901:   stream_putc (stream, hdr->version2);
        !          1902:   stream_putc (stream, hdr->reserved);
        !          1903:   stream_putc (stream, hdr->max_area_addrs);
        !          1904: 
        !          1905:   return;
        !          1906: }
        !          1907: 
        !          1908: int
        !          1909: send_hello (struct isis_circuit *circuit, int level)
        !          1910: {
        !          1911:   struct isis_fixed_hdr fixed_hdr;
        !          1912:   struct isis_lan_hello_hdr hello_hdr;
        !          1913:   struct isis_p2p_hello_hdr p2p_hello_hdr;
        !          1914: 
        !          1915:   u_int32_t interval;
        !          1916:   unsigned long len_pointer, length;
        !          1917:   int retval;
        !          1918: 
        !          1919:   if (circuit->interface->mtu == 0)
        !          1920:     {
        !          1921:       zlog_warn ("circuit has zero MTU");
        !          1922:       return ISIS_WARNING;
        !          1923:     }
        !          1924: 
        !          1925:   if (!circuit->snd_stream)
        !          1926:     circuit->snd_stream = stream_new (ISO_MTU (circuit));
        !          1927:   else
        !          1928:     stream_reset (circuit->snd_stream);
        !          1929: 
        !          1930:   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
        !          1931:     if (level == 1)
        !          1932:       fill_fixed_hdr_andstream (&fixed_hdr, L1_LAN_HELLO,
        !          1933:                                circuit->snd_stream);
        !          1934:     else
        !          1935:       fill_fixed_hdr_andstream (&fixed_hdr, L2_LAN_HELLO,
        !          1936:                                circuit->snd_stream);
        !          1937:   else
        !          1938:     fill_fixed_hdr_andstream (&fixed_hdr, P2P_HELLO, circuit->snd_stream);
        !          1939: 
        !          1940:   /*
        !          1941:    * Fill LAN Level 1 or 2 Hello PDU header
        !          1942:    */
        !          1943:   memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr));
        !          1944:   interval = circuit->hello_multiplier[level - 1] *
        !          1945:     circuit->hello_interval[level - 1];
        !          1946:   /* If we are the DIS then hello interval is divided by three, as is the hold-timer */
        !          1947:   if (circuit->u.bc.is_dr[level - 1])
        !          1948:     interval=interval/3;
        !          1949:   if (interval > USHRT_MAX)
        !          1950:     interval = USHRT_MAX;
        !          1951:   hello_hdr.circuit_t = circuit->circuit_is_type;
        !          1952:   memcpy (hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN);
        !          1953:   hello_hdr.hold_time = htons ((u_int16_t) interval);
        !          1954: 
        !          1955:   hello_hdr.pdu_len = 0;       /* Update the PDU Length later */
        !          1956:   len_pointer = stream_get_endp (circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN;
        !          1957: 
        !          1958:   /* copy the shared part of the hello to the p2p hello if needed */
        !          1959:   if (circuit->circ_type == CIRCUIT_T_P2P)
        !          1960:     {
        !          1961:       memcpy (&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN);
        !          1962:       p2p_hello_hdr.local_id = circuit->circuit_id;
        !          1963:       /* FIXME: need better understanding */
        !          1964:       stream_put (circuit->snd_stream, &p2p_hello_hdr, ISIS_P2PHELLO_HDRLEN);
        !          1965:     }
        !          1966:   else
        !          1967:     {
        !          1968:       hello_hdr.prio = circuit->u.bc.priority[level - 1];
        !          1969:       if (level == 1 && circuit->u.bc.l1_desig_is)
        !          1970:        {
        !          1971:          memcpy (hello_hdr.lan_id, circuit->u.bc.l1_desig_is,
        !          1972:                  ISIS_SYS_ID_LEN + 1);
        !          1973:        }
        !          1974:       else if (level == 2 && circuit->u.bc.l2_desig_is)
        !          1975:        {
        !          1976:          memcpy (hello_hdr.lan_id, circuit->u.bc.l2_desig_is,
        !          1977:                  ISIS_SYS_ID_LEN + 1);
        !          1978:        }
        !          1979:       stream_put (circuit->snd_stream, &hello_hdr, ISIS_LANHELLO_HDRLEN);
        !          1980:     }
        !          1981: 
        !          1982:   /*
        !          1983:    * Then the variable length part 
        !          1984:    */
        !          1985:   /* add circuit password */
        !          1986:   if (circuit->passwd.type)
        !          1987:     if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len,
        !          1988:                          circuit->passwd.passwd, circuit->snd_stream))
        !          1989:       return ISIS_WARNING;
        !          1990:   /*  Area Addresses TLV */
        !          1991:   assert (circuit->area);
        !          1992:   if (circuit->area->area_addrs && circuit->area->area_addrs->count > 0)
        !          1993:     if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream))
        !          1994:       return ISIS_WARNING;
        !          1995: 
        !          1996:   /*  LAN Neighbors TLV */
        !          1997:   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
        !          1998:     {
        !          1999:       if (level == 1 && circuit->u.bc.lan_neighs[0]->count > 0)
        !          2000:        if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0],
        !          2001:                                circuit->snd_stream))
        !          2002:          return ISIS_WARNING;
        !          2003:       if (level == 2 && circuit->u.bc.lan_neighs[1]->count > 0)
        !          2004:        if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1],
        !          2005:                                circuit->snd_stream))
        !          2006:          return ISIS_WARNING;
        !          2007:     }
        !          2008: 
        !          2009:   /* Protocols Supported TLV */
        !          2010:   if (circuit->nlpids.count > 0)
        !          2011:     if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream))
        !          2012:       return ISIS_WARNING;
        !          2013:   /* IP interface Address TLV */
        !          2014:   if (circuit->ip_router && circuit->ip_addrs && circuit->ip_addrs->count > 0)
        !          2015:     if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream))
        !          2016:       return ISIS_WARNING;
        !          2017: 
        !          2018: #ifdef HAVE_IPV6
        !          2019:   /* IPv6 Interface Address TLV */
        !          2020:   if (circuit->ipv6_router && circuit->ipv6_link &&
        !          2021:       circuit->ipv6_link->count > 0)
        !          2022:     if (tlv_add_ipv6_addrs (circuit->ipv6_link, circuit->snd_stream))
        !          2023:       return ISIS_WARNING;
        !          2024: #endif /* HAVE_IPV6 */
        !          2025: 
        !          2026:   if (circuit->u.bc.pad_hellos)
        !          2027:     if (tlv_add_padding (circuit->snd_stream))
        !          2028:       return ISIS_WARNING;
        !          2029: 
        !          2030:   length = stream_get_endp (circuit->snd_stream);
        !          2031:   /* Update PDU length */
        !          2032:   stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t) length);
        !          2033: 
        !          2034:   retval = circuit->tx (circuit, level);
        !          2035:   if (retval)
        !          2036:     zlog_warn ("sending of LAN Level %d Hello failed", level);
        !          2037: 
        !          2038:   /* DEBUG_ADJ_PACKETS */
        !          2039:   if (isis->debugs & DEBUG_ADJ_PACKETS)
        !          2040:     {
        !          2041:       if (circuit->circ_type == CIRCUIT_T_BROADCAST)
        !          2042:        {
        !          2043:          zlog_debug ("ISIS-Adj (%s): Sent L%d LAN IIH on %s, length %ld",
        !          2044:                      circuit->area->area_tag, level, circuit->interface->name,
        !          2045:                      /* FIXME: use %z when we stop supporting old compilers. */
        !          2046:                      (unsigned long) STREAM_SIZE (circuit->snd_stream));
        !          2047:        }
        !          2048:       else
        !          2049:        {
        !          2050:          zlog_debug ("ISIS-Adj (%s): Sent P2P IIH on %s, length %ld",
        !          2051:                      circuit->area->area_tag, circuit->interface->name,
        !          2052:                      /* FIXME: use %z when we stop supporting old compilers. */
        !          2053:                      (unsigned long) STREAM_SIZE (circuit->snd_stream));
        !          2054:        }
        !          2055:     }
        !          2056: 
        !          2057:   return retval;
        !          2058: }
        !          2059: 
        !          2060: static int
        !          2061: send_lan_hello (struct isis_circuit *circuit, int level)
        !          2062: {
        !          2063:   return send_hello (circuit, level);
        !          2064: }
        !          2065: 
        !          2066: int
        !          2067: send_lan_l1_hello (struct thread *thread)
        !          2068: {
        !          2069:   struct isis_circuit *circuit;
        !          2070:   int retval;
        !          2071:   unsigned long next_hello;
        !          2072: 
        !          2073:   circuit = THREAD_ARG (thread);
        !          2074:   assert (circuit);
        !          2075: 
        !          2076:   if (!circuit->area) {
        !          2077:     return ISIS_OK;
        !          2078:   }
        !          2079: 
        !          2080:   /* Pseudonode sends hellos three times more than the other nodes */
        !          2081:   if (circuit->u.bc.is_dr[0])
        !          2082:     next_hello=circuit->hello_interval[0]/3+1;
        !          2083:   else
        !          2084:     next_hello=circuit->hello_interval[0];
        !          2085: 
        !          2086:   circuit->u.bc.t_send_lan_hello[0] = NULL;
        !          2087: 
        !          2088:   if (circuit->u.bc.run_dr_elect[0])
        !          2089:     retval = isis_dr_elect (circuit, 1);
        !          2090: 
        !          2091:   retval = send_lan_hello (circuit, 1);
        !          2092: 
        !          2093:   /* set next timer thread */
        !          2094:   THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[0],
        !          2095:                   send_lan_l1_hello, circuit,
        !          2096:                   isis_jitter (next_hello, IIH_JITTER));
        !          2097: 
        !          2098:   return retval;
        !          2099: }
        !          2100: 
        !          2101: int
        !          2102: send_lan_l2_hello (struct thread *thread)
        !          2103: {
        !          2104:   struct isis_circuit *circuit;
        !          2105:   int retval;
        !          2106:   unsigned long next_hello;
        !          2107: 
        !          2108:   circuit = THREAD_ARG (thread);
        !          2109:   assert (circuit);
        !          2110: 
        !          2111:   if (!circuit->area) {
        !          2112:     return ISIS_OK;
        !          2113:   }
        !          2114: 
        !          2115:   /* Pseudonode sends hellos three times more than the other nodes */
        !          2116:   if (circuit->u.bc.is_dr[1])
        !          2117:     next_hello=circuit->hello_interval[1]/3+1;
        !          2118:   else
        !          2119:     next_hello=circuit->hello_interval[1];
        !          2120: 
        !          2121:   circuit->u.bc.t_send_lan_hello[1] = NULL;
        !          2122: 
        !          2123:   if (circuit->u.bc.run_dr_elect[1])
        !          2124:     retval = isis_dr_elect (circuit, 2);
        !          2125: 
        !          2126:   retval = send_lan_hello (circuit, 2);
        !          2127: 
        !          2128:   /* set next timer thread */
        !          2129:   THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[1],
        !          2130:                   send_lan_l2_hello, circuit,
        !          2131:                   isis_jitter (next_hello, IIH_JITTER));
        !          2132: 
        !          2133:   return retval;
        !          2134: }
        !          2135: 
        !          2136: int
        !          2137: send_p2p_hello (struct thread *thread)
        !          2138: {
        !          2139:   struct isis_circuit *circuit;
        !          2140: 
        !          2141:   circuit = THREAD_ARG (thread);
        !          2142:   assert (circuit);
        !          2143:   circuit->u.p2p.t_send_p2p_hello = NULL;
        !          2144: 
        !          2145:   send_hello (circuit, 1);
        !          2146: 
        !          2147:   /* set next timer thread */
        !          2148:   THREAD_TIMER_ON (master, circuit->u.p2p.t_send_p2p_hello, send_p2p_hello,
        !          2149:                   circuit, isis_jitter (circuit->hello_interval[1],
        !          2150:                                         IIH_JITTER));
        !          2151: 
        !          2152:   return ISIS_OK;
        !          2153: }
        !          2154: 
        !          2155: static int
        !          2156: build_csnp (int level, u_char * start, u_char * stop, struct list *lsps,
        !          2157:            struct isis_circuit *circuit)
        !          2158: {
        !          2159:   struct isis_fixed_hdr fixed_hdr;
        !          2160:   struct isis_passwd *passwd;
        !          2161:   int retval = ISIS_OK;
        !          2162:   unsigned long lenp;
        !          2163:   u_int16_t length;
        !          2164: 
        !          2165:   if (level == 1)
        !          2166:     fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM,
        !          2167:                              circuit->snd_stream);
        !          2168:   else
        !          2169:     fill_fixed_hdr_andstream (&fixed_hdr, L2_COMPLETE_SEQ_NUM,
        !          2170:                              circuit->snd_stream);
        !          2171: 
        !          2172:   /*
        !          2173:    * Fill Level 1 or 2 Complete Sequence Numbers header
        !          2174:    */
        !          2175: 
        !          2176:   lenp = stream_get_endp (circuit->snd_stream);
        !          2177:   stream_putw (circuit->snd_stream, 0);        /* PDU length - when we know it */
        !          2178:   /* no need to send the source here, it is always us if we csnp */
        !          2179:   stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
        !          2180:   /* with zero circuit id - ref 9.10, 9.11 */
        !          2181:   stream_putc (circuit->snd_stream, 0x00);
        !          2182: 
        !          2183:   stream_put (circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2);
        !          2184:   stream_put (circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2);
        !          2185: 
        !          2186:   /*
        !          2187:    * And TLVs
        !          2188:    */
        !          2189:   if (level == 1)
        !          2190:     passwd = &circuit->area->area_passwd;
        !          2191:   else
        !          2192:     passwd = &circuit->area->domain_passwd;
        !          2193: 
        !          2194:   if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
        !          2195:     if (passwd->type)
        !          2196:       retval = tlv_add_authinfo (passwd->type, passwd->len,
        !          2197:                                 passwd->passwd, circuit->snd_stream);
        !          2198: 
        !          2199:   if (!retval && lsps)
        !          2200:     {
        !          2201:       retval = tlv_add_lsp_entries (lsps, circuit->snd_stream);
        !          2202:     }
        !          2203:   length = (u_int16_t) stream_get_endp (circuit->snd_stream);
        !          2204:   assert (length >= ISIS_CSNP_HDRLEN);
        !          2205:   /* Update PU length */
        !          2206:   stream_putw_at (circuit->snd_stream, lenp, length);
        !          2207: 
        !          2208:   return retval;
        !          2209: }
        !          2210: 
        !          2211: /*
        !          2212:  * FIXME: support multiple CSNPs
        !          2213:  */
        !          2214: 
        !          2215: int
        !          2216: send_csnp (struct isis_circuit *circuit, int level)
        !          2217: {
        !          2218:   int retval = ISIS_OK;
        !          2219:   u_char start[ISIS_SYS_ID_LEN + 2];
        !          2220:   u_char stop[ISIS_SYS_ID_LEN + 2];
        !          2221:   struct list *list = NULL;
        !          2222:   struct listnode *node;
        !          2223:   struct isis_lsp *lsp;
        !          2224: 
        !          2225:   memset (start, 0x00, ISIS_SYS_ID_LEN + 2);
        !          2226:   memset (stop, 0xff, ISIS_SYS_ID_LEN + 2);
        !          2227: 
        !          2228:   if (circuit->area->lspdb[level - 1] &&
        !          2229:       dict_count (circuit->area->lspdb[level - 1]) > 0)
        !          2230:     {
        !          2231:       list = list_new ();
        !          2232:       lsp_build_list (start, stop, list, circuit->area->lspdb[level - 1]);
        !          2233: 
        !          2234:       if (circuit->snd_stream == NULL)
        !          2235:        circuit->snd_stream = stream_new (ISO_MTU (circuit));
        !          2236:       else
        !          2237:        stream_reset (circuit->snd_stream);
        !          2238: 
        !          2239:       retval = build_csnp (level, start, stop, list, circuit);
        !          2240: 
        !          2241:       if (isis->debugs & DEBUG_SNP_PACKETS)
        !          2242:        {
        !          2243:          zlog_debug ("ISIS-Snp (%s): Sent L%d CSNP on %s, length %ld",
        !          2244:                     circuit->area->area_tag, level, circuit->interface->name,
        !          2245:                     /* FIXME: use %z when we stop supporting old compilers. */
        !          2246:                     (unsigned long) STREAM_SIZE (circuit->snd_stream));
        !          2247:          for (ALL_LIST_ELEMENTS_RO (list, node, lsp))
        !          2248:          {
        !          2249:            zlog_debug ("ISIS-Snp (%s):         CSNP entry %s, seq 0x%08x,"
        !          2250:                        " cksum 0x%04x, lifetime %us",
        !          2251:                        circuit->area->area_tag,
        !          2252:                        rawlspid_print (lsp->lsp_header->lsp_id),
        !          2253:                        ntohl (lsp->lsp_header->seq_num),
        !          2254:                        ntohs (lsp->lsp_header->checksum),
        !          2255:                        ntohs (lsp->lsp_header->rem_lifetime));
        !          2256:          }
        !          2257:        }
        !          2258: 
        !          2259:       list_delete (list);
        !          2260: 
        !          2261:       if (retval == ISIS_OK)
        !          2262:        retval = circuit->tx (circuit, level);
        !          2263:     }
        !          2264:   return retval;
        !          2265: }
        !          2266: 
        !          2267: int
        !          2268: send_l1_csnp (struct thread *thread)
        !          2269: {
        !          2270:   struct isis_circuit *circuit;
        !          2271:   int retval = ISIS_OK;
        !          2272: 
        !          2273:   circuit = THREAD_ARG (thread);
        !          2274:   assert (circuit);
        !          2275: 
        !          2276:   circuit->t_send_csnp[0] = NULL;
        !          2277: 
        !          2278:   if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[0])
        !          2279:     {
        !          2280:       send_csnp (circuit, 1);
        !          2281:     }
        !          2282:   /* set next timer thread */
        !          2283:   THREAD_TIMER_ON (master, circuit->t_send_csnp[0], send_l1_csnp, circuit,
        !          2284:                   isis_jitter (circuit->csnp_interval[0], CSNP_JITTER));
        !          2285: 
        !          2286:   return retval;
        !          2287: }
        !          2288: 
        !          2289: int
        !          2290: send_l2_csnp (struct thread *thread)
        !          2291: {
        !          2292:   struct isis_circuit *circuit;
        !          2293:   int retval = ISIS_OK;
        !          2294: 
        !          2295:   circuit = THREAD_ARG (thread);
        !          2296:   assert (circuit);
        !          2297: 
        !          2298:   circuit->t_send_csnp[1] = NULL;
        !          2299: 
        !          2300:   if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[1])
        !          2301:     {
        !          2302:       send_csnp (circuit, 2);
        !          2303:     }
        !          2304:   /* set next timer thread */
        !          2305:   THREAD_TIMER_ON (master, circuit->t_send_csnp[1], send_l2_csnp, circuit,
        !          2306:                   isis_jitter (circuit->csnp_interval[1], CSNP_JITTER));
        !          2307: 
        !          2308:   return retval;
        !          2309: }
        !          2310: 
        !          2311: static int
        !          2312: build_psnp (int level, struct isis_circuit *circuit, struct list *lsps)
        !          2313: {
        !          2314:   struct isis_fixed_hdr fixed_hdr;
        !          2315:   unsigned long lenp;
        !          2316:   u_int16_t length;
        !          2317:   int retval = 0;
        !          2318:   struct isis_lsp *lsp;
        !          2319:   struct isis_passwd *passwd;
        !          2320:   struct listnode *node;
        !          2321: 
        !          2322:   if (level == 1)
        !          2323:     fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM,
        !          2324:                              circuit->snd_stream);
        !          2325:   else
        !          2326:     fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM,
        !          2327:                              circuit->snd_stream);
        !          2328: 
        !          2329:   /*
        !          2330:    * Fill Level 1 or 2 Partial Sequence Numbers header
        !          2331:    */
        !          2332:   lenp = stream_get_endp (circuit->snd_stream);
        !          2333:   stream_putw (circuit->snd_stream, 0);        /* PDU length - when we know it */
        !          2334:   stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
        !          2335:   stream_putc (circuit->snd_stream, circuit->idx);
        !          2336: 
        !          2337:   /*
        !          2338:    * And TLVs
        !          2339:    */
        !          2340: 
        !          2341:   if (level == 1)
        !          2342:     passwd = &circuit->area->area_passwd;
        !          2343:   else
        !          2344:     passwd = &circuit->area->domain_passwd;
        !          2345: 
        !          2346:   if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
        !          2347:     if (passwd->type)
        !          2348:       retval = tlv_add_authinfo (passwd->type, passwd->len,
        !          2349:                                 passwd->passwd, circuit->snd_stream);
        !          2350: 
        !          2351:   if (!retval && lsps)
        !          2352:     {
        !          2353:       retval = tlv_add_lsp_entries (lsps, circuit->snd_stream);
        !          2354:     }
        !          2355: 
        !          2356:   if (isis->debugs & DEBUG_SNP_PACKETS)
        !          2357:     {
        !          2358:       for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp))
        !          2359:       {
        !          2360:        zlog_debug ("ISIS-Snp (%s):         PSNP entry %s, seq 0x%08x,"
        !          2361:                    " cksum 0x%04x, lifetime %us",
        !          2362:                    circuit->area->area_tag,
        !          2363:                    rawlspid_print (lsp->lsp_header->lsp_id),
        !          2364:                    ntohl (lsp->lsp_header->seq_num),
        !          2365:                    ntohs (lsp->lsp_header->checksum),
        !          2366:                    ntohs (lsp->lsp_header->rem_lifetime));
        !          2367:       }
        !          2368:     }
        !          2369: 
        !          2370:   length = (u_int16_t) stream_get_endp (circuit->snd_stream);
        !          2371:   assert (length >= ISIS_PSNP_HDRLEN);
        !          2372:   /* Update PDU length */
        !          2373:   stream_putw_at (circuit->snd_stream, lenp, length);
        !          2374: 
        !          2375:   return ISIS_OK;
        !          2376: }
        !          2377: 
        !          2378: /*
        !          2379:  *  7.3.15.4 action on expiration of partial SNP interval
        !          2380:  *  level 1
        !          2381:  */
        !          2382: static int
        !          2383: send_psnp (int level, struct isis_circuit *circuit)
        !          2384: {
        !          2385:   int retval = ISIS_OK;
        !          2386:   struct isis_lsp *lsp;
        !          2387:   struct list *list = NULL;
        !          2388:   struct listnode *node;
        !          2389: 
        !          2390:   if ((circuit->circ_type == CIRCUIT_T_BROADCAST &&
        !          2391:        !circuit->u.bc.is_dr[level - 1]) ||
        !          2392:       circuit->circ_type != CIRCUIT_T_BROADCAST)
        !          2393:     {
        !          2394: 
        !          2395:       if (circuit->area->lspdb[level - 1] &&
        !          2396:          dict_count (circuit->area->lspdb[level - 1]) > 0)
        !          2397:        {
        !          2398:          list = list_new ();
        !          2399:          lsp_build_list_ssn (circuit, list, circuit->area->lspdb[level - 1]);
        !          2400: 
        !          2401:          if (listcount (list) > 0)
        !          2402:            {
        !          2403:              if (circuit->snd_stream == NULL)
        !          2404:                circuit->snd_stream = stream_new (ISO_MTU (circuit));
        !          2405:              else
        !          2406:                stream_reset (circuit->snd_stream);
        !          2407: 
        !          2408: 
        !          2409:              if (isis->debugs & DEBUG_SNP_PACKETS)
        !          2410:                zlog_debug ("ISIS-Snp (%s): Sent L%d PSNP on %s, length %ld",
        !          2411:                            circuit->area->area_tag, level,
        !          2412:                            circuit->interface->name,
        !          2413:                            /* FIXME: use %z when we stop supporting old
        !          2414:                             * compilers. */
        !          2415:                            (unsigned long) STREAM_SIZE (circuit->snd_stream));
        !          2416: 
        !          2417:              retval = build_psnp (level, circuit, list);
        !          2418:              if (retval == ISIS_OK)
        !          2419:                retval = circuit->tx (circuit, level);
        !          2420: 
        !          2421:              if (retval == ISIS_OK)
        !          2422:                {
        !          2423:                  /*
        !          2424:                   * sending succeeded, we can clear SSN flags of this circuit
        !          2425:                   * for the LSPs in list
        !          2426:                   */
        !          2427:                  for (ALL_LIST_ELEMENTS_RO (list, node, lsp))
        !          2428:                     ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
        !          2429:                }
        !          2430:            }
        !          2431:          list_delete (list);
        !          2432:        }
        !          2433:     }
        !          2434: 
        !          2435:   return retval;
        !          2436: }
        !          2437: 
        !          2438: int
        !          2439: send_l1_psnp (struct thread *thread)
        !          2440: {
        !          2441: 
        !          2442:   struct isis_circuit *circuit;
        !          2443:   int retval = ISIS_OK;
        !          2444: 
        !          2445:   circuit = THREAD_ARG (thread);
        !          2446:   assert (circuit);
        !          2447: 
        !          2448:   circuit->t_send_psnp[0] = NULL;
        !          2449: 
        !          2450:   send_psnp (1, circuit);
        !          2451:   /* set next timer thread */
        !          2452:   THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit,
        !          2453:                   isis_jitter (circuit->psnp_interval[0], PSNP_JITTER));
        !          2454: 
        !          2455:   return retval;
        !          2456: }
        !          2457: 
        !          2458: /*
        !          2459:  *  7.3.15.4 action on expiration of partial SNP interval
        !          2460:  *  level 2
        !          2461:  */
        !          2462: int
        !          2463: send_l2_psnp (struct thread *thread)
        !          2464: {
        !          2465:   struct isis_circuit *circuit;
        !          2466:   int retval = ISIS_OK;
        !          2467: 
        !          2468:   circuit = THREAD_ARG (thread);
        !          2469:   assert (circuit);
        !          2470: 
        !          2471:   circuit->t_send_psnp[1] = NULL;
        !          2472: 
        !          2473:   send_psnp (2, circuit);
        !          2474: 
        !          2475:   /* set next timer thread */
        !          2476:   THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit,
        !          2477:                   isis_jitter (circuit->psnp_interval[1], PSNP_JITTER));
        !          2478: 
        !          2479:   return retval;
        !          2480: }
        !          2481: 
        !          2482: /*
        !          2483:  * ISO 10589 - 7.3.14.3
        !          2484:  */
        !          2485: int
        !          2486: send_lsp (struct thread *thread)
        !          2487: {
        !          2488:   struct isis_circuit *circuit;
        !          2489:   struct isis_lsp *lsp;
        !          2490:   struct listnode *node;
        !          2491:   int retval = 0;
        !          2492: 
        !          2493:   circuit = THREAD_ARG (thread);
        !          2494:   assert (circuit);
        !          2495: 
        !          2496:   if (circuit->state == C_STATE_UP)
        !          2497:     {
        !          2498:       lsp = listgetdata ((node = listhead (circuit->lsp_queue)));
        !          2499: 
        !          2500:       /*
        !          2501:        * Do not send if levels do not match
        !          2502:        */
        !          2503:       if (!(lsp->level & circuit->circuit_is_type))
        !          2504:        goto dontsend;
        !          2505: 
        !          2506:       /*
        !          2507:        * Do not send if we do not have adjacencies in state up on the circuit
        !          2508:        */
        !          2509:       if (circuit->upadjcount[lsp->level - 1] == 0)
        !          2510:        goto dontsend;
        !          2511:       /* only send if it needs sending */
        !          2512:       if ((time (NULL) - lsp->last_sent) >=
        !          2513:          circuit->area->lsp_gen_interval[lsp->level - 1])
        !          2514:        {
        !          2515: 
        !          2516:          if (isis->debugs & DEBUG_UPDATE_PACKETS)
        !          2517:            {
        !          2518:              zlog_debug
        !          2519:                ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x,"
        !          2520:                 " lifetime %us on %s", circuit->area->area_tag, lsp->level,
        !          2521:                 rawlspid_print (lsp->lsp_header->lsp_id),
        !          2522:                 ntohl (lsp->lsp_header->seq_num),
        !          2523:                 ntohs (lsp->lsp_header->checksum),
        !          2524:                 ntohs (lsp->lsp_header->rem_lifetime),
        !          2525:                 circuit->interface->name);
        !          2526:            }
        !          2527:          /* copy our lsp to the send buffer */
        !          2528:          stream_copy (circuit->snd_stream, lsp->pdu);
        !          2529: 
        !          2530:          retval = circuit->tx (circuit, lsp->level);
        !          2531: 
        !          2532:          /*
        !          2533:           * If the sending succeeded, we can del the lsp from circuits
        !          2534:           * lsp_queue
        !          2535:           */
        !          2536:          if (retval == ISIS_OK)
        !          2537:            {
        !          2538:              list_delete_node (circuit->lsp_queue, node);
        !          2539: 
        !          2540:              /*
        !          2541:               * On broadcast circuits also the SRMflag can be cleared
        !          2542:               */
        !          2543:              if (circuit->circ_type == CIRCUIT_T_BROADCAST)
        !          2544:                ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
        !          2545: 
        !          2546:              if (flags_any_set (lsp->SRMflags) == 0)
        !          2547:                {
        !          2548:                  /*
        !          2549:                   * need to remember when we were last sent
        !          2550:                   */
        !          2551:                  lsp->last_sent = time (NULL);
        !          2552:                }
        !          2553:            }
        !          2554:          else
        !          2555:            {
        !          2556:              zlog_debug ("sending of level %d link state failed", lsp->level);
        !          2557:            }
        !          2558:        }
        !          2559:       else
        !          2560:        {
        !          2561:          /* my belief is that if it wasn't his time, the lsp can be removed
        !          2562:           * from the queue
        !          2563:           */
        !          2564:        dontsend:
        !          2565:          list_delete_node (circuit->lsp_queue, node);
        !          2566:        }
        !          2567: #if 0
        !          2568:       /*
        !          2569:        * If there are still LSPs send next one after lsp-interval (33 msecs)
        !          2570:        */
        !          2571:       if (listcount (circuit->lsp_queue) > 0)
        !          2572:        thread_add_timer (master, send_lsp, circuit, 1);
        !          2573: #endif
        !          2574:     }
        !          2575: 
        !          2576:   return retval;
        !          2577: }
        !          2578: 
        !          2579: int
        !          2580: ack_lsp (struct isis_link_state_hdr *hdr, struct isis_circuit *circuit,
        !          2581:         int level)
        !          2582: {
        !          2583:   unsigned long lenp;
        !          2584:   int retval;
        !          2585:   u_int16_t length;
        !          2586:   struct isis_fixed_hdr fixed_hdr;
        !          2587: 
        !          2588:   if (!circuit->snd_stream)
        !          2589:     circuit->snd_stream = stream_new (ISO_MTU (circuit));
        !          2590:   else
        !          2591:     stream_reset (circuit->snd_stream);
        !          2592: 
        !          2593: //  fill_llc_hdr (stream);
        !          2594:   if (level == 1)
        !          2595:     fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM,
        !          2596:                              circuit->snd_stream);
        !          2597:   else
        !          2598:     fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM,
        !          2599:                              circuit->snd_stream);
        !          2600: 
        !          2601: 
        !          2602:   lenp = stream_get_endp (circuit->snd_stream);
        !          2603:   stream_putw (circuit->snd_stream, 0);        /* PDU length  */
        !          2604:   stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
        !          2605:   stream_putc (circuit->snd_stream, circuit->idx);
        !          2606:   stream_putc (circuit->snd_stream, 9);        /* code */
        !          2607:   stream_putc (circuit->snd_stream, 16);       /* len */
        !          2608: 
        !          2609:   stream_putw (circuit->snd_stream, ntohs (hdr->rem_lifetime));
        !          2610:   stream_put (circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2);
        !          2611:   stream_putl (circuit->snd_stream, ntohl (hdr->seq_num));
        !          2612:   stream_putw (circuit->snd_stream, ntohs (hdr->checksum));
        !          2613: 
        !          2614:   length = (u_int16_t) stream_get_endp (circuit->snd_stream);
        !          2615:   /* Update PDU length */
        !          2616:   stream_putw_at (circuit->snd_stream, lenp, length);
        !          2617: 
        !          2618:   retval = circuit->tx (circuit, level);
        !          2619: 
        !          2620:   return retval;
        !          2621: }
        !          2622: 

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