File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / isisd / isis_tlv.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:11 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_20_1, v0_99_20, HEAD
quagga

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

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