/* * Name: isis_dissect_area_address_clv() * * Description: * Take an area address CLV and display it pieces. An area address * CLV is n, x byte hex strings. * * Input: * tvbuff_t * : tvbuffer for packet data * proto_tree * : protocol display tree to fill out. May be NULL * int : offset into packet data where we are. * int : length of clv we are decoding * * Output: * void, but we will add to proto tree if !NULL. */ void isis_dissect_area_address_clv(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb, expert_field* expert, int offset, int length) { int arealen,area_idx; while ( length > 0 ) { arealen = tvb_get_guint8(tvb, offset); length--; if (length<=0) { proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1, "short address (no length for payload)"); return; } if ( arealen > length) { proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1, "short address, packet says %d, we have %d left", arealen, length ); return; } if ( tree ) { proto_item *ti; /* * Throw an exception rather than putting in a * partial address. */ tvb_ensure_bytes_exist ( tvb, offset, arealen + 1 ); ti = proto_tree_add_text ( tree, tvb, offset, arealen + 1, "Area address (%d): ", arealen ); /* * Lets turn the area address into "standard" * xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx format string. * this is a private routine as the print_nsap_net in * epan/osi_utils.c is incomplete and we need only * a subset - actually some nice placing of dots .... */ for (area_idx = 0; area_idx < arealen; area_idx++) { proto_item_append_text(ti, "%02x", tvb_get_guint8(tvb, offset+area_idx+1)); if (((area_idx & 1) == 0) && (area_idx + 1 < arealen)) { proto_item_append_text(ti, "."); } } } offset += arealen + 1; length -= arealen; /* length already adjusted for len fld*/ } }
/* * Name: isis_dissect_clvs() * * Description: * Dispatch routine to shred all the CLVs in a packet. We just * walk through the clv entries in the packet. For each one, we * search the passed in valid clv's for this protocol (opts) for * a matching code. If found, we add to the display tree and * then call the dissector. If it is not, we just post an * "unknown" clv entry using the passed in unknown clv tree id. * * Input: * tvbuff_t * : tvbuffer for packet data * proto_tree * : protocol display tree to fill out. May be NULL * int : offset into packet data where we are. * isis_clv_handle_t * : NULL dissector terminated array of codes * and handlers (along with tree text and tree id's). * int : length of CLV area. * int : length of IDs in packet. * int : unknown clv tree id * * Output: * void, but we will add to proto tree if !NULL. */ void isis_dissect_clvs(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset, const isis_clv_handle_t *opts, expert_field* expert_short_len, int len, int id_length, int unknown_tree_id _U_, int tree_type, int tree_length) { guint8 code; guint8 length; int q; proto_tree *clv_tree; while ( len > 0 ) { code = tvb_get_guint8(tvb, offset); offset += 1; len -= 1; if (len == 0) break; length = tvb_get_guint8(tvb, offset); offset += 1; len -= 1; if (len == 0) break; if ( len < length ) { proto_tree_add_expert_format(tree, pinfo, expert_short_len, tvb, offset, -1, "Short CLV header (%d vs %d)", length, len ); return; } q = 0; while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){ q++; } if ( opts[q].dissect ) { /* adjust by 2 for code/len octets */ clv_tree = proto_tree_add_subtree_format(tree, tvb, offset - 2, length + 2, *opts[q].tree_id, NULL, "%s (t=%u, l=%u)", opts[q].tree_text, opts[q].optcode, length); proto_tree_add_item(clv_tree, tree_type, tvb, offset - 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(clv_tree, tree_length, tvb, offset - 1, 1, ENC_BIG_ENDIAN); opts[q].dissect(tvb, pinfo, clv_tree, offset, id_length, length); } else { #if 0 /* XXX: Left as commented out in case info about "unknown code" is ever to be displayed under a sub-tree */ clv_tree = proto_tree_add_subtree_format(tree, tvb, offset - 2, length + 2, unknown_tree_id, NULL, "Unknown code %u (%u)", code, length); #else if (tree) { proto_tree_add_text(tree, tvb, offset - 2, length + 2, "Unknown code %u (%u)", code, length); } #endif } offset += length; len -= length; } }
static void dissect_v8_message_data(tvbuff_t *message_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree) { guint32 message_data_length; guint8 type; tvbuff_t *message_data_tvb; message_data_length = tvb_get_ntohl(message_tvb, V8_LENGTH_OFFSET) - V8_HEADER_LENGTH; if ((gint) message_data_length < 1) { proto_tree_add_expert_format(m2pa_tree, pinfo, &ei_length, message_tvb, V8_LENGTH_OFFSET, 4, "Invalid message data length: %u", message_data_length); /* XXX - is this really necessary? Can we just return since the expert info can still find the "malformed" packet? */ THROW(ReportedBoundsError); } message_data_tvb = tvb_new_subset_length(message_tvb, V8_MESSAGE_DATA_OFFSET, message_data_length); type = tvb_get_guint8(message_tvb, V8_TYPE_OFFSET); switch(type) { case V8_USER_DATA_TYPE: dissect_v8_user_data_message(message_data_tvb, pinfo, m2pa_item, m2pa_tree, tree); break; case V8_LINK_STATUS_TYPE: dissect_v8_link_status_message(message_data_tvb, pinfo, m2pa_tree); break; default: dissect_unknown_message(message_data_tvb, m2pa_tree); } }
/* PAPI Debug loop ! */ static int dissect_papi_debug(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree) { proto_item *ti; proto_tree *debug_tree, *debug_sub_tree; ti = proto_tree_add_item(tree, hf_papi_debug, tvb, offset, -1, ENC_NA); debug_tree = proto_item_add_subtree(ti, ett_papi); while(offset < tvb_reported_length(tvb)) { switch(tvb_get_guint8(tvb,offset)) { case 0x00: ti = proto_tree_add_item(debug_tree, hf_papi_debug_text, tvb, offset+3, tvb_get_ntohs(tvb,offset+1), ENC_ASCII|ENC_NA); debug_sub_tree = proto_item_add_subtree(ti, ett_papi); proto_tree_add_item(debug_sub_tree, hf_papi_debug_text_length, tvb, offset+1, 2, ENC_BIG_ENDIAN); offset += tvb_get_ntohs(tvb, offset+1) + 3; break; case 0x01: proto_tree_add_item(debug_tree, hf_papi_debug_48bits, tvb, offset+1, 6, ENC_BIG_ENDIAN); offset += 7; break; case 0x02: proto_tree_add_item(debug_tree, hf_papi_debug_8bits, tvb, offset+1, 1, ENC_BIG_ENDIAN); offset += 2; break; case 0x03: proto_tree_add_item(debug_tree, hf_papi_debug_16bits, tvb, offset+1, 2, ENC_BIG_ENDIAN); offset += 3; break; case 0x04: proto_tree_add_item(debug_tree, hf_papi_debug_32bits, tvb, offset+1, 4, ENC_BIG_ENDIAN); offset += 5; break; case 0x05: proto_tree_add_item(debug_tree, hf_papi_debug_ipv4, tvb, offset+1, 4, ENC_BIG_ENDIAN); offset += 5; break; case 0x07: proto_tree_add_item(debug_tree, hf_papi_debug_16bits, tvb, offset+1, 2, ENC_BIG_ENDIAN); offset += 3; break; case 0x08: ti = proto_tree_add_item(debug_tree, hf_papi_debug_bytes, tvb, offset+3, tvb_get_ntohs(tvb,offset+1), ENC_NA); debug_sub_tree = proto_item_add_subtree(ti, ett_papi); proto_tree_add_item(debug_sub_tree, hf_papi_debug_bytes_length, tvb, offset+1, 2, ENC_BIG_ENDIAN); offset += tvb_get_ntohs(tvb,offset+1) + 3; break; case 0x09: proto_tree_add_item(debug_tree, hf_papi_debug_64bits, tvb, offset+1, 8, ENC_BIG_ENDIAN); offset += 9; break; default: proto_tree_add_expert_format(debug_tree, pinfo, &ei_papi_debug_unknown, tvb, offset, 1, "Unknown (%d)", tvb_get_guint8(tvb, offset)); offset +=1; } } return offset; }
static gint dissect_counted_values(tvbuff_t *tvb, gint offset, int hf_id, packet_info *pinfo, proto_tree *tree, gboolean single, guint encoding) { proto_item *item; guint32 length, count, i; count = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_tnef_values_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); if(count > 1) { if(single) { item = proto_tree_add_expert_format(tree, pinfo, &ei_tnef_expect_single_item, tvb, offset, 4, "Expecting a single item but found %d", count); tree = proto_item_add_subtree(item, ett_tnef_counted_items); } } offset += 4; for(i = 0; i < count; i++) { length = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_tnef_value_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_id, tvb, offset, length, encoding); offset += length; /* XXX: may be padding ? */ } return offset; }
static void dissect_v8_message_data(tvbuff_t *message_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree) { guint32 message_data_length; guint8 type; tvbuff_t *message_data_tvb; message_data_length = tvb_get_ntohl(message_tvb, V8_LENGTH_OFFSET) - V8_HEADER_LENGTH; if ((gint) message_data_length < 1) { proto_tree_add_expert_format(m2pa_tree, pinfo, &ei_length, message_tvb, V8_LENGTH_OFFSET, 4, "Invalid message data length: %u", message_data_length); return; } message_data_tvb = tvb_new_subset_length(message_tvb, V8_MESSAGE_DATA_OFFSET, message_data_length); type = tvb_get_guint8(message_tvb, V8_TYPE_OFFSET); switch(type) { case V8_USER_DATA_TYPE: dissect_v8_user_data_message(message_data_tvb, pinfo, m2pa_item, m2pa_tree, tree); break; case V8_LINK_STATUS_TYPE: dissect_v8_link_status_message(message_data_tvb, pinfo, m2pa_tree); break; default: dissect_unknown_message(message_data_tvb, m2pa_tree); } }
static void dissect_bfd_authentication(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 24; guint8 auth_type; guint8 auth_len; proto_item *ti = NULL; proto_item *auth_item = NULL; proto_tree *auth_tree = NULL; guint8 *password; auth_type = tvb_get_guint8(tvb, offset); auth_len = tvb_get_guint8(tvb, offset + 1); if (tree) { auth_tree = proto_tree_add_subtree_format(tree, tvb, offset, auth_len, ett_bfd_auth, NULL, "Authentication: %s", val_to_str(auth_type, bfd_control_auth_type_values, "Unknown Authentication Type (%d)") ); proto_tree_add_item(auth_tree, hf_bfd_auth_type, tvb, offset, 1, ENC_BIG_ENDIAN); ti = proto_tree_add_item(auth_tree, hf_bfd_auth_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); proto_item_append_text(ti, " bytes"); proto_tree_add_item(auth_tree, hf_bfd_auth_key, tvb, offset + 2, 1, ENC_BIG_ENDIAN); } switch (auth_type) { case BFD_AUTH_SIMPLE: if (tree) { password = tvb_get_string_enc(wmem_packet_scope(), tvb, offset+3, auth_len-3, ENC_ASCII); proto_tree_add_string(auth_tree, hf_bfd_auth_password, tvb, offset+3, auth_len-3, password); proto_item_append_text(auth_item, ": %s", password); } break; case BFD_AUTH_MD5: case BFD_AUTH_MET_MD5: case BFD_AUTH_SHA1: case BFD_AUTH_MET_SHA1: if (auth_len != get_bfd_required_auth_len(auth_type)) { proto_tree_add_expert_format(auth_tree, pinfo, &ei_bfd_auth_len_invalid, tvb, offset, auth_len, "Length of authentication section (%d) is invalid for Authentication Type: %s", auth_len, val_to_str(auth_type, bfd_control_auth_type_values, "Unknown Authentication Type (%d)") ); proto_item_append_text(auth_item, ": Invalid Authentication Section"); } if (tree) { proto_tree_add_item(auth_tree, hf_bfd_auth_seq_num, tvb, offset+4, 4, ENC_BIG_ENDIAN); proto_tree_add_item(auth_tree, hf_bfd_checksum, tvb, offset+8, get_bfd_checksum_len(auth_type), ENC_NA); } break; default: break; } }
/* * Name: isis_dissect_te_router_id_clv() * * Description: * Display the Traffic Engineering Router ID TLV #134. * This TLV is like the IP Interface TLV, except that * only _one_ IP address is present * * Input: * tvbuff_t * : tvbuffer for packet data * proto_tree * : protocol display tree to fill out. May be NULL * int : offset into packet data where we are. * int : length of clv we are decoding * int : tree id to use for proto tree. * * Output: * void, but we will add to proto tree if !NULL. */ void isis_dissect_te_router_id_clv(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb, expert_field* expert, int offset, int length, int tree_id) { if ( length <= 0 ) { return; } if ( length != 4 ) { proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1, "malformed Traffic Engineering Router ID (%d vs 4)",length ); return; } proto_tree_add_item(tree, tree_id, tvb, offset, 4, ENC_BIG_ENDIAN); }
/* XXX this one should be broken out later and moved into the conformance file */ static int dissect_cmip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data) { struct SESSION_DATA_STRUCTURE* session; proto_item *item; proto_tree *tree; asn1_ctx_t asn1_ctx; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); /* Reject the packet if data is NULL */ if (data == NULL) return 0; session = (struct SESSION_DATA_STRUCTURE*)data; if(session->spdu_type == 0 ) { proto_tree_add_expert_format(parent_tree, pinfo, &ei_wrong_spdu_type, tvb, 0, -1, "Internal error: wrong spdu type %x from session dissector.", session->spdu_type); return 0; } asn1_ctx.private_data = session; item = proto_tree_add_item(parent_tree, proto_cmip, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_cmip); col_set_str(pinfo->cinfo, COL_PROTOCOL, "CMIP"); col_clear(pinfo->cinfo, COL_INFO); switch(session->spdu_type){ case SES_CONNECTION_REQUEST: case SES_CONNECTION_ACCEPT: case SES_DISCONNECT: case SES_FINISH: case SES_REFUSE: dissect_cmip_CMIPUserInfo(FALSE,tvb,0,&asn1_ctx,tree,-1); break; case SES_ABORT: dissect_cmip_CMIPAbortInfo(FALSE,tvb,0,&asn1_ctx,tree,-1); break; case SES_DATA_TRANSFER: dissect_cmip_ROS(FALSE,tvb,0,&asn1_ctx,tree,-1); break; default: ; } return tvb_captured_length(tvb); }
tvbuff_t * dissect_cbs_data(guint8 sms_encoding, tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint offset ) { tvbuff_t * tvb_out = NULL; int length = tvb_length(tvb) - offset; gchar *utf8_text = NULL, *utf8_out; switch(sms_encoding){ case SMS_ENCODING_7BIT: case SMS_ENCODING_7BIT_LANG: utf8_text = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), tvb, offset<<3, (length*8)/7); utf8_out = g_strdup(utf8_text); tvb_out = tvb_new_child_real_data(tvb, utf8_out, (guint)strlen(utf8_out), (guint)strlen(utf8_out)); tvb_set_free_cb(tvb_out, g_free); add_new_data_source(pinfo, tvb_out, "unpacked 7 bit data"); break; case SMS_ENCODING_8BIT: /* * XXX - encoding is "user-defined". Have a preference? */ utf8_text = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, length, ENC_ASCII|ENC_NA); utf8_out = g_strdup(utf8_text); tvb_out = tvb_new_child_real_data(tvb, utf8_out, (guint)strlen(utf8_out), (guint)strlen(utf8_out)); tvb_set_free_cb(tvb_out, g_free); add_new_data_source(pinfo, tvb_out, "unpacked 7 bit data"); break; case SMS_ENCODING_UCS2: case SMS_ENCODING_UCS2_LANG: utf8_text = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, length, ENC_UCS_2|ENC_BIG_ENDIAN); utf8_out = g_strdup(utf8_text); tvb_out = tvb_new_child_real_data(tvb, utf8_out, (guint)strlen(utf8_out), (guint)strlen(utf8_out)); tvb_set_free_cb(tvb_out, g_free); add_new_data_source(pinfo, tvb_out, "unpacked UCS-2 data"); break; default: proto_tree_add_expert_format(tree, pinfo, &ei_gsm_cbs_unhandled_encoding, tvb, offset, length, "Unhandled encoding %d of CBS String", sms_encoding); break; } return tvb_out; }
static void gog_attrs_tree(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, mate_gog* gog) { AVPN* c; proto_tree *avpl_t; int* hfi_p; avpl_t = proto_tree_add_subtree_format(tree,tvb,0,0,gog->cfg->ett_attr,NULL,"%s Attributes",gog->cfg->name); for ( c = gog->avpl->null.next; c->avp; c = c->next) { hfi_p = (int *)g_hash_table_lookup(gog->cfg->my_hfids,(char*)c->avp->n); if (hfi_p) { proto_tree_add_string(avpl_t,*hfi_p,tvb,0,0,c->avp->v); } else { proto_tree_add_expert_format(avpl_t,pinfo,&ei_mate_undefined_attribute,tvb,0,0,"Undefined attribute: %s=%s",c->avp->n, c->avp->v); } } }
static int call_rtse_external_type_callback(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_) { const char *oid = NULL; if (actx->external.indirect_ref_present) { oid = (const char *)find_oid_by_pres_ctx_id(actx->pinfo, actx->external.indirect_reference); if (!oid) proto_tree_add_expert_format(tree, actx->pinfo, &ei_rtse_abstract_syntax, tvb, offset, tvb_captured_length_remaining(tvb, offset), "Unable to determine abstract syntax for indirect reference: %d.", actx->external.indirect_reference); } else if (actx->external.direct_ref_present) { oid = actx->external.direct_reference; } if (oid) offset = call_rtse_oid_callback(oid, tvb, offset, actx->pinfo, top_tree ? top_tree : tree, actx->private_data); return offset; }
/* * Name: isis_dissect_ip_int_clv() * * Description: * Take apart the CLV that lists all the IP interfaces. The * meaning of which is slightly different for the different base packet * types, but the display is not different. What we have is n ip * addresses, plain and simple. * * Input: * tvbuff_t * : tvbuffer for packet data * proto_tree * : protocol display tree to fill out. May be NULL * int : offset into packet data where we are. * int : length of clv we are decoding * int : tree id to use for proto tree. * * Output: * void, but we will add to proto tree if !NULL. */ void isis_dissect_ip_int_clv(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb, expert_field* expert, int offset, int length, int tree_id) { if ( length <= 0 ) { return; } while ( length > 0 ) { if ( length < 4 ) { proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1, "Short IP interface address (%d vs 4)",length ); return; } if ( tree ) { proto_tree_add_item(tree, tree_id, tvb, offset, 4, ENC_BIG_ENDIAN); } offset += 4; length -= 4; } }
static int check_term(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree) { /* First, check for CRLF, or, if global_beep_strict_term is false, * one of CR or LF ... If neither of these hold, we add an element * that complains of a protocol violation, and return -1, else * we add a terminator to the tree (possibly non-standard) and return * the count of characters we saw ... This may throw off the rest of the * dissection ... so-be-it! */ if ((tvb_get_guint8(tvb, offset) == 0x0d && tvb_get_guint8(tvb, offset + 1) == 0x0a)){ /* Correct terminator */ proto_tree_add_item(tree, hf_beep_crlf_terminator, tvb, offset, 2, ENC_NA); return 2; } if ((tvb_get_guint8(tvb, offset) == 0x0d) && !global_beep_strict_term) { proto_tree_add_expert(tree, pinfo, &ei_beep_cr_terminator, tvb, offset, 1); return 1; } if ((tvb_get_guint8(tvb, offset) == 0x0a) && !global_beep_strict_term) { proto_tree_add_expert(tree, pinfo, &ei_beep_lf_terminator, tvb, offset, 1); return 1; } proto_tree_add_expert_format(tree, pinfo, &ei_beep_invalid_terminator, tvb, offset, 1, "Terminator: %s", tvb_format_text(tvb, offset, 2)); return -1; }
/* * Name: isis_dissect_ipv6_int_clv() * * Description: * Take apart the CLV that lists all the IPv6 interfaces. The * meaning of which is slightly different for the different base packet * types, but the display is not different. What we have is n ip * addresses, plain and simple. * * Input: * tvbuff_t * : tvbuffer for packet data * proto_tree * : protocol display tree to fill out. May be NULL * int : offset into packet data where we are. * int : length of clv we are decoding * int : tree id to use for proto tree. * * Output: * void, but we will add to proto tree if !NULL. */ void isis_dissect_ipv6_int_clv(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb, expert_field* expert, int offset, int length, int tree_id) { guint8 addr [16]; if ( length <= 0 ) { return; } while ( length > 0 ) { if ( length < 16 ) { proto_tree_add_expert_format(tree, pinfo, expert, tvb, offset, -1, "Short IPv6 interface address (%d vs 16)",length ); return; } tvb_memcpy(tvb, addr, offset, sizeof(addr)); if ( tree ) { proto_tree_add_ipv6(tree, tree_id, tvb, offset, 16, addr); } offset += 16; length -= 16; } }
static int dissect_mpls_y1711(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { struct mplsinfo *mplsinfo; int offset = 0; proto_item *ti; proto_tree *mpls_y1711_tree; int functype; tvbuff_t *data_tvb; static const guint8 allone[] = { 0xff, 0xff }; static const guint8 allzero[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Reject the packet if data is NULL */ if (data == NULL) return 0; mplsinfo = (struct mplsinfo *)data; functype = tvb_get_guint8(tvb, offset); col_append_fstr(pinfo->cinfo, COL_INFO, " (Y.1711: %s)", (functype == 0x01) ? "CV" : (functype == 0x02) ? "FDI" : (functype == 0x03) ? "BDI" : (functype == 0x07) ? "FDD" : "reserved/unknown"); /* sanity checks */ if (tvb_reported_length(tvb) < 44) { /* * ITU-T Y.1711, 5.3: PDUs must have a minimum payload length of * 44 bytes */ proto_tree_add_expert(tree, pinfo, &ei_mpls_y1711_minimum_payload, tvb, offset, -1); data_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, data_tvb, pinfo, tree); return tvb_reported_length(tvb); } ti = proto_tree_add_text(tree, tvb, offset, 44, "Y.1711 OAM"); mpls_y1711_tree = proto_item_add_subtree(ti, ett_mpls_y1711); /* checks for exp, bos and ttl encoding */ if (mplsinfo->label != MPLS_LABEL_OAM_ALERT) proto_tree_add_expert_format(mpls_y1711_tree, pinfo, &ei_mpls_y1711_no_OAM_alert_label, tvb, offset - 4, 3, "Warning: Y.1711 but no OAM alert label (%d) ?!", MPLS_LABEL_OAM_ALERT); if (mplsinfo->exp != 0) proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_exp_bits_not_zero, tvb, offset - 2, 1); if (mplsinfo->bos != 1) proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_s_bit_not_one, tvb, offset - 2, 1); if (mplsinfo->ttl != 1) proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_ttl_not_one, tvb, offset - 1, 1); /* starting dissection */ functype = tvb_get_guint8(tvb, offset); proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_function_type, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; switch (functype) { case 0x01: /* CV */ { /* 3 octets reserved (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 3) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_reserved_not_zero, tvb, offset, 3); } offset += 3; /* ttsi (ipv4 flavor as in RFC 2373) */ if (tvb_memeql(tvb, offset, allzero, 10) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 10); } offset += 10; if (tvb_memeql(tvb, offset, allone, 2) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_ff, tvb, offset, 2); } offset += 2; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsr_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsp_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* 18 octets of padding (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 18) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 18); } offset += 18; } break; case 0x02: /* FDI */ case 0x03: /* BDI */ { /* 1 octets reserved (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 1) == -1) { proto_tree_add_expert_format(mpls_y1711_tree, pinfo, &ei_mpls_y1711_reserved_not_zero, tvb, offset, 3, "Error: this byte is reserved and must be 0x00"); } offset++; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_defect_type, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* * ttsi (ipv4 flavor as in RFC 2373) is optional if not used must * be set to all 0x00 */ if (tvb_memeql(tvb, offset, allzero, 20) == 0) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_ttsi_not_preset, tvb, offset, 20); offset += 20; } else { if (tvb_memeql(tvb, offset, allzero, 10) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 10); } offset += 10; if (tvb_memeql(tvb, offset, allone, 2) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_ff, tvb, offset, 2); } offset += 2; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsr_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsp_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } /* defect location */ proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_defect_location, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* 14 octets of padding (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 14) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 14); } offset += 14; } break; case 0x07: /* FDD */ { /* 3 octets reserved (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 3) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_reserved_not_zero, tvb, offset, 3); } offset += 3; /* ttsi (ipv4 flavor as in RFC 2373) */ if (tvb_memeql(tvb, offset, allzero, 10) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 10); } offset += 10; if (tvb_memeql(tvb, offset, allone, 2) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_ff, tvb, offset, 2); } offset += 2; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsr_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsp_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_frequency, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; /* 17 octets of padding (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 17) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 17); } offset += 17; } break; default: proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_unknown_pdu, tvb, offset - 1, -1); return offset; } /* BIP16 */ proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_bip16, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; }
/* * Dissect DISP PDUs inside a ROS PDUs */ static int dissect_disp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data) { int offset = 0; int old_offset; proto_item *item; proto_tree *tree; struct SESSION_DATA_STRUCTURE* session; int (*disp_dissector)(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_) = NULL; const char *disp_op_name; asn1_ctx_t asn1_ctx; /* do we have operation information from the ROS dissector */ if (data == NULL) return 0; session = (struct SESSION_DATA_STRUCTURE*)data; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); asn1_ctx.private_data = session; item = proto_tree_add_item(parent_tree, proto_disp, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_disp); col_set_str(pinfo->cinfo, COL_PROTOCOL, "DISP"); col_clear(pinfo->cinfo, COL_INFO); switch(session->ros_op & ROS_OP_MASK) { case (ROS_OP_BIND | ROS_OP_ARGUMENT): /* BindInvoke */ disp_dissector = dissect_disp_DSAShadowBindArgument; disp_op_name = "Shadow-Bind-Argument"; break; case (ROS_OP_BIND | ROS_OP_RESULT): /* BindResult */ disp_dissector = dissect_disp_DSAShadowBindResult; disp_op_name = "Shadow-Bind-Result"; break; case (ROS_OP_BIND | ROS_OP_ERROR): /* BindError */ disp_dissector = dissect_disp_DSAShadowBindError; disp_op_name = "Shadow-Bind-Error"; break; case (ROS_OP_INVOKE | ROS_OP_ARGUMENT): /* Invoke Argument */ switch(session->ros_op & ROS_OP_OPCODE_MASK) { case 1: /* requestShadowUpdate */ disp_dissector = dissect_disp_RequestShadowUpdateArgument; disp_op_name = "Request-Shadow-Update-Argument"; break; case 2: /* updateShadow*/ disp_dissector = dissect_disp_UpdateShadowArgument; disp_op_name = "Update-Shadow-Argument"; break; case 3: /* coordinateShadowUpdate */ disp_dissector = dissect_disp_CoordinateShadowUpdateArgument; disp_op_name = "Coordinate-Shadow-Update-Argument"; break; default: proto_tree_add_expert_format(tree, pinfo, &ei_disp_unsupported_opcode, tvb, offset, -1, "Unsupported DISP opcode (%d)", session->ros_op & ROS_OP_OPCODE_MASK); break; } break; case (ROS_OP_INVOKE | ROS_OP_RESULT): /* Return Result */ switch(session->ros_op & ROS_OP_OPCODE_MASK) { case 1: /* requestShadowUpdate */ disp_dissector = dissect_disp_RequestShadowUpdateResult; disp_op_name = "Request-Shadow-Result"; break; case 2: /* updateShadow */ disp_dissector = dissect_disp_UpdateShadowResult; disp_op_name = "Update-Shadow-Result"; break; case 3: /* coordinateShadowUpdate */ disp_dissector = dissect_disp_CoordinateShadowUpdateResult; disp_op_name = "Coordinate-Shadow-Update-Result"; break; default: proto_tree_add_expert_format(tree, pinfo, &ei_disp_unsupported_opcode, tvb, offset, -1, "Unsupported DISP opcode (%d)", session->ros_op & ROS_OP_OPCODE_MASK); break; } break; case (ROS_OP_INVOKE | ROS_OP_ERROR): /* Return Error */ switch(session->ros_op & ROS_OP_OPCODE_MASK) { case 1: /* shadowError */ disp_dissector = dissect_disp_ShadowError; disp_op_name = "Shadow-Error"; break; default: proto_tree_add_expert_format(tree, pinfo, &ei_disp_unsupported_errcode, tvb, offset, -1, "Unsupported DISP errcode (%d)", session->ros_op & ROS_OP_OPCODE_MASK); break; } break; default: proto_tree_add_expert(tree, pinfo, &ei_disp_unsupported_pdu, tvb, offset, -1); return tvb_captured_length(tvb); } if(disp_dissector) { col_set_str(pinfo->cinfo, COL_INFO, disp_op_name); while (tvb_reported_length_remaining(tvb, offset) > 0){ old_offset=offset; offset=(*disp_dissector)(FALSE, tvb, offset, &asn1_ctx, tree, -1); if(offset == old_offset){ proto_tree_add_expert(tree, pinfo, &ei_disp_zero_pdu, tvb, offset, -1); break; } } } return tvb_captured_length(tvb); }
static int dissect_pbb_addressblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint maxoffset, guint8 addressType, guint8 addressSize) { guint8 addr[MAX_ADDR_SIZE]; guint8 numAddr; guint8 address_flags; guint8 head_length = 0, tail_length = 0; guint block_length = 0, midSize = 0; guint block_index = 0, head_index = 0, tail_index = 0, mid_index = 0, prefix_index = 0; proto_tree *addr_tree = NULL; proto_tree *addrFlags_tree = NULL; proto_tree *addrValue_tree = NULL; proto_item *addr_item = NULL; proto_item *addrFlags_item = NULL; proto_item *addrValue_item = NULL; int i = 0; if (maxoffset - offset < 2) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for minimal addressblock header"); return tvb_reported_length(tvb); } DISSECTOR_ASSERT(addressSize <= MAX_ADDR_SIZE); memset(addr, 0, addressSize); block_length = 2; block_index = offset; midSize = addressSize; numAddr = tvb_get_guint8(tvb, offset++); address_flags = tvb_get_guint8(tvb, offset++); if ((address_flags & ADDR_HASHEAD) != 0) { head_index = offset; if (maxoffset - offset <= 0) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock head"); return tvb_reported_length(tvb); } head_length = tvb_get_guint8(tvb, offset++); if (head_length > addressSize-1) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "address head length is too long"); return tvb_reported_length(tvb); } if (maxoffset - offset < head_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock head"); return tvb_reported_length(tvb); } tvb_memcpy(tvb, addr, offset, head_length); midSize -= head_length; block_length += (head_length+1); offset += head_length; } if ((address_flags & ADDR_HASZEROTAIL) != 0) { tail_index = offset; if (maxoffset - offset <= 0) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock tail"); return tvb_reported_length(tvb); } tail_length = tvb_get_guint8(tvb, offset++); if (tail_length > addressSize-1-head_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "address tail length is too long"); return tvb_reported_length(tvb); } midSize -= tail_length; block_length++; } else if ((address_flags & ADDR_HASFULLTAIL) != 0) { tail_index = offset; if (maxoffset - offset <= 0) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock tail"); return tvb_reported_length(tvb); } tail_length = tvb_get_guint8(tvb, offset++); if (tail_length > addressSize-1-head_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "address tail length is too long"); return tvb_reported_length(tvb); } if (maxoffset - offset < tail_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock tail"); return tvb_reported_length(tvb); } tvb_memcpy(tvb, &addr[addressSize - tail_length], offset, tail_length); midSize -= tail_length; block_length += (tail_length+1); offset += tail_length; } mid_index = offset; block_length += numAddr * midSize; offset += numAddr * midSize; if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) { prefix_index = offset; block_length++; } else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) { prefix_index = offset; block_length += numAddr; } if (maxoffset < block_index + block_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for address block"); return maxoffset; } /* add address tree */ addr_item = proto_tree_add_item(tree, hf_packetbb_addr, tvb, block_index, block_length, ENC_NA); addr_tree = proto_item_add_subtree(addr_item, ett_packetbb_addr); proto_item_append_text(addr_item, " (%d addresses)", numAddr); /* add num-addr */ proto_tree_add_item(addr_tree, hf_packetbb_addr_num, tvb, block_index, 1, ENC_BIG_ENDIAN); /* add flags */ addrFlags_item = proto_tree_add_item(addr_tree, hf_packetbb_addr_flags, tvb, block_index+1, 1, ENC_BIG_ENDIAN); addrFlags_tree = proto_item_add_subtree(addrFlags_item, ett_packetbb_addr_flags); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hashead, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasfulltail, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_haszerotail, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hassingleprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasmultiprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN); if ((address_flags & ADDR_HASHEAD) != 0) { /* add head */ proto_tree_add_item(addr_tree, hf_packetbb_addr_head, tvb, head_index, head_length+1, ENC_NA); } if ((address_flags & ADDR_HASFULLTAIL) != 0) { /* add full tail */ proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, tail_length+1, ENC_NA); } else if ((address_flags & ADDR_HASZEROTAIL) != 0) { /* add zero tail */ proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, 1, ENC_NA); } for (i=0; i<numAddr; i++) { guint32 ipv4 = 0; guint8 prefix = addressSize * 8; tvb_memcpy(tvb, &addr[head_length], mid_index + midSize*i, midSize); ipv4 = (addr[3] << 24) + (addr[2] << 16) + (addr[1] << 8) + addr[0]; switch (addressType) { case 0: addrValue_item = proto_tree_add_ipv4(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, ipv4); break; case 1: addrValue_item = proto_tree_add_ipv6(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, (struct e_in6_addr *)addr); break; case 2: addrValue_item = proto_tree_add_ether(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, addr); break; case 3: addrValue_item = proto_tree_add_bytes(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, addr); break; default: break; } addrValue_tree = proto_item_add_subtree(addrValue_item, ett_packetbb_addr_value); proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_mid, tvb, mid_index + midSize*i, midSize, ENC_NA); if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) { prefix = tvb_get_guint8(tvb, prefix_index); proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index, 1, ENC_BIG_ENDIAN); } else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) { prefix = tvb_get_guint8(tvb, prefix_index + i); proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index + i, 1, ENC_BIG_ENDIAN); } proto_item_append_text(addrValue_item, "/%d", prefix); } offset = dissect_pbb_tlvblock(tvb, pinfo, addr_tree, block_index + block_length, maxoffset, numAddr); return offset; }
void dissect_mqpcf_parm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mq_tree, guint offset, guint32 uCount, guint bLittleEndian, gboolean bParse) { guint32 u = 0; guint32 tOfs = 0; guint32 uLenF; char strPrm[256]; guint32 uTyp; guint32 uLen = 0; guint32 uPrm; guint32 uCnt; guint32 uCCS; guint32 uSLn; guint32 uVal; guint64 uVal64; guint32 uDig; const char sMaxLst[] = " Max # of List reached. DECODE interrupted (actual %u of %u)"; const char sPrmLn0[] = " MQPrm[%3u] has a zero length. DECODE Failed (MQPrm Count: %u)"; const char sMaxPrm[] = " Max # of Parm reached. DECODE interrupted (actual %u of %u)"; const char sPrmCnt[] = " Cnt=-1 and Length(%u) < 16. DECODE interrupted for elem %u"; proto_item *ti = NULL; proto_tree *tree = NULL; if (uCount == (guint32)-1) { guint32 xOfs = offset; uCnt = 0; while (tvb_reported_length_remaining(tvb, xOfs) >= 16) { uLen = tvb_get_guint32(tvb, xOfs + 4, bLittleEndian); if (uLen < 16) { proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_PrmCnt, tvb, xOfs, 16, sPrmCnt, uLen, uCnt); break; } uCnt++; xOfs += uLen; } uCount = uCnt; } uDig = dissect_mqpcf_getDigits(uCount); for (u = 0; u < uCount && u < mq_pcf_maxprm; u++) { tOfs = offset; uTyp = tvb_get_guint32(tvb, offset , bLittleEndian); uLen = tvb_get_guint32(tvb, offset + 4, bLittleEndian); if (uLen == 0) { proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_prmln0, tvb, offset, 12, sPrmLn0, u+1, uCount); u = uCount; break; } uPrm = tvb_get_guint32(tvb, offset + 8, bLittleEndian); uLenF = 12; if (bParse) g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d-%-30.30s", "MQPrm", uDig, u+1, uTyp, val_to_str_ext_const(uTyp, GET_VALS_EXTP(PrmTyp), " Unknown") + 6, uPrm, uPrm, val_to_str_ext_const(uPrm, GET_VALS_EXTP(PrmId), "Unknown")); else g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d", "XtraD", uDig, u+1, uTyp, val_to_str_ext_const(uTyp, GET_VALS_EXTP(PrmTyp), " Unknown") + 6, uPrm, uPrm); switch (uTyp) { case MQ_MQCFT_NONE: break; case MQ_MQCFT_COMMAND: break; case MQ_MQCFT_RESPONSE: break; case MQ_MQCFT_INTEGER: { const guint8 *pVal = NULL; uVal = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian); if (bParse) pVal = dissect_mqpcf_parm_getintval(uPrm, uVal); if (pVal) { tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %8x-(%9d) %s", strPrm, uVal, uVal, pVal); } else { tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %8x-(%9d)", strPrm, uVal, uVal); } proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); dissect_mqpcf_parm_int(tvb, tree, offset+uLenF, uPrm, uVal, hf_mq_pcf_int, 0, 0, 0, bParse); } break; case MQ_MQCFT_STRING: { guint8 *sStr; uCCS = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian); uSLn = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian); sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC); if (*sStr) strip_trailing_blanks(sStr, uSLn); if (*sStr) format_text_chr(sStr, strlen((const char *)sStr), '.'); tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s", strPrm, sStr); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 8, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC); } break; case MQ_MQCFT_INTEGER_LIST: { guint32 u2; guint32 uDigit = 0; uCnt = tvb_get_guint32(tvb, offset+uLenF, bLittleEndian); uDigit = dissect_mqpcf_getDigits(uCnt); tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, &ti, "%s Cnt(%d)", strPrm, uCnt); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian); offset += uLenF+4; for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++) { uVal = tvb_get_guint32(tvb, offset, bLittleEndian); dissect_mqpcf_parm_int(tvb, tree, offset, uPrm, uVal, hf_mq_pcf_intlist, u2+1, uCnt, uDigit, bParse); offset += 4; } if (u2 != uCnt) { proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxInt, tvb, offset, (uCnt- u2) * 4, sMaxLst, u2, uCnt); } } break; case MQ_MQCFT_STRING_LIST: { guint32 u2; guint32 uDigit; guint8 *sStr; header_field_info *hfinfo; hfinfo = proto_registrar_get_nth(hf_mq_pcf_stringlist); uCCS = tvb_get_guint32(tvb, offset + uLenF , bLittleEndian); uCnt = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian); uSLn = tvb_get_guint32(tvb, offset + uLenF + 8, bLittleEndian); tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s Cnt(%d)", strPrm, uCnt); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmcount , tvb, offset + 16, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian); uDigit = dissect_mqpcf_getDigits(uCnt); offset += uLenF+12; for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++) { sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC); if (*sStr) strip_trailing_blanks(sStr, uSLn); if (*sStr) format_text_chr(sStr, strlen((const char *)sStr), '.'); proto_tree_add_string_format(tree, hf_mq_pcf_stringlist, tvb, offset, uSLn, (const char *)sStr, "%s[%*d]: %s", hfinfo->name, uDigit, u2+1, sStr); offset += uSLn; } if (u2 != uCnt) { proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxStr, tvb, offset,(uCnt - u2) * uSLn, sMaxLst, u2, uCnt); } } break; case MQ_MQCFT_EVENT: break; case MQ_MQCFT_USER: { tree = proto_tree_add_subtree(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, strPrm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + 8, uLen - 8, bLittleEndian); } break; case MQ_MQCFT_BYTE_STRING: { uSLn = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian); if (uSLn) { guint8 *sStrA = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_ASCII) , uSLn, '.'); guint8 *sStrE = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_EBCDIC), uSLn, '.'); if (uSLn > 35) { tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s [Truncated] A(%-.35s) E(%-.35s)", strPrm, sStrA, sStrE); } else { tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s A(%s) E(%s)", strPrm, sStrA, sStrE); } } else { tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s <MISSING>", strPrm); } proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 4 , uSLn, bLittleEndian); } break; case MQ_MQCFT_TRACE_ROUTE: break; case MQ_MQCFT_REPORT: break; case MQ_MQCFT_INTEGER_FILTER: { guint32 uOpe; uOpe = tvb_get_guint32(tvb, offset + uLenF , bLittleEndian); uVal = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian); tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s %8x-(%9d)", strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, uVal, uVal); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_int, tvb, offset + uLenF + 4, 4, bLittleEndian); } break; case MQ_MQCFT_STRING_FILTER: { guint8 *sStr; guint32 uOpe; uOpe = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian); uCCS = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian); uSLn = tvb_get_guint32(tvb, offset + uLenF + 8, bLittleEndian); sStr = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC), uSLn, '.'); strip_trailing_blanks(sStr, uSLn); tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s %s", strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, sStr); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 16, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC); } break; case MQ_MQCFT_BYTE_STRING_FILTER: { guint32 uOpe; uOpe = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian); uSLn = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian); if (uSLn) { guint8 *sStrA = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_ASCII), uSLn, '.'); guint8 *sStrE = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_EBCDIC), uSLn, '.'); tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s A(%s) E(%s)", strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, sStrA, sStrE); } else { tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s <MISSING>", strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7); } proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 8 , uSLn, bLittleEndian); } break; case MQ_MQCFT_COMMAND_XR: break; case MQ_MQCFT_XR_MSG: break; case MQ_MQCFT_XR_ITEM: break; case MQ_MQCFT_XR_SUMMARY: break; case MQ_MQCFT_GROUP: break; case MQ_MQCFT_STATISTICS: break; case MQ_MQCFT_ACCOUNTING: break; case MQ_MQCFT_INTEGER64: { uVal64 = tvb_get_guint64(tvb, offset + uLenF + 4, bLittleEndian); tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)", strPrm, uVal64, uVal64); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmunused, tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_int64, tvb, offset + uLenF + 4, 8, bLittleEndian); } break; case MQ_MQCFT_INTEGER64_LIST: { guint32 u2; guint32 uDigit; header_field_info *hfinfo; hfinfo = proto_registrar_get_nth(hf_mq_pcf_int64list); uCnt = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian); tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s Cnt(%d)", strPrm, uCnt); uDigit = dissect_mqpcf_getDigits(uCnt); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian); offset += uLenF + 4; for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++) { uVal64 = tvb_get_guint64(tvb, offset, bLittleEndian); proto_tree_add_int64_format(tree, hf_mq_pcf_int64list, tvb, offset, 8, uVal64, "%s[%*d]: %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)", hfinfo->name, uDigit, u2+1, uVal64, uVal64); offset += 8; } if (u2 != uCnt) { proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxI64, tvb, offset, (uCnt - u2) * 8, sMaxLst, u2, uCnt); } } break; } offset = tOfs+uLen; } if (u != uCount) { proto_tree_add_expert_format(mq_tree, pinfo, &ei_mq_pcf_MaxPrm, tvb, offset, tvb_reported_length_remaining(tvb, offset), sMaxPrm, u, uCount); } }
static int dissect_gssapi_work(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_verifier, gssapi_encrypt_info_t* encrypt_info) { proto_item *volatile item; proto_tree *volatile subtree; volatile int return_offset = 0; gssapi_conv_info_t *volatile gss_info; gssapi_oid_value *oidvalue; dissector_handle_t handle; conversation_t *conversation; tvbuff_t *oid_tvb; int len, start_offset, oid_start_offset; volatile int offset; gint8 appclass; gboolean pc, ind_field; gint32 tag; guint32 len1; const char *oid; fragment_head *fd_head=NULL; gssapi_frag_info_t *fi; tvbuff_t *volatile gss_tvb=NULL; asn1_ctx_t asn1_ctx; start_offset=0; offset=0; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); /* * We don't know whether the data is encrypted, so say it's * not, for now. The subdissector must set gssapi_data_encrypted * if it is. */ encrypt_info->gssapi_data_encrypted = FALSE; /* * We need a conversation for later */ conversation = find_or_create_conversation(pinfo); gss_info = (gssapi_conv_info_t *)conversation_get_proto_data(conversation, proto_gssapi); if (!gss_info) { gss_info = wmem_new(wmem_file_scope(), gssapi_conv_info_t); gss_info->oid=NULL; gss_info->do_reassembly=FALSE; gss_info->frags=wmem_tree_new(wmem_file_scope()); conversation_add_proto_data(conversation, proto_gssapi, gss_info); } item = proto_tree_add_item( tree, proto_gssapi, tvb, offset, -1, ENC_NA); subtree = proto_item_add_subtree(item, ett_gssapi); /* * Catch the ReportedBoundsError exception; the stuff we've been * handed doesn't necessarily run to the end of the packet, it's * an item inside a packet, so if it happens to be malformed (or * we, or a dissector we call, has a bug), so that an exception * is thrown, we want to report the error, but return and let * our caller dissect the rest of the packet. * * If it gets a BoundsError, we can stop, as there's nothing more * in the packet after our blob to see, so we just re-throw the * exception. */ TRY { gss_tvb=tvb; /* First of all, if it's the first time we see this packet * then check whether we are in the middle of reassembly or not */ if( (!pinfo->fd->flags.visited) && (gss_info->do_reassembly) && (gssapi_reassembly) ){ fi=(gssapi_frag_info_t *)wmem_tree_lookup32(gss_info->frags, gss_info->first_frame); if(!fi){ goto done; } wmem_tree_insert32(gss_info->frags, pinfo->num, fi); fd_head=fragment_add(&gssapi_reassembly_table, tvb, 0, pinfo, fi->first_frame, NULL, gss_info->frag_offset, tvb_captured_length(tvb), TRUE); gss_info->frag_offset+=tvb_captured_length(tvb); /* we need more fragments */ if(!fd_head){ goto done; } /* this blob is now fully reassembled */ gss_info->do_reassembly=FALSE; fi->reassembled_in=pinfo->num; gss_tvb=tvb_new_chain(tvb, fd_head->tvb_data); add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI"); } /* We have seen this packet before. * Is this blob part of reassembly or a normal blob ? */ if( (pinfo->fd->flags.visited) && (gssapi_reassembly) ){ fi=(gssapi_frag_info_t *)wmem_tree_lookup32(gss_info->frags, pinfo->num); if(fi){ fd_head=fragment_get(&gssapi_reassembly_table, pinfo, fi->first_frame, NULL); if(fd_head && (fd_head->flags&FD_DEFRAGMENTED)){ if(pinfo->num==fi->reassembled_in){ proto_item *frag_tree_item; gss_tvb=tvb_new_chain(tvb, fd_head->tvb_data); add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI"); show_fragment_tree(fd_head, &gssapi_frag_items, tree, pinfo, tvb, &frag_tree_item); } else { proto_item *it; it=proto_tree_add_uint(tree, hf_gssapi_reassembled_in, tvb, 0, 0, fi->reassembled_in); PROTO_ITEM_SET_GENERATED(it); goto done; } } } } /* Read header */ offset = get_ber_identifier(gss_tvb, offset, &appclass, &pc, &tag); offset = get_ber_length(gss_tvb, offset, &len1, &ind_field); if (!(appclass == BER_CLASS_APP && pc && tag == 0)) { /* It could be NTLMSSP, with no OID. This can happen for anything that microsoft calls 'Negotiate' or GSS-SPNEGO */ if ((tvb_captured_length_remaining(gss_tvb, start_offset)>7) && (tvb_strneql(gss_tvb, start_offset, "NTLMSSP", 7) == 0)) { return_offset = call_dissector(ntlmssp_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); goto done; } /* Maybe it's new NTLMSSP payload */ if ((tvb_captured_length_remaining(gss_tvb, start_offset)>16) && ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) { return_offset = call_dissector(ntlmssp_payload_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); encrypt_info->gssapi_data_encrypted = TRUE; goto done; } if ((tvb_captured_length_remaining(gss_tvb, start_offset)==16) && ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) { if( is_verifier ) { return_offset = call_dissector(ntlmssp_verf_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); } else if( encrypt_info->gssapi_encrypted_tvb ) { return_offset = call_dissector_with_data(ntlmssp_data_only_handle, tvb_new_subset_remaining(encrypt_info->gssapi_encrypted_tvb, 0), pinfo, subtree, &encrypt_info->gssapi_decrypted_tvb); encrypt_info->gssapi_data_encrypted = TRUE; } goto done; } /* Maybe it's new GSSKRB5 CFX Wrapping */ if ((tvb_captured_length_remaining(gss_tvb, start_offset)>2) && ((tvb_memeql(gss_tvb, start_offset, "\04\x04", 2) == 0) || (tvb_memeql(gss_tvb, start_offset, "\05\x04", 2) == 0))) { return_offset = call_dissector_with_data(spnego_krb5_wrap_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree, encrypt_info); goto done; } /* * If we do not recognise an Application class, * then we are probably dealing with an inner context * token or a wrap token, and we should retrieve the * gssapi_oid_value pointer from the per-frame data or, * if there is no per-frame data (as would be the case * the first time we dissect this frame), from the * conversation that exists or that we created from * pinfo (and then make it per-frame data). * We need to make it per-frame data as there can be * more than one GSS-API negotiation in a conversation. * * Note! We "cheat". Since we only need the pointer, * we store that as the data. (That's not really * "cheating" - the per-frame data and per-conversation * data code doesn't care what you supply as a data * pointer; it just treats it as an opaque pointer, it * doesn't dereference it or free what it points to.) */ oidvalue = (gssapi_oid_value *)p_get_proto_data(wmem_file_scope(), pinfo, proto_gssapi, 0); if (!oidvalue && !pinfo->fd->flags.visited) { /* No handle attached to this frame, but it's the first */ /* pass, so it'd be attached to the conversation. */ oidvalue = gss_info->oid; if (gss_info->oid) p_add_proto_data(wmem_file_scope(), pinfo, proto_gssapi, 0, gss_info->oid); } if (!oidvalue) { proto_tree_add_expert_format(subtree, pinfo, &ei_gssapi_unknown_header, gss_tvb, start_offset, 0, "Unknown header (class=%d, pc=%d, tag=%d)", appclass, pc, tag); return_offset = tvb_captured_length(gss_tvb); goto done; } else { tvbuff_t *oid_tvb_local; oid_tvb_local = tvb_new_subset_remaining(gss_tvb, start_offset); if (is_verifier) handle = oidvalue->wrap_handle; else handle = oidvalue->handle; len = call_dissector_with_data(handle, oid_tvb_local, pinfo, subtree, encrypt_info); if (len == 0) return_offset = tvb_captured_length(gss_tvb); else return_offset = start_offset + len; goto done; /* We are finished here */ } } /* Read oid */ oid_start_offset=offset; offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, gss_tvb, offset, hf_gssapi_oid, &oid); oidvalue = gssapi_lookup_oid_str(oid); /* Check if we need reassembly of this blob. * Only try reassembly for OIDs we recognize * and when we have the entire tvb * * SMB will sometimes split one large GSSAPI blob * across multiple SMB/SessionSetup commands. * While we should look at the uid returned in the response * to the first SessionSetup and use that as a key * instead for simplicity we assume there will not be several * such authentication at once on a single tcp session */ if( (!pinfo->fd->flags.visited) && (oidvalue) && (tvb_captured_length(gss_tvb)==tvb_reported_length(gss_tvb)) && (len1>(guint32)tvb_captured_length_remaining(gss_tvb, oid_start_offset)) && (gssapi_reassembly) ){ fi=wmem_new(wmem_file_scope(), gssapi_frag_info_t); fi->first_frame=pinfo->num; fi->reassembled_in=0; wmem_tree_insert32(gss_info->frags, pinfo->num, fi); fragment_add(&gssapi_reassembly_table, gss_tvb, 0, pinfo, pinfo->num, NULL, 0, tvb_captured_length(gss_tvb), TRUE); fragment_set_tot_len(&gssapi_reassembly_table, pinfo, pinfo->num, NULL, len1+oid_start_offset); gss_info->do_reassembly=TRUE; gss_info->first_frame=pinfo->num; gss_info->frag_offset=tvb_captured_length(gss_tvb); goto done; } /* * Hand off to subdissector. */ if ((oidvalue == NULL) || !proto_is_protocol_enabled(oidvalue->proto)) { /* No dissector for this oid */ proto_tree_add_item(subtree, hf_gssapi_token_object, gss_tvb, oid_start_offset, -1, ENC_NA); return_offset = tvb_captured_length(gss_tvb); goto done; } /* Save a pointer to the data for the OID for the * GSSAPI protocol for this conversation. */ /* * Now add the proto data ... * but only if it is not already there. */ if(!gss_info->oid){ gss_info->oid=oidvalue; } if (is_verifier) { handle = oidvalue->wrap_handle; if (handle != NULL) { oid_tvb = tvb_new_subset_remaining(gss_tvb, offset); len = call_dissector_with_data(handle, oid_tvb, pinfo, subtree, encrypt_info); if (len == 0) return_offset = tvb_captured_length(gss_tvb); else return_offset = offset + len; } else { proto_tree_add_item(subtree, hf_gssapi_auth_verifier, gss_tvb, offset, -1, ENC_NA); return_offset = tvb_captured_length(gss_tvb); } } else { handle = oidvalue->handle; if (handle != NULL) { oid_tvb = tvb_new_subset_remaining(gss_tvb, offset); len = call_dissector_with_data(handle, oid_tvb, pinfo, subtree, encrypt_info); if (len == 0) return_offset = tvb_captured_length(gss_tvb); else return_offset = offset + len; } else { proto_tree_add_item(subtree, hf_gssapi_auth_credentials, gss_tvb, offset, -1, ENC_NA); return_offset = tvb_captured_length(gss_tvb); } } done: ; } CATCH_NONFATAL_ERRORS { /* * Somebody threw an exception that means that there * was a problem dissecting the payload; that means * that a dissector was found, so we don't need to * dissect the payload as data or update the protocol * or info columns. * * Just show the exception and then drive on to show * the trailer, after noting that a dissector was found * and restoring the protocol value that was in effect * before we called the subdissector. */ show_exception(gss_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; proto_item_set_len(item, return_offset); return return_offset; }
static int dissect_pbb_tlvblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint maxoffset, gint8 addrCount) { guint16 tlvblockLength; guint tlvblockEnd; proto_tree *tlvblock_tree = NULL; proto_tree *tlv_tree = NULL; proto_tree *tlv_flags_tree = NULL; proto_tree *tlvValue_tree = NULL; proto_item *tlvBlock_item = NULL; proto_item *tlv_item = NULL; proto_item *tlvFlags_item = NULL; proto_item *tlvValue_item = NULL; proto_item *ti = NULL; int tlvCount = 0; if (maxoffset < offset + 2) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for minimal tlvblock"); return maxoffset; } tlvblockLength = tvb_get_ntohs(tvb, offset); tlvblockEnd = offset + 2 + tlvblockLength; if (maxoffset < tlvblockEnd) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for tlvblock"); return maxoffset; } tlvBlock_item = proto_tree_add_item(tree, hf_packetbb_tlvblock, tvb, offset, tlvblockEnd - offset, ENC_NA); tlvblock_tree = proto_item_add_subtree(tlvBlock_item, ett_packetbb_tlvblock); proto_tree_add_item(tlvblock_tree, hf_packetbb_tlvblock_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; while (offset < tlvblockEnd) { guint tlvStart, tlvLength; guint8 tlvType, tlvFlags, tlvExtType, indexStart, indexEnd; guint16 length = 0; tlvStart = offset; tlvType = tvb_get_guint8(tvb, offset++); tlvFlags = tvb_get_guint8(tvb, offset++); indexStart = 0; indexEnd = addrCount; tlvExtType = 0; if ((tlvFlags & TLV_HAS_TYPEEXT) != 0) { tlvExtType = tvb_get_guint8(tvb, offset++); } if ((tlvFlags & TLV_HAS_SINGLEINDEX) != 0) { indexStart = indexEnd = tvb_get_guint8(tvb, offset++); } else if ((tlvFlags & TLV_HAS_MULTIINDEX) != 0) { indexStart = tvb_get_guint8(tvb, offset++); indexEnd = tvb_get_guint8(tvb, offset++); } if ((tlvFlags & TLV_HAS_VALUE) != 0) { if ((tlvFlags & TLV_HAS_EXTLEN) != 0) { length = tvb_get_ntohs(tvb, offset++); } else { length = tvb_get_guint8(tvb, offset++); } } tlvLength = offset - tlvStart + length; offset = tlvStart; tlv_item = proto_tree_add_item(tlvBlock_item, hf_packetbb_tlv, tvb, tlvStart, tlvLength, ENC_NA); tlv_tree = proto_item_add_subtree(tlv_item, ett_packetbb_tlv[tlvType]); if ((tlvFlags & TLV_HAS_TYPEEXT) == 0) { proto_item_append_text(tlv_item, " (%d)", tlvType); } else { proto_item_append_text(tlv_item, " (%d/%d)", tlvType, tlvExtType); } /* add type */ proto_tree_add_item(tlv_tree, hf_packetbb_tlv_type, tvb, offset++, 1, ENC_BIG_ENDIAN); /* add flags */ tlvFlags_item = proto_tree_add_item(tlv_tree, hf_packetbb_tlv_flags, tvb, offset, 1, ENC_BIG_ENDIAN); tlv_flags_tree = proto_item_add_subtree(tlvFlags_item, ett_packetbb_tlv_flags); proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hastypext, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hassingleindex, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasmultiindex, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasvalue, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasextlen, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasmultivalue, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; if ((tlvFlags & TLV_HAS_TYPEEXT) != 0) { /* add ext-type */ proto_tree_add_item(tlv_tree, hf_packetbb_tlv_typeext, tvb, offset++, 1, ENC_BIG_ENDIAN); } if (addrCount > 0) { /* add index values */ if ((tlvFlags & TLV_HAS_SINGLEINDEX) != 0) { proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexstart, tvb, offset++, 1, indexStart); ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexend, tvb, offset, 0, indexEnd); proto_item_append_text(ti, " (implicit)"); } else if ((tlvFlags & TLV_HAS_MULTIINDEX) != 0) { proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexstart, tvb, offset++, 1, indexStart); proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexend, tvb, offset++, 1, indexEnd); } else { ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexstart, tvb, offset, 0, indexStart); proto_item_append_text(ti, " (implicit)"); ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexend, tvb, offset, 0, indexEnd); proto_item_append_text(ti, " (implicit)"); } } /* add length */ if ((tlvFlags & TLV_HAS_VALUE) != 0) { if ((tlvFlags & TLV_HAS_EXTLEN) != 0) { proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_length, tvb, offset, 2, length); offset += 2; } else { proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_length, tvb, offset++, 1, length); } } else { ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_length, tvb, offset, 0, 0); proto_item_append_text(ti, " (implicit)"); } if (length > 0) { /* add value */ tlvValue_item = proto_tree_add_item(tlv_tree, hf_packetbb_tlv_value, tvb, offset, length, ENC_NA); if ((tlvFlags & TLV_HAS_MULTIVALUE) == 0) { offset += length; } else { int i; guint8 c = indexEnd - indexStart + 1; tlvValue_tree = proto_item_add_subtree(tlvValue_item, ett_packetbb_tlv_value); for (i=indexStart; i<=indexEnd; i++) { proto_tree_add_item(tlvValue_tree, hf_packetbb_tlv_multivalue, tvb, offset, length/c, ENC_NA); offset += (length/c); } } } tlvCount++; } proto_item_append_text(tlvBlock_item, " (%d TLVs)", tlvCount); return offset; }
/* dissects MPA REQUEST or MPA REPLY */ static gboolean dissect_mpa_req_rep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint message_type) { proto_tree *mpa_tree = NULL; proto_tree *mpa_header_tree = NULL; proto_item *mpa_item = NULL; proto_item *mpa_header_item = NULL; guint16 pd_length; guint32 offset = 0; mpa_packetlist(pinfo, message_type); if (tree) { mpa_item = proto_tree_add_item(tree, proto_iwarp_mpa, tvb, 0, -1, ENC_NA); mpa_tree = proto_item_add_subtree(mpa_item, ett_mpa); if (message_type == MPA_REQUEST_FRAME) { mpa_header_item = proto_tree_add_item(mpa_tree, hf_mpa_req, tvb, offset, -1, ENC_NA); mpa_header_tree = proto_item_add_subtree( mpa_header_item, ett_mpa); proto_tree_add_item(mpa_header_tree, hf_mpa_key_req, tvb, offset, MPA_REQ_REP_KEY_LEN, ENC_NA); } if (message_type == MPA_REPLY_FRAME) { mpa_header_item = proto_tree_add_item(mpa_tree, hf_mpa_rep, tvb, offset, -1, ENC_NA); mpa_header_tree = proto_item_add_subtree( mpa_header_item, ett_mpa); proto_tree_add_item(mpa_header_tree, hf_mpa_key_rep, tvb, offset, MPA_REQ_REP_KEY_LEN, ENC_NA); } offset += MPA_REQ_REP_KEY_LEN; proto_tree_add_item(mpa_header_tree, hf_mpa_flag_m, tvb, offset, MPA_REQ_REP_FLAG_LEN, ENC_BIG_ENDIAN); proto_tree_add_item(mpa_header_tree, hf_mpa_flag_c, tvb, offset, MPA_REQ_REP_FLAG_LEN, ENC_BIG_ENDIAN); proto_tree_add_item(mpa_header_tree, hf_mpa_flag_r, tvb, offset, MPA_REQ_REP_FLAG_LEN, ENC_BIG_ENDIAN); proto_tree_add_item(mpa_header_tree, hf_mpa_flag_res, tvb, offset, MPA_REQ_REP_FLAG_LEN, ENC_BIG_ENDIAN); offset += MPA_REQ_REP_FLAG_LEN; proto_tree_add_item(mpa_header_tree, hf_mpa_rev, tvb, offset, MPA_REQ_REP_REV_LEN, ENC_BIG_ENDIAN); offset += MPA_REQ_REP_REV_LEN; /* check whether the Private Data Length conforms to RFC 5044 */ pd_length = tvb_get_ntohs(tvb, offset); if (pd_length > MPA_MAX_PD_LENGTH) { proto_tree_add_expert_format(tree, pinfo, &ei_mpa_bad_length, tvb, offset, 2, "[PD length field indicates more 512 bytes of Private Data]"); return FALSE; } proto_tree_add_uint_format_value(mpa_header_tree, hf_mpa_pd_length, tvb, offset, MPA_REQ_REP_PDLENGTH_LEN, pd_length, "%u bytes", pd_length); offset += MPA_REQ_REP_PDLENGTH_LEN; if (pd_length) { proto_tree_add_item(mpa_header_tree, hf_mpa_private_data, tvb, offset, pd_length, ENC_NA); } } return TRUE; }
static int dissect_pbb_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset) { proto_tree *message_tree = NULL; proto_tree *header_tree = NULL; proto_tree *headerFlags_tree = NULL; proto_item *message_item = NULL; proto_item *header_item = NULL; proto_item *headerFlags_item = NULL; guint8 messageType; guint8 messageFlags; guint16 messageLength, headerLength, messageEnd; guint8 addressSize, addressType; if (tvb_reported_length(tvb) - offset < 6) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, -1, "Not enough octets for minimal message header"); return tvb_reported_length(tvb); } messageType = tvb_get_guint8(tvb, offset); messageFlags = tvb_get_guint8(tvb, offset+1); messageLength = tvb_get_ntohs(tvb, offset+2); addressSize = (messageFlags & 0x0f) + 1; switch (addressSize) { case 4: addressType = 0; break; case 16: addressType = 1; break; case 6: addressType = 2; break; default: addressType = 3; break; } messageEnd = offset + messageLength; headerLength = 4; /* calculate header size */ if ((messageFlags & MSG_HEADER_HASORIG) != 0) { headerLength += addressSize; } if ((messageFlags & MSG_HEADER_HASHOPLIMIT) != 0) { headerLength ++; } if ((messageFlags & MSG_HEADER_HASHOPCOUNT) != 0) { headerLength ++; } if ((messageFlags & MSG_HEADER_HASSEQNR) != 0) { headerLength += 2; } /* test length for message size */ if (tvb_reported_length(tvb) - offset < messageLength) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, -1, "Not enough octets for message"); return tvb_reported_length(tvb); } message_item = proto_tree_add_item(tree, hf_packetbb_msg, tvb, offset, messageLength, ENC_NA); message_tree = proto_item_add_subtree(message_item, ett_packetbb_msg[messageType]); proto_item_append_text(message_item, " (type %d)", messageType); header_item = proto_tree_add_item(message_tree, hf_packetbb_msgheader, tvb, offset, headerLength, ENC_NA); header_tree = proto_item_add_subtree(header_item, ett_packetbb_msgheader); /* type */ proto_tree_add_item(header_tree, hf_packetbb_msgheader_type, tvb, offset, 1, ENC_BIG_ENDIAN); /* flags */ headerFlags_item = proto_tree_add_uint(header_tree, hf_packetbb_msgheader_flags, tvb, offset+1, 1, messageFlags & 0xf8); headerFlags_tree = proto_item_add_subtree(headerFlags_item, ett_packetbb_msgheader_flags); proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhasorig, tvb, offset+1, 1, messageFlags); proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhashoplimit, tvb, offset+1, 1, messageFlags); proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhashopcount, tvb, offset+1, 1, messageFlags); proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhasseqnr, tvb, offset+1, 1, messageFlags); proto_tree_add_uint(header_tree, hf_packetbb_msgheader_addresssize, tvb, offset + 1, 1, (messageFlags & 0x0f) + 1); /* size */ proto_tree_add_item(header_tree, hf_packetbb_msgheader_size, tvb, offset+2, 2, ENC_BIG_ENDIAN); offset += 4; /* originator address */ if ((messageFlags & MSG_HEADER_HASORIG) != 0) { switch (addressSize) { case 4: /* IPv4 */ proto_tree_add_item(header_tree, hf_packetbb_msgheader_origaddripv4, tvb, offset, addressSize, ENC_BIG_ENDIAN); break; case 16: /* IPv6 */ proto_tree_add_item(header_tree, hf_packetbb_msgheader_origaddripv6, tvb, offset, addressSize, ENC_NA); break; case 6: /* MAC */ proto_tree_add_item(header_tree, hf_packetbb_msgheader_origaddrmac, tvb, offset, addressSize, ENC_NA); break; default: /* Unknown */ proto_tree_add_item(header_tree, hf_packetbb_msgheader_origaddrcustom, tvb, offset, addressSize, ENC_NA); break; } offset += addressSize; } /* hop limit */ if ((messageFlags & MSG_HEADER_HASHOPLIMIT) != 0) { proto_tree_add_item(header_tree, hf_packetbb_msgheader_hoplimit, tvb, offset++, 1, ENC_BIG_ENDIAN); } /* hop count */ if ((messageFlags & MSG_HEADER_HASHOPCOUNT) != 0) { proto_tree_add_item(header_tree, hf_packetbb_msgheader_hopcount, tvb, offset++, 1, ENC_BIG_ENDIAN); } /* sequence number */ if ((messageFlags & MSG_HEADER_HASSEQNR) != 0) { proto_tree_add_item(header_tree, hf_packetbb_msgheader_seqnr, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } if (offset >= messageEnd) { /* this is an error, tlv block is mandatory */ return tvb_reported_length(tvb); } offset = dissect_pbb_tlvblock(tvb, pinfo, message_tree, offset, messageEnd, 0); while (offset < messageEnd) { offset = dissect_pbb_addressblock(tvb, pinfo, message_tree, offset, messageEnd, addressType, addressSize); } return offset; }
/* * Dissect X518 PDUs inside a ROS PDUs */ static int dissect_dsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data) { int offset = 0; int old_offset; proto_item *item; proto_tree *tree; struct SESSION_DATA_STRUCTURE* session; int (*dsp_dissector)(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_) = NULL; const char *dsp_op_name; asn1_ctx_t asn1_ctx; /* do we have operation information from the ROS dissector? */ if (data == NULL) return 0; session = (struct SESSION_DATA_STRUCTURE*)data; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); item = proto_tree_add_item(parent_tree, proto_dsp, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_dsp); col_set_str(pinfo->cinfo, COL_PROTOCOL, "DAP"); col_clear(pinfo->cinfo, COL_INFO); asn1_ctx.private_data = session; switch(session->ros_op & ROS_OP_MASK) { case (ROS_OP_BIND | ROS_OP_ARGUMENT): /* BindInvoke */ dsp_dissector = dissect_dsp_DSASystemBindArgument; dsp_op_name = "System-Bind-Argument"; break; case (ROS_OP_BIND | ROS_OP_RESULT): /* BindResult */ dsp_dissector = dissect_dsp_DSASystemBindResult; dsp_op_name = "System-Bind-Result"; break; case (ROS_OP_BIND | ROS_OP_ERROR): /* BindError */ dsp_dissector = dissect_dsp_DSASystemBindError; dsp_op_name = "System-Bind-Error"; break; case (ROS_OP_INVOKE | ROS_OP_ARGUMENT): /* Invoke Argument */ switch(session->ros_op & ROS_OP_OPCODE_MASK) { case 1: /* read */ dsp_dissector = dissect_dsp_ChainedReadArgument; dsp_op_name = "Chained-Read-Argument"; break; case 2: /* compare */ dsp_dissector = dissect_dsp_ChainedCompareArgument; dsp_op_name = "Chained-Compare-Argument"; break; case 3: /* abandon */ dsp_dissector = dissect_dsp_ChainedAbandonArgument; dsp_op_name = "Chained-Abandon-Argument"; break; case 4: /* list */ dsp_dissector = dissect_dsp_ChainedListArgument; dsp_op_name = "Chained-List-Argument"; break; case 5: /* search */ dsp_dissector = dissect_dsp_ChainedSearchArgument; dsp_op_name = "Chained-Search-Argument"; break; case 6: /* addEntry */ dsp_dissector = dissect_dsp_ChainedAddEntryArgument; dsp_op_name = "Chained-Add-Entry-Argument"; break; case 7: /* removeEntry */ dsp_dissector = dissect_dsp_ChainedRemoveEntryArgument; dsp_op_name = "Chained-Remove-Entry-Argument"; break; case 8: /* modifyEntry */ dsp_dissector = dissect_dsp_ChainedModifyEntryArgument; dsp_op_name = "ChainedModify-Entry-Argument"; break; case 9: /* modifyDN */ dsp_dissector = dissect_dsp_ChainedModifyDNArgument; dsp_op_name = "ChainedModify-DN-Argument"; break; default: proto_tree_add_expert_format(tree, pinfo, &ei_dsp_unsupported_opcode, tvb, offset, -1, "Unsupported DSP opcode (%d)", session->ros_op & ROS_OP_OPCODE_MASK); break; } break; case (ROS_OP_INVOKE | ROS_OP_RESULT): /* Return Result */ switch(session->ros_op & ROS_OP_OPCODE_MASK) { case 1: /* read */ dsp_dissector = dissect_dsp_ChainedReadResult; dsp_op_name = "Chained-Read-Result"; break; case 2: /* compare */ dsp_dissector = dissect_dsp_ChainedCompareResult; dsp_op_name = "Chained-Compare-Result"; break; case 3: /* abandon */ dsp_dissector = dissect_dsp_ChainedAbandonResult; dsp_op_name = "Chained-Abandon-Result"; break; case 4: /* list */ dsp_dissector = dissect_dsp_ChainedListResult; dsp_op_name = "Chained-List-Result"; break; case 5: /* search */ dsp_dissector = dissect_dsp_ChainedSearchResult; dsp_op_name = "Chained-Search-Result"; break; case 6: /* addEntry */ dsp_dissector = dissect_dsp_ChainedAddEntryResult; dsp_op_name = "Chained-Add-Entry-Result"; break; case 7: /* removeEntry */ dsp_dissector = dissect_dsp_ChainedRemoveEntryResult; dsp_op_name = "Chained-Remove-Entry-Result"; break; case 8: /* modifyEntry */ dsp_dissector = dissect_dsp_ChainedModifyEntryResult; dsp_op_name = "Chained-Modify-Entry-Result"; break; case 9: /* modifyDN */ dsp_dissector = dissect_dsp_ChainedModifyDNResult; dsp_op_name = "ChainedModify-DN-Result"; break; default: proto_tree_add_expert(tree, pinfo, &ei_dsp_unsupported_opcode, tvb, offset, -1); break; } break; case (ROS_OP_INVOKE | ROS_OP_ERROR): /* Return Error */ switch(session->ros_op & ROS_OP_OPCODE_MASK) { case 1: /* attributeError */ dsp_dissector = dissect_dap_AttributeError; dsp_op_name = "Attribute-Error"; break; case 2: /* nameError */ dsp_dissector = dissect_dap_NameError; dsp_op_name = "Name-Error"; break; case 3: /* serviceError */ dsp_dissector = dissect_dap_ServiceError; dsp_op_name = "Service-Error"; break; case 4: /* referral */ dsp_dissector = dissect_dap_Referral; dsp_op_name = "Referral"; break; case 5: /* abandoned */ dsp_dissector = dissect_dap_Abandoned; dsp_op_name = "Abandoned"; break; case 6: /* securityError */ dsp_dissector = dissect_dap_SecurityError; dsp_op_name = "Security-Error"; break; case 7: /* abandonFailed */ dsp_dissector = dissect_dap_AbandonFailedError; dsp_op_name = "Abandon-Failed-Error"; break; case 8: /* updateError */ dsp_dissector = dissect_dap_UpdateError; dsp_op_name = "Update-Error"; break; case 9: /* DSAReferral */ dsp_dissector = dissect_dsp_DSAReferral; dsp_op_name = "DSA-Referral"; break; default: proto_tree_add_expert(tree, pinfo, &ei_dsp_unsupported_errcode, tvb, offset, -1); break; } break; default: proto_tree_add_expert(tree, pinfo, &ei_dsp_unsupported_pdu, tvb, offset, -1); return tvb_captured_length(tvb); } if(dsp_dissector) { col_set_str(pinfo->cinfo, COL_INFO, dsp_op_name); while (tvb_reported_length_remaining(tvb, offset) > 0){ old_offset=offset; offset=(*dsp_dissector)(FALSE, tvb, offset, &asn1_ctx, tree, -1); if(offset == old_offset){ proto_tree_add_expert(tree, pinfo, &ei_dsp_zero_pdu, tvb, offset, -1); break; } } } return tvb_captured_length(tvb); }
/* dissects MPA FPDU */ static guint16 dissect_mpa_fpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mpa_state_t *state, struct tcpinfo *tcpinfo, guint8 endpoint) { proto_item *mpa_item = NULL; proto_item *mpa_header_item = NULL; proto_tree *mpa_tree = NULL; proto_tree *mpa_header_tree = NULL; guint8 pad_length; guint16 ulpdu_length, exp_ulpdu_length; guint32 offset, total_length; guint32 num_of_m = 0; /* * Initialize starting offset for this FPDU. Deals with the case that this * FPDU may start with a Marker instead of the ULPDU_LENTH header field. */ if (state->minfo[endpoint].valid && get_first_marker_offset(state, tcpinfo, endpoint) == 0) { offset = MPA_MARKER_LEN; } else { offset = 0; } /* get ULPDU length of this FPDU */ ulpdu_length = (guint16) tvb_get_ntohs(tvb, offset); mpa_packetlist(pinfo, MPA_FPDU); if (state->minfo[endpoint].valid) { num_of_m = number_of_markers(state, tcpinfo, endpoint); } if (tree) { /* * Stop FPDU dissection if the read ULPDU_LENGTH field does NOT contain * what is expected. * Reasons for getting a wrong ULPDU_LENGTH can be lost packets (because * libpcap was not able to capture every packet) or lost alignment (the * MPA FPDU header does not start right after TCP header). * We consider the above to be an error since we make the assumption * that exactly one MPA FPDU is contained in one TCP segement and starts * always either with a Marker or the ULPDU_LENGTH header field. */ exp_ulpdu_length = expected_ulpdu_length(state, tcpinfo, endpoint); if (!exp_ulpdu_length || exp_ulpdu_length != ulpdu_length) { proto_tree_add_expert_format(tree, pinfo, &ei_mpa_bad_length, tvb, offset, MPA_ULPDU_LENGTH_LEN, "[ULPDU length [%u] field does not contain the expected length[%u]]", exp_ulpdu_length, ulpdu_length); } mpa_item = proto_tree_add_item(tree, proto_iwarp_mpa, tvb, 0, -1, ENC_NA); mpa_tree = proto_item_add_subtree(mpa_item, ett_mpa); mpa_header_item = proto_tree_add_item(mpa_tree, hf_mpa_fpdu, tvb, offset, -1, ENC_NA); mpa_header_tree = proto_item_add_subtree(mpa_header_item, ett_mpa); /* ULPDU Length header field */ proto_tree_add_uint_format_value(mpa_header_tree, hf_mpa_ulpdu_length, tvb, offset, MPA_ULPDU_LENGTH_LEN, ulpdu_length, "%u bytes", ulpdu_length); pad_length = fpdu_pad_length(ulpdu_length); /* Markers are present in this FPDU */ if (state->minfo[endpoint].valid && num_of_m > 0) { total_length = fpdu_total_length(tcpinfo); if (pad_length > 0) { proto_tree_add_item(mpa_header_tree, hf_mpa_pad, tvb, pad_offset(tcpinfo, total_length, pad_length), pad_length, ENC_NA); } dissect_fpdu_crc(tvb, mpa_header_tree, state, total_length-MPA_CRC_LEN, num_of_m * MPA_MARKER_LEN + ulpdu_length + pad_length + MPA_ULPDU_LENGTH_LEN); dissect_fpdu_markers(tvb, mpa_tree, state, tcpinfo, endpoint); } else { /* Markers are not present or not enabled */ offset += MPA_ULPDU_LENGTH_LEN + ulpdu_length; if (pad_length > 0) { proto_tree_add_item(mpa_header_tree, hf_mpa_pad, tvb, offset, pad_length, ENC_NA); offset += pad_length; } dissect_fpdu_crc(tvb, mpa_header_tree, state, offset, ulpdu_length+pad_length+MPA_ULPDU_LENGTH_LEN); } } return ulpdu_length; }
static int dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data) { proto_item *volatile ti = NULL, *comment_item; guint cap_len = 0, frame_len = 0; proto_tree *volatile tree; proto_tree *comments_tree; proto_tree *volatile fh_tree = NULL; proto_item *item; const gchar *cap_plurality, *frame_plurality; frame_data_t *fr_data = (frame_data_t*)data; const color_filter_t *color_filter; tree=parent_tree; switch (pinfo->phdr->rec_type) { case REC_TYPE_PACKET: pinfo->current_proto = "Frame"; if (pinfo->pseudo_header != NULL) { switch (pinfo->pkt_encap) { case WTAP_ENCAP_WFLEET_HDLC: case WTAP_ENCAP_CHDLC_WITH_PHDR: case WTAP_ENCAP_PPP_WITH_PHDR: case WTAP_ENCAP_SDLC: case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ? P2P_DIR_SENT : P2P_DIR_RECV; break; case WTAP_ENCAP_BLUETOOTH_HCI: pinfo->p2p_dir = pinfo->pseudo_header->bthci.sent; break; case WTAP_ENCAP_LAPB: case WTAP_ENCAP_FRELAY_WITH_PHDR: pinfo->p2p_dir = (pinfo->pseudo_header->x25.flags & FROM_DCE) ? P2P_DIR_RECV : P2P_DIR_SENT; break; case WTAP_ENCAP_ISDN: case WTAP_ENCAP_V5_EF: case WTAP_ENCAP_DPNSS: case WTAP_ENCAP_BACNET_MS_TP_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ? P2P_DIR_SENT : P2P_DIR_RECV; break; case WTAP_ENCAP_LINUX_LAPD: pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 || pinfo->pseudo_header->lapd.pkttype == 4) ? P2P_DIR_SENT : P2P_DIR_RECV; break; case WTAP_ENCAP_MTP2_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ? P2P_DIR_SENT : P2P_DIR_RECV; pinfo->link_number = pinfo->pseudo_header->mtp2.link_number; break; case WTAP_ENCAP_GSM_UM: pinfo->p2p_dir = pinfo->pseudo_header->gsm_um.uplink ? P2P_DIR_SENT : P2P_DIR_RECV; break; } } break; case REC_TYPE_FT_SPECIFIC_EVENT: pinfo->current_proto = "Event"; break; case REC_TYPE_FT_SPECIFIC_REPORT: pinfo->current_proto = "Report"; break; default: g_assert_not_reached(); break; } if (fr_data && fr_data->pkt_comment) { item = proto_tree_add_item(tree, proto_pkt_comment, tvb, 0, 0, ENC_NA); comments_tree = proto_item_add_subtree(item, ett_comments); comment_item = proto_tree_add_string_format(comments_tree, hf_comments_text, tvb, 0, 0, fr_data->pkt_comment, "%s", fr_data->pkt_comment); expert_add_info_format(pinfo, comment_item, &ei_comments_text, "%s", fr_data->pkt_comment); } /* if FRAME is not referenced from any filters we don't need to worry about generating any tree items. */ if (!proto_field_is_referenced(tree, proto_frame)) { tree=NULL; if (pinfo->presence_flags & PINFO_HAS_TS) { if (pinfo->abs_ts.nsecs < 0 || pinfo->abs_ts.nsecs >= 1000000000) expert_add_info(pinfo, NULL, &ei_arrive_time_out_of_range); } } else { gboolean old_visible; /* Put in frame header information. */ cap_len = tvb_captured_length(tvb); frame_len = tvb_reported_length(tvb); cap_plurality = plurality(cap_len, "", "s"); frame_plurality = plurality(frame_len, "", "s"); ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb), "Frame %u: %u byte%s on wire", pinfo->num, frame_len, frame_plurality); if (generate_bits_field) proto_item_append_text(ti, " (%u bits)", frame_len * 8); proto_item_append_text(ti, ", %u byte%s captured", cap_len, cap_plurality); if (generate_bits_field) { proto_item_append_text(ti, " (%u bits)", cap_len * 8); } if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) { proto_item_append_text(ti, " on interface %u", pinfo->phdr->interface_id); } if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) { if (pinfo->phdr->pack_flags & 0x00000001) { proto_item_append_text(ti, " (inbound)"); pinfo->p2p_dir = P2P_DIR_RECV; } if (pinfo->phdr->pack_flags & 0x00000002) { proto_item_append_text(ti, " (outbound)"); pinfo->p2p_dir = P2P_DIR_SENT; } } fh_tree = proto_item_add_subtree(ti, ett_frame); if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID && proto_field_is_referenced(tree, hf_frame_interface_id)) { const char *interface_name = epan_get_interface_name(pinfo->epan, pinfo->phdr->interface_id); if (interface_name) proto_tree_add_uint_format_value(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id, "%u (%s)", pinfo->phdr->interface_id, interface_name); else proto_tree_add_uint(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id); } if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) { proto_tree *flags_tree; proto_item *flags_item; flags_item = proto_tree_add_uint(fh_tree, hf_frame_pack_flags, tvb, 0, 0, pinfo->phdr->pack_flags); flags_tree = proto_item_add_subtree(flags_item, ett_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_direction, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_reception_type, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_fcs_length, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_reserved, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_crc_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_long_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_short_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_inter_frame_gap_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_unaligned_frame_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_start_frame_delimiter_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_preamble_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_symbol_error, tvb, 0, 0, pinfo->phdr->pack_flags); } if (pinfo->phdr->rec_type == REC_TYPE_PACKET) proto_tree_add_int(fh_tree, hf_frame_wtap_encap, tvb, 0, 0, pinfo->pkt_encap); if (pinfo->presence_flags & PINFO_HAS_TS) { proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb, 0, 0, &(pinfo->abs_ts)); if (pinfo->abs_ts.nsecs < 0 || pinfo->abs_ts.nsecs >= 1000000000) { expert_add_info_format(pinfo, ti, &ei_arrive_time_out_of_range, "Arrival Time: Fractional second %09ld is invalid," " the valid range is 0-1000000000", (long) pinfo->abs_ts.nsecs); } item = proto_tree_add_time(fh_tree, hf_frame_shift_offset, tvb, 0, 0, &(pinfo->fd->shift_offset)); PROTO_ITEM_SET_GENERATED(item); if (generate_epoch_time) { proto_tree_add_time(fh_tree, hf_frame_arrival_time_epoch, tvb, 0, 0, &(pinfo->abs_ts)); } if (proto_field_is_referenced(tree, hf_frame_time_delta)) { nstime_t del_cap_ts; frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->num - 1, &del_cap_ts); item = proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb, 0, 0, &(del_cap_ts)); PROTO_ITEM_SET_GENERATED(item); } if (proto_field_is_referenced(tree, hf_frame_time_delta_displayed)) { nstime_t del_dis_ts; frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->fd->prev_dis_num, &del_dis_ts); item = proto_tree_add_time(fh_tree, hf_frame_time_delta_displayed, tvb, 0, 0, &(del_dis_ts)); PROTO_ITEM_SET_GENERATED(item); } item = proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb, 0, 0, &(pinfo->rel_ts)); PROTO_ITEM_SET_GENERATED(item); if (pinfo->fd->flags.ref_time) { ti = proto_tree_add_item(fh_tree, hf_frame_time_reference, tvb, 0, 0, ENC_NA); PROTO_ITEM_SET_GENERATED(ti); } } proto_tree_add_uint(fh_tree, hf_frame_number, tvb, 0, 0, pinfo->num); proto_tree_add_uint_format(fh_tree, hf_frame_len, tvb, 0, 0, frame_len, "Frame Length: %u byte%s (%u bits)", frame_len, frame_plurality, frame_len * 8); proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb, 0, 0, cap_len, "Capture Length: %u byte%s (%u bits)", cap_len, cap_plurality, cap_len * 8); if (generate_md5_hash) { const guint8 *cp; md5_state_t md_ctx; md5_byte_t digest[16]; const gchar *digest_string; cp = tvb_get_ptr(tvb, 0, cap_len); md5_init(&md_ctx); md5_append(&md_ctx, cp, cap_len); md5_finish(&md_ctx, digest); digest_string = bytestring_to_str(wmem_packet_scope(), digest, 16, '\0'); ti = proto_tree_add_string(fh_tree, hf_frame_md5_hash, tvb, 0, 0, digest_string); PROTO_ITEM_SET_GENERATED(ti); } ti = proto_tree_add_boolean(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_boolean(fh_tree, hf_frame_ignored, tvb, 0, 0,pinfo->fd->flags.ignored); PROTO_ITEM_SET_GENERATED(ti); if (proto_field_is_referenced(tree, hf_frame_protocols)) { /* we are going to be using proto_item_append_string() on * hf_frame_protocols, and we must therefore disable the * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by * setting it as visible. * * See proto.h for details. */ old_visible = proto_tree_set_visible(fh_tree, TRUE); ti = proto_tree_add_string(fh_tree, hf_frame_protocols, tvb, 0, 0, ""); PROTO_ITEM_SET_GENERATED(ti); proto_tree_set_visible(fh_tree, old_visible); } /* Check for existences of P2P pseudo header */ if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) { proto_tree_add_int(fh_tree, hf_frame_p2p_dir, tvb, 0, 0, pinfo->p2p_dir); } /* Check for existences of MTP2 link number */ if ((pinfo->pseudo_header != NULL ) && (pinfo->pkt_encap == WTAP_ENCAP_MTP2_WITH_PHDR)) { proto_tree_add_uint(fh_tree, hf_link_number, tvb, 0, 0, pinfo->link_number); } if (show_file_off) { proto_tree_add_int64_format_value(fh_tree, hf_frame_file_off, tvb, 0, 0, pinfo->fd->file_off, "%" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)", pinfo->fd->file_off, pinfo->fd->file_off); } } if (pinfo->fd->flags.ignored) { /* Ignored package, stop handling here */ col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>"); proto_tree_add_boolean_format(tree, hf_frame_ignored, tvb, 0, 0, TRUE, "This frame is marked as ignored"); return tvb_captured_length(tvb); } /* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */ TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations. (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif switch (pinfo->phdr->rec_type) { case REC_TYPE_PACKET: if ((force_docsis_encap) && (docsis_handle)) { call_dissector_with_data(docsis_handle, tvb, pinfo, parent_tree, (void *)pinfo->pseudo_header); } else { if (!dissector_try_uint_new(wtap_encap_dissector_table, pinfo->pkt_encap, tvb, pinfo, parent_tree, TRUE, (void *)pinfo->pseudo_header)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN"); col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %d", pinfo->pkt_encap); call_dissector_with_data(data_handle, tvb, pinfo, parent_tree, (void *)pinfo->pseudo_header); } } break; case REC_TYPE_FT_SPECIFIC_EVENT: case REC_TYPE_FT_SPECIFIC_REPORT: { int file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; if (fr_data) { file_type_subtype = fr_data->file_type_subtype; } if (!dissector_try_uint(wtap_fts_rec_dissector_table, file_type_subtype, tvb, pinfo, parent_tree)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN"); col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %d", file_type_subtype); call_dissector(data_handle,tvb, pinfo, parent_tree); } } break; } #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch (GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; if (proto_field_is_referenced(tree, hf_frame_protocols)) { wmem_strbuf_t *val = wmem_strbuf_sized_new(wmem_packet_scope(), 128, 0); wmem_list_frame_t *frame; /* skip the first entry, it's always the "frame" protocol */ frame = wmem_list_frame_next(wmem_list_head(pinfo->layers)); if (frame) { wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } while (frame) { wmem_strbuf_append_c(val, ':'); wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } proto_item_append_string(ti, wmem_strbuf_get_str(val)); } /* Call postdissectors if we have any (while trying to avoid another * TRY/CATCH) */ if (have_postdissector()) { TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations */ /* (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif call_all_postdissectors(tvb, pinfo, parent_tree); #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch (GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; } /* Attempt to (re-)calculate color filters (if any). */ if (pinfo->fd->flags.need_colorize) { color_filter = color_filters_colorize_packet(fr_data->color_edt); pinfo->fd->color_filter = color_filter; pinfo->fd->flags.need_colorize = 0; } else { color_filter = pinfo->fd->color_filter; } if (color_filter) { item = proto_tree_add_string(fh_tree, hf_frame_color_filter_name, tvb, 0, 0, color_filter->filter_name); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_string(fh_tree, hf_frame_color_filter_text, tvb, 0, 0, color_filter->filter_text); PROTO_ITEM_SET_GENERATED(item); } tap_queue_packet(frame_tap, pinfo, NULL); if (pinfo->frame_end_routines) { g_slist_foreach(pinfo->frame_end_routines, &call_frame_end_routine, NULL); g_slist_free(pinfo->frame_end_routines); pinfo->frame_end_routines = NULL; } if (prefs.enable_incomplete_dissectors_check && tree && tree->tree_data->visible) { gchar* decoded; guint length; guint i; guint byte; guint bit; length = tvb_captured_length(tvb); decoded = proto_find_undecoded_data(tree, length); for (i = 0; i < length; i++) { byte = i / 8; bit = i % 8; if (!(decoded[byte] & (1 << bit))) { field_info* fi = proto_find_field_from_offset(tree, i, tvb); if (fi && fi->hfinfo->id != proto_frame) { g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_WARNING, "Dissector %s incomplete in frame %u: undecoded byte number %u " "(0x%.4X+%u)", (fi ? fi->hfinfo->abbrev : "[unknown]"), pinfo->num, i, i - i % 16, i % 16); proto_tree_add_expert_format(tree, pinfo, &ei_incomplete, tvb, i, 1, "Undecoded byte number: %u (0x%.4X+%u)", i, i - i % 16, i % 16); } } } } return tvb_captured_length(tvb); }