blob: 273d19c2235c387ccd8d5a23fe946e271946bf88 [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;
hassof891f442004-09-14 13:54:30 +0000440#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000441 zlog_info ("ISIS-TLV (%s) : IP ADDR %s, pnt %p", areatag,
442 inet_ntoa (*ipv4_addr), pnt);
hassof891f442004-09-14 13:54:30 +0000443#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000444 if (!tlvs->ipv4_addrs)
445 tlvs->ipv4_addrs = list_new ();
446 listnode_add (tlvs->ipv4_addrs, ipv4_addr);
447 value_len += 4;
448 pnt += 4;
449 }
450 }
451 else
452 {
453 pnt += length;
454 }
455 break;
456
457 case AUTH_INFO:
458 *found |= TLVFLAG_AUTH_INFO;
459#ifdef EXTREME_TLV_DEBUG
460 zlog_info ("ISIS-TLV (%s): IS-IS Authentication Information",
461 areatag);
jardineb5d44e2003-12-23 08:09:43 +0000462#endif
hassof390d2c2004-09-10 20:48:21 +0000463 if (*expected & TLVFLAG_AUTH_INFO)
464 {
465 tlvs->auth_info.type = *pnt;
466 pnt++;
467 memcpy (tlvs->auth_info.passwd, pnt, length - 1);
468 pnt += length - 1;
469 }
470 else
471 {
472 pnt += length;
473 }
474 break;
jardineb5d44e2003-12-23 08:09:43 +0000475
hassof390d2c2004-09-10 20:48:21 +0000476 case DYNAMIC_HOSTNAME:
477 *found |= TLVFLAG_DYN_HOSTNAME;
jardineb5d44e2003-12-23 08:09:43 +0000478#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000479 zlog_info ("ISIS-TLV (%s): Dynamic Hostname length %d",
480 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000481#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000482 if (*expected & TLVFLAG_DYN_HOSTNAME)
483 {
484 /* the length is also included in the pointed struct */
485 tlvs->hostname = (struct hostname *) (pnt - 1);
486 }
487 pnt += length;
488 break;
jardineb5d44e2003-12-23 08:09:43 +0000489
hassof390d2c2004-09-10 20:48:21 +0000490 case TE_ROUTER_ID:
491 /* +---------------------------------------------------------------+
492 * + Router ID + 4
493 * +---------------------------------------------------------------+
494 */
495 *found |= TLVFLAG_TE_ROUTER_ID;
jardineb5d44e2003-12-23 08:09:43 +0000496#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000497 zlog_info ("ISIS-TLV (%s): TE Router ID %d", areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000498#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000499 if (*expected & TLVFLAG_TE_ROUTER_ID)
500 {
501 tlvs->router_id = (struct te_router_id *) (pnt);
502 }
503 pnt += length;
504 break;
jardineb5d44e2003-12-23 08:09:43 +0000505
hassof390d2c2004-09-10 20:48:21 +0000506 case IPV4_INT_REACHABILITY:
507 /* +-------+-------+-------+-------+-------+-------+-------+-------+
508 * | 0 | I/E | Default Metric | 1
509 * +-------+-------+-------+-------+-------+-------+-------+-------+
510 * | S | I/E | Delay Metric | 1
511 * +-------+-------+-------+-------+-------+-------+-------+-------+
512 * | S | I/E | Expense Metric | 1
513 * +-------+-------+-------+-------+-------+-------+-------+-------+
514 * | S | I/E | Error Metric | 1
515 * +-------+-------+-------+-------+-------+-------+-------+-------+
516 * | ip address | 4
517 * +---------------------------------------------------------------+
518 * | address mask | 4
519 * +---------------------------------------------------------------+
520 * : :
521 */
522 *found |= TLVFLAG_IPV4_INT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000523#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000524 zlog_info ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
525 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000526#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000527 if (*expected & TLVFLAG_IPV4_INT_REACHABILITY)
528 {
529 while (length > value_len)
530 {
531 ipv4_reach = (struct ipv4_reachability *) pnt;
532 if (!tlvs->ipv4_int_reachs)
533 tlvs->ipv4_int_reachs = list_new ();
534 listnode_add (tlvs->ipv4_int_reachs, ipv4_reach);
535 value_len += 12;
536 pnt += 12;
537 }
538 }
539 else
540 {
541 pnt += length;
542 }
543 break;
jardineb5d44e2003-12-23 08:09:43 +0000544
hassof390d2c2004-09-10 20:48:21 +0000545 case IPV4_EXT_REACHABILITY:
546 /* +-------+-------+-------+-------+-------+-------+-------+-------+
547 * | 0 | I/E | Default Metric | 1
548 * +-------+-------+-------+-------+-------+-------+-------+-------+
549 * | S | I/E | Delay Metric | 1
550 * +-------+-------+-------+-------+-------+-------+-------+-------+
551 * | S | I/E | Expense Metric | 1
552 * +-------+-------+-------+-------+-------+-------+-------+-------+
553 * | S | I/E | Error Metric | 1
554 * +-------+-------+-------+-------+-------+-------+-------+-------+
555 * | ip address | 4
556 * +---------------------------------------------------------------+
557 * | address mask | 4
558 * +---------------------------------------------------------------+
559 * : :
560 */
561 *found |= TLVFLAG_IPV4_EXT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000562#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000563 zlog_info ("ISIS-TLV (%s): IPv4 external Reachability length %d",
564 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000565#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000566 if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY)
567 {
568 while (length > value_len)
569 {
570 ipv4_reach = (struct ipv4_reachability *) pnt;
571 if (!tlvs->ipv4_ext_reachs)
572 tlvs->ipv4_ext_reachs = list_new ();
573 listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach);
574 value_len += 12;
575 pnt += 12;
576 }
577 }
578 else
579 {
580 pnt += length;
581 }
582 break;
jardineb5d44e2003-12-23 08:09:43 +0000583
hassof390d2c2004-09-10 20:48:21 +0000584 case TE_IPV4_REACHABILITY:
585 /* +-------+-------+-------+-------+-------+-------+-------+-------+
586 * | TE Metric | 4
587 * +-------+-------+-------+-------+-------+-------+-------+-------+
588 * | U/D | sTLV? | Prefix Mask Len | 1
589 * +-------+-------+-------+-------+-------+-------+-------+-------+
590 * | Prefix | 0-4
591 * +---------------------------------------------------------------+
592 * | sub tlvs |
593 * +---------------------------------------------------------------+
594 * : :
595 */
596 *found |= TLVFLAG_TE_IPV4_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000597#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000598 zlog_info ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
599 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000600#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000601 if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
602 {
603 while (length > value_len)
604 {
605 te_ipv4_reach = (struct te_ipv4_reachability *) pnt;
606 if (!tlvs->te_ipv4_reachs)
607 tlvs->te_ipv4_reachs = list_new ();
608 listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach);
609 /* this trickery is permitable since no subtlvs are defined */
610 value_len += 5 + ((te_ipv4_reach->control & 0x3F) ?
611 ((((te_ipv4_reach->control & 0x3F) -
612 1) >> 3) + 1) : 0);
613 pnt += 5 + ((te_ipv4_reach->control & 0x3F) ?
614 ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0);
615 }
616 }
617 else
618 {
619 pnt += length;
620 }
621 break;
jardineb5d44e2003-12-23 08:09:43 +0000622
623#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000624 case IPV6_ADDR:
625 /* +-------+-------+-------+-------+-------+-------+-------+-------+
626 * + IP version 6 address + 16
627 * +-------+-------+-------+-------+-------+-------+-------+-------+
628 * : :
629 */
630 *found |= TLVFLAG_IPV6_ADDR;
jardineb5d44e2003-12-23 08:09:43 +0000631#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000632 zlog_info ("ISIS-TLV (%s): IPv6 Address length %d",
633 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000634#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000635 if (*expected & TLVFLAG_IPV6_ADDR)
636 {
637 while (length > value_len)
638 {
639 ipv6_addr = (struct in6_addr *) pnt;
640 if (!tlvs->ipv6_addrs)
641 tlvs->ipv6_addrs = list_new ();
642 listnode_add (tlvs->ipv6_addrs, ipv6_addr);
643 value_len += 16;
644 pnt += 16;
645 }
646 }
647 else
648 {
649 pnt += length;
650 }
651 break;
jardineb5d44e2003-12-23 08:09:43 +0000652
hassof390d2c2004-09-10 20:48:21 +0000653 case IPV6_REACHABILITY:
654 /* +-------+-------+-------+-------+-------+-------+-------+-------+
655 * | Default Metric | 4
656 * +-------+-------+-------+-------+-------+-------+-------+-------+
657 * | Control Informantion |
658 * +---------------------------------------------------------------+
659 * | IPv6 Prefix Length |--+
660 * +---------------------------------------------------------------+ |
661 * | IPv6 Prefix |<-+
662 * +---------------------------------------------------------------+
663 */
664 *found |= TLVFLAG_IPV6_REACHABILITY;
665 if (*expected & TLVFLAG_IPV6_REACHABILITY)
666 {
667 while (length > value_len)
668 {
669 ipv6_reach = (struct ipv6_reachability *) pnt;
670 prefix_octets = ((ipv6_reach->prefix_len + 7) / 8);
671 value_len += prefix_octets + 6;
672 pnt += prefix_octets + 6;
673 /* FIXME: sub-tlvs */
674 if (!tlvs->ipv6_reachs)
675 tlvs->ipv6_reachs = list_new ();
676 listnode_add (tlvs->ipv6_reachs, ipv6_reach);
677 }
678 }
679 else
680 {
681 pnt += length;
682 }
683 break;
jardineb5d44e2003-12-23 08:09:43 +0000684#endif /* HAVE_IPV6 */
685
hassof390d2c2004-09-10 20:48:21 +0000686 case WAY3_HELLO:
687 /* +---------------------------------------------------------------+
688 * | Adjacency state | 1
689 * +---------------------------------------------------------------+
690 * | Extended Local Circuit ID | 4
691 * +---------------------------------------------------------------+
692 * | Neighbor System ID (If known) | 0-8
693 * (probably 6)
694 * +---------------------------------------------------------------+
695 * | Neighbor Local Circuit ID (If known) | 4
696 * +---------------------------------------------------------------+
697 */
698 *found |= TLVFLAG_3WAY_HELLO;
699 if (*expected & TLVFLAG_3WAY_HELLO)
700 {
701 while (length > value_len)
702 {
703 /* FIXME: make this work */
jardineb5d44e2003-12-23 08:09:43 +0000704/* Adjacency State (one octet):
705 0 = Up
706 1 = Initializing
707 2 = Down
708 Extended Local Circuit ID (four octets)
709 Neighbor System ID if known (zero to eight octets)
710 Neighbor Extended Local Circuit ID (four octets, if Neighbor
711 System ID is present) */
hassof390d2c2004-09-10 20:48:21 +0000712 pnt += length;
713 }
714 }
715 else
716 {
717 pnt += length;
718 }
jardineb5d44e2003-12-23 08:09:43 +0000719
hassof390d2c2004-09-10 20:48:21 +0000720 break;
721 case GRACEFUL_RESTART:
722 /* +-------+-------+-------+-------+-------+-------+-------+-------+
723 * | Reserved | SA | RA | RR | 1
724 * +-------+-------+-------+-------+-------+-------+-------+-------+
725 * | Remaining Time | 2
726 * +---------------------------------------------------------------+
727 * | Restarting Neighbor ID (If known) | 0-8
728 * +---------------------------------------------------------------+
729 */
730 *found |= TLVFLAG_GRACEFUL_RESTART;
731 if (*expected & TLVFLAG_GRACEFUL_RESTART)
732 {
733 /* FIXME: make this work */
734 }
735 pnt += length;
736 break;
jardineb5d44e2003-12-23 08:09:43 +0000737
hassof390d2c2004-09-10 20:48:21 +0000738 default:
739 zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
740 areatag, type, length);
jardineb5d44e2003-12-23 08:09:43 +0000741
hassof390d2c2004-09-10 20:48:21 +0000742 retval = ISIS_WARNING;
743 pnt += length;
744 break;
745 }
jardineb5d44e2003-12-23 08:09:43 +0000746 }
hassof390d2c2004-09-10 20:48:21 +0000747
jardineb5d44e2003-12-23 08:09:43 +0000748 return retval;
749}
750
751int
hassof390d2c2004-09-10 20:48:21 +0000752add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000753{
754
hassof390d2c2004-09-10 20:48:21 +0000755 if (STREAM_SIZE (stream) - stream_get_putp (stream) < len + 2)
756 {
757 zlog_warn ("No room for TLV of type %d", tag);
758 return ISIS_WARNING;
759 }
jardineb5d44e2003-12-23 08:09:43 +0000760
hassof390d2c2004-09-10 20:48:21 +0000761 stream_putc (stream, tag); /* TAG */
762 stream_putc (stream, len); /* LENGTH */
763 stream_put (stream, value, (int) len); /* VALUE */
jardineb5d44e2003-12-23 08:09:43 +0000764
765#ifdef EXTREME_DEBUG
766 zlog_info ("Added TLV %d len %d", tag, len);
767#endif /* EXTREME DEBUG */
768 return ISIS_OK;
769}
770
jardineb5d44e2003-12-23 08:09:43 +0000771int
hassof390d2c2004-09-10 20:48:21 +0000772tlv_add_area_addrs (struct list *area_addrs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000773{
774 struct listnode *node;
775 struct area_addr *area_addr;
776
hassof390d2c2004-09-10 20:48:21 +0000777 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000778 u_char *pos = value;
hassof390d2c2004-09-10 20:48:21 +0000779
780 for (node = listhead (area_addrs); node; nextnode (node))
781 {
782 area_addr = getdata (node);
783 if (pos - value + area_addr->addr_len > 255)
784 goto err;
785 *pos = area_addr->addr_len;
786 pos++;
787 memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len);
788 pos += area_addr->addr_len;
789 }
790
jardineb5d44e2003-12-23 08:09:43 +0000791 return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
792
hassof390d2c2004-09-10 20:48:21 +0000793err:
jardineb5d44e2003-12-23 08:09:43 +0000794 zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
795 return ISIS_WARNING;
796}
797
hassof390d2c2004-09-10 20:48:21 +0000798int
799tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000800{
801 struct listnode *node;
802 struct is_neigh *is_neigh;
hassof390d2c2004-09-10 20:48:21 +0000803 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000804 u_char *pos = value;
805 int retval;
806
hassof390d2c2004-09-10 20:48:21 +0000807 *pos = 0; /*is_neigh->virtual; */
808 pos++;
jardineb5d44e2003-12-23 08:09:43 +0000809
hassof390d2c2004-09-10 20:48:21 +0000810 for (node = listhead (is_neighs); node; nextnode (node))
811 {
812 is_neigh = getdata (node);
813 if (pos - value + IS_NEIGHBOURS_LEN > 255)
814 {
815 retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
816 if (retval != ISIS_OK)
817 return retval;
818 pos = value;
819 }
820 *pos = is_neigh->metrics.metric_default;
821 pos++;
822 *pos = is_neigh->metrics.metric_delay;
823 pos++;
824 *pos = is_neigh->metrics.metric_expense;
825 pos++;
826 *pos = is_neigh->metrics.metric_error;
827 pos++;
828 memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
829 pos += ISIS_SYS_ID_LEN + 1;
jardineb5d44e2003-12-23 08:09:43 +0000830 }
jardineb5d44e2003-12-23 08:09:43 +0000831
832 return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
833}
834
jardineb5d44e2003-12-23 08:09:43 +0000835int
836tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
837{
838 struct listnode *node;
839 u_char *snpa;
hassof390d2c2004-09-10 20:48:21 +0000840 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000841 u_char *pos = value;
842 int retval;
843
hassof390d2c2004-09-10 20:48:21 +0000844 for (node = listhead (lan_neighs); node; nextnode (node))
845 {
846 snpa = getdata (node);
847 if (pos - value + ETH_ALEN > 255)
848 {
849 retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
850 if (retval != ISIS_OK)
851 return retval;
852 pos = value;
853 }
854 memcpy (pos, snpa, ETH_ALEN);
855 pos += ETH_ALEN;
jardineb5d44e2003-12-23 08:09:43 +0000856 }
jardineb5d44e2003-12-23 08:09:43 +0000857
858 return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
859}
860
jardineb5d44e2003-12-23 08:09:43 +0000861/*
862 u_char value[255];
863 u_char *pos = value;
864
865 if (circuit->ip_router) {
866 *pos = (u_char)NLPID_IP;
867 pos ++;
868 }
869 if (circuit->ipv6_router) {
870 *pos = (u_char)NLPID_IPV6;
871 pos ++;
872 }
873*/
874
875int
876tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
877{
hassof390d2c2004-09-10 20:48:21 +0000878
879 return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream);
jardineb5d44e2003-12-23 08:09:43 +0000880}
881
hassof390d2c2004-09-10 20:48:21 +0000882int
883tlv_add_authinfo (char auth_type, char auth_len, char *auth_value,
884 struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000885{
886 u_char value[255];
887 u_char *pos = value;
888 pos++;
889 memcpy (pos, auth_value, auth_len);
890
891 return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
892}
893
894int
895tlv_add_checksum (struct checksum *checksum, struct stream *stream)
896{
897 u_char value[255];
hassof390d2c2004-09-10 20:48:21 +0000898 u_char *pos = value;
899 return add_tlv (CHECKSUM, pos - value, value, stream);
jardineb5d44e2003-12-23 08:09:43 +0000900}
901
902int
903tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
904{
905 struct listnode *node;
906 struct prefix_ipv4 *ipv4;
907 u_char value[255];
908 u_char *pos = value;
909 int retval;
910
hassof390d2c2004-09-10 20:48:21 +0000911 for (node = listhead (ip_addrs); node; nextnode (node))
912 {
913 ipv4 = getdata (node);
914 if (pos - value + IPV4_MAX_BYTELEN > 255)
915 {
916 retval = add_tlv (IPV4_ADDR, pos - value, value, stream);
917 if (retval != ISIS_OK)
918 return retval;
919 pos = value;
920 }
921 *(u_int32_t *) pos = ipv4->prefix.s_addr;
922 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000923 }
hassof390d2c2004-09-10 20:48:21 +0000924
jardineb5d44e2003-12-23 08:09:43 +0000925 return add_tlv (IPV4_ADDR, pos - value, value, stream);
926}
927
928int
929tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
930{
hassof390d2c2004-09-10 20:48:21 +0000931 return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
932 stream);
jardineb5d44e2003-12-23 08:09:43 +0000933}
934
hassof390d2c2004-09-10 20:48:21 +0000935int
jardineb5d44e2003-12-23 08:09:43 +0000936tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
937{
938 struct listnode *node;
939 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000940 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000941 u_char *pos = value;
942 int retval;
943
hassof390d2c2004-09-10 20:48:21 +0000944 for (node = listhead (lsps); node; nextnode (node))
945 {
946 lsp = getdata (node);
947 if (pos - value + LSP_ENTRIES_LEN > 255)
948 {
949 retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
950 if (retval != ISIS_OK)
951 return retval;
952 pos = value;
953 }
954 *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime;
955 pos += 2;
956 memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
957 pos += ISIS_SYS_ID_LEN + 2;
958 *((u_int32_t *) pos) = lsp->lsp_header->seq_num;
959 pos += 4;
960 *((u_int16_t *) pos) = lsp->lsp_header->checksum;
961 pos += 2;
jardineb5d44e2003-12-23 08:09:43 +0000962 }
hassof390d2c2004-09-10 20:48:21 +0000963
jardineb5d44e2003-12-23 08:09:43 +0000964 return add_tlv (LSP_ENTRIES, pos - value, value, stream);
965}
966
hassof390d2c2004-09-10 20:48:21 +0000967int
jardineb5d44e2003-12-23 08:09:43 +0000968tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
969{
970 struct listnode *node;
971 struct ipv4_reachability *reach;
hassof390d2c2004-09-10 20:48:21 +0000972 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000973 u_char *pos = value;
974 int retval;
975
hassof390d2c2004-09-10 20:48:21 +0000976 for (node = listhead (ipv4_reachs); node; nextnode (node))
977 {
978 reach = getdata (node);
979 if (pos - value + IPV4_REACH_LEN > 255)
980 {
981 retval =
982 add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
983 if (retval != ISIS_OK)
984 return retval;
985 pos = value;
986 }
987 *pos = reach->metrics.metric_default;
988 pos++;
989 *pos = reach->metrics.metric_delay;
990 pos++;
991 *pos = reach->metrics.metric_expense;
992 pos++;
993 *pos = reach->metrics.metric_error;
994 pos++;
995 *(u_int32_t *) pos = reach->prefix.s_addr;
996 pos += IPV4_MAX_BYTELEN;
997 *(u_int32_t *) pos = reach->mask.s_addr;
998 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000999 }
hassof390d2c2004-09-10 20:48:21 +00001000
1001
jardineb5d44e2003-12-23 08:09:43 +00001002 return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
1003}
1004
hassof390d2c2004-09-10 20:48:21 +00001005#ifdef HAVE_IPV6
jardineb5d44e2003-12-23 08:09:43 +00001006int
1007tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
1008{
1009 struct listnode *node;
1010 struct prefix_ipv6 *ipv6;
1011 u_char value[255];
1012 u_char *pos = value;
1013 int retval;
hassof390d2c2004-09-10 20:48:21 +00001014
1015 for (node = listhead (ipv6_addrs); node; nextnode (node))
1016 {
1017 ipv6 = getdata (node);
1018 if (pos - value + IPV6_MAX_BYTELEN > 255)
1019 {
1020 retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
1021 if (retval != ISIS_OK)
1022 return retval;
1023 pos = value;
1024 }
1025 memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
1026 pos += IPV6_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +00001027 }
hassof390d2c2004-09-10 20:48:21 +00001028
jardineb5d44e2003-12-23 08:09:43 +00001029 return add_tlv (IPV6_ADDR, pos - value, value, stream);
1030}
1031
1032int
1033tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
1034{
1035 struct listnode *node;
1036 struct ipv6_reachability *ip6reach;
1037 u_char value[255];
1038 u_char *pos = value;
1039 int retval, prefix_octets;
hassof390d2c2004-09-10 20:48:21 +00001040
1041 for (node = listhead (ipv6_reachs); node; nextnode (node))
1042 {
1043 ip6reach = getdata (node);
1044 if (pos - value + IPV6_MAX_BYTELEN + 6 > 255)
1045 {
1046 retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1047 if (retval != ISIS_OK)
1048 return retval;
1049 pos = value;
1050 }
1051 *(uint32_t *) pos = ip6reach->metric;
1052 pos += 4;
1053 *pos = ip6reach->control_info;
1054 pos++;
1055 prefix_octets = ((ip6reach->prefix_len + 7) / 8);
1056 *pos = ip6reach->prefix_len;
1057 pos++;
1058 memcpy (pos, ip6reach->prefix, prefix_octets);
1059 pos += prefix_octets;
jardineb5d44e2003-12-23 08:09:43 +00001060 }
hassof390d2c2004-09-10 20:48:21 +00001061
jardineb5d44e2003-12-23 08:09:43 +00001062 return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1063}
1064#endif /* HAVE_IPV6 */
1065
1066int
1067tlv_add_padding (struct stream *stream)
1068{
1069 unsigned long putp, endp;
hassof390d2c2004-09-10 20:48:21 +00001070 int fullpads, i, left;
1071
jardineb5d44e2003-12-23 08:09:43 +00001072 /*
1073 * How many times can we add full padding ?
1074 */
hassof390d2c2004-09-10 20:48:21 +00001075 fullpads = (STREAM_SIZE (stream) - stream_get_endp (stream)) / 257;
1076 for (i = 0; i < fullpads; i++)
1077 {
1078 if (!stream_putc (stream, (u_char) PADDING)) /* TAG */
1079 goto err;
1080 if (!stream_putc (stream, (u_char) 255)) /* LENGHT */
1081 goto err;
1082 endp = stream_get_endp (stream);
1083 putp = stream_get_putp (stream);
1084 if (putp != endp)
1085 zlog_warn ("tvl_add_padding endp %ld while putp %ld", endp, putp);
1086 stream_set_putp (stream, putp + 255); /* VALUE */
1087 stream->endp = stream->putp;
1088 }
1089
1090 left = STREAM_SIZE (stream) - stream_get_putp (stream);
1091
jardineb5d44e2003-12-23 08:09:43 +00001092 if (left < 2)
1093 return ISIS_OK;
hassof390d2c2004-09-10 20:48:21 +00001094
1095 if (left == 2)
1096 {
1097 stream_putc (stream, PADDING);
1098 stream_putc (stream, 0);
1099 return ISIS_OK;
1100 }
1101
jardineb5d44e2003-12-23 08:09:43 +00001102 stream_putc (stream, PADDING);
1103 stream_putc (stream, left - 2);
1104 stream_set_putp (stream, stream_get_putp (stream) + left - 2);
1105 stream->endp = stream->putp;
1106
1107 return ISIS_OK;
1108
hassof390d2c2004-09-10 20:48:21 +00001109err:
jardineb5d44e2003-12-23 08:09:43 +00001110 zlog_warn ("tlv_add_padding(): no room for tlv");
1111 return ISIS_WARNING;
1112}