Diff for /embedaddon/quagga/isisd/isis_pdu.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2013/07/21 23:54:38 version 1.1.1.4, 2016/11/02 10:09:10
Line 62 Line 62
 #endif /* PNBBY */  #endif /* PNBBY */
   
 /* Utility mask array. */  /* Utility mask array. */
static u_char maskbit[] = {static const u_char maskbit[] = {
   0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff    0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
 };  };
   
Line 204  authentication_check (struct isis_passwd *remote, stru Line 204  authentication_check (struct isis_passwd *remote, stru
       /* Compute the digest */        /* Compute the digest */
       hmac_md5 (STREAM_DATA (stream), stream_get_endp (stream),        hmac_md5 (STREAM_DATA (stream), stream_get_endp (stream),
                 (unsigned char *) &(local->passwd), local->len,                  (unsigned char *) &(local->passwd), local->len,
                (caddr_t) &digest);                (unsigned char *) &digest);
       /* Copy back the authentication value after the check */        /* Copy back the authentication value after the check */
       memcpy (STREAM_DATA (stream) + auth_tlv_offset + 3,        memcpy (STREAM_DATA (stream) + auth_tlv_offset + 3,
               remote->passwd, ISIS_AUTH_MD5_SIZE);                remote->passwd, ISIS_AUTH_MD5_SIZE);
Line 402  process_p2p_hello (struct isis_circuit *circuit) Line 402  process_p2p_hello (struct isis_circuit *circuit)
   u_int32_t expected = 0, found = 0, auth_tlv_offset = 0;    u_int32_t expected = 0, found = 0, auth_tlv_offset = 0;
   uint16_t pdu_len;    uint16_t pdu_len;
   struct tlvs tlvs;    struct tlvs tlvs;
     int v4_usable = 0, v6_usable = 0;
   
   if (isis->debugs & DEBUG_ADJ_PACKETS)    if (isis->debugs & DEBUG_ADJ_PACKETS)
     {      {
Line 518  process_p2p_hello (struct isis_circuit *circuit) Line 519  process_p2p_hello (struct isis_circuit *circuit)
   /*    /*
    * check if it's own interface ip match iih ip addrs     * check if it's own interface ip match iih ip addrs
    */     */
  if ((found & TLVFLAG_IPV4_ADDR) == 0 ||  if (found & TLVFLAG_IPV4_ADDR)
      ip_match (circuit->ip_addrs, tlvs.ipv4_addrs) == 0) 
     {      {
      zlog_warn ("ISIS-Adj: No usable IP interface addresses "      if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs))
                 "in LAN IIH from %s\n", circuit->interface->name);        v4_usable = 1;
       else
         zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap "
                    "in P2P IIH from %s\n", circuit->interface->name);
     }
 #ifndef HAVE_IPV6
   else /* !(found & TLVFLAG_IPV4_ADDR) */
     zlog_warn ("ISIS-Adj: no IPv4 in P2P IIH from %s "
                "(this isisd has no IPv6)\n", circuit->interface->name);
 
 #else
   if (found & TLVFLAG_IPV6_ADDR)
     {
       /* TBA: check that we have a linklocal ourselves? */
       struct listnode *node;
       struct in6_addr *ip;
       for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip))
         if (IN6_IS_ADDR_LINKLOCAL (ip))
           {
             v6_usable = 1;
             break;
           }
 
       if (!v6_usable)
         zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local "
                    "in P2P IIH from %s\n", circuit->interface->name);
     }
 
   if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR)))
     zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in P2P IIH from %s\n",
                circuit->interface->name);
 #endif
 
   if (!v6_usable && !v4_usable)
     {
       free_tlvs (&tlvs);        free_tlvs (&tlvs);
       return ISIS_WARNING;        return ISIS_WARNING;
     }      }
   
   /*    /*
      * it's own p2p IIH PDU - discard
      */
     if (!memcmp (hdr->source_id, isis->sysid, ISIS_SYS_ID_LEN))
       {
         zlog_warn ("ISIS-Adj (%s): it's own IIH PDU - discarded",
                     circuit->area->area_tag);
         free_tlvs (&tlvs);
         return ISIS_WARNING;
       }
   
     /*
    * My interpertation of the ISO, if no adj exists we will create one for     * My interpertation of the ISO, if no adj exists we will create one for
    * the circuit     * the circuit
    */     */
   adj = circuit->u.p2p.neighbor;    adj = circuit->u.p2p.neighbor;
     /* If an adjacency exists, check it is with the source of the hello
      * packets */
     if (adj)
       {
         if (memcmp(hdr->source_id, adj->sysid, ISIS_SYS_ID_LEN))
           {
             zlog_debug("hello source and adjacency do not match, set adj down\n");
             isis_adj_state_change (adj, ISIS_ADJ_DOWN, "adj do not exist");
             return 0;
           }
       }
   if (!adj || adj->level != hdr->circuit_t)    if (!adj || adj->level != hdr->circuit_t)
     {      {
       if (!adj)        if (!adj)
Line 545  process_p2p_hello (struct isis_circuit *circuit) Line 601  process_p2p_hello (struct isis_circuit *circuit)
           adj->level = hdr->circuit_t;            adj->level = hdr->circuit_t;
         }          }
       circuit->u.p2p.neighbor = adj;        circuit->u.p2p.neighbor = adj;
         /* Build lsp with the new neighbor entry when a new
          * adjacency is formed. Set adjacency circuit type to
          * IIH PDU header circuit type before lsp is regenerated
          * when an adjacency is up. This will result in the new
          * adjacency entry getting added to the lsp tlv neighbor list.
          */
         adj->circuit_t = hdr->circuit_t;
       isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);        isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
       adj->sys_type = ISIS_SYSTYPE_UNKNOWN;        adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
     }      }
Line 830  process_p2p_hello (struct isis_circuit *circuit) Line 893  process_p2p_hello (struct isis_circuit *circuit)
       break;        break;
     }      }
   
   adj->circuit_t = hdr->circuit_t;  
   
   if (isis->debugs & DEBUG_ADJ_PACKETS)    if (isis->debugs & DEBUG_ADJ_PACKETS)
     {      {
Line 850  process_p2p_hello (struct isis_circuit *circuit) Line 912  process_p2p_hello (struct isis_circuit *circuit)
  * Process IS-IS LAN Level 1/2 Hello PDU   * Process IS-IS LAN Level 1/2 Hello PDU
  */   */
 static int  static int
process_lan_hello (int level, struct isis_circuit *circuit, u_char * ssnpa)process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa)
 {  {
   int retval = ISIS_OK;    int retval = ISIS_OK;
   struct isis_lan_hello_hdr hdr;    struct isis_lan_hello_hdr hdr;
Line 859  process_lan_hello (int level, struct isis_circuit *cir Line 921  process_lan_hello (int level, struct isis_circuit *cir
   struct tlvs tlvs;    struct tlvs tlvs;
   u_char *snpa;    u_char *snpa;
   struct listnode *node;    struct listnode *node;
     int v4_usable = 0, v6_usable = 0;
   
   if (isis->debugs & DEBUG_ADJ_PACKETS)    if (isis->debugs & DEBUG_ADJ_PACKETS)
     {      {
Line 1045  process_lan_hello (int level, struct isis_circuit *cir Line 1108  process_lan_hello (int level, struct isis_circuit *cir
   /*    /*
    * check if it's own interface ip match iih ip addrs     * check if it's own interface ip match iih ip addrs
    */     */
  if ((found & TLVFLAG_IPV4_ADDR) == 0 ||  if (found & TLVFLAG_IPV4_ADDR)
      ip_match (circuit->ip_addrs, tlvs.ipv4_addrs) == 0) 
     {      {
      zlog_debug ("ISIS-Adj: No usable IP interface addresses "      if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs))
                  "in LAN IIH from %s\n", circuit->interface->name);        v4_usable = 1;
      retval = ISIS_WARNING;      else
      goto out;        zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap "
                    "in LAN IIH from %s\n", circuit->interface->name);
     }      }
   #ifndef HAVE_IPV6
     else /* !(found & TLVFLAG_IPV4_ADDR) */
       zlog_warn ("ISIS-Adj: no IPv4 in LAN IIH from %s "
                  "(this isisd has no IPv6)\n", circuit->interface->name);
   
   #else
     if (found & TLVFLAG_IPV6_ADDR)
       {
         /* TBA: check that we have a linklocal ourselves? */
         struct listnode *node;
         struct in6_addr *ip;
         for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip))
           if (IN6_IS_ADDR_LINKLOCAL (ip))
             {
               v6_usable = 1;
               break;
             }
   
         if (!v6_usable)
           zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local "
                      "in LAN IIH from %s\n", circuit->interface->name);
       }
   
     if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR)))
       zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in LAN IIH from %s\n",
                  circuit->interface->name);
   #endif
   
     if (!v6_usable && !v4_usable)
       {
         free_tlvs (&tlvs);
         return ISIS_WARNING;
       }
   
   
   adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]);    adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]);
   if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN)) ||    if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN)) ||
       (adj->level != level))        (adj->level != level))
Line 1184  out: Line 1281  out:
   if (isis->debugs & DEBUG_ADJ_PACKETS)    if (isis->debugs & DEBUG_ADJ_PACKETS)
     {      {
       zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, "        zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, "
                  "cirID %u, length %ld",                  "cirID %u, length %zd",
                   circuit->area->area_tag,                    circuit->area->area_tag,
                   level, snpa_print (ssnpa), circuit->interface->name,                    level, snpa_print (ssnpa), circuit->interface->name,
                   circuit_t2string (circuit->is_type),                    circuit_t2string (circuit->is_type),
Line 1203  out: Line 1300  out:
  * Section 7.3.15.1 - Action on receipt of a link state PDU   * Section 7.3.15.1 - Action on receipt of a link state PDU
  */   */
 static int  static int
process_lsp (int level, struct isis_circuit *circuit, u_char * ssnpa)process_lsp (int level, struct isis_circuit *circuit, const u_char *ssnpa)
 {  {
   struct isis_link_state_hdr *hdr;    struct isis_link_state_hdr *hdr;
   struct isis_adjacency *adj = NULL;    struct isis_adjacency *adj = NULL;
Line 1212  process_lsp (int level, struct isis_circuit *circuit,  Line 1309  process_lsp (int level, struct isis_circuit *circuit, 
   u_char lspid[ISIS_SYS_ID_LEN + 2];    u_char lspid[ISIS_SYS_ID_LEN + 2];
   struct isis_passwd *passwd;    struct isis_passwd *passwd;
   uint16_t pdu_len;    uint16_t pdu_len;
     int lsp_confusion;
   
   if (isis->debugs & DEBUG_UPDATE_PACKETS)    if (isis->debugs & DEBUG_UPDATE_PACKETS)
     {      {
Line 1386  dontcheckadj: Line 1484  dontcheckadj:
   
   /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented  FIXME: do it */    /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented  FIXME: do it */
   
     /* 7.3.16.2 - If this is an LSP from another IS with identical seq_num but
      *            wrong checksum, initiate a purge. */
     if (lsp
         && (lsp->lsp_header->seq_num == hdr->seq_num)
         && (lsp->lsp_header->checksum != hdr->checksum))
       {
         zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.",
                   circuit->area->area_tag, rawlspid_print(hdr->lsp_id),
                   ntohl(hdr->seq_num));
         hdr->rem_lifetime = 0;
         lsp_confusion = 1;
       }
     else
       lsp_confusion = 0;
   
   /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */    /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */
   if (hdr->rem_lifetime == 0)    if (hdr->rem_lifetime == 0)
     {      {
Line 1408  dontcheckadj: Line 1521  dontcheckadj:
                   lsp_update (lsp, circuit->rcv_stream, circuit->area, level);                    lsp_update (lsp, circuit->rcv_stream, circuit->area, level);
                   /* ii */                    /* ii */
                   lsp_set_all_srmflags (lsp);                    lsp_set_all_srmflags (lsp);
                   /* iii */  
                   ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);  
                   /* v */                    /* v */
                   ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */                    ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */
                   /* iv */  
                   if (circuit->circ_type != CIRCUIT_T_BROADCAST)  
                     ISIS_SET_FLAG (lsp->SSNflags, circuit);  
   
                     /* For the case of lsp confusion, flood the purge back to its
                      * originator so that it can react. Otherwise, don't reflood
                      * through incoming circuit as usual */
                     if (!lsp_confusion)
                       {
                         /* iii */
                         ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
                         /* iv */
                         if (circuit->circ_type != CIRCUIT_T_BROADCAST)
                           ISIS_SET_FLAG (lsp->SSNflags, circuit);
                       }
                 }               /* 7.3.16.4 b) 2) */                  }               /* 7.3.16.4 b) 2) */
               else if (comp == LSP_EQUAL)                else if (comp == LSP_EQUAL)
                 {                  {
Line 1460  dontcheckadj: Line 1579  dontcheckadj:
       if (!lsp)        if (!lsp)
         {          {
           /* 7.3.16.4: initiate a purge */            /* 7.3.16.4: initiate a purge */
          lsp_purge_non_exist (hdr, circuit->area);          lsp_purge_non_exist(level, hdr, circuit->area);
           return ISIS_OK;            return ISIS_OK;
         }          }
       /* 7.3.15.1 d) - If this is our own lsp and we have it */        /* 7.3.15.1 d) - If this is our own lsp and we have it */
Line 1552  dontcheckadj: Line 1671  dontcheckadj:
   
 static int  static int
 process_snp (int snp_type, int level, struct isis_circuit *circuit,  process_snp (int snp_type, int level, struct isis_circuit *circuit,
             u_char * ssnpa)             const u_char *ssnpa)
 {  {
   int retval = ISIS_OK;    int retval = ISIS_OK;
   int cmp, own_lsp;    int cmp, own_lsp;
Line 1597  process_snp (int snp_type, int level, struct isis_circ Line 1716  process_snp (int snp_type, int level, struct isis_circ
           pdu_len > ISO_MTU(circuit) ||            pdu_len > ISO_MTU(circuit) ||
           pdu_len > stream_get_endp (circuit->rcv_stream))            pdu_len > stream_get_endp (circuit->rcv_stream))
         {          {
          zlog_warn ("Received a CSNP with bogus length %d", pdu_len);          zlog_warn ("Received a PSNP with bogus length %d", pdu_len);
           return ISIS_WARNING;            return ISIS_WARNING;
         }          }
     }      }
Line 1798  process_snp (int snp_type, int level, struct isis_circ Line 1917  process_snp (int snp_type, int level, struct isis_circ
             if (entry->rem_lifetime && entry->checksum && entry->seq_num &&              if (entry->rem_lifetime && entry->checksum && entry->seq_num &&
                 memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))                  memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))
               {                {
                lsp = lsp_new (entry->lsp_id, ntohs (entry->rem_lifetime),                lsp = lsp_new(circuit->area, entry->lsp_id,
                               0, 0, entry->checksum, level);                              ntohs(entry->rem_lifetime),
                lsp->area = circuit->area;                              0, 0, entry->checksum, level);
                 lsp_insert (lsp, circuit->area->lspdb[level - 1]);                  lsp_insert (lsp, circuit->area->lspdb[level - 1]);
                 ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags);                  ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags);
                 ISIS_SET_FLAG (lsp->SSNflags, circuit);                  ISIS_SET_FLAG (lsp->SSNflags, circuit);
Line 1848  process_snp (int snp_type, int level, struct isis_circ Line 1967  process_snp (int snp_type, int level, struct isis_circ
 }  }
   
 static int  static int
process_csnp (int level, struct isis_circuit *circuit, u_char * ssnpa)process_csnp (int level, struct isis_circuit *circuit, const u_char *ssnpa)
 {  {
   if (isis->debugs & DEBUG_SNP_PACKETS)    if (isis->debugs & DEBUG_SNP_PACKETS)
     {      {
Line 1872  process_csnp (int level, struct isis_circuit *circuit, Line 1991  process_csnp (int level, struct isis_circuit *circuit,
 }  }
   
 static int  static int
process_psnp (int level, struct isis_circuit *circuit, u_char * ssnpa)process_psnp (int level, struct isis_circuit *circuit, const u_char *ssnpa)
 {  {
   if (isis->debugs & DEBUG_SNP_PACKETS)    if (isis->debugs & DEBUG_SNP_PACKETS)
     {      {
Line 1895  process_psnp (int level, struct isis_circuit *circuit, Line 2014  process_psnp (int level, struct isis_circuit *circuit,
 }  }
   
 /*  /*
  * Process ISH  
  * ISO - 10589  
  * Section 8.2.2 - Receiving ISH PDUs by an intermediate system  
  * FIXME: sample packet dump, need to figure 0x81 - looks like NLPid  
  *           0x82       0x15    0x01    0x00    0x04    0x01    0x2c    0x59  
  *           0x38       0x08    0x47    0x00    0x01    0x00    0x02    0x00  
  *           0x03       0x00    0x81    0x01    0xcc  
  */  
 static int  
 process_is_hello (struct isis_circuit *circuit)  
 {  
   struct isis_adjacency *adj;  
   int retval = ISIS_OK;  
   u_char neigh_len;  
   u_char *sysid;  
   
   if (isis->debugs & DEBUG_ADJ_PACKETS)  
     {  
       zlog_debug ("ISIS-Adj (%s): Rcvd ISH on %s, cirType %s, cirID %u",  
                   circuit->area->area_tag, circuit->interface->name,  
                   circuit_t2string (circuit->is_type), circuit->circuit_id);  
       if (isis->debugs & DEBUG_PACKET_DUMP)  
         zlog_dump_data (STREAM_DATA (circuit->rcv_stream),  
                         stream_get_endp (circuit->rcv_stream));  
     }  
   
   /* In this point in time we are not yet able to handle is_hellos  
    * on lan - Sorry juniper...  
    */  
   if (circuit->circ_type == CIRCUIT_T_BROADCAST)  
     return retval;  
   
   neigh_len = stream_getc (circuit->rcv_stream);  
   sysid = STREAM_PNT (circuit->rcv_stream) + neigh_len - 1 - ISIS_SYS_ID_LEN;  
   adj = circuit->u.p2p.neighbor;  
   if (!adj)  
     {  
       /* 8.2.2 */  
       adj = isis_new_adj (sysid, NULL, 0, circuit);  
       if (adj == NULL)  
         return ISIS_ERROR;  
   
       isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);  
       adj->sys_type = ISIS_SYSTYPE_UNKNOWN;  
       circuit->u.p2p.neighbor = adj;  
     }  
   /* 8.2.2 a) */  
   if ((adj->adj_state == ISIS_ADJ_UP) && memcmp (adj->sysid, sysid,  
                                                  ISIS_SYS_ID_LEN))  
     {  
       /* 8.2.2 a) 1) FIXME: adjStateChange(down) event */  
       /* 8.2.2 a) 2) delete the adj */  
       XFREE (MTYPE_ISIS_ADJACENCY, adj);  
       /* 8.2.2 a) 3) create a new adj */  
       adj = isis_new_adj (sysid, NULL, 0, circuit);  
       if (adj == NULL)  
         return ISIS_ERROR;  
   
       /* 8.2.2 a) 3) i */  
       isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);  
       /* 8.2.2 a) 3) ii */  
       adj->sys_type = ISIS_SYSTYPE_UNKNOWN;  
       /* 8.2.2 a) 4) quite meaningless */  
     }  
   /* 8.2.2 b) ignore on condition */  
   if ((adj->adj_state == ISIS_ADJ_INITIALIZING) &&  
       (adj->sys_type == ISIS_SYSTYPE_IS))  
     {  
       /* do nothing */  
     }  
   else  
     {  
       /* 8.2.2 c) respond with a p2p IIH */  
       send_hello (circuit, 1);  
     }  
   /* 8.2.2 d) type is IS */  
   adj->sys_type = ISIS_SYSTYPE_IS;  
   /* 8.2.2 e) FIXME: Circuit type of? */  
   
   return retval;  
 }  
   
 /*  
  * PDU Dispatcher   * PDU Dispatcher
  */   */
   
Line 2107  isis_receive (struct thread *thread) Line 2143  isis_receive (struct thread *thread)
   circuit = THREAD_ARG (thread);    circuit = THREAD_ARG (thread);
   assert (circuit);    assert (circuit);
   
  if (circuit->rcv_stream == NULL)  isis_circuit_stream(circuit, &circuit->rcv_stream);
    circuit->rcv_stream = stream_new (ISO_MTU (circuit)); 
  else 
    stream_reset (circuit->rcv_stream); 
   
   retval = circuit->rx (circuit, ssnpa);    retval = circuit->rx (circuit, ssnpa);
   circuit->t_read = NULL;    circuit->t_read = NULL;
Line 2146  isis_receive (struct thread *thread) Line 2179  isis_receive (struct thread *thread)
   
   circuit->t_read = NULL;    circuit->t_read = NULL;
   
  if (circuit->rcv_stream == NULL)  isis_circuit_stream(circuit, &circuit->rcv_stream);
    circuit->rcv_stream = stream_new (ISO_MTU (circuit)); 
  else 
    stream_reset (circuit->rcv_stream); 
   
   retval = circuit->rx (circuit, ssnpa);    retval = circuit->rx (circuit, ssnpa);
   
Line 2241  send_hello (struct isis_circuit *circuit, int level) Line 2271  send_hello (struct isis_circuit *circuit, int level)
   struct isis_lan_hello_hdr hello_hdr;    struct isis_lan_hello_hdr hello_hdr;
   struct isis_p2p_hello_hdr p2p_hello_hdr;    struct isis_p2p_hello_hdr p2p_hello_hdr;
   unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];    unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
  unsigned long len_pointer, length, auth_tlv_offset = 0;  size_t len_pointer, length, auth_tlv_offset = 0;
   u_int32_t interval;    u_int32_t interval;
   int retval;    int retval;
   
Line 2254  send_hello (struct isis_circuit *circuit, int level) Line 2284  send_hello (struct isis_circuit *circuit, int level)
       return ISIS_WARNING;        return ISIS_WARNING;
     }      }
   
  if (!circuit->snd_stream)  isis_circuit_stream(circuit, &circuit->snd_stream);
    circuit->snd_stream = stream_new (ISO_MTU (circuit)); 
  else 
    stream_reset (circuit->snd_stream); 
   
   if (circuit->circ_type == CIRCUIT_T_BROADCAST)    if (circuit->circ_type == CIRCUIT_T_BROADCAST)
     if (level == IS_LEVEL_1)      if (level == IS_LEVEL_1)
Line 2389  send_hello (struct isis_circuit *circuit, int level) Line 2416  send_hello (struct isis_circuit *circuit, int level)
       hmac_md5 (STREAM_DATA (circuit->snd_stream),        hmac_md5 (STREAM_DATA (circuit->snd_stream),
                 stream_get_endp (circuit->snd_stream),                  stream_get_endp (circuit->snd_stream),
                 (unsigned char *) &circuit->passwd.passwd, circuit->passwd.len,                  (unsigned char *) &circuit->passwd.passwd, circuit->passwd.len,
                (caddr_t) &hmac_md5_hash);                (unsigned char *) &hmac_md5_hash);
       /* Copy the hash into the stream */        /* Copy the hash into the stream */
       memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3,        memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3,
               hmac_md5_hash, ISIS_AUTH_MD5_SIZE);                hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
Line 2399  send_hello (struct isis_circuit *circuit, int level) Line 2426  send_hello (struct isis_circuit *circuit, int level)
     {      {
       if (circuit->circ_type == CIRCUIT_T_BROADCAST)        if (circuit->circ_type == CIRCUIT_T_BROADCAST)
         {          {
          zlog_debug ("ISIS-Adj (%s): Sent L%d LAN IIH on %s, length %ld",          zlog_debug ("ISIS-Adj (%s): Sending L%d LAN IIH on %s, length %zd",
                       circuit->area->area_tag, level, circuit->interface->name,                        circuit->area->area_tag, level, circuit->interface->name,
                       /* FIXME: use %z when we stop supporting old compilers. */  
                       length);                        length);
         }          }
       else        else
         {          {
          zlog_debug ("ISIS-Adj (%s): Sent P2P IIH on %s, length %ld",          zlog_debug ("ISIS-Adj (%s): Sending P2P IIH on %s, length %zd",
                       circuit->area->area_tag, circuit->interface->name,                        circuit->area->area_tag, circuit->interface->name,
                       /* FIXME: use %z when we stop supporting old compilers. */  
                       length);                        length);
         }          }
       if (isis->debugs & DEBUG_PACKET_DUMP)        if (isis->debugs & DEBUG_PACKET_DUMP)
Line 2434  send_lan_l1_hello (struct thread *thread) Line 2459  send_lan_l1_hello (struct thread *thread)
   assert (circuit);    assert (circuit);
   circuit->u.bc.t_send_lan_hello[0] = NULL;    circuit->u.bc.t_send_lan_hello[0] = NULL;
   
     if (!(circuit->area->is_type & IS_LEVEL_1))
       {
         zlog_warn ("ISIS-Hello (%s): Trying to send L1 IIH in L2-only area",
                    circuit->area->area_tag);
         return 1;
       }
   
   if (circuit->u.bc.run_dr_elect[0])    if (circuit->u.bc.run_dr_elect[0])
     retval = isis_dr_elect (circuit, 1);      retval = isis_dr_elect (circuit, 1);
   
Line 2457  send_lan_l2_hello (struct thread *thread) Line 2489  send_lan_l2_hello (struct thread *thread)
   assert (circuit);    assert (circuit);
   circuit->u.bc.t_send_lan_hello[1] = NULL;    circuit->u.bc.t_send_lan_hello[1] = NULL;
   
     if (!(circuit->area->is_type & IS_LEVEL_2))
       {
         zlog_warn ("ISIS-Hello (%s): Trying to send L2 IIH in L1 area",
                    circuit->area->area_tag);
         return 1;
       }
   
   if (circuit->u.bc.run_dr_elect[1])    if (circuit->u.bc.run_dr_elect[1])
     retval = isis_dr_elect (circuit, 2);      retval = isis_dr_elect (circuit, 2);
   
Line 2501  build_csnp (int level, u_char * start, u_char * stop,  Line 2540  build_csnp (int level, u_char * start, u_char * stop, 
   unsigned long auth_tlv_offset = 0;    unsigned long auth_tlv_offset = 0;
   int retval = ISIS_OK;    int retval = ISIS_OK;
   
  if (circuit->snd_stream == NULL)  isis_circuit_stream(circuit, &circuit->snd_stream);
    circuit->snd_stream = stream_new (ISO_MTU (circuit)); 
  else 
    stream_reset (circuit->snd_stream); 
   
   if (level == IS_LEVEL_1)    if (level == IS_LEVEL_1)
     fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM,      fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM,
Line 2576  build_csnp (int level, u_char * start, u_char * stop,  Line 2612  build_csnp (int level, u_char * start, u_char * stop, 
       hmac_md5 (STREAM_DATA (circuit->snd_stream),        hmac_md5 (STREAM_DATA (circuit->snd_stream),
                 stream_get_endp(circuit->snd_stream),                  stream_get_endp(circuit->snd_stream),
                 (unsigned char *) &passwd->passwd, passwd->len,                  (unsigned char *) &passwd->passwd, passwd->len,
                (caddr_t) &hmac_md5_hash);                (unsigned char *) &hmac_md5_hash);
       /* Copy the hash into the stream */        /* Copy the hash into the stream */
       memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3,        memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3,
               hmac_md5_hash, ISIS_AUTH_MD5_SIZE);                hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
Line 2721  send_csnp (struct isis_circuit *circuit, int level) Line 2757  send_csnp (struct isis_circuit *circuit, int level)
   
       if (isis->debugs & DEBUG_SNP_PACKETS)        if (isis->debugs & DEBUG_SNP_PACKETS)
         {          {
          zlog_debug ("ISIS-Snp (%s): Sent L%d CSNP on %s, length %ld",          zlog_debug ("ISIS-Snp (%s): Sending L%d CSNP on %s, length %zd",
                       circuit->area->area_tag, level, circuit->interface->name,                        circuit->area->area_tag, level, circuit->interface->name,
                       stream_get_endp (circuit->snd_stream));                        stream_get_endp (circuit->snd_stream));
           for (ALL_LIST_ELEMENTS_RO (list, node, lsp))            for (ALL_LIST_ELEMENTS_RO (list, node, lsp))
Line 2828  build_psnp (int level, struct isis_circuit *circuit, s Line 2864  build_psnp (int level, struct isis_circuit *circuit, s
   unsigned long auth_tlv_offset = 0;    unsigned long auth_tlv_offset = 0;
   int retval = ISIS_OK;    int retval = ISIS_OK;
   
  if (circuit->snd_stream == NULL)  isis_circuit_stream(circuit, &circuit->snd_stream);
    circuit->snd_stream = stream_new (ISO_MTU (circuit)); 
  else 
    stream_reset (circuit->snd_stream); 
   
   if (level == IS_LEVEL_1)    if (level == IS_LEVEL_1)
     fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM,      fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM,
Line 2912  build_psnp (int level, struct isis_circuit *circuit, s Line 2945  build_psnp (int level, struct isis_circuit *circuit, s
       hmac_md5 (STREAM_DATA (circuit->snd_stream),        hmac_md5 (STREAM_DATA (circuit->snd_stream),
                 stream_get_endp(circuit->snd_stream),                  stream_get_endp(circuit->snd_stream),
                 (unsigned char *) &passwd->passwd, passwd->len,                  (unsigned char *) &passwd->passwd, passwd->len,
                (caddr_t) &hmac_md5_hash);                (unsigned char *) &hmac_md5_hash);
       /* Copy the hash into the stream */        /* Copy the hash into the stream */
       memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3,        memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3,
               hmac_md5_hash, ISIS_AUTH_MD5_SIZE);                hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
Line 2970  send_psnp (int level, struct isis_circuit *circuit) Line 3003  send_psnp (int level, struct isis_circuit *circuit)
   
       if (isis->debugs & DEBUG_SNP_PACKETS)        if (isis->debugs & DEBUG_SNP_PACKETS)
         {          {
          zlog_debug ("ISIS-Snp (%s): Sent L%d PSNP on %s, length %ld",          zlog_debug ("ISIS-Snp (%s): Sending L%d PSNP on %s, length %zd",
                       circuit->area->area_tag, level,                        circuit->area->area_tag, level,
                       circuit->interface->name,                        circuit->interface->name,
                       stream_get_endp (circuit->snd_stream));                        stream_get_endp (circuit->snd_stream));
Line 3054  send_lsp (struct thread *thread) Line 3087  send_lsp (struct thread *thread)
   struct isis_circuit *circuit;    struct isis_circuit *circuit;
   struct isis_lsp *lsp;    struct isis_lsp *lsp;
   struct listnode *node;    struct listnode *node;
     int clear_srm = 1;
   int retval = ISIS_OK;    int retval = ISIS_OK;
   
   circuit = THREAD_ARG (thread);    circuit = THREAD_ARG (thread);
   assert (circuit);    assert (circuit);
   
  if (circuit->state != C_STATE_UP || circuit->is_passive == 1)  if (!circuit->lsp_queue)
  {    return ISIS_OK;
    return retval; 
  } 
   
   node = listhead (circuit->lsp_queue);    node = listhead (circuit->lsp_queue);
   
Line 3072  send_lsp (struct thread *thread) Line 3104  send_lsp (struct thread *thread)
    * thread gets a chance to run.     * thread gets a chance to run.
    */     */
   if (!node)    if (!node)
    {    return ISIS_OK;
      return retval; 
    } 
   
     /*
      * Delete LSP from lsp_queue. If it's still in queue, it is assumed
      * as 'transmit pending', but send_lsp may never be called again.
      * Retry will happen because SRM flag will not be cleared.
      */
   lsp = listgetdata(node);    lsp = listgetdata(node);
     list_delete_node (circuit->lsp_queue, node);
   
     /* Set the last-cleared time if the queue is empty. */
     /* TODO: Is is possible that new lsps keep being added to the queue
      * that the queue is never empty? */
     if (list_isempty (circuit->lsp_queue))
       circuit->lsp_queue_last_cleared = time (NULL);
   
     if (circuit->state != C_STATE_UP || circuit->is_passive == 1)
       goto out;
   
   /*    /*
    * Do not send if levels do not match     * Do not send if levels do not match
    */     */
   if (!(lsp->level & circuit->is_type))    if (!(lsp->level & circuit->is_type))
    {    goto out;
      list_delete_node (circuit->lsp_queue, node); 
      return retval; 
    } 
   
   /*    /*
    * Do not send if we do not have adjacencies in state up on the circuit     * Do not send if we do not have adjacencies in state up on the circuit
    */     */
   if (circuit->upadjcount[lsp->level - 1] == 0)    if (circuit->upadjcount[lsp->level - 1] == 0)
       goto out;
   
     /* stream_copy will assert and stop program execution if LSP is larger than
      * the circuit's MTU. So handle and log this case here. */
     if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream))
     {      {
      list_delete_node (circuit->lsp_queue, node);      zlog_err("ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x,"
      return retval;               " cksum 0x%04x, lifetime %us on %s. LSP Size is %zu"
                " while interface stream size is %zu.",
                circuit->area->area_tag, lsp->level,
                rawlspid_print(lsp->lsp_header->lsp_id),
                ntohl(lsp->lsp_header->seq_num),
                ntohs(lsp->lsp_header->checksum),
                ntohs(lsp->lsp_header->rem_lifetime),
                circuit->interface->name,
                stream_get_endp(lsp->pdu),
                stream_get_size(circuit->snd_stream));
       if (isis->debugs & DEBUG_PACKET_DUMP)
         zlog_dump_data(STREAM_DATA(lsp->pdu), stream_get_endp(lsp->pdu));
       retval = ISIS_ERROR;
       goto out;
     }      }
   
   /* copy our lsp to the send buffer */    /* copy our lsp to the send buffer */
Line 3102  send_lsp (struct thread *thread) Line 3162  send_lsp (struct thread *thread)
   if (isis->debugs & DEBUG_UPDATE_PACKETS)    if (isis->debugs & DEBUG_UPDATE_PACKETS)
     {      {
       zlog_debug        zlog_debug
        ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x,"        ("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08x, cksum 0x%04x,"
          " lifetime %us on %s", circuit->area->area_tag, lsp->level,           " lifetime %us on %s", circuit->area->area_tag, lsp->level,
          rawlspid_print (lsp->lsp_header->lsp_id),           rawlspid_print (lsp->lsp_header->lsp_id),
          ntohl (lsp->lsp_header->seq_num),           ntohl (lsp->lsp_header->seq_num),
Line 3114  send_lsp (struct thread *thread) Line 3174  send_lsp (struct thread *thread)
                         stream_get_endp (circuit->snd_stream));                          stream_get_endp (circuit->snd_stream));
     }      }
   
     clear_srm = 0;
   retval = circuit->tx (circuit, lsp->level);    retval = circuit->tx (circuit, lsp->level);
   if (retval != ISIS_OK)    if (retval != ISIS_OK)
     {      {
      zlog_err ("ISIS-Upd (%s): Send L%d LSP on %s failed",      zlog_err ("ISIS-Upd (%s): Send L%d LSP on %s failed %s",
                 circuit->area->area_tag, lsp->level,                  circuit->area->area_tag, lsp->level,
                circuit->interface->name);                circuit->interface->name,
      return retval;                (retval == ISIS_WARNING) ? "temporarily" : "permanently");
     }      }
   
  /*out:
   * If the sending succeeded, we can del the lsp from circuits  if (clear_srm
   * lsp_queue      || (retval == ISIS_OK && circuit->circ_type == CIRCUIT_T_BROADCAST)
   */      || (retval != ISIS_OK && retval != ISIS_WARNING))
  list_delete_node (circuit->lsp_queue, node);    {
       /* SRM flag will trigger retransmission. We will not retransmit if we
        * encountered a fatal error.
        * On success, they should only be cleared if it's a broadcast circuit.
        * On a P2P circuit, we will wait for the ack from the neighbor to clear
        * the fag.
        */
       ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
     }
   
   /* Set the last-cleared time if the queue is empty. */  
   /* TODO: Is is possible that new lsps keep being added to the queue  
    * that the queue is never empty? */  
   if (list_isempty (circuit->lsp_queue))  
     circuit->lsp_queue_last_cleared = time (NULL);  
   
   /*  
    * On broadcast circuits also the SRMflag can be cleared  
    */  
   if (circuit->circ_type == CIRCUIT_T_BROADCAST)  
     ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);  
   
   return retval;    return retval;
 }  }
   
Line 3153  ack_lsp (struct isis_link_state_hdr *hdr, struct isis_ Line 3210  ack_lsp (struct isis_link_state_hdr *hdr, struct isis_
   u_int16_t length;    u_int16_t length;
   struct isis_fixed_hdr fixed_hdr;    struct isis_fixed_hdr fixed_hdr;
   
  if (!circuit->snd_stream)  isis_circuit_stream(circuit, &circuit->snd_stream);
    circuit->snd_stream = stream_new (ISO_MTU (circuit)); 
  else 
    stream_reset (circuit->snd_stream); 
   
   //  fill_llc_hdr (stream);    //  fill_llc_hdr (stream);
   if (level == IS_LEVEL_1)    if (level == IS_LEVEL_1)

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


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