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

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

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