Annotation of embedaddon/quagga/isisd/isis_tlv.c, revision 1.1.1.1

1.1       misho       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>