MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-isis-hello.c
blobc354aadf1b693114473b74da13902638735bda17
1 /* packet-isis-hello.c
2 * Routines for decoding isis hello packets and their CLVs
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>
29 #include <epan/packet.h>
30 #include "packet-osi.h"
31 #include "packet-isis.h"
32 #include "packet-isis-clv.h"
33 #include "packet-isis-hello.h"
34 #include <epan/addr_resolv.h>
37 #define APPEND_BOOLEAN_FLAG(flag, item, string) \
38 if(flag){ \
39 if(item) \
40 proto_item_append_text(item, string, sep); \
41 sep = cont_sep; \
43 static const char initial_sep[] = " (";
44 static const char cont_sep[] = ", ";
47 /* hello packets */
48 static int hf_isis_hello_circuit_reserved = -1;
49 static int hf_isis_hello_source_id = -1;
50 static int hf_isis_hello_holding_timer = -1;
51 static int hf_isis_hello_pdu_length = -1;
52 static int hf_isis_hello_priority_reserved = -1;
53 static int hf_isis_hello_lan_id = -1;
54 static int hf_isis_hello_local_circuit_id = -1;
55 static int hf_isis_hello_clv_ipv4_int_addr = -1;
56 static int hf_isis_hello_clv_ipv6_int_addr = -1;
57 /* static int hf_isis_hello_clv_ptp_adj = -1; */
58 static int hf_isis_hello_clv_mt = -1;
59 static int hf_isis_hello_clv_restart_flags = -1;
60 static int hf_isis_hello_clv_restart_flags_rr = -1;
61 static int hf_isis_hello_clv_restart_flags_ra = -1;
62 static int hf_isis_hello_clv_restart_flags_sa = -1;
63 static int hf_isis_hello_clv_restart_remain_time = -1;
64 static int hf_isis_hello_clv_restart_neighbor = -1;
66 static gint ett_isis_hello = -1;
67 static gint ett_isis_hello_clv_area_addr = -1;
68 static gint ett_isis_hello_clv_is_neighbors = -1;
69 static gint ett_isis_hello_clv_padding = -1;
70 static gint ett_isis_hello_clv_unknown = -1;
71 static gint ett_isis_hello_clv_nlpid = -1;
72 static gint ett_isis_hello_clv_authentication = -1;
73 static gint ett_isis_hello_clv_ip_authentication = -1;
74 static gint ett_isis_hello_clv_ipv4_int_addr = -1;
75 static gint ett_isis_hello_clv_ipv6_int_addr = -1;
76 static gint ett_isis_hello_clv_ptp_adj = -1;
77 static gint ett_isis_hello_clv_mt = -1;
78 static gint ett_isis_hello_clv_restart = -1;
79 static gint ett_isis_hello_clv_restart_flags = -1;
80 static gint ett_isis_hello_clv_mt_port_cap = -1;
81 static gint ett_isis_hello_clv_mt_port_cap_spb_mcid = -1;
82 static gint ett_isis_hello_clv_mt_port_cap_spb_aux_mcid = -1;
83 static gint ett_isis_hello_clv_mt_port_cap_spb_digest = -1;
84 static gint ett_isis_hello_clv_mt_port_cap_spb_bvid_tuples = -1;
85 static gint ett_isis_hello_clv_checksum = -1;
87 static const value_string isis_hello_circuit_type_vals[] = {
88 { ISIS_HELLO_TYPE_RESERVED, "Reserved 0 (discard PDU)"},
89 { ISIS_HELLO_TYPE_LEVEL_1, "Level 1 only"},
90 { ISIS_HELLO_TYPE_LEVEL_2, "Level 2 only"},
91 { ISIS_HELLO_TYPE_LEVEL_12, "Level 1 and 2"},
92 { 0, NULL} };
95 * Predclare dissectors for use in clv dissection.
97 static void dissect_hello_padding_clv(tvbuff_t *tvb,
98 proto_tree *tree, int offset, int id_length, int length);
99 static void dissect_hello_is_neighbors_clv(tvbuff_t *tvb,
100 proto_tree *tree, int offset, int id_length, int length);
101 static void dissect_hello_ptp_adj_clv(tvbuff_t *tvb,
102 proto_tree *tree, int offset, int id_length, int length);
103 static void dissect_hello_area_address_clv(tvbuff_t *tvb,
104 proto_tree *tree, int offset, int id_length, int length);
105 static void dissect_hello_authentication_clv(tvbuff_t *tvb,
106 proto_tree *tree, int offset, int id_length, int length);
107 static void dissect_hello_ip_authentication_clv(tvbuff_t *tvb,
108 proto_tree *tree, int offset, int id_length, int length);
109 static void dissect_hello_checksum_clv(tvbuff_t *tvb,
110 proto_tree *tree, int offset, int id_length, int length);
111 static void dissect_hello_ipv6_int_addr_clv(tvbuff_t *tvb,
112 proto_tree *tree, int offset, int id_length, int length);
113 static void dissect_hello_ip_int_addr_clv(tvbuff_t *tvb,
114 proto_tree *tree, int offset, int id_length, int length);
115 static void dissect_hello_mt_clv(tvbuff_t *tvb,
116 proto_tree *tree, int offset, int id_length, int length);
117 static void dissect_hello_nlpid_clv(tvbuff_t *tvb,
118 proto_tree *tree, int offset, int id_length, int length);
119 static void dissect_hello_restart_clv(tvbuff_t *tvb,
120 proto_tree *tree, int offset, int id_length, int length);
121 static void dissect_hello_mt_port_cap_clv(tvbuff_t *tvb,
122 proto_tree *tree, int offset, int id_length, int length);
125 static const isis_clv_handle_t clv_l1_hello_opts[] = {
127 ISIS_CLV_AREA_ADDRESS,
128 "Area address(es)",
129 &ett_isis_hello_clv_area_addr,
130 dissect_hello_area_address_clv
133 ISIS_CLV_IS_NEIGHBORS,
134 "IS Neighbor(s)",
135 &ett_isis_hello_clv_is_neighbors,
136 dissect_hello_is_neighbors_clv
139 ISIS_CLV_PADDING,
140 "Padding",
141 &ett_isis_hello_clv_padding,
142 dissect_hello_padding_clv
145 ISIS_CLV_PROTOCOLS_SUPPORTED,
146 "Protocols Supported",
147 &ett_isis_hello_clv_nlpid,
148 dissect_hello_nlpid_clv
151 ISIS_CLV_IP_ADDR,
152 "IP Interface address(es)",
153 &ett_isis_hello_clv_ipv4_int_addr,
154 dissect_hello_ip_int_addr_clv
157 ISIS_CLV_IP6_ADDR,
158 "IPv6 Interface address(es)",
159 &ett_isis_hello_clv_ipv6_int_addr,
160 dissect_hello_ipv6_int_addr_clv
163 ISIS_CLV_RESTART,
164 "Restart Signaling",
165 &ett_isis_hello_clv_restart,
166 dissect_hello_restart_clv
169 ISIS_CLV_AUTHENTICATION,
170 "Authentication",
171 &ett_isis_hello_clv_authentication,
172 dissect_hello_authentication_clv
175 ISIS_CLV_IP_AUTHENTICATION,
176 "IP Authentication",
177 &ett_isis_hello_clv_ip_authentication,
178 dissect_hello_ip_authentication_clv
181 ISIS_CLV_MT_SUPPORTED,
182 "Multi Topology",
183 &ett_isis_hello_clv_mt,
184 dissect_hello_mt_clv
187 ISIS_CLV_CHECKSUM,
188 "Checksum",
189 &ett_isis_hello_clv_checksum,
190 dissect_hello_checksum_clv
195 NULL,
196 NULL
200 static const isis_clv_handle_t clv_l2_hello_opts[] = {
202 ISIS_CLV_AREA_ADDRESS,
203 "Area address(es)",
204 &ett_isis_hello_clv_area_addr,
205 dissect_hello_area_address_clv
208 ISIS_CLV_IS_NEIGHBORS,
209 "IS Neighbor(s)",
210 &ett_isis_hello_clv_is_neighbors,
211 dissect_hello_is_neighbors_clv
214 ISIS_CLV_PADDING,
215 "Padding",
216 &ett_isis_hello_clv_padding,
217 dissect_hello_padding_clv
220 ISIS_CLV_PROTOCOLS_SUPPORTED,
221 "Protocols Supported",
222 &ett_isis_hello_clv_nlpid,
223 dissect_hello_nlpid_clv
226 ISIS_CLV_IP_ADDR,
227 "IP Interface address(es)",
228 &ett_isis_hello_clv_ipv4_int_addr,
229 dissect_hello_ip_int_addr_clv
232 ISIS_CLV_IP6_ADDR,
233 "IPv6 Interface address(es)",
234 &ett_isis_hello_clv_ipv6_int_addr,
235 dissect_hello_ipv6_int_addr_clv
238 ISIS_CLV_AUTHENTICATION,
239 "Authentication",
240 &ett_isis_hello_clv_authentication,
241 dissect_hello_authentication_clv
244 ISIS_CLV_IP_AUTHENTICATION,
245 "IP Authentication",
246 &ett_isis_hello_clv_ip_authentication,
247 dissect_hello_ip_authentication_clv
250 ISIS_CLV_RESTART,
251 "Restart Signaling",
252 &ett_isis_hello_clv_restart,
253 dissect_hello_restart_clv
256 ISIS_CLV_MT_SUPPORTED,
257 "Multi Topology",
258 &ett_isis_hello_clv_mt,
259 dissect_hello_mt_clv
262 ISIS_CLV_CHECKSUM,
263 "Checksum",
264 &ett_isis_hello_clv_checksum,
265 dissect_hello_checksum_clv
270 NULL,
271 NULL
275 static const isis_clv_handle_t clv_ptp_hello_opts[] = {
277 ISIS_CLV_AREA_ADDRESS,
278 "Area address(es)",
279 &ett_isis_hello_clv_area_addr,
280 dissect_hello_area_address_clv
283 ISIS_CLV_PADDING,
284 "Padding",
285 &ett_isis_hello_clv_padding,
286 dissect_hello_padding_clv
289 ISIS_CLV_PROTOCOLS_SUPPORTED,
290 "Protocols Supported",
291 &ett_isis_hello_clv_nlpid,
292 dissect_hello_nlpid_clv
295 ISIS_CLV_IP_ADDR,
296 "IP Interface address(es)",
297 &ett_isis_hello_clv_ipv4_int_addr,
298 dissect_hello_ip_int_addr_clv
301 ISIS_CLV_IP6_ADDR,
302 "IPv6 Interface address(es)",
303 &ett_isis_hello_clv_ipv6_int_addr,
304 dissect_hello_ipv6_int_addr_clv
307 ISIS_CLV_AUTHENTICATION,
308 "Authentication",
309 &ett_isis_hello_clv_authentication,
310 dissect_hello_authentication_clv
313 ISIS_CLV_IP_AUTHENTICATION,
314 "IP Authentication",
315 &ett_isis_hello_clv_ip_authentication,
316 dissect_hello_ip_authentication_clv
319 ISIS_CLV_MT_PORT_CAP,
320 "MT Port Capability",
321 &ett_isis_hello_clv_mt_port_cap,
322 dissect_hello_mt_port_cap_clv
325 ISIS_CLV_RESTART,
326 "Restart Option",
327 &ett_isis_hello_clv_restart,
328 dissect_hello_restart_clv
331 ISIS_CLV_PTP_ADJ_STATE,
332 "Point-to-point Adjacency State",
333 &ett_isis_hello_clv_ptp_adj,
334 dissect_hello_ptp_adj_clv
337 ISIS_CLV_MT_SUPPORTED,
338 "Multi Topology",
339 &ett_isis_hello_clv_mt,
340 dissect_hello_mt_clv
343 ISIS_CLV_CHECKSUM,
344 "Checksum",
345 &ett_isis_hello_clv_checksum,
346 dissect_hello_checksum_clv
351 NULL,
352 NULL
356 static void
357 dissect_hello_mt_port_cap_spb_mcid_clv(tvbuff_t *tvb,
358 proto_tree *tree, int offset, int subtype, int sublen)
360 const int MCID_LEN = 51;
361 const int SUBLEN = 2 * MCID_LEN;
363 if (sublen != SUBLEN) {
364 isis_dissect_unknown( tvb, tree, offset,
365 "Short SPB MCID TLV (%d vs %d)", sublen, SUBLEN);
366 return;
368 else {
369 proto_tree *subtree, *ti;
370 const guint8 *mcid = tvb_get_ptr(tvb, offset, MCID_LEN);
371 const guint8 *aux_mcid = tvb_get_ptr(tvb, offset + MCID_LEN, MCID_LEN);
372 int i;
374 ti = proto_tree_add_text( tree, tvb, offset-2, sublen+2,
375 "SPB MCID: Type: 0x%02x, Length: %d", subtype, sublen);
376 subtree = proto_item_add_subtree(ti, ett_isis_hello_clv_mt_port_cap_spb_mcid);
378 /* MCID: */
379 proto_tree_add_text( subtree, tvb, offset, MCID_LEN, "MCID:");
380 for (i = 0 ; i < 48 ; i+= 8, offset += 8) {
381 proto_tree_add_text( subtree, tvb, offset, 8,
382 " %02x %02x %02x %02x %02x %02x %02x %02x",
383 mcid[i+0], mcid[i+1], mcid[i+2], mcid[i+3],
384 mcid[i+4], mcid[i+5], mcid[i+6], mcid[i+7]);
386 proto_tree_add_text( subtree, tvb, offset, 3,
387 " %02x %02x %02x",
388 mcid[i+0], mcid[i+1], mcid[i+2]);
389 offset += 3;
391 /* Aux MCID: */
392 proto_tree_add_text( subtree, tvb, offset, MCID_LEN, "Aux MCID:");
393 for (i = 0 ; i < 48 ; i+= 8, offset += 8) {
394 proto_tree_add_text( subtree, tvb, offset, 8,
395 " %02x %02x %02x %02x %02x %02x %02x %02x",
396 aux_mcid[i+0], aux_mcid[i+1], aux_mcid[i+2], aux_mcid[i+3],
397 aux_mcid[i+4], aux_mcid[i+5], aux_mcid[i+6], aux_mcid[i+7]);
399 proto_tree_add_text( subtree, tvb, offset, 3,
400 " %02x %02x %02x",
401 aux_mcid[i+0], aux_mcid[i+1], aux_mcid[i+2]);
402 /*offset += 3;*/
406 static void
407 dissect_hello_mt_port_cap_spb_digest_clv(tvbuff_t *tvb,
408 proto_tree *tree, int offset, int subtype, int sublen)
410 const int DIGEST_LEN = 32;
411 const int SUBLEN = 1 + DIGEST_LEN;
412 if (sublen != SUBLEN) {
413 isis_dissect_unknown( tvb, tree, offset,
414 "Short SPB Digest TLV (%d vs %d)", sublen, SUBLEN);
415 return;
417 else {
418 proto_tree *subtree, *ti;
419 const guint8 vad = tvb_get_guint8(tvb, offset);
420 const guint8 *digest = tvb_get_ptr(tvb, offset + 1, DIGEST_LEN);
421 int i;
423 ti = proto_tree_add_text( tree, tvb, offset-2, sublen+2,
424 "SPB Digest: Type: 0x%02x, Length: %d", subtype, sublen);
425 subtree = proto_item_add_subtree(ti, ett_isis_hello_clv_mt_port_cap_spb_digest);
427 proto_tree_add_text( subtree, tvb, offset, 1,
428 "V: %d, A: %d, D: %d",
429 (vad >> 4) & 0x1,
430 (vad >> 2) & 0x3,
431 (vad >> 0) & 0x3);
432 ++offset;
434 /* Digest: */
435 proto_tree_add_text( subtree, tvb, offset, DIGEST_LEN, "Digest:");
436 for (i = 0 ; i < DIGEST_LEN ; i+= 8, offset += 8) {
437 proto_tree_add_text( subtree, tvb, offset, 8,
438 " %02x %02x %02x %02x %02x %02x %02x %02x",
439 digest[i+0], digest[i+1], digest[i+2], digest[i+3],
440 digest[i+4], digest[i+5], digest[i+6], digest[i+7]);
445 static void
446 dissect_hello_mt_port_cap_spb_bvid_tuples_clv(tvbuff_t *tvb,
447 proto_tree *tree, int offset, int subtype, int sublen)
449 proto_tree *subtree, *ti;
450 int subofs = offset;
452 ti = proto_tree_add_text( tree, tvb, offset-2, sublen+2,
453 "SPB Base Vlan Identifiers: Type: 0x%02x, Length: %d", subtype, sublen);
454 subtree = proto_item_add_subtree(ti, ett_isis_hello_clv_mt_port_cap_spb_bvid_tuples);
456 while (sublen > 0) {
457 if (sublen < 6) {
458 isis_dissect_unknown( tvb, subtree, offset,
459 "Short SPB BVID header entry (%d vs %d)", sublen, 6);
460 return;
462 else {
463 const guint8 *ect_tlv = tvb_get_ptr(tvb, subofs, 6);
464 guint16 word = (ect_tlv[4] << 8) | ect_tlv[5];
465 guint16 bvid = (word >> 4) & 0xfff;
466 int u_bit = (ect_tlv[5] & 8) ? 1 : 0;
467 int m_bit = (ect_tlv[5] & 4) ? 1 : 0;
468 proto_tree_add_text( subtree, tvb, subofs, 6,
469 "ECT: %02x-%02x-%02x-%02x, BVID: 0x%03x (%d),%s U: %d, M: %d",
470 ect_tlv[0], ect_tlv[1], ect_tlv[2], ect_tlv[3],
471 bvid, bvid,
472 ( bvid < 10 ? " "
473 : bvid < 100 ? " "
474 : bvid < 1000 ? " "
475 : ""),
476 u_bit,
477 m_bit);
479 sublen -= 6;
480 subofs += 6;
484 static void
485 dissect_hello_mt_port_cap_clv(tvbuff_t *tvb,
486 proto_tree *tree, int offset, int id_length _U_, int length)
488 if (length >= 2) {
489 /* mtid */
490 guint16 mtid = tvb_get_ntohs(tvb, offset);
491 proto_tree_add_text( tree, tvb, offset, 2,
492 "MTID: 0x%03x",
493 (mtid & 0xfff));
494 length -= 2;
495 offset += 2;
496 while (length >= 2) {
497 guint8 subtype = tvb_get_guint8(tvb, offset);
498 guint8 subtlvlen = tvb_get_guint8(tvb, offset+1);
499 length -= 2;
500 offset += 2;
501 if (subtlvlen > length) {
502 isis_dissect_unknown( tvb, tree, offset,
503 "Short type 0x%02x TLV (%d vs %d)", subtype, subtlvlen, length);
504 return;
506 if (subtype == 0x04) { /* SPB MCID */
507 dissect_hello_mt_port_cap_spb_mcid_clv(tvb, tree, offset, subtype, subtlvlen);
509 else if (subtype == 0x05) { /* SPB Digest */
510 dissect_hello_mt_port_cap_spb_digest_clv(tvb, tree, offset, subtype, subtlvlen);
512 else if (subtype == 0x06) { /* SPB BVID Tuples */
513 dissect_hello_mt_port_cap_spb_bvid_tuples_clv(tvb, tree, offset, subtype, subtlvlen);
515 else {
516 isis_dissect_unknown( tvb, tree, offset,
517 "Unknown SubTlv: Type: 0x%02x, Length: %d", subtype, subtlvlen);
519 length -= subtlvlen;
520 offset += subtlvlen;
526 * The Restart CLV is documented in RFC 3847 (Restart Signaling for
527 * Intermediate System to Intermediate System). The CLV looks like this
529 * Type 211
530 * Length # of octets in the value field (1 to (3 + ID Length))
531 * Value
533 * No. of octets
534 * +-----------------------+
535 * | Flags | 1
536 * +-----------------------+
537 * | Remaining Time | 2
538 * +-----------------------+
539 * | Restarting Neighbor ID| ID Length
540 * +-----------------------+
542 * Flags (1 octet)
544 * 0 1 2 3 4 5 6 7
545 * +--+--+--+--+--+--+--+--+
546 * | Reserved |SA|RA|RR|
547 * +--+--+--+--+--+--+--+--+
549 * RR - Restart Request
550 * RA - Restart Acknowledgement
551 * SA - Suppress adjacency advertisement
553 * The Remaining Time and Restarting Neighbor ID fields are only required when
554 * the RA flag is set. The Flags field is always required.
558 * Name: dissect_hello_restart_clv()
560 * Description:
561 * Decode for a restart clv - only found in IIHs
562 * hence no call in the common clv dissector
566 static void
567 dissect_hello_restart_clv(tvbuff_t *tvb,
568 proto_tree *tree, int offset, int id_length, int length)
570 int restart_options=0;
571 proto_tree *flags_tree;
572 proto_item *restart_flags_item;
573 proto_item *hold_time_item;
574 const char *sep;
575 const guint8 *neighbor_id;
577 if (length >= 1) {
578 restart_options = tvb_get_guint8(tvb, offset);
579 restart_flags_item = proto_tree_add_uint ( tree, hf_isis_hello_clv_restart_flags,
580 tvb, offset, 1, restart_options);
581 flags_tree = proto_item_add_subtree(restart_flags_item, ett_isis_hello_clv_restart_flags);
582 proto_tree_add_boolean (flags_tree, hf_isis_hello_clv_restart_flags_sa,
583 tvb, offset, 1, restart_options );
584 proto_tree_add_boolean (flags_tree, hf_isis_hello_clv_restart_flags_ra,
585 tvb, offset, 1, restart_options );
586 proto_tree_add_boolean (flags_tree, hf_isis_hello_clv_restart_flags_rr,
587 tvb, offset, 1, restart_options );
589 /* Append an indication of which flags are set in the restart
590 * options
592 sep = initial_sep;
593 APPEND_BOOLEAN_FLAG(ISIS_MASK_RESTART_SA(restart_options), restart_flags_item, "%sSA");
594 APPEND_BOOLEAN_FLAG(ISIS_MASK_RESTART_RA(restart_options), restart_flags_item, "%sRA");
595 APPEND_BOOLEAN_FLAG(ISIS_MASK_RESTART_RR(restart_options), restart_flags_item, "%sRR");
596 if (sep != initial_sep)
598 proto_item_append_text (restart_flags_item, ")");
603 /* The Remaining Time field should only be present if the RA flag is
604 * set
606 if (length >= 3 && ISIS_MASK_RESTART_RA(restart_options)) {
607 hold_time_item = proto_tree_add_uint ( tree, hf_isis_hello_clv_restart_remain_time,
608 tvb, offset+1, 2, tvb_get_ntohs(tvb, offset+1) );
609 proto_item_append_text( hold_time_item, "s" );
612 /* The Restarting Neighbor ID should only be present if the RA flag is
613 * set.
615 if (length >= 3 + id_length && ISIS_MASK_RESTART_RA(restart_options)) {
616 neighbor_id = tvb_get_ptr(tvb, offset+3, id_length);
617 proto_tree_add_bytes_format_value( tree,
618 hf_isis_hello_clv_restart_neighbor, tvb, offset+3,
619 id_length, neighbor_id, "%s",
620 print_system_id( neighbor_id, id_length ) );
625 * Name: dissect_hello_nlpid_clv()
627 * Description:
628 * Decode for a hello packets NLPID clv. Calls into the
629 * clv common one.
631 * Input:
632 * tvbuff_t * : tvbuffer for packet data
633 * proto_tree * : proto tree to build on (may be null)
634 * int : current offset into packet data
635 * int : length of IDs in packet.
636 * int : length of this clv
638 * Output:
639 * void, will modify proto_tree if not null.
641 static void
642 dissect_hello_nlpid_clv(tvbuff_t *tvb,
643 proto_tree *tree, int offset, int id_length _U_, int length)
645 isis_dissect_nlpid_clv(tvb, tree, offset, length);
649 * Name: dissect_hello_mt_clv()
651 * Description:
652 * Decode for a hello packets Multi Topology clv. Calls into the
653 * clv common one.
655 * Input:
656 * tvbuff_t * : tvbuffer for packet data
657 * proto_tree * : proto tree to build on (may be null)
658 * int : current offset into packet data
659 * int : length of IDs in packet.
660 * int : length of this clv
662 * Output:
663 * void, will modify proto_tree if not null.
666 static void
667 dissect_hello_mt_clv(tvbuff_t *tvb,
668 proto_tree *tree, int offset, int id_length _U_, int length)
670 isis_dissect_mt_clv(tvb, tree, offset, length,
671 hf_isis_hello_clv_mt );
675 * Name: dissect_hello_ip_int_addr_clv()
677 * Description:
678 * Decode for a hello packets ip interface addr clv. Calls into the
679 * clv common one.
681 * Input:
682 * tvbuff_t * : tvbuffer for packet data
683 * proto_tree * : proto tree to build on (may be null)
684 * int : current offset into packet data
685 * int : length of IDs in packet.
686 * int : length of this clv
688 * Output:
689 * void, will modify proto_tree if not null.
691 static void
692 dissect_hello_ip_int_addr_clv(tvbuff_t *tvb,
693 proto_tree *tree, int offset, int id_length _U_, int length)
695 isis_dissect_ip_int_clv(tvb, tree, offset, length,
696 hf_isis_hello_clv_ipv4_int_addr );
700 * Name: dissect_hello_ipv6_int_addr_clv()
702 * Description:
703 * Decode for a hello packets ipv6 interface addr clv. Calls into the
704 * clv common one.
706 * Input:
707 * tvbuff_t * : tvbuffer for packet data
708 * proto_tree * : proto tree to build on (may be null)
709 * int : current offset into packet data
710 * int : length of IDs in packet.
711 * int : length of this clv
713 * Output:
714 * void, will modify proto_tree if not null.
716 static void
717 dissect_hello_ipv6_int_addr_clv(tvbuff_t *tvb,
718 proto_tree *tree, int offset, int id_length _U_, int length)
720 isis_dissect_ipv6_int_clv(tvb, tree, offset, length,
721 hf_isis_hello_clv_ipv6_int_addr );
725 * Name: dissect_hello_authentication_clv()
727 * Description:
728 * Decode for a hello packets authenticaion clv.
729 * Calls into the CLV common one.
731 * Input:
732 * tvbuff_t * : tvbuffer for packet data
733 * proto_tree * : proto tree to build on (may be null)
734 * int : current offset into packet data
735 * int : length of IDs in packet.
736 * int : length of this clv
738 * Output:
739 * void, will modify proto_tree if not null.
741 static void
742 dissect_hello_authentication_clv(tvbuff_t *tvb,
743 proto_tree *tree, int offset, int id_length _U_, int length)
745 isis_dissect_authentication_clv(tvb, tree, offset, length);
749 * Name: dissect_hello_ip_authentication_clv()
751 * Description:
752 * Decode for a hello packets IP authenticaion clv.
753 * Calls into the CLV common one.
755 * Input:
756 * tvbuff_t * : tvbuffer for packet data
757 * proto_tree * : proto tree to build on (may be null)
758 * int : current offset into packet data
759 * int : length of IDs in packet.
760 * int : length of this clv
762 * Output:
763 * void, will modify proto_tree if not null.
765 static void
766 dissect_hello_ip_authentication_clv(tvbuff_t *tvb,
767 proto_tree *tree, int offset, int id_length _U_, int length)
769 isis_dissect_ip_authentication_clv(tvb, tree, offset, length);
773 * Name: dissect_hello_checksum_clv()
775 * Description:
776 * dump and verify the optional checksum in TLV 12
778 * Input:
779 * tvbuff_t * : tvbuffer for packet data
780 * proto_tree * : protocol display tree to fill out. May be NULL
781 * int : offset into packet data where we are.
782 * int : length of clv we are decoding
784 * Output:
785 * void, but we will add to proto tree if !NULL.
788 static void
789 dissect_hello_checksum_clv(tvbuff_t *tvb,
790 proto_tree *tree, int offset, int id_length _U_, int length) {
792 guint16 pdu_length,checksum, cacl_checksum=0;
794 if (tree) {
795 if ( length != 2 ) {
796 proto_tree_add_text ( tree, tvb, offset, length,
797 "incorrect checksum length (%u), should be (2)", length );
798 return;
801 checksum = tvb_get_ntohs(tvb, offset);
803 /* the check_and_get_checksum() function needs to know how big
804 * the packet is. we can either pass through the pdu-len through several layers
805 * of dissectors and wrappers or extract the PDU length field from the PDU specific header
806 * which is offseted 17 bytes in IIHs (relative to the beginning of the IS-IS packet) */
808 pdu_length = tvb_get_ntohs(tvb, 17);
810 /* unlike the LSP checksum verification which starts at an offset of 12 we start at offset 0*/
811 switch (check_and_get_checksum(tvb, 0, pdu_length, checksum, offset, &cacl_checksum))
814 case NO_CKSUM :
815 proto_tree_add_text ( tree, tvb, offset, length,
816 "Checksum: 0x%04x [unused]", checksum);
817 break;
818 case DATA_MISSING :
819 isis_dissect_unknown(tvb, tree, offset,
820 "[packet length %d went beyond packet]",
821 tvb_length(tvb));
822 break;
823 case CKSUM_NOT_OK :
824 proto_tree_add_text ( tree, tvb, offset, length,
825 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
826 checksum,
827 cacl_checksum);
828 break;
829 case CKSUM_OK :
830 proto_tree_add_text ( tree, tvb, offset, length,
831 "Checksum: 0x%04x [correct]", checksum);
832 break;
833 default :
834 g_message("'check_and_get_checksum' returned an invalid value");
842 * Name: dissect_hello_area_address_clv()
844 * Description:
845 * Decode for a hello packets area address clv.
846 * Calls into the CLV common one.
848 * Input:
849 * tvbuff_t * : tvbuffer for packet data
850 * proto_tree * : proto tree to build on (may be null)
851 * int : current offset into packet data
852 * int : length of IDs in packet.
853 * int : length of this clv
855 * Output:
856 * void, will modify proto_tree if not null.
858 static void
859 dissect_hello_area_address_clv(tvbuff_t *tvb,
860 proto_tree *tree, int offset, int id_length _U_, int length)
862 isis_dissect_area_address_clv(tvb, tree, offset, length);
867 static void
868 dissect_hello_ptp_adj_clv(tvbuff_t *tvb,
869 proto_tree *tree, int offset, int id_length, int length)
871 static const value_string adj_state_vals[] = {
872 { 0, "Up" },
873 { 1, "Initializing" },
874 { 2, "Down" },
875 { 0, NULL }
877 guint8 adj_state;
878 const char *adj_state_str;
880 adj_state = tvb_get_guint8(tvb, offset);
881 adj_state_str = val_to_str(adj_state, adj_state_vals, "Unknown (%u)");
882 switch(length) {
883 case 1:
884 proto_tree_add_text ( tree, tvb, offset, 1,
885 "Adjacency State: %s", adj_state_str );
886 break;
887 case 5:
888 proto_tree_add_text ( tree, tvb, offset, 1,
889 "Adjacency State: %s", adj_state_str );
890 proto_tree_add_text ( tree, tvb, offset+1, 4,
891 "Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+1) );
892 break;
893 case 11:
894 proto_tree_add_text ( tree, tvb, offset, 1,
895 "Adjacency State: %s", adj_state_str );
896 proto_tree_add_text ( tree, tvb, offset+1, 4,
897 "Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+1) );
898 proto_tree_add_text ( tree, tvb, offset+5, id_length,
899 "Neighbor SystemID: %s",
900 print_system_id( tvb_get_ptr(tvb, offset+5, id_length), id_length ) );
901 break;
902 case 15:
903 proto_tree_add_text ( tree, tvb, offset, 1,
904 "Adjacency State: %s", adj_state_str );
905 proto_tree_add_text ( tree, tvb, offset+1, 4,
906 "Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+1) );
907 proto_tree_add_text ( tree, tvb, offset+5, id_length,
908 "Neighbor SystemID: %s",
909 print_system_id( tvb_get_ptr(tvb, offset+5, id_length), id_length ) );
910 proto_tree_add_text ( tree, tvb, offset+5+id_length, 4,
911 "Neighbor Extended Local circuit ID: 0x%08x",
912 tvb_get_ntohl(tvb, offset+5+id_length) );
913 break;
914 default:
915 isis_dissect_unknown(tvb, tree, offset,
916 "malformed TLV (%d vs 1,5,11,15)", length );
917 return;
922 * Name: isis_dissect_is_neighbors_clv()
924 * Description:
925 * Take apart a IS neighbor packet. A neighbor is n 6 byte packets.
926 * (they tend to be an 802.3 MAC address, but it's not required).
928 * Input:
929 * tvbuff_t * : tvbuffer for packet data
930 * proto_tree * : protocol display tree to fill out. May be NULL
931 * int : offset into packet data where we are.
932 * int : length of IDs in packet.
933 * int : length of clv we are decoding
935 * Output:
936 * void, but we will add to proto tree if !NULL.
938 static void
939 dissect_hello_is_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
940 int id_length _U_, int length)
942 while ( length > 0 ) {
943 if (length<6) {
944 isis_dissect_unknown(tvb, tree, offset,
945 "short is neighbor (%d vs 6)", length );
946 return;
949 * Lets turn the area address into "standard" 0000.0000.etc
950 * format string.
952 if ( tree ) {
953 proto_tree_add_text ( tree, tvb, offset, 6,
954 "IS Neighbor: %s", get_ether_name( tvb_get_ptr(tvb, offset, 6)) );
956 offset += 6;
957 length -= 6;
962 * Name: dissect_hello_padding_clv()
964 * Description:
965 * Decode for a hello packet's padding clv. Padding does nothing,
966 * so we just return.
968 * Input:
969 * tvbuff_t * : tvbuffer for packet data
970 * proto_tree * : proto tree to build on (may be null)
971 * int : current offset into packet data
972 * int : length of IDs in packet.
973 * int : length of this clv
975 * Output:
976 * void
978 static void
979 dissect_hello_padding_clv(tvbuff_t *tvb _U_, proto_tree *tree _U_, int offset _U_,
980 int id_length _U_, int length _U_)
982 /* nothing to do here! */
987 * Name: isis_dissect_isis_hello()
989 * Description:
990 * This procedure rips apart the various types of ISIS hellos. L1H and
991 * L2H's are identical for the most part, while the PTP hello has
992 * a shorter header.
994 * Input:
995 * tvbuff_t * : tvbuffer for packet data
996 * proto_tree * : protocol display tree to add to. May be NULL.
997 * int offset : our offset into packet data.
998 * int : hello type, a la packet-isis.h ISIS_TYPE_* values
999 * int : header length of packet.
1000 * int : length of IDs in packet.
1002 * Output:
1003 * void, will modify proto_tree if not NULL.
1005 void
1006 isis_dissect_isis_hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
1007 int hello_type, int header_length, int id_length)
1009 proto_item *ti;
1010 proto_tree *hello_tree = NULL;
1011 int len;
1012 guint8 octet;
1013 const guint8 *source_id;
1014 guint16 pdu_length;
1015 const guint8 *lan_id;
1017 if (tree) {
1018 ti = proto_tree_add_text(tree, tvb, offset, -1, "ISIS HELLO");
1019 hello_tree = proto_item_add_subtree(ti, ett_isis_hello);
1020 octet = tvb_get_guint8(tvb, offset);
1021 proto_tree_add_uint_format(hello_tree,
1022 hf_isis_hello_circuit_reserved,
1023 tvb, offset, 1, octet,
1024 "Circuit type : %s, reserved(0x%02x == 0)",
1025 val_to_str(octet&ISIS_HELLO_CTYPE_MASK,
1026 isis_hello_circuit_type_vals,
1027 "Unknown (0x%x)"),
1028 octet&ISIS_HELLO_CT_RESERVED_MASK
1031 offset += 1;
1033 if (tree) {
1034 source_id = tvb_get_ptr(tvb, offset, id_length);
1035 proto_tree_add_bytes_format_value(hello_tree, hf_isis_hello_source_id, tvb,
1036 offset, id_length, source_id,
1037 "%s", print_system_id( source_id, id_length ) );
1039 col_append_fstr(pinfo->cinfo, COL_INFO, ", System-ID: %s",
1040 print_system_id( tvb_get_ptr(tvb, offset, id_length), id_length ) );
1042 offset += id_length;
1044 if (tree) {
1045 proto_tree_add_item(hello_tree, hf_isis_hello_holding_timer, tvb,
1046 offset, 2, ENC_BIG_ENDIAN);
1048 offset += 2;
1050 pdu_length = tvb_get_ntohs(tvb, offset);
1051 if (tree) {
1052 proto_tree_add_uint(hello_tree, hf_isis_hello_pdu_length, tvb,
1053 offset, 2, pdu_length);
1055 offset += 2;
1057 if (hello_type == ISIS_TYPE_PTP_HELLO) {
1058 if (tree) {
1059 proto_tree_add_item(hello_tree, hf_isis_hello_local_circuit_id, tvb,
1060 offset, 1, ENC_BIG_ENDIAN );
1062 offset += 1;
1063 } else {
1064 if (tree) {
1065 octet = tvb_get_guint8(tvb, offset);
1066 proto_tree_add_uint_format(hello_tree, hf_isis_hello_priority_reserved, tvb,
1067 offset, 1, octet,
1068 "Priority : %d, reserved(0x%02x == 0)",
1069 octet&ISIS_HELLO_PRIORITY_MASK,
1070 octet&ISIS_HELLO_P_RESERVED_MASK );
1072 offset += 1;
1074 if (tree) {
1075 lan_id = tvb_get_ptr(tvb, offset, id_length+1);
1076 proto_tree_add_bytes_format_value(hello_tree, hf_isis_hello_lan_id, tvb,
1077 offset, id_length + 1, lan_id,
1078 "%s", print_system_id( lan_id, id_length + 1 ) );
1080 offset += id_length + 1;
1083 len = pdu_length;
1084 len -= header_length;
1085 if (len < 0) {
1086 isis_dissect_unknown(tvb, tree, offset,
1087 "Packet header length %d went beyond packet",
1088 header_length );
1089 return;
1092 * Now, we need to decode our CLVs. We need to pass in
1093 * our list of valid ones!
1095 if (hello_type == ISIS_TYPE_L1_HELLO){
1096 isis_dissect_clvs(tvb, hello_tree, offset,
1097 clv_l1_hello_opts, len, id_length,
1098 ett_isis_hello_clv_unknown);
1099 } else if (hello_type == ISIS_TYPE_L2_HELLO) {
1100 isis_dissect_clvs(tvb, hello_tree, offset,
1101 clv_l2_hello_opts, len, id_length,
1102 ett_isis_hello_clv_unknown);
1103 } else {
1104 isis_dissect_clvs(tvb, hello_tree, offset,
1105 clv_ptp_hello_opts, len, id_length,
1106 ett_isis_hello_clv_unknown);
1111 * Name: isis_register_hello()
1113 * Description:
1114 * Register our protocol sub-sets with protocol manager.
1116 * Input:
1117 * int : protocol index for the ISIS protocol
1119 * Output:
1120 * void
1122 void
1123 isis_register_hello(int proto_isis) {
1124 static hf_register_info hf[] = {
1125 { &hf_isis_hello_circuit_reserved,
1126 { "Circuit type", "isis.hello.circuit_type",
1127 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1129 { &hf_isis_hello_source_id,
1130 { "SystemID {Sender of PDU}", "isis.hello.source_id",
1131 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1133 { &hf_isis_hello_holding_timer,
1134 { "Holding timer", "isis.hello.holding_timer",
1135 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1137 { &hf_isis_hello_pdu_length,
1138 { "PDU length", "isis.hello.pdu_length",
1139 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1141 { &hf_isis_hello_priority_reserved,
1142 { "Priority", "isis.hello.priority",
1143 FT_UINT8, BASE_DEC, NULL, ISIS_HELLO_P_RESERVED_MASK, NULL, HFILL }},
1145 { &hf_isis_hello_lan_id,
1146 { "SystemID {Designated IS}", "isis.hello.lan_id",
1147 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1149 { &hf_isis_hello_local_circuit_id,
1150 { "Local circuit ID", "isis.hello.local_circuit_id",
1151 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1153 { &hf_isis_hello_clv_ipv4_int_addr,
1154 { "IPv4 interface address", "isis.hello.clv_ipv4_int_addr",
1155 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1157 { &hf_isis_hello_clv_ipv6_int_addr,
1158 { "IPv6 interface address", "isis.hello.clv_ipv6_int_addr",
1159 FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1161 #if 0
1162 { &hf_isis_hello_clv_ptp_adj,
1163 { "Point-to-point Adjacency", "isis.hello.clv_ptp_adj",
1164 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1165 #endif
1167 { &hf_isis_hello_clv_mt,
1168 { "MT-ID", "isis.hello.clv_mt",
1169 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1171 { &hf_isis_hello_clv_restart_flags,
1172 { "Restart Signaling Flags", "isis.hello.clv_restart_flags",
1173 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1175 { &hf_isis_hello_clv_restart_flags_rr,
1176 { "Restart Request", "isis.hello.clv_restart_flags.rr",
1177 FT_BOOLEAN, 8, TFS(&tfs_true_false), ISIS_RESTART_RR,
1178 "When set, the router is beginning a graceful restart", HFILL }},
1180 { &hf_isis_hello_clv_restart_flags_ra,
1181 { "Restart Acknowledgment", "isis.hello.clv_restart_flags.ra",
1182 FT_BOOLEAN, 8, TFS(&tfs_true_false), ISIS_RESTART_RA,
1183 "When set, the router is willing to enter helper mode", HFILL }},
1185 { &hf_isis_hello_clv_restart_flags_sa,
1186 { "Suppress Adjacency", "isis.hello.clv_restart_flags.sa",
1187 FT_BOOLEAN, 8, TFS(&tfs_true_false), ISIS_RESTART_SA,
1188 "When set, the router is starting as opposed to restarting", HFILL }},
1190 { &hf_isis_hello_clv_restart_remain_time,
1191 { "Remaining holding time", "isis.hello.clv_restart.remain_time",
1192 FT_UINT16, BASE_DEC, NULL, 0x0,
1193 "How long the helper router will maintain the existing adjacency", HFILL }},
1195 { &hf_isis_hello_clv_restart_neighbor,
1196 { "Restarting Neighbor ID", "isis.hello.clv_restart.neighbor",
1197 FT_BYTES, BASE_NONE, NULL, 0x0,
1198 "The System ID of the restarting neighbor", HFILL }}
1200 static gint *ett[] = {
1201 &ett_isis_hello,
1202 &ett_isis_hello_clv_area_addr,
1203 &ett_isis_hello_clv_is_neighbors,
1204 &ett_isis_hello_clv_padding,
1205 &ett_isis_hello_clv_unknown,
1206 &ett_isis_hello_clv_nlpid,
1207 &ett_isis_hello_clv_authentication,
1208 &ett_isis_hello_clv_ip_authentication,
1209 &ett_isis_hello_clv_ipv4_int_addr,
1210 &ett_isis_hello_clv_ipv6_int_addr,
1211 &ett_isis_hello_clv_ptp_adj,
1212 &ett_isis_hello_clv_mt,
1213 &ett_isis_hello_clv_restart,
1214 &ett_isis_hello_clv_restart_flags,
1215 &ett_isis_hello_clv_mt_port_cap,
1216 &ett_isis_hello_clv_mt_port_cap_spb_mcid,
1217 &ett_isis_hello_clv_mt_port_cap_spb_aux_mcid,
1218 &ett_isis_hello_clv_mt_port_cap_spb_digest,
1219 &ett_isis_hello_clv_mt_port_cap_spb_bvid_tuples,
1220 &ett_isis_hello_clv_checksum
1223 proto_register_field_array(proto_isis, hf, array_length(hf));
1224 proto_register_subtree_array(ett, array_length(ett));