blob: f167a9fadafef3c0d5fdd29608d8925452b27f03 [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)
hasso1cd80842004-10-07 20:07:40 +0000501 tlvs->router_id = (struct te_router_id *) (pnt);
hassof390d2c2004-09-10 20:48:21 +0000502 pnt += length;
503 break;
jardineb5d44e2003-12-23 08:09:43 +0000504
hassof390d2c2004-09-10 20:48:21 +0000505 case IPV4_INT_REACHABILITY:
506 /* +-------+-------+-------+-------+-------+-------+-------+-------+
507 * | 0 | I/E | Default Metric | 1
508 * +-------+-------+-------+-------+-------+-------+-------+-------+
509 * | S | I/E | Delay Metric | 1
510 * +-------+-------+-------+-------+-------+-------+-------+-------+
511 * | S | I/E | Expense Metric | 1
512 * +-------+-------+-------+-------+-------+-------+-------+-------+
513 * | S | I/E | Error Metric | 1
514 * +-------+-------+-------+-------+-------+-------+-------+-------+
515 * | ip address | 4
516 * +---------------------------------------------------------------+
517 * | address mask | 4
518 * +---------------------------------------------------------------+
519 * : :
520 */
521 *found |= TLVFLAG_IPV4_INT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000522#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000523 zlog_info ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
524 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000525#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000526 if (*expected & TLVFLAG_IPV4_INT_REACHABILITY)
527 {
528 while (length > value_len)
529 {
530 ipv4_reach = (struct ipv4_reachability *) pnt;
531 if (!tlvs->ipv4_int_reachs)
532 tlvs->ipv4_int_reachs = list_new ();
533 listnode_add (tlvs->ipv4_int_reachs, ipv4_reach);
534 value_len += 12;
535 pnt += 12;
536 }
537 }
538 else
539 {
540 pnt += length;
541 }
542 break;
jardineb5d44e2003-12-23 08:09:43 +0000543
hassof390d2c2004-09-10 20:48:21 +0000544 case IPV4_EXT_REACHABILITY:
545 /* +-------+-------+-------+-------+-------+-------+-------+-------+
546 * | 0 | I/E | Default Metric | 1
547 * +-------+-------+-------+-------+-------+-------+-------+-------+
548 * | S | I/E | Delay Metric | 1
549 * +-------+-------+-------+-------+-------+-------+-------+-------+
550 * | S | I/E | Expense Metric | 1
551 * +-------+-------+-------+-------+-------+-------+-------+-------+
552 * | S | I/E | Error Metric | 1
553 * +-------+-------+-------+-------+-------+-------+-------+-------+
554 * | ip address | 4
555 * +---------------------------------------------------------------+
556 * | address mask | 4
557 * +---------------------------------------------------------------+
558 * : :
559 */
560 *found |= TLVFLAG_IPV4_EXT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000561#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000562 zlog_info ("ISIS-TLV (%s): IPv4 external Reachability length %d",
563 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000564#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000565 if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY)
566 {
567 while (length > value_len)
568 {
569 ipv4_reach = (struct ipv4_reachability *) pnt;
570 if (!tlvs->ipv4_ext_reachs)
571 tlvs->ipv4_ext_reachs = list_new ();
572 listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach);
573 value_len += 12;
574 pnt += 12;
575 }
576 }
577 else
578 {
579 pnt += length;
580 }
581 break;
jardineb5d44e2003-12-23 08:09:43 +0000582
hassof390d2c2004-09-10 20:48:21 +0000583 case TE_IPV4_REACHABILITY:
584 /* +-------+-------+-------+-------+-------+-------+-------+-------+
585 * | TE Metric | 4
586 * +-------+-------+-------+-------+-------+-------+-------+-------+
587 * | U/D | sTLV? | Prefix Mask Len | 1
588 * +-------+-------+-------+-------+-------+-------+-------+-------+
589 * | Prefix | 0-4
590 * +---------------------------------------------------------------+
591 * | sub tlvs |
592 * +---------------------------------------------------------------+
593 * : :
594 */
595 *found |= TLVFLAG_TE_IPV4_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000596#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000597 zlog_info ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
598 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000599#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000600 if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
601 {
602 while (length > value_len)
603 {
604 te_ipv4_reach = (struct te_ipv4_reachability *) pnt;
605 if (!tlvs->te_ipv4_reachs)
606 tlvs->te_ipv4_reachs = list_new ();
607 listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach);
608 /* this trickery is permitable since no subtlvs are defined */
609 value_len += 5 + ((te_ipv4_reach->control & 0x3F) ?
610 ((((te_ipv4_reach->control & 0x3F) -
611 1) >> 3) + 1) : 0);
612 pnt += 5 + ((te_ipv4_reach->control & 0x3F) ?
613 ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0);
614 }
615 }
616 else
617 {
618 pnt += length;
619 }
620 break;
jardineb5d44e2003-12-23 08:09:43 +0000621
622#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000623 case IPV6_ADDR:
624 /* +-------+-------+-------+-------+-------+-------+-------+-------+
625 * + IP version 6 address + 16
626 * +-------+-------+-------+-------+-------+-------+-------+-------+
627 * : :
628 */
629 *found |= TLVFLAG_IPV6_ADDR;
jardineb5d44e2003-12-23 08:09:43 +0000630#ifdef EXTREME_TLV_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000631 zlog_info ("ISIS-TLV (%s): IPv6 Address length %d",
632 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000633#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000634 if (*expected & TLVFLAG_IPV6_ADDR)
635 {
636 while (length > value_len)
637 {
638 ipv6_addr = (struct in6_addr *) pnt;
639 if (!tlvs->ipv6_addrs)
640 tlvs->ipv6_addrs = list_new ();
641 listnode_add (tlvs->ipv6_addrs, ipv6_addr);
642 value_len += 16;
643 pnt += 16;
644 }
645 }
646 else
647 {
648 pnt += length;
649 }
650 break;
jardineb5d44e2003-12-23 08:09:43 +0000651
hassof390d2c2004-09-10 20:48:21 +0000652 case IPV6_REACHABILITY:
653 /* +-------+-------+-------+-------+-------+-------+-------+-------+
654 * | Default Metric | 4
655 * +-------+-------+-------+-------+-------+-------+-------+-------+
656 * | Control Informantion |
657 * +---------------------------------------------------------------+
658 * | IPv6 Prefix Length |--+
659 * +---------------------------------------------------------------+ |
660 * | IPv6 Prefix |<-+
661 * +---------------------------------------------------------------+
662 */
663 *found |= TLVFLAG_IPV6_REACHABILITY;
664 if (*expected & TLVFLAG_IPV6_REACHABILITY)
665 {
666 while (length > value_len)
667 {
668 ipv6_reach = (struct ipv6_reachability *) pnt;
669 prefix_octets = ((ipv6_reach->prefix_len + 7) / 8);
670 value_len += prefix_octets + 6;
671 pnt += prefix_octets + 6;
672 /* FIXME: sub-tlvs */
673 if (!tlvs->ipv6_reachs)
674 tlvs->ipv6_reachs = list_new ();
675 listnode_add (tlvs->ipv6_reachs, ipv6_reach);
676 }
677 }
678 else
679 {
680 pnt += length;
681 }
682 break;
jardineb5d44e2003-12-23 08:09:43 +0000683#endif /* HAVE_IPV6 */
684
hassof390d2c2004-09-10 20:48:21 +0000685 case WAY3_HELLO:
686 /* +---------------------------------------------------------------+
687 * | Adjacency state | 1
688 * +---------------------------------------------------------------+
689 * | Extended Local Circuit ID | 4
690 * +---------------------------------------------------------------+
691 * | Neighbor System ID (If known) | 0-8
692 * (probably 6)
693 * +---------------------------------------------------------------+
694 * | Neighbor Local Circuit ID (If known) | 4
695 * +---------------------------------------------------------------+
696 */
697 *found |= TLVFLAG_3WAY_HELLO;
698 if (*expected & TLVFLAG_3WAY_HELLO)
699 {
700 while (length > value_len)
701 {
702 /* FIXME: make this work */
jardineb5d44e2003-12-23 08:09:43 +0000703/* Adjacency State (one octet):
704 0 = Up
705 1 = Initializing
706 2 = Down
707 Extended Local Circuit ID (four octets)
708 Neighbor System ID if known (zero to eight octets)
709 Neighbor Extended Local Circuit ID (four octets, if Neighbor
710 System ID is present) */
hassof390d2c2004-09-10 20:48:21 +0000711 pnt += length;
712 }
713 }
714 else
715 {
716 pnt += length;
717 }
jardineb5d44e2003-12-23 08:09:43 +0000718
hassof390d2c2004-09-10 20:48:21 +0000719 break;
720 case GRACEFUL_RESTART:
721 /* +-------+-------+-------+-------+-------+-------+-------+-------+
722 * | Reserved | SA | RA | RR | 1
723 * +-------+-------+-------+-------+-------+-------+-------+-------+
724 * | Remaining Time | 2
725 * +---------------------------------------------------------------+
726 * | Restarting Neighbor ID (If known) | 0-8
727 * +---------------------------------------------------------------+
728 */
729 *found |= TLVFLAG_GRACEFUL_RESTART;
730 if (*expected & TLVFLAG_GRACEFUL_RESTART)
731 {
732 /* FIXME: make this work */
733 }
734 pnt += length;
735 break;
jardineb5d44e2003-12-23 08:09:43 +0000736
hassof390d2c2004-09-10 20:48:21 +0000737 default:
738 zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
739 areatag, type, length);
jardineb5d44e2003-12-23 08:09:43 +0000740
hassof390d2c2004-09-10 20:48:21 +0000741 retval = ISIS_WARNING;
742 pnt += length;
743 break;
744 }
jardineb5d44e2003-12-23 08:09:43 +0000745 }
hassof390d2c2004-09-10 20:48:21 +0000746
jardineb5d44e2003-12-23 08:09:43 +0000747 return retval;
748}
749
750int
hassof390d2c2004-09-10 20:48:21 +0000751add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000752{
753
hasso1cd80842004-10-07 20:07:40 +0000754 if (STREAM_SIZE (stream) - stream_get_putp (stream) < (unsigned) len + 2)
hassof390d2c2004-09-10 20:48:21 +0000755 {
756 zlog_warn ("No room for TLV of type %d", tag);
757 return ISIS_WARNING;
758 }
jardineb5d44e2003-12-23 08:09:43 +0000759
hassof390d2c2004-09-10 20:48:21 +0000760 stream_putc (stream, tag); /* TAG */
761 stream_putc (stream, len); /* LENGTH */
762 stream_put (stream, value, (int) len); /* VALUE */
jardineb5d44e2003-12-23 08:09:43 +0000763
764#ifdef EXTREME_DEBUG
765 zlog_info ("Added TLV %d len %d", tag, len);
766#endif /* EXTREME DEBUG */
767 return ISIS_OK;
768}
769
jardineb5d44e2003-12-23 08:09:43 +0000770int
hassof390d2c2004-09-10 20:48:21 +0000771tlv_add_area_addrs (struct list *area_addrs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000772{
773 struct listnode *node;
774 struct area_addr *area_addr;
775
hassof390d2c2004-09-10 20:48:21 +0000776 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000777 u_char *pos = value;
hassof390d2c2004-09-10 20:48:21 +0000778
779 for (node = listhead (area_addrs); node; nextnode (node))
780 {
781 area_addr = getdata (node);
782 if (pos - value + area_addr->addr_len > 255)
783 goto err;
784 *pos = area_addr->addr_len;
785 pos++;
786 memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len);
787 pos += area_addr->addr_len;
788 }
789
jardineb5d44e2003-12-23 08:09:43 +0000790 return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
791
hassof390d2c2004-09-10 20:48:21 +0000792err:
jardineb5d44e2003-12-23 08:09:43 +0000793 zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
794 return ISIS_WARNING;
795}
796
hassof390d2c2004-09-10 20:48:21 +0000797int
798tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000799{
800 struct listnode *node;
801 struct is_neigh *is_neigh;
hassof390d2c2004-09-10 20:48:21 +0000802 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000803 u_char *pos = value;
804 int retval;
805
hassof390d2c2004-09-10 20:48:21 +0000806 *pos = 0; /*is_neigh->virtual; */
807 pos++;
jardineb5d44e2003-12-23 08:09:43 +0000808
hassof390d2c2004-09-10 20:48:21 +0000809 for (node = listhead (is_neighs); node; nextnode (node))
810 {
811 is_neigh = getdata (node);
812 if (pos - value + IS_NEIGHBOURS_LEN > 255)
813 {
814 retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
815 if (retval != ISIS_OK)
816 return retval;
817 pos = value;
818 }
819 *pos = is_neigh->metrics.metric_default;
820 pos++;
821 *pos = is_neigh->metrics.metric_delay;
822 pos++;
823 *pos = is_neigh->metrics.metric_expense;
824 pos++;
825 *pos = is_neigh->metrics.metric_error;
826 pos++;
827 memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
828 pos += ISIS_SYS_ID_LEN + 1;
jardineb5d44e2003-12-23 08:09:43 +0000829 }
jardineb5d44e2003-12-23 08:09:43 +0000830
831 return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
832}
833
jardineb5d44e2003-12-23 08:09:43 +0000834int
835tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
836{
837 struct listnode *node;
838 u_char *snpa;
hassof390d2c2004-09-10 20:48:21 +0000839 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000840 u_char *pos = value;
841 int retval;
842
hassof390d2c2004-09-10 20:48:21 +0000843 for (node = listhead (lan_neighs); node; nextnode (node))
844 {
845 snpa = getdata (node);
846 if (pos - value + ETH_ALEN > 255)
847 {
848 retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
849 if (retval != ISIS_OK)
850 return retval;
851 pos = value;
852 }
853 memcpy (pos, snpa, ETH_ALEN);
854 pos += ETH_ALEN;
jardineb5d44e2003-12-23 08:09:43 +0000855 }
jardineb5d44e2003-12-23 08:09:43 +0000856
857 return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
858}
859
jardineb5d44e2003-12-23 08:09:43 +0000860/*
861 u_char value[255];
862 u_char *pos = value;
863
864 if (circuit->ip_router) {
865 *pos = (u_char)NLPID_IP;
866 pos ++;
867 }
868 if (circuit->ipv6_router) {
869 *pos = (u_char)NLPID_IPV6;
870 pos ++;
871 }
872*/
873
874int
875tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
876{
hassof390d2c2004-09-10 20:48:21 +0000877
878 return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream);
jardineb5d44e2003-12-23 08:09:43 +0000879}
880
hassof390d2c2004-09-10 20:48:21 +0000881int
hassof7c43dc2004-09-26 16:24:14 +0000882tlv_add_authinfo (char auth_type, char auth_len, u_char *auth_value,
hassof390d2c2004-09-10 20:48:21 +0000883 struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000884{
885 u_char value[255];
886 u_char *pos = value;
hasso53c997c2004-09-15 16:21:59 +0000887 *pos++ = ISIS_PASSWD_TYPE_CLEARTXT;
jardineb5d44e2003-12-23 08:09:43 +0000888 memcpy (pos, auth_value, auth_len);
889
890 return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
891}
892
893int
894tlv_add_checksum (struct checksum *checksum, struct stream *stream)
895{
896 u_char value[255];
hassof390d2c2004-09-10 20:48:21 +0000897 u_char *pos = value;
898 return add_tlv (CHECKSUM, pos - value, value, stream);
jardineb5d44e2003-12-23 08:09:43 +0000899}
900
901int
902tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
903{
904 struct listnode *node;
905 struct prefix_ipv4 *ipv4;
906 u_char value[255];
907 u_char *pos = value;
908 int retval;
909
hassof390d2c2004-09-10 20:48:21 +0000910 for (node = listhead (ip_addrs); node; nextnode (node))
911 {
912 ipv4 = getdata (node);
913 if (pos - value + IPV4_MAX_BYTELEN > 255)
914 {
915 retval = add_tlv (IPV4_ADDR, pos - value, value, stream);
916 if (retval != ISIS_OK)
917 return retval;
918 pos = value;
919 }
920 *(u_int32_t *) pos = ipv4->prefix.s_addr;
921 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000922 }
hassof390d2c2004-09-10 20:48:21 +0000923
jardineb5d44e2003-12-23 08:09:43 +0000924 return add_tlv (IPV4_ADDR, pos - value, value, stream);
925}
926
927int
928tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
929{
hassof390d2c2004-09-10 20:48:21 +0000930 return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
931 stream);
jardineb5d44e2003-12-23 08:09:43 +0000932}
933
hassof390d2c2004-09-10 20:48:21 +0000934int
jardineb5d44e2003-12-23 08:09:43 +0000935tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
936{
937 struct listnode *node;
938 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000939 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000940 u_char *pos = value;
941 int retval;
942
hassof390d2c2004-09-10 20:48:21 +0000943 for (node = listhead (lsps); node; nextnode (node))
944 {
945 lsp = getdata (node);
946 if (pos - value + LSP_ENTRIES_LEN > 255)
947 {
948 retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
949 if (retval != ISIS_OK)
950 return retval;
951 pos = value;
952 }
953 *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime;
954 pos += 2;
955 memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
956 pos += ISIS_SYS_ID_LEN + 2;
957 *((u_int32_t *) pos) = lsp->lsp_header->seq_num;
958 pos += 4;
959 *((u_int16_t *) pos) = lsp->lsp_header->checksum;
960 pos += 2;
jardineb5d44e2003-12-23 08:09:43 +0000961 }
hassof390d2c2004-09-10 20:48:21 +0000962
jardineb5d44e2003-12-23 08:09:43 +0000963 return add_tlv (LSP_ENTRIES, pos - value, value, stream);
964}
965
hassof390d2c2004-09-10 20:48:21 +0000966int
jardineb5d44e2003-12-23 08:09:43 +0000967tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
968{
969 struct listnode *node;
970 struct ipv4_reachability *reach;
hassof390d2c2004-09-10 20:48:21 +0000971 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000972 u_char *pos = value;
973 int retval;
974
hassof390d2c2004-09-10 20:48:21 +0000975 for (node = listhead (ipv4_reachs); node; nextnode (node))
976 {
977 reach = getdata (node);
978 if (pos - value + IPV4_REACH_LEN > 255)
979 {
980 retval =
981 add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
982 if (retval != ISIS_OK)
983 return retval;
984 pos = value;
985 }
986 *pos = reach->metrics.metric_default;
987 pos++;
988 *pos = reach->metrics.metric_delay;
989 pos++;
990 *pos = reach->metrics.metric_expense;
991 pos++;
992 *pos = reach->metrics.metric_error;
993 pos++;
994 *(u_int32_t *) pos = reach->prefix.s_addr;
995 pos += IPV4_MAX_BYTELEN;
996 *(u_int32_t *) pos = reach->mask.s_addr;
997 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000998 }
hassof390d2c2004-09-10 20:48:21 +0000999
1000
jardineb5d44e2003-12-23 08:09:43 +00001001 return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
1002}
1003
hassof390d2c2004-09-10 20:48:21 +00001004#ifdef HAVE_IPV6
jardineb5d44e2003-12-23 08:09:43 +00001005int
1006tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
1007{
1008 struct listnode *node;
1009 struct prefix_ipv6 *ipv6;
1010 u_char value[255];
1011 u_char *pos = value;
1012 int retval;
hassof390d2c2004-09-10 20:48:21 +00001013
1014 for (node = listhead (ipv6_addrs); node; nextnode (node))
1015 {
1016 ipv6 = getdata (node);
1017 if (pos - value + IPV6_MAX_BYTELEN > 255)
1018 {
1019 retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
1020 if (retval != ISIS_OK)
1021 return retval;
1022 pos = value;
1023 }
1024 memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
1025 pos += IPV6_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +00001026 }
hassof390d2c2004-09-10 20:48:21 +00001027
jardineb5d44e2003-12-23 08:09:43 +00001028 return add_tlv (IPV6_ADDR, pos - value, value, stream);
1029}
1030
1031int
1032tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
1033{
1034 struct listnode *node;
1035 struct ipv6_reachability *ip6reach;
1036 u_char value[255];
1037 u_char *pos = value;
1038 int retval, prefix_octets;
hassof390d2c2004-09-10 20:48:21 +00001039
1040 for (node = listhead (ipv6_reachs); node; nextnode (node))
1041 {
1042 ip6reach = getdata (node);
1043 if (pos - value + IPV6_MAX_BYTELEN + 6 > 255)
1044 {
1045 retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1046 if (retval != ISIS_OK)
1047 return retval;
1048 pos = value;
1049 }
1050 *(uint32_t *) pos = ip6reach->metric;
1051 pos += 4;
1052 *pos = ip6reach->control_info;
1053 pos++;
1054 prefix_octets = ((ip6reach->prefix_len + 7) / 8);
1055 *pos = ip6reach->prefix_len;
1056 pos++;
1057 memcpy (pos, ip6reach->prefix, prefix_octets);
1058 pos += prefix_octets;
jardineb5d44e2003-12-23 08:09:43 +00001059 }
hassof390d2c2004-09-10 20:48:21 +00001060
jardineb5d44e2003-12-23 08:09:43 +00001061 return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1062}
1063#endif /* HAVE_IPV6 */
1064
1065int
1066tlv_add_padding (struct stream *stream)
1067{
1068 unsigned long putp, endp;
hassof390d2c2004-09-10 20:48:21 +00001069 int fullpads, i, left;
1070
jardineb5d44e2003-12-23 08:09:43 +00001071 /*
1072 * How many times can we add full padding ?
1073 */
hassof390d2c2004-09-10 20:48:21 +00001074 fullpads = (STREAM_SIZE (stream) - stream_get_endp (stream)) / 257;
1075 for (i = 0; i < fullpads; i++)
1076 {
1077 if (!stream_putc (stream, (u_char) PADDING)) /* TAG */
1078 goto err;
1079 if (!stream_putc (stream, (u_char) 255)) /* LENGHT */
1080 goto err;
1081 endp = stream_get_endp (stream);
1082 putp = stream_get_putp (stream);
1083 if (putp != endp)
1084 zlog_warn ("tvl_add_padding endp %ld while putp %ld", endp, putp);
1085 stream_set_putp (stream, putp + 255); /* VALUE */
1086 stream->endp = stream->putp;
1087 }
1088
1089 left = STREAM_SIZE (stream) - stream_get_putp (stream);
1090
jardineb5d44e2003-12-23 08:09:43 +00001091 if (left < 2)
1092 return ISIS_OK;
hassof390d2c2004-09-10 20:48:21 +00001093
1094 if (left == 2)
1095 {
1096 stream_putc (stream, PADDING);
1097 stream_putc (stream, 0);
1098 return ISIS_OK;
1099 }
1100
jardineb5d44e2003-12-23 08:09:43 +00001101 stream_putc (stream, PADDING);
1102 stream_putc (stream, left - 2);
1103 stream_set_putp (stream, stream_get_putp (stream) + left - 2);
1104 stream->endp = stream->putp;
1105
1106 return ISIS_OK;
1107
hassof390d2c2004-09-10 20:48:21 +00001108err:
jardineb5d44e2003-12-23 08:09:43 +00001109 zlog_warn ("tlv_add_padding(): no room for tlv");
1110 return ISIS_WARNING;
1111}