2 * Common CLV decode routines.
4 * $Id: packet-isis-clv.c,v 1.15 2001/08/22 18:00:40 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.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
40 #ifdef NEED_SNPRINTF_H
41 # include "snprintf.h"
45 #include "packet-osi.h"
46 #include "packet-isis.h"
47 #include "packet-isis-clv.h"
52 * Name: isis_dissect_area_address_clv()
55 * Take an area address CLV and display it pieces. An area address
56 * CLV is n, x byte hex strings.
59 * tvbuff_t * : tvbuffer for packet data
60 * packet_info * : info for current packet
61 * proto_tree * : protocol display tree to fill out. May be NULL
62 * int : offset into packet data where we are.
63 * int : length of clv we are decoding
66 * void, but we will add to proto tree if !NULL.
69 isis_dissect_area_address_clv(tvbuff_t *tvb, packet_info *pinfo,
70 proto_tree *tree, int offset, int length)
75 while ( length > 0 ) {
76 mylen = tvb_get_guint8(tvb, offset);
79 isis_dissect_unknown(tvb, pinfo, tree, offset,
80 "short address (no length for payload)");
83 if ( mylen > length) {
84 isis_dissect_unknown(tvb, pinfo, tree, offset,
85 "short address, packet say %d, we have %d left",
91 * Lets turn the area address into "standard" 0000.0000.etc
94 /* sbuf = isis_address_to_string ( tvb, offset + 1, mylen );*/
95 sbuf = print_nsap_net( tvb_get_ptr(tvb, offset + 1, mylen), mylen );
98 proto_tree_add_text ( tree, tvb, offset, mylen + 1,
99 "Area address (%d): %s", mylen, sbuf );
102 length -= mylen; /* length already adjusted for len fld*/
108 * Name: isis_dissect_authentication_clv()
111 * Take apart the CLV that hold authentication information. This
112 * is currently 1 octet auth type (which must be 1) and then
113 * the clear text password.
115 * An ISIS password has different meaning depending where it
116 * is found. Thus we support a passed in prefix string to
120 * tvbuff_t * : tvbuffer for packet data
121 * packet_info * : info for current packet
122 * proto_tree * : protocol display tree to fill out. May be NULL
123 * int : offset into packet data where we are.
124 * int : length of clv we are decoding
125 * char * : Password meaning
128 * void, but we will add to proto tree if !NULL.
131 isis_dissect_authentication_clv(tvbuff_t *tvb, packet_info *pinfo,
132 proto_tree *tree, int offset, int length, char *meaning)
135 char sbuf[300]; /* 255 + header info area */
137 int auth_unsupported;
143 pw_type = tvb_get_guint8(tvb, offset);
146 auth_unsupported = FALSE;
150 s += sprintf ( s, "clear text (1), password (length %d) = ", length );
153 strncpy(s, tvb_get_ptr(tvb, offset, length), length);
156 strcat(s, "no clear-text password found!!!" );
160 s += sprintf ( s, "hmac-md5 (54), password (length %d) = ", length );
162 if ( length == 16 ) {
163 s += sprintf ( s, "0x%02x", tvb_get_guint8(tvb, offset) );
167 s += sprintf ( s, "%02x", tvb_get_guint8(tvb, offset) );
173 strcat(s, "illegal hmac-md5 digest format (must be 16 bytes)" );
177 s += sprintf ( s, "type 0x%02x (0x%02x): ", pw_type, length );
178 auth_unsupported=TRUE;
182 proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
183 "%s %s", meaning, sbuf );
185 if ( auth_unsupported ) {
186 isis_dissect_unknown(tvb, pinfo, tree, offset,
187 "Unknown authentication type" );
192 * Name: isis_dissect_hostname_clv()
195 * dump the hostname information found in TLV 137
196 * pls note that the hostname is not null terminated
199 * tvbuff_t * : tvbuffer for packet data
200 * packet_info * : info for current packet
201 * proto_tree * : protocol display tree to fill out. May be NULL
202 * int : offset into packet data where we are.
203 * int : length of clv we are decoding
206 * void, but we will add to proto tree if !NULL.
211 isis_dissect_hostname_clv(tvbuff_t *tvb, packet_info *pinfo,
212 proto_tree *tree, int offset, int length)
214 if ( !tree ) return; /* nothing to do! */
217 proto_tree_add_text ( tree, tvb, offset, length,
218 "Hostname: --none--" );
220 proto_tree_add_text ( tree, tvb, offset, length,
221 "Hostname: %.*s", length,
222 tvb_get_ptr(tvb, offset, length) );
230 isis_dissect_mt_clv(tvbuff_t *tvb, packet_info *pinfo,
231 proto_tree *tree, int offset, int length, int tree_id)
237 /* length can only be a multiple of 2, otherwise there is
238 something broken -> so decode down until length is 1 */
241 /* fetch two bytes */
242 mt_block=tvb_get_ntohs(tvb, offset);
244 /* mask out the lower 12 bits */
245 switch(mt_block&0x0fff) {
247 strcpy(mt_desc,"IPv4 unicast");
250 strcpy(mt_desc,"In-Band Management");
253 strcpy(mt_desc,"IPv6 unicast");
256 strcpy(mt_desc,"Multicast");
259 strcpy(mt_desc,"Development, Experimental or Proprietary");
262 strcpy(mt_desc,"Reserved for IETF Consensus");
264 proto_tree_add_text ( tree, tvb, offset, 2 ,
265 "%s Topology (0x%03x)%s%s",
268 (mt_block&0x8000) ? "" : ", no sub-TLVs present",
269 (mt_block&0x4000) ? ", ATT bit set" : "" );
272 proto_tree_add_text ( tree, tvb, offset, 2 ,
283 * Name: isis_dissect_ip_int_clv()
286 * Take apart the CLV that lists all the IP interfaces. The
287 * meaning of which is slightly different for the different base packet
288 * types, but the display is not different. What we have is n ip
289 * addresses, plain and simple.
292 * tvbuff_t * : tvbuffer for packet data
293 * packet_info * : info for current packet
294 * proto_tree * : protocol display tree to fill out. May be NULL
295 * int : offset into packet data where we are.
296 * int : length of clv we are decoding
297 * int : tree id to use for proto tree.
300 * void, but we will add to proto tree if !NULL.
303 isis_dissect_ip_int_clv(tvbuff_t *tvb, packet_info *pinfo,
304 proto_tree *tree, int offset, int length, int tree_id)
312 while ( length > 0 ) {
314 isis_dissect_unknown(tvb, pinfo, tree, offset,
315 "Short ip interface address (%d vs 4)",length );
319 tvb_memcpy(tvb, (guint8 *)&addr, offset, sizeof(addr));
321 proto_tree_add_ipv4(tree, tree_id, tvb, offset, 4, addr);
329 * Name: isis_dissect_ipv6_int_clv()
332 * Take apart the CLV that lists all the IPv6 interfaces. The
333 * meaning of which is slightly different for the different base packet
334 * types, but the display is not different. What we have is n ip
335 * addresses, plain and simple.
338 * tvbuff_t * : tvbuffer for packet data
339 * packet_info * : info for current packet
340 * proto_tree * : protocol display tree to fill out. May be NULL
341 * int : offset into packet data where we are.
342 * int : length of clv we are decoding
343 * int : tree id to use for proto tree.
346 * void, but we will add to proto tree if !NULL.
349 isis_dissect_ipv6_int_clv(tvbuff_t *tvb, packet_info *pinfo,
350 proto_tree *tree, int offset, int length, int tree_id)
358 while ( length > 0 ) {
360 isis_dissect_unknown(tvb, pinfo, tree, offset,
361 "Short IPv6 interface address (%d vs 16)",length );
364 tvb_memcpy(tvb, addr, offset, sizeof(addr));
366 proto_tree_add_ipv6(tree, tree_id, tvb, offset, 16, addr);
375 * Name: isis_dissect_te_router_id_clv()
378 * Display the Traffic Engineering Router ID TLV #134.
379 * This TLV is like the IP Interface TLV, except that
380 * only _one_ IP address is present
383 * tvbuff_t * : tvbuffer for packet data
384 * packet_info * : info for current packet
385 * proto_tree * : protocol display tree to fill out. May be NULL
386 * int : offset into packet data where we are.
387 * int : length of clv we are decoding
388 * int : tree id to use for proto tree.
391 * void, but we will add to proto tree if !NULL.
394 isis_dissect_te_router_id_clv(tvbuff_t *tvb, packet_info *pinfo,
395 proto_tree *tree, int offset, int length, int tree_id)
404 isis_dissect_unknown(tvb, pinfo, tree, offset,
405 "malformed Traffic Engineering Router ID (%d vs 4)",length );
408 tvb_memcpy(tvb, (guint8 *)&addr, offset, sizeof(addr));
410 proto_tree_add_ipv4(tree, tree_id, tvb, offset, 4, addr);
415 * Name: isis_dissect_nlpid_clv()
418 * Take apart a NLPID packet and display it. The NLPID (for intergrated
419 * ISIS, contains n network layer protocol IDs that the box supports.
420 * Our display buffer we use is upto 255 entries, 6 bytes per (0x00, )
421 * plus 1 for zero termination. We just just 256*6 for simplicity.
424 * tvbuff_t * : tvbuffer for packet data
425 * packet_info * : info for current packet
426 * proto_tree * : protocol display tree to fill out. May be NULL
427 * int : offset into packet data where we are.
428 * int : length of clv we are decoding
431 * void, but we will add to proto tree if !NULL.
434 isis_dissect_nlpid_clv(tvbuff_t *tvb, packet_info *pinfo,
435 proto_tree *tree, int offset, int length)
440 int old_offset = offset;
442 if ( !tree ) return; /* nothing to do! */
444 while ( length-- > 0 ) {
446 s += sprintf ( s, ", " );
448 s += sprintf ( s, "%s (0x%02x)",
449 val_to_str(tvb_get_guint8(tvb, offset), nlpid_vals,
450 "Unknown"), tvb_get_guint8(tvb, offset));
455 sprintf ( sbuf, "--none--" );
458 proto_tree_add_text ( tree, tvb, old_offset, hlen,
459 "NLPID(s): %s", sbuf );
463 * Name: isis_dissect_clvs()
466 * Dispatch routine to shred all the CLVs in a packet. We just
467 * walk through the clv entries in the packet. For each one, we
468 * search the passed in valid clv's for this protocol (opts) for
469 * a matching code. If found, we add to the display tree and
470 * then call the dissector. If it is not, we just post an
471 * "unknown" clv entrie using the passed in unknown clv tree id.
474 * tvbuff_t * : tvbuffer for packet data
475 * packet_info * : info for current packet
476 * proto_tree * : protocol display tree to fill out. May be NULL
477 * int : offset into packet data where we are.
478 * isis_clv_handle_t * : NULL dissector terminated array of codes
479 * and handlers (along with tree text and tree id's).
480 * int : length of CLV area.
481 * int : length of IDs in packet.
482 * int : unknown clv tree id
485 * void, but we will add to proto tree if !NULL.
488 isis_dissect_clvs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
489 int offset, const isis_clv_handle_t *opts, int len, int id_length,
496 proto_tree *clv_tree;
501 code = tvb_get_guint8(tvb, offset);
504 length = tvb_get_guint8(tvb, offset);
507 adj = (sizeof(code) + sizeof(length) + length);
510 isis_dissect_unknown(tvb, pinfo, tree, offset,
511 "Short CLV header (%d vs %d)",
516 while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
519 if ( opts[q].dissect ) {
521 /* adjust by 2 for code/len octets */
522 snprintf ( sbuf, sizeof(sbuf), "%s (%d)",
523 opts[q].tree_text, length );
524 ti = proto_tree_add_text(tree, tvb, offset - 2,
526 clv_tree = proto_item_add_subtree(ti,
531 opts[q].dissect(tvb, pinfo, clv_tree, offset,
535 snprintf ( sbuf, sizeof(sbuf),
536 "Unknown code (%d:%d)", code, length );
537 ti = proto_tree_add_text(tree, tvb, offset - 2,
539 clv_tree = proto_item_add_subtree(ti,