Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-isis-clv.c
bloba415764d4e19eef730b6cdf1a2f199a4c5429632
1 /* packet-isis-clv.c
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
13 #include "config.h"
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[] = {
22 { 16, "hmac-md5" },
23 { 20, "hmac-sha1" },
24 { 28, "hmac-sha224" },
25 { 32, "hmac-sha256" },
26 { 48, "hmac-sha384" },
27 { 64, "hmac-sha512" },
28 { 0, NULL }
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" },
39 { 0, NULL }
43 * Name: isis_dissect_area_address_clv()
45 * Description:
46 * Take an area address CLV and display it pieces. An area address
47 * CLV is n, x byte hex strings.
49 * Input:
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
55 * Output:
56 * void, but we will add to proto tree if !NULL.
58 void
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)
62 int arealen,area_idx;
64 while ( length > 0 ) {
65 arealen = tvb_get_uint8(tvb, offset);
66 length--;
67 if (length<=0) {
68 proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1,
69 "short address (no length for payload)");
70 return;
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",
75 arealen, length );
76 return;
79 if ( tree ) {
80 proto_item *ti;
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()
110 * Input:
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
116 * Output:
117 * void, but we will add to proto tree if !NULL.
119 void
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)
124 length--;
125 if (length<=0) {
126 proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1,
127 "short address (no length for payload)");
128 return;
131 proto_tree_add_item(tree, hf_iid, tvb, offset, 2, ENC_BIG_ENDIAN);
132 offset += 2;
133 length -= 2;
135 while ( length > 0 ) {
137 proto_tree_add_item(tree, hf_supported_itid, tvb, offset, 2, ENC_BIG_ENDIAN);
138 offset += 2;
139 length -= 2;
145 * Name: isis_dissect_authentication_clv()
147 * Description:
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)
155 * Input:
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
161 * Output:
162 * void, but we will add to proto tree if !NULL.
164 void
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;
172 if ( length <= 0 ) {
173 return;
176 pw_type = tvb_get_uint8(tvb, offset);
177 offset += 1;
178 length--;
179 auth_unsupported = false;
181 switch (pw_type) {
182 case 1:
183 if ( length > 0 ) {
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));
186 } else {
187 proto_tree_add_bytes_format( tree, hf_auth_bytes, tvb, offset, length,
188 NULL, "clear text (1), no clear-text password found!!!");
190 break;
191 case 54:
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));
195 } else {
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)");
199 break;
200 case 3:
201 proto_tree_add_item(tree, hf_key_id, tvb, offset, 2, ENC_BIG_ENDIAN);
202 offset += 2;
203 length -= 2;
204 algorithm = try_val_to_str(length, algorithm_vals);
205 if ( algorithm ) {
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));
209 } else {
210 proto_tree_add_bytes_format( tree, hf_auth_bytes, tvb, offset, length,
211 NULL, "CRYPTO_AUTH (3) illegal message digest format");
213 break;
214 default:
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;
218 break;
221 if ( auth_unsupported ) {
222 proto_tree_add_expert(tree, pinfo, auth_expert, tvb, offset, -1);
227 * Name: isis_dissect_hostname_clv()
229 * Description:
230 * dump the hostname information found in TLV 137
231 * pls note that the hostname is not null terminated
233 * Input:
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.
240 * Output:
241 * void, but we will add to proto tree if !NULL.
245 void
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);
250 if ( length == 0 ) {
251 proto_item_append_text(ti, "--none--" );
258 void
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)
262 uint16_t mt_block;
263 const char *mt_desc;
265 while (length>0) {
266 /* length can only be a multiple of 2, otherwise there is
267 something broken -> so decode down until length is 1 */
268 if (length!=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,
274 mt_block,
275 "%s Topology (0x%03x)%s%s",
276 mt_desc,
277 mt_block&0xfff,
278 (mt_block&0x8000) ? ", Overload bit set" : "",
279 (mt_block&0x4000) ? ", ATT bit set" : "" );
280 } else {
281 proto_tree_add_expert( tree, pinfo, mtid_expert, tvb, offset, 1);
282 break;
284 length -= 2;
285 offset += 2;
291 * Name: isis_dissect_ip_int_clv()
293 * Description:
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.
299 * Input:
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.
306 * Output:
307 * void, but we will add to proto tree if !NULL.
309 void
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)
313 if ( length <= 0 ) {
314 return;
317 while ( length > 0 ) {
318 if ( length < 4 ) {
319 proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1,
320 "Short IP interface address (%d vs 4)",length );
321 return;
324 if ( tree ) {
325 proto_tree_add_item(tree, tree_id, tvb, offset, 4, ENC_BIG_ENDIAN);
327 offset += 4;
328 length -= 4;
333 * Name: isis_dissect_ipv6_int_clv()
335 * Description:
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.
341 * Input:
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.
348 * Output:
349 * void, but we will add to proto tree if !NULL.
351 void
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)
355 ws_in6_addr addr;
357 if ( length <= 0 ) {
358 return;
361 while ( length > 0 ) {
362 if ( length < 16 ) {
363 proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1,
364 "Short IPv6 interface address (%d vs 16)",length );
365 return;
367 tvb_get_ipv6(tvb, offset, &addr);
368 if ( tree ) {
369 proto_tree_add_ipv6(tree, tree_id, tvb, offset, 16, &addr);
371 offset += 16;
372 length -= 16;
378 * Name: isis_dissect_te_router_id_clv()
380 * Description:
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
385 * Input:
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.
392 * Output:
393 * void, but we will add to proto tree if !NULL.
395 void
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)
399 if ( length <= 0 ) {
400 return;
403 if ( length != 4 ) {
404 proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1,
405 "malformed Traffic Engineering Router ID (%d vs 4)",length );
406 return;
409 proto_tree_add_item(tree, tree_id, tvb, offset, 4, ENC_BIG_ENDIAN);
413 * Name: isis_dissect_nlpid_clv()
415 * Description:
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.
420 * Input:
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
426 * Output:
427 * void, but we will add to proto tree if !NULL.
430 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
432 void
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;
436 proto_item *ti;
437 uint8_t nlpid;
439 if (length <= 0) {
440 proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nlpid, NULL, "No NLPIDs");
441 } else {
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")),
448 nlpid);
449 if (length) {
450 proto_item_append_text(ti, ", ");
452 proto_tree_add_uint(nlpid_tree, hf_nlpid, tvb, offset, 1, nlpid);
453 offset++;
459 * Name: isis_dissect_clvs()
461 * Description:
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.
469 * Input:
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
480 * Output:
481 * void, but we will add to proto tree if !NULL.
483 void
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 */
489 uint8_t code;
490 uint8_t length;
491 int q;
492 proto_tree *clv_tree;
494 while ( len != 0 ) {
495 code = tvb_get_uint8(tvb, offset);
496 offset += 1;
497 len -= 1;
498 if (len == 0)
499 break;
501 length = tvb_get_uint8(tvb, offset);
502 offset += 1;
503 len -= 1;
504 if (len == 0)
505 break;
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)",
510 length, len );
511 return;
513 q = 0;
514 while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
515 q++;
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);
526 } else {
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)",
529 code, length);
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);
535 offset += length;
536 len -= length;
541 * Editor modelines - https://www.wireshark.org/tools/modelines.html
543 * Local variables:
544 * c-basic-offset: 4
545 * tab-width: 8
546 * indent-tabs-mode: nil
547 * End:
549 * vi: set shiftwidth=4 tabstop=8 expandtab:
550 * :indentSize=4:tabSize=8:noTabs=true: