2 * Common CLV decode routines.
4 * $Id: packet-isis-clv.c,v 1.28 2003/06/04 08:46:35 guy 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 #include <epan/packet.h>
35 #include "packet-osi.h"
36 #include "packet-isis.h"
37 #include "packet-isis-clv.h"
41 free_g_string(void *arg)
43 g_string_free(arg, TRUE);
47 * Name: isis_dissect_area_address_clv()
50 * Take an area address CLV and display it pieces. An area address
51 * CLV is n, x byte hex strings.
54 * tvbuff_t * : tvbuffer for packet data
55 * proto_tree * : protocol display tree to fill out. May be NULL
56 * int : offset into packet data where we are.
57 * int : length of clv we are decoding
60 * void, but we will add to proto tree if !NULL.
63 isis_dissect_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
69 while ( length > 0 ) {
70 arealen = tvb_get_guint8(tvb, offset);
73 isis_dissect_unknown(tvb, tree, offset,
74 "short address (no length for payload)");
77 if ( arealen > length) {
78 isis_dissect_unknown(tvb, tree, offset,
79 "short address, packet says %d, we have %d left",
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 * We pick an initial size of 32 bytes.
94 gstr = g_string_sized_new(32);
97 * Free the GString if we throw an exception.
99 CLEANUP_PUSH(free_g_string, gstr);
101 for (area_idx = 0; area_idx < arealen; area_idx++) {
102 g_string_sprintfa(gstr, "%02x",
103 tvb_get_guint8(tvb, offset+area_idx+1));
104 if (((area_idx & 1) == 0) &&
105 (area_idx + 1 < arealen)) {
106 g_string_sprintfa(gstr, ".");
110 /* and spit it out */
111 proto_tree_add_text ( tree, tvb, offset, arealen + 1,
112 "Area address (%d): %s", arealen, gstr->str );
115 * We're done with the GString, so delete it and
116 * get rid of the cleanup handler.
118 CLEANUP_CALL_AND_POP;
120 offset += arealen + 1;
121 length -= arealen; /* length already adjusted for len fld*/
127 * Name: isis_dissect_authentication_clv()
130 * Take apart the CLV that hold authentication information. This
131 * is currently 1 octet auth type (which must be 1) and then
132 * the clear text password.
134 * An ISIS password has different meaning depending where it
135 * is found. Thus we support a passed in prefix string to
139 * tvbuff_t * : tvbuffer for packet data
140 * proto_tree * : protocol display tree to fill out. May be NULL
141 * int : offset into packet data where we are.
142 * int : length of clv we are decoding
143 * char * : Password meaning
146 * void, but we will add to proto tree if !NULL.
149 isis_dissect_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
150 int length, char *meaning)
153 int auth_unsupported;
160 pw_type = tvb_get_guint8(tvb, offset);
163 auth_unsupported = FALSE;
165 gstr = g_string_new("");
168 * Free the GString if we throw an exception.
170 CLEANUP_PUSH(free_g_string, gstr);
174 g_string_sprintfa(gstr,
175 "clear text (1), password (length %d) = ", length);
177 g_string_sprintfa(gstr, "%s",
178 tvb_format_text(tvb, offset, length));
180 g_string_append(gstr, "no clear-text password found!!!");
184 g_string_sprintfa(gstr,
185 "hmac-md5 (54), password (length %d) = ", length);
187 if ( length == 16 ) {
188 g_string_sprintfa(gstr, "0x%02x", tvb_get_guint8(tvb, offset));
192 g_string_sprintfa(gstr, "%02x", tvb_get_guint8(tvb, offset));
197 g_string_append(gstr,
198 "illegal hmac-md5 digest format (must be 16 bytes)");
202 g_string_sprintfa(gstr, "type 0x%02x (0x%02x): ", pw_type, length );
203 auth_unsupported=TRUE;
207 proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
208 "%s %s", meaning, gstr->str );
211 * We're done with the GString, so delete it and get rid of
212 * the cleanup handler.
214 CLEANUP_CALL_AND_POP;
216 if ( auth_unsupported ) {
217 isis_dissect_unknown(tvb, tree, offset,
218 "Unknown authentication type" );
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 strcpy(mt_desc,"IPv4 unicast");
279 strcpy(mt_desc,"In-Band Management");
282 strcpy(mt_desc,"IPv6 unicast");
285 strcpy(mt_desc,"Multicast");
288 strcpy(mt_desc,"Development, Experimental or Proprietary");
291 strcpy(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 * Our display buffer we use is upto 255 entries, 6 bytes per (0x00, )
442 * plus 1 for zero termination. We just just 256*6 for simplicity.
445 * tvbuff_t * : tvbuffer for packet data
446 * proto_tree * : protocol display tree to fill out. May be NULL
447 * int : offset into packet data where we are.
448 * int : length of clv we are decoding
451 * void, but we will add to proto tree if !NULL.
454 isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length)
459 int old_offset = offset;
461 if ( !tree ) return; /* nothing to do! */
463 while ( length-- > 0 ) {
465 s += sprintf ( s, ", " );
467 s += sprintf ( s, "%s (0x%02x)",
468 val_to_str(tvb_get_guint8(tvb, offset), nlpid_vals,
469 "Unknown"), tvb_get_guint8(tvb, offset));
474 sprintf ( sbuf, "--none--" );
477 proto_tree_add_text ( tree, tvb, old_offset, hlen,
478 "NLPID(s): %s", sbuf );
482 * Name: isis_dissect_clvs()
485 * Dispatch routine to shred all the CLVs in a packet. We just
486 * walk through the clv entries in the packet. For each one, we
487 * search the passed in valid clv's for this protocol (opts) for
488 * a matching code. If found, we add to the display tree and
489 * then call the dissector. If it is not, we just post an
490 * "unknown" clv entry using the passed in unknown clv tree id.
493 * tvbuff_t * : tvbuffer for packet data
494 * proto_tree * : protocol display tree to fill out. May be NULL
495 * int : offset into packet data where we are.
496 * isis_clv_handle_t * : NULL dissector terminated array of codes
497 * and handlers (along with tree text and tree id's).
498 * int : length of CLV area.
499 * int : length of IDs in packet.
500 * int : unknown clv tree id
503 * void, but we will add to proto tree if !NULL.
506 isis_dissect_clvs(tvbuff_t *tvb, proto_tree *tree, int offset,
507 const isis_clv_handle_t *opts, int len, int id_length,
514 proto_tree *clv_tree;
518 code = tvb_get_guint8(tvb, offset);
521 length = tvb_get_guint8(tvb, offset);
524 adj = (sizeof(code) + sizeof(length) + length);
527 isis_dissect_unknown(tvb, tree, offset,
528 "Short CLV header (%d vs %d)",
533 while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
536 if ( opts[q].dissect ) {
538 /* adjust by 2 for code/len octets */
539 ti = proto_tree_add_text(tree, tvb, offset - 2,
540 length + 2, "%s (%u)",
541 opts[q].tree_text, length );
542 clv_tree = proto_item_add_subtree(ti,
547 opts[q].dissect(tvb, clv_tree, offset,
551 ti = proto_tree_add_text(tree, tvb, offset - 2,
552 length + 2, "Unknown code %u (%u)",
554 clv_tree = proto_item_add_subtree(ti,