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 XFREE (MTYPE_ISIS_TLV
, val
);
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
61 free_tlvs (struct tlvs
*tlvs
)
65 list_delete (tlvs
->area_addrs
);
69 list_delete (tlvs
->is_neighs
);
71 if (tlvs
->te_is_neighs
)
73 list_delete (tlvs
->te_is_neighs
);
77 list_delete (tlvs
->es_neighs
);
79 if (tlvs
->lsp_entries
)
81 list_delete (tlvs
->lsp_entries
);
85 list_delete (tlvs
->lan_neighs
);
87 if (tlvs
->prefix_neighs
)
89 list_delete (tlvs
->prefix_neighs
);
93 list_delete (tlvs
->ipv4_addrs
);
95 if (tlvs
->ipv4_int_reachs
)
97 list_delete (tlvs
->ipv4_int_reachs
);
99 if (tlvs
->ipv4_ext_reachs
)
101 list_delete (tlvs
->ipv4_ext_reachs
);
103 if (tlvs
->te_ipv4_reachs
)
105 list_delete (tlvs
->te_ipv4_reachs
);
108 if (tlvs
->ipv6_addrs
)
110 list_delete (tlvs
->ipv6_addrs
);
112 if (tlvs
->ipv6_reachs
)
114 list_delete (tlvs
->ipv6_reachs
);
116 #endif /* HAVE_IPV6 */
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.
125 parse_tlvs (char *areatag
, u_char
* stream
, int size
, u_int32_t
* expected
,
126 u_int32_t
* found
, struct tlvs
*tlvs
)
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
;
139 struct in6_addr
*ipv6_addr
;
140 struct ipv6_reachability
*ipv6_reach
;
142 #endif /* HAVE_IPV6 */
144 int value_len
, retval
= ISIS_OK
;
145 u_char
*pnt
= stream
;
148 memset (tlvs
, 0, sizeof (struct tlvs
));
150 while (pnt
< stream
+ size
- 2)
156 if (pnt
+ length
> stream
+ size
)
158 zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet "
159 "boundaries", areatag
, type
, length
);
160 retval
= ISIS_WARNING
;
166 /* +-------+-------+-------+-------+-------+-------+-------+-------+
168 * +-------+-------+-------+-------+-------+-------+-------+-------+
170 * +-------+-------+-------+-------+-------+-------+-------+-------+
173 *found
|= TLVFLAG_AREA_ADDRS
;
174 #ifdef EXTREME_TLV_DEBUG
175 zlog_info ("TLV Area Adresses len %d", length
);
176 #endif /* EXTREME_TLV_DEBUG */
177 if (*expected
& TLVFLAG_AREA_ADDRS
)
179 while (length
> value_len
)
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
);
196 *found
|= TLVFLAG_IS_NEIGHS
;
197 #ifdef EXTREME_TLV_DEBUG
198 zlog_info ("ISIS-TLV (%s): IS Neighbours length %d",
200 #endif /* EXTREME_TLV_DEBUG */
201 if (TLVFLAG_IS_NEIGHS
& *expected
)
203 /* +-------+-------+-------+-------+-------+-------+-------+-------+
205 * +-------+-------+-------+-------+-------+-------+-------+-------+
207 virtual = *pnt
; /* FIXME: what is the use for this? */
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 * +-------+-------+-------+-------+-------+-------+-------+-------+
220 * +---------------------------------------------------------------+
223 while (length
> value_len
)
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
);
239 case TE_IS_NEIGHBOURS
:
240 /* +-------+-------+-------+-------+-------+-------+-------+-------+
242 * +---------------------------------------------------------------+
244 * +---------------------------------------------------------------+
245 * | SubTLVs Length | 1
246 * +---------------------------------------------------------------+
249 *found
|= TLVFLAG_TE_IS_NEIGHS
;
250 #ifdef EXTREME_TLV_DEBUG
251 zlog_info ("ISIS-TLV (%s): Extended IS Neighbours length %d",
253 #endif /* EXTREME_TLV_DEBUG */
254 if (TLVFLAG_TE_IS_NEIGHS
& *expected
)
256 while (length
> value_len
)
258 te_is_nei
= (struct te_is_neigh
*) pnt
;
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
;
265 if (!tlvs
->te_is_neighs
)
266 tlvs
->te_is_neighs
= list_new ();
267 listnode_add (tlvs
->te_is_neighs
, te_is_nei
);
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 * +-------+-------+-------+-------+-------+-------+-------+-------+
287 * +---------------------------------------------------------------+
289 * +---------------------------------------------------------------+
292 #ifdef EXTREME_TLV_DEBUG
293 zlog_info ("ISIS-TLV (%s): ES Neighbours length %d",
295 #endif /* EXTREME_TLV_DEBUG */
296 *found
|= TLVFLAG_ES_NEIGHS
;
297 if (*expected
& TLVFLAG_ES_NEIGHS
)
299 es_nei
= (struct es_neigh
*) pnt
;
302 while (length
> value_len
)
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; */
310 if (!tlvs
->es_neighs
)
311 tlvs
->es_neighs
= list_new ();
312 listnode_add (tlvs
->es_neighs
, es_nei
);
321 /* +-------+-------+-------+-------+-------+-------+-------+-------+
323 * +-------+-------+-------+-------+-------+-------+-------+-------+
326 *found
|= TLVFLAG_LAN_NEIGHS
;
327 #ifdef EXTREME_TLV_DEBUG
328 zlog_info ("ISIS-TLV (%s): LAN Neigbours length %d",
330 #endif /* EXTREME_TLV_DEBUG */
331 if (TLVFLAG_LAN_NEIGHS
& *expected
)
333 while (length
> value_len
)
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
;
350 #ifdef EXTREME_TLV_DEBUG
351 zlog_info ("TLV padding %d", length
);
352 #endif /* EXTREME_TLV_DEBUG */
357 /* +-------+-------+-------+-------+-------+-------+-------+-------+
358 * | Remaining Lifetime | 2
359 * +-------+-------+-------+-------+-------+-------+-------+-------+
361 * +-------+-------+-------+-------+-------+-------+-------+-------+
362 * | LSP Sequence Number |Â 4
363 * +-------+-------+-------+-------+-------+-------+-------+-------+
365 * +-------+-------+-------+-------+-------+-------+-------+-------+
367 #ifdef EXTREME_TLV_DEBUG
368 zlog_info ("LSP Entries length %d", areatag
, length
);
369 #endif /* EXTREME_TLV_DEBUG */
370 *found
|= TLVFLAG_LSP_ENTRIES
;
371 if (TLVFLAG_LSP_ENTRIES
& *expected
)
373 while (length
> value_len
)
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
);
390 /* +-------+-------+-------+-------+-------+-------+-------+-------+
391 * | 16 bit fletcher CHECKSUM |
392 * +-------+-------+-------+-------+-------+-------+-------+-------+
395 *found
|= TLVFLAG_CHECKSUM
;
396 #ifdef EXTREME_TLV_DEBUG
397 zlog_info ("ISIS-TLV (%s): Checksum length %d", areatag
, length
);
398 #endif /* EXTREME_TLV_DEBUG */
399 if (*expected
& TLVFLAG_CHECKSUM
)
401 tlvs
->checksum
= (struct checksum
*) pnt
;
406 case PROTOCOLS_SUPPORTED
:
407 /* +-------+-------+-------+-------+-------+-------+-------+-------+
409 * +-------+-------+-------+-------+-------+-------+-------+-------+
412 *found
|= TLVFLAG_NLPID
;
413 #ifdef EXTREME_TLV_DEBUG
414 zlog_info ("ISIS-TLV (%s): Protocols Supported length %d",
416 #endif /* EXTREME_TLV_DEBUG */
417 if (*expected
& TLVFLAG_NLPID
)
419 tlvs
->nlpids
= (struct nlpids
*) (pnt
- 1);
425 /* +-------+-------+-------+-------+-------+-------+-------+-------+
426 * + IP version 4 address + 4
427 * +-------+-------+-------+-------+-------+-------+-------+-------+
430 *found
|= TLVFLAG_IPV4_ADDR
;
431 #ifdef EXTREME_TLV_DEBUG
432 zlog_info ("ISIS-TLV (%s): IPv4 Address length %d",
434 #endif /* EXTREME_TLV_DEBUG */
435 if (*expected
& TLVFLAG_IPV4_ADDR
)
437 while (length
> value_len
)
439 ipv4_addr
= (struct in_addr
*) pnt
;
440 zlog_info ("ISIS-TLV (%s) : IP ADDR %s, pnt %p", areatag
,
441 inet_ntoa (*ipv4_addr
), pnt
);
442 if (!tlvs
->ipv4_addrs
)
443 tlvs
->ipv4_addrs
= list_new ();
444 listnode_add (tlvs
->ipv4_addrs
, ipv4_addr
);
456 *found
|= TLVFLAG_AUTH_INFO
;
457 #ifdef EXTREME_TLV_DEBUG
458 zlog_info ("ISIS-TLV (%s): IS-IS Authentication Information",
461 if (*expected
& TLVFLAG_AUTH_INFO
)
463 tlvs
->auth_info
.type
= *pnt
;
465 memcpy (tlvs
->auth_info
.passwd
, pnt
, length
- 1);
474 case DYNAMIC_HOSTNAME
:
475 *found
|= TLVFLAG_DYN_HOSTNAME
;
476 #ifdef EXTREME_TLV_DEBUG
477 zlog_info ("ISIS-TLV (%s): Dynamic Hostname length %d",
479 #endif /* EXTREME_TLV_DEBUG */
480 if (*expected
& TLVFLAG_DYN_HOSTNAME
)
482 /* the length is also included in the pointed struct */
483 tlvs
->hostname
= (struct hostname
*) (pnt
- 1);
489 /* +---------------------------------------------------------------+
491 * +---------------------------------------------------------------+
493 *found
|= TLVFLAG_TE_ROUTER_ID
;
494 #ifdef EXTREME_TLV_DEBUG
495 zlog_info ("ISIS-TLV (%s): TE Router ID %d", areatag
, length
);
496 #endif /* EXTREME_TLV_DEBUG */
497 if (*expected
& TLVFLAG_TE_ROUTER_ID
)
499 tlvs
->router_id
= (struct te_router_id
*) (pnt
);
504 case IPV4_INT_REACHABILITY
:
505 /* +-------+-------+-------+-------+-------+-------+-------+-------+
506 * | 0 | I/E | Default Metric | 1
507 * +-------+-------+-------+-------+-------+-------+-------+-------+
508 * | S | I/E | Delay Metric | 1
509 * +-------+-------+-------+-------+-------+-------+-------+-------+
510 * | S | I/E | Expense Metric | 1
511 * +-------+-------+-------+-------+-------+-------+-------+-------+
512 * | S | I/E | Error Metric | 1
513 * +-------+-------+-------+-------+-------+-------+-------+-------+
515 * +---------------------------------------------------------------+
517 * +---------------------------------------------------------------+
520 *found
|= TLVFLAG_IPV4_INT_REACHABILITY
;
521 #ifdef EXTREME_TLV_DEBUG
522 zlog_info ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
524 #endif /* EXTREME_TLV_DEBUG */
525 if (*expected
& TLVFLAG_IPV4_INT_REACHABILITY
)
527 while (length
> value_len
)
529 ipv4_reach
= (struct ipv4_reachability
*) pnt
;
530 if (!tlvs
->ipv4_int_reachs
)
531 tlvs
->ipv4_int_reachs
= list_new ();
532 listnode_add (tlvs
->ipv4_int_reachs
, ipv4_reach
);
543 case IPV4_EXT_REACHABILITY
:
544 /* +-------+-------+-------+-------+-------+-------+-------+-------+
545 * | 0 | I/E | Default Metric | 1
546 * +-------+-------+-------+-------+-------+-------+-------+-------+
547 * | S | I/E | Delay Metric | 1
548 * +-------+-------+-------+-------+-------+-------+-------+-------+
549 * | S | I/E | Expense Metric | 1
550 * +-------+-------+-------+-------+-------+-------+-------+-------+
551 * | S | I/E | Error Metric | 1
552 * +-------+-------+-------+-------+-------+-------+-------+-------+
554 * +---------------------------------------------------------------+
556 * +---------------------------------------------------------------+
559 *found
|= TLVFLAG_IPV4_EXT_REACHABILITY
;
560 #ifdef EXTREME_TLV_DEBUG
561 zlog_info ("ISIS-TLV (%s): IPv4 external Reachability length %d",
563 #endif /* EXTREME_TLV_DEBUG */
564 if (*expected
& TLVFLAG_IPV4_EXT_REACHABILITY
)
566 while (length
> value_len
)
568 ipv4_reach
= (struct ipv4_reachability
*) pnt
;
569 if (!tlvs
->ipv4_ext_reachs
)
570 tlvs
->ipv4_ext_reachs
= list_new ();
571 listnode_add (tlvs
->ipv4_ext_reachs
, ipv4_reach
);
582 case TE_IPV4_REACHABILITY
:
583 /* +-------+-------+-------+-------+-------+-------+-------+-------+
585 * +-------+-------+-------+-------+-------+-------+-------+-------+
586 * | U/D | sTLV? | Prefix Mask Len | 1
587 * +-------+-------+-------+-------+-------+-------+-------+-------+
589 * +---------------------------------------------------------------+
591 * +---------------------------------------------------------------+
594 *found
|= TLVFLAG_TE_IPV4_REACHABILITY
;
595 #ifdef EXTREME_TLV_DEBUG
596 zlog_info ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
598 #endif /* EXTREME_TLV_DEBUG */
599 if (*expected
& TLVFLAG_TE_IPV4_REACHABILITY
)
601 while (length
> value_len
)
603 te_ipv4_reach
= (struct te_ipv4_reachability
*) pnt
;
604 if (!tlvs
->te_ipv4_reachs
)
605 tlvs
->te_ipv4_reachs
= list_new ();
606 listnode_add (tlvs
->te_ipv4_reachs
, te_ipv4_reach
);
607 /* this trickery is permitable since no subtlvs are defined */
608 value_len
+= 5 + ((te_ipv4_reach
->control
& 0x3F) ?
609 ((((te_ipv4_reach
->control
& 0x3F) -
611 pnt
+= 5 + ((te_ipv4_reach
->control
& 0x3F) ?
612 ((((te_ipv4_reach
->control
& 0x3F) - 1) >> 3) + 1) : 0);
623 /* +-------+-------+-------+-------+-------+-------+-------+-------+
624 * + IP version 6 address + 16
625 * +-------+-------+-------+-------+-------+-------+-------+-------+
628 *found
|= TLVFLAG_IPV6_ADDR
;
629 #ifdef EXTREME_TLV_DEBUG
630 zlog_info ("ISIS-TLV (%s): IPv6 Address length %d",
632 #endif /* EXTREME_TLV_DEBUG */
633 if (*expected
& TLVFLAG_IPV6_ADDR
)
635 while (length
> value_len
)
637 ipv6_addr
= (struct in6_addr
*) pnt
;
638 if (!tlvs
->ipv6_addrs
)
639 tlvs
->ipv6_addrs
= list_new ();
640 listnode_add (tlvs
->ipv6_addrs
, ipv6_addr
);
651 case IPV6_REACHABILITY
:
652 /* +-------+-------+-------+-------+-------+-------+-------+-------+
653 * | Default Metric | 4
654 * +-------+-------+-------+-------+-------+-------+-------+-------+
655 * | Control Informantion |
656 * +---------------------------------------------------------------+
657 * | IPv6 Prefix Length |--+
658 * +---------------------------------------------------------------+ |
660 * +---------------------------------------------------------------+
662 *found
|= TLVFLAG_IPV6_REACHABILITY
;
663 if (*expected
& TLVFLAG_IPV6_REACHABILITY
)
665 while (length
> value_len
)
667 ipv6_reach
= (struct ipv6_reachability
*) pnt
;
668 prefix_octets
= ((ipv6_reach
->prefix_len
+ 7) / 8);
669 value_len
+= prefix_octets
+ 6;
670 pnt
+= prefix_octets
+ 6;
671 /* FIXME: sub-tlvs */
672 if (!tlvs
->ipv6_reachs
)
673 tlvs
->ipv6_reachs
= list_new ();
674 listnode_add (tlvs
->ipv6_reachs
, ipv6_reach
);
682 #endif /* HAVE_IPV6 */
685 /* +---------------------------------------------------------------+
686 * | Adjacency state | 1
687 * +---------------------------------------------------------------+
688 * | Extended Local Circuit ID | 4
689 * +---------------------------------------------------------------+
690 * | Neighbor System ID (If known) | 0-8
692 * +---------------------------------------------------------------+
693 * | Neighbor Local Circuit ID (If known) | 4
694 * +---------------------------------------------------------------+
696 *found
|= TLVFLAG_3WAY_HELLO
;
697 if (*expected
& TLVFLAG_3WAY_HELLO
)
699 while (length
> value_len
)
701 /* FIXME: make this work */
702 /* Adjacency State (one octet):
706 Extended Local Circuit ID (four octets)
707 Neighbor System ID if known (zero to eight octets)
708 Neighbor Extended Local Circuit ID (four octets, if Neighbor
709 System ID is present) */
719 case GRACEFUL_RESTART
:
720 /* +-------+-------+-------+-------+-------+-------+-------+-------+
721 * | Reserved | SA | RA | RR | 1
722 * +-------+-------+-------+-------+-------+-------+-------+-------+
723 * | Remaining Time | 2
724 * +---------------------------------------------------------------+
725 * | Restarting Neighbor ID (If known) | 0-8
726 * +---------------------------------------------------------------+
728 *found
|= TLVFLAG_GRACEFUL_RESTART
;
729 if (*expected
& TLVFLAG_GRACEFUL_RESTART
)
731 /* FIXME: make this work */
737 zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
738 areatag
, type
, length
);
740 retval
= ISIS_WARNING
;
750 add_tlv (u_char tag
, u_char len
, u_char
* value
, struct stream
*stream
)
753 if (STREAM_SIZE (stream
) - stream_get_putp (stream
) < len
+ 2)
755 zlog_warn ("No room for TLV of type %d", tag
);
759 stream_putc (stream
, tag
); /* TAG */
760 stream_putc (stream
, len
); /* LENGTH */
761 stream_put (stream
, value
, (int) len
); /* VALUE */
764 zlog_info ("Added TLV %d len %d", tag
, len
);
765 #endif /* EXTREME DEBUG */
770 tlv_add_area_addrs (struct list
*area_addrs
, struct stream
*stream
)
772 struct listnode
*node
;
773 struct area_addr
*area_addr
;
778 for (node
= listhead (area_addrs
); node
; nextnode (node
))
780 area_addr
= getdata (node
);
781 if (pos
- value
+ area_addr
->addr_len
> 255)
783 *pos
= area_addr
->addr_len
;
785 memcpy (pos
, area_addr
->area_addr
, (int) area_addr
->addr_len
);
786 pos
+= area_addr
->addr_len
;
789 return add_tlv (AREA_ADDRESSES
, pos
- value
, value
, stream
);
792 zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
797 tlv_add_is_neighs (struct list
*is_neighs
, struct stream
*stream
)
799 struct listnode
*node
;
800 struct is_neigh
*is_neigh
;
805 *pos
= 0; /*is_neigh->virtual; */
808 for (node
= listhead (is_neighs
); node
; nextnode (node
))
810 is_neigh
= getdata (node
);
811 if (pos
- value
+ IS_NEIGHBOURS_LEN
> 255)
813 retval
= add_tlv (IS_NEIGHBOURS
, pos
- value
, value
, stream
);
814 if (retval
!= ISIS_OK
)
818 *pos
= is_neigh
->metrics
.metric_default
;
820 *pos
= is_neigh
->metrics
.metric_delay
;
822 *pos
= is_neigh
->metrics
.metric_expense
;
824 *pos
= is_neigh
->metrics
.metric_error
;
826 memcpy (pos
, is_neigh
->neigh_id
, ISIS_SYS_ID_LEN
+ 1);
827 pos
+= ISIS_SYS_ID_LEN
+ 1;
830 return add_tlv (IS_NEIGHBOURS
, pos
- value
, value
, stream
);
834 tlv_add_lan_neighs (struct list
*lan_neighs
, struct stream
*stream
)
836 struct listnode
*node
;
842 for (node
= listhead (lan_neighs
); node
; nextnode (node
))
844 snpa
= getdata (node
);
845 if (pos
- value
+ ETH_ALEN
> 255)
847 retval
= add_tlv (LAN_NEIGHBOURS
, pos
- value
, value
, stream
);
848 if (retval
!= ISIS_OK
)
852 memcpy (pos
, snpa
, ETH_ALEN
);
856 return add_tlv (LAN_NEIGHBOURS
, pos
- value
, value
, stream
);
863 if (circuit->ip_router) {
864 *pos = (u_char)NLPID_IP;
867 if (circuit->ipv6_router) {
868 *pos = (u_char)NLPID_IPV6;
874 tlv_add_nlpid (struct nlpids
*nlpids
, struct stream
*stream
)
877 return add_tlv (PROTOCOLS_SUPPORTED
, nlpids
->count
, nlpids
->nlpids
, stream
);
881 tlv_add_authinfo (char auth_type
, char auth_len
, char *auth_value
,
882 struct stream
*stream
)
887 memcpy (pos
, auth_value
, auth_len
);
889 return add_tlv (AUTH_INFO
, auth_len
+ 1, value
, stream
);
893 tlv_add_checksum (struct checksum
*checksum
, struct stream
*stream
)
897 return add_tlv (CHECKSUM
, pos
- value
, value
, stream
);
901 tlv_add_ip_addrs (struct list
*ip_addrs
, struct stream
*stream
)
903 struct listnode
*node
;
904 struct prefix_ipv4
*ipv4
;
909 for (node
= listhead (ip_addrs
); node
; nextnode (node
))
911 ipv4
= getdata (node
);
912 if (pos
- value
+ IPV4_MAX_BYTELEN
> 255)
914 retval
= add_tlv (IPV4_ADDR
, pos
- value
, value
, stream
);
915 if (retval
!= ISIS_OK
)
919 *(u_int32_t
*) pos
= ipv4
->prefix
.s_addr
;
920 pos
+= IPV4_MAX_BYTELEN
;
923 return add_tlv (IPV4_ADDR
, pos
- value
, value
, stream
);
927 tlv_add_dynamic_hostname (struct hostname
*hostname
, struct stream
*stream
)
929 return add_tlv (DYNAMIC_HOSTNAME
, hostname
->namelen
, hostname
->name
,
934 tlv_add_lsp_entries (struct list
*lsps
, struct stream
*stream
)
936 struct listnode
*node
;
937 struct isis_lsp
*lsp
;
942 for (node
= listhead (lsps
); node
; nextnode (node
))
944 lsp
= getdata (node
);
945 if (pos
- value
+ LSP_ENTRIES_LEN
> 255)
947 retval
= add_tlv (LSP_ENTRIES
, pos
- value
, value
, stream
);
948 if (retval
!= ISIS_OK
)
952 *((u_int16_t
*) pos
) = lsp
->lsp_header
->rem_lifetime
;
954 memcpy (pos
, lsp
->lsp_header
->lsp_id
, ISIS_SYS_ID_LEN
+ 2);
955 pos
+= ISIS_SYS_ID_LEN
+ 2;
956 *((u_int32_t
*) pos
) = lsp
->lsp_header
->seq_num
;
958 *((u_int16_t
*) pos
) = lsp
->lsp_header
->checksum
;
962 return add_tlv (LSP_ENTRIES
, pos
- value
, value
, stream
);
966 tlv_add_ipv4_reachs (struct list
*ipv4_reachs
, struct stream
*stream
)
968 struct listnode
*node
;
969 struct ipv4_reachability
*reach
;
974 for (node
= listhead (ipv4_reachs
); node
; nextnode (node
))
976 reach
= getdata (node
);
977 if (pos
- value
+ IPV4_REACH_LEN
> 255)
980 add_tlv (IPV4_INT_REACHABILITY
, pos
- value
, value
, stream
);
981 if (retval
!= ISIS_OK
)
985 *pos
= reach
->metrics
.metric_default
;
987 *pos
= reach
->metrics
.metric_delay
;
989 *pos
= reach
->metrics
.metric_expense
;
991 *pos
= reach
->metrics
.metric_error
;
993 *(u_int32_t
*) pos
= reach
->prefix
.s_addr
;
994 pos
+= IPV4_MAX_BYTELEN
;
995 *(u_int32_t
*) pos
= reach
->mask
.s_addr
;
996 pos
+= IPV4_MAX_BYTELEN
;
1000 return add_tlv (IPV4_INT_REACHABILITY
, pos
- value
, value
, stream
);
1005 tlv_add_ipv6_addrs (struct list
*ipv6_addrs
, struct stream
*stream
)
1007 struct listnode
*node
;
1008 struct prefix_ipv6
*ipv6
;
1010 u_char
*pos
= value
;
1013 for (node
= listhead (ipv6_addrs
); node
; nextnode (node
))
1015 ipv6
= getdata (node
);
1016 if (pos
- value
+ IPV6_MAX_BYTELEN
> 255)
1018 retval
= add_tlv (IPV6_ADDR
, pos
- value
, value
, stream
);
1019 if (retval
!= ISIS_OK
)
1023 memcpy (pos
, ipv6
->prefix
.s6_addr
, IPV6_MAX_BYTELEN
);
1024 pos
+= IPV6_MAX_BYTELEN
;
1027 return add_tlv (IPV6_ADDR
, pos
- value
, value
, stream
);
1031 tlv_add_ipv6_reachs (struct list
*ipv6_reachs
, struct stream
*stream
)
1033 struct listnode
*node
;
1034 struct ipv6_reachability
*ip6reach
;
1036 u_char
*pos
= value
;
1037 int retval
, prefix_octets
;
1039 for (node
= listhead (ipv6_reachs
); node
; nextnode (node
))
1041 ip6reach
= getdata (node
);
1042 if (pos
- value
+ IPV6_MAX_BYTELEN
+ 6 > 255)
1044 retval
= add_tlv (IPV6_REACHABILITY
, pos
- value
, value
, stream
);
1045 if (retval
!= ISIS_OK
)
1049 *(uint32_t *) pos
= ip6reach
->metric
;
1051 *pos
= ip6reach
->control_info
;
1053 prefix_octets
= ((ip6reach
->prefix_len
+ 7) / 8);
1054 *pos
= ip6reach
->prefix_len
;
1056 memcpy (pos
, ip6reach
->prefix
, prefix_octets
);
1057 pos
+= prefix_octets
;
1060 return add_tlv (IPV6_REACHABILITY
, pos
- value
, value
, stream
);
1062 #endif /* HAVE_IPV6 */
1065 tlv_add_padding (struct stream
*stream
)
1067 unsigned long putp
, endp
;
1068 int fullpads
, i
, left
;
1071 * How many times can we add full padding ?
1073 fullpads
= (STREAM_SIZE (stream
) - stream_get_endp (stream
)) / 257;
1074 for (i
= 0; i
< fullpads
; i
++)
1076 if (!stream_putc (stream
, (u_char
) PADDING
)) /* TAG */
1078 if (!stream_putc (stream
, (u_char
) 255)) /* LENGHT */
1080 endp
= stream_get_endp (stream
);
1081 putp
= stream_get_putp (stream
);
1083 zlog_warn ("tvl_add_padding endp %ld while putp %ld", endp
, putp
);
1084 stream_set_putp (stream
, putp
+ 255); /* VALUE */
1085 stream
->endp
= stream
->putp
;
1088 left
= STREAM_SIZE (stream
) - stream_get_putp (stream
);
1095 stream_putc (stream
, PADDING
);
1096 stream_putc (stream
, 0);
1100 stream_putc (stream
, PADDING
);
1101 stream_putc (stream
, left
- 2);
1102 stream_set_putp (stream
, stream_get_putp (stream
) + left
- 2);
1103 stream
->endp
= stream
->putp
;
1108 zlog_warn ("tlv_add_padding(): no room for tlv");
1109 return ISIS_WARNING
;