MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-isis-clv.c
blob4d401b3623422db76eb3d4f9fe8cecbd0736f29a
1 /* packet-isis-clv.c
2 * Common CLV decode routines.
4 * $Id$
5 * Stuart Stanley <stuarts@mxmail.net>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <glib.h>
30 #include <epan/packet.h>
31 #include "packet-osi.h"
32 #include "packet-isis.h"
33 #include "packet-isis-clv.h"
34 #include <epan/nlpid.h>
37 * Name: isis_dissect_area_address_clv()
39 * Description:
40 * Take an area address CLV and display it pieces. An area address
41 * CLV is n, x byte hex strings.
43 * Input:
44 * tvbuff_t * : tvbuffer for packet data
45 * proto_tree * : protocol display tree to fill out. May be NULL
46 * int : offset into packet data where we are.
47 * int : length of clv we are decoding
49 * Output:
50 * void, but we will add to proto tree if !NULL.
52 void
53 isis_dissect_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
54 int length)
56 int arealen,area_idx;
58 while ( length > 0 ) {
59 arealen = tvb_get_guint8(tvb, offset);
60 length--;
61 if (length<=0) {
62 isis_dissect_unknown(tvb, tree, offset,
63 "short address (no length for payload)");
64 return;
66 if ( arealen > length) {
67 isis_dissect_unknown(tvb, tree, offset,
68 "short address, packet says %d, we have %d left",
69 arealen, length );
70 return;
73 if ( tree ) {
74 proto_item *ti;
77 * Throw an exception rather than putting in a
78 * partial address.
80 tvb_ensure_bytes_exist ( tvb, offset, arealen + 1 );
82 ti = proto_tree_add_text ( tree, tvb, offset, arealen + 1,
83 "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_guint8(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*/
108 * Name: isis_dissect_authentication_clv()
110 * Description:
111 * Take apart the CLV that hold authentication information. This
112 * is currently 1 octet auth type.
113 * the two defined authentication types
114 * are 1 for a clear text password and
115 * 54 for a HMAC-MD5 digest
117 * Input:
118 * tvbuff_t * : tvbuffer for packet data
119 * proto_tree * : protocol display tree to fill out. May be NULL
120 * int : offset into packet data where we are.
121 * int : length of clv we are decoding
123 * Output:
124 * void, but we will add to proto tree if !NULL.
126 void
127 isis_dissect_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
128 int length)
130 guchar pw_type;
131 int auth_unsupported;
132 proto_item *ti;
134 if ( length <= 0 ) {
135 return;
138 pw_type = tvb_get_guint8(tvb, offset);
139 offset += 1;
140 length--;
141 auth_unsupported = FALSE;
143 switch (pw_type) {
144 case 1:
145 ti = proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
146 "clear text (1), password (length %d) = ", length);
147 if ( length > 0 ) {
148 proto_item_append_text(ti, "%s",
149 tvb_format_text(tvb, offset, length));
150 } else {
151 proto_item_append_text(ti, "no clear-text password found!!!");
153 break;
154 case 54:
155 ti = proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
156 "hmac-md5 (54), password (length %d) = ", length);
158 if ( length == 16 ) {
159 proto_item_append_text(ti, "0x%02x", tvb_get_guint8(tvb, offset));
160 offset += 1;
161 length--;
162 while (length > 0) {
163 proto_item_append_text(ti, "%02x", tvb_get_guint8(tvb, offset));
164 offset += 1;
165 length--;
167 } else {
168 proto_item_append_text(ti,
169 "illegal hmac-md5 digest format (must be 16 bytes)");
171 break;
172 default:
173 proto_tree_add_text ( tree, tvb, offset - 1, length + 1,
174 "type 0x%02x (0x%02x): ", pw_type, length );
175 auth_unsupported=TRUE;
176 break;
179 if ( auth_unsupported ) {
180 isis_dissect_unknown(tvb, tree, offset,
181 "Unknown authentication type" );
186 * Name: isis_ip_authentication_clv()
188 * Description:
189 * dump the IP authentication information found in TLV 133
190 * the CLV is standardized in rf1195, however all major
191 * implementations use TLV #10
192 * Input:
193 * tvbuff_t * : tvbuffer for packet data
194 * proto_tree * : protocol display tree to fill out. May be NULL
195 * int : offset into packet data where we are.
196 * int : length of clv we are decoding
198 * Output:
199 * void, but we will add to proto tree if !NULL.
203 void
204 isis_dissect_ip_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
205 int length)
207 if ( !tree ) return; /* nothing to do! */
209 if ( length != 0 ) {
210 proto_tree_add_text ( tree, tvb, offset, length,
211 "IP Authentication: %.*s", length,
212 tvb_get_string(wmem_packet_scope(), tvb, offset, length) );
218 * Name: isis_dissect_hostname_clv()
220 * Description:
221 * dump the hostname information found in TLV 137
222 * pls note that the hostname is not null terminated
224 * Input:
225 * tvbuff_t * : tvbuffer for packet data
226 * proto_tree * : protocol display tree to fill out. May be NULL
227 * int : offset into packet data where we are.
228 * int : length of clv we are decoding
229 * int : tree id to use for proto tree.
231 * Output:
232 * void, but we will add to proto tree if !NULL.
236 void
237 isis_dissect_hostname_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
238 int length, int tree_id)
240 if ( !tree ) return; /* nothing to do! */
242 if ( length == 0 ) {
243 proto_tree_add_text ( tree, tvb, offset, length,
244 "Hostname: --none--" );
245 } else {
246 const char* value = tvb_get_string(wmem_packet_scope(), tvb, offset, length);
247 proto_tree_add_string_format ( tree, tree_id,
248 tvb, offset, length,
249 value, "Hostname: %.*s", length, value);
256 void
257 isis_dissect_mt_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length,
258 int tree_id)
260 guint16 mt_block;
261 const char *mt_desc;
263 while (length>0) {
264 /* length can only be a multiple of 2, otherwise there is
265 something broken -> so decode down until length is 1 */
266 if (length!=1) {
267 /* fetch two bytes */
268 mt_block=tvb_get_ntohs(tvb, offset);
270 /* mask out the lower 12 bits */
271 switch(mt_block&0x0fff) {
272 case 0:
273 mt_desc="IPv4 unicast";
274 break;
275 case 1:
276 mt_desc="In-Band Management";
277 break;
278 case 2:
279 mt_desc="IPv6 unicast";
280 break;
281 case 3:
282 mt_desc="Multicast";
283 break;
284 case 4095:
285 mt_desc="Development, Experimental or Proprietary";
286 break;
287 default:
288 mt_desc="Reserved for IETF Consensus";
289 break;
291 proto_tree_add_uint_format ( tree, tree_id, tvb, offset, 2,
292 mt_block,
293 "%s Topology (0x%03x), %ssubTLVs present%s",
294 mt_desc,
295 mt_block&0xfff,
296 (mt_block&0x8000) ? "" : "no ",
297 (mt_block&0x4000) ? ", ATT bit set" : "" );
298 } else {
299 proto_tree_add_text ( tree, tvb, offset, 1,
300 "malformed MT-ID");
301 break;
303 length=length-2;
304 offset=offset+2;
310 * Name: isis_dissect_ip_int_clv()
312 * Description:
313 * Take apart the CLV that lists all the IP interfaces. The
314 * meaning of which is slightly different for the different base packet
315 * types, but the display is not different. What we have is n ip
316 * addresses, plain and simple.
318 * Input:
319 * tvbuff_t * : tvbuffer for packet data
320 * proto_tree * : protocol display tree to fill out. May be NULL
321 * int : offset into packet data where we are.
322 * int : length of clv we are decoding
323 * int : tree id to use for proto tree.
325 * Output:
326 * void, but we will add to proto tree if !NULL.
328 void
329 isis_dissect_ip_int_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
330 int length, int tree_id)
332 if ( length <= 0 ) {
333 return;
336 while ( length > 0 ) {
337 if ( length < 4 ) {
338 isis_dissect_unknown(tvb, tree, offset,
339 "Short IP interface address (%d vs 4)",length );
340 return;
343 if ( tree ) {
344 proto_tree_add_item(tree, tree_id, tvb, offset, 4, ENC_BIG_ENDIAN);
346 offset += 4;
347 length -= 4;
352 * Name: isis_dissect_ipv6_int_clv()
354 * Description:
355 * Take apart the CLV that lists all the IPv6 interfaces. The
356 * meaning of which is slightly different for the different base packet
357 * types, but the display is not different. What we have is n ip
358 * addresses, plain and simple.
360 * Input:
361 * tvbuff_t * : tvbuffer for packet data
362 * proto_tree * : protocol display tree to fill out. May be NULL
363 * int : offset into packet data where we are.
364 * int : length of clv we are decoding
365 * int : tree id to use for proto tree.
367 * Output:
368 * void, but we will add to proto tree if !NULL.
370 void
371 isis_dissect_ipv6_int_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
372 int length, int tree_id)
374 guint8 addr [16];
376 if ( length <= 0 ) {
377 return;
380 while ( length > 0 ) {
381 if ( length < 16 ) {
382 isis_dissect_unknown(tvb, tree, offset,
383 "Short IPv6 interface address (%d vs 16)",length );
384 return;
386 tvb_memcpy(tvb, addr, offset, sizeof(addr));
387 if ( tree ) {
388 proto_tree_add_ipv6(tree, tree_id, tvb, offset, 16, addr);
390 offset += 16;
391 length -= 16;
397 * Name: isis_dissect_te_router_id_clv()
399 * Description:
400 * Display the Traffic Engineering Router ID TLV #134.
401 * This TLV is like the IP Interface TLV, except that
402 * only _one_ IP address is present
404 * Input:
405 * tvbuff_t * : tvbuffer for packet data
406 * proto_tree * : protocol display tree to fill out. May be NULL
407 * int : offset into packet data where we are.
408 * int : length of clv we are decoding
409 * int : tree id to use for proto tree.
411 * Output:
412 * void, but we will add to proto tree if !NULL.
414 void
415 isis_dissect_te_router_id_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
416 int length, int tree_id)
418 if ( length <= 0 ) {
419 return;
422 if ( length != 4 ) {
423 isis_dissect_unknown(tvb, tree, offset,
424 "malformed Traffic Engineering Router ID (%d vs 4)",length );
425 return;
427 if ( tree ) {
428 proto_tree_add_item(tree, tree_id, tvb, offset, 4, ENC_BIG_ENDIAN);
433 * Name: isis_dissect_nlpid_clv()
435 * Description:
436 * Take apart a NLPID packet and display it. The NLPID (for intergrated
437 * ISIS, contains n network layer protocol IDs that the box supports.
438 * We max out at 256 entries.
440 * Input:
441 * tvbuff_t * : tvbuffer for packet data
442 * proto_tree * : protocol display tree to fill out. May be NULL
443 * int : offset into packet data where we are.
444 * int : length of clv we are decoding
446 * Output:
447 * void, but we will add to proto tree if !NULL.
450 #define TRUNCATED_TEXT " [truncated]"
451 void
452 isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length)
454 gboolean first;
455 proto_item *ti;
457 if ( !tree ) return; /* nothing to do! */
460 * Throw an exception rather than putting in a
461 * partial address.
463 tvb_ensure_bytes_exist ( tvb, offset, length );
465 if (length <= 0) {
466 proto_tree_add_text (tree, tvb, offset, length,
467 "NLPID(s): --none--");
468 } else {
469 first = TRUE;
470 ti = proto_tree_add_text (tree, tvb, offset, length,
471 "NLPID(s): ");
472 while (length-- > 0 ) {
473 if (!first) {
474 proto_item_append_text(ti, ", ");
476 proto_item_append_text(ti, "%s (0x%02x)",
477 /* NLPID_IEEE_8021AQ conflicts with NLPID_SNDCF.
478 * In this context, we want the former.
480 (tvb_get_guint8(tvb, offset) == NLPID_IEEE_8021AQ
481 ? "IEEE 802.1aq (SPB)"
482 : val_to_str_const(tvb_get_guint8(tvb, offset), nlpid_vals,
483 "Unknown")),
484 tvb_get_guint8(tvb, offset));
485 offset++;
486 first = FALSE;
492 * Name: isis_dissect_clvs()
494 * Description:
495 * Dispatch routine to shred all the CLVs in a packet. We just
496 * walk through the clv entries in the packet. For each one, we
497 * search the passed in valid clv's for this protocol (opts) for
498 * a matching code. If found, we add to the display tree and
499 * then call the dissector. If it is not, we just post an
500 * "unknown" clv entry using the passed in unknown clv tree id.
502 * Input:
503 * tvbuff_t * : tvbuffer for packet data
504 * proto_tree * : protocol display tree to fill out. May be NULL
505 * int : offset into packet data where we are.
506 * isis_clv_handle_t * : NULL dissector terminated array of codes
507 * and handlers (along with tree text and tree id's).
508 * int : length of CLV area.
509 * int : length of IDs in packet.
510 * int : unknown clv tree id
512 * Output:
513 * void, but we will add to proto tree if !NULL.
515 void
516 isis_dissect_clvs(tvbuff_t *tvb, proto_tree *tree, int offset,
517 const isis_clv_handle_t *opts, int len, int id_length,
518 int unknown_tree_id _U_)
520 guint8 code;
521 guint8 length;
522 int q;
523 proto_item *ti;
524 proto_tree *clv_tree;
526 while ( len > 0 ) {
527 code = tvb_get_guint8(tvb, offset);
528 offset += 1;
529 len -= 1;
530 if (len == 0)
531 break;
533 length = tvb_get_guint8(tvb, offset);
534 offset += 1;
535 len -= 1;
536 if (len == 0)
537 break;
539 if ( len < length ) {
540 isis_dissect_unknown(tvb, tree, offset,
541 "Short CLV header (%d vs %d)",
542 length, len );
543 return;
545 q = 0;
546 while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
547 q++;
549 if ( opts[q].dissect ) {
550 if (tree) {
551 /* adjust by 2 for code/len octets */
552 ti = proto_tree_add_text(tree, tvb, offset - 2,
553 length + 2, "%s (%u)",
554 opts[q].tree_text, length );
555 clv_tree = proto_item_add_subtree(ti,
556 *opts[q].tree_id );
557 } else {
558 clv_tree = NULL;
560 opts[q].dissect(tvb, clv_tree, offset,
561 id_length, length);
562 } else {
563 #if 0 /* XXX: Left as commented out in case info about "unknown code" is ever to be displayed under a sub-tree */
564 if (tree) {
565 ti = proto_tree_add_text(tree, tvb, offset - 2,
566 length + 2, "Unknown code %u (%u)",
567 code, length);
568 clv_tree = proto_item_add_subtree(ti,
569 unknown_tree_id );
570 } else {
571 clv_tree = NULL;
573 #else
574 if (tree) {
575 proto_tree_add_text(tree, tvb, offset - 2,
576 length + 2, "Unknown code %u (%u)",
577 code, length);
579 #endif
581 offset += length;
582 len -= length;