blob: c859ef0e866546720e76c2c0f18838027b4024f1 [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;
hasso53c997c2004-09-15 16:21:59 +0000466 tlvs->auth_info.len = length-1;
hassof390d2c2004-09-10 20:48:21 +0000467 pnt++;
468 memcpy (tlvs->auth_info.passwd, pnt, length - 1);
469 pnt += length - 1;
470 }
471 else
472 {
473 pnt += length;
474 }
475 break;
jardineb5d44e2003-12-23 08:09:43 +0000476
hassof390d2c2004-09-10 20:48:21 +0000477 case DYNAMIC_HOSTNAME:
478 *found |= TLVFLAG_DYN_HOSTNAME;
jardineb5d44e2003-12-23 08:09:43 +0000479#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000480 zlog_info ("ISIS-TLV (%s): Dynamic Hostname length %d",
481 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000482#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000483 if (*expected & TLVFLAG_DYN_HOSTNAME)
484 {
485 /* the length is also included in the pointed struct */
486 tlvs->hostname = (struct hostname *) (pnt - 1);
487 }
488 pnt += length;
489 break;
jardineb5d44e2003-12-23 08:09:43 +0000490
hassof390d2c2004-09-10 20:48:21 +0000491 case TE_ROUTER_ID:
492 /* +---------------------------------------------------------------+
493 * + Router ID + 4
494 * +---------------------------------------------------------------+
495 */
496 *found |= TLVFLAG_TE_ROUTER_ID;
jardineb5d44e2003-12-23 08:09:43 +0000497#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000498 zlog_info ("ISIS-TLV (%s): TE Router ID %d", areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000499#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000500 if (*expected & TLVFLAG_TE_ROUTER_ID)
501 {
502 tlvs->router_id = (struct te_router_id *) (pnt);
503 }
504 pnt += length;
505 break;
jardineb5d44e2003-12-23 08:09:43 +0000506
hassof390d2c2004-09-10 20:48:21 +0000507 case IPV4_INT_REACHABILITY:
508 /* +-------+-------+-------+-------+-------+-------+-------+-------+
509 * | 0 | I/E | Default Metric | 1
510 * +-------+-------+-------+-------+-------+-------+-------+-------+
511 * | S | I/E | Delay Metric | 1
512 * +-------+-------+-------+-------+-------+-------+-------+-------+
513 * | S | I/E | Expense Metric | 1
514 * +-------+-------+-------+-------+-------+-------+-------+-------+
515 * | S | I/E | Error Metric | 1
516 * +-------+-------+-------+-------+-------+-------+-------+-------+
517 * | ip address | 4
518 * +---------------------------------------------------------------+
519 * | address mask | 4
520 * +---------------------------------------------------------------+
521 * : :
522 */
523 *found |= TLVFLAG_IPV4_INT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000524#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000525 zlog_info ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
526 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000527#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000528 if (*expected & TLVFLAG_IPV4_INT_REACHABILITY)
529 {
530 while (length > value_len)
531 {
532 ipv4_reach = (struct ipv4_reachability *) pnt;
533 if (!tlvs->ipv4_int_reachs)
534 tlvs->ipv4_int_reachs = list_new ();
535 listnode_add (tlvs->ipv4_int_reachs, ipv4_reach);
536 value_len += 12;
537 pnt += 12;
538 }
539 }
540 else
541 {
542 pnt += length;
543 }
544 break;
jardineb5d44e2003-12-23 08:09:43 +0000545
hassof390d2c2004-09-10 20:48:21 +0000546 case IPV4_EXT_REACHABILITY:
547 /* +-------+-------+-------+-------+-------+-------+-------+-------+
548 * | 0 | I/E | Default Metric | 1
549 * +-------+-------+-------+-------+-------+-------+-------+-------+
550 * | S | I/E | Delay Metric | 1
551 * +-------+-------+-------+-------+-------+-------+-------+-------+
552 * | S | I/E | Expense Metric | 1
553 * +-------+-------+-------+-------+-------+-------+-------+-------+
554 * | S | I/E | Error Metric | 1
555 * +-------+-------+-------+-------+-------+-------+-------+-------+
556 * | ip address | 4
557 * +---------------------------------------------------------------+
558 * | address mask | 4
559 * +---------------------------------------------------------------+
560 * : :
561 */
562 *found |= TLVFLAG_IPV4_EXT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000563#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000564 zlog_info ("ISIS-TLV (%s): IPv4 external Reachability length %d",
565 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000566#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000567 if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY)
568 {
569 while (length > value_len)
570 {
571 ipv4_reach = (struct ipv4_reachability *) pnt;
572 if (!tlvs->ipv4_ext_reachs)
573 tlvs->ipv4_ext_reachs = list_new ();
574 listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach);
575 value_len += 12;
576 pnt += 12;
577 }
578 }
579 else
580 {
581 pnt += length;
582 }
583 break;
jardineb5d44e2003-12-23 08:09:43 +0000584
hassof390d2c2004-09-10 20:48:21 +0000585 case TE_IPV4_REACHABILITY:
586 /* +-------+-------+-------+-------+-------+-------+-------+-------+
587 * | TE Metric | 4
588 * +-------+-------+-------+-------+-------+-------+-------+-------+
589 * | U/D | sTLV? | Prefix Mask Len | 1
590 * +-------+-------+-------+-------+-------+-------+-------+-------+
591 * | Prefix | 0-4
592 * +---------------------------------------------------------------+
593 * | sub tlvs |
594 * +---------------------------------------------------------------+
595 * : :
596 */
597 *found |= TLVFLAG_TE_IPV4_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000598#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000599 zlog_info ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
600 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000601#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000602 if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
603 {
604 while (length > value_len)
605 {
606 te_ipv4_reach = (struct te_ipv4_reachability *) pnt;
607 if (!tlvs->te_ipv4_reachs)
608 tlvs->te_ipv4_reachs = list_new ();
609 listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach);
610 /* this trickery is permitable since no subtlvs are defined */
611 value_len += 5 + ((te_ipv4_reach->control & 0x3F) ?
612 ((((te_ipv4_reach->control & 0x3F) -
613 1) >> 3) + 1) : 0);
614 pnt += 5 + ((te_ipv4_reach->control & 0x3F) ?
615 ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0);
616 }
617 }
618 else
619 {
620 pnt += length;
621 }
622 break;
jardineb5d44e2003-12-23 08:09:43 +0000623
624#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000625 case IPV6_ADDR:
626 /* +-------+-------+-------+-------+-------+-------+-------+-------+
627 * + IP version 6 address + 16
628 * +-------+-------+-------+-------+-------+-------+-------+-------+
629 * : :
630 */
631 *found |= TLVFLAG_IPV6_ADDR;
jardineb5d44e2003-12-23 08:09:43 +0000632#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000633 zlog_info ("ISIS-TLV (%s): IPv6 Address length %d",
634 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000635#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000636 if (*expected & TLVFLAG_IPV6_ADDR)
637 {
638 while (length > value_len)
639 {
640 ipv6_addr = (struct in6_addr *) pnt;
641 if (!tlvs->ipv6_addrs)
642 tlvs->ipv6_addrs = list_new ();
643 listnode_add (tlvs->ipv6_addrs, ipv6_addr);
644 value_len += 16;
645 pnt += 16;
646 }
647 }
648 else
649 {
650 pnt += length;
651 }
652 break;
jardineb5d44e2003-12-23 08:09:43 +0000653
hassof390d2c2004-09-10 20:48:21 +0000654 case IPV6_REACHABILITY:
655 /* +-------+-------+-------+-------+-------+-------+-------+-------+
656 * | Default Metric | 4
657 * +-------+-------+-------+-------+-------+-------+-------+-------+
658 * | Control Informantion |
659 * +---------------------------------------------------------------+
660 * | IPv6 Prefix Length |--+
661 * +---------------------------------------------------------------+ |
662 * | IPv6 Prefix |<-+
663 * +---------------------------------------------------------------+
664 */
665 *found |= TLVFLAG_IPV6_REACHABILITY;
666 if (*expected & TLVFLAG_IPV6_REACHABILITY)
667 {
668 while (length > value_len)
669 {
670 ipv6_reach = (struct ipv6_reachability *) pnt;
671 prefix_octets = ((ipv6_reach->prefix_len + 7) / 8);
672 value_len += prefix_octets + 6;
673 pnt += prefix_octets + 6;
674 /* FIXME: sub-tlvs */
675 if (!tlvs->ipv6_reachs)
676 tlvs->ipv6_reachs = list_new ();
677 listnode_add (tlvs->ipv6_reachs, ipv6_reach);
678 }
679 }
680 else
681 {
682 pnt += length;
683 }
684 break;
jardineb5d44e2003-12-23 08:09:43 +0000685#endif /* HAVE_IPV6 */
686
hassof390d2c2004-09-10 20:48:21 +0000687 case WAY3_HELLO:
688 /* +---------------------------------------------------------------+
689 * | Adjacency state | 1
690 * +---------------------------------------------------------------+
691 * | Extended Local Circuit ID | 4
692 * +---------------------------------------------------------------+
693 * | Neighbor System ID (If known) | 0-8
694 * (probably 6)
695 * +---------------------------------------------------------------+
696 * | Neighbor Local Circuit ID (If known) | 4
697 * +---------------------------------------------------------------+
698 */
699 *found |= TLVFLAG_3WAY_HELLO;
700 if (*expected & TLVFLAG_3WAY_HELLO)
701 {
702 while (length > value_len)
703 {
704 /* FIXME: make this work */
jardineb5d44e2003-12-23 08:09:43 +0000705/* Adjacency State (one octet):
706 0 = Up
707 1 = Initializing
708 2 = Down
709 Extended Local Circuit ID (four octets)
710 Neighbor System ID if known (zero to eight octets)
711 Neighbor Extended Local Circuit ID (four octets, if Neighbor
712 System ID is present) */
hassof390d2c2004-09-10 20:48:21 +0000713 pnt += length;
714 }
715 }
716 else
717 {
718 pnt += length;
719 }
jardineb5d44e2003-12-23 08:09:43 +0000720
hassof390d2c2004-09-10 20:48:21 +0000721 break;
722 case GRACEFUL_RESTART:
723 /* +-------+-------+-------+-------+-------+-------+-------+-------+
724 * | Reserved | SA | RA | RR | 1
725 * +-------+-------+-------+-------+-------+-------+-------+-------+
726 * | Remaining Time | 2
727 * +---------------------------------------------------------------+
728 * | Restarting Neighbor ID (If known) | 0-8
729 * +---------------------------------------------------------------+
730 */
731 *found |= TLVFLAG_GRACEFUL_RESTART;
732 if (*expected & TLVFLAG_GRACEFUL_RESTART)
733 {
734 /* FIXME: make this work */
735 }
736 pnt += length;
737 break;
jardineb5d44e2003-12-23 08:09:43 +0000738
hassof390d2c2004-09-10 20:48:21 +0000739 default:
740 zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
741 areatag, type, length);
jardineb5d44e2003-12-23 08:09:43 +0000742
hassof390d2c2004-09-10 20:48:21 +0000743 retval = ISIS_WARNING;
744 pnt += length;
745 break;
746 }
jardineb5d44e2003-12-23 08:09:43 +0000747 }
hassof390d2c2004-09-10 20:48:21 +0000748
jardineb5d44e2003-12-23 08:09:43 +0000749 return retval;
750}
751
752int
hassof390d2c2004-09-10 20:48:21 +0000753add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000754{
755
hassof390d2c2004-09-10 20:48:21 +0000756 if (STREAM_SIZE (stream) - stream_get_putp (stream) < len + 2)
757 {
758 zlog_warn ("No room for TLV of type %d", tag);
759 return ISIS_WARNING;
760 }
jardineb5d44e2003-12-23 08:09:43 +0000761
hassof390d2c2004-09-10 20:48:21 +0000762 stream_putc (stream, tag); /* TAG */
763 stream_putc (stream, len); /* LENGTH */
764 stream_put (stream, value, (int) len); /* VALUE */
jardineb5d44e2003-12-23 08:09:43 +0000765
766#ifdef EXTREME_DEBUG
767 zlog_info ("Added TLV %d len %d", tag, len);
768#endif /* EXTREME DEBUG */
769 return ISIS_OK;
770}
771
jardineb5d44e2003-12-23 08:09:43 +0000772int
hassof390d2c2004-09-10 20:48:21 +0000773tlv_add_area_addrs (struct list *area_addrs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000774{
775 struct listnode *node;
776 struct area_addr *area_addr;
777
hassof390d2c2004-09-10 20:48:21 +0000778 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000779 u_char *pos = value;
hassof390d2c2004-09-10 20:48:21 +0000780
781 for (node = listhead (area_addrs); node; nextnode (node))
782 {
783 area_addr = getdata (node);
784 if (pos - value + area_addr->addr_len > 255)
785 goto err;
786 *pos = area_addr->addr_len;
787 pos++;
788 memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len);
789 pos += area_addr->addr_len;
790 }
791
jardineb5d44e2003-12-23 08:09:43 +0000792 return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
793
hassof390d2c2004-09-10 20:48:21 +0000794err:
jardineb5d44e2003-12-23 08:09:43 +0000795 zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
796 return ISIS_WARNING;
797}
798
hassof390d2c2004-09-10 20:48:21 +0000799int
800tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000801{
802 struct listnode *node;
803 struct is_neigh *is_neigh;
hassof390d2c2004-09-10 20:48:21 +0000804 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000805 u_char *pos = value;
806 int retval;
807
hassof390d2c2004-09-10 20:48:21 +0000808 *pos = 0; /*is_neigh->virtual; */
809 pos++;
jardineb5d44e2003-12-23 08:09:43 +0000810
hassof390d2c2004-09-10 20:48:21 +0000811 for (node = listhead (is_neighs); node; nextnode (node))
812 {
813 is_neigh = getdata (node);
814 if (pos - value + IS_NEIGHBOURS_LEN > 255)
815 {
816 retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
817 if (retval != ISIS_OK)
818 return retval;
819 pos = value;
820 }
821 *pos = is_neigh->metrics.metric_default;
822 pos++;
823 *pos = is_neigh->metrics.metric_delay;
824 pos++;
825 *pos = is_neigh->metrics.metric_expense;
826 pos++;
827 *pos = is_neigh->metrics.metric_error;
828 pos++;
829 memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
830 pos += ISIS_SYS_ID_LEN + 1;
jardineb5d44e2003-12-23 08:09:43 +0000831 }
jardineb5d44e2003-12-23 08:09:43 +0000832
833 return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
834}
835
jardineb5d44e2003-12-23 08:09:43 +0000836int
837tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
838{
839 struct listnode *node;
840 u_char *snpa;
hassof390d2c2004-09-10 20:48:21 +0000841 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000842 u_char *pos = value;
843 int retval;
844
hassof390d2c2004-09-10 20:48:21 +0000845 for (node = listhead (lan_neighs); node; nextnode (node))
846 {
847 snpa = getdata (node);
848 if (pos - value + ETH_ALEN > 255)
849 {
850 retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
851 if (retval != ISIS_OK)
852 return retval;
853 pos = value;
854 }
855 memcpy (pos, snpa, ETH_ALEN);
856 pos += ETH_ALEN;
jardineb5d44e2003-12-23 08:09:43 +0000857 }
jardineb5d44e2003-12-23 08:09:43 +0000858
859 return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
860}
861
jardineb5d44e2003-12-23 08:09:43 +0000862/*
863 u_char value[255];
864 u_char *pos = value;
865
866 if (circuit->ip_router) {
867 *pos = (u_char)NLPID_IP;
868 pos ++;
869 }
870 if (circuit->ipv6_router) {
871 *pos = (u_char)NLPID_IPV6;
872 pos ++;
873 }
874*/
875
876int
877tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
878{
hassof390d2c2004-09-10 20:48:21 +0000879
880 return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream);
jardineb5d44e2003-12-23 08:09:43 +0000881}
882
hassof390d2c2004-09-10 20:48:21 +0000883int
hassof7c43dc2004-09-26 16:24:14 +0000884tlv_add_authinfo (char auth_type, char auth_len, u_char *auth_value,
hassof390d2c2004-09-10 20:48:21 +0000885 struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000886{
887 u_char value[255];
888 u_char *pos = value;
hasso53c997c2004-09-15 16:21:59 +0000889 *pos++ = ISIS_PASSWD_TYPE_CLEARTXT;
jardineb5d44e2003-12-23 08:09:43 +0000890 memcpy (pos, auth_value, auth_len);
891
892 return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
893}
894
895int
896tlv_add_checksum (struct checksum *checksum, struct stream *stream)
897{
898 u_char value[255];
hassof390d2c2004-09-10 20:48:21 +0000899 u_char *pos = value;
900 return add_tlv (CHECKSUM, pos - value, value, stream);
jardineb5d44e2003-12-23 08:09:43 +0000901}
902
903int
904tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
905{
906 struct listnode *node;
907 struct prefix_ipv4 *ipv4;
908 u_char value[255];
909 u_char *pos = value;
910 int retval;
911
hassof390d2c2004-09-10 20:48:21 +0000912 for (node = listhead (ip_addrs); node; nextnode (node))
913 {
914 ipv4 = getdata (node);
915 if (pos - value + IPV4_MAX_BYTELEN > 255)
916 {
917 retval = add_tlv (IPV4_ADDR, pos - value, value, stream);
918 if (retval != ISIS_OK)
919 return retval;
920 pos = value;
921 }
922 *(u_int32_t *) pos = ipv4->prefix.s_addr;
923 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000924 }
hassof390d2c2004-09-10 20:48:21 +0000925
jardineb5d44e2003-12-23 08:09:43 +0000926 return add_tlv (IPV4_ADDR, pos - value, value, stream);
927}
928
929int
930tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
931{
hassof390d2c2004-09-10 20:48:21 +0000932 return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
933 stream);
jardineb5d44e2003-12-23 08:09:43 +0000934}
935
hassof390d2c2004-09-10 20:48:21 +0000936int
jardineb5d44e2003-12-23 08:09:43 +0000937tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
938{
939 struct listnode *node;
940 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000941 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000942 u_char *pos = value;
943 int retval;
944
hassof390d2c2004-09-10 20:48:21 +0000945 for (node = listhead (lsps); node; nextnode (node))
946 {
947 lsp = getdata (node);
948 if (pos - value + LSP_ENTRIES_LEN > 255)
949 {
950 retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
951 if (retval != ISIS_OK)
952 return retval;
953 pos = value;
954 }
955 *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime;
956 pos += 2;
957 memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
958 pos += ISIS_SYS_ID_LEN + 2;
959 *((u_int32_t *) pos) = lsp->lsp_header->seq_num;
960 pos += 4;
961 *((u_int16_t *) pos) = lsp->lsp_header->checksum;
962 pos += 2;
jardineb5d44e2003-12-23 08:09:43 +0000963 }
hassof390d2c2004-09-10 20:48:21 +0000964
jardineb5d44e2003-12-23 08:09:43 +0000965 return add_tlv (LSP_ENTRIES, pos - value, value, stream);
966}
967
hassof390d2c2004-09-10 20:48:21 +0000968int
jardineb5d44e2003-12-23 08:09:43 +0000969tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
970{
971 struct listnode *node;
972 struct ipv4_reachability *reach;
hassof390d2c2004-09-10 20:48:21 +0000973 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000974 u_char *pos = value;
975 int retval;
976
hassof390d2c2004-09-10 20:48:21 +0000977 for (node = listhead (ipv4_reachs); node; nextnode (node))
978 {
979 reach = getdata (node);
980 if (pos - value + IPV4_REACH_LEN > 255)
981 {
982 retval =
983 add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
984 if (retval != ISIS_OK)
985 return retval;
986 pos = value;
987 }
988 *pos = reach->metrics.metric_default;
989 pos++;
990 *pos = reach->metrics.metric_delay;
991 pos++;
992 *pos = reach->metrics.metric_expense;
993 pos++;
994 *pos = reach->metrics.metric_error;
995 pos++;
996 *(u_int32_t *) pos = reach->prefix.s_addr;
997 pos += IPV4_MAX_BYTELEN;
998 *(u_int32_t *) pos = reach->mask.s_addr;
999 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +00001000 }
hassof390d2c2004-09-10 20:48:21 +00001001
1002
jardineb5d44e2003-12-23 08:09:43 +00001003 return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
1004}
1005
hassof390d2c2004-09-10 20:48:21 +00001006#ifdef HAVE_IPV6
jardineb5d44e2003-12-23 08:09:43 +00001007int
1008tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
1009{
1010 struct listnode *node;
1011 struct prefix_ipv6 *ipv6;
1012 u_char value[255];
1013 u_char *pos = value;
1014 int retval;
hassof390d2c2004-09-10 20:48:21 +00001015
1016 for (node = listhead (ipv6_addrs); node; nextnode (node))
1017 {
1018 ipv6 = getdata (node);
1019 if (pos - value + IPV6_MAX_BYTELEN > 255)
1020 {
1021 retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
1022 if (retval != ISIS_OK)
1023 return retval;
1024 pos = value;
1025 }
1026 memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
1027 pos += IPV6_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +00001028 }
hassof390d2c2004-09-10 20:48:21 +00001029
jardineb5d44e2003-12-23 08:09:43 +00001030 return add_tlv (IPV6_ADDR, pos - value, value, stream);
1031}
1032
1033int
1034tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
1035{
1036 struct listnode *node;
1037 struct ipv6_reachability *ip6reach;
1038 u_char value[255];
1039 u_char *pos = value;
1040 int retval, prefix_octets;
hassof390d2c2004-09-10 20:48:21 +00001041
1042 for (node = listhead (ipv6_reachs); node; nextnode (node))
1043 {
1044 ip6reach = getdata (node);
1045 if (pos - value + IPV6_MAX_BYTELEN + 6 > 255)
1046 {
1047 retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1048 if (retval != ISIS_OK)
1049 return retval;
1050 pos = value;
1051 }
1052 *(uint32_t *) pos = ip6reach->metric;
1053 pos += 4;
1054 *pos = ip6reach->control_info;
1055 pos++;
1056 prefix_octets = ((ip6reach->prefix_len + 7) / 8);
1057 *pos = ip6reach->prefix_len;
1058 pos++;
1059 memcpy (pos, ip6reach->prefix, prefix_octets);
1060 pos += prefix_octets;
jardineb5d44e2003-12-23 08:09:43 +00001061 }
hassof390d2c2004-09-10 20:48:21 +00001062
jardineb5d44e2003-12-23 08:09:43 +00001063 return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1064}
1065#endif /* HAVE_IPV6 */
1066
1067int
1068tlv_add_padding (struct stream *stream)
1069{
1070 unsigned long putp, endp;
hassof390d2c2004-09-10 20:48:21 +00001071 int fullpads, i, left;
1072
jardineb5d44e2003-12-23 08:09:43 +00001073 /*
1074 * How many times can we add full padding ?
1075 */
hassof390d2c2004-09-10 20:48:21 +00001076 fullpads = (STREAM_SIZE (stream) - stream_get_endp (stream)) / 257;
1077 for (i = 0; i < fullpads; i++)
1078 {
1079 if (!stream_putc (stream, (u_char) PADDING)) /* TAG */
1080 goto err;
1081 if (!stream_putc (stream, (u_char) 255)) /* LENGHT */
1082 goto err;
1083 endp = stream_get_endp (stream);
1084 putp = stream_get_putp (stream);
1085 if (putp != endp)
1086 zlog_warn ("tvl_add_padding endp %ld while putp %ld", endp, putp);
1087 stream_set_putp (stream, putp + 255); /* VALUE */
1088 stream->endp = stream->putp;
1089 }
1090
1091 left = STREAM_SIZE (stream) - stream_get_putp (stream);
1092
jardineb5d44e2003-12-23 08:09:43 +00001093 if (left < 2)
1094 return ISIS_OK;
hassof390d2c2004-09-10 20:48:21 +00001095
1096 if (left == 2)
1097 {
1098 stream_putc (stream, PADDING);
1099 stream_putc (stream, 0);
1100 return ISIS_OK;
1101 }
1102
jardineb5d44e2003-12-23 08:09:43 +00001103 stream_putc (stream, PADDING);
1104 stream_putc (stream, left - 2);
1105 stream_set_putp (stream, stream_get_putp (stream) + left - 2);
1106 stream->endp = stream->putp;
1107
1108 return ISIS_OK;
1109
hassof390d2c2004-09-10 20:48:21 +00001110err:
jardineb5d44e2003-12-23 08:09:43 +00001111 zlog_warn ("tlv_add_padding(): no room for tlv");
1112 return ISIS_WARNING;
1113}