static void dissect_hello_restart_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int id_length, int length) { int restart_options=0; proto_tree *flags_tree; proto_item *restart_flags_item; proto_item *hold_time_item; const char *sep; const guint8 *neighbor_id; if (length >= 1) { restart_options = tvb_get_guint8(tvb, offset); restart_flags_item = proto_tree_add_uint ( tree, hf_isis_hello_clv_restart_flags, tvb, offset, 1, restart_options); flags_tree = proto_item_add_subtree(restart_flags_item, ett_isis_hello_clv_restart_flags); proto_tree_add_boolean (flags_tree, hf_isis_hello_clv_restart_flags_sa, tvb, offset, 1, restart_options ); proto_tree_add_boolean (flags_tree, hf_isis_hello_clv_restart_flags_ra, tvb, offset, 1, restart_options ); proto_tree_add_boolean (flags_tree, hf_isis_hello_clv_restart_flags_rr, tvb, offset, 1, restart_options ); /* Append an indication of which flags are set in the restart * options */ sep = initial_sep; APPEND_BOOLEAN_FLAG(ISIS_MASK_RESTART_SA(restart_options), restart_flags_item, "%sSA"); APPEND_BOOLEAN_FLAG(ISIS_MASK_RESTART_RA(restart_options), restart_flags_item, "%sRA"); APPEND_BOOLEAN_FLAG(ISIS_MASK_RESTART_RR(restart_options), restart_flags_item, "%sRR"); if (sep != initial_sep) { proto_item_append_text (restart_flags_item, ")"); } } /* The Remaining Time field should only be present if the RA flag is * set */ if (length >= 3 && ISIS_MASK_RESTART_RA(restart_options)) { hold_time_item = proto_tree_add_uint ( tree, hf_isis_hello_clv_restart_remain_time, tvb, offset+1, 2, tvb_get_ntohs(tvb, offset+1) ); proto_item_append_text( hold_time_item, "s" ); } /* The Restarting Neighbor ID should only be present if the RA flag is * set. */ if (length >= 3 + id_length && ISIS_MASK_RESTART_RA(restart_options)) { neighbor_id = tvb_get_ptr(tvb, offset+3, id_length); proto_tree_add_bytes_format( tree, hf_isis_hello_clv_restart_neighbor, tvb, offset+3, id_length, neighbor_id, "Restarting Neighbor ID: %s", print_system_id( neighbor_id, id_length ) ); } }
static void dissect_dec_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 protocol_version; guint8 bpdu_type; guint8 flags; proto_tree *bpdu_tree; proto_tree *flags_tree; proto_item *ti; const char *sep; col_set_str(pinfo->cinfo, COL_PROTOCOL, "DEC_STP"); col_clear(pinfo->cinfo, COL_INFO); bpdu_type = tvb_get_guint8(tvb, BPDU_TYPE); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(bpdu_type, bpdu_type_vals, "Unknown BPDU type (%u)")); } set_actual_length(tvb, DEC_BPDU_SIZE); if (tree) { ti = proto_tree_add_item(tree, proto_dec_bpdu, tvb, 0, DEC_BPDU_SIZE, FALSE); bpdu_tree = proto_item_add_subtree(ti, ett_dec_bpdu); protocol_version = tvb_get_guint8(tvb, BPDU_VERSION); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_proto_id, tvb, BPDU_DEC_CODE, 1, FALSE); proto_tree_add_uint(bpdu_tree, hf_dec_bpdu_type, tvb, BPDU_TYPE, 1, bpdu_type); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_version_id, tvb, BPDU_VERSION, 1, FALSE); flags = tvb_get_guint8(tvb, BPDU_FLAGS); ti = proto_tree_add_uint(bpdu_tree, hf_dec_bpdu_flags, tvb, BPDU_FLAGS, 1, flags); flags_tree = proto_item_add_subtree(ti, ett_dec_bpdu_flags); sep = initial_sep; APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_SHORT_TIMERS, ti, "%sUse short timers"); proto_tree_add_boolean(flags_tree, hf_dec_bpdu_flags_short_timers, tvb, BPDU_FLAGS, 1, flags); APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TCACK, ti, "%sTopology Change Acknowledgment"); proto_tree_add_boolean(flags_tree, hf_dec_bpdu_flags_tcack, tvb, BPDU_FLAGS, 1, flags); APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TC, ti, "%sTopology Change"); proto_tree_add_boolean(flags_tree, hf_dec_bpdu_flags_tc, tvb, BPDU_FLAGS, 1, flags); if (sep != initial_sep) { /* We put something in; put in the terminating ")" */ proto_item_append_text(ti, ")"); } proto_tree_add_item(bpdu_tree, hf_dec_bpdu_root_pri, tvb, BPDU_ROOT_PRI, 2, FALSE); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_root_mac, tvb, BPDU_ROOT_MAC, 6, FALSE); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_root_cost, tvb, BPDU_ROOT_PATH_COST, 2, FALSE); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_bridge_pri, tvb, BPDU_BRIDGE_PRI, 2, FALSE); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_bridge_mac, tvb, BPDU_BRIDGE_MAC, 6, FALSE); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_port_id, tvb, BPDU_PORT_IDENTIFIER, 1, FALSE); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_msg_age, tvb, BPDU_MESSAGE_AGE, 1, FALSE); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_hello_time, tvb, BPDU_HELLO_TIME, 1, FALSE); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_max_age, tvb, BPDU_MAX_AGE, 1, FALSE); proto_tree_add_item(bpdu_tree, hf_dec_bpdu_forward_delay, tvb, BPDU_FORWARD_DELAY, 1, FALSE); } }
static void dissect_bfd_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint flags; guint bfd_version; guint bfd_diag; guint bfd_sta = 0; guint bfd_flags; guint bfd_flags_h = 0; guint bfd_flags_p = 0; guint bfd_flags_f = 0; guint bfd_flags_c = 0; guint bfd_flags_a = 0; guint bfd_flags_d = 0; guint bfd_flags_m = 0; guint bfd_flags_d_v0 = 0; guint bfd_flags_p_v0 = 0; guint bfd_flags_f_v0 = 0; guint bfd_detect_time_multiplier; guint bfd_length; guint bfd_my_discriminator; guint bfd_your_discriminator; guint bfd_desired_min_tx_interval; guint bfd_required_min_rx_interval; guint bfd_required_min_echo_interval; proto_tree *bfd_tree = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BFD Control"); col_clear(pinfo->cinfo, COL_INFO); bfd_version = (tvb_get_guint8(tvb, 0) & 0xe0) >> 5; bfd_diag = (tvb_get_guint8(tvb, 0) & 0x1f); flags = tvb_get_guint8(tvb, 1); switch (bfd_version) { case 0: bfd_flags = flags; bfd_flags_h = flags & 0x80; bfd_flags_d_v0 = flags & 0x40; bfd_flags_p_v0 = flags & 0x20; bfd_flags_f_v0 = flags & 0x10; break; case 1: default: bfd_sta = flags & 0xc0; bfd_flags = flags & 0x3e; bfd_flags_p = flags & 0x20; bfd_flags_f = flags & 0x10; bfd_flags_c = flags & 0x08; bfd_flags_a = flags & 0x04; bfd_flags_d = flags & 0x02; bfd_flags_m = flags & 0x01; break; } bfd_detect_time_multiplier = tvb_get_guint8(tvb, 2); bfd_length = tvb_get_guint8(tvb, 3); bfd_my_discriminator = tvb_get_ntohl(tvb, 4); bfd_your_discriminator = tvb_get_ntohl(tvb, 8); bfd_desired_min_tx_interval = tvb_get_ntohl(tvb, 12); bfd_required_min_rx_interval = tvb_get_ntohl(tvb, 16); bfd_required_min_echo_interval = tvb_get_ntohl(tvb, 20); switch (bfd_version) { case 0: col_add_fstr(pinfo->cinfo, COL_INFO, "Diag: %s, Flags: 0x%02x", val_to_str_const(bfd_diag, bfd_control_v0_diag_values, "Unknown"), bfd_flags); break; case 1: default: col_add_fstr(pinfo->cinfo, COL_INFO, "Diag: %s, State: %s, Flags: 0x%02x", val_to_str_const(bfd_diag, bfd_control_v1_diag_values, "Unknown"), val_to_str_const(bfd_sta >> 6 , bfd_control_sta_values, "Unknown"), bfd_flags); break; } if (tree) { proto_item *ti; proto_tree *bfd_flags_tree; const char *sep; ti = proto_tree_add_protocol_format(tree, proto_bfd, tvb, 0, bfd_length, "BFD Control message"); bfd_tree = proto_item_add_subtree(ti, ett_bfd); proto_tree_add_uint(bfd_tree, hf_bfd_version, tvb, 0, 1, bfd_version << 5); proto_tree_add_uint(bfd_tree, hf_bfd_diag, tvb, 0, 1, bfd_diag); switch (bfd_version) { case 0: break; case 1: default: proto_tree_add_uint(bfd_tree, hf_bfd_sta, tvb, 1, 1, bfd_sta); break; } switch (bfd_version) { case 0: ti = proto_tree_add_text ( bfd_tree, tvb, 1, 1, "Message Flags: 0x%02x", bfd_flags); bfd_flags_tree = proto_item_add_subtree(ti, ett_bfd_flags); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_h, tvb, 1, 1, bfd_flags_h); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_d_v0, tvb, 1, 1, bfd_flags_d_v0); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_p_v0, tvb, 1, 1, bfd_flags_p_v0); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_f_v0, tvb, 1, 1, bfd_flags_f_v0); sep = initial_sep; APPEND_BOOLEAN_FLAG(bfd_flags_h, ti, "%sH"); APPEND_BOOLEAN_FLAG(bfd_flags_d_v0, ti, "%sD"); APPEND_BOOLEAN_FLAG(bfd_flags_p_v0, ti, "%sP"); APPEND_BOOLEAN_FLAG(bfd_flags_f_v0, ti, "%sF"); if (sep != initial_sep) { proto_item_append_text (ti, ")"); } break; case 1: default: ti = proto_tree_add_text ( bfd_tree, tvb, 1, 1, "Message Flags: 0x%02x", bfd_flags); bfd_flags_tree = proto_item_add_subtree(ti, ett_bfd_flags); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_p, tvb, 1, 1, bfd_flags_p); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_f, tvb, 1, 1, bfd_flags_f); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_c, tvb, 1, 1, bfd_flags_c); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_a, tvb, 1, 1, bfd_flags_a); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_d, tvb, 1, 1, bfd_flags_d); proto_tree_add_boolean(bfd_flags_tree, hf_bfd_flags_m, tvb, 1, 1, bfd_flags_m); sep = initial_sep; APPEND_BOOLEAN_FLAG(bfd_flags_p, ti, "%sP"); APPEND_BOOLEAN_FLAG(bfd_flags_f, ti, "%sF"); APPEND_BOOLEAN_FLAG(bfd_flags_c, ti, "%sC"); APPEND_BOOLEAN_FLAG(bfd_flags_a, ti, "%sA"); APPEND_BOOLEAN_FLAG(bfd_flags_d, ti, "%sD"); APPEND_BOOLEAN_FLAG(bfd_flags_m, ti, "%sM"); if (sep != initial_sep) { proto_item_append_text (ti, ")"); } break; } proto_tree_add_uint_format_value(bfd_tree, hf_bfd_detect_time_multiplier, tvb, 2, 1, bfd_detect_time_multiplier, "%u (= %u ms Detection time)", bfd_detect_time_multiplier, bfd_detect_time_multiplier * (bfd_desired_min_tx_interval/1000)); proto_tree_add_uint_format_value(bfd_tree, hf_bfd_message_length, tvb, 3, 1, bfd_length, "%u bytes", bfd_length); proto_tree_add_uint(bfd_tree, hf_bfd_my_discriminator, tvb, 4, 4, bfd_my_discriminator); proto_tree_add_uint(bfd_tree, hf_bfd_your_discriminator, tvb, 8, 4, bfd_your_discriminator); proto_tree_add_uint_format_value(bfd_tree, hf_bfd_desired_min_tx_interval, tvb, 12, 4, bfd_desired_min_tx_interval, "%4u ms (%u us)", bfd_desired_min_tx_interval/1000, bfd_desired_min_tx_interval); proto_tree_add_uint_format_value(bfd_tree, hf_bfd_required_min_rx_interval, tvb, 16, 4, bfd_required_min_rx_interval, "%4u ms (%u us)", bfd_required_min_rx_interval/1000, bfd_required_min_rx_interval); proto_tree_add_uint_format_value(bfd_tree, hf_bfd_required_min_echo_interval, tvb, 20, 4, bfd_required_min_echo_interval, "%4u ms (%u us)", bfd_required_min_echo_interval/1000, bfd_required_min_echo_interval); } /* if (tree) */ /* Dissect the authentication fields if the Authentication flag has * been set */ if (bfd_version && bfd_flags_a) { if (bfd_length >= 28) { dissect_bfd_authentication(tvb, pinfo, bfd_tree); } else { proto_item *ti = proto_tree_add_text(bfd_tree, tvb, 24, bfd_length-24, "Authentication: Length of the BFD frame is invalid (%d)", bfd_length); expert_add_info(pinfo, ti, &ei_bfd_auth_no_data); } } return; }
/* Code to actually dissect the PAGP packets */ static void dissect_pagp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint32 raw_word; guint16 raw_half_word; guint16 num_tlvs; guint16 tlv; guint16 len; guint16 ii; guint16 offset = PAGP_FIRST_TLV; guint8 raw_octet; guint8 flags; guchar *ch; proto_tree *pagp_tree = NULL; proto_item *pagp_item; proto_tree *flags_tree; proto_item *flags_item; proto_tree *tlv_tree; proto_item *tlv_item; const char *sep; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PAGP"); /* PAGP Protocol */ col_clear(pinfo->cinfo, COL_INFO); pinfo->current_proto = "PAGP"; raw_octet = tvb_get_guint8(tvb, PAGP_VERSION_NUMBER); if (tree) { pagp_item = proto_tree_add_protocol_format(tree, proto_pagp, tvb, 0, -1, "Port Aggregation Protocol"); pagp_tree = proto_item_add_subtree(pagp_item, ett_pagp); proto_tree_add_uint(pagp_tree, hf_pagp_version_number, tvb, PAGP_VERSION_NUMBER, 1, raw_octet); } col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(raw_octet, pdu_vers, "Unknown PDU version")); if (raw_octet == PAGP_FLUSH_PDU) { col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s", tvb_ether_to_str(tvb, PAGP_FLUSH_LOCAL_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_flush_local_device_id, tvb, PAGP_FLUSH_LOCAL_DEVICE_ID, 6, ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s", tvb_ether_to_str(tvb, PAGP_FLUSH_PARTNER_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_flush_partner_device_id, tvb, PAGP_FLUSH_PARTNER_DEVICE_ID, 6, ENC_NA); raw_word = tvb_get_ntohl(tvb, PAGP_FLUSH_TRANSACTION_ID); col_append_fstr(pinfo->cinfo, COL_INFO, "; Transaction ID: 0x%x ", raw_word); proto_tree_add_uint(pagp_tree, hf_pagp_flush_transaction_id, tvb, PAGP_FLUSH_TRANSACTION_ID, 4, raw_word); return; } /* Info PDU */ flags = tvb_get_guint8(tvb, PAGP_FLAGS); col_append_fstr(pinfo->cinfo, COL_INFO, "; Flags 0x%x", flags); if (tree) { flags_item = proto_tree_add_uint(pagp_tree, hf_pagp_flags, tvb, PAGP_FLAGS, 1, flags); flags_tree = proto_item_add_subtree(flags_item, ett_pagp_flags); sep = initial_sep; APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_SLOW_HELLO, flags_item, "%sSlow Hello"); proto_tree_add_boolean(flags_tree, hf_pagp_flags_slow_hello, tvb, PAGP_FLAGS, 1, flags); APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_AUTO_MODE, flags_item, "%sAuto Mode"); proto_tree_add_boolean(flags_tree, hf_pagp_flags_auto_mode, tvb, PAGP_FLAGS, 1, flags); APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_CONSISTENT_STATE, flags_item, "%sConsistent State"); proto_tree_add_boolean(flags_tree, hf_pagp_flags_consistent_state, tvb, PAGP_FLAGS, 1, flags); sep = cont_sep; if (sep != initial_sep) { /* We put something in; put in the terminating ")" */ proto_item_append_text(flags_item, ")"); } } col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s", tvb_ether_to_str(tvb, PAGP_LOCAL_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_local_device_id, tvb, PAGP_LOCAL_DEVICE_ID, 6, ENC_NA); if (tree) { raw_octet = tvb_get_guint8(tvb, PAGP_LOCAL_LEARN_CAP); proto_tree_add_uint(pagp_tree, hf_pagp_local_learn_cap, tvb, PAGP_LOCAL_LEARN_CAP, 1, raw_octet); raw_octet = tvb_get_guint8(tvb, PAGP_LOCAL_PORT_PRIORITY); proto_tree_add_uint(pagp_tree, hf_pagp_local_port_priority, tvb, PAGP_LOCAL_PORT_PRIORITY, 1, raw_octet); raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_SENT_PORT_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_local_sent_port_ifindex, tvb, PAGP_LOCAL_SENT_PORT_IFINDEX, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_GROUP_CAPABILITY); proto_tree_add_uint(pagp_tree, hf_pagp_local_group_capability, tvb, PAGP_LOCAL_GROUP_CAPABILITY, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_GROUP_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_local_group_ifindex, tvb, PAGP_LOCAL_GROUP_IFINDEX, 4, raw_word); } col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s", tvb_ether_to_str(tvb, PAGP_PARTNER_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_partner_device_id, tvb, PAGP_PARTNER_DEVICE_ID, 6, ENC_NA); if (tree) { raw_octet = tvb_get_guint8(tvb, PAGP_PARTNER_LEARN_CAP); proto_tree_add_uint(pagp_tree, hf_pagp_partner_learn_cap, tvb, PAGP_PARTNER_LEARN_CAP, 1, raw_octet); raw_octet = tvb_get_guint8(tvb, PAGP_PARTNER_PORT_PRIORITY); proto_tree_add_uint(pagp_tree, hf_pagp_partner_port_priority, tvb, PAGP_PARTNER_PORT_PRIORITY, 1, raw_octet); raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_SENT_PORT_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_partner_sent_port_ifindex, tvb, PAGP_PARTNER_SENT_PORT_IFINDEX, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_GROUP_CAPABILITY); proto_tree_add_uint(pagp_tree, hf_pagp_partner_group_capability, tvb, PAGP_PARTNER_GROUP_CAPABILITY, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_GROUP_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_partner_group_ifindex, tvb, PAGP_PARTNER_GROUP_IFINDEX, 4, raw_word); raw_half_word = tvb_get_ntohs(tvb, PAGP_PARTNER_COUNT); proto_tree_add_uint(pagp_tree, hf_pagp_partner_count, tvb, PAGP_PARTNER_COUNT, 2, raw_half_word); num_tlvs = tvb_get_ntohs(tvb, PAGP_NUM_TLVS); proto_tree_add_uint(pagp_tree, hf_pagp_num_tlvs, tvb, PAGP_NUM_TLVS, 2, num_tlvs); /* dump TLV entries */ for ( ii = 0; ii < num_tlvs; ii++ ) { tlv = tvb_get_ntohs(tvb, offset); len = tvb_get_ntohs(tvb, offset + 2); if ( len == 0 ) { proto_tree_add_text(pagp_tree, tvb, offset, -1, "Unknown data - TLV len=0"); return; } tlv_item = proto_tree_add_text (pagp_tree, tvb, offset, len, "TLV Entry #%d", ii+1); tlv_tree = proto_item_add_subtree (tlv_item, ett_pagp_tlvs); proto_tree_add_uint_format (tlv_tree, hf_pagp_tlv, tvb, offset,2,tlv,"Type = %d (%s)", tlv, val_to_str_const(tlv,tlv_types, "Unknown")) ; proto_tree_add_text (tlv_tree, tvb, offset+2, 2, "Length = %u bytes (includes Type and Length)", len) ; if ( tvb_reported_length_remaining(tvb, offset) < len ) { proto_tree_add_text(tlv_tree, tvb, offset, -1, "TLV length too large"); return; } switch (tlv) { case PAGP_TLV_DEVICE_NAME: ch = tvb_get_string(wmem_packet_scope(), tvb, offset+4, len-4); proto_tree_add_string(tlv_tree, hf_pagp_tlv_device_name, tvb, offset+4, len-4, ch); break; case PAGP_TLV_PORT_NAME: ch = tvb_get_string(wmem_packet_scope(), tvb, offset+4, len-4); proto_tree_add_string(tlv_tree, hf_pagp_tlv_port_name, tvb, offset+4, len-4, ch); break; case PAGP_TLV_AGPORT_MAC: proto_tree_add_item(tlv_tree, hf_pagp_tlv_agport_mac, tvb, offset+4, 6, ENC_NA); break; case PAGP_TLV_RESERVED: break; } offset += len; } } }