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

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

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