blob: 94fa65ed32936ebaef4d77f87262c62e858aad07 [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
Paul Jakma41b36e92006-12-08 01:09:50 +000048/*
49 * Prototypes.
50 */
51int add_tlv (u_char, u_char, u_char *, struct stream *);
52
jardineb5d44e2003-12-23 08:09:43 +000053void
54free_tlv (void *val)
55{
hassof390d2c2004-09-10 20:48:21 +000056 XFREE (MTYPE_ISIS_TLV, val);
57
58 return;
jardineb5d44e2003-12-23 08:09:43 +000059}
60
61/*
62 * Called after parsing of a PDU. There shouldn't be any tlv's left, so this
63 * is only a caution to avoid memory leaks
64 */
hassof390d2c2004-09-10 20:48:21 +000065void
jardineb5d44e2003-12-23 08:09:43 +000066free_tlvs (struct tlvs *tlvs)
67{
hassof390d2c2004-09-10 20:48:21 +000068 if (tlvs->area_addrs)
hassoaac372f2005-09-01 17:52:33 +000069 list_delete (tlvs->area_addrs);
hassof390d2c2004-09-10 20:48:21 +000070 if (tlvs->is_neighs)
hassoaac372f2005-09-01 17:52:33 +000071 list_delete (tlvs->is_neighs);
hassof390d2c2004-09-10 20:48:21 +000072 if (tlvs->te_is_neighs)
hassoaac372f2005-09-01 17:52:33 +000073 list_delete (tlvs->te_is_neighs);
hassof390d2c2004-09-10 20:48:21 +000074 if (tlvs->es_neighs)
hassoaac372f2005-09-01 17:52:33 +000075 list_delete (tlvs->es_neighs);
hassof390d2c2004-09-10 20:48:21 +000076 if (tlvs->lsp_entries)
hassoaac372f2005-09-01 17:52:33 +000077 list_delete (tlvs->lsp_entries);
hassof390d2c2004-09-10 20:48:21 +000078 if (tlvs->lan_neighs)
hassoaac372f2005-09-01 17:52:33 +000079 list_delete (tlvs->lan_neighs);
hassof390d2c2004-09-10 20:48:21 +000080 if (tlvs->prefix_neighs)
hassoaac372f2005-09-01 17:52:33 +000081 list_delete (tlvs->prefix_neighs);
hassof390d2c2004-09-10 20:48:21 +000082 if (tlvs->ipv4_addrs)
hassoaac372f2005-09-01 17:52:33 +000083 list_delete (tlvs->ipv4_addrs);
hassof390d2c2004-09-10 20:48:21 +000084 if (tlvs->ipv4_int_reachs)
hassoaac372f2005-09-01 17:52:33 +000085 list_delete (tlvs->ipv4_int_reachs);
hassof390d2c2004-09-10 20:48:21 +000086 if (tlvs->ipv4_ext_reachs)
hassoaac372f2005-09-01 17:52:33 +000087 list_delete (tlvs->ipv4_ext_reachs);
hassof390d2c2004-09-10 20:48:21 +000088 if (tlvs->te_ipv4_reachs)
hassoaac372f2005-09-01 17:52:33 +000089 list_delete (tlvs->te_ipv4_reachs);
jardineb5d44e2003-12-23 08:09:43 +000090#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +000091 if (tlvs->ipv6_addrs)
hassoaac372f2005-09-01 17:52:33 +000092 list_delete (tlvs->ipv6_addrs);
hassof390d2c2004-09-10 20:48:21 +000093 if (tlvs->ipv6_reachs)
hassoaac372f2005-09-01 17:52:33 +000094 list_delete (tlvs->ipv6_reachs);
jardineb5d44e2003-12-23 08:09:43 +000095#endif /* HAVE_IPV6 */
hassoaac372f2005-09-01 17:52:33 +000096
jardineb5d44e2003-12-23 08:09:43 +000097 return;
98}
99
100/*
101 * Parses the tlvs found in the variant length part of the PDU.
102 * Caller tells with flags in "expected" which TLV's it is interested in.
103 */
hassof390d2c2004-09-10 20:48:21 +0000104int
105parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
106 u_int32_t * found, struct tlvs *tlvs)
jardineb5d44e2003-12-23 08:09:43 +0000107{
hassof390d2c2004-09-10 20:48:21 +0000108 u_char type, length;
109 struct lan_neigh *lan_nei;
110 struct area_addr *area_addr;
111 struct is_neigh *is_nei;
112 struct te_is_neigh *te_is_nei;
113 struct es_neigh *es_nei;
114 struct lsp_entry *lsp_entry;
115 struct in_addr *ipv4_addr;
116 struct ipv4_reachability *ipv4_reach;
117 struct te_ipv4_reachability *te_ipv4_reach;
jardineb5d44e2003-12-23 08:09:43 +0000118#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000119 struct in6_addr *ipv6_addr;
120 struct ipv6_reachability *ipv6_reach;
121 int prefix_octets;
jardineb5d44e2003-12-23 08:09:43 +0000122#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000123 u_char virtual;
124 int value_len, retval = ISIS_OK;
125 u_char *pnt = stream;
jardineb5d44e2003-12-23 08:09:43 +0000126
127 *found = 0;
128 memset (tlvs, 0, sizeof (struct tlvs));
hassof390d2c2004-09-10 20:48:21 +0000129
130 while (pnt < stream + size - 2)
131 {
132 type = *pnt;
133 length = *(pnt + 1);
134 pnt += 2;
135 value_len = 0;
136 if (pnt + length > stream + size)
137 {
138 zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet "
139 "boundaries", areatag, type, length);
140 retval = ISIS_WARNING;
141 break;
142 }
143 switch (type)
144 {
145 case AREA_ADDRESSES:
146 /* +-------+-------+-------+-------+-------+-------+-------+-------+
147 * | Address Length |
148 * +-------+-------+-------+-------+-------+-------+-------+-------+
149 * | Area Address |
150 * +-------+-------+-------+-------+-------+-------+-------+-------+
151 * : :
152 */
153 *found |= TLVFLAG_AREA_ADDRS;
jardineb5d44e2003-12-23 08:09:43 +0000154#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000155 zlog_debug ("TLV Area Adresses len %d", length);
jardineb5d44e2003-12-23 08:09:43 +0000156#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000157 if (*expected & TLVFLAG_AREA_ADDRS)
158 {
159 while (length > value_len)
160 {
161 area_addr = (struct area_addr *) pnt;
162 value_len += area_addr->addr_len + 1;
163 pnt += area_addr->addr_len + 1;
164 if (!tlvs->area_addrs)
165 tlvs->area_addrs = list_new ();
166 listnode_add (tlvs->area_addrs, area_addr);
167 }
168 }
169 else
170 {
171 pnt += length;
172 }
173 break;
jardineb5d44e2003-12-23 08:09:43 +0000174
hassof390d2c2004-09-10 20:48:21 +0000175 case IS_NEIGHBOURS:
176 *found |= TLVFLAG_IS_NEIGHS;
jardineb5d44e2003-12-23 08:09:43 +0000177#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000178 zlog_debug ("ISIS-TLV (%s): IS Neighbours length %d",
179 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000180#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000181 if (TLVFLAG_IS_NEIGHS & *expected)
182 {
183 /* +-------+-------+-------+-------+-------+-------+-------+-------+
184 * | Virtual Flag |
185 * +-------+-------+-------+-------+-------+-------+-------+-------+
186 */
187 virtual = *pnt; /* FIXME: what is the use for this? */
188 pnt++;
189 value_len++;
190 /* +-------+-------+-------+-------+-------+-------+-------+-------+
191 * | 0 | I/E | Default Metric |
192 * +-------+-------+-------+-------+-------+-------+-------+-------+
193 * | S | I/E | Delay Metric |
194 * +-------+-------+-------+-------+-------+-------+-------+-------+
195 * | S | I/E | Expense Metric |
196 * +-------+-------+-------+-------+-------+-------+-------+-------+
197 * | S | I/E | Error Metric |
198 * +-------+-------+-------+-------+-------+-------+-------+-------+
199 * | Neighbour ID |
200 * +---------------------------------------------------------------+
201 * : :
202 */
203 while (length > value_len)
204 {
205 is_nei = (struct is_neigh *) pnt;
206 value_len += 4 + ISIS_SYS_ID_LEN + 1;
207 pnt += 4 + ISIS_SYS_ID_LEN + 1;
208 if (!tlvs->is_neighs)
209 tlvs->is_neighs = list_new ();
210 listnode_add (tlvs->is_neighs, is_nei);
211 }
212 }
213 else
214 {
215 pnt += length;
216 }
217 break;
jardineb5d44e2003-12-23 08:09:43 +0000218
hassof390d2c2004-09-10 20:48:21 +0000219 case TE_IS_NEIGHBOURS:
220 /* +-------+-------+-------+-------+-------+-------+-------+-------+
221 * | Neighbour ID | 7
222 * +---------------------------------------------------------------+
223 * | TE Metric | 3
224 * +---------------------------------------------------------------+
225 * | SubTLVs Length | 1
226 * +---------------------------------------------------------------+
227 * : :
228 */
229 *found |= TLVFLAG_TE_IS_NEIGHS;
jardineb5d44e2003-12-23 08:09:43 +0000230#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000231 zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d",
hassof390d2c2004-09-10 20:48:21 +0000232 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000233#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000234 if (TLVFLAG_TE_IS_NEIGHS & *expected)
235 {
236 while (length > value_len)
237 {
238 te_is_nei = (struct te_is_neigh *) pnt;
239 value_len += 11;
240 pnt += 11;
241 /* FIXME - subtlvs are handled here, for now we skip */
242 value_len += te_is_nei->sub_tlvs_length;
243 pnt += te_is_nei->sub_tlvs_length;
jardineb5d44e2003-12-23 08:09:43 +0000244
hassof390d2c2004-09-10 20:48:21 +0000245 if (!tlvs->te_is_neighs)
246 tlvs->te_is_neighs = list_new ();
247 listnode_add (tlvs->te_is_neighs, te_is_nei);
248 }
249 }
250 else
251 {
252 pnt += length;
253 }
254 break;
jardineb5d44e2003-12-23 08:09:43 +0000255
hassof390d2c2004-09-10 20:48:21 +0000256 case ES_NEIGHBOURS:
257 /* +-------+-------+-------+-------+-------+-------+-------+-------+
258 * | 0 | I/E | Default Metric |
259 * +-------+-------+-------+-------+-------+-------+-------+-------+
260 * | S | I/E | Delay Metric |
261 * +-------+-------+-------+-------+-------+-------+-------+-------+
262 * | S | I/E | Expense Metric |
263 * +-------+-------+-------+-------+-------+-------+-------+-------+
264 * | S | I/E | Error Metric |
265 * +-------+-------+-------+-------+-------+-------+-------+-------+
266 * | Neighbour ID |
267 * +---------------------------------------------------------------+
268 * | Neighbour ID |
269 * +---------------------------------------------------------------+
270 * : :
271 */
jardineb5d44e2003-12-23 08:09:43 +0000272#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000273 zlog_debug ("ISIS-TLV (%s): ES Neighbours length %d",
hassof390d2c2004-09-10 20:48:21 +0000274 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000275#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000276 *found |= TLVFLAG_ES_NEIGHS;
277 if (*expected & TLVFLAG_ES_NEIGHS)
278 {
279 es_nei = (struct es_neigh *) pnt;
280 value_len += 4;
281 pnt += 4;
282 while (length > value_len)
283 {
284 /* FIXME FIXME FIXME - add to the list */
285 /* sys_id->id = pnt; */
286 value_len += ISIS_SYS_ID_LEN;
287 pnt += ISIS_SYS_ID_LEN;
288 /* if (!es_nei->neigh_ids) es_nei->neigh_ids = sysid; */
289 }
290 if (!tlvs->es_neighs)
291 tlvs->es_neighs = list_new ();
292 listnode_add (tlvs->es_neighs, es_nei);
293 }
294 else
295 {
296 pnt += length;
297 }
298 break;
jardineb5d44e2003-12-23 08:09:43 +0000299
hassof390d2c2004-09-10 20:48:21 +0000300 case LAN_NEIGHBOURS:
301 /* +-------+-------+-------+-------+-------+-------+-------+-------+
302 * | LAN Address |
303 * +-------+-------+-------+-------+-------+-------+-------+-------+
304 * : :
305 */
306 *found |= TLVFLAG_LAN_NEIGHS;
jardineb5d44e2003-12-23 08:09:43 +0000307#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000308 zlog_debug ("ISIS-TLV (%s): LAN Neigbours length %d",
309 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000310#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000311 if (TLVFLAG_LAN_NEIGHS & *expected)
312 {
313 while (length > value_len)
314 {
315 lan_nei = (struct lan_neigh *) pnt;
316 if (!tlvs->lan_neighs)
317 tlvs->lan_neighs = list_new ();
318 listnode_add (tlvs->lan_neighs, lan_nei);
319 value_len += ETH_ALEN;
320 pnt += ETH_ALEN;
321 }
322 }
323 else
324 {
325 pnt += length;
326 }
327 break;
jardineb5d44e2003-12-23 08:09:43 +0000328
hassof390d2c2004-09-10 20:48:21 +0000329 case PADDING:
jardineb5d44e2003-12-23 08:09:43 +0000330#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000331 zlog_debug ("TLV padding %d", length);
jardineb5d44e2003-12-23 08:09:43 +0000332#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000333 pnt += length;
334 break;
jardineb5d44e2003-12-23 08:09:43 +0000335
hassof390d2c2004-09-10 20:48:21 +0000336 case LSP_ENTRIES:
337 /* +-------+-------+-------+-------+-------+-------+-------+-------+
338 * | Remaining Lifetime | 2
339 * +-------+-------+-------+-------+-------+-------+-------+-------+
340 * | LSP ID | id+2
341 * +-------+-------+-------+-------+-------+-------+-------+-------+
342 * | LSP Sequence Number | 4
343 * +-------+-------+-------+-------+-------+-------+-------+-------+
344 * | Checksum | 2
345 * +-------+-------+-------+-------+-------+-------+-------+-------+
346 */
jardineb5d44e2003-12-23 08:09:43 +0000347#ifdef EXTREME_TLV_DEBUG
hasso92365882005-01-18 13:53:33 +0000348 zlog_debug ("ISIS-TLV (%s): LSP Entries length %d", areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000349#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000350 *found |= TLVFLAG_LSP_ENTRIES;
351 if (TLVFLAG_LSP_ENTRIES & *expected)
352 {
353 while (length > value_len)
354 {
355 lsp_entry = (struct lsp_entry *) pnt;
356 value_len += 10 + ISIS_SYS_ID_LEN;
357 pnt += 10 + ISIS_SYS_ID_LEN;
358 if (!tlvs->lsp_entries)
359 tlvs->lsp_entries = list_new ();
360 listnode_add (tlvs->lsp_entries, lsp_entry);
361 }
362 }
363 else
364 {
365 pnt += length;
366 }
367 break;
jardineb5d44e2003-12-23 08:09:43 +0000368
hassof390d2c2004-09-10 20:48:21 +0000369 case CHECKSUM:
370 /* +-------+-------+-------+-------+-------+-------+-------+-------+
371 * | 16 bit fletcher CHECKSUM |
372 * +-------+-------+-------+-------+-------+-------+-------+-------+
373 * : :
374 */
375 *found |= TLVFLAG_CHECKSUM;
jardineb5d44e2003-12-23 08:09:43 +0000376#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000377 zlog_debug ("ISIS-TLV (%s): Checksum length %d", areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000378#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000379 if (*expected & TLVFLAG_CHECKSUM)
380 {
381 tlvs->checksum = (struct checksum *) pnt;
382 }
383 pnt += length;
384 break;
jardineb5d44e2003-12-23 08:09:43 +0000385
hassof390d2c2004-09-10 20:48:21 +0000386 case PROTOCOLS_SUPPORTED:
387 /* +-------+-------+-------+-------+-------+-------+-------+-------+
388 * | NLPID |
389 * +-------+-------+-------+-------+-------+-------+-------+-------+
390 * : :
391 */
392 *found |= TLVFLAG_NLPID;
jardineb5d44e2003-12-23 08:09:43 +0000393#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000394 zlog_debug ("ISIS-TLV (%s): Protocols Supported length %d",
395 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000396#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000397 if (*expected & TLVFLAG_NLPID)
398 {
399 tlvs->nlpids = (struct nlpids *) (pnt - 1);
400 }
401 pnt += length;
402 break;
jardineb5d44e2003-12-23 08:09:43 +0000403
hassof390d2c2004-09-10 20:48:21 +0000404 case IPV4_ADDR:
405 /* +-------+-------+-------+-------+-------+-------+-------+-------+
406 * + IP version 4 address + 4
407 * +-------+-------+-------+-------+-------+-------+-------+-------+
408 * : :
409 */
410 *found |= TLVFLAG_IPV4_ADDR;
jardineb5d44e2003-12-23 08:09:43 +0000411#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000412 zlog_debug ("ISIS-TLV (%s): IPv4 Address length %d",
413 areatag, length);
hassof390d2c2004-09-10 20:48:21 +0000414#endif /* EXTREME_TLV_DEBUG */
415 if (*expected & TLVFLAG_IPV4_ADDR)
416 {
417 while (length > value_len)
418 {
419 ipv4_addr = (struct in_addr *) pnt;
hassof891f442004-09-14 13:54:30 +0000420#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000421 zlog_debug ("ISIS-TLV (%s) : IP ADDR %s, pnt %p", areatag,
422 inet_ntoa (*ipv4_addr), pnt);
hassof891f442004-09-14 13:54:30 +0000423#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000424 if (!tlvs->ipv4_addrs)
425 tlvs->ipv4_addrs = list_new ();
426 listnode_add (tlvs->ipv4_addrs, ipv4_addr);
427 value_len += 4;
428 pnt += 4;
429 }
430 }
431 else
432 {
433 pnt += length;
434 }
435 break;
436
437 case AUTH_INFO:
438 *found |= TLVFLAG_AUTH_INFO;
439#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000440 zlog_debug ("ISIS-TLV (%s): IS-IS Authentication Information",
441 areatag);
jardineb5d44e2003-12-23 08:09:43 +0000442#endif
hassof390d2c2004-09-10 20:48:21 +0000443 if (*expected & TLVFLAG_AUTH_INFO)
444 {
445 tlvs->auth_info.type = *pnt;
hasso53c997c2004-09-15 16:21:59 +0000446 tlvs->auth_info.len = length-1;
hassof390d2c2004-09-10 20:48:21 +0000447 pnt++;
448 memcpy (tlvs->auth_info.passwd, pnt, length - 1);
449 pnt += length - 1;
450 }
451 else
452 {
453 pnt += length;
454 }
455 break;
jardineb5d44e2003-12-23 08:09:43 +0000456
hassof390d2c2004-09-10 20:48:21 +0000457 case DYNAMIC_HOSTNAME:
458 *found |= TLVFLAG_DYN_HOSTNAME;
jardineb5d44e2003-12-23 08:09:43 +0000459#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000460 zlog_debug ("ISIS-TLV (%s): Dynamic Hostname length %d",
461 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000462#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000463 if (*expected & TLVFLAG_DYN_HOSTNAME)
464 {
465 /* the length is also included in the pointed struct */
466 tlvs->hostname = (struct hostname *) (pnt - 1);
467 }
468 pnt += length;
469 break;
jardineb5d44e2003-12-23 08:09:43 +0000470
hassof390d2c2004-09-10 20:48:21 +0000471 case TE_ROUTER_ID:
472 /* +---------------------------------------------------------------+
473 * + Router ID + 4
474 * +---------------------------------------------------------------+
475 */
476 *found |= TLVFLAG_TE_ROUTER_ID;
jardineb5d44e2003-12-23 08:09:43 +0000477#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000478 zlog_debug ("ISIS-TLV (%s): TE Router ID %d", areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000479#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000480 if (*expected & TLVFLAG_TE_ROUTER_ID)
hasso1cd80842004-10-07 20:07:40 +0000481 tlvs->router_id = (struct te_router_id *) (pnt);
hassof390d2c2004-09-10 20:48:21 +0000482 pnt += length;
483 break;
jardineb5d44e2003-12-23 08:09:43 +0000484
hassof390d2c2004-09-10 20:48:21 +0000485 case IPV4_INT_REACHABILITY:
486 /* +-------+-------+-------+-------+-------+-------+-------+-------+
487 * | 0 | I/E | Default Metric | 1
488 * +-------+-------+-------+-------+-------+-------+-------+-------+
489 * | S | I/E | Delay Metric | 1
490 * +-------+-------+-------+-------+-------+-------+-------+-------+
491 * | S | I/E | Expense Metric | 1
492 * +-------+-------+-------+-------+-------+-------+-------+-------+
493 * | S | I/E | Error Metric | 1
494 * +-------+-------+-------+-------+-------+-------+-------+-------+
495 * | ip address | 4
496 * +---------------------------------------------------------------+
497 * | address mask | 4
498 * +---------------------------------------------------------------+
499 * : :
500 */
501 *found |= TLVFLAG_IPV4_INT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000502#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000503 zlog_debug ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
504 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000505#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000506 if (*expected & TLVFLAG_IPV4_INT_REACHABILITY)
507 {
508 while (length > value_len)
509 {
510 ipv4_reach = (struct ipv4_reachability *) pnt;
511 if (!tlvs->ipv4_int_reachs)
512 tlvs->ipv4_int_reachs = list_new ();
513 listnode_add (tlvs->ipv4_int_reachs, ipv4_reach);
514 value_len += 12;
515 pnt += 12;
516 }
517 }
518 else
519 {
520 pnt += length;
521 }
522 break;
jardineb5d44e2003-12-23 08:09:43 +0000523
hassof390d2c2004-09-10 20:48:21 +0000524 case IPV4_EXT_REACHABILITY:
525 /* +-------+-------+-------+-------+-------+-------+-------+-------+
526 * | 0 | I/E | Default Metric | 1
527 * +-------+-------+-------+-------+-------+-------+-------+-------+
528 * | S | I/E | Delay Metric | 1
529 * +-------+-------+-------+-------+-------+-------+-------+-------+
530 * | S | I/E | Expense Metric | 1
531 * +-------+-------+-------+-------+-------+-------+-------+-------+
532 * | S | I/E | Error Metric | 1
533 * +-------+-------+-------+-------+-------+-------+-------+-------+
534 * | ip address | 4
535 * +---------------------------------------------------------------+
536 * | address mask | 4
537 * +---------------------------------------------------------------+
538 * : :
539 */
540 *found |= TLVFLAG_IPV4_EXT_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000541#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000542 zlog_debug ("ISIS-TLV (%s): IPv4 external Reachability length %d",
543 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000544#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000545 if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY)
546 {
547 while (length > value_len)
548 {
549 ipv4_reach = (struct ipv4_reachability *) pnt;
550 if (!tlvs->ipv4_ext_reachs)
551 tlvs->ipv4_ext_reachs = list_new ();
552 listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach);
553 value_len += 12;
554 pnt += 12;
555 }
556 }
557 else
558 {
559 pnt += length;
560 }
561 break;
jardineb5d44e2003-12-23 08:09:43 +0000562
hassof390d2c2004-09-10 20:48:21 +0000563 case TE_IPV4_REACHABILITY:
564 /* +-------+-------+-------+-------+-------+-------+-------+-------+
565 * | TE Metric | 4
566 * +-------+-------+-------+-------+-------+-------+-------+-------+
567 * | U/D | sTLV? | Prefix Mask Len | 1
568 * +-------+-------+-------+-------+-------+-------+-------+-------+
569 * | Prefix | 0-4
570 * +---------------------------------------------------------------+
571 * | sub tlvs |
572 * +---------------------------------------------------------------+
573 * : :
574 */
575 *found |= TLVFLAG_TE_IPV4_REACHABILITY;
jardineb5d44e2003-12-23 08:09:43 +0000576#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000577 zlog_debug ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
578 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000579#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000580 if (*expected & TLVFLAG_TE_IPV4_REACHABILITY)
581 {
582 while (length > value_len)
583 {
584 te_ipv4_reach = (struct te_ipv4_reachability *) pnt;
585 if (!tlvs->te_ipv4_reachs)
586 tlvs->te_ipv4_reachs = list_new ();
587 listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach);
588 /* this trickery is permitable since no subtlvs are defined */
589 value_len += 5 + ((te_ipv4_reach->control & 0x3F) ?
590 ((((te_ipv4_reach->control & 0x3F) -
591 1) >> 3) + 1) : 0);
592 pnt += 5 + ((te_ipv4_reach->control & 0x3F) ?
593 ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0);
594 }
595 }
596 else
597 {
598 pnt += length;
599 }
600 break;
jardineb5d44e2003-12-23 08:09:43 +0000601
602#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000603 case IPV6_ADDR:
604 /* +-------+-------+-------+-------+-------+-------+-------+-------+
605 * + IP version 6 address + 16
606 * +-------+-------+-------+-------+-------+-------+-------+-------+
607 * : :
608 */
609 *found |= TLVFLAG_IPV6_ADDR;
jardineb5d44e2003-12-23 08:09:43 +0000610#ifdef EXTREME_TLV_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000611 zlog_debug ("ISIS-TLV (%s): IPv6 Address length %d",
612 areatag, length);
jardineb5d44e2003-12-23 08:09:43 +0000613#endif /* EXTREME_TLV_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000614 if (*expected & TLVFLAG_IPV6_ADDR)
615 {
616 while (length > value_len)
617 {
618 ipv6_addr = (struct in6_addr *) pnt;
619 if (!tlvs->ipv6_addrs)
620 tlvs->ipv6_addrs = list_new ();
621 listnode_add (tlvs->ipv6_addrs, ipv6_addr);
622 value_len += 16;
623 pnt += 16;
624 }
625 }
626 else
627 {
628 pnt += length;
629 }
630 break;
jardineb5d44e2003-12-23 08:09:43 +0000631
hassof390d2c2004-09-10 20:48:21 +0000632 case IPV6_REACHABILITY:
633 /* +-------+-------+-------+-------+-------+-------+-------+-------+
634 * | Default Metric | 4
635 * +-------+-------+-------+-------+-------+-------+-------+-------+
636 * | Control Informantion |
637 * +---------------------------------------------------------------+
638 * | IPv6 Prefix Length |--+
639 * +---------------------------------------------------------------+ |
640 * | IPv6 Prefix |<-+
641 * +---------------------------------------------------------------+
642 */
643 *found |= TLVFLAG_IPV6_REACHABILITY;
644 if (*expected & TLVFLAG_IPV6_REACHABILITY)
645 {
646 while (length > value_len)
647 {
648 ipv6_reach = (struct ipv6_reachability *) pnt;
649 prefix_octets = ((ipv6_reach->prefix_len + 7) / 8);
650 value_len += prefix_octets + 6;
651 pnt += prefix_octets + 6;
652 /* FIXME: sub-tlvs */
653 if (!tlvs->ipv6_reachs)
654 tlvs->ipv6_reachs = list_new ();
655 listnode_add (tlvs->ipv6_reachs, ipv6_reach);
656 }
657 }
658 else
659 {
660 pnt += length;
661 }
662 break;
jardineb5d44e2003-12-23 08:09:43 +0000663#endif /* HAVE_IPV6 */
664
hassof390d2c2004-09-10 20:48:21 +0000665 case WAY3_HELLO:
666 /* +---------------------------------------------------------------+
667 * | Adjacency state | 1
668 * +---------------------------------------------------------------+
669 * | Extended Local Circuit ID | 4
670 * +---------------------------------------------------------------+
671 * | Neighbor System ID (If known) | 0-8
672 * (probably 6)
673 * +---------------------------------------------------------------+
674 * | Neighbor Local Circuit ID (If known) | 4
675 * +---------------------------------------------------------------+
676 */
677 *found |= TLVFLAG_3WAY_HELLO;
678 if (*expected & TLVFLAG_3WAY_HELLO)
679 {
680 while (length > value_len)
681 {
682 /* FIXME: make this work */
jardineb5d44e2003-12-23 08:09:43 +0000683/* Adjacency State (one octet):
684 0 = Up
685 1 = Initializing
686 2 = Down
687 Extended Local Circuit ID (four octets)
688 Neighbor System ID if known (zero to eight octets)
689 Neighbor Extended Local Circuit ID (four octets, if Neighbor
690 System ID is present) */
hassof390d2c2004-09-10 20:48:21 +0000691 pnt += length;
692 }
693 }
694 else
695 {
696 pnt += length;
697 }
jardineb5d44e2003-12-23 08:09:43 +0000698
hassof390d2c2004-09-10 20:48:21 +0000699 break;
700 case GRACEFUL_RESTART:
701 /* +-------+-------+-------+-------+-------+-------+-------+-------+
702 * | Reserved | SA | RA | RR | 1
703 * +-------+-------+-------+-------+-------+-------+-------+-------+
704 * | Remaining Time | 2
705 * +---------------------------------------------------------------+
706 * | Restarting Neighbor ID (If known) | 0-8
707 * +---------------------------------------------------------------+
708 */
709 *found |= TLVFLAG_GRACEFUL_RESTART;
710 if (*expected & TLVFLAG_GRACEFUL_RESTART)
711 {
712 /* FIXME: make this work */
713 }
714 pnt += length;
715 break;
jardineb5d44e2003-12-23 08:09:43 +0000716
hassof390d2c2004-09-10 20:48:21 +0000717 default:
718 zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
719 areatag, type, length);
jardineb5d44e2003-12-23 08:09:43 +0000720
hassof390d2c2004-09-10 20:48:21 +0000721 retval = ISIS_WARNING;
722 pnt += length;
723 break;
724 }
jardineb5d44e2003-12-23 08:09:43 +0000725 }
hassof390d2c2004-09-10 20:48:21 +0000726
jardineb5d44e2003-12-23 08:09:43 +0000727 return retval;
728}
729
730int
hassof390d2c2004-09-10 20:48:21 +0000731add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000732{
733
paul9985f832005-02-09 15:51:56 +0000734 if (STREAM_SIZE (stream) - stream_get_endp (stream) < (unsigned) len + 2)
hassof390d2c2004-09-10 20:48:21 +0000735 {
736 zlog_warn ("No room for TLV of type %d", tag);
737 return ISIS_WARNING;
738 }
jardineb5d44e2003-12-23 08:09:43 +0000739
hassof390d2c2004-09-10 20:48:21 +0000740 stream_putc (stream, tag); /* TAG */
741 stream_putc (stream, len); /* LENGTH */
742 stream_put (stream, value, (int) len); /* VALUE */
jardineb5d44e2003-12-23 08:09:43 +0000743
744#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000745 zlog_debug ("Added TLV %d len %d", tag, len);
jardineb5d44e2003-12-23 08:09:43 +0000746#endif /* EXTREME DEBUG */
747 return ISIS_OK;
748}
749
jardineb5d44e2003-12-23 08:09:43 +0000750int
hassof390d2c2004-09-10 20:48:21 +0000751tlv_add_area_addrs (struct list *area_addrs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000752{
753 struct listnode *node;
754 struct area_addr *area_addr;
755
hassof390d2c2004-09-10 20:48:21 +0000756 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000757 u_char *pos = value;
hassof390d2c2004-09-10 20:48:21 +0000758
paul1eb8ef22005-04-07 07:30:20 +0000759 for (ALL_LIST_ELEMENTS_RO (area_addrs, node, area_addr))
hassof390d2c2004-09-10 20:48:21 +0000760 {
hassof390d2c2004-09-10 20:48:21 +0000761 if (pos - value + area_addr->addr_len > 255)
762 goto err;
763 *pos = area_addr->addr_len;
764 pos++;
765 memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len);
766 pos += area_addr->addr_len;
767 }
768
jardineb5d44e2003-12-23 08:09:43 +0000769 return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
770
hassof390d2c2004-09-10 20:48:21 +0000771err:
jardineb5d44e2003-12-23 08:09:43 +0000772 zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
773 return ISIS_WARNING;
774}
775
hassof390d2c2004-09-10 20:48:21 +0000776int
777tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000778{
hasso3fdb2dd2005-09-28 18:45:54 +0000779 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +0000780 struct is_neigh *is_neigh;
hassof390d2c2004-09-10 20:48:21 +0000781 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000782 u_char *pos = value;
783 int retval;
784
hassof390d2c2004-09-10 20:48:21 +0000785 *pos = 0; /*is_neigh->virtual; */
786 pos++;
jardineb5d44e2003-12-23 08:09:43 +0000787
hasso3fdb2dd2005-09-28 18:45:54 +0000788 for (ALL_LIST_ELEMENTS_RO (is_neighs, node, is_neigh))
hassof390d2c2004-09-10 20:48:21 +0000789 {
hassof390d2c2004-09-10 20:48:21 +0000790 if (pos - value + IS_NEIGHBOURS_LEN > 255)
791 {
792 retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
793 if (retval != ISIS_OK)
794 return retval;
795 pos = value;
796 }
797 *pos = is_neigh->metrics.metric_default;
798 pos++;
799 *pos = is_neigh->metrics.metric_delay;
800 pos++;
801 *pos = is_neigh->metrics.metric_expense;
802 pos++;
803 *pos = is_neigh->metrics.metric_error;
804 pos++;
805 memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
806 pos += ISIS_SYS_ID_LEN + 1;
jardineb5d44e2003-12-23 08:09:43 +0000807 }
jardineb5d44e2003-12-23 08:09:43 +0000808
809 return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
810}
811
jardineb5d44e2003-12-23 08:09:43 +0000812int
hassoea3be4c2005-09-26 17:11:12 +0000813tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream)
814{
hasso3fdb2dd2005-09-28 18:45:54 +0000815 struct listnode *node;
hassoea3be4c2005-09-26 17:11:12 +0000816 struct te_is_neigh *te_is_neigh;
817 u_char value[255];
818 u_char *pos = value;
819 int retval;
820
hasso3fdb2dd2005-09-28 18:45:54 +0000821 for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh))
hassoea3be4c2005-09-26 17:11:12 +0000822 {
823 /* FIXME: This will be wrong if we are going to add TE sub TLVs. */
824 if (pos - value + IS_NEIGHBOURS_LEN > 255)
825 {
826 retval = add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
827 if (retval != ISIS_OK)
828 return retval;
829 pos = value;
830 }
831
832 memcpy (pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
833 pos += ISIS_SYS_ID_LEN + 1;
834 memcpy (pos, te_is_neigh->te_metric, 3);
835 pos += 3;
836 /* Sub TLVs length. */
837 *pos = 0;
838 pos++;
839 }
840
841 return add_tlv (TE_IS_NEIGHBOURS, pos - value, value, stream);
842}
843
844int
jardineb5d44e2003-12-23 08:09:43 +0000845tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
846{
hasso3fdb2dd2005-09-28 18:45:54 +0000847 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +0000848 u_char *snpa;
hassof390d2c2004-09-10 20:48:21 +0000849 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000850 u_char *pos = value;
851 int retval;
852
hasso3fdb2dd2005-09-28 18:45:54 +0000853 for (ALL_LIST_ELEMENTS_RO (lan_neighs, node, snpa))
hassof390d2c2004-09-10 20:48:21 +0000854 {
hassof390d2c2004-09-10 20:48:21 +0000855 if (pos - value + ETH_ALEN > 255)
856 {
857 retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
858 if (retval != ISIS_OK)
859 return retval;
860 pos = value;
861 }
862 memcpy (pos, snpa, ETH_ALEN);
863 pos += ETH_ALEN;
jardineb5d44e2003-12-23 08:09:43 +0000864 }
jardineb5d44e2003-12-23 08:09:43 +0000865
866 return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
867}
868
jardineb5d44e2003-12-23 08:09:43 +0000869int
870tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
871{
hassof390d2c2004-09-10 20:48:21 +0000872 return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream);
jardineb5d44e2003-12-23 08:09:43 +0000873}
874
hassof390d2c2004-09-10 20:48:21 +0000875int
hassof7c43dc2004-09-26 16:24:14 +0000876tlv_add_authinfo (char auth_type, char auth_len, u_char *auth_value,
hassof390d2c2004-09-10 20:48:21 +0000877 struct stream *stream)
jardineb5d44e2003-12-23 08:09:43 +0000878{
879 u_char value[255];
880 u_char *pos = value;
hasso53c997c2004-09-15 16:21:59 +0000881 *pos++ = ISIS_PASSWD_TYPE_CLEARTXT;
jardineb5d44e2003-12-23 08:09:43 +0000882 memcpy (pos, auth_value, auth_len);
883
884 return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
885}
886
887int
888tlv_add_checksum (struct checksum *checksum, struct stream *stream)
889{
890 u_char value[255];
hassof390d2c2004-09-10 20:48:21 +0000891 u_char *pos = value;
892 return add_tlv (CHECKSUM, pos - value, value, stream);
jardineb5d44e2003-12-23 08:09:43 +0000893}
894
895int
896tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
897{
hasso3fdb2dd2005-09-28 18:45:54 +0000898 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +0000899 struct prefix_ipv4 *ipv4;
900 u_char value[255];
901 u_char *pos = value;
902 int retval;
903
hasso3fdb2dd2005-09-28 18:45:54 +0000904 for (ALL_LIST_ELEMENTS_RO (ip_addrs, node, ipv4))
hassof390d2c2004-09-10 20:48:21 +0000905 {
hassof390d2c2004-09-10 20:48:21 +0000906 if (pos - value + IPV4_MAX_BYTELEN > 255)
907 {
908 retval = add_tlv (IPV4_ADDR, pos - value, value, stream);
909 if (retval != ISIS_OK)
910 return retval;
911 pos = value;
912 }
913 *(u_int32_t *) pos = ipv4->prefix.s_addr;
914 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +0000915 }
hassof390d2c2004-09-10 20:48:21 +0000916
jardineb5d44e2003-12-23 08:09:43 +0000917 return add_tlv (IPV4_ADDR, pos - value, value, stream);
918}
919
hasso81ad8f62005-09-26 17:58:24 +0000920/* Used to add TLV containing just one IPv4 address - either IPv4 address TLV
921 * (in case of LSP) or TE router ID TLV. */
922int
923tlv_add_in_addr (struct in_addr *addr, struct stream *stream, u_char tag)
924{
925 u_char value[255];
926 u_char *pos = value;
927
928 memcpy (pos, addr, IPV4_MAX_BYTELEN);
929 pos += IPV4_MAX_BYTELEN;
930
931 return add_tlv (tag, pos - value, value, stream);
932}
933
jardineb5d44e2003-12-23 08:09:43 +0000934int
935tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
936{
hassof390d2c2004-09-10 20:48:21 +0000937 return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name,
938 stream);
jardineb5d44e2003-12-23 08:09:43 +0000939}
940
hassof390d2c2004-09-10 20:48:21 +0000941int
jardineb5d44e2003-12-23 08:09:43 +0000942tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
943{
hasso3fdb2dd2005-09-28 18:45:54 +0000944 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +0000945 struct isis_lsp *lsp;
hassof390d2c2004-09-10 20:48:21 +0000946 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000947 u_char *pos = value;
948 int retval;
949
hasso3fdb2dd2005-09-28 18:45:54 +0000950 for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp))
hassof390d2c2004-09-10 20:48:21 +0000951 {
hassof390d2c2004-09-10 20:48:21 +0000952 if (pos - value + LSP_ENTRIES_LEN > 255)
953 {
954 retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
955 if (retval != ISIS_OK)
956 return retval;
957 pos = value;
958 }
959 *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime;
960 pos += 2;
961 memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
962 pos += ISIS_SYS_ID_LEN + 2;
963 *((u_int32_t *) pos) = lsp->lsp_header->seq_num;
964 pos += 4;
965 *((u_int16_t *) pos) = lsp->lsp_header->checksum;
966 pos += 2;
jardineb5d44e2003-12-23 08:09:43 +0000967 }
hassof390d2c2004-09-10 20:48:21 +0000968
jardineb5d44e2003-12-23 08:09:43 +0000969 return add_tlv (LSP_ENTRIES, pos - value, value, stream);
970}
971
hassof390d2c2004-09-10 20:48:21 +0000972int
jardineb5d44e2003-12-23 08:09:43 +0000973tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
974{
hasso3fdb2dd2005-09-28 18:45:54 +0000975 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +0000976 struct ipv4_reachability *reach;
hassof390d2c2004-09-10 20:48:21 +0000977 u_char value[255];
jardineb5d44e2003-12-23 08:09:43 +0000978 u_char *pos = value;
979 int retval;
980
hasso3fdb2dd2005-09-28 18:45:54 +0000981 for (ALL_LIST_ELEMENTS_RO (ipv4_reachs, node, reach))
hassof390d2c2004-09-10 20:48:21 +0000982 {
hassof390d2c2004-09-10 20:48:21 +0000983 if (pos - value + IPV4_REACH_LEN > 255)
984 {
985 retval =
986 add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
987 if (retval != ISIS_OK)
988 return retval;
989 pos = value;
990 }
991 *pos = reach->metrics.metric_default;
992 pos++;
993 *pos = reach->metrics.metric_delay;
994 pos++;
995 *pos = reach->metrics.metric_expense;
996 pos++;
997 *pos = reach->metrics.metric_error;
998 pos++;
999 *(u_int32_t *) pos = reach->prefix.s_addr;
1000 pos += IPV4_MAX_BYTELEN;
1001 *(u_int32_t *) pos = reach->mask.s_addr;
1002 pos += IPV4_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +00001003 }
hassof390d2c2004-09-10 20:48:21 +00001004
1005
jardineb5d44e2003-12-23 08:09:43 +00001006 return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
1007}
1008
hassoea3be4c2005-09-26 17:11:12 +00001009int
1010tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream)
1011{
hasso3fdb2dd2005-09-28 18:45:54 +00001012 struct listnode *node;
hassoea3be4c2005-09-26 17:11:12 +00001013 struct te_ipv4_reachability *te_reach;
1014 u_char value[255];
1015 u_char *pos = value;
1016 u_char prefix_size;
1017 int retval;
1018
hasso3fdb2dd2005-09-28 18:45:54 +00001019 for (ALL_LIST_ELEMENTS_RO (te_ipv4_reachs, node, te_reach))
hassoea3be4c2005-09-26 17:11:12 +00001020 {
1021 prefix_size = ((((te_reach->control & 0x3F) - 1) >> 3) + 1);
1022
1023 if (pos - value + (5 + prefix_size) > 255)
1024 {
1025 retval =
1026 add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
1027 if (retval != ISIS_OK)
1028 return retval;
1029 pos = value;
1030 }
1031 *(u_int32_t *) pos = te_reach->te_metric;
1032 pos += 4;
1033 *pos = te_reach->control;
1034 pos++;
1035 memcpy (pos, &te_reach->prefix_start, prefix_size);
1036 pos += prefix_size;
1037 }
1038
1039 return add_tlv (TE_IPV4_REACHABILITY, pos - value, value, stream);
1040}
1041
hassof390d2c2004-09-10 20:48:21 +00001042#ifdef HAVE_IPV6
jardineb5d44e2003-12-23 08:09:43 +00001043int
1044tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
1045{
hasso3fdb2dd2005-09-28 18:45:54 +00001046 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001047 struct prefix_ipv6 *ipv6;
1048 u_char value[255];
1049 u_char *pos = value;
1050 int retval;
hassof390d2c2004-09-10 20:48:21 +00001051
hasso3fdb2dd2005-09-28 18:45:54 +00001052 for (ALL_LIST_ELEMENTS_RO (ipv6_addrs, node, ipv6))
hassof390d2c2004-09-10 20:48:21 +00001053 {
hassof390d2c2004-09-10 20:48:21 +00001054 if (pos - value + IPV6_MAX_BYTELEN > 255)
1055 {
1056 retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
1057 if (retval != ISIS_OK)
1058 return retval;
1059 pos = value;
1060 }
1061 memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
1062 pos += IPV6_MAX_BYTELEN;
jardineb5d44e2003-12-23 08:09:43 +00001063 }
hassof390d2c2004-09-10 20:48:21 +00001064
jardineb5d44e2003-12-23 08:09:43 +00001065 return add_tlv (IPV6_ADDR, pos - value, value, stream);
1066}
1067
1068int
1069tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
1070{
hasso3fdb2dd2005-09-28 18:45:54 +00001071 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +00001072 struct ipv6_reachability *ip6reach;
1073 u_char value[255];
1074 u_char *pos = value;
1075 int retval, prefix_octets;
hassof390d2c2004-09-10 20:48:21 +00001076
hasso3fdb2dd2005-09-28 18:45:54 +00001077 for (ALL_LIST_ELEMENTS_RO (ipv6_reachs, node, ip6reach))
hassof390d2c2004-09-10 20:48:21 +00001078 {
hassof390d2c2004-09-10 20:48:21 +00001079 if (pos - value + IPV6_MAX_BYTELEN + 6 > 255)
1080 {
1081 retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1082 if (retval != ISIS_OK)
1083 return retval;
1084 pos = value;
1085 }
1086 *(uint32_t *) pos = ip6reach->metric;
1087 pos += 4;
1088 *pos = ip6reach->control_info;
1089 pos++;
1090 prefix_octets = ((ip6reach->prefix_len + 7) / 8);
1091 *pos = ip6reach->prefix_len;
1092 pos++;
1093 memcpy (pos, ip6reach->prefix, prefix_octets);
1094 pos += prefix_octets;
jardineb5d44e2003-12-23 08:09:43 +00001095 }
hassof390d2c2004-09-10 20:48:21 +00001096
jardineb5d44e2003-12-23 08:09:43 +00001097 return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
1098}
1099#endif /* HAVE_IPV6 */
1100
1101int
1102tlv_add_padding (struct stream *stream)
1103{
hassof390d2c2004-09-10 20:48:21 +00001104 int fullpads, i, left;
1105
jardineb5d44e2003-12-23 08:09:43 +00001106 /*
1107 * How many times can we add full padding ?
1108 */
hassof390d2c2004-09-10 20:48:21 +00001109 fullpads = (STREAM_SIZE (stream) - stream_get_endp (stream)) / 257;
1110 for (i = 0; i < fullpads; i++)
1111 {
1112 if (!stream_putc (stream, (u_char) PADDING)) /* TAG */
1113 goto err;
1114 if (!stream_putc (stream, (u_char) 255)) /* LENGHT */
1115 goto err;
paul15935e92005-05-03 09:27:23 +00001116 stream_put (stream, NULL, 255); /* zero padding */
hassof390d2c2004-09-10 20:48:21 +00001117 }
1118
paul9985f832005-02-09 15:51:56 +00001119 left = STREAM_SIZE (stream) - stream_get_endp (stream);
hassof390d2c2004-09-10 20:48:21 +00001120
jardineb5d44e2003-12-23 08:09:43 +00001121 if (left < 2)
1122 return ISIS_OK;
hassof390d2c2004-09-10 20:48:21 +00001123
1124 if (left == 2)
1125 {
1126 stream_putc (stream, PADDING);
1127 stream_putc (stream, 0);
1128 return ISIS_OK;
1129 }
1130
jardineb5d44e2003-12-23 08:09:43 +00001131 stream_putc (stream, PADDING);
1132 stream_putc (stream, left - 2);
paul15935e92005-05-03 09:27:23 +00001133 stream_put (stream, NULL, left-2);
jardineb5d44e2003-12-23 08:09:43 +00001134
1135 return ISIS_OK;
1136
hassof390d2c2004-09-10 20:48:21 +00001137err:
jardineb5d44e2003-12-23 08:09:43 +00001138 zlog_warn ("tlv_add_padding(): no room for tlv");
1139 return ISIS_WARNING;
1140}