2 * Common CLV decode routines.
5 * Stuart Stanley <stuarts@mxmail.net>
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <epan/packet.h>
35 #include <epan/emem.h>
36 #include "packet-osi.h"
37 #include "packet-isis.h"
38 #include "packet-isis-clv.h"
39 #include <epan/nlpid.h>
42 * Name: isis_dissect_area_address_clv()
45 * Take an area address CLV and display it pieces. An area address
46 * CLV is n, x byte hex strings.
49 * tvbuff_t * : tvbuffer for packet data
50 * proto_tree * : protocol display tree to fill out. May be NULL
51 * int : offset into packet data where we are.
52 * int : length of clv we are decoding
55 * void, but we will add to proto tree if !NULL.
58 isis_dissect_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
63 while ( length > 0 ) {
64 arealen = tvb_get_guint8(tvb, offset);
67 isis_dissect_unknown(tvb, tree, offset,
68 "short address (no length for payload)");
71 if ( arealen > length) {
72 isis_dissect_unknown(tvb, tree, offset,
73 "short address, packet says %d, we have %d left",
82 * Throw an exception rather than putting in a
85 tvb_ensure_bytes_exist ( tvb, offset, arealen + 1 );
87 ti = proto_tree_add_text ( tree, tvb, offset, arealen + 1,
88 "Area address (%d): ", arealen );
91 * Lets turn the area address into "standard"
92 * xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx format string.
93 * this is a private routine as the print_nsap_net in
94 * epan/osi_utils.c is incomplete and we need only
95 * a subset - actually some nice placing of dots ....
97 for (area_idx = 0; area_idx < arealen; area_idx++) {
98 proto_item_append_text(ti, "%02x",
99 tvb_get_guint8(tvb, offset+area_idx+1));
100 if (((area_idx & 1) == 0) &&
101 (area_idx + 1 < arealen)) {
102 proto_item_append_text(ti, ".");
106 offset += arealen + 1;
107 length -= arealen; /* length already adjusted for len fld*/
113 * Name: isis_dissect_authentication_clv()
116 * Take apart the CLV that hold authentication information. This
117 * is currently 1 octet auth type.
118 * the two defined authentication types
119 * are 1 for a clear text password and
120 * 54 for a HMAC-MD5 digest
123 * tvbuff_t * : tvbuffer for packet data
124 * proto_tree * : protocol display tree to fill out. May be NULL
125 * int : offset into packet data where we are.
126 * int : length of clv we are decoding
129 * void, but we will add to proto tree if !NULL.
132 isis_dissect_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
136 int auth_unsupported;
143 pw_type = tvb_get_guint8(tvb, offset);
146 auth_unsupported = FALSE;
150 ti = proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
151 "clear text (1), password (length %d) = ", length);
153 proto_item_append_text(ti, "%s",
154 tvb_format_text(tvb, offset, length));
156 proto_item_append_text(ti, "no clear-text password found!!!");
160 ti = proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
161 "hmac-md5 (54), password (length %d) = ", length);
163 if ( length == 16 ) {
164 proto_item_append_text(ti, "0x%02x", tvb_get_guint8(tvb, offset));
168 proto_item_append_text(ti, "%02x", tvb_get_guint8(tvb, offset));
173 proto_item_append_text(ti,
174 "illegal hmac-md5 digest format (must be 16 bytes)");
178 ti = proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
179 "type 0x%02x (0x%02x): ", pw_type, length );
180 auth_unsupported=TRUE;
184 if ( auth_unsupported ) {
185 isis_dissect_unknown(tvb, tree, offset,
186 "Unknown authentication type" );
191 * Name: isis_ip_authentication_clv()
194 * dump the IP authentication information found in TLV 133
195 * the CLV is standardized in rf1195, however all major
196 * implementations use TLV #10
198 * tvbuff_t * : tvbuffer for packet data
199 * proto_tree * : protocol display tree to fill out. May be NULL
200 * int : offset into packet data where we are.
201 * int : length of clv we are decoding
204 * void, but we will add to proto tree if !NULL.
209 isis_dissect_ip_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
212 if ( !tree ) return; /* nothing to do! */
215 proto_tree_add_text ( tree, tvb, offset, length,
216 "IP Authentication: %.*s", length,
217 tvb_get_ptr(tvb, offset, length) );
223 * Name: isis_dissect_hostname_clv()
226 * dump the hostname information found in TLV 137
227 * pls note that the hostname is not null terminated
230 * tvbuff_t * : tvbuffer for packet data
231 * proto_tree * : protocol display tree to fill out. May be NULL
232 * int : offset into packet data where we are.
233 * int : length of clv we are decoding
236 * void, but we will add to proto tree if !NULL.
241 isis_dissect_hostname_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
244 if ( !tree ) return; /* nothing to do! */
247 proto_tree_add_text ( tree, tvb, offset, length,
248 "Hostname: --none--" );
250 proto_tree_add_text ( tree, tvb, offset, length,
251 "Hostname: %.*s", length,
252 tvb_get_ptr(tvb, offset, length) );
260 isis_dissect_mt_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length,
267 /* length can only be a multiple of 2, otherwise there is
268 something broken -> so decode down until length is 1 */
270 /* fetch two bytes */
271 mt_block=tvb_get_ntohs(tvb, offset);
273 /* mask out the lower 12 bits */
274 switch(mt_block&0x0fff) {
276 mt_desc="IPv4 unicast";
279 mt_desc="In-Band Management";
282 mt_desc="IPv6 unicast";
288 mt_desc="Development, Experimental or Proprietary";
291 mt_desc="Reserved for IETF Consensus";
294 proto_tree_add_uint_format ( tree, tree_id, tvb, offset, 2,
296 "%s Topology (0x%03x)%s%s",
299 (mt_block&0x8000) ? "" : ", no sub-TLVs present",
300 (mt_block&0x4000) ? ", ATT bit set" : "" );
302 proto_tree_add_text ( tree, tvb, offset, 1,
313 * Name: isis_dissect_ip_int_clv()
316 * Take apart the CLV that lists all the IP interfaces. The
317 * meaning of which is slightly different for the different base packet
318 * types, but the display is not different. What we have is n ip
319 * addresses, plain and simple.
322 * tvbuff_t * : tvbuffer for packet data
323 * proto_tree * : protocol display tree to fill out. May be NULL
324 * int : offset into packet data where we are.
325 * int : length of clv we are decoding
326 * int : tree id to use for proto tree.
329 * void, but we will add to proto tree if !NULL.
332 isis_dissect_ip_int_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
333 int length, int tree_id)
339 while ( length > 0 ) {
341 isis_dissect_unknown(tvb, tree, offset,
342 "Short IP interface address (%d vs 4)",length );
347 proto_tree_add_item(tree, tree_id, tvb, offset, 4, FALSE);
355 * Name: isis_dissect_ipv6_int_clv()
358 * Take apart the CLV that lists all the IPv6 interfaces. The
359 * meaning of which is slightly different for the different base packet
360 * types, but the display is not different. What we have is n ip
361 * addresses, plain and simple.
364 * tvbuff_t * : tvbuffer for packet data
365 * proto_tree * : protocol display tree to fill out. May be NULL
366 * int : offset into packet data where we are.
367 * int : length of clv we are decoding
368 * int : tree id to use for proto tree.
371 * void, but we will add to proto tree if !NULL.
374 isis_dissect_ipv6_int_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
375 int length, int tree_id)
383 while ( length > 0 ) {
385 isis_dissect_unknown(tvb, tree, offset,
386 "Short IPv6 interface address (%d vs 16)",length );
389 tvb_memcpy(tvb, addr, offset, sizeof(addr));
391 proto_tree_add_ipv6(tree, tree_id, tvb, offset, 16, addr);
400 * Name: isis_dissect_te_router_id_clv()
403 * Display the Traffic Engineering Router ID TLV #134.
404 * This TLV is like the IP Interface TLV, except that
405 * only _one_ IP address is present
408 * tvbuff_t * : tvbuffer for packet data
409 * proto_tree * : protocol display tree to fill out. May be NULL
410 * int : offset into packet data where we are.
411 * int : length of clv we are decoding
412 * int : tree id to use for proto tree.
415 * void, but we will add to proto tree if !NULL.
418 isis_dissect_te_router_id_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
419 int length, int tree_id)
426 isis_dissect_unknown(tvb, tree, offset,
427 "malformed Traffic Engineering Router ID (%d vs 4)",length );
431 proto_tree_add_item(tree, tree_id, tvb, offset, 4, FALSE);
436 * Name: isis_dissect_nlpid_clv()
439 * Take apart a NLPID packet and display it. The NLPID (for intergrated
440 * ISIS, contains n network layer protocol IDs that the box supports.
441 * We max out at 256 entries.
444 * tvbuff_t * : tvbuffer for packet data
445 * proto_tree * : protocol display tree to fill out. May be NULL
446 * int : offset into packet data where we are.
447 * int : length of clv we are decoding
450 * void, but we will add to proto tree if !NULL.
453 #define TRUNCATED_TEXT " [truncated]"
455 isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length)
460 if ( !tree ) return; /* nothing to do! */
463 * Throw an exception rather than putting in a
466 tvb_ensure_bytes_exist ( tvb, offset, length );
469 proto_tree_add_text (tree, tvb, offset, length,
470 "NLPID(s): --none--");
473 ti = proto_tree_add_text (tree, tvb, offset, length,
475 while (length-- > 0 ) {
477 proto_item_append_text(ti, ", ");
479 proto_item_append_text(ti, "%s (0x%02x)",
480 val_to_str(tvb_get_guint8(tvb, offset), nlpid_vals,
481 "Unknown"), tvb_get_guint8(tvb, offset));
489 * Name: isis_dissect_clvs()
492 * Dispatch routine to shred all the CLVs in a packet. We just
493 * walk through the clv entries in the packet. For each one, we
494 * search the passed in valid clv's for this protocol (opts) for
495 * a matching code. If found, we add to the display tree and
496 * then call the dissector. If it is not, we just post an
497 * "unknown" clv entry using the passed in unknown clv tree id.
500 * tvbuff_t * : tvbuffer for packet data
501 * proto_tree * : protocol display tree to fill out. May be NULL
502 * int : offset into packet data where we are.
503 * isis_clv_handle_t * : NULL dissector terminated array of codes
504 * and handlers (along with tree text and tree id's).
505 * int : length of CLV area.
506 * int : length of IDs in packet.
507 * int : unknown clv tree id
510 * void, but we will add to proto tree if !NULL.
513 isis_dissect_clvs(tvbuff_t *tvb, proto_tree *tree, int offset,
514 const isis_clv_handle_t *opts, int len, int id_length,
521 proto_tree *clv_tree;
525 code = tvb_get_guint8(tvb, offset);
528 length = tvb_get_guint8(tvb, offset);
531 adj = (sizeof(code) + sizeof(length) + length);
534 isis_dissect_unknown(tvb, tree, offset,
535 "Short CLV header (%d vs %d)",
540 while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
543 if ( opts[q].dissect ) {
545 /* adjust by 2 for code/len octets */
546 ti = proto_tree_add_text(tree, tvb, offset - 2,
547 length + 2, "%s (%u)",
548 opts[q].tree_text, length );
549 clv_tree = proto_item_add_subtree(ti,
554 opts[q].dissect(tvb, clv_tree, offset,
558 ti = proto_tree_add_text(tree, tvb, offset - 2,
559 length + 2, "Unknown code %u (%u)",
561 clv_tree = proto_item_add_subtree(ti,