2 * IS-IS Rout(e)ing protocol - isis_tlv.c
3 * IS-IS TLV related routines
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
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)
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
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.
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"
46 extern struct isis
*isis
;
51 int add_tlv (u_char
, u_char
, u_char
*, struct stream
*);
56 XFREE (MTYPE_ISIS_TLV
, val
);
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
66 free_tlvs (struct tlvs
*tlvs
)
69 list_delete (tlvs
->area_addrs
);
71 list_delete (tlvs
->is_neighs
);
72 if (tlvs
->te_is_neighs
)
73 list_delete (tlvs
->te_is_neighs
);
75 list_delete (tlvs
->es_neighs
);
76 if (tlvs
->lsp_entries
)
77 list_delete (tlvs
->lsp_entries
);
79 list_delete (tlvs
->lan_neighs
);
80 if (tlvs
->prefix_neighs
)
81 list_delete (tlvs
->prefix_neighs
);
83 list_delete (tlvs
->ipv4_addrs
);
84 if (tlvs
->ipv4_int_reachs
)
85 list_delete (tlvs
->ipv4_int_reachs
);
86 if (tlvs
->ipv4_ext_reachs
)
87 list_delete (tlvs
->ipv4_ext_reachs
);
88 if (tlvs
->te_ipv4_reachs
)
89 list_delete (tlvs
->te_ipv4_reachs
);
92 list_delete (tlvs
->ipv6_addrs
);
93 if (tlvs
->ipv6_reachs
)
94 list_delete (tlvs
->ipv6_reachs
);
95 #endif /* HAVE_IPV6 */
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.
105 parse_tlvs (char *areatag
, u_char
* stream
, int size
, u_int32_t
* expected
,
106 u_int32_t
* found
, struct tlvs
*tlvs
)
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
;
119 struct in6_addr
*ipv6_addr
;
120 struct ipv6_reachability
*ipv6_reach
;
122 #endif /* HAVE_IPV6 */
124 int value_len
, retval
= ISIS_OK
;
125 u_char
*pnt
= stream
;
128 memset (tlvs
, 0, sizeof (struct tlvs
));
130 while (pnt
< stream
+ size
- 2)
136 if (pnt
+ length
> stream
+ size
)
138 zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet "
139 "boundaries", areatag
, type
, length
);
140 retval
= ISIS_WARNING
;
146 /* +-------+-------+-------+-------+-------+-------+-------+-------+
148 * +-------+-------+-------+-------+-------+-------+-------+-------+
150 * +-------+-------+-------+-------+-------+-------+-------+-------+
153 *found
|= TLVFLAG_AREA_ADDRS
;
154 #ifdef EXTREME_TLV_DEBUG
155 zlog_debug ("TLV Area Adresses len %d", length
);
156 #endif /* EXTREME_TLV_DEBUG */
157 if (*expected
& TLVFLAG_AREA_ADDRS
)
159 while (length
> value_len
)
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
);
176 *found
|= TLVFLAG_IS_NEIGHS
;
177 #ifdef EXTREME_TLV_DEBUG
178 zlog_debug ("ISIS-TLV (%s): IS Neighbours length %d",
180 #endif /* EXTREME_TLV_DEBUG */
181 if (TLVFLAG_IS_NEIGHS
& *expected
)
183 /* +-------+-------+-------+-------+-------+-------+-------+-------+
185 * +-------+-------+-------+-------+-------+-------+-------+-------+
187 virtual = *pnt
; /* FIXME: what is the use for this? */
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 * +-------+-------+-------+-------+-------+-------+-------+-------+
200 * +---------------------------------------------------------------+
203 while (length
> value_len
)
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
);
219 case TE_IS_NEIGHBOURS
:
220 /* +-------+-------+-------+-------+-------+-------+-------+-------+
222 * +---------------------------------------------------------------+
224 * +---------------------------------------------------------------+
225 * | SubTLVs Length | 1
226 * +---------------------------------------------------------------+
229 *found
|= TLVFLAG_TE_IS_NEIGHS
;
230 #ifdef EXTREME_TLV_DEBUG
231 zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d",
233 #endif /* EXTREME_TLV_DEBUG */
234 if (TLVFLAG_TE_IS_NEIGHS
& *expected
)
236 while (length
> value_len
)
238 te_is_nei
= (struct te_is_neigh
*) pnt
;
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
;
245 if (!tlvs
->te_is_neighs
)
246 tlvs
->te_is_neighs
= list_new ();
247 listnode_add (tlvs
->te_is_neighs
, te_is_nei
);
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 * +-------+-------+-------+-------+-------+-------+-------+-------+
267 * +---------------------------------------------------------------+
269 * +---------------------------------------------------------------+
272 #ifdef EXTREME_TLV_DEBUG
273 zlog_debug ("ISIS-TLV (%s): ES Neighbours length %d",
275 #endif /* EXTREME_TLV_DEBUG */
276 *found
|= TLVFLAG_ES_NEIGHS
;
277 if (*expected
& TLVFLAG_ES_NEIGHS
)
279 es_nei
= (struct es_neigh
*) pnt
;
282 while (length
> value_len
)
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; */
290 if (!tlvs
->es_neighs
)
291 tlvs
->es_neighs
= list_new ();
292 listnode_add (tlvs
->es_neighs
, es_nei
);
301 /* +-------+-------+-------+-------+-------+-------+-------+-------+
303 * +-------+-------+-------+-------+-------+-------+-------+-------+
306 *found
|= TLVFLAG_LAN_NEIGHS
;
307 #ifdef EXTREME_TLV_DEBUG
308 zlog_debug ("ISIS-TLV (%s): LAN Neigbours length %d",
310 #endif /* EXTREME_TLV_DEBUG */
311 if (TLVFLAG_LAN_NEIGHS
& *expected
)
313 while (length
> value_len
)
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
;
330 #ifdef EXTREME_TLV_DEBUG
331 zlog_debug ("TLV padding %d", length
);
332 #endif /* EXTREME_TLV_DEBUG */
337 /* +-------+-------+-------+-------+-------+-------+-------+-------+
338 * | Remaining Lifetime | 2
339 * +-------+-------+-------+-------+-------+-------+-------+-------+
341 * +-------+-------+-------+-------+-------+-------+-------+-------+
342 * | LSP Sequence Number |Â 4
343 * +-------+-------+-------+-------+-------+-------+-------+-------+
345 * +-------+-------+-------+-------+-------+-------+-------+-------+
347 #ifdef EXTREME_TLV_DEBUG
348 zlog_debug ("ISIS-TLV (%s): LSP Entries length %d", areatag
, length
);
349 #endif /* EXTREME_TLV_DEBUG */
350 *found
|= TLVFLAG_LSP_ENTRIES
;
351 if (TLVFLAG_LSP_ENTRIES
& *expected
)
353 while (length
> value_len
)
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
);
370 /* +-------+-------+-------+-------+-------+-------+-------+-------+
371 * | 16 bit fletcher CHECKSUM |
372 * +-------+-------+-------+-------+-------+-------+-------+-------+
375 *found
|= TLVFLAG_CHECKSUM
;
376 #ifdef EXTREME_TLV_DEBUG
377 zlog_debug ("ISIS-TLV (%s): Checksum length %d", areatag
, length
);
378 #endif /* EXTREME_TLV_DEBUG */
379 if (*expected
& TLVFLAG_CHECKSUM
)
381 tlvs
->checksum
= (struct checksum
*) pnt
;
386 case PROTOCOLS_SUPPORTED
:
387 /* +-------+-------+-------+-------+-------+-------+-------+-------+
389 * +-------+-------+-------+-------+-------+-------+-------+-------+
392 *found
|= TLVFLAG_NLPID
;
393 #ifdef EXTREME_TLV_DEBUG
394 zlog_debug ("ISIS-TLV (%s): Protocols Supported length %d",
396 #endif /* EXTREME_TLV_DEBUG */
397 if (*expected
& TLVFLAG_NLPID
)
399 tlvs
->nlpids
= (struct nlpids
*) (pnt
- 1);
405 /* +-------+-------+-------+-------+-------+-------+-------+-------+
406 * + IP version 4 address + 4
407 * +-------+-------+-------+-------+-------+-------+-------+-------+
410 *found
|= TLVFLAG_IPV4_ADDR
;
411 #ifdef EXTREME_TLV_DEBUG
412 zlog_debug ("ISIS-TLV (%s): IPv4 Address length %d",
414 #endif /* EXTREME_TLV_DEBUG */
415 if (*expected
& TLVFLAG_IPV4_ADDR
)
417 while (length
> value_len
)
419 ipv4_addr
= (struct in_addr
*) pnt
;
420 #ifdef EXTREME_TLV_DEBUG
421 zlog_debug ("ISIS-TLV (%s) : IP ADDR %s, pnt %p", areatag
,
422 inet_ntoa (*ipv4_addr
), pnt
);
423 #endif /* EXTREME_TLV_DEBUG */
424 if (!tlvs
->ipv4_addrs
)
425 tlvs
->ipv4_addrs
= list_new ();
426 listnode_add (tlvs
->ipv4_addrs
, ipv4_addr
);
438 *found
|= TLVFLAG_AUTH_INFO
;
439 #ifdef EXTREME_TLV_DEBUG
440 zlog_debug ("ISIS-TLV (%s): IS-IS Authentication Information",
443 if (*expected
& TLVFLAG_AUTH_INFO
)
445 tlvs
->auth_info
.type
= *pnt
;
446 tlvs
->auth_info
.len
= length
-1;
448 memcpy (tlvs
->auth_info
.passwd
, pnt
, length
- 1);
457 case DYNAMIC_HOSTNAME
:
458 *found
|= TLVFLAG_DYN_HOSTNAME
;
459 #ifdef EXTREME_TLV_DEBUG
460 zlog_debug ("ISIS-TLV (%s): Dynamic Hostname length %d",
462 #endif /* EXTREME_TLV_DEBUG */
463 if (*expected
& TLVFLAG_DYN_HOSTNAME
)
465 /* the length is also included in the pointed struct */
466 tlvs
->hostname
= (struct hostname
*) (pnt
- 1);
472 /* +---------------------------------------------------------------+
474 * +---------------------------------------------------------------+
476 *found
|= TLVFLAG_TE_ROUTER_ID
;
477 #ifdef EXTREME_TLV_DEBUG
478 zlog_debug ("ISIS-TLV (%s): TE Router ID %d", areatag
, length
);
479 #endif /* EXTREME_TLV_DEBUG */
480 if (*expected
& TLVFLAG_TE_ROUTER_ID
)
481 tlvs
->router_id
= (struct te_router_id
*) (pnt
);
485 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 * +-------+-------+-------+-------+-------+-------+-------+-------+
496 * +---------------------------------------------------------------+
498 * +---------------------------------------------------------------+
501 *found
|= TLVFLAG_IPV4_INT_REACHABILITY
;
502 #ifdef EXTREME_TLV_DEBUG
503 zlog_debug ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
505 #endif /* EXTREME_TLV_DEBUG */
506 if (*expected
& TLVFLAG_IPV4_INT_REACHABILITY
)
508 while (length
> value_len
)
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
);
524 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 * +-------+-------+-------+-------+-------+-------+-------+-------+
535 * +---------------------------------------------------------------+
537 * +---------------------------------------------------------------+
540 *found
|= TLVFLAG_IPV4_EXT_REACHABILITY
;
541 #ifdef EXTREME_TLV_DEBUG
542 zlog_debug ("ISIS-TLV (%s): IPv4 external Reachability length %d",
544 #endif /* EXTREME_TLV_DEBUG */
545 if (*expected
& TLVFLAG_IPV4_EXT_REACHABILITY
)
547 while (length
> value_len
)
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
);
563 case TE_IPV4_REACHABILITY
:
564 /* +-------+-------+-------+-------+-------+-------+-------+-------+
566 * +-------+-------+-------+-------+-------+-------+-------+-------+
567 * | U/D | sTLV? | Prefix Mask Len | 1
568 * +-------+-------+-------+-------+-------+-------+-------+-------+
570 * +---------------------------------------------------------------+
572 * +---------------------------------------------------------------+
575 *found
|= TLVFLAG_TE_IPV4_REACHABILITY
;
576 #ifdef EXTREME_TLV_DEBUG
577 zlog_debug ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
579 #endif /* EXTREME_TLV_DEBUG */
580 if (*expected
& TLVFLAG_TE_IPV4_REACHABILITY
)
582 while (length
> value_len
)
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) -
592 pnt
+= 5 + ((te_ipv4_reach
->control
& 0x3F) ?
593 ((((te_ipv4_reach
->control
& 0x3F) - 1) >> 3) + 1) : 0);
604 /* +-------+-------+-------+-------+-------+-------+-------+-------+
605 * + IP version 6 address + 16
606 * +-------+-------+-------+-------+-------+-------+-------+-------+
609 *found
|= TLVFLAG_IPV6_ADDR
;
610 #ifdef EXTREME_TLV_DEBUG
611 zlog_debug ("ISIS-TLV (%s): IPv6 Address length %d",
613 #endif /* EXTREME_TLV_DEBUG */
614 if (*expected
& TLVFLAG_IPV6_ADDR
)
616 while (length
> value_len
)
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
);
632 case IPV6_REACHABILITY
:
633 /* +-------+-------+-------+-------+-------+-------+-------+-------+
634 * | Default Metric | 4
635 * +-------+-------+-------+-------+-------+-------+-------+-------+
636 * | Control Informantion |
637 * +---------------------------------------------------------------+
638 * | IPv6 Prefix Length |--+
639 * +---------------------------------------------------------------+ |
641 * +---------------------------------------------------------------+
643 *found
|= TLVFLAG_IPV6_REACHABILITY
;
644 if (*expected
& TLVFLAG_IPV6_REACHABILITY
)
646 while (length
> value_len
)
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
);
663 #endif /* HAVE_IPV6 */
666 /* +---------------------------------------------------------------+
667 * | Adjacency state | 1
668 * +---------------------------------------------------------------+
669 * | Extended Local Circuit ID | 4
670 * +---------------------------------------------------------------+
671 * | Neighbor System ID (If known) | 0-8
673 * +---------------------------------------------------------------+
674 * | Neighbor Local Circuit ID (If known) | 4
675 * +---------------------------------------------------------------+
677 *found
|= TLVFLAG_3WAY_HELLO
;
678 if (*expected
& TLVFLAG_3WAY_HELLO
)
680 while (length
> value_len
)
682 /* FIXME: make this work */
683 /* Adjacency State (one octet):
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) */
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 * +---------------------------------------------------------------+
709 *found
|= TLVFLAG_GRACEFUL_RESTART
;
710 if (*expected
& TLVFLAG_GRACEFUL_RESTART
)
712 /* FIXME: make this work */
718 zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
719 areatag
, type
, length
);
721 retval
= ISIS_WARNING
;
731 add_tlv (u_char tag
, u_char len
, u_char
* value
, struct stream
*stream
)
734 if (STREAM_SIZE (stream
) - stream_get_endp (stream
) < (unsigned) len
+ 2)
736 zlog_warn ("No room for TLV of type %d", tag
);
740 stream_putc (stream
, tag
); /* TAG */
741 stream_putc (stream
, len
); /* LENGTH */
742 stream_put (stream
, value
, (int) len
); /* VALUE */
745 zlog_debug ("Added TLV %d len %d", tag
, len
);
746 #endif /* EXTREME DEBUG */
751 tlv_add_area_addrs (struct list
*area_addrs
, struct stream
*stream
)
753 struct listnode
*node
;
754 struct area_addr
*area_addr
;
759 for (ALL_LIST_ELEMENTS_RO (area_addrs
, node
, area_addr
))
761 if (pos
- value
+ area_addr
->addr_len
> 255)
763 *pos
= area_addr
->addr_len
;
765 memcpy (pos
, area_addr
->area_addr
, (int) area_addr
->addr_len
);
766 pos
+= area_addr
->addr_len
;
769 return add_tlv (AREA_ADDRESSES
, pos
- value
, value
, stream
);
772 zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
777 tlv_add_is_neighs (struct list
*is_neighs
, struct stream
*stream
)
779 struct listnode
*node
;
780 struct is_neigh
*is_neigh
;
785 *pos
= 0; /*is_neigh->virtual; */
788 for (ALL_LIST_ELEMENTS_RO (is_neighs
, node
, is_neigh
))
790 if (pos
- value
+ IS_NEIGHBOURS_LEN
> 255)
792 retval
= add_tlv (IS_NEIGHBOURS
, pos
- value
, value
, stream
);
793 if (retval
!= ISIS_OK
)
797 *pos
= is_neigh
->metrics
.metric_default
;
799 *pos
= is_neigh
->metrics
.metric_delay
;
801 *pos
= is_neigh
->metrics
.metric_expense
;
803 *pos
= is_neigh
->metrics
.metric_error
;
805 memcpy (pos
, is_neigh
->neigh_id
, ISIS_SYS_ID_LEN
+ 1);
806 pos
+= ISIS_SYS_ID_LEN
+ 1;
809 return add_tlv (IS_NEIGHBOURS
, pos
- value
, value
, stream
);
813 tlv_add_te_is_neighs (struct list
*te_is_neighs
, struct stream
*stream
)
815 struct listnode
*node
;
816 struct te_is_neigh
*te_is_neigh
;
821 for (ALL_LIST_ELEMENTS_RO (te_is_neighs
, node
, te_is_neigh
))
823 /* FIXME: This will be wrong if we are going to add TE sub TLVs. */
824 if (pos
- value
+ IS_NEIGHBOURS_LEN
> 255)
826 retval
= add_tlv (TE_IS_NEIGHBOURS
, pos
- value
, value
, stream
);
827 if (retval
!= ISIS_OK
)
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);
836 /* Sub TLVs length. */
841 return add_tlv (TE_IS_NEIGHBOURS
, pos
- value
, value
, stream
);
845 tlv_add_lan_neighs (struct list
*lan_neighs
, struct stream
*stream
)
847 struct listnode
*node
;
853 for (ALL_LIST_ELEMENTS_RO (lan_neighs
, node
, snpa
))
855 if (pos
- value
+ ETH_ALEN
> 255)
857 retval
= add_tlv (LAN_NEIGHBOURS
, pos
- value
, value
, stream
);
858 if (retval
!= ISIS_OK
)
862 memcpy (pos
, snpa
, ETH_ALEN
);
866 return add_tlv (LAN_NEIGHBOURS
, pos
- value
, value
, stream
);
870 tlv_add_nlpid (struct nlpids
*nlpids
, struct stream
*stream
)
872 return add_tlv (PROTOCOLS_SUPPORTED
, nlpids
->count
, nlpids
->nlpids
, stream
);
876 tlv_add_authinfo (char auth_type
, char auth_len
, u_char
*auth_value
,
877 struct stream
*stream
)
881 *pos
++ = ISIS_PASSWD_TYPE_CLEARTXT
;
882 memcpy (pos
, auth_value
, auth_len
);
884 return add_tlv (AUTH_INFO
, auth_len
+ 1, value
, stream
);
888 tlv_add_checksum (struct checksum
*checksum
, struct stream
*stream
)
892 return add_tlv (CHECKSUM
, pos
- value
, value
, stream
);
896 tlv_add_ip_addrs (struct list
*ip_addrs
, struct stream
*stream
)
898 struct listnode
*node
;
899 struct prefix_ipv4
*ipv4
;
904 for (ALL_LIST_ELEMENTS_RO (ip_addrs
, node
, ipv4
))
906 if (pos
- value
+ IPV4_MAX_BYTELEN
> 255)
908 retval
= add_tlv (IPV4_ADDR
, pos
- value
, value
, stream
);
909 if (retval
!= ISIS_OK
)
913 *(u_int32_t
*) pos
= ipv4
->prefix
.s_addr
;
914 pos
+= IPV4_MAX_BYTELEN
;
917 return add_tlv (IPV4_ADDR
, pos
- value
, value
, stream
);
920 /* Used to add TLV containing just one IPv4 address - either IPv4 address TLV
921 * (in case of LSP) or TE router ID TLV. */
923 tlv_add_in_addr (struct in_addr
*addr
, struct stream
*stream
, u_char tag
)
928 memcpy (pos
, addr
, IPV4_MAX_BYTELEN
);
929 pos
+= IPV4_MAX_BYTELEN
;
931 return add_tlv (tag
, pos
- value
, value
, stream
);
935 tlv_add_dynamic_hostname (struct hostname
*hostname
, struct stream
*stream
)
937 return add_tlv (DYNAMIC_HOSTNAME
, hostname
->namelen
, hostname
->name
,
942 tlv_add_lsp_entries (struct list
*lsps
, struct stream
*stream
)
944 struct listnode
*node
;
945 struct isis_lsp
*lsp
;
950 for (ALL_LIST_ELEMENTS_RO (lsps
, node
, lsp
))
952 if (pos
- value
+ LSP_ENTRIES_LEN
> 255)
954 retval
= add_tlv (LSP_ENTRIES
, pos
- value
, value
, stream
);
955 if (retval
!= ISIS_OK
)
959 *((u_int16_t
*) pos
) = lsp
->lsp_header
->rem_lifetime
;
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
;
965 *((u_int16_t
*) pos
) = lsp
->lsp_header
->checksum
;
969 return add_tlv (LSP_ENTRIES
, pos
- value
, value
, stream
);
973 tlv_add_ipv4_reachs (struct list
*ipv4_reachs
, struct stream
*stream
)
975 struct listnode
*node
;
976 struct ipv4_reachability
*reach
;
981 for (ALL_LIST_ELEMENTS_RO (ipv4_reachs
, node
, reach
))
983 if (pos
- value
+ IPV4_REACH_LEN
> 255)
986 add_tlv (IPV4_INT_REACHABILITY
, pos
- value
, value
, stream
);
987 if (retval
!= ISIS_OK
)
991 *pos
= reach
->metrics
.metric_default
;
993 *pos
= reach
->metrics
.metric_delay
;
995 *pos
= reach
->metrics
.metric_expense
;
997 *pos
= reach
->metrics
.metric_error
;
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
;
1006 return add_tlv (IPV4_INT_REACHABILITY
, pos
- value
, value
, stream
);
1010 tlv_add_te_ipv4_reachs (struct list
*te_ipv4_reachs
, struct stream
*stream
)
1012 struct listnode
*node
;
1013 struct te_ipv4_reachability
*te_reach
;
1015 u_char
*pos
= value
;
1019 for (ALL_LIST_ELEMENTS_RO (te_ipv4_reachs
, node
, te_reach
))
1021 prefix_size
= ((((te_reach
->control
& 0x3F) - 1) >> 3) + 1);
1023 if (pos
- value
+ (5 + prefix_size
) > 255)
1026 add_tlv (IPV4_INT_REACHABILITY
, pos
- value
, value
, stream
);
1027 if (retval
!= ISIS_OK
)
1031 *(u_int32_t
*) pos
= te_reach
->te_metric
;
1033 *pos
= te_reach
->control
;
1035 memcpy (pos
, &te_reach
->prefix_start
, prefix_size
);
1039 return add_tlv (TE_IPV4_REACHABILITY
, pos
- value
, value
, stream
);
1044 tlv_add_ipv6_addrs (struct list
*ipv6_addrs
, struct stream
*stream
)
1046 struct listnode
*node
;
1047 struct prefix_ipv6
*ipv6
;
1049 u_char
*pos
= value
;
1052 for (ALL_LIST_ELEMENTS_RO (ipv6_addrs
, node
, ipv6
))
1054 if (pos
- value
+ IPV6_MAX_BYTELEN
> 255)
1056 retval
= add_tlv (IPV6_ADDR
, pos
- value
, value
, stream
);
1057 if (retval
!= ISIS_OK
)
1061 memcpy (pos
, ipv6
->prefix
.s6_addr
, IPV6_MAX_BYTELEN
);
1062 pos
+= IPV6_MAX_BYTELEN
;
1065 return add_tlv (IPV6_ADDR
, pos
- value
, value
, stream
);
1069 tlv_add_ipv6_reachs (struct list
*ipv6_reachs
, struct stream
*stream
)
1071 struct listnode
*node
;
1072 struct ipv6_reachability
*ip6reach
;
1074 u_char
*pos
= value
;
1075 int retval
, prefix_octets
;
1077 for (ALL_LIST_ELEMENTS_RO (ipv6_reachs
, node
, ip6reach
))
1079 if (pos
- value
+ IPV6_MAX_BYTELEN
+ 6 > 255)
1081 retval
= add_tlv (IPV6_REACHABILITY
, pos
- value
, value
, stream
);
1082 if (retval
!= ISIS_OK
)
1086 *(uint32_t *) pos
= ip6reach
->metric
;
1088 *pos
= ip6reach
->control_info
;
1090 prefix_octets
= ((ip6reach
->prefix_len
+ 7) / 8);
1091 *pos
= ip6reach
->prefix_len
;
1093 memcpy (pos
, ip6reach
->prefix
, prefix_octets
);
1094 pos
+= prefix_octets
;
1097 return add_tlv (IPV6_REACHABILITY
, pos
- value
, value
, stream
);
1099 #endif /* HAVE_IPV6 */
1102 tlv_add_padding (struct stream
*stream
)
1104 int fullpads
, i
, left
;
1107 * How many times can we add full padding ?
1109 fullpads
= (STREAM_SIZE (stream
) - stream_get_endp (stream
)) / 257;
1110 for (i
= 0; i
< fullpads
; i
++)
1112 if (!stream_putc (stream
, (u_char
) PADDING
)) /* TAG */
1114 if (!stream_putc (stream
, (u_char
) 255)) /* LENGHT */
1116 stream_put (stream
, NULL
, 255); /* zero padding */
1119 left
= STREAM_SIZE (stream
) - stream_get_endp (stream
);
1126 stream_putc (stream
, PADDING
);
1127 stream_putc (stream
, 0);
1131 stream_putc (stream
, PADDING
);
1132 stream_putc (stream
, left
- 2);
1133 stream_put (stream
, NULL
, left
-2);
1138 zlog_warn ("tlv_add_padding(): no room for tlv");
1139 return ISIS_WARNING
;