blob: 1194f046776c6e72961a09e62260ed2be90849cc [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
hasso529d65b2004-12-24 00:14:50 +0000175 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000198 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000251 zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d",
hassof390d2c2004-09-10 20:48:21 +0000252 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
hasso529d65b2004-12-24 00:14:50 +0000293 zlog_debug ("ISIS-TLV (%s): ES Neighbours length %d",
hassof390d2c2004-09-10 20:48:21 +0000294 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
hasso529d65b2004-12-24 00:14:50 +0000328 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000351 zlog_debug ("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
hasso92365882005-01-18 13:53:33 +0000368 zlog_debug ("ISIS-TLV (%s): 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
hasso529d65b2004-12-24 00:14:50 +0000397 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000414 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000432 zlog_debug ("ISIS-TLV (%s): IPv4 Address length %d",
433 areatag, length);
hassof390d2c2004-09-10 20:48:21 +0000434#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
hasso529d65b2004-12-24 00:14:50 +0000441 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000460 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000480 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000498 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000523 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000562 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000597 zlog_debug ("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
hasso529d65b2004-12-24 00:14:50 +0000631 zlog_debug ("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
paul9985f832005-02-09 15:51:56 +0000754 if (STREAM_SIZE (stream) - stream_get_endp (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
hasso529d65b2004-12-24 00:14:50 +0000765 zlog_debug ("Added TLV %d len %d", tag, len);
jardineb5d44e2003-12-23 08:09:43 +0000766#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
paul1eb8ef22005-04-07 07:30:20 +0000779 for (ALL_LIST_ELEMENTS_RO (area_addrs, node, area_addr))
hassof390d2c2004-09-10 20:48:21 +0000780 {
hassof390d2c2004-09-10 20:48:21 +0000781 if (pos - value + area_addr->addr_len > 255)
782 goto err;
783 *pos = area_addr->addr_len;
784 pos++;
785 memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len);
786 pos += area_addr->addr_len;
787 }
788
jardineb5d44e2003-12-23 08:09:43 +0000789 return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
790
hassof390d2c2004-09-10 20:48:21 +0000791err:
jardineb5d44e2003-12-23 08:09:43 +0000792 zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
793 return ISIS_WARNING;
794}
795
hassof390d2c2004-09-10 20:48:21 +0000796int
797tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000798{
paul1eb8ef22005-04-07 07:30:20 +0000799 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000800 struct is_neigh *is_neigh;
hassof390d2c2004-09-10 20:48:21 +0000801 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000802 u_char *pos = value;
803 int retval;
804
hassof390d2c2004-09-10 20:48:21 +0000805 *pos = 0; /*is_neigh->virtual; */
806 pos++;
jardineb5d44e2003-12-23 08:09:43 +0000807
paul1eb8ef22005-04-07 07:30:20 +0000808 for (ALL_LIST_ELEMENTS (is_neighs, node, nnode, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000809 {
hassof390d2c2004-09-10 20:48:21 +0000810 if (pos - value + IS_NEIGHBOURS_LEN > 255)
811 {
812 retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
813 if (retval != ISIS_OK)
814 return retval;
815 pos = value;
816 }
817 *pos = is_neigh->metrics.metric_default;
818 pos++;
819 *pos = is_neigh->metrics.metric_delay;
820 pos++;
821 *pos = is_neigh->metrics.metric_expense;
822 pos++;
823 *pos = is_neigh->metrics.metric_error;
824 pos++;
825 memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
826 pos += ISIS_SYS_ID_LEN + 1;
jardineb5d44e2003-12-23 08:09:43 +0000827 }
jardineb5d44e2003-12-23 08:09:43 +0000828
829 return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
830}
831
jardineb5d44e2003-12-23 08:09:43 +0000832int
833tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
834{
paul1eb8ef22005-04-07 07:30:20 +0000835 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000836 u_char *snpa;
hassof390d2c2004-09-10 20:48:21 +0000837 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000838 u_char *pos = value;
839 int retval;
840
paul1eb8ef22005-04-07 07:30:20 +0000841 for (ALL_LIST_ELEMENTS (lan_neighs, node, nnode, snpa))
hassof390d2c2004-09-10 20:48:21 +0000842 {
hassof390d2c2004-09-10 20:48:21 +0000843 if (pos - value + ETH_ALEN > 255)
844 {
845 retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
846 if (retval != ISIS_OK)
847 return retval;
848 pos = value;
849 }
850 memcpy (pos, snpa, ETH_ALEN);
851 pos += ETH_ALEN;
jardineb5d44e2003-12-23 08:09:43 +0000852 }
jardineb5d44e2003-12-23 08:09:43 +0000853
854 return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
855}
856
jardineb5d44e2003-12-23 08:09:43 +0000857/*
858 u_char value[255];
859 u_char *pos = value;
860
861 if (circuit->ip_router) {
862 *pos = (u_char)NLPID_IP;
863 pos ++;
864 }
865 if (circuit->ipv6_router) {
866 *pos = (u_char)NLPID_IPV6;
867 pos ++;
868 }
869*/
870
871int
872tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
873{
hassof390d2c2004-09-10 20:48:21 +0000874
875 return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream);
jardineb5d44e2003-12-23 08:09:43 +0000876}
877
hassof390d2c2004-09-10 20:48:21 +0000878int
hassof7c43dc2004-09-26 16:24:14 +0000879tlv_add_authinfo (char auth_type, char auth_len, u_char *auth_value,
hassof390d2c2004-09-10 20:48:21 +0000880 struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000881{
882 u_char value[255];
883 u_char *pos = value;
hasso53c997c2004-09-15 16:21:59 +0000884 *pos++ = ISIS_PASSWD_TYPE_CLEARTXT;
jardineb5d44e2003-12-23 08:09:43 +0000885 memcpy (pos, auth_value, auth_len);
886
887 return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
888}
889
890int
891tlv_add_checksum (struct checksum *checksum, struct stream *stream)
892{
893 u_char value[255];
hassof390d2c2004-09-10 20:48:21 +0000894 u_char *pos = value;
895 return add_tlv (CHECKSUM, pos - value, value, stream);
jardineb5d44e2003-12-23 08:09:43 +0000896}
897
898int
899tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
900{
paul1eb8ef22005-04-07 07:30:20 +0000901 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000902 struct prefix_ipv4 *ipv4;
903 u_char value[255];
904 u_char *pos = value;
905 int retval;
906
paul1eb8ef22005-04-07 07:30:20 +0000907 for (ALL_LIST_ELEMENTS (ip_addrs, node, nnode, ipv4))
hassof390d2c2004-09-10 20:48:21 +0000908 {
hassof390d2c2004-09-10 20:48:21 +0000909 if (pos - value + IPV4_MAX_BYTELEN > 255)
910 {
911 retval = add_tlv (IPV4_ADDR, pos - value, value, stream);
912 if (retval != ISIS_OK)
913 return retval;
914 pos = value;
915 }
916 *(u_int32_t *) pos = ipv4->prefix.s_addr;
917 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000918 }
hassof390d2c2004-09-10 20:48:21 +0000919
jardineb5d44e2003-12-23 08:09:43 +0000920 return add_tlv (IPV4_ADDR, pos - value, value, stream);
921}
922
923int
924tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
925{
hassof390d2c2004-09-10 20:48:21 +0000926 return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
927 stream);
jardineb5d44e2003-12-23 08:09:43 +0000928}
929
hassof390d2c2004-09-10 20:48:21 +0000930int
jardineb5d44e2003-12-23 08:09:43 +0000931tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
932{
paul1eb8ef22005-04-07 07:30:20 +0000933 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000934 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000935 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000936 u_char *pos = value;
937 int retval;
938
paul1eb8ef22005-04-07 07:30:20 +0000939 for (ALL_LIST_ELEMENTS (lsps, node, nnode, lsp))
hassof390d2c2004-09-10 20:48:21 +0000940 {
hassof390d2c2004-09-10 20:48:21 +0000941 if (pos - value + LSP_ENTRIES_LEN > 255)
942 {
943 retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
944 if (retval != ISIS_OK)
945 return retval;
946 pos = value;
947 }
948 *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime;
949 pos += 2;
950 memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
951 pos += ISIS_SYS_ID_LEN + 2;
952 *((u_int32_t *) pos) = lsp->lsp_header->seq_num;
953 pos += 4;
954 *((u_int16_t *) pos) = lsp->lsp_header->checksum;
955 pos += 2;
jardineb5d44e2003-12-23 08:09:43 +0000956 }
hassof390d2c2004-09-10 20:48:21 +0000957
jardineb5d44e2003-12-23 08:09:43 +0000958 return add_tlv (LSP_ENTRIES, pos - value, value, stream);
959}
960
hassof390d2c2004-09-10 20:48:21 +0000961int
jardineb5d44e2003-12-23 08:09:43 +0000962tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
963{
paul1eb8ef22005-04-07 07:30:20 +0000964 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000965 struct ipv4_reachability *reach;
hassof390d2c2004-09-10 20:48:21 +0000966 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000967 u_char *pos = value;
968 int retval;
969
paul1eb8ef22005-04-07 07:30:20 +0000970 for (ALL_LIST_ELEMENTS (ipv4_reachs, node, nnode, reach))
hassof390d2c2004-09-10 20:48:21 +0000971 {
hassof390d2c2004-09-10 20:48:21 +0000972 if (pos - value + IPV4_REACH_LEN > 255)
973 {
974 retval =
975 add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
976 if (retval != ISIS_OK)
977 return retval;
978 pos = value;
979 }
980 *pos = reach->metrics.metric_default;
981 pos++;
982 *pos = reach->metrics.metric_delay;
983 pos++;
984 *pos = reach->metrics.metric_expense;
985 pos++;
986 *pos = reach->metrics.metric_error;
987 pos++;
988 *(u_int32_t *) pos = reach->prefix.s_addr;
989 pos += IPV4_MAX_BYTELEN;
990 *(u_int32_t *) pos = reach->mask.s_addr;
991 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000992 }
hassof390d2c2004-09-10 20:48:21 +0000993
994
jardineb5d44e2003-12-23 08:09:43 +0000995 return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
996}
997
hassof390d2c2004-09-10 20:48:21 +0000998#ifdef HAVE_IPV6
jardineb5d44e2003-12-23 08:09:43 +0000999int
1000tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
1001{
paul1eb8ef22005-04-07 07:30:20 +00001002 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +00001003 struct prefix_ipv6 *ipv6;
1004 u_char value[255];
1005 u_char *pos = value;
1006 int retval;
hassof390d2c2004-09-10 20:48:21 +00001007
paul1eb8ef22005-04-07 07:30:20 +00001008 for (ALL_LIST_ELEMENTS (ipv6_addrs, node, nnode, ipv6))
hassof390d2c2004-09-10 20:48:21 +00001009 {
hassof390d2c2004-09-10 20:48:21 +00001010 if (pos - value + IPV6_MAX_BYTELEN > 255)
1011 {
1012 retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
1013 if (retval != ISIS_OK)
1014 return retval;
1015 pos = value;
1016 }
1017 memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
1018 pos += IPV6_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +00001019 }
hassof390d2c2004-09-10 20:48:21 +00001020
jardineb5d44e2003-12-23 08:09:43 +00001021 return add_tlv (IPV6_ADDR, pos - value, value, stream);
1022}
1023
1024int
1025tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
1026{
paul1eb8ef22005-04-07 07:30:20 +00001027 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +00001028 struct ipv6_reachability *ip6reach;
1029 u_char value[255];
1030 u_char *pos = value;
1031 int retval, prefix_octets;
hassof390d2c2004-09-10 20:48:21 +00001032
paul1eb8ef22005-04-07 07:30:20 +00001033 for (ALL_LIST_ELEMENTS (ipv6_reachs, node, nnode, ip6reach))
hassof390d2c2004-09-10 20:48:21 +00001034 {
hassof390d2c2004-09-10 20:48:21 +00001035 if (pos - value + IPV6_MAX_BYTELEN + 6 > 255)
1036 {
1037 retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1038 if (retval != ISIS_OK)
1039 return retval;
1040 pos = value;
1041 }
1042 *(uint32_t *) pos = ip6reach->metric;
1043 pos += 4;
1044 *pos = ip6reach->control_info;
1045 pos++;
1046 prefix_octets = ((ip6reach->prefix_len + 7) / 8);
1047 *pos = ip6reach->prefix_len;
1048 pos++;
1049 memcpy (pos, ip6reach->prefix, prefix_octets);
1050 pos += prefix_octets;
jardineb5d44e2003-12-23 08:09:43 +00001051 }
hassof390d2c2004-09-10 20:48:21 +00001052
jardineb5d44e2003-12-23 08:09:43 +00001053 return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1054}
1055#endif /* HAVE_IPV6 */
1056
1057int
1058tlv_add_padding (struct stream *stream)
1059{
hassof390d2c2004-09-10 20:48:21 +00001060 int fullpads, i, left;
1061
jardineb5d44e2003-12-23 08:09:43 +00001062 /*
1063 * How many times can we add full padding ?
1064 */
hassof390d2c2004-09-10 20:48:21 +00001065 fullpads = (STREAM_SIZE (stream) - stream_get_endp (stream)) / 257;
1066 for (i = 0; i < fullpads; i++)
1067 {
1068 if (!stream_putc (stream, (u_char) PADDING)) /* TAG */
1069 goto err;
1070 if (!stream_putc (stream, (u_char) 255)) /* LENGHT */
1071 goto err;
paul15935e92005-05-03 09:27:23 +00001072 stream_put (stream, NULL, 255); /* zero padding */
hassof390d2c2004-09-10 20:48:21 +00001073 }
1074
paul9985f832005-02-09 15:51:56 +00001075 left = STREAM_SIZE (stream) - stream_get_endp (stream);
hassof390d2c2004-09-10 20:48:21 +00001076
jardineb5d44e2003-12-23 08:09:43 +00001077 if (left < 2)
1078 return ISIS_OK;
hassof390d2c2004-09-10 20:48:21 +00001079
1080 if (left == 2)
1081 {
1082 stream_putc (stream, PADDING);
1083 stream_putc (stream, 0);
1084 return ISIS_OK;
1085 }
1086
jardineb5d44e2003-12-23 08:09:43 +00001087 stream_putc (stream, PADDING);
1088 stream_putc (stream, left - 2);
paul15935e92005-05-03 09:27:23 +00001089 stream_put (stream, NULL, left-2);
jardineb5d44e2003-12-23 08:09:43 +00001090
1091 return ISIS_OK;
1092
hassof390d2c2004-09-10 20:48:21 +00001093err:
jardineb5d44e2003-12-23 08:09:43 +00001094 zlog_warn ("tlv_add_padding(): no room for tlv");
1095 return ISIS_WARNING;
1096}