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

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.3 ! misho     120:   u_char *start = stream, *pnt = stream, *endpnt;
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 */
1.1.1.3 ! misho     587:          endpnt = pnt + length;
1.1       misho     588:          if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
                    589:            {
                    590:              while (length > value_len)
                    591:                {
                    592:                  te_ipv4_reach = (struct te_ipv4_reachability *) pnt;
1.1.1.3 ! misho     593:                  if ((te_ipv4_reach->control & 0x3F) > IPV4_MAX_BITLEN)
        !           594:                    {
        !           595:                      zlog_warn ("ISIS-TLV (%s): invalid IPv4 extended reach"
        !           596:                                 "ability prefix length %d", areatag,
        !           597:                                 te_ipv4_reach->control & 0x3F);
        !           598:                      retval = ISIS_WARNING;
        !           599:                      break;
        !           600:                    }
1.1       misho     601:                  if (!tlvs->te_ipv4_reachs)
                    602:                    tlvs->te_ipv4_reachs = list_new ();
                    603:                  listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach);
                    604:                  /* this trickery is permitable since no subtlvs are defined */
                    605:                  value_len += 5 + ((te_ipv4_reach->control & 0x3F) ?
                    606:                                    ((((te_ipv4_reach->control & 0x3F) -
                    607:                                       1) >> 3) + 1) : 0);
                    608:                  pnt += 5 + ((te_ipv4_reach->control & 0x3F) ?
                    609:                              ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0);
                    610:                }
                    611:            }
1.1.1.3 ! misho     612: 
        !           613:          pnt = endpnt;
1.1       misho     614:          break;
                    615: 
                    616: #ifdef  HAVE_IPV6
                    617:        case IPV6_ADDR:
                    618:          /* +-------+-------+-------+-------+-------+-------+-------+-------+
                    619:           * +                 IP version 6 address                          + 16
                    620:           * +-------+-------+-------+-------+-------+-------+-------+-------+
                    621:           * :                                                               :
                    622:           */
                    623:          *found |= TLVFLAG_IPV6_ADDR;
                    624: #ifdef EXTREME_TLV_DEBUG
                    625:          zlog_debug ("ISIS-TLV (%s): IPv6 Address length %d",
                    626:                      areatag, length);
                    627: #endif /* EXTREME_TLV_DEBUG */
                    628:          if (*expected & TLVFLAG_IPV6_ADDR)
                    629:            {
                    630:              while (length > value_len)
                    631:                {
                    632:                  ipv6_addr = (struct in6_addr *) pnt;
                    633:                  if (!tlvs->ipv6_addrs)
                    634:                    tlvs->ipv6_addrs = list_new ();
                    635:                  listnode_add (tlvs->ipv6_addrs, ipv6_addr);
                    636:                  value_len += 16;
                    637:                  pnt += 16;
                    638:                }
                    639:            }
                    640:          else
                    641:            {
                    642:              pnt += length;
                    643:            }
                    644:          break;
                    645: 
                    646:        case IPV6_REACHABILITY:
                    647:          /* +-------+-------+-------+-------+-------+-------+-------+-------+
                    648:           * |                 Default Metric                                | 4 
                    649:           * +-------+-------+-------+-------+-------+-------+-------+-------+
                    650:           * |                        Control Informantion                   |
                    651:           * +---------------------------------------------------------------+
                    652:           * |                        IPv6 Prefix Length                     |--+
                    653:           * +---------------------------------------------------------------+  |
                    654:           * |                        IPv6 Prefix                            |<-+
                    655:           * +---------------------------------------------------------------+
                    656:           */
                    657:          *found |= TLVFLAG_IPV6_REACHABILITY;
1.1.1.3 ! misho     658:          endpnt = pnt + length;
        !           659: 
1.1       misho     660:          if (*expected & TLVFLAG_IPV6_REACHABILITY)
                    661:            {
                    662:              while (length > value_len)
                    663:                {
                    664:                  ipv6_reach = (struct ipv6_reachability *) pnt;
1.1.1.3 ! misho     665:                  if (ipv6_reach->prefix_len > IPV6_MAX_BITLEN)
        !           666:                    {
        !           667:                      zlog_warn ("ISIS-TLV (%s): invalid IPv6 extended reach"
        !           668:                                 "ability prefix length %d", areatag,
        !           669:                                 ipv6_reach->prefix_len);
        !           670:                      retval = ISIS_WARNING;
        !           671:                      break;
        !           672:                    }
        !           673: 
1.1       misho     674:                  prefix_octets = ((ipv6_reach->prefix_len + 7) / 8);
                    675:                  value_len += prefix_octets + 6;
                    676:                  pnt += prefix_octets + 6;
                    677:                  /* FIXME: sub-tlvs */
                    678:                  if (!tlvs->ipv6_reachs)
                    679:                    tlvs->ipv6_reachs = list_new ();
                    680:                  listnode_add (tlvs->ipv6_reachs, ipv6_reach);
                    681:                }
                    682:            }
1.1.1.3 ! misho     683: 
        !           684:          pnt = endpnt;
1.1       misho     685:          break;
                    686: #endif /* HAVE_IPV6 */
                    687: 
                    688:        case WAY3_HELLO:
                    689:          /* +---------------------------------------------------------------+
                    690:           * |                  Adjacency state                              | 1
                    691:           * +---------------------------------------------------------------+
                    692:           * |                  Extended Local Circuit ID                    | 4
                    693:           * +---------------------------------------------------------------+
                    694:           * |                  Neighbor System ID (If known)                | 0-8
                    695:           *                                      (probably 6)
                    696:           * +---------------------------------------------------------------+
                    697:           * |                  Neighbor Local Circuit ID (If known)         | 4
                    698:           * +---------------------------------------------------------------+
                    699:           */
                    700:          *found |= TLVFLAG_3WAY_HELLO;
                    701:          if (*expected & TLVFLAG_3WAY_HELLO)
                    702:            {
                    703:              while (length > value_len)
                    704:                {
                    705:                  /* FIXME: make this work */
                    706: /*           Adjacency State (one octet):
                    707:               0 = Up
                    708:               1 = Initializing
                    709:               2 = Down
                    710:             Extended Local Circuit ID (four octets)
                    711:             Neighbor System ID if known (zero to eight octets)
                    712:             Neighbor Extended Local Circuit ID (four octets, if Neighbor
                    713:               System ID is present) */
                    714:                  pnt += length;
1.1.1.3 ! misho     715:                  value_len += length;
1.1       misho     716:                }
                    717:            }
                    718:          else
                    719:            {
                    720:              pnt += length;
                    721:            }
                    722: 
                    723:          break;
                    724:        case GRACEFUL_RESTART:
                    725:          /* +-------+-------+-------+-------+-------+-------+-------+-------+
                    726:           * |         Reserved                      |  SA   |  RA   |  RR   | 1
                    727:           * +-------+-------+-------+-------+-------+-------+-------+-------+
                    728:           * |                          Remaining Time                       | 2
                    729:           * +---------------------------------------------------------------+
                    730:           * |                Restarting Neighbor ID (If known)              | 0-8
                    731:           * +---------------------------------------------------------------+
                    732:           */
                    733:          *found |= TLVFLAG_GRACEFUL_RESTART;
                    734:          if (*expected & TLVFLAG_GRACEFUL_RESTART)
                    735:            {
                    736:              /* FIXME: make this work */
                    737:            }
                    738:          pnt += length;
                    739:          break;
                    740: 
                    741:        default:
                    742:          zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
                    743:                     areatag, type, length);
                    744: 
                    745:          retval = ISIS_WARNING;
                    746:          pnt += length;
                    747:          break;
                    748:        }
                    749:     }
                    750: 
                    751:   return retval;
                    752: }
                    753: 
                    754: int
                    755: add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
                    756: {
1.1.1.2   misho     757:   if ((stream_get_size (stream) - stream_get_endp (stream)) <
                    758:       (((unsigned)len) + 2))
1.1       misho     759:     {
1.1.1.2   misho     760:       zlog_warn ("No room for TLV of type %d "
                    761:                  "(total size %d available %d required %d)",
                    762:                  tag, (int)stream_get_size (stream),
                    763:                  (int)(stream_get_size (stream) - stream_get_endp (stream)),
                    764:                  len+2);
1.1       misho     765:       return ISIS_WARNING;
                    766:     }
                    767: 
                    768:   stream_putc (stream, tag);   /* TAG */
                    769:   stream_putc (stream, len);   /* LENGTH */
                    770:   stream_put (stream, value, (int) len);       /* VALUE */
                    771: 
                    772: #ifdef EXTREME_DEBUG
                    773:   zlog_debug ("Added TLV %d len %d", tag, len);
                    774: #endif /* EXTREME DEBUG */
                    775:   return ISIS_OK;
                    776: }
                    777: 
                    778: int
                    779: tlv_add_area_addrs (struct list *area_addrs, struct stream *stream)
                    780: {
                    781:   struct listnode *node;
                    782:   struct area_addr *area_addr;
                    783: 
                    784:   u_char value[255];
                    785:   u_char *pos = value;
                    786: 
                    787:   for (ALL_LIST_ELEMENTS_RO (area_addrs, node, area_addr))
                    788:     {
                    789:       if (pos - value + area_addr->addr_len > 255)
                    790:        goto err;
                    791:       *pos = area_addr->addr_len;
                    792:       pos++;
                    793:       memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len);
                    794:       pos += area_addr->addr_len;
                    795:     }
                    796: 
                    797:   return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
                    798: 
                    799: err:
                    800:   zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
                    801:   return ISIS_WARNING;
                    802: }
                    803: 
                    804: int
                    805: tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
                    806: {
                    807:   struct listnode *node;
                    808:   struct is_neigh *is_neigh;
                    809:   u_char value[255];
                    810:   u_char *pos = value;
                    811:   int retval;
                    812: 
                    813:   *pos = 0;                    /*is_neigh->virtual; */
                    814:   pos++;
                    815: 
                    816:   for (ALL_LIST_ELEMENTS_RO (is_neighs, node, is_neigh))
                    817:     {
                    818:       if (pos - value + IS_NEIGHBOURS_LEN > 255)
                    819:        {
                    820:          retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
                    821:          if (retval != ISIS_OK)
                    822:            return retval;
                    823:          pos = value;
                    824:        }
                    825:       *pos = is_neigh->metrics.metric_default;
                    826:       pos++;
                    827:       *pos = is_neigh->metrics.metric_delay;
                    828:       pos++;
                    829:       *pos = is_neigh->metrics.metric_expense;
                    830:       pos++;
                    831:       *pos = is_neigh->metrics.metric_error;
                    832:       pos++;
                    833:       memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
                    834:       pos += ISIS_SYS_ID_LEN + 1;
                    835:     }
                    836: 
                    837:   return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
                    838: }
                    839: 
                    840: int
                    841: tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream)
                    842: {
                    843:   struct listnode *node;
                    844:   struct te_is_neigh *te_is_neigh;
                    845:   u_char value[255];
                    846:   u_char *pos = value;
                    847:   int retval;
                    848: 
                    849:   for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh))
                    850:     {
                    851:       /* FIXME: This will be wrong if we are going to add TE sub TLVs. */
                    852:       if (pos - value + IS_NEIGHBOURS_LEN > 255)
                    853:         {
                    854:           retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
                    855:           if (retval != ISIS_OK)
                    856:             return retval;
                    857:           pos = value;
                    858:         }
                    859:       
                    860:       memcpy (pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
                    861:       pos += ISIS_SYS_ID_LEN + 1;
                    862:       memcpy (pos, te_is_neigh->te_metric, 3);
                    863:       pos += 3;
                    864:       /* Sub TLVs length. */
                    865:       *pos = 0;
                    866:       pos++;
                    867:     }
                    868: 
                    869:   return add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
                    870: }
                    871: 
                    872: int
                    873: tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
                    874: {
                    875:   struct listnode *node;
                    876:   u_char *snpa;
                    877:   u_char value[255];
                    878:   u_char *pos = value;
                    879:   int retval;
                    880: 
                    881:   for (ALL_LIST_ELEMENTS_RO (lan_neighs, node, snpa))
                    882:     {
                    883:       if (pos - value + ETH_ALEN > 255)
                    884:        {
                    885:          retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
                    886:          if (retval != ISIS_OK)
                    887:            return retval;
                    888:          pos = value;
                    889:        }
                    890:       memcpy (pos, snpa, ETH_ALEN);
                    891:       pos += ETH_ALEN;
                    892:     }
                    893: 
                    894:   return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
                    895: }
                    896: 
                    897: int
                    898: tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
                    899: {
                    900:   return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream);
                    901: }
                    902: 
                    903: int
1.1.1.2   misho     904: tlv_add_authinfo (u_char auth_type, u_char auth_len, u_char *auth_value,
1.1       misho     905:                  struct stream *stream)
                    906: {
                    907:   u_char value[255];
                    908:   u_char *pos = value;
1.1.1.2   misho     909:   *pos++ = auth_type;
1.1       misho     910:   memcpy (pos, auth_value, auth_len);
                    911: 
                    912:   return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
                    913: }
                    914: 
                    915: int
                    916: tlv_add_checksum (struct checksum *checksum, struct stream *stream)
                    917: {
                    918:   u_char value[255];
                    919:   u_char *pos = value;
                    920:   return add_tlv (CHECKSUM, pos - value, value, stream);
                    921: }
                    922: 
                    923: int
                    924: tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
                    925: {
                    926:   struct listnode *node;
                    927:   struct prefix_ipv4 *ipv4;
                    928:   u_char value[255];
                    929:   u_char *pos = value;
                    930:   int retval;
                    931: 
                    932:   for (ALL_LIST_ELEMENTS_RO (ip_addrs, node, ipv4))
                    933:     {
                    934:       if (pos - value + IPV4_MAX_BYTELEN > 255)
                    935:        {
1.1.1.3 ! misho     936:          /* RFC 1195 s4.2: only one tuple of 63 allowed. */
        !           937:          zlog_warn ("tlv_add_ip_addrs(): cutting off at 63 IP addresses");
        !           938:          break;
1.1       misho     939:        }
                    940:       *(u_int32_t *) pos = ipv4->prefix.s_addr;
                    941:       pos += IPV4_MAX_BYTELEN;
                    942:     }
                    943: 
                    944:   return add_tlv (IPV4_ADDR, pos - value, value, stream);
                    945: }
                    946: 
                    947: /* Used to add TLV containing just one IPv4 address - either IPv4 address TLV
                    948:  * (in case of LSP) or TE router ID TLV. */
                    949: int
                    950: tlv_add_in_addr (struct in_addr *addr, struct stream *stream, u_char tag)
                    951: {
                    952:   u_char value[255];
                    953:   u_char *pos = value;
                    954:   
                    955:   memcpy (pos, addr, IPV4_MAX_BYTELEN);
                    956:   pos += IPV4_MAX_BYTELEN;
                    957: 
                    958:   return add_tlv (tag, pos - value, value, stream);
                    959: }
                    960: 
                    961: int
                    962: tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
                    963: {
                    964:   return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
                    965:                  stream);
                    966: }
                    967: 
                    968: int
                    969: tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
                    970: {
                    971:   struct listnode *node;
                    972:   struct isis_lsp *lsp;
                    973:   u_char value[255];
                    974:   u_char *pos = value;
                    975:   int retval;
                    976: 
                    977:   for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp))
                    978:     {
                    979:       if (pos - value + LSP_ENTRIES_LEN > 255)
                    980:        {
                    981:          retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
                    982:          if (retval != ISIS_OK)
                    983:            return retval;
                    984:          pos = value;
                    985:        }
                    986:       *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime;
                    987:       pos += 2;
                    988:       memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
                    989:       pos += ISIS_SYS_ID_LEN + 2;
                    990:       *((u_int32_t *) pos) = lsp->lsp_header->seq_num;
                    991:       pos += 4;
                    992:       *((u_int16_t *) pos) = lsp->lsp_header->checksum;
                    993:       pos += 2;
                    994:     }
                    995: 
                    996:   return add_tlv (LSP_ENTRIES, pos - value, value, stream);
                    997: }
                    998: 
                    999: int
                   1000: tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
                   1001: {
                   1002:   struct listnode *node;
                   1003:   struct ipv4_reachability *reach;
                   1004:   u_char value[255];
                   1005:   u_char *pos = value;
                   1006:   int retval;
                   1007: 
                   1008:   for (ALL_LIST_ELEMENTS_RO (ipv4_reachs, node, reach))
                   1009:     {
                   1010:       if (pos - value + IPV4_REACH_LEN > 255)
                   1011:        {
                   1012:          retval =
                   1013:            add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
                   1014:          if (retval != ISIS_OK)
                   1015:            return retval;
                   1016:          pos = value;
                   1017:        }
                   1018:       *pos = reach->metrics.metric_default;
                   1019:       pos++;
                   1020:       *pos = reach->metrics.metric_delay;
                   1021:       pos++;
                   1022:       *pos = reach->metrics.metric_expense;
                   1023:       pos++;
                   1024:       *pos = reach->metrics.metric_error;
                   1025:       pos++;
                   1026:       *(u_int32_t *) pos = reach->prefix.s_addr;
                   1027:       pos += IPV4_MAX_BYTELEN;
                   1028:       *(u_int32_t *) pos = reach->mask.s_addr;
                   1029:       pos += IPV4_MAX_BYTELEN;
                   1030:     }
                   1031: 
                   1032:   return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
                   1033: }
                   1034: 
                   1035: int
                   1036: tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream)
                   1037: {
                   1038:   struct listnode *node;
                   1039:   struct te_ipv4_reachability *te_reach;
                   1040:   u_char value[255];
                   1041:   u_char *pos = value;
                   1042:   u_char prefix_size;
                   1043:   int retval;
                   1044: 
                   1045:   for (ALL_LIST_ELEMENTS_RO (te_ipv4_reachs, node, te_reach))
                   1046:     {
                   1047:       prefix_size = ((((te_reach->control & 0x3F) - 1) >> 3) + 1);
                   1048: 
                   1049:       if (pos - value + (5 + prefix_size) > 255)
                   1050:        {
                   1051:          retval =
1.1.1.2   misho    1052:            add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
1.1       misho    1053:          if (retval != ISIS_OK)
                   1054:            return retval;
                   1055:          pos = value;
                   1056:        }
                   1057:       *(u_int32_t *) pos = te_reach->te_metric;
                   1058:       pos += 4;
                   1059:       *pos = te_reach->control;
                   1060:       pos++;
                   1061:       memcpy (pos, &te_reach->prefix_start, prefix_size);
                   1062:       pos += prefix_size;
                   1063:     }
                   1064: 
                   1065:   return add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
                   1066: }
                   1067: 
                   1068: #ifdef HAVE_IPV6
                   1069: int
                   1070: tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
                   1071: {
                   1072:   struct listnode *node;
                   1073:   struct prefix_ipv6 *ipv6;
                   1074:   u_char value[255];
                   1075:   u_char *pos = value;
                   1076:   int retval;
                   1077: 
                   1078:   for (ALL_LIST_ELEMENTS_RO (ipv6_addrs, node, ipv6))
                   1079:     {
                   1080:       if (pos - value + IPV6_MAX_BYTELEN > 255)
                   1081:        {
                   1082:          retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
                   1083:          if (retval != ISIS_OK)
                   1084:            return retval;
                   1085:          pos = value;
                   1086:        }
                   1087:       memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
                   1088:       pos += IPV6_MAX_BYTELEN;
                   1089:     }
                   1090: 
                   1091:   return add_tlv (IPV6_ADDR, pos - value, value, stream);
                   1092: }
                   1093: 
                   1094: int
                   1095: tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
                   1096: {
                   1097:   struct listnode *node;
                   1098:   struct ipv6_reachability *ip6reach;
                   1099:   u_char value[255];
                   1100:   u_char *pos = value;
                   1101:   int retval, prefix_octets;
                   1102: 
                   1103:   for (ALL_LIST_ELEMENTS_RO (ipv6_reachs, node, ip6reach))
                   1104:     {
                   1105:       if (pos - value + IPV6_MAX_BYTELEN + 6 > 255)
                   1106:        {
                   1107:          retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
                   1108:          if (retval != ISIS_OK)
                   1109:            return retval;
                   1110:          pos = value;
                   1111:        }
                   1112:       *(uint32_t *) pos = ip6reach->metric;
                   1113:       pos += 4;
                   1114:       *pos = ip6reach->control_info;
                   1115:       pos++;
                   1116:       prefix_octets = ((ip6reach->prefix_len + 7) / 8);
                   1117:       *pos = ip6reach->prefix_len;
                   1118:       pos++;
                   1119:       memcpy (pos, ip6reach->prefix, prefix_octets);
                   1120:       pos += prefix_octets;
                   1121:     }
                   1122: 
                   1123:   return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
                   1124: }
                   1125: #endif /* HAVE_IPV6 */
                   1126: 
                   1127: int
                   1128: tlv_add_padding (struct stream *stream)
                   1129: {
                   1130:   int fullpads, i, left;
                   1131: 
                   1132:   /*
                   1133:    * How many times can we add full padding ?
                   1134:    */
1.1.1.2   misho    1135:   fullpads = (stream_get_size (stream) - stream_get_endp (stream)) / 257;
1.1       misho    1136:   for (i = 0; i < fullpads; i++)
                   1137:     {
                   1138:       if (!stream_putc (stream, (u_char) PADDING))     /* TAG */
                   1139:        goto err;
                   1140:       if (!stream_putc (stream, (u_char) 255)) /* LENGHT */
                   1141:        goto err;
                   1142:       stream_put (stream, NULL, 255);          /* zero padding */
                   1143:     }
                   1144: 
1.1.1.2   misho    1145:   left = stream_get_size (stream) - stream_get_endp (stream);
1.1       misho    1146: 
                   1147:   if (left < 2)
                   1148:     return ISIS_OK;
                   1149: 
                   1150:   if (left == 2)
                   1151:     {
                   1152:       stream_putc (stream, PADDING);
                   1153:       stream_putc (stream, 0);
                   1154:       return ISIS_OK;
                   1155:     }
                   1156: 
                   1157:   stream_putc (stream, PADDING);
                   1158:   stream_putc (stream, left - 2);
                   1159:   stream_put (stream, NULL, left-2);
                   1160: 
                   1161:   return ISIS_OK;
                   1162: 
                   1163: err:
                   1164:   zlog_warn ("tlv_add_padding(): no room for tlv");
                   1165:   return ISIS_WARNING;
                   1166: }

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