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

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

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