2 * Common CLV decode routines.
4 * Stuart Stanley <stuarts@mxmail.net>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/expert.h>
17 #include "packet-isis.h"
18 #include "packet-isis-clv.h"
19 #include <epan/nlpid.h>
21 static const value_string algorithm_vals
[] = {
24 { 28, "hmac-sha224" },
25 { 32, "hmac-sha256" },
26 { 48, "hmac-sha384" },
27 { 64, "hmac-sha512" },
31 static const value_string mt_id_vals
[] = {
32 { 0, "IPv4 Unicast" },
33 { 1, "IPv4 In-Band Management" },
34 { 2, "IPv6 Unicast" },
35 { 3, "IPv4 Multicast" },
36 { 4, "IPv6 Multicast" },
37 { 5, "IPv6 In-Band Management" },
38 { 4095, "Development, Experimental or Proprietary" },
43 * Name: isis_dissect_area_address_clv()
46 * Take an area address CLV and display it pieces. An area address
47 * CLV is n, x byte hex strings.
50 * tvbuff_t * : tvbuffer for packet data
51 * proto_tree * : protocol display tree to fill out. May be NULL
52 * int : offset into packet data where we are.
53 * int : length of clv we are decoding
56 * void, but we will add to proto tree if !NULL.
59 isis_dissect_area_address_clv(proto_tree
*tree
, packet_info
* pinfo
, tvbuff_t
*tvb
,
60 expert_field
* expert
, int hf_area
, int offset
, int length
)
64 while ( length
> 0 ) {
65 arealen
= tvb_get_uint8(tvb
, offset
);
68 proto_tree_add_expert_format(tree
, pinfo
, expert
, tvb
, offset
, -1,
69 "short address (no length for payload)");
72 if ( arealen
> length
) {
73 proto_tree_add_expert_format(tree
, pinfo
, expert
, tvb
, offset
, -1,
74 "short address, packet says %d, we have %d left",
82 ti
= proto_tree_add_bytes_format( tree
, hf_area
, tvb
, offset
, arealen
+ 1,
83 NULL
, "Area address (%d): ", arealen
);
86 * Lets turn the area address into "standard"
87 * xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx format string.
88 * this is a private routine as the print_nsap_net in
89 * epan/osi_utils.c is incomplete and we need only
90 * a subset - actually some nice placing of dots ....
92 for (area_idx
= 0; area_idx
< arealen
; area_idx
++) {
93 proto_item_append_text(ti
, "%02x",
94 tvb_get_uint8(tvb
, offset
+area_idx
+1));
95 if (((area_idx
& 1) == 0) &&
96 (area_idx
+ 1 < arealen
)) {
97 proto_item_append_text(ti
, ".");
101 offset
+= arealen
+ 1;
102 length
-= arealen
; /* length already adjusted for len fld*/
107 * Name: isis_dissect_instance_identifier_clv()
111 * tvbuff_t * : tvbuffer for packet data
112 * proto_tree * : protocol display tree to fill out. May be NULL
113 * int : offset into packet data where we are.
114 * int : length of clv we are decoding
117 * void, but we will add to proto tree if !NULL.
120 isis_dissect_instance_identifier_clv(proto_tree
*tree
, packet_info
* pinfo
, tvbuff_t
*tvb
,
121 expert_field
* expert
, int hf_iid
, int hf_supported_itid
, int offset
, int length
)
126 proto_tree_add_expert_format(tree
, pinfo
, expert
, tvb
, offset
, -1,
127 "short address (no length for payload)");
131 proto_tree_add_item(tree
, hf_iid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
135 while ( length
> 0 ) {
137 proto_tree_add_item(tree
, hf_supported_itid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
145 * Name: isis_dissect_authentication_clv()
148 * Take apart the CLV that hold authentication information. This
149 * is currently 1 octet auth type.
150 * the two defined authentication types
151 * are 1 for a clear text password,
152 * 54 for a HMAC-MD5 digest and
153 * 3 for CRYPTO_AUTH (rfc5310)
156 * tvbuff_t * : tvbuffer for packet data
157 * proto_tree * : protocol display tree to fill out. May be NULL
158 * int : offset into packet data where we are.
159 * int : length of clv we are decoding
162 * void, but we will add to proto tree if !NULL.
165 isis_dissect_authentication_clv(proto_tree
*tree
, packet_info
* pinfo
, tvbuff_t
*tvb
,
166 int hf_auth_bytes
, int hf_key_id
, expert_field
* auth_expert
, int offset
, int length
)
168 unsigned char pw_type
;
169 int auth_unsupported
;
170 const char *algorithm
= NULL
;
176 pw_type
= tvb_get_uint8(tvb
, offset
);
179 auth_unsupported
= false;
184 proto_tree_add_bytes_format( tree
, hf_auth_bytes
, tvb
, offset
, length
,
185 NULL
, "clear text (1), password (length %d) = %s", length
, tvb_format_text(pinfo
->pool
, tvb
, offset
, length
));
187 proto_tree_add_bytes_format( tree
, hf_auth_bytes
, tvb
, offset
, length
,
188 NULL
, "clear text (1), no clear-text password found!!!");
192 if ( length
== 16 ) {
193 proto_tree_add_bytes_format( tree
, hf_auth_bytes
, tvb
, offset
, length
,
194 NULL
, "hmac-md5 (54), message digest (length %d) = %s", length
, tvb_bytes_to_str(pinfo
->pool
, tvb
, offset
, length
));
196 proto_tree_add_bytes_format( tree
, hf_auth_bytes
, tvb
, offset
, length
,
197 NULL
, "hmac-md5 (54), illegal hmac-md5 digest format (must be 16 bytes)");
201 proto_tree_add_item(tree
, hf_key_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
204 algorithm
= try_val_to_str(length
, algorithm_vals
);
206 proto_tree_add_bytes_format( tree
, hf_auth_bytes
, tvb
, offset
, length
,
207 NULL
, "CRYPTO_AUTH %s (3), message digest (length %d) = %s", algorithm
,
208 length
, tvb_bytes_to_str(pinfo
->pool
, tvb
, offset
, length
));
210 proto_tree_add_bytes_format( tree
, hf_auth_bytes
, tvb
, offset
, length
,
211 NULL
, "CRYPTO_AUTH (3) illegal message digest format");
215 proto_tree_add_bytes_format( tree
, hf_auth_bytes
, tvb
, offset
, length
,
216 NULL
, "type 0x%02x (0x%02x)", pw_type
, length
);
217 auth_unsupported
=true;
221 if ( auth_unsupported
) {
222 proto_tree_add_expert(tree
, pinfo
, auth_expert
, tvb
, offset
, -1);
227 * Name: isis_dissect_hostname_clv()
230 * dump the hostname information found in TLV 137
231 * pls note that the hostname is not null terminated
234 * tvbuff_t * : tvbuffer for packet data
235 * proto_tree * : protocol display tree to fill out. May be NULL
236 * int : offset into packet data where we are.
237 * int : length of clv we are decoding
238 * int : tree id to use for proto tree.
241 * void, but we will add to proto tree if !NULL.
246 isis_dissect_hostname_clv(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
,
247 int length
, int tree_id
)
249 proto_item
* ti
= proto_tree_add_item( tree
, tree_id
, tvb
, offset
, length
, ENC_ASCII
|ENC_NA
);
251 proto_item_append_text(ti
, "--none--" );
259 isis_dissect_mt_clv(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, int offset
, int length
,
260 int tree_id
, expert_field
* mtid_expert
)
266 /* length can only be a multiple of 2, otherwise there is
267 something broken -> so decode down until length is 1 */
269 /* fetch two bytes */
270 mt_block
=tvb_get_ntohs(tvb
, offset
);
272 mt_desc
= val_to_str_const(mt_block
&0x0fff, mt_id_vals
, "Unknown");
273 proto_tree_add_uint_format ( tree
, tree_id
, tvb
, offset
, 2,
275 "%s Topology (0x%03x)%s%s",
278 (mt_block
&0x8000) ? ", Overload bit set" : "",
279 (mt_block
&0x4000) ? ", ATT bit set" : "" );
281 proto_tree_add_expert( tree
, pinfo
, mtid_expert
, tvb
, offset
, 1);
291 * Name: isis_dissect_ip_int_clv()
294 * Take apart the CLV that lists all the IP interfaces. The
295 * meaning of which is slightly different for the different base packet
296 * types, but the display is not different. What we have is n ip
297 * addresses, plain and simple.
300 * tvbuff_t * : tvbuffer for packet data
301 * proto_tree * : protocol display tree to fill out. May be NULL
302 * int : offset into packet data where we are.
303 * int : length of clv we are decoding
304 * int : tree id to use for proto tree.
307 * void, but we will add to proto tree if !NULL.
310 isis_dissect_ip_int_clv(proto_tree
*tree
, packet_info
* pinfo
, tvbuff_t
*tvb
, expert_field
* expert
,
311 int offset
, int length
, int tree_id
)
317 while ( length
> 0 ) {
319 proto_tree_add_expert_format(tree
, pinfo
, expert
, tvb
, offset
, -1,
320 "Short IP interface address (%d vs 4)",length
);
325 proto_tree_add_item(tree
, tree_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
333 * Name: isis_dissect_ipv6_int_clv()
336 * Take apart the CLV that lists all the IPv6 interfaces. The
337 * meaning of which is slightly different for the different base packet
338 * types, but the display is not different. What we have is n ip
339 * addresses, plain and simple.
342 * tvbuff_t * : tvbuffer for packet data
343 * proto_tree * : protocol display tree to fill out. May be NULL
344 * int : offset into packet data where we are.
345 * int : length of clv we are decoding
346 * int : tree id to use for proto tree.
349 * void, but we will add to proto tree if !NULL.
352 isis_dissect_ipv6_int_clv(proto_tree
*tree
, packet_info
* pinfo
, tvbuff_t
*tvb
, expert_field
* expert
,
353 int offset
, int length
, int tree_id
)
361 while ( length
> 0 ) {
363 proto_tree_add_expert_format(tree
, pinfo
, expert
, tvb
, offset
, -1,
364 "Short IPv6 interface address (%d vs 16)",length
);
367 tvb_get_ipv6(tvb
, offset
, &addr
);
369 proto_tree_add_ipv6(tree
, tree_id
, tvb
, offset
, 16, &addr
);
378 * Name: isis_dissect_te_router_id_clv()
381 * Display the Traffic Engineering Router ID TLV #134.
382 * This TLV is like the IP Interface TLV, except that
383 * only _one_ IP address is present
386 * tvbuff_t * : tvbuffer for packet data
387 * proto_tree * : protocol display tree to fill out. May be NULL
388 * int : offset into packet data where we are.
389 * int : length of clv we are decoding
390 * int : tree id to use for proto tree.
393 * void, but we will add to proto tree if !NULL.
396 isis_dissect_te_router_id_clv(proto_tree
*tree
, packet_info
* pinfo
, tvbuff_t
*tvb
, expert_field
* expert
,
397 int offset
, int length
, int tree_id
)
404 proto_tree_add_expert_format(tree
, pinfo
, expert
, tvb
, offset
, -1,
405 "malformed Traffic Engineering Router ID (%d vs 4)",length
);
409 proto_tree_add_item(tree
, tree_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
413 * Name: isis_dissect_nlpid_clv()
416 * Take apart a NLPID packet and display it. The NLPID (for integrated
417 * ISIS, contains n network layer protocol IDs that the box supports.
418 * We max out at 256 entries.
421 * tvbuff_t * : tvbuffer for packet data
422 * proto_tree * : protocol display tree to fill out. May be NULL
423 * int : offset into packet data where we are.
424 * int : length of clv we are decoding
427 * void, but we will add to proto tree if !NULL.
430 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
433 isis_dissect_nlpid_clv(tvbuff_t
*tvb
, proto_tree
*tree
, int ett_nlpid
, int hf_nlpid
, int offset
, int length
)
435 proto_tree
*nlpid_tree
;
440 proto_tree_add_subtree_format(tree
, tvb
, offset
, 0, ett_nlpid
, NULL
, "No NLPIDs");
442 nlpid_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, length
, ett_nlpid
, &ti
, "NLPID%s: ", PLURALIZE(length
));
443 while (length
-- > 0 ) {
444 nlpid
= tvb_get_uint8(tvb
, offset
);
445 proto_item_append_text(ti
, "%s (0x%02x)",
446 /* NLPID_IEEE_8021AQ conflicts with NLPID_SNDCF. In this context, we want the former. */
447 (nlpid
== NLPID_IEEE_8021AQ
? "IEEE 802.1aq (SPB)" : val_to_str_const(nlpid
, nlpid_vals
, "Unknown")),
450 proto_item_append_text(ti
, ", ");
452 proto_tree_add_uint(nlpid_tree
, hf_nlpid
, tvb
, offset
, 1, nlpid
);
459 * Name: isis_dissect_clvs()
462 * Dispatch routine to shred all the CLVs in a packet. We just
463 * walk through the clv entries in the packet. For each one, we
464 * search the passed in valid clv's for this protocol (opts) for
465 * a matching code. If found, we add to the display tree and
466 * then call the dissector. If it is not, we just post an
467 * "unknown" clv entry using the passed in unknown clv tree id.
470 * tvbuff_t * : tvbuffer for packet data
471 * packet_info * : packet_info for dissection
472 * proto_tree * : protocol display tree to fill out. May be NULL
473 * int : offset into packet data where we are.
474 * isis_clv_handle_t * : NULL dissector terminated array of codes
475 * and handlers (along with tree text and tree id's).
476 * expert_field * : expert info for short length
477 * isis_data_t * : data about the PDU from earlier headers
478 * int : unknown clv tree id
481 * void, but we will add to proto tree if !NULL.
484 isis_dissect_clvs(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, int offset
,
485 const isis_clv_handle_t
*opts
, expert_field
*expert_short_len
, isis_data_t
*isis
,
486 int unknown_tree_id _U_
, int tree_type
, int tree_length
, expert_field
*ei_unknown
)
488 unsigned len
= isis
->pdu_length
- isis
->header_length
; /* length of CLV area */
492 proto_tree
*clv_tree
;
495 code
= tvb_get_uint8(tvb
, offset
);
501 length
= tvb_get_uint8(tvb
, offset
);
507 if ( len
< length
) {
508 proto_tree_add_expert_format(tree
, pinfo
, expert_short_len
, tvb
, offset
, -1,
509 "Short CLV header (%d vs %d)",
514 while ((opts
[q
].dissect
!= NULL
)&&( opts
[q
].optcode
!= code
)){
517 if ( opts
[q
].dissect
) {
518 /* adjust by 2 for code/len octets */
519 clv_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
- 2,
520 length
+ 2, *opts
[q
].tree_id
, NULL
, "%s (t=%u, l=%u)",
521 opts
[q
].tree_text
, opts
[q
].optcode
, length
);
523 proto_tree_add_item(clv_tree
, tree_type
, tvb
, offset
- 2, 1, ENC_BIG_ENDIAN
);
524 proto_tree_add_item(clv_tree
, tree_length
, tvb
, offset
- 1, 1, ENC_BIG_ENDIAN
);
525 opts
[q
].dissect(tvb
, pinfo
, clv_tree
, offset
, isis
, length
);
527 clv_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
- 2,
528 length
+ 2, unknown_tree_id
, NULL
, "Unknown code (t=%u, l=%u)",
530 proto_tree_add_item(clv_tree
, tree_type
, tvb
, offset
- 2, 1, ENC_BIG_ENDIAN
);
531 proto_tree_add_item(clv_tree
, tree_length
, tvb
, offset
- 1, 1, ENC_BIG_ENDIAN
);
532 proto_tree_add_expert_format(clv_tree
, pinfo
, ei_unknown
, tvb
, offset
, length
, "Dissector for IS-IS CLV (%d)"
533 " code not implemented, Contact Wireshark developers if you want this supported", code
);
541 * Editor modelines - https://www.wireshark.org/tools/modelines.html
546 * indent-tabs-mode: nil
549 * vi: set shiftwidth=4 tabstop=8 expandtab:
550 * :indentSize=4:tabSize=8:noTabs=true: