blob: a35b68785bc2f2625ee16f92ddc06147cc8409c0 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
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>
jardineb5d44e2003-12-23 08:09:43 +000025
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
46extern struct isis *isis;
47
48void
49free_tlv (void *val)
50{
hassof390d2c2004-09-10 20:48:21 +000051 XFREE (MTYPE_ISIS_TLV, val);
52
53 return;
jardineb5d44e2003-12-23 08:09:43 +000054}
55
56/*
57 * Called after parsing of a PDU. There shouldn't be any tlv's left, so this
58 * is only a caution to avoid memory leaks
59 */
hassof390d2c2004-09-10 20:48:21 +000060void
jardineb5d44e2003-12-23 08:09:43 +000061free_tlvs (struct tlvs *tlvs)
62{
hassof390d2c2004-09-10 20:48:21 +000063 if (tlvs->area_addrs)
64 {
65 list_delete (tlvs->area_addrs);
66 }
67 if (tlvs->is_neighs)
68 {
69 list_delete (tlvs->is_neighs);
70 }
71 if (tlvs->te_is_neighs)
72 {
73 list_delete (tlvs->te_is_neighs);
74 }
75 if (tlvs->es_neighs)
76 {
77 list_delete (tlvs->es_neighs);
78 }
79 if (tlvs->lsp_entries)
80 {
81 list_delete (tlvs->lsp_entries);
82 }
83 if (tlvs->lan_neighs)
84 {
85 list_delete (tlvs->lan_neighs);
86 }
87 if (tlvs->prefix_neighs)
88 {
89 list_delete (tlvs->prefix_neighs);
90 }
91 if (tlvs->ipv4_addrs)
92 {
93 list_delete (tlvs->ipv4_addrs);
94 }
95 if (tlvs->ipv4_int_reachs)
96 {
97 list_delete (tlvs->ipv4_int_reachs);
98 }
99 if (tlvs->ipv4_ext_reachs)
100 {
101 list_delete (tlvs->ipv4_ext_reachs);
102 }
103 if (tlvs->te_ipv4_reachs)
104 {
105 list_delete (tlvs->te_ipv4_reachs);
106 }
jardineb5d44e2003-12-23 08:09:43 +0000107#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000108 if (tlvs->ipv6_addrs)
109 {
110 list_delete (tlvs->ipv6_addrs);
111 }
112 if (tlvs->ipv6_reachs)
113 {
114 list_delete (tlvs->ipv6_reachs);
115 }
jardineb5d44e2003-12-23 08:09:43 +0000116#endif /* HAVE_IPV6 */
117 return;
118}
119
120/*
121 * Parses the tlvs found in the variant length part of the PDU.
122 * Caller tells with flags in "expected" which TLV's it is interested in.
123 */
hassof390d2c2004-09-10 20:48:21 +0000124int
125parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
126 u_int32_t * found, struct tlvs *tlvs)
jardineb5d44e2003-12-23 08:09:43 +0000127{
hassof390d2c2004-09-10 20:48:21 +0000128 u_char type, length;
129 struct lan_neigh *lan_nei;
130 struct area_addr *area_addr;
131 struct is_neigh *is_nei;
132 struct te_is_neigh *te_is_nei;
133 struct es_neigh *es_nei;
134 struct lsp_entry *lsp_entry;
135 struct in_addr *ipv4_addr;
136 struct ipv4_reachability *ipv4_reach;
137 struct te_ipv4_reachability *te_ipv4_reach;
jardineb5d44e2003-12-23 08:09:43 +0000138#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000139 struct in6_addr *ipv6_addr;
140 struct ipv6_reachability *ipv6_reach;
141 int prefix_octets;
jardineb5d44e2003-12-23 08:09:43 +0000142#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000143 u_char virtual;
144 int value_len, retval = ISIS_OK;
145 u_char *pnt = stream;
jardineb5d44e2003-12-23 08:09:43 +0000146
147 *found = 0;
148 memset (tlvs, 0, sizeof (struct tlvs));
hassof390d2c2004-09-10 20:48:21 +0000149
150 while (pnt < stream + size - 2)
151 {
152 type = *pnt;
153 length = *(pnt + 1);
154 pnt += 2;
155 value_len = 0;
156 if (pnt + length > stream + size)
157 {
158 zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet "
159 "boundaries", areatag, type, length);
160 retval = ISIS_WARNING;
161 break;
162 }
163 switch (type)
164 {
165 case AREA_ADDRESSES:
166 /* +-------+-------+-------+-------+-------+-------+-------+-------+
167 * | Address Length |
168 * +-------+-------+-------+-------+-------+-------+-------+-------+
169 * | Area Address |
170 * +-------+-------+-------+-------+-------+-------+-------+-------+
171 * : :
172 */
173 *found |= TLVFLAG_AREA_ADDRS;
jardineb5d44e2003-12-23 08:09:43 +0000174#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000175 zlog_info ("TLV Area Adresses len %d", length);
jardineb5d44e2003-12-23 08:09:43 +0000176#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000177 if (*expected & TLVFLAG_AREA_ADDRS)
178 {
179 while (length > value_len)
180 {
181 area_addr = (struct area_addr *) pnt;
182 value_len += area_addr->addr_len + 1;
183 pnt += area_addr->addr_len + 1;
184 if (!tlvs->area_addrs)
185 tlvs->area_addrs = list_new ();
186 listnode_add (tlvs->area_addrs, area_addr);
187 }
188 }
189 else
190 {
191 pnt += length;
192 }
193 break;
jardineb5d44e2003-12-23 08:09:43 +0000194
hassof390d2c2004-09-10 20:48:21 +0000195 case IS_NEIGHBOURS:
196 *found |= TLVFLAG_IS_NEIGHS;
jardineb5d44e2003-12-23 08:09:43 +0000197#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000198 zlog_info ("ISIS-TLV (%s): IS Neighbours length %d",
199 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000200#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000201 if (TLVFLAG_IS_NEIGHS & *expected)
202 {
203 /* +-------+-------+-------+-------+-------+-------+-------+-------+
204 * | Virtual Flag |
205 * +-------+-------+-------+-------+-------+-------+-------+-------+
206 */
207 virtual = *pnt; /* FIXME: what is the use for this? */
208 pnt++;
209 value_len++;
210 /* +-------+-------+-------+-------+-------+-------+-------+-------+
211 * | 0 | I/E | Default Metric |
212 * +-------+-------+-------+-------+-------+-------+-------+-------+
213 * | S | I/E | Delay Metric |
214 * +-------+-------+-------+-------+-------+-------+-------+-------+
215 * | S | I/E | Expense Metric |
216 * +-------+-------+-------+-------+-------+-------+-------+-------+
217 * | S | I/E | Error Metric |
218 * +-------+-------+-------+-------+-------+-------+-------+-------+
219 * | Neighbour ID |
220 * +---------------------------------------------------------------+
221 * : :
222 */
223 while (length > value_len)
224 {
225 is_nei = (struct is_neigh *) pnt;
226 value_len += 4 + ISIS_SYS_ID_LEN + 1;
227 pnt += 4 + ISIS_SYS_ID_LEN + 1;
228 if (!tlvs->is_neighs)
229 tlvs->is_neighs = list_new ();
230 listnode_add (tlvs->is_neighs, is_nei);
231 }
232 }
233 else
234 {
235 pnt += length;
236 }
237 break;
jardineb5d44e2003-12-23 08:09:43 +0000238
hassof390d2c2004-09-10 20:48:21 +0000239 case TE_IS_NEIGHBOURS:
240 /* +-------+-------+-------+-------+-------+-------+-------+-------+
241 * | Neighbour ID | 7
242 * +---------------------------------------------------------------+
243 * | TE Metric | 3
244 * +---------------------------------------------------------------+
245 * | SubTLVs Length | 1
246 * +---------------------------------------------------------------+
247 * : :
248 */
249 *found |= TLVFLAG_TE_IS_NEIGHS;
jardineb5d44e2003-12-23 08:09:43 +0000250#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000251 zlog_info ("ISIS-TLV (%s): Extended IS Neighbours length %d",
252 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000253#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000254 if (TLVFLAG_TE_IS_NEIGHS & *expected)
255 {
256 while (length > value_len)
257 {
258 te_is_nei = (struct te_is_neigh *) pnt;
259 value_len += 11;
260 pnt += 11;
261 /* FIXME - subtlvs are handled here, for now we skip */
262 value_len += te_is_nei->sub_tlvs_length;
263 pnt += te_is_nei->sub_tlvs_length;
jardineb5d44e2003-12-23 08:09:43 +0000264
hassof390d2c2004-09-10 20:48:21 +0000265 if (!tlvs->te_is_neighs)
266 tlvs->te_is_neighs = list_new ();
267 listnode_add (tlvs->te_is_neighs, te_is_nei);
268 }
269 }
270 else
271 {
272 pnt += length;
273 }
274 break;
jardineb5d44e2003-12-23 08:09:43 +0000275
hassof390d2c2004-09-10 20:48:21 +0000276 case ES_NEIGHBOURS:
277 /* +-------+-------+-------+-------+-------+-------+-------+-------+
278 * | 0 | I/E | Default Metric |
279 * +-------+-------+-------+-------+-------+-------+-------+-------+
280 * | S | I/E | Delay Metric |
281 * +-------+-------+-------+-------+-------+-------+-------+-------+
282 * | S | I/E | Expense Metric |
283 * +-------+-------+-------+-------+-------+-------+-------+-------+
284 * | S | I/E | Error Metric |
285 * +-------+-------+-------+-------+-------+-------+-------+-------+
286 * | Neighbour ID |
287 * +---------------------------------------------------------------+
288 * | Neighbour ID |
289 * +---------------------------------------------------------------+
290 * : :
291 */
jardineb5d44e2003-12-23 08:09:43 +0000292#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000293 zlog_info ("ISIS-TLV (%s): ES Neighbours length %d",
294 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000295#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000296 *found |= TLVFLAG_ES_NEIGHS;
297 if (*expected & TLVFLAG_ES_NEIGHS)
298 {
299 es_nei = (struct es_neigh *) pnt;
300 value_len += 4;
301 pnt += 4;
302 while (length > value_len)
303 {
304 /* FIXME FIXME FIXME - add to the list */
305 /* sys_id->id = pnt; */
306 value_len += ISIS_SYS_ID_LEN;
307 pnt += ISIS_SYS_ID_LEN;
308 /* if (!es_nei->neigh_ids) es_nei->neigh_ids = sysid; */
309 }
310 if (!tlvs->es_neighs)
311 tlvs->es_neighs = list_new ();
312 listnode_add (tlvs->es_neighs, es_nei);
313 }
314 else
315 {
316 pnt += length;
317 }
318 break;
jardineb5d44e2003-12-23 08:09:43 +0000319
hassof390d2c2004-09-10 20:48:21 +0000320 case LAN_NEIGHBOURS:
321 /* +-------+-------+-------+-------+-------+-------+-------+-------+
322 * | LAN Address |
323 * +-------+-------+-------+-------+-------+-------+-------+-------+
324 * : :
325 */
326 *found |= TLVFLAG_LAN_NEIGHS;
jardineb5d44e2003-12-23 08:09:43 +0000327#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000328 zlog_info ("ISIS-TLV (%s): LAN Neigbours length %d",
329 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000330#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000331 if (TLVFLAG_LAN_NEIGHS & *expected)
332 {
333 while (length > value_len)
334 {
335 lan_nei = (struct lan_neigh *) pnt;
336 if (!tlvs->lan_neighs)
337 tlvs->lan_neighs = list_new ();
338 listnode_add (tlvs->lan_neighs, lan_nei);
339 value_len += ETH_ALEN;
340 pnt += ETH_ALEN;
341 }
342 }
343 else
344 {
345 pnt += length;
346 }
347 break;
jardineb5d44e2003-12-23 08:09:43 +0000348
hassof390d2c2004-09-10 20:48:21 +0000349 case PADDING:
jardineb5d44e2003-12-23 08:09:43 +0000350#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000351 zlog_info ("TLV padding %d", length);
jardineb5d44e2003-12-23 08:09:43 +0000352#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000353 pnt += length;
354 break;
jardineb5d44e2003-12-23 08:09:43 +0000355
hassof390d2c2004-09-10 20:48:21 +0000356 case LSP_ENTRIES:
357 /* +-------+-------+-------+-------+-------+-------+-------+-------+
358 * | Remaining Lifetime | 2
359 * +-------+-------+-------+-------+-------+-------+-------+-------+
360 * | LSP ID | id+2
361 * +-------+-------+-------+-------+-------+-------+-------+-------+
362 * | LSP Sequence Number | 4
363 * +-------+-------+-------+-------+-------+-------+-------+-------+
364 * | Checksum | 2
365 * +-------+-------+-------+-------+-------+-------+-------+-------+
366 */
jardineb5d44e2003-12-23 08:09:43 +0000367#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000368 zlog_info ("LSP Entries length %d", areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000369#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000370 *found |= TLVFLAG_LSP_ENTRIES;
371 if (TLVFLAG_LSP_ENTRIES & *expected)
372 {
373 while (length > value_len)
374 {
375 lsp_entry = (struct lsp_entry *) pnt;
376 value_len += 10 + ISIS_SYS_ID_LEN;
377 pnt += 10 + ISIS_SYS_ID_LEN;
378 if (!tlvs->lsp_entries)
379 tlvs->lsp_entries = list_new ();
380 listnode_add (tlvs->lsp_entries, lsp_entry);
381 }
382 }
383 else
384 {
385 pnt += length;
386 }
387 break;
jardineb5d44e2003-12-23 08:09:43 +0000388
hassof390d2c2004-09-10 20:48:21 +0000389 case CHECKSUM:
390 /* +-------+-------+-------+-------+-------+-------+-------+-------+
391 * | 16 bit fletcher CHECKSUM |
392 * +-------+-------+-------+-------+-------+-------+-------+-------+
393 * : :
394 */
395 *found |= TLVFLAG_CHECKSUM;
jardineb5d44e2003-12-23 08:09:43 +0000396#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000397 zlog_info ("ISIS-TLV (%s): Checksum length %d", areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000398#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000399 if (*expected & TLVFLAG_CHECKSUM)
400 {
401 tlvs->checksum = (struct checksum *) pnt;
402 }
403 pnt += length;
404 break;
jardineb5d44e2003-12-23 08:09:43 +0000405
hassof390d2c2004-09-10 20:48:21 +0000406 case PROTOCOLS_SUPPORTED:
407 /* +-------+-------+-------+-------+-------+-------+-------+-------+
408 * | NLPID |
409 * +-------+-------+-------+-------+-------+-------+-------+-------+
410 * : :
411 */
412 *found |= TLVFLAG_NLPID;
jardineb5d44e2003-12-23 08:09:43 +0000413#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000414 zlog_info ("ISIS-TLV (%s): Protocols Supported length %d",
415 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000416#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000417 if (*expected & TLVFLAG_NLPID)
418 {
419 tlvs->nlpids = (struct nlpids *) (pnt - 1);
420 }
421 pnt += length;
422 break;
jardineb5d44e2003-12-23 08:09:43 +0000423
hassof390d2c2004-09-10 20:48:21 +0000424 case IPV4_ADDR:
425 /* +-------+-------+-------+-------+-------+-------+-------+-------+
426 * + IP version 4 address + 4
427 * +-------+-------+-------+-------+-------+-------+-------+-------+
428 * : :
429 */
430 *found |= TLVFLAG_IPV4_ADDR;
jardineb5d44e2003-12-23 08:09:43 +0000431#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000432 zlog_info ("ISIS-TLV (%s): IPv4 Address length %d",
433 areatag, length);
434#endif /* EXTREME_TLV_DEBUG */
435 if (*expected & TLVFLAG_IPV4_ADDR)
436 {
437 while (length > value_len)
438 {
439 ipv4_addr = (struct in_addr *) pnt;
440 zlog_info ("ISIS-TLV (%s) : IP ADDR %s, pnt %p", areatag,
441 inet_ntoa (*ipv4_addr), pnt);
442 if (!tlvs->ipv4_addrs)
443 tlvs->ipv4_addrs = list_new ();
444 listnode_add (tlvs->ipv4_addrs, ipv4_addr);
445 value_len += 4;
446 pnt += 4;
447 }
448 }
449 else
450 {
451 pnt += length;
452 }
453 break;
454
455 case AUTH_INFO:
456 *found |= TLVFLAG_AUTH_INFO;
457#ifdef EXTREME_TLV_DEBUG
458 zlog_info ("ISIS-TLV (%s): IS-IS Authentication Information",
459 areatag);
jardineb5d44e2003-12-23 08:09:43 +0000460#endif
hassof390d2c2004-09-10 20:48:21 +0000461 if (*expected & TLVFLAG_AUTH_INFO)
462 {
463 tlvs->auth_info.type = *pnt;
464 pnt++;
465 memcpy (tlvs->auth_info.passwd, pnt, length - 1);
466 pnt += length - 1;
467 }
468 else
469 {
470 pnt += length;
471 }
472 break;
jardineb5d44e2003-12-23 08:09:43 +0000473
hassof390d2c2004-09-10 20:48:21 +0000474 case DYNAMIC_HOSTNAME:
475 *found |= TLVFLAG_DYN_HOSTNAME;
jardineb5d44e2003-12-23 08:09:43 +0000476#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000477 zlog_info ("ISIS-TLV (%s): Dynamic Hostname length %d",
478 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000479#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000480 if (*expected & TLVFLAG_DYN_HOSTNAME)
481 {
482 /* the length is also included in the pointed struct */
483 tlvs->hostname = (struct hostname *) (pnt - 1);
484 }
485 pnt += length;
486 break;
jardineb5d44e2003-12-23 08:09:43 +0000487
hassof390d2c2004-09-10 20:48:21 +0000488 case TE_ROUTER_ID:
489 /* +---------------------------------------------------------------+
490 * + Router ID + 4
491 * +---------------------------------------------------------------+
492 */
493 *found |= TLVFLAG_TE_ROUTER_ID;
jardineb5d44e2003-12-23 08:09:43 +0000494#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000495 zlog_info ("ISIS-TLV (%s): TE Router ID %d", areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000496#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000497 if (*expected & TLVFLAG_TE_ROUTER_ID)
498 {
499 tlvs->router_id = (struct te_router_id *) (pnt);
500 }
501 pnt += length;
502 break;
jardineb5d44e2003-12-23 08:09:43 +0000503
hassof390d2c2004-09-10 20:48:21 +0000504 case IPV4_INT_REACHABILITY:
505 /* +-------+-------+-------+-------+-------+-------+-------+-------+
506 * | 0 | I/E | Default Metric | 1
507 * +-------+-------+-------+-------+-------+-------+-------+-------+
508 * | S | I/E | Delay Metric | 1
509 * +-------+-------+-------+-------+-------+-------+-------+-------+
510 * | S | I/E | Expense Metric | 1
511 * +-------+-------+-------+-------+-------+-------+-------+-------+
512 * | S | I/E | Error Metric | 1
513 * +-------+-------+-------+-------+-------+-------+-------+-------+
514 * | ip address | 4
515 * +---------------------------------------------------------------+
516 * | address mask | 4
517 * +---------------------------------------------------------------+
518 * : :
519 */
520 *found |= TLVFLAG_IPV4_INT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000521#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000522 zlog_info ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
523 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000524#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000525 if (*expected & TLVFLAG_IPV4_INT_REACHABILITY)
526 {
527 while (length > value_len)
528 {
529 ipv4_reach = (struct ipv4_reachability *) pnt;
530 if (!tlvs->ipv4_int_reachs)
531 tlvs->ipv4_int_reachs = list_new ();
532 listnode_add (tlvs->ipv4_int_reachs, ipv4_reach);
533 value_len += 12;
534 pnt += 12;
535 }
536 }
537 else
538 {
539 pnt += length;
540 }
541 break;
jardineb5d44e2003-12-23 08:09:43 +0000542
hassof390d2c2004-09-10 20:48:21 +0000543 case IPV4_EXT_REACHABILITY:
544 /* +-------+-------+-------+-------+-------+-------+-------+-------+
545 * | 0 | I/E | Default Metric | 1
546 * +-------+-------+-------+-------+-------+-------+-------+-------+
547 * | S | I/E | Delay Metric | 1
548 * +-------+-------+-------+-------+-------+-------+-------+-------+
549 * | S | I/E | Expense Metric | 1
550 * +-------+-------+-------+-------+-------+-------+-------+-------+
551 * | S | I/E | Error Metric | 1
552 * +-------+-------+-------+-------+-------+-------+-------+-------+
553 * | ip address | 4
554 * +---------------------------------------------------------------+
555 * | address mask | 4
556 * +---------------------------------------------------------------+
557 * : :
558 */
559 *found |= TLVFLAG_IPV4_EXT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000560#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000561 zlog_info ("ISIS-TLV (%s): IPv4 external Reachability length %d",
562 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000563#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000564 if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY)
565 {
566 while (length > value_len)
567 {
568 ipv4_reach = (struct ipv4_reachability *) pnt;
569 if (!tlvs->ipv4_ext_reachs)
570 tlvs->ipv4_ext_reachs = list_new ();
571 listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach);
572 value_len += 12;
573 pnt += 12;
574 }
575 }
576 else
577 {
578 pnt += length;
579 }
580 break;
jardineb5d44e2003-12-23 08:09:43 +0000581
hassof390d2c2004-09-10 20:48:21 +0000582 case TE_IPV4_REACHABILITY:
583 /* +-------+-------+-------+-------+-------+-------+-------+-------+
584 * | TE Metric | 4
585 * +-------+-------+-------+-------+-------+-------+-------+-------+
586 * | U/D | sTLV? | Prefix Mask Len | 1
587 * +-------+-------+-------+-------+-------+-------+-------+-------+
588 * | Prefix | 0-4
589 * +---------------------------------------------------------------+
590 * | sub tlvs |
591 * +---------------------------------------------------------------+
592 * : :
593 */
594 *found |= TLVFLAG_TE_IPV4_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000595#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000596 zlog_info ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
597 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000598#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000599 if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
600 {
601 while (length > value_len)
602 {
603 te_ipv4_reach = (struct te_ipv4_reachability *) pnt;
604 if (!tlvs->te_ipv4_reachs)
605 tlvs->te_ipv4_reachs = list_new ();
606 listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach);
607 /* this trickery is permitable since no subtlvs are defined */
608 value_len += 5 + ((te_ipv4_reach->control & 0x3F) ?
609 ((((te_ipv4_reach->control & 0x3F) -
610 1) >> 3) + 1) : 0);
611 pnt += 5 + ((te_ipv4_reach->control & 0x3F) ?
612 ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0);
613 }
614 }
615 else
616 {
617 pnt += length;
618 }
619 break;
jardineb5d44e2003-12-23 08:09:43 +0000620
621#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000622 case IPV6_ADDR:
623 /* +-------+-------+-------+-------+-------+-------+-------+-------+
624 * + IP version 6 address + 16
625 * +-------+-------+-------+-------+-------+-------+-------+-------+
626 * : :
627 */
628 *found |= TLVFLAG_IPV6_ADDR;
jardineb5d44e2003-12-23 08:09:43 +0000629#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000630 zlog_info ("ISIS-TLV (%s): IPv6 Address length %d",
631 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000632#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000633 if (*expected & TLVFLAG_IPV6_ADDR)
634 {
635 while (length > value_len)
636 {
637 ipv6_addr = (struct in6_addr *) pnt;
638 if (!tlvs->ipv6_addrs)
639 tlvs->ipv6_addrs = list_new ();
640 listnode_add (tlvs->ipv6_addrs, ipv6_addr);
641 value_len += 16;
642 pnt += 16;
643 }
644 }
645 else
646 {
647 pnt += length;
648 }
649 break;
jardineb5d44e2003-12-23 08:09:43 +0000650
hassof390d2c2004-09-10 20:48:21 +0000651 case IPV6_REACHABILITY:
652 /* +-------+-------+-------+-------+-------+-------+-------+-------+
653 * | Default Metric | 4
654 * +-------+-------+-------+-------+-------+-------+-------+-------+
655 * | Control Informantion |
656 * +---------------------------------------------------------------+
657 * | IPv6 Prefix Length |--+
658 * +---------------------------------------------------------------+ |
659 * | IPv6 Prefix |<-+
660 * +---------------------------------------------------------------+
661 */
662 *found |= TLVFLAG_IPV6_REACHABILITY;
663 if (*expected & TLVFLAG_IPV6_REACHABILITY)
664 {
665 while (length > value_len)
666 {
667 ipv6_reach = (struct ipv6_reachability *) pnt;
668 prefix_octets = ((ipv6_reach->prefix_len + 7) / 8);
669 value_len += prefix_octets + 6;
670 pnt += prefix_octets + 6;
671 /* FIXME: sub-tlvs */
672 if (!tlvs->ipv6_reachs)
673 tlvs->ipv6_reachs = list_new ();
674 listnode_add (tlvs->ipv6_reachs, ipv6_reach);
675 }
676 }
677 else
678 {
679 pnt += length;
680 }
681 break;
jardineb5d44e2003-12-23 08:09:43 +0000682#endif /* HAVE_IPV6 */
683
hassof390d2c2004-09-10 20:48:21 +0000684 case WAY3_HELLO:
685 /* +---------------------------------------------------------------+
686 * | Adjacency state | 1
687 * +---------------------------------------------------------------+
688 * | Extended Local Circuit ID | 4
689 * +---------------------------------------------------------------+
690 * | Neighbor System ID (If known) | 0-8
691 * (probably 6)
692 * +---------------------------------------------------------------+
693 * | Neighbor Local Circuit ID (If known) | 4
694 * +---------------------------------------------------------------+
695 */
696 *found |= TLVFLAG_3WAY_HELLO;
697 if (*expected & TLVFLAG_3WAY_HELLO)
698 {
699 while (length > value_len)
700 {
701 /* FIXME: make this work */
jardineb5d44e2003-12-23 08:09:43 +0000702/* Adjacency State (one octet):
703 0 = Up
704 1 = Initializing
705 2 = Down
706 Extended Local Circuit ID (four octets)
707 Neighbor System ID if known (zero to eight octets)
708 Neighbor Extended Local Circuit ID (four octets, if Neighbor
709 System ID is present) */
hassof390d2c2004-09-10 20:48:21 +0000710 pnt += length;
711 }
712 }
713 else
714 {
715 pnt += length;
716 }
jardineb5d44e2003-12-23 08:09:43 +0000717
hassof390d2c2004-09-10 20:48:21 +0000718 break;
719 case GRACEFUL_RESTART:
720 /* +-------+-------+-------+-------+-------+-------+-------+-------+
721 * | Reserved | SA | RA | RR | 1
722 * +-------+-------+-------+-------+-------+-------+-------+-------+
723 * | Remaining Time | 2
724 * +---------------------------------------------------------------+
725 * | Restarting Neighbor ID (If known) | 0-8
726 * +---------------------------------------------------------------+
727 */
728 *found |= TLVFLAG_GRACEFUL_RESTART;
729 if (*expected & TLVFLAG_GRACEFUL_RESTART)
730 {
731 /* FIXME: make this work */
732 }
733 pnt += length;
734 break;
jardineb5d44e2003-12-23 08:09:43 +0000735
hassof390d2c2004-09-10 20:48:21 +0000736 default:
737 zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
738 areatag, type, length);
jardineb5d44e2003-12-23 08:09:43 +0000739
hassof390d2c2004-09-10 20:48:21 +0000740 retval = ISIS_WARNING;
741 pnt += length;
742 break;
743 }
jardineb5d44e2003-12-23 08:09:43 +0000744 }
hassof390d2c2004-09-10 20:48:21 +0000745
jardineb5d44e2003-12-23 08:09:43 +0000746 return retval;
747}
748
749int
hassof390d2c2004-09-10 20:48:21 +0000750add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000751{
752
hassof390d2c2004-09-10 20:48:21 +0000753 if (STREAM_SIZE (stream) - stream_get_putp (stream) < len + 2)
754 {
755 zlog_warn ("No room for TLV of type %d", tag);
756 return ISIS_WARNING;
757 }
jardineb5d44e2003-12-23 08:09:43 +0000758
hassof390d2c2004-09-10 20:48:21 +0000759 stream_putc (stream, tag); /* TAG */
760 stream_putc (stream, len); /* LENGTH */
761 stream_put (stream, value, (int) len); /* VALUE */
jardineb5d44e2003-12-23 08:09:43 +0000762
763#ifdef EXTREME_DEBUG
764 zlog_info ("Added TLV %d len %d", tag, len);
765#endif /* EXTREME DEBUG */
766 return ISIS_OK;
767}
768
jardineb5d44e2003-12-23 08:09:43 +0000769int
hassof390d2c2004-09-10 20:48:21 +0000770tlv_add_area_addrs (struct list *area_addrs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000771{
772 struct listnode *node;
773 struct area_addr *area_addr;
774
hassof390d2c2004-09-10 20:48:21 +0000775 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000776 u_char *pos = value;
hassof390d2c2004-09-10 20:48:21 +0000777
778 for (node = listhead (area_addrs); node; nextnode (node))
779 {
780 area_addr = getdata (node);
781 if (pos - value + area_addr->addr_len > 255)
782 goto err;
783 *pos = area_addr->addr_len;
784 pos++;
785 memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len);
786 pos += area_addr->addr_len;
787 }
788
jardineb5d44e2003-12-23 08:09:43 +0000789 return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
790
hassof390d2c2004-09-10 20:48:21 +0000791err:
jardineb5d44e2003-12-23 08:09:43 +0000792 zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
793 return ISIS_WARNING;
794}
795
hassof390d2c2004-09-10 20:48:21 +0000796int
797tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000798{
799 struct listnode *node;
800 struct is_neigh *is_neigh;
hassof390d2c2004-09-10 20:48:21 +0000801 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000802 u_char *pos = value;
803 int retval;
804
hassof390d2c2004-09-10 20:48:21 +0000805 *pos = 0; /*is_neigh->virtual; */
806 pos++;
jardineb5d44e2003-12-23 08:09:43 +0000807
hassof390d2c2004-09-10 20:48:21 +0000808 for (node = listhead (is_neighs); node; nextnode (node))
809 {
810 is_neigh = getdata (node);
811 if (pos - value + IS_NEIGHBOURS_LEN > 255)
812 {
813 retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
814 if (retval != ISIS_OK)
815 return retval;
816 pos = value;
817 }
818 *pos = is_neigh->metrics.metric_default;
819 pos++;
820 *pos = is_neigh->metrics.metric_delay;
821 pos++;
822 *pos = is_neigh->metrics.metric_expense;
823 pos++;
824 *pos = is_neigh->metrics.metric_error;
825 pos++;
826 memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
827 pos += ISIS_SYS_ID_LEN + 1;
jardineb5d44e2003-12-23 08:09:43 +0000828 }
jardineb5d44e2003-12-23 08:09:43 +0000829
830 return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
831}
832
jardineb5d44e2003-12-23 08:09:43 +0000833int
834tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
835{
836 struct listnode *node;
837 u_char *snpa;
hassof390d2c2004-09-10 20:48:21 +0000838 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000839 u_char *pos = value;
840 int retval;
841
hassof390d2c2004-09-10 20:48:21 +0000842 for (node = listhead (lan_neighs); node; nextnode (node))
843 {
844 snpa = getdata (node);
845 if (pos - value + ETH_ALEN > 255)
846 {
847 retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
848 if (retval != ISIS_OK)
849 return retval;
850 pos = value;
851 }
852 memcpy (pos, snpa, ETH_ALEN);
853 pos += ETH_ALEN;
jardineb5d44e2003-12-23 08:09:43 +0000854 }
jardineb5d44e2003-12-23 08:09:43 +0000855
856 return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
857}
858
jardineb5d44e2003-12-23 08:09:43 +0000859/*
860 u_char value[255];
861 u_char *pos = value;
862
863 if (circuit->ip_router) {
864 *pos = (u_char)NLPID_IP;
865 pos ++;
866 }
867 if (circuit->ipv6_router) {
868 *pos = (u_char)NLPID_IPV6;
869 pos ++;
870 }
871*/
872
873int
874tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
875{
hassof390d2c2004-09-10 20:48:21 +0000876
877 return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream);
jardineb5d44e2003-12-23 08:09:43 +0000878}
879
hassof390d2c2004-09-10 20:48:21 +0000880int
881tlv_add_authinfo (char auth_type, char auth_len, char *auth_value,
882 struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000883{
884 u_char value[255];
885 u_char *pos = value;
886 pos++;
887 memcpy (pos, auth_value, auth_len);
888
889 return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
890}
891
892int
893tlv_add_checksum (struct checksum *checksum, struct stream *stream)
894{
895 u_char value[255];
hassof390d2c2004-09-10 20:48:21 +0000896 u_char *pos = value;
897 return add_tlv (CHECKSUM, pos - value, value, stream);
jardineb5d44e2003-12-23 08:09:43 +0000898}
899
900int
901tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
902{
903 struct listnode *node;
904 struct prefix_ipv4 *ipv4;
905 u_char value[255];
906 u_char *pos = value;
907 int retval;
908
hassof390d2c2004-09-10 20:48:21 +0000909 for (node = listhead (ip_addrs); node; nextnode (node))
910 {
911 ipv4 = getdata (node);
912 if (pos - value + IPV4_MAX_BYTELEN > 255)
913 {
914 retval = add_tlv (IPV4_ADDR, pos - value, value, stream);
915 if (retval != ISIS_OK)
916 return retval;
917 pos = value;
918 }
919 *(u_int32_t *) pos = ipv4->prefix.s_addr;
920 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000921 }
hassof390d2c2004-09-10 20:48:21 +0000922
jardineb5d44e2003-12-23 08:09:43 +0000923 return add_tlv (IPV4_ADDR, pos - value, value, stream);
924}
925
926int
927tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
928{
hassof390d2c2004-09-10 20:48:21 +0000929 return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
930 stream);
jardineb5d44e2003-12-23 08:09:43 +0000931}
932
hassof390d2c2004-09-10 20:48:21 +0000933int
jardineb5d44e2003-12-23 08:09:43 +0000934tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
935{
936 struct listnode *node;
937 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000938 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000939 u_char *pos = value;
940 int retval;
941
hassof390d2c2004-09-10 20:48:21 +0000942 for (node = listhead (lsps); node; nextnode (node))
943 {
944 lsp = getdata (node);
945 if (pos - value + LSP_ENTRIES_LEN > 255)
946 {
947 retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
948 if (retval != ISIS_OK)
949 return retval;
950 pos = value;
951 }
952 *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime;
953 pos += 2;
954 memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
955 pos += ISIS_SYS_ID_LEN + 2;
956 *((u_int32_t *) pos) = lsp->lsp_header->seq_num;
957 pos += 4;
958 *((u_int16_t *) pos) = lsp->lsp_header->checksum;
959 pos += 2;
jardineb5d44e2003-12-23 08:09:43 +0000960 }
hassof390d2c2004-09-10 20:48:21 +0000961
jardineb5d44e2003-12-23 08:09:43 +0000962 return add_tlv (LSP_ENTRIES, pos - value, value, stream);
963}
964
hassof390d2c2004-09-10 20:48:21 +0000965int
jardineb5d44e2003-12-23 08:09:43 +0000966tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
967{
968 struct listnode *node;
969 struct ipv4_reachability *reach;
hassof390d2c2004-09-10 20:48:21 +0000970 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000971 u_char *pos = value;
972 int retval;
973
hassof390d2c2004-09-10 20:48:21 +0000974 for (node = listhead (ipv4_reachs); node; nextnode (node))
975 {
976 reach = getdata (node);
977 if (pos - value + IPV4_REACH_LEN > 255)
978 {
979 retval =
980 add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
981 if (retval != ISIS_OK)
982 return retval;
983 pos = value;
984 }
985 *pos = reach->metrics.metric_default;
986 pos++;
987 *pos = reach->metrics.metric_delay;
988 pos++;
989 *pos = reach->metrics.metric_expense;
990 pos++;
991 *pos = reach->metrics.metric_error;
992 pos++;
993 *(u_int32_t *) pos = reach->prefix.s_addr;
994 pos += IPV4_MAX_BYTELEN;
995 *(u_int32_t *) pos = reach->mask.s_addr;
996 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000997 }
hassof390d2c2004-09-10 20:48:21 +0000998
999
jardineb5d44e2003-12-23 08:09:43 +00001000 return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
1001}
1002
hassof390d2c2004-09-10 20:48:21 +00001003#ifdef HAVE_IPV6
jardineb5d44e2003-12-23 08:09:43 +00001004int
1005tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
1006{
1007 struct listnode *node;
1008 struct prefix_ipv6 *ipv6;
1009 u_char value[255];
1010 u_char *pos = value;
1011 int retval;
hassof390d2c2004-09-10 20:48:21 +00001012
1013 for (node = listhead (ipv6_addrs); node; nextnode (node))
1014 {
1015 ipv6 = getdata (node);
1016 if (pos - value + IPV6_MAX_BYTELEN > 255)
1017 {
1018 retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
1019 if (retval != ISIS_OK)
1020 return retval;
1021 pos = value;
1022 }
1023 memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
1024 pos += IPV6_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +00001025 }
hassof390d2c2004-09-10 20:48:21 +00001026
jardineb5d44e2003-12-23 08:09:43 +00001027 return add_tlv (IPV6_ADDR, pos - value, value, stream);
1028}
1029
1030int
1031tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
1032{
1033 struct listnode *node;
1034 struct ipv6_reachability *ip6reach;
1035 u_char value[255];
1036 u_char *pos = value;
1037 int retval, prefix_octets;
hassof390d2c2004-09-10 20:48:21 +00001038
1039 for (node = listhead (ipv6_reachs); node; nextnode (node))
1040 {
1041 ip6reach = getdata (node);
1042 if (pos - value + IPV6_MAX_BYTELEN + 6 > 255)
1043 {
1044 retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1045 if (retval != ISIS_OK)
1046 return retval;
1047 pos = value;
1048 }
1049 *(uint32_t *) pos = ip6reach->metric;
1050 pos += 4;
1051 *pos = ip6reach->control_info;
1052 pos++;
1053 prefix_octets = ((ip6reach->prefix_len + 7) / 8);
1054 *pos = ip6reach->prefix_len;
1055 pos++;
1056 memcpy (pos, ip6reach->prefix, prefix_octets);
1057 pos += prefix_octets;
jardineb5d44e2003-12-23 08:09:43 +00001058 }
hassof390d2c2004-09-10 20:48:21 +00001059
jardineb5d44e2003-12-23 08:09:43 +00001060 return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1061}
1062#endif /* HAVE_IPV6 */
1063
1064int
1065tlv_add_padding (struct stream *stream)
1066{
1067 unsigned long putp, endp;
hassof390d2c2004-09-10 20:48:21 +00001068 int fullpads, i, left;
1069
jardineb5d44e2003-12-23 08:09:43 +00001070 /*
1071 * How many times can we add full padding ?
1072 */
hassof390d2c2004-09-10 20:48:21 +00001073 fullpads = (STREAM_SIZE (stream) - stream_get_endp (stream)) / 257;
1074 for (i = 0; i < fullpads; i++)
1075 {
1076 if (!stream_putc (stream, (u_char) PADDING)) /* TAG */
1077 goto err;
1078 if (!stream_putc (stream, (u_char) 255)) /* LENGHT */
1079 goto err;
1080 endp = stream_get_endp (stream);
1081 putp = stream_get_putp (stream);
1082 if (putp != endp)
1083 zlog_warn ("tvl_add_padding endp %ld while putp %ld", endp, putp);
1084 stream_set_putp (stream, putp + 255); /* VALUE */
1085 stream->endp = stream->putp;
1086 }
1087
1088 left = STREAM_SIZE (stream) - stream_get_putp (stream);
1089
jardineb5d44e2003-12-23 08:09:43 +00001090 if (left < 2)
1091 return ISIS_OK;
hassof390d2c2004-09-10 20:48:21 +00001092
1093 if (left == 2)
1094 {
1095 stream_putc (stream, PADDING);
1096 stream_putc (stream, 0);
1097 return ISIS_OK;
1098 }
1099
jardineb5d44e2003-12-23 08:09:43 +00001100 stream_putc (stream, PADDING);
1101 stream_putc (stream, left - 2);
1102 stream_set_putp (stream, stream_get_putp (stream) + left - 2);
1103 stream->endp = stream->putp;
1104
1105 return ISIS_OK;
1106
hassof390d2c2004-09-10 20:48:21 +00001107err:
jardineb5d44e2003-12-23 08:09:43 +00001108 zlog_warn ("tlv_add_padding(): no room for tlv");
1109 return ISIS_WARNING;
1110}