File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / isisd / isis_tlv.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:39 2013 UTC (11 years ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

    1: /*
    2:  * IS-IS Rout(e)ing protocol - isis_tlv.c
    3:  *                             IS-IS TLV related routines
    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 "log.h"
   27: #include "linklist.h"
   28: #include "stream.h"
   29: #include "memory.h"
   30: #include "prefix.h"
   31: #include "vty.h"
   32: #include "if.h"
   33: 
   34: #include "isisd/dict.h"
   35: #include "isisd/isis_constants.h"
   36: #include "isisd/isis_common.h"
   37: #include "isisd/isis_flags.h"
   38: #include "isisd/isis_circuit.h"
   39: #include "isisd/isis_tlv.h"
   40: #include "isisd/isisd.h"
   41: #include "isisd/isis_dynhn.h"
   42: #include "isisd/isis_misc.h"
   43: #include "isisd/isis_pdu.h"
   44: #include "isisd/isis_lsp.h"
   45: 
   46: void
   47: free_tlv (void *val)
   48: {
   49:   XFREE (MTYPE_ISIS_TLV, val);
   50: 
   51:   return;
   52: }
   53: 
   54: /*
   55:  * Called after parsing of a PDU. There shouldn't be any tlv's left, so this
   56:  * is only a caution to avoid memory leaks
   57:  */
   58: void
   59: free_tlvs (struct tlvs *tlvs)
   60: {
   61:   if (tlvs->area_addrs)
   62:     list_delete (tlvs->area_addrs);
   63:   if (tlvs->is_neighs)
   64:     list_delete (tlvs->is_neighs);
   65:   if (tlvs->te_is_neighs)
   66:     list_delete (tlvs->te_is_neighs);
   67:   if (tlvs->es_neighs)
   68:     list_delete (tlvs->es_neighs);
   69:   if (tlvs->lsp_entries)
   70:     list_delete (tlvs->lsp_entries);
   71:   if (tlvs->prefix_neighs)
   72:     list_delete (tlvs->prefix_neighs);
   73:   if (tlvs->lan_neighs)
   74:     list_delete (tlvs->lan_neighs);
   75:   if (tlvs->ipv4_addrs)
   76:     list_delete (tlvs->ipv4_addrs);
   77:   if (tlvs->ipv4_int_reachs)
   78:     list_delete (tlvs->ipv4_int_reachs);
   79:   if (tlvs->ipv4_ext_reachs)
   80:     list_delete (tlvs->ipv4_ext_reachs);
   81:   if (tlvs->te_ipv4_reachs)
   82:     list_delete (tlvs->te_ipv4_reachs);
   83: #ifdef HAVE_IPV6
   84:   if (tlvs->ipv6_addrs)
   85:     list_delete (tlvs->ipv6_addrs);
   86:   if (tlvs->ipv6_reachs)
   87:     list_delete (tlvs->ipv6_reachs);
   88: #endif /* HAVE_IPV6 */
   89: 
   90:   memset (tlvs, 0, sizeof (struct tlvs));
   91: 
   92:   return;
   93: }
   94: 
   95: /*
   96:  * Parses the tlvs found in the variant length part of the PDU.
   97:  * Caller tells with flags in "expected" which TLV's it is interested in.
   98:  */
   99: int
  100: parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
  101: 	    u_int32_t * found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset)
  102: {
  103:   u_char type, length;
  104:   struct lan_neigh *lan_nei;
  105:   struct area_addr *area_addr;
  106:   struct is_neigh *is_nei;
  107:   struct te_is_neigh *te_is_nei;
  108:   struct es_neigh *es_nei;
  109:   struct lsp_entry *lsp_entry;
  110:   struct in_addr *ipv4_addr;
  111:   struct ipv4_reachability *ipv4_reach;
  112:   struct te_ipv4_reachability *te_ipv4_reach;
  113: #ifdef HAVE_IPV6
  114:   struct in6_addr *ipv6_addr;
  115:   struct ipv6_reachability *ipv6_reach;
  116:   int prefix_octets;
  117: #endif /* HAVE_IPV6 */
  118:   u_char virtual;
  119:   int value_len, retval = ISIS_OK;
  120:   u_char *start = stream, *pnt = stream, *endpnt;
  121: 
  122:   *found = 0;
  123:   memset (tlvs, 0, sizeof (struct tlvs));
  124: 
  125:   while (pnt < stream + size - 2)
  126:     {
  127:       type = *pnt;
  128:       length = *(pnt + 1);
  129:       pnt += 2;
  130:       value_len = 0;
  131:       if (pnt + length > stream + size)
  132: 	{
  133: 	  zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet "
  134: 		     "boundaries", areatag, type, length);
  135: 	  retval = ISIS_WARNING;
  136: 	  break;
  137: 	}
  138:       switch (type)
  139: 	{
  140: 	case AREA_ADDRESSES:
  141: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  142: 	   * |                        Address Length                         | 
  143: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  144: 	   * |                         Area Address                          | 
  145: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  146: 	   * :                                                               :
  147: 	   */
  148: 	  *found |= TLVFLAG_AREA_ADDRS;
  149: #ifdef EXTREME_TLV_DEBUG
  150: 	  zlog_debug ("TLV Area Adresses len %d", length);
  151: #endif /* EXTREME_TLV_DEBUG */
  152: 	  if (*expected & TLVFLAG_AREA_ADDRS)
  153: 	    {
  154: 	      while (length > value_len)
  155: 		{
  156: 		  area_addr = (struct area_addr *) pnt;
  157: 		  value_len += area_addr->addr_len + 1;
  158: 		  pnt += area_addr->addr_len + 1;
  159: 		  if (!tlvs->area_addrs)
  160: 		    tlvs->area_addrs = list_new ();
  161: 		  listnode_add (tlvs->area_addrs, area_addr);
  162: 		}
  163: 	    }
  164: 	  else
  165: 	    {
  166: 	      pnt += length;
  167: 	    }
  168: 	  break;
  169: 
  170: 	case IS_NEIGHBOURS:
  171: 	  *found |= TLVFLAG_IS_NEIGHS;
  172: #ifdef EXTREME_TLV_DEBUG
  173: 	  zlog_debug ("ISIS-TLV (%s): IS Neighbours length %d",
  174: 		      areatag, length);
  175: #endif /* EXTREME_TLV_DEBUG */
  176: 	  if (TLVFLAG_IS_NEIGHS & *expected)
  177: 	    {
  178: 	      /* +-------+-------+-------+-------+-------+-------+-------+-------+
  179: 	       * |                        Virtual Flag                           | 
  180: 	       * +-------+-------+-------+-------+-------+-------+-------+-------+
  181: 	       */
  182: 	      virtual = *pnt;	/* FIXME: what is the use for this? */
  183: 	      pnt++;
  184: 	      value_len++;
  185: 	      /* +-------+-------+-------+-------+-------+-------+-------+-------+
  186: 	       * |   0   |  I/E  |               Default Metric                  | 
  187: 	       * +-------+-------+-------+-------+-------+-------+-------+-------+
  188: 	       * |   S   |  I/E  |               Delay Metric                    |
  189: 	       * +-------+-------+-------+-------+-------+-------+-------+-------+
  190: 	       * |   S   |  I/E  |               Expense Metric                  |
  191: 	       * +-------+-------+-------+-------+-------+-------+-------+-------+
  192: 	       * |   S   |  I/E  |               Error Metric                    |
  193: 	       * +-------+-------+-------+-------+-------+-------+-------+-------+
  194: 	       * |                        Neighbour ID                           |
  195: 	       * +---------------------------------------------------------------+
  196: 	       * :                                                               :
  197: 	       */
  198: 	      while (length > value_len)
  199: 		{
  200: 		  is_nei = (struct is_neigh *) pnt;
  201: 		  value_len += 4 + ISIS_SYS_ID_LEN + 1;
  202: 		  pnt += 4 + ISIS_SYS_ID_LEN + 1;
  203: 		  if (!tlvs->is_neighs)
  204: 		    tlvs->is_neighs = list_new ();
  205: 		  listnode_add (tlvs->is_neighs, is_nei);
  206: 		}
  207: 	    }
  208: 	  else
  209: 	    {
  210: 	      pnt += length;
  211: 	    }
  212: 	  break;
  213: 
  214: 	case TE_IS_NEIGHBOURS:
  215: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  216: 	   * |                        Neighbour ID                           | 7
  217: 	   * +---------------------------------------------------------------+
  218: 	   * |                        TE Metric                              | 3
  219: 	   * +---------------------------------------------------------------+
  220: 	   * |                        SubTLVs Length                         | 1
  221: 	   * +---------------------------------------------------------------+
  222: 	   * :                                                               :
  223: 	   */
  224: 	  *found |= TLVFLAG_TE_IS_NEIGHS;
  225: #ifdef EXTREME_TLV_DEBUG
  226: 	  zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d",
  227: 		     areatag, length);
  228: #endif /* EXTREME_TLV_DEBUG */
  229: 	  if (TLVFLAG_TE_IS_NEIGHS & *expected)
  230: 	    {
  231: 	      while (length > value_len)
  232: 		{
  233: 		  te_is_nei = (struct te_is_neigh *) pnt;
  234: 		  value_len += 11;
  235: 		  pnt += 11;
  236: 		  /* FIXME - subtlvs are handled here, for now we skip */
  237: 		  value_len += te_is_nei->sub_tlvs_length;
  238: 		  pnt += te_is_nei->sub_tlvs_length;
  239: 
  240: 		  if (!tlvs->te_is_neighs)
  241: 		    tlvs->te_is_neighs = list_new ();
  242: 		  listnode_add (tlvs->te_is_neighs, te_is_nei);
  243: 		}
  244: 	    }
  245: 	  else
  246: 	    {
  247: 	      pnt += length;
  248: 	    }
  249: 	  break;
  250: 
  251: 	case ES_NEIGHBOURS:
  252: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  253: 	   * |   0   |  I/E  |               Default Metric                  | 
  254: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  255: 	   * |   S   |  I/E  |               Delay Metric                    |
  256: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  257: 	   * |   S   |  I/E  |               Expense Metric                  |
  258: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  259: 	   * |   S   |  I/E  |               Error Metric                    |
  260: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  261: 	   * |                        Neighbour ID                           |
  262: 	   * +---------------------------------------------------------------+
  263: 	   * |                        Neighbour ID                           |
  264: 	   * +---------------------------------------------------------------+
  265: 	   * :                                                               :
  266: 	   */
  267: #ifdef EXTREME_TLV_DEBUG
  268: 	  zlog_debug ("ISIS-TLV (%s): ES Neighbours length %d",
  269: 		     areatag, length);
  270: #endif /* EXTREME_TLV_DEBUG */
  271: 	  *found |= TLVFLAG_ES_NEIGHS;
  272: 	  if (*expected & TLVFLAG_ES_NEIGHS)
  273: 	    {
  274: 	      es_nei = (struct es_neigh *) pnt;
  275: 	      value_len += 4;
  276: 	      pnt += 4;
  277: 	      while (length > value_len)
  278: 		{
  279: 		  /* FIXME FIXME FIXME - add to the list */
  280: 		  /*          sys_id->id = pnt; */
  281: 		  value_len += ISIS_SYS_ID_LEN;
  282: 		  pnt += ISIS_SYS_ID_LEN;
  283: 		  /*  if (!es_nei->neigh_ids) es_nei->neigh_ids = sysid; */
  284: 		}
  285: 	      if (!tlvs->es_neighs)
  286: 		tlvs->es_neighs = list_new ();
  287: 	      listnode_add (tlvs->es_neighs, es_nei);
  288: 	    }
  289: 	  else
  290: 	    {
  291: 	      pnt += length;
  292: 	    }
  293: 	  break;
  294: 
  295: 	case LAN_NEIGHBOURS:
  296: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  297: 	   * |                        LAN Address                            | 
  298: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  299: 	   * :                                                               :
  300: 	   */
  301: 	  *found |= TLVFLAG_LAN_NEIGHS;
  302: #ifdef EXTREME_TLV_DEBUG
  303: 	  zlog_debug ("ISIS-TLV (%s): LAN Neigbours length %d",
  304: 		      areatag, length);
  305: #endif /* EXTREME_TLV_DEBUG */
  306: 	  if (TLVFLAG_LAN_NEIGHS & *expected)
  307: 	    {
  308: 	      while (length > value_len)
  309: 		{
  310: 		  lan_nei = (struct lan_neigh *) pnt;
  311: 		  if (!tlvs->lan_neighs)
  312: 		    tlvs->lan_neighs = list_new ();
  313: 		  listnode_add (tlvs->lan_neighs, lan_nei);
  314: 		  value_len += ETH_ALEN;
  315: 		  pnt += ETH_ALEN;
  316: 		}
  317: 	    }
  318: 	  else
  319: 	    {
  320: 	      pnt += length;
  321: 	    }
  322: 	  break;
  323: 
  324: 	case PADDING:
  325: #ifdef EXTREME_TLV_DEBUG
  326: 	  zlog_debug ("TLV padding %d", length);
  327: #endif /* EXTREME_TLV_DEBUG */
  328: 	  pnt += length;
  329: 	  break;
  330: 
  331: 	case LSP_ENTRIES:
  332: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  333: 	   * |                     Remaining Lifetime                        | 2
  334: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  335: 	   * |                         LSP ID                                | id+2
  336: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  337: 	   * |                   LSP Sequence Number                         | 4
  338: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  339: 	   * |                        Checksum                               | 2
  340: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  341: 	   */
  342: #ifdef EXTREME_TLV_DEBUG
  343: 	  zlog_debug ("ISIS-TLV (%s): LSP Entries length %d", areatag, length);
  344: #endif /* EXTREME_TLV_DEBUG */
  345: 	  *found |= TLVFLAG_LSP_ENTRIES;
  346: 	  if (TLVFLAG_LSP_ENTRIES & *expected)
  347: 	    {
  348: 	      while (length > value_len)
  349: 		{
  350: 		  lsp_entry = (struct lsp_entry *) pnt;
  351: 		  value_len += 10 + ISIS_SYS_ID_LEN;
  352: 		  pnt += 10 + ISIS_SYS_ID_LEN;
  353: 		  if (!tlvs->lsp_entries)
  354: 		    tlvs->lsp_entries = list_new ();
  355: 		  listnode_add (tlvs->lsp_entries, lsp_entry);
  356: 		}
  357: 	    }
  358: 	  else
  359: 	    {
  360: 	      pnt += length;
  361: 	    }
  362: 	  break;
  363: 
  364: 	case CHECKSUM:
  365: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  366: 	   * |                   16 bit fletcher CHECKSUM                    |
  367: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  368: 	   * :                                                               :
  369: 	   */
  370: 	  *found |= TLVFLAG_CHECKSUM;
  371: #ifdef EXTREME_TLV_DEBUG
  372: 	  zlog_debug ("ISIS-TLV (%s): Checksum length %d", areatag, length);
  373: #endif /* EXTREME_TLV_DEBUG */
  374: 	  if (*expected & TLVFLAG_CHECKSUM)
  375: 	    {
  376: 	      tlvs->checksum = (struct checksum *) pnt;
  377: 	    }
  378: 	  pnt += length;
  379: 	  break;
  380: 
  381: 	case PROTOCOLS_SUPPORTED:
  382: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  383: 	   * |                       NLPID                                   |
  384: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  385: 	   * :                                                               :
  386: 	   */
  387: 	  *found |= TLVFLAG_NLPID;
  388: #ifdef EXTREME_TLV_DEBUG
  389: 	  zlog_debug ("ISIS-TLV (%s): Protocols Supported length %d",
  390: 		      areatag, length);
  391: #endif /* EXTREME_TLV_DEBUG */
  392: 	  if (*expected & TLVFLAG_NLPID)
  393: 	    {
  394: 	      tlvs->nlpids = (struct nlpids *) (pnt - 1);
  395: 	    }
  396: 	  pnt += length;
  397: 	  break;
  398: 
  399: 	case IPV4_ADDR:
  400: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  401: 	   * +                 IP version 4 address                          + 4
  402: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  403: 	   * :                                                               :
  404: 	   */
  405: 	  *found |= TLVFLAG_IPV4_ADDR;
  406: #ifdef EXTREME_TLV_DEBUG
  407: 	  zlog_debug ("ISIS-TLV (%s): IPv4 Address length %d",
  408: 		      areatag, length);
  409: #endif /* EXTREME_TLV_DEBUG */
  410: 	  if (*expected & TLVFLAG_IPV4_ADDR)
  411: 	    {
  412: 	      while (length > value_len)
  413: 		{
  414: 		  ipv4_addr = (struct in_addr *) pnt;
  415: #ifdef EXTREME_TLV_DEBUG
  416: 		  zlog_debug ("ISIS-TLV (%s) : IP ADDR %s, pnt %p", areatag,
  417: 			      inet_ntoa (*ipv4_addr), pnt);
  418: #endif /* EXTREME_TLV_DEBUG */
  419: 		  if (!tlvs->ipv4_addrs)
  420: 		    tlvs->ipv4_addrs = list_new ();
  421: 		  listnode_add (tlvs->ipv4_addrs, ipv4_addr);
  422: 		  value_len += 4;
  423: 		  pnt += 4;
  424: 		}
  425: 	    }
  426: 	  else
  427: 	    {
  428: 	      pnt += length;
  429: 	    }
  430: 	  break;
  431: 
  432: 	case AUTH_INFO:
  433: 	  *found |= TLVFLAG_AUTH_INFO;
  434: #ifdef EXTREME_TLV_DEBUG
  435: 	  zlog_debug ("ISIS-TLV (%s): IS-IS Authentication Information",
  436: 		      areatag);
  437: #endif
  438: 	  if (*expected & TLVFLAG_AUTH_INFO)
  439: 	    {
  440: 	      tlvs->auth_info.type = *pnt;
  441:               if (length == 0)
  442:                 {
  443:                   zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) "
  444:                              "incorrect.", areatag, type, length);
  445:                   return ISIS_WARNING;
  446:                 }
  447:               --length;
  448: 	      tlvs->auth_info.len = length;
  449: 	      pnt++;
  450: 	      memcpy (tlvs->auth_info.passwd, pnt, length);
  451:               /* Return the authentication tlv pos for later computation
  452:                * of MD5 (RFC 5304, 2)
  453:                */
  454:               if (auth_tlv_offset)
  455:                 *auth_tlv_offset += (pnt - start - 3);
  456:               pnt += length;
  457: 	    }
  458: 	  else
  459: 	    {
  460: 	      pnt += length;
  461: 	    }
  462: 	  break;
  463: 
  464: 	case DYNAMIC_HOSTNAME:
  465: 	  *found |= TLVFLAG_DYN_HOSTNAME;
  466: #ifdef EXTREME_TLV_DEBUG
  467: 	  zlog_debug ("ISIS-TLV (%s): Dynamic Hostname length %d",
  468: 		      areatag, length);
  469: #endif /* EXTREME_TLV_DEBUG */
  470: 	  if (*expected & TLVFLAG_DYN_HOSTNAME)
  471: 	    {
  472: 	      /* the length is also included in the pointed struct */
  473: 	      tlvs->hostname = (struct hostname *) (pnt - 1);
  474: 	    }
  475: 	  pnt += length;
  476: 	  break;
  477: 
  478: 	case TE_ROUTER_ID:
  479: 	  /* +---------------------------------------------------------------+
  480: 	   * +                         Router ID                             + 4
  481: 	   * +---------------------------------------------------------------+
  482: 	   */
  483: 	  *found |= TLVFLAG_TE_ROUTER_ID;
  484: #ifdef EXTREME_TLV_DEBUG
  485: 	  zlog_debug ("ISIS-TLV (%s): TE Router ID %d", areatag, length);
  486: #endif /* EXTREME_TLV_DEBUG */
  487: 	  if (*expected & TLVFLAG_TE_ROUTER_ID)
  488: 	    tlvs->router_id = (struct te_router_id *) (pnt);
  489: 	  pnt += length;
  490: 	  break;
  491: 
  492: 	case IPV4_INT_REACHABILITY:
  493: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  494: 	   * |   0   |  I/E  |               Default Metric                  | 1
  495: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  496: 	   * |   S   |  I/E  |               Delay Metric                    | 1
  497: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  498: 	   * |   S   |  I/E  |               Expense Metric                  | 1
  499: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  500: 	   * |   S   |  I/E  |               Error Metric                    | 1
  501: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  502: 	   * |                        ip address                             | 4
  503: 	   * +---------------------------------------------------------------+
  504: 	   * |                        address mask                           | 4
  505: 	   * +---------------------------------------------------------------+
  506: 	   * :                                                               :
  507: 	   */
  508: 	  *found |= TLVFLAG_IPV4_INT_REACHABILITY;
  509: #ifdef EXTREME_TLV_DEBUG
  510: 	  zlog_debug ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
  511: 		      areatag, length);
  512: #endif /* EXTREME_TLV_DEBUG */
  513: 	  if (*expected & TLVFLAG_IPV4_INT_REACHABILITY)
  514: 	    {
  515: 	      while (length > value_len)
  516: 		{
  517: 		  ipv4_reach = (struct ipv4_reachability *) pnt;
  518: 		  if (!tlvs->ipv4_int_reachs)
  519: 		    tlvs->ipv4_int_reachs = list_new ();
  520: 		  listnode_add (tlvs->ipv4_int_reachs, ipv4_reach);
  521: 		  value_len += 12;
  522: 		  pnt += 12;
  523: 		}
  524: 	    }
  525: 	  else
  526: 	    {
  527: 	      pnt += length;
  528: 	    }
  529: 	  break;
  530: 
  531: 	case IPV4_EXT_REACHABILITY:
  532: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  533: 	   * |   0   |  I/E  |               Default Metric                  | 1
  534: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  535: 	   * |   S   |  I/E  |               Delay Metric                    | 1
  536: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  537: 	   * |   S   |  I/E  |               Expense Metric                  | 1
  538: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  539: 	   * |   S   |  I/E  |               Error Metric                    | 1
  540: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  541: 	   * |                        ip address                             | 4
  542: 	   * +---------------------------------------------------------------+
  543: 	   * |                        address mask                           | 4
  544: 	   * +---------------------------------------------------------------+
  545: 	   * :                                                               :
  546: 	   */
  547: 	  *found |= TLVFLAG_IPV4_EXT_REACHABILITY;
  548: #ifdef EXTREME_TLV_DEBUG
  549: 	  zlog_debug ("ISIS-TLV (%s): IPv4 external Reachability length %d",
  550: 		      areatag, length);
  551: #endif /* EXTREME_TLV_DEBUG */
  552: 	  if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY)
  553: 	    {
  554: 	      while (length > value_len)
  555: 		{
  556: 		  ipv4_reach = (struct ipv4_reachability *) pnt;
  557: 		  if (!tlvs->ipv4_ext_reachs)
  558: 		    tlvs->ipv4_ext_reachs = list_new ();
  559: 		  listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach);
  560: 		  value_len += 12;
  561: 		  pnt += 12;
  562: 		}
  563: 	    }
  564: 	  else
  565: 	    {
  566: 	      pnt += length;
  567: 	    }
  568: 	  break;
  569: 
  570: 	case TE_IPV4_REACHABILITY:
  571: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  572: 	   * |                        TE Metric                              | 4
  573: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  574: 	   * |  U/D  | sTLV? |               Prefix Mask Len                 | 1
  575: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  576: 	   * |                           Prefix                              | 0-4
  577: 	   * +---------------------------------------------------------------+
  578: 	   * |                         sub tlvs                              |
  579: 	   * +---------------------------------------------------------------+
  580: 	   * :                                                               :
  581: 	   */
  582: 	  *found |= TLVFLAG_TE_IPV4_REACHABILITY;
  583: #ifdef EXTREME_TLV_DEBUG
  584: 	  zlog_debug ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
  585: 		      areatag, length);
  586: #endif /* EXTREME_TLV_DEBUG */
  587: 	  endpnt = pnt + length;
  588: 	  if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
  589: 	    {
  590: 	      while (length > value_len)
  591: 		{
  592: 		  te_ipv4_reach = (struct te_ipv4_reachability *) pnt;
  593: 		  if ((te_ipv4_reach->control & 0x3F) > IPV4_MAX_BITLEN)
  594: 		    {
  595: 		      zlog_warn ("ISIS-TLV (%s): invalid IPv4 extended reach"
  596: 				 "ability prefix length %d", areatag,
  597: 				 te_ipv4_reach->control & 0x3F);
  598: 		      retval = ISIS_WARNING;
  599: 		      break;
  600: 		    }
  601: 		  if (!tlvs->te_ipv4_reachs)
  602: 		    tlvs->te_ipv4_reachs = list_new ();
  603: 		  listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach);
  604: 		  /* this trickery is permitable since no subtlvs are defined */
  605: 		  value_len += 5 + ((te_ipv4_reach->control & 0x3F) ?
  606: 				    ((((te_ipv4_reach->control & 0x3F) -
  607: 				       1) >> 3) + 1) : 0);
  608: 		  pnt += 5 + ((te_ipv4_reach->control & 0x3F) ?
  609: 		              ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0);
  610: 		}
  611: 	    }
  612: 
  613: 	  pnt = endpnt;
  614: 	  break;
  615: 
  616: #ifdef  HAVE_IPV6
  617: 	case IPV6_ADDR:
  618: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  619: 	   * +                 IP version 6 address                          + 16
  620: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  621: 	   * :                                                               :
  622: 	   */
  623: 	  *found |= TLVFLAG_IPV6_ADDR;
  624: #ifdef EXTREME_TLV_DEBUG
  625: 	  zlog_debug ("ISIS-TLV (%s): IPv6 Address length %d",
  626: 		      areatag, length);
  627: #endif /* EXTREME_TLV_DEBUG */
  628: 	  if (*expected & TLVFLAG_IPV6_ADDR)
  629: 	    {
  630: 	      while (length > value_len)
  631: 		{
  632: 		  ipv6_addr = (struct in6_addr *) pnt;
  633: 		  if (!tlvs->ipv6_addrs)
  634: 		    tlvs->ipv6_addrs = list_new ();
  635: 		  listnode_add (tlvs->ipv6_addrs, ipv6_addr);
  636: 		  value_len += 16;
  637: 		  pnt += 16;
  638: 		}
  639: 	    }
  640: 	  else
  641: 	    {
  642: 	      pnt += length;
  643: 	    }
  644: 	  break;
  645: 
  646: 	case IPV6_REACHABILITY:
  647: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  648: 	   * |                 Default Metric                                | 4 
  649: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  650: 	   * |                        Control Informantion                   |
  651: 	   * +---------------------------------------------------------------+
  652: 	   * |                        IPv6 Prefix Length                     |--+
  653: 	   * +---------------------------------------------------------------+  |
  654: 	   * |                        IPv6 Prefix                            |<-+
  655: 	   * +---------------------------------------------------------------+
  656: 	   */
  657: 	  *found |= TLVFLAG_IPV6_REACHABILITY;
  658: 	  endpnt = pnt + length;
  659: 
  660: 	  if (*expected & TLVFLAG_IPV6_REACHABILITY)
  661: 	    {
  662: 	      while (length > value_len)
  663: 		{
  664: 		  ipv6_reach = (struct ipv6_reachability *) pnt;
  665: 		  if (ipv6_reach->prefix_len > IPV6_MAX_BITLEN)
  666: 		    {
  667: 		      zlog_warn ("ISIS-TLV (%s): invalid IPv6 extended reach"
  668: 				 "ability prefix length %d", areatag,
  669: 				 ipv6_reach->prefix_len);
  670: 		      retval = ISIS_WARNING;
  671: 		      break;
  672: 		    }
  673: 
  674: 		  prefix_octets = ((ipv6_reach->prefix_len + 7) / 8);
  675: 		  value_len += prefix_octets + 6;
  676: 		  pnt += prefix_octets + 6;
  677: 		  /* FIXME: sub-tlvs */
  678: 		  if (!tlvs->ipv6_reachs)
  679: 		    tlvs->ipv6_reachs = list_new ();
  680: 		  listnode_add (tlvs->ipv6_reachs, ipv6_reach);
  681: 		}
  682: 	    }
  683: 
  684: 	  pnt = endpnt;
  685: 	  break;
  686: #endif /* HAVE_IPV6 */
  687: 
  688: 	case WAY3_HELLO:
  689: 	  /* +---------------------------------------------------------------+
  690: 	   * |                  Adjacency state                              | 1
  691: 	   * +---------------------------------------------------------------+
  692: 	   * |                  Extended Local Circuit ID                    | 4
  693: 	   * +---------------------------------------------------------------+
  694: 	   * |                  Neighbor System ID (If known)                | 0-8
  695: 	   *                                      (probably 6)
  696: 	   * +---------------------------------------------------------------+
  697: 	   * |                  Neighbor Local Circuit ID (If known)         | 4
  698: 	   * +---------------------------------------------------------------+
  699: 	   */
  700: 	  *found |= TLVFLAG_3WAY_HELLO;
  701: 	  if (*expected & TLVFLAG_3WAY_HELLO)
  702: 	    {
  703: 	      while (length > value_len)
  704: 		{
  705: 		  /* FIXME: make this work */
  706: /*           Adjacency State (one octet):
  707:               0 = Up
  708:               1 = Initializing
  709:               2 = Down
  710:             Extended Local Circuit ID (four octets)
  711:             Neighbor System ID if known (zero to eight octets)
  712:             Neighbor Extended Local Circuit ID (four octets, if Neighbor
  713:               System ID is present) */
  714: 		  pnt += length;
  715: 		  value_len += length;
  716: 		}
  717: 	    }
  718: 	  else
  719: 	    {
  720: 	      pnt += length;
  721: 	    }
  722: 
  723: 	  break;
  724: 	case GRACEFUL_RESTART:
  725: 	  /* +-------+-------+-------+-------+-------+-------+-------+-------+
  726: 	   * |         Reserved                      |  SA   |  RA   |  RR   | 1
  727: 	   * +-------+-------+-------+-------+-------+-------+-------+-------+
  728: 	   * |                          Remaining Time                       | 2
  729: 	   * +---------------------------------------------------------------+
  730: 	   * |                Restarting Neighbor ID (If known)              | 0-8
  731: 	   * +---------------------------------------------------------------+
  732: 	   */
  733: 	  *found |= TLVFLAG_GRACEFUL_RESTART;
  734: 	  if (*expected & TLVFLAG_GRACEFUL_RESTART)
  735: 	    {
  736: 	      /* FIXME: make this work */
  737: 	    }
  738: 	  pnt += length;
  739: 	  break;
  740: 
  741: 	default:
  742: 	  zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
  743: 		     areatag, type, length);
  744: 
  745: 	  retval = ISIS_WARNING;
  746: 	  pnt += length;
  747: 	  break;
  748: 	}
  749:     }
  750: 
  751:   return retval;
  752: }
  753: 
  754: int
  755: add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
  756: {
  757:   if ((stream_get_size (stream) - stream_get_endp (stream)) <
  758:       (((unsigned)len) + 2))
  759:     {
  760:       zlog_warn ("No room for TLV of type %d "
  761:                  "(total size %d available %d required %d)",
  762:                  tag, (int)stream_get_size (stream),
  763:                  (int)(stream_get_size (stream) - stream_get_endp (stream)),
  764:                  len+2);
  765:       return ISIS_WARNING;
  766:     }
  767: 
  768:   stream_putc (stream, tag);	/* TAG */
  769:   stream_putc (stream, len);	/* LENGTH */
  770:   stream_put (stream, value, (int) len);	/* VALUE */
  771: 
  772: #ifdef EXTREME_DEBUG
  773:   zlog_debug ("Added TLV %d len %d", tag, len);
  774: #endif /* EXTREME DEBUG */
  775:   return ISIS_OK;
  776: }
  777: 
  778: int
  779: tlv_add_area_addrs (struct list *area_addrs, struct stream *stream)
  780: {
  781:   struct listnode *node;
  782:   struct area_addr *area_addr;
  783: 
  784:   u_char value[255];
  785:   u_char *pos = value;
  786: 
  787:   for (ALL_LIST_ELEMENTS_RO (area_addrs, node, area_addr))
  788:     {
  789:       if (pos - value + area_addr->addr_len > 255)
  790: 	goto err;
  791:       *pos = area_addr->addr_len;
  792:       pos++;
  793:       memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len);
  794:       pos += area_addr->addr_len;
  795:     }
  796: 
  797:   return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
  798: 
  799: err:
  800:   zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
  801:   return ISIS_WARNING;
  802: }
  803: 
  804: int
  805: tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
  806: {
  807:   struct listnode *node;
  808:   struct is_neigh *is_neigh;
  809:   u_char value[255];
  810:   u_char *pos = value;
  811:   int retval;
  812: 
  813:   *pos = 0;			/*is_neigh->virtual; */
  814:   pos++;
  815: 
  816:   for (ALL_LIST_ELEMENTS_RO (is_neighs, node, is_neigh))
  817:     {
  818:       if (pos - value + IS_NEIGHBOURS_LEN > 255)
  819: 	{
  820: 	  retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
  821: 	  if (retval != ISIS_OK)
  822: 	    return retval;
  823: 	  pos = value;
  824: 	}
  825:       *pos = is_neigh->metrics.metric_default;
  826:       pos++;
  827:       *pos = is_neigh->metrics.metric_delay;
  828:       pos++;
  829:       *pos = is_neigh->metrics.metric_expense;
  830:       pos++;
  831:       *pos = is_neigh->metrics.metric_error;
  832:       pos++;
  833:       memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
  834:       pos += ISIS_SYS_ID_LEN + 1;
  835:     }
  836: 
  837:   return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
  838: }
  839: 
  840: int
  841: tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream)
  842: {
  843:   struct listnode *node;
  844:   struct te_is_neigh *te_is_neigh;
  845:   u_char value[255];
  846:   u_char *pos = value;
  847:   int retval;
  848: 
  849:   for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh))
  850:     {
  851:       /* FIXME: This will be wrong if we are going to add TE sub TLVs. */
  852:       if (pos - value + IS_NEIGHBOURS_LEN > 255)
  853:         {
  854:           retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
  855:           if (retval != ISIS_OK)
  856:             return retval;
  857:           pos = value;
  858:         }
  859:       
  860:       memcpy (pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
  861:       pos += ISIS_SYS_ID_LEN + 1;
  862:       memcpy (pos, te_is_neigh->te_metric, 3);
  863:       pos += 3;
  864:       /* Sub TLVs length. */
  865:       *pos = 0;
  866:       pos++;
  867:     }
  868: 
  869:   return add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
  870: }
  871: 
  872: int
  873: tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
  874: {
  875:   struct listnode *node;
  876:   u_char *snpa;
  877:   u_char value[255];
  878:   u_char *pos = value;
  879:   int retval;
  880: 
  881:   for (ALL_LIST_ELEMENTS_RO (lan_neighs, node, snpa))
  882:     {
  883:       if (pos - value + ETH_ALEN > 255)
  884: 	{
  885: 	  retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
  886: 	  if (retval != ISIS_OK)
  887: 	    return retval;
  888: 	  pos = value;
  889: 	}
  890:       memcpy (pos, snpa, ETH_ALEN);
  891:       pos += ETH_ALEN;
  892:     }
  893: 
  894:   return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
  895: }
  896: 
  897: int
  898: tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
  899: {
  900:   return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream);
  901: }
  902: 
  903: int
  904: tlv_add_authinfo (u_char auth_type, u_char auth_len, u_char *auth_value,
  905: 		  struct stream *stream)
  906: {
  907:   u_char value[255];
  908:   u_char *pos = value;
  909:   *pos++ = auth_type;
  910:   memcpy (pos, auth_value, auth_len);
  911: 
  912:   return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
  913: }
  914: 
  915: int
  916: tlv_add_checksum (struct checksum *checksum, struct stream *stream)
  917: {
  918:   u_char value[255];
  919:   u_char *pos = value;
  920:   return add_tlv (CHECKSUM, pos - value, value, stream);
  921: }
  922: 
  923: int
  924: tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
  925: {
  926:   struct listnode *node;
  927:   struct prefix_ipv4 *ipv4;
  928:   u_char value[255];
  929:   u_char *pos = value;
  930:   int retval;
  931: 
  932:   for (ALL_LIST_ELEMENTS_RO (ip_addrs, node, ipv4))
  933:     {
  934:       if (pos - value + IPV4_MAX_BYTELEN > 255)
  935: 	{
  936: 	  /* RFC 1195 s4.2: only one tuple of 63 allowed. */
  937: 	  zlog_warn ("tlv_add_ip_addrs(): cutting off at 63 IP addresses");
  938: 	  break;
  939: 	}
  940:       *(u_int32_t *) pos = ipv4->prefix.s_addr;
  941:       pos += IPV4_MAX_BYTELEN;
  942:     }
  943: 
  944:   return add_tlv (IPV4_ADDR, pos - value, value, stream);
  945: }
  946: 
  947: /* Used to add TLV containing just one IPv4 address - either IPv4 address TLV
  948:  * (in case of LSP) or TE router ID TLV. */
  949: int
  950: tlv_add_in_addr (struct in_addr *addr, struct stream *stream, u_char tag)
  951: {
  952:   u_char value[255];
  953:   u_char *pos = value;
  954:   
  955:   memcpy (pos, addr, IPV4_MAX_BYTELEN);
  956:   pos += IPV4_MAX_BYTELEN;
  957: 
  958:   return add_tlv (tag, pos - value, value, stream);
  959: }
  960: 
  961: int
  962: tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
  963: {
  964:   return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
  965: 		  stream);
  966: }
  967: 
  968: int
  969: tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
  970: {
  971:   struct listnode *node;
  972:   struct isis_lsp *lsp;
  973:   u_char value[255];
  974:   u_char *pos = value;
  975:   int retval;
  976: 
  977:   for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp))
  978:     {
  979:       if (pos - value + LSP_ENTRIES_LEN > 255)
  980: 	{
  981: 	  retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
  982: 	  if (retval != ISIS_OK)
  983: 	    return retval;
  984: 	  pos = value;
  985: 	}
  986:       *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime;
  987:       pos += 2;
  988:       memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
  989:       pos += ISIS_SYS_ID_LEN + 2;
  990:       *((u_int32_t *) pos) = lsp->lsp_header->seq_num;
  991:       pos += 4;
  992:       *((u_int16_t *) pos) = lsp->lsp_header->checksum;
  993:       pos += 2;
  994:     }
  995: 
  996:   return add_tlv (LSP_ENTRIES, pos - value, value, stream);
  997: }
  998: 
  999: int
 1000: tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
 1001: {
 1002:   struct listnode *node;
 1003:   struct ipv4_reachability *reach;
 1004:   u_char value[255];
 1005:   u_char *pos = value;
 1006:   int retval;
 1007: 
 1008:   for (ALL_LIST_ELEMENTS_RO (ipv4_reachs, node, reach))
 1009:     {
 1010:       if (pos - value + IPV4_REACH_LEN > 255)
 1011: 	{
 1012: 	  retval =
 1013: 	    add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
 1014: 	  if (retval != ISIS_OK)
 1015: 	    return retval;
 1016: 	  pos = value;
 1017: 	}
 1018:       *pos = reach->metrics.metric_default;
 1019:       pos++;
 1020:       *pos = reach->metrics.metric_delay;
 1021:       pos++;
 1022:       *pos = reach->metrics.metric_expense;
 1023:       pos++;
 1024:       *pos = reach->metrics.metric_error;
 1025:       pos++;
 1026:       *(u_int32_t *) pos = reach->prefix.s_addr;
 1027:       pos += IPV4_MAX_BYTELEN;
 1028:       *(u_int32_t *) pos = reach->mask.s_addr;
 1029:       pos += IPV4_MAX_BYTELEN;
 1030:     }
 1031: 
 1032:   return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
 1033: }
 1034: 
 1035: int
 1036: tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream)
 1037: {
 1038:   struct listnode *node;
 1039:   struct te_ipv4_reachability *te_reach;
 1040:   u_char value[255];
 1041:   u_char *pos = value;
 1042:   u_char prefix_size;
 1043:   int retval;
 1044: 
 1045:   for (ALL_LIST_ELEMENTS_RO (te_ipv4_reachs, node, te_reach))
 1046:     {
 1047:       prefix_size = ((((te_reach->control & 0x3F) - 1) >> 3) + 1);
 1048: 
 1049:       if (pos - value + (5 + prefix_size) > 255)
 1050: 	{
 1051: 	  retval =
 1052: 	    add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
 1053: 	  if (retval != ISIS_OK)
 1054: 	    return retval;
 1055: 	  pos = value;
 1056: 	}
 1057:       *(u_int32_t *) pos = te_reach->te_metric;
 1058:       pos += 4;
 1059:       *pos = te_reach->control;
 1060:       pos++;
 1061:       memcpy (pos, &te_reach->prefix_start, prefix_size);
 1062:       pos += prefix_size;
 1063:     }
 1064: 
 1065:   return add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
 1066: }
 1067: 
 1068: #ifdef HAVE_IPV6
 1069: int
 1070: tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
 1071: {
 1072:   struct listnode *node;
 1073:   struct prefix_ipv6 *ipv6;
 1074:   u_char value[255];
 1075:   u_char *pos = value;
 1076:   int retval;
 1077: 
 1078:   for (ALL_LIST_ELEMENTS_RO (ipv6_addrs, node, ipv6))
 1079:     {
 1080:       if (pos - value + IPV6_MAX_BYTELEN > 255)
 1081: 	{
 1082: 	  retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
 1083: 	  if (retval != ISIS_OK)
 1084: 	    return retval;
 1085: 	  pos = value;
 1086: 	}
 1087:       memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
 1088:       pos += IPV6_MAX_BYTELEN;
 1089:     }
 1090: 
 1091:   return add_tlv (IPV6_ADDR, pos - value, value, stream);
 1092: }
 1093: 
 1094: int
 1095: tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
 1096: {
 1097:   struct listnode *node;
 1098:   struct ipv6_reachability *ip6reach;
 1099:   u_char value[255];
 1100:   u_char *pos = value;
 1101:   int retval, prefix_octets;
 1102: 
 1103:   for (ALL_LIST_ELEMENTS_RO (ipv6_reachs, node, ip6reach))
 1104:     {
 1105:       if (pos - value + IPV6_MAX_BYTELEN + 6 > 255)
 1106: 	{
 1107: 	  retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
 1108: 	  if (retval != ISIS_OK)
 1109: 	    return retval;
 1110: 	  pos = value;
 1111: 	}
 1112:       *(uint32_t *) pos = ip6reach->metric;
 1113:       pos += 4;
 1114:       *pos = ip6reach->control_info;
 1115:       pos++;
 1116:       prefix_octets = ((ip6reach->prefix_len + 7) / 8);
 1117:       *pos = ip6reach->prefix_len;
 1118:       pos++;
 1119:       memcpy (pos, ip6reach->prefix, prefix_octets);
 1120:       pos += prefix_octets;
 1121:     }
 1122: 
 1123:   return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
 1124: }
 1125: #endif /* HAVE_IPV6 */
 1126: 
 1127: int
 1128: tlv_add_padding (struct stream *stream)
 1129: {
 1130:   int fullpads, i, left;
 1131: 
 1132:   /*
 1133:    * How many times can we add full padding ?
 1134:    */
 1135:   fullpads = (stream_get_size (stream) - stream_get_endp (stream)) / 257;
 1136:   for (i = 0; i < fullpads; i++)
 1137:     {
 1138:       if (!stream_putc (stream, (u_char) PADDING))	/* TAG */
 1139: 	goto err;
 1140:       if (!stream_putc (stream, (u_char) 255))	/* LENGHT */
 1141: 	goto err;
 1142:       stream_put (stream, NULL, 255);		/* zero padding */
 1143:     }
 1144: 
 1145:   left = stream_get_size (stream) - stream_get_endp (stream);
 1146: 
 1147:   if (left < 2)
 1148:     return ISIS_OK;
 1149: 
 1150:   if (left == 2)
 1151:     {
 1152:       stream_putc (stream, PADDING);
 1153:       stream_putc (stream, 0);
 1154:       return ISIS_OK;
 1155:     }
 1156: 
 1157:   stream_putc (stream, PADDING);
 1158:   stream_putc (stream, left - 2);
 1159:   stream_put (stream, NULL, left-2);
 1160: 
 1161:   return ISIS_OK;
 1162: 
 1163: err:
 1164:   zlog_warn ("tlv_add_padding(): no room for tlv");
 1165:   return ISIS_WARNING;
 1166: }

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