2 * Common CLV decode routines.
4 * $Id: packet-isis-clv.c,v 1.23 2002/08/28 21:00:18 jmayer Exp $
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 #ifdef NEED_SNPRINTF_H
35 # include "snprintf.h"
38 #include <epan/packet.h>
39 #include "packet-osi.h"
40 #include "packet-isis.h"
41 #include "packet-isis-clv.h"
45 free_g_string(void *arg)
47 g_string_free(arg, TRUE);
51 * Name: isis_dissect_area_address_clv()
54 * Take an area address CLV and display it pieces. An area address
55 * CLV is n, x byte hex strings.
58 * tvbuff_t * : tvbuffer for packet data
59 * proto_tree * : protocol display tree to fill out. May be NULL
60 * int : offset into packet data where we are.
61 * int : length of clv we are decoding
64 * void, but we will add to proto tree if !NULL.
67 isis_dissect_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
73 while ( length > 0 ) {
74 arealen = tvb_get_guint8(tvb, offset);
77 isis_dissect_unknown(tvb, tree, offset,
78 "short address (no length for payload)");
81 if ( arealen > length) {
82 isis_dissect_unknown(tvb, tree, offset,
83 "short address, packet says %d, we have %d left",
90 * Lets turn the area address into "standard"
91 * xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx format string.
92 * this is a private routine as the print_nsap_net in
93 * epan/osi_utils.c is incomplete and we need only
94 * a subset - actually some nice placing of dots ....
96 * We pick an initial size of 32 bytes.
98 gstr = g_string_sized_new(32);
101 * Free the GString if we throw an exception.
103 CLEANUP_PUSH(free_g_string, gstr);
105 for (area_idx = 0; area_idx < arealen; area_idx++) {
106 g_string_sprintfa(gstr, "%02x",
107 tvb_get_guint8(tvb, offset+area_idx+1));
108 if (((area_idx & 1) == 0) &&
109 (area_idx + 1 < arealen)) {
110 g_string_sprintfa(gstr, ".");
114 /* and spit it out */
115 proto_tree_add_text ( tree, tvb, offset, arealen + 1,
116 "Area address (%d): %s", arealen, gstr->str );
119 * We're done with the GString, so delete it and
120 * get rid of the cleanup handler.
122 CLEANUP_CALL_AND_POP;
124 offset += arealen + 1;
125 length -= arealen; /* length already adjusted for len fld*/
131 * Name: isis_dissect_authentication_clv()
134 * Take apart the CLV that hold authentication information. This
135 * is currently 1 octet auth type (which must be 1) and then
136 * the clear text password.
138 * An ISIS password has different meaning depending where it
139 * is found. Thus we support a passed in prefix string to
143 * tvbuff_t * : tvbuffer for packet data
144 * proto_tree * : protocol display tree to fill out. May be NULL
145 * int : offset into packet data where we are.
146 * int : length of clv we are decoding
147 * char * : Password meaning
150 * void, but we will add to proto tree if !NULL.
153 isis_dissect_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
154 int length, char *meaning)
157 char sbuf[300]; /* 255 + header info area */
159 int auth_unsupported;
165 pw_type = tvb_get_guint8(tvb, offset);
168 auth_unsupported = FALSE;
172 s += sprintf ( s, "clear text (1), password (length %d) = ", length );
175 strncpy(s, tvb_get_ptr(tvb, offset, length), length);
178 strcat(s, "no clear-text password found!!!" );
182 s += sprintf ( s, "hmac-md5 (54), password (length %d) = ", length );
184 if ( length == 16 ) {
185 s += sprintf ( s, "0x%02x", tvb_get_guint8(tvb, offset) );
189 s += sprintf ( s, "%02x", tvb_get_guint8(tvb, offset) );
195 strcat(s, "illegal hmac-md5 digest format (must be 16 bytes)" );
199 s += sprintf ( s, "type 0x%02x (0x%02x): ", pw_type, length );
200 auth_unsupported=TRUE;
204 proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
205 "%s %s", meaning, sbuf );
207 if ( auth_unsupported ) {
208 isis_dissect_unknown(tvb, tree, offset,
209 "Unknown authentication type" );
214 * Name: isis_dissect_hostname_clv()
217 * dump the hostname information found in TLV 137
218 * pls note that the hostname is not null terminated
221 * tvbuff_t * : tvbuffer for packet data
222 * proto_tree * : protocol display tree to fill out. May be NULL
223 * int : offset into packet data where we are.
224 * int : length of clv we are decoding
227 * void, but we will add to proto tree if !NULL.
232 isis_dissect_hostname_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
235 if ( !tree ) return; /* nothing to do! */
238 proto_tree_add_text ( tree, tvb, offset, length,
239 "Hostname: --none--" );
241 proto_tree_add_text ( tree, tvb, offset, length,
242 "Hostname: %.*s", length,
243 tvb_get_ptr(tvb, offset, length) );
251 isis_dissect_mt_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length,
258 /* length can only be a multiple of 2, otherwise there is
259 something broken -> so decode down until length is 1 */
261 /* fetch two bytes */
262 mt_block=tvb_get_ntohs(tvb, offset);
264 /* mask out the lower 12 bits */
265 switch(mt_block&0x0fff) {
267 strcpy(mt_desc,"IPv4 unicast");
270 strcpy(mt_desc,"In-Band Management");
273 strcpy(mt_desc,"IPv6 unicast");
276 strcpy(mt_desc,"Multicast");
279 strcpy(mt_desc,"Development, Experimental or Proprietary");
282 strcpy(mt_desc,"Reserved for IETF Consensus");
285 proto_tree_add_uint_format ( tree, tree_id, tvb, offset, 2,
287 "%s Topology (0x%03x)%s%s",
290 (mt_block&0x8000) ? "" : ", no sub-TLVs present",
291 (mt_block&0x4000) ? ", ATT bit set" : "" );
293 proto_tree_add_text ( tree, tvb, offset, 1,
304 * Name: isis_dissect_ip_int_clv()
307 * Take apart the CLV that lists all the IP interfaces. The
308 * meaning of which is slightly different for the different base packet
309 * types, but the display is not different. What we have is n ip
310 * addresses, plain and simple.
313 * tvbuff_t * : tvbuffer for packet data
314 * proto_tree * : protocol display tree to fill out. May be NULL
315 * int : offset into packet data where we are.
316 * int : length of clv we are decoding
317 * int : tree id to use for proto tree.
320 * void, but we will add to proto tree if !NULL.
323 isis_dissect_ip_int_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
324 int length, int tree_id)
330 while ( length > 0 ) {
332 isis_dissect_unknown(tvb, tree, offset,
333 "Short IP interface address (%d vs 4)",length );
338 proto_tree_add_item(tree, tree_id, tvb, offset, 4, FALSE);
346 * Name: isis_dissect_ipv6_int_clv()
349 * Take apart the CLV that lists all the IPv6 interfaces. The
350 * meaning of which is slightly different for the different base packet
351 * types, but the display is not different. What we have is n ip
352 * addresses, plain and simple.
355 * tvbuff_t * : tvbuffer for packet data
356 * proto_tree * : protocol display tree to fill out. May be NULL
357 * int : offset into packet data where we are.
358 * int : length of clv we are decoding
359 * int : tree id to use for proto tree.
362 * void, but we will add to proto tree if !NULL.
365 isis_dissect_ipv6_int_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
366 int length, int tree_id)
374 while ( length > 0 ) {
376 isis_dissect_unknown(tvb, tree, offset,
377 "Short IPv6 interface address (%d vs 16)",length );
380 tvb_memcpy(tvb, addr, offset, sizeof(addr));
382 proto_tree_add_ipv6(tree, tree_id, tvb, offset, 16, addr);
391 * Name: isis_dissect_te_router_id_clv()
394 * Display the Traffic Engineering Router ID TLV #134.
395 * This TLV is like the IP Interface TLV, except that
396 * only _one_ IP address is present
399 * tvbuff_t * : tvbuffer for packet data
400 * proto_tree * : protocol display tree to fill out. May be NULL
401 * int : offset into packet data where we are.
402 * int : length of clv we are decoding
403 * int : tree id to use for proto tree.
406 * void, but we will add to proto tree if !NULL.
409 isis_dissect_te_router_id_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
410 int length, int tree_id)
417 isis_dissect_unknown(tvb, tree, offset,
418 "malformed Traffic Engineering Router ID (%d vs 4)",length );
422 proto_tree_add_item(tree, tree_id, tvb, offset, 4, FALSE);
427 * Name: isis_dissect_nlpid_clv()
430 * Take apart a NLPID packet and display it. The NLPID (for intergrated
431 * ISIS, contains n network layer protocol IDs that the box supports.
432 * Our display buffer we use is upto 255 entries, 6 bytes per (0x00, )
433 * plus 1 for zero termination. We just just 256*6 for simplicity.
436 * tvbuff_t * : tvbuffer for packet data
437 * proto_tree * : protocol display tree to fill out. May be NULL
438 * int : offset into packet data where we are.
439 * int : length of clv we are decoding
442 * void, but we will add to proto tree if !NULL.
445 isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length)
450 int old_offset = offset;
452 if ( !tree ) return; /* nothing to do! */
454 while ( length-- > 0 ) {
456 s += sprintf ( s, ", " );
458 s += sprintf ( s, "%s (0x%02x)",
459 val_to_str(tvb_get_guint8(tvb, offset), nlpid_vals,
460 "Unknown"), tvb_get_guint8(tvb, offset));
465 sprintf ( sbuf, "--none--" );
468 proto_tree_add_text ( tree, tvb, old_offset, hlen,
469 "NLPID(s): %s", sbuf );
473 * Name: isis_dissect_clvs()
476 * Dispatch routine to shred all the CLVs in a packet. We just
477 * walk through the clv entries in the packet. For each one, we
478 * search the passed in valid clv's for this protocol (opts) for
479 * a matching code. If found, we add to the display tree and
480 * then call the dissector. If it is not, we just post an
481 * "unknown" clv entry using the passed in unknown clv tree id.
484 * tvbuff_t * : tvbuffer for packet data
485 * proto_tree * : protocol display tree to fill out. May be NULL
486 * int : offset into packet data where we are.
487 * isis_clv_handle_t * : NULL dissector terminated array of codes
488 * and handlers (along with tree text and tree id's).
489 * int : length of CLV area.
490 * int : length of IDs in packet.
491 * int : unknown clv tree id
494 * void, but we will add to proto tree if !NULL.
497 isis_dissect_clvs(tvbuff_t *tvb, proto_tree *tree, int offset,
498 const isis_clv_handle_t *opts, int len, int id_length,
505 proto_tree *clv_tree;
510 code = tvb_get_guint8(tvb, offset);
513 length = tvb_get_guint8(tvb, offset);
516 adj = (sizeof(code) + sizeof(length) + length);
519 isis_dissect_unknown(tvb, tree, offset,
520 "Short CLV header (%d vs %d)",
525 while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
528 if ( opts[q].dissect ) {
530 /* adjust by 2 for code/len octets */
531 snprintf ( sbuf, sizeof(sbuf), "%s (%d)",
532 opts[q].tree_text, length );
533 ti = proto_tree_add_text(tree, tvb, offset - 2,
535 clv_tree = proto_item_add_subtree(ti,
540 opts[q].dissect(tvb, clv_tree, offset,
544 snprintf ( sbuf, sizeof(sbuf),
545 "Unknown code (%d:%d)", code, length );
546 ti = proto_tree_add_text(tree, tvb, offset - 2,
548 clv_tree = proto_item_add_subtree(ti,