static int dissect_dtpt_wstring(tvbuff_t *tvb, guint offset, proto_tree *tree, int hfindex) { guint32 wstring_length; guint32 wstring_size; char *wstring_data = NULL; guint32 wstring_padding = 0; wstring_length = tvb_get_letohl(tvb, offset); wstring_data = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset+4, wstring_length, ENC_LITTLE_ENDIAN); wstring_size = wstring_length; if (wstring_size%4) { wstring_padding = (4-wstring_size%4); wstring_size += wstring_padding; } if (tree) { proto_item *dtpt_wstring_item = NULL; proto_tree *dtpt_wstring_tree = NULL; dtpt_wstring_item = proto_tree_add_string(tree, hfindex, tvb, offset+0, 4+wstring_size, wstring_data); if (dtpt_wstring_item) dtpt_wstring_tree = proto_item_add_subtree(dtpt_wstring_item, ett_dtpt_wstring); if (dtpt_wstring_tree) { proto_tree_add_uint(dtpt_wstring_tree, hf_dtpt_wstring_length, tvb, offset+0, 4, wstring_length); if (wstring_length) proto_tree_add_string(dtpt_wstring_tree, hf_dtpt_wstring_data, tvb, offset+4, wstring_length, wstring_data); if (wstring_padding) proto_tree_add_text(dtpt_wstring_tree, tvb, offset+4+wstring_length,wstring_padding, "Padding"); } } offset += 4+wstring_size; return offset; }
/* Calculates a CRC32 checksum from the tvb zeroing out four bytes at the offset and checks it with the given crc32 and adds the result to the tree * Returns true if the calculated CRC32 matches the passed CRC32. * */ static gboolean ts2_add_checked_crc32(proto_tree *tree, int hf_item, tvbuff_t *tvb, guint16 offset, guint32 icrc32 ) { guint8 *zero; gint len; guint32 ocrc32; zero = (guint8 *)wmem_alloc0(wmem_packet_scope(), 4); ocrc32 = crc32_ccitt_tvb(tvb, offset); ocrc32 = crc32_ccitt_seed(zero, 4, 0xffffffff-ocrc32); len = tvb_reported_length_remaining(tvb, offset+4); if (len<0) return FALSE; ocrc32 = crc32_ccitt_tvb_offset_seed(tvb, offset+4, (guint)len, 0xffffffff-ocrc32); if(icrc32==ocrc32) { proto_tree_add_uint_format(tree, hf_item, tvb, offset, 4, tvb_get_letohl(tvb, 16), "crc32: 0x%04x [correct]", tvb_get_letohl(tvb, offset)); return TRUE; } else { proto_tree_add_uint_format(tree, hf_item, tvb, offset, 4, tvb_get_letohl(tvb,16), "crc32: 0x%04x [incorrect, should be 0x%04x]", tvb_get_letohl(tvb, offset),ocrc32); return FALSE; } }
static int generate_key_or_iv(unsigned int id, tvbuff_t *salt_tvb, unsigned int iter, const char *pw, unsigned int req_keylen, char * keybuf) { int rc; unsigned int i, j; gcry_md_hd_t md; gcry_mpi_t num_b1 = NULL; size_t pwlen; char hash[20], buf_b[64], buf_i[128], *p; char *salt_p; int salt_size; size_t cur_keylen; size_t n; gcry_error_t err; cur_keylen = 0; salt_size = tvb_captured_length(salt_tvb); salt_p = (char *)tvb_memdup(wmem_packet_scope(), salt_tvb, 0, salt_size); if (pw == NULL) pwlen = 0; else pwlen = strlen(pw); if (pwlen > 63 / 2) { return FALSE; } /* Store salt and password in BUF_I */ p = buf_i; for (i = 0; i < 64; i++) *p++ = salt_p[i % salt_size]; if (pw) { for (i = j = 0; i < 64; i += 2) { *p++ = 0; *p++ = pw[j]; if (++j > pwlen) /* Note, that we include the trailing zero */ j = 0; } } else memset (p, 0, 64); for (;;) { err = gcry_md_open(&md, GCRY_MD_SHA1, 0); if (gcry_err_code(err)) { return FALSE; } for (i = 0; i < 64; i++) { unsigned char lid = id & 0xFF; gcry_md_write (md, &lid, 1); } gcry_md_write(md, buf_i, pw ? 128 : 64); gcry_md_final (md); memcpy (hash, gcry_md_read (md, 0), 20); gcry_md_close (md); for (i = 1; i < iter; i++) gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash, 20); for (i = 0; i < 20 && cur_keylen < req_keylen; i++) keybuf[cur_keylen++] = hash[i]; if (cur_keylen == req_keylen) { gcry_mpi_release (num_b1); return TRUE; /* ready */ } /* need more bytes. */ for (i = 0; i < 64; i++) buf_b[i] = hash[i % 20]; n = 64; rc = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, n, &n); if (rc != 0) { return FALSE; } gcry_mpi_add_ui (num_b1, num_b1, 1); for (i = 0; i < 128; i += 64) { gcry_mpi_t num_ij; n = 64; rc = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, n, &n); if (rc != 0) { return FALSE; } gcry_mpi_add (num_ij, num_ij, num_b1); gcry_mpi_clear_highbit (num_ij, 64 * 8); n = 64; rc = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i, n, &n, num_ij); if (rc != 0) { return FALSE; } gcry_mpi_release (num_ij); } } }
/* * Process a multipart body-part: * MIME-part-headers [ line-end *OCTET ] * line-end dashed-boundary transport-padding line-end * * If applicable, call a media subdissector. * * Return the offset to the start of the next body-part. */ static gint process_body_part(proto_tree *tree, tvbuff_t *tvb, const guint8 *boundary, gint boundary_len, packet_info *pinfo, gint start, gboolean *last_boundary) { proto_tree *subtree; proto_item *ti; gint offset = start, next_offset = 0; char *parameters = NULL; gint body_start, boundary_start, boundary_line_len; gchar *content_type_str = NULL; gchar *content_encoding_str = NULL; char *filename = NULL; char *mimetypename = NULL; int len = 0; gboolean last_field = FALSE; ti = proto_tree_add_item(tree, hf_multipart_part, tvb, start, 0, ENC_ASCII|ENC_NA); subtree = proto_item_add_subtree(ti, ett_multipart_body); /* * Process the MIME-part-headers */ while (!last_field) { gint colon_offset; char *hdr_str; char *header_str; /* Look for the end of the header (denoted by cr) * 3:d argument to imf_find_field_end() maxlen; must be last offset in the tvb. */ next_offset = imf_find_field_end(tvb, offset, tvb_length_remaining(tvb, offset)+offset, &last_field); /* If cr not found, won't have advanced - get out to avoid infinite loop! */ if (next_offset == offset) { break; } hdr_str = tvb_get_string(wmem_packet_scope(), tvb, offset, next_offset - offset); header_str = unfold_and_compact_mime_header(hdr_str, &colon_offset); if (colon_offset <= 0) { proto_tree_add_text(subtree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); } else { gint hf_index; /* Split header name from header value */ header_str[colon_offset] = '\0'; hf_index = is_known_multipart_header(header_str, colon_offset); if (hf_index == -1) { proto_tree_add_text(subtree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); } else { char *value_str = header_str + colon_offset + 1; proto_tree_add_string_format(subtree, hf_header_array[hf_index], tvb, offset, next_offset - offset, (const char *)value_str, "%s", tvb_format_text(tvb, offset, next_offset - offset)); switch (hf_index) { case POS_CONTENT_TYPE: { /* The Content-Type starts at colon_offset + 1 */ gint semicolon_offset = index_of_char( value_str, ';'); if (semicolon_offset > 0) { value_str[semicolon_offset] = '\0'; parameters = wmem_strdup(wmem_packet_scope(), value_str + semicolon_offset + 1); } else { parameters = NULL; } content_type_str = wmem_ascii_strdown(wmem_packet_scope(), value_str, -1); /* Show content-type in root 'part' label */ proto_item_append_text(ti, " (%s)", content_type_str); /* find the "name" parameter in case we don't find a content disposition "filename" */ if((mimetypename = find_parameter(parameters, "name=", &len)) != NULL) { mimetypename = g_strndup(mimetypename, len); } } break; case POS_CONTENT_TRANSFER_ENCODING: { /* The Content-Transfeing starts at colon_offset + 1 */ gint cr_offset = index_of_char(value_str, '\r'); if (cr_offset > 0) { value_str[cr_offset] = '\0'; } content_encoding_str = wmem_ascii_strdown(wmem_packet_scope(), value_str, -1); } break; case POS_CONTENT_DISPOSITION: { /* find the "filename" parameter */ if((filename = find_parameter(value_str, "filename=", &len)) != NULL) { filename = g_strndup(filename, len); } } break; default: break; } } } offset = next_offset; } body_start = next_offset; /* * Process the body */ boundary_start = find_next_boundary(tvb, body_start, boundary, boundary_len, &boundary_line_len, last_boundary); if (boundary_start > 0) { gint body_len = boundary_start - body_start; tvbuff_t *tmp_tvb = tvb_new_subset(tvb, body_start, body_len, body_len); if (content_type_str) { /* * subdissection */ void *save_private_data = pinfo->private_data; gboolean dissected; /* * Try and remove any content transfer encoding so that each sub-dissector * doesn't have to do it itself * */ if(content_encoding_str && remove_base64_encoding) { if(!g_ascii_strncasecmp(content_encoding_str, "base64", 6)) tmp_tvb = base64_decode(pinfo, tmp_tvb, filename ? filename : (mimetypename ? mimetypename : content_type_str)); } pinfo->private_data = parameters; /* * First try the dedicated multipart dissector table */ dissected = dissector_try_string(multipart_media_subdissector_table, content_type_str, tmp_tvb, pinfo, subtree, NULL); if (! dissected) { /* * Fall back to the default media dissector table */ dissected = dissector_try_string(media_type_dissector_table, content_type_str, tmp_tvb, pinfo, subtree, NULL); } if (! dissected) { const char *save_match_string = pinfo->match_string; pinfo->match_string = content_type_str; call_dissector(media_handle, tmp_tvb, pinfo, subtree); pinfo->match_string = save_match_string; } pinfo->private_data = save_private_data; parameters = NULL; /* Shares same memory as content_type_str */ } else { call_dissector(data_handle, tmp_tvb, pinfo, subtree); } proto_item_set_len(ti, boundary_start - start); if (*last_boundary == TRUE) { proto_tree_add_text(tree, tvb, boundary_start, boundary_line_len, "Last boundary: %s", tvb_format_text(tvb, boundary_start, boundary_line_len)); } else { proto_tree_add_text(tree, tvb, boundary_start, boundary_line_len, "Boundary: %s", tvb_format_text(tvb, boundary_start, boundary_line_len)); } g_free(filename); g_free(mimetypename); return boundary_start + boundary_line_len; } g_free(filename); g_free(mimetypename); return -1; }
/* * Main dissection functions */ static guint16 dissect_control(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int is_response) { proto_tree *ctl_tree; proto_item *ctl_ti; guint16 ctl, poll_final; const char *frame_type; char *info; info = (char *)wmem_alloc(wmem_packet_scope(), 80); /* Grab complete control field */ ctl = tvb_get_ntohs(tvb, 1) >> 4; poll_final = ctl & LAPSAT_CTL_P_F; /* Generate small 'descriptive' text */ switch (ctl & LAPSAT_CTL_TYPE_S_U_MSK) { case LAPSAT_CTL_TYPE_S: /* * Supervisory frame. */ switch (ctl & LAPSAT_CTL_S_FTYPE_MSK) { case LAPSAT_RR: frame_type = "RR";
static int dissect_bson_document(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree, int hf_mongo_doc, int nest_level) { gint32 document_length; guint final_offset; proto_item *ti, *elements, *element, *objectid, *js_code, *js_scope; proto_tree *doc_tree, *elements_tree, *element_sub_tree, *objectid_sub_tree, *js_code_sub_tree, *js_scope_sub_tree; document_length = tvb_get_letohl(tvb, offset); ti = proto_tree_add_item(tree, hf_mongo_doc, tvb, offset, document_length, ENC_NA); doc_tree = proto_item_add_subtree(ti, ett_mongo_doc); proto_tree_add_item(doc_tree, hf_mongo_document_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); if (nest_level > BSON_MAX_NESTING) { expert_add_info_format(pinfo, ti, &ei_mongo_document_recursion_exceeded, "BSON document recursion exceeds %u", BSON_MAX_NESTING); THROW(ReportedBoundsError); } if (document_length < 5) { expert_add_info_format(pinfo, ti, &ei_mongo_document_length_bad, "BSON document length too short: %u", document_length); THROW(ReportedBoundsError); } if (document_length > BSON_MAX_DOC_SIZE) { expert_add_info_format(pinfo, ti, &ei_mongo_document_length_bad, "BSON document length too long: %u", document_length); THROW(ReportedBoundsError); } if (document_length == 5) { /* document with length 5 is an empty document */ /* don't display the element subtree */ proto_tree_add_item(tree, hf_mongo_document_empty, tvb, offset, document_length, ENC_NA); return document_length; } final_offset = offset + document_length; offset += 4; elements = proto_tree_add_item(doc_tree, hf_mongo_elements, tvb, offset, document_length-5, ENC_NA); elements_tree = proto_item_add_subtree(elements, ett_mongo_elements); do { /* Read document elements */ guint8 e_type = -1; /* Element type */ gint str_len = -1; /* String length */ gint e_len = -1; /* Element length */ gint doc_len = -1; /* Document length */ e_type = tvb_get_guint8(tvb, offset); tvb_get_stringz(wmem_packet_scope(), tvb, offset+1, &str_len); element = proto_tree_add_item(elements_tree, hf_mongo_element_name, tvb, offset+1, str_len-1, ENC_UTF_8|ENC_NA); element_sub_tree = proto_item_add_subtree(element, ett_mongo_element); proto_tree_add_item(element_sub_tree, hf_mongo_element_type, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += str_len+1; switch(e_type) { case BSON_ELEMENT_TYPE_DOUBLE: proto_tree_add_item(element_sub_tree, hf_mongo_element_value_double, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; break; case BSON_ELEMENT_TYPE_STRING: case BSON_ELEMENT_TYPE_JS_CODE: case BSON_ELEMENT_TYPE_SYMBOL: str_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string, tvb, offset+4, str_len, ENC_UTF_8|ENC_NA); offset += str_len+4; break; case BSON_ELEMENT_TYPE_DOC: case BSON_ELEMENT_TYPE_ARRAY: offset += dissect_bson_document(tvb, pinfo, offset, element_sub_tree, hf_mongo_document, nest_level+1); break; case BSON_ELEMENT_TYPE_BINARY: e_len = tvb_get_letohl(tvb, offset); /* TODO - Add functions to decode various binary subtypes */ proto_tree_add_item(element_sub_tree, hf_mongo_element_value_binary_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_binary, tvb, offset+5, e_len, ENC_NA); offset += e_len+5; break; case BSON_ELEMENT_TYPE_UNDEF: case BSON_ELEMENT_TYPE_NULL: case BSON_ELEMENT_TYPE_MIN_KEY: case BSON_ELEMENT_TYPE_MAX_KEY: /* Nothing to do, as there is no element content */ break; case BSON_ELEMENT_TYPE_OBJ_ID: objectid = proto_tree_add_item(element_sub_tree, hf_mongo_element_value_objectid, tvb, offset, 12, ENC_NA); objectid_sub_tree = proto_item_add_subtree(objectid, ett_mongo_objectid); /* Unlike most BSON elements, parts of ObjectID are stored Big Endian, so they can be compared bit by bit */ proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_time, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_machine, tvb, offset+4, 3, ENC_LITTLE_ENDIAN); proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_pid, tvb, offset+7, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_inc, tvb, offset+9, 3, ENC_BIG_ENDIAN); offset += 12; break; case BSON_ELEMENT_TYPE_BOOL: proto_tree_add_item(element_sub_tree, hf_mongo_element_value_boolean, tvb, offset, 1, ENC_NA); offset += 1; break; case BSON_ELEMENT_TYPE_REGEX: /* regex pattern */ tvb_get_stringz(wmem_packet_scope(), tvb, offset, &str_len); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_regex_pattern, tvb, offset, str_len, ENC_UTF_8|ENC_NA); offset += str_len; /* regex options */ tvb_get_stringz(wmem_packet_scope(), tvb, offset, &str_len); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_regex_options, tvb, offset, str_len, ENC_UTF_8|ENC_NA); offset += str_len; break; case BSON_ELEMENT_TYPE_DB_PTR: str_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string, tvb, offset+4, str_len, ENC_UTF_8|ENC_NA); offset += str_len; proto_tree_add_item(element_sub_tree, hf_mongo_element_value_db_ptr, tvb, offset, 12, ENC_NA); offset += 12; break; case BSON_ELEMENT_TYPE_JS_CODE_SCOPE: /* code_w_s ::= int32 string document */ proto_tree_add_item(element_sub_tree, hf_mongo_element_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); e_len = tvb_get_letohl(tvb, offset); offset += 4; str_len = tvb_get_letohl(tvb, offset); js_code = proto_tree_add_item(element_sub_tree, hf_mongo_element_value_js_code, tvb, offset, str_len+4, ENC_NA); js_code_sub_tree = proto_item_add_subtree(js_code, ett_mongo_code); proto_tree_add_item(js_code_sub_tree, hf_mongo_element_value_string_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(js_code_sub_tree, hf_mongo_element_value_string, tvb, offset+4, str_len, ENC_UTF_8|ENC_NA); offset += str_len+4; doc_len = e_len - (str_len + 8); js_scope = proto_tree_add_item(element_sub_tree, hf_mongo_element_value_js_scope, tvb, offset, doc_len, ENC_NA); js_scope_sub_tree = proto_item_add_subtree(js_scope, ett_mongo_code); offset += dissect_bson_document(tvb, pinfo, offset, js_scope_sub_tree, hf_mongo_document, nest_level+1); break; case BSON_ELEMENT_TYPE_INT32: proto_tree_add_item(element_sub_tree, hf_mongo_element_value_int32, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; break; case BSON_ELEMENT_TYPE_DATETIME: case BSON_ELEMENT_TYPE_TIMESTAMP: /* TODO Implement routine to convert datetime & timestamp values to UTC date/time */ /* for now, simply display the integer value */ case BSON_ELEMENT_TYPE_INT64: proto_tree_add_item(element_sub_tree, hf_mongo_element_value_int64, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; break; default: break; } /* end switch() */ } while (offset < final_offset-1); return document_length; }
static void dissect_tftp_message(tftp_conv_info_t *tftp_info, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *tftp_tree; proto_item *ti; gint offset = 0; guint16 opcode; guint16 bytes; guint16 blocknum; guint i1; guint16 error; tvbuff_t *data_tvb = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFTP"); /* Protocol root */ ti = proto_tree_add_item(tree, proto_tftp, tvb, offset, -1, ENC_NA); tftp_tree = proto_item_add_subtree(ti, ett_tftp); /* Opcode */ opcode = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tftp_tree, hf_tftp_opcode, tvb, offset, 2, opcode); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, tftp_opcode_vals, "Unknown (0x%04x)")); offset += 2; /* read and write requests contain file names for other messages, we add the filenames from the conversation */ if (opcode!=TFTP_RRQ && opcode!=TFTP_WRQ) { if (tftp_info->source_file) { ti = proto_tree_add_string(tftp_tree, hf_tftp_source_file, tvb, 0, 0, tftp_info->source_file); PROTO_ITEM_SET_GENERATED(ti); } if (tftp_info->destination_file) { ti = proto_tree_add_string(tftp_tree, hf_tftp_destination_file, tvb, 0, 0, tftp_info->destination_file); PROTO_ITEM_SET_GENERATED(ti); } } switch (opcode) { case TFTP_RRQ: i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_source_file, tvb, offset, i1, ENC_ASCII|ENC_NA); tftp_info->source_file = tvb_get_string_enc(wmem_file_scope(), tvb, offset, i1, ENC_ASCII); /* we either have a source file name (for read requests) or a destination file name (for write requests) when we set one of the names, we clear the other */ tftp_info->destination_file = NULL; col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s", tvb_format_stringzpad(tvb, offset, i1)); offset += i1; i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_transfer_type, tvb, offset, i1, ENC_ASCII|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s", tvb_format_stringzpad(tvb, offset, i1)); offset += i1; tftp_dissect_options(tvb, pinfo, offset, tftp_tree, opcode, tftp_info); break; case TFTP_WRQ: i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_destination_file, tvb, offset, i1, ENC_ASCII|ENC_NA); tftp_info->destination_file = tvb_get_string_enc(wmem_file_scope(), tvb, offset, i1, ENC_ASCII); tftp_info->source_file = NULL; /* see above */ col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s", tvb_format_stringzpad(tvb, offset, i1)); offset += i1; i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_transfer_type, tvb, offset, i1, ENC_ASCII|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s", tvb_format_stringzpad(tvb, offset, i1)); offset += i1; tftp_dissect_options(tvb, pinfo, offset, tftp_tree, opcode, tftp_info); break; case TFTP_INFO: tftp_dissect_options(tvb, pinfo, offset, tftp_tree, opcode, tftp_info); break; case TFTP_DATA: blocknum = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2, blocknum); /* Sequence analysis on blocknums (first pass only) */ if (!pinfo->fd->flags.visited) { if (blocknum > tftp_info->next_block_num) { /* There is a gap. Don't try to recover from this. */ tftp_info->next_block_num = blocknum + 1; tftp_info->blocks_missing = TRUE; /* TODO: add info to a result table for showing expert info in later passes */ } else if (blocknum == tftp_info->next_block_num) { /* OK, inc what we expect next */ tftp_info->next_block_num++; } } offset += 2; /* Show number of bytes in this block, and whether it is the end of the file */ bytes = tvb_reported_length_remaining(tvb, offset); col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i%s", blocknum, (bytes < tftp_info->blocksize)?" (last)":"" ); /* Show data in tree */ if (bytes > 0) { data_tvb = tvb_new_subset(tvb, offset, -1, bytes); call_dissector(data_handle, data_tvb, pinfo, tree); } /* If Export Object tap is listening, need to accumulate blocks info list to send to tap. But if already know there are blocks missing, there is no point in trying. */ if (have_tap_listener(tftp_eo_tap) && !tftp_info->blocks_missing) { file_block_t *block; if (blocknum == 1) { /* Reset data for this conversation, freeing any accumulated blocks! */ cleanup_tftp_blocks(tftp_info); tftp_info->next_tap_block_num = 1; } if (blocknum != tftp_info->next_tap_block_num) { /* Ignore. Could be missing frames, or just clicking previous frame */ return; } if (bytes > 0) { /* Create a block for this block */ block = (file_block_t*)g_malloc(sizeof(file_block_t)); block->length = bytes; block->data = tvb_memdup(NULL, data_tvb, 0, bytes); /* Add to the end of the list (does involve traversing whole list..) */ tftp_info->block_list = g_slist_append(tftp_info->block_list, block); tftp_info->file_length += bytes; /* Look for next blocknum next time */ tftp_info->next_tap_block_num++; } /* Tap export object only when reach end of file */ if (bytes < tftp_info->blocksize) { tftp_eo_t *eo_info; /* If don't have a filename, won't tap file info */ if ((tftp_info->source_file == NULL) && (tftp_info->destination_file == NULL)) { cleanup_tftp_blocks(tftp_info); return; } /* Create the eo_info to pass to the listener */ eo_info = wmem_new(wmem_packet_scope(), tftp_eo_t); /* Set filename */ if (tftp_info->source_file) { eo_info->filename = g_strdup(tftp_info->source_file); } else if (tftp_info->destination_file) { eo_info->filename = g_strdup(tftp_info->destination_file); } /* Send block list, which will be combined and freed at tap. */ eo_info->payload_len = tftp_info->file_length; eo_info->pkt_num = blocknum; eo_info->block_list = tftp_info->block_list; /* Send to tap */ tap_queue_packet(tftp_eo_tap, pinfo, eo_info); /* Have sent, so forget list of blocks, and only pay attention if we get back to the first block again. */ tftp_info->block_list = NULL; tftp_info->next_tap_block_num = 1; } } break; case TFTP_ACK: blocknum = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2, blocknum); col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i", blocknum); break; case TFTP_ERROR: error = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tftp_tree, hf_tftp_error_code, tvb, offset, 2, error); col_append_fstr(pinfo->cinfo, COL_INFO, ", Code: %s", val_to_str(error, tftp_error_code_vals, "Unknown (%u)")); offset += 2; i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_error_string, tvb, offset, i1, ENC_ASCII|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ", Message: %s", tvb_format_stringzpad(tvb, offset, i1)); expert_add_info(pinfo, NULL, &ei_tftp_blocksize_range); break; case TFTP_OACK: tftp_dissect_options(tvb, pinfo, offset, tftp_tree, opcode, tftp_info); break; default: proto_tree_add_item(tftp_tree, hf_tftp_data, tvb, offset, -1, ENC_NA); break; } }
static int dissect_chargen(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dissector_data _U_) { proto_tree* chargen_tree; proto_item* ti; guint8* data; guint32 len; col_set_str(pinfo->cinfo, COL_PROTOCOL, "Chargen"); col_set_str(pinfo->cinfo, COL_INFO, "Chargen"); ti = proto_tree_add_item(tree, proto_chargen, tvb, 0, -1, ENC_NA); chargen_tree = proto_item_add_subtree(ti, ett_chargen); len = tvb_reported_length(tvb); data = tvb_get_string_enc(wmem_packet_scope(), tvb, 0, len, ENC_ASCII); proto_tree_add_string_format(chargen_tree, hf_chargen_data, tvb, 0, len, "Data", "Data (%u): %s", len, data); /* proto_tree_add_item(chargen_tree, hf_chargen_data, tvb, 0, -1, ENC_ASCII|ENC_NA); */ return tvb_captured_length(tvb); } void proto_register_chargen(void) { static hf_register_info hf[] = { { &hf_chargen_data, { "Data", "chargen.data", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}
static gint dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *ttree = NULL; proto_tree *titem = NULL; proto_item *pitem = NULL; gint offset = 0; usb_conv_info_t *usb_conv_info = (usb_conv_info_t *)data; tvbuff_t *next_tvb = NULL; hci_data_t *hci_data; gint p2p_dir_save; guint32 session_id; fragment_head *reassembled; if (tvb_length_remaining(tvb, offset) <= 0) return 0; titem = proto_tree_add_item(tree, proto_hci_usb, tvb, offset, -1, ENC_NA); ttree = proto_item_add_subtree(titem, ett_hci_usb); col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_USB"); DISSECTOR_ASSERT(usb_conv_info); p2p_dir_save = pinfo->p2p_dir; pinfo->p2p_dir = usb_conv_info->direction; switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_set_str(pinfo->cinfo, COL_INFO, "Sent"); break; case P2P_DIR_RECV: col_set_str(pinfo->cinfo, COL_INFO, "Rcvd"); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction"); break; } session_id = usb_conv_info->bus_id << 16 | usb_conv_info->device_address << 8 | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0 ) << 7 | usb_conv_info->endpoint; hci_data = (hci_data_t *) wmem_new(wmem_packet_scope(), hci_data_t); hci_data->interface_id = HCI_INTERFACE_USB; hci_data->adapter_id = usb_conv_info->bus_id << 8 | usb_conv_info->device_address; hci_data->chandle_to_bdaddr_table = chandle_to_bdaddr_table; hci_data->bdaddr_to_name_table = bdaddr_to_name_table; hci_data->localhost_bdaddr = localhost_bdaddr; hci_data->localhost_name = localhost_name; pinfo->ptype = PT_BLUETOOTH; next_tvb = tvb_new_subset_remaining(tvb, offset); if (!pinfo->fd->flags.visited && usb_conv_info->endpoint <= 0x02) { fragment_info_t *fragment_info; fragment_info = (fragment_info_t *) wmem_tree_lookup32(fragment_info_table, session_id); if (fragment_info == NULL) { fragment_info = (fragment_info_t *) wmem_new(wmem_file_scope(), fragment_info_t); fragment_info->fragment_id = 0; fragment_info->remaining_length = 0; wmem_tree_insert32(fragment_info_table, session_id, fragment_info); } if (fragment_info->fragment_id == 0) { switch(usb_conv_info->endpoint) { case 0: fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 2) + 3; break; case 1: fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 1) + 2; break; case 2: fragment_info->remaining_length = tvb_get_letohs(tvb, offset + 2) + 4; break; } } fragment_info->remaining_length -= tvb_ensure_length_remaining(tvb, offset); fragment_add_seq_check(&hci_usb_reassembly_table, tvb, offset, pinfo, session_id, NULL, fragment_info->fragment_id, tvb_length_remaining(tvb, offset), (fragment_info->remaining_length == 0) ? FALSE : TRUE); if (fragment_info->remaining_length > 0) fragment_info->fragment_id += 1; else fragment_info->fragment_id = 0; } reassembled = fragment_get_reassembled_id(&hci_usb_reassembly_table, pinfo, session_id); if (reassembled && pinfo->fd->num < reassembled->reassembled_in) { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_fragment, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); col_append_str(pinfo->cinfo, COL_INFO, " Fragment"); } else if (reassembled && pinfo->fd->num == reassembled->reassembled_in) { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_complete, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); if (reassembled->len > tvb_ensure_length_remaining(tvb, offset)) { next_tvb = process_reassembled_data(tvb, 0, pinfo, "Reassembled HCI_USB", reassembled, &hci_usb_msg_frag_items, NULL, ttree); } switch(usb_conv_info->endpoint) { case 0: call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, hci_data); break; case 1: call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, hci_data); break; case 2: call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, hci_data); break; } } else { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_unknown_fragment, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); } if (usb_conv_info->endpoint == 0x03) { call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, hci_data); } else if (usb_conv_info->endpoint > 0x03) { proto_tree_add_item(ttree, hf_bthci_usb_data, tvb, offset, -1, ENC_NA); } offset += tvb_length_remaining(tvb, offset); pinfo->p2p_dir = p2p_dir_save; return offset; }
static gint dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *arg0_item; proto_tree *arg0_tree; proto_item *arg1_item; proto_tree *arg1_tree; proto_item *magic_item; proto_item *crc_item; proto_tree *crc_tree = NULL; proto_item *sub_item; gint offset = 0; guint32 command; guint32 arg0; guint32 arg1; guint32 data_length = 0; guint32 crc32 = 0; usb_conv_info_t *usb_conv_info = NULL; wmem_tree_key_t key[5]; guint32 interface_id; guint32 bus_id; guint32 device_address; guint32 side_id; guint32 frame_number; gboolean is_command = TRUE; gboolean is_next_fragment = FALSE; gboolean is_service = FALSE; gint proto; gint direction = P2P_DIR_UNKNOWN; wmem_tree_t *wmem_tree; command_data_t *command_data = NULL; service_data_t *service_data = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ADB"); col_clear(pinfo->cinfo, COL_INFO); main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_adb); frame_number = pinfo->fd->num; /* XXX: Why? If interface is USB only first try is correct * (and seems strange...), in other cases standard check for * previous protocol is correct */ proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers)))); if (proto != proto_usb) { proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers)))); } if (proto == proto_usb) { usb_conv_info = (usb_conv_info_t *) data; DISSECTOR_ASSERT(usb_conv_info); direction = usb_conv_info->direction; } else if (proto == proto_tcp) { if (pinfo->destport == ADB_TCP_PORT) direction = P2P_DIR_SENT; else direction = P2P_DIR_RECV; } else { return offset; } if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) interface_id = pinfo->phdr->interface_id; else interface_id = 0; if (proto == proto_usb) { bus_id = usb_conv_info->bus_id; device_address = usb_conv_info->device_address; key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[1].key = &bus_id; key[2].length = 1; key[2].key = &device_address; key[3].length = 0; key[3].key = NULL; } else { /* tcp */ key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[2].length = 1; if (direction == P2P_DIR_SENT) { key[1].key = &pinfo->srcport; key[2].key = &pinfo->destport; } else { key[1].key = &pinfo->destport; key[2].key = &pinfo->srcport; } key[3].length = 0; key[3].key = NULL; } wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key); if (wmem_tree) { command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (command_data && command_data->completed_in_frame >= frame_number && command_data->command_in_frame <= frame_number) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if (direction == P2P_DIR_SENT) if (command_data->command == A_CLSE) side_id = command_data->arg1; /* OUT: local id */ else side_id = command_data->arg0; /* OUT: local id */ else if (command_data->command == A_OKAY) { side_id = command_data->arg1; /* IN: remote id */ } else side_id = command_data->arg1; /* IN: remote id */ key[3].length = 1; key[3].key = &side_id; key[4].length = 0; key[4].key = NULL; wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key); if (wmem_tree) { service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (service_data && command_data->command == A_OPEN) { is_service = TRUE; } } } } /* Simple heuristics to check if packet is command or data */ if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) { if (tvb_reported_length(tvb) < 24) { is_command = FALSE; } else if (tvb_reported_length(tvb) >= 24) { command = tvb_get_letohl(tvb, offset); if (command != A_SYNC && command != A_CLSE && command != A_WRTE && command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY) is_command = FALSE; else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20))) is_command = FALSE; if (is_command) { data_length = tvb_get_letohl(tvb, offset + 12); crc32 = tvb_get_letohl(tvb, offset + 16); } if (command == A_OPEN) is_service = TRUE; } } if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) { sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data) { sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); if (service_data->close_local_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data->close_remote_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } } if (is_command) { proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN); command = tvb_get_letohl(tvb, offset); offset += 4; col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command")); arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0); arg0 = tvb_get_letohl(tvb, offset); offset += 4; arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1); arg1 = tvb_get_letohl(tvb, offset); offset += 4; switch (command) { case A_CNXN: proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4)); break; case A_AUTH: proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown")); break; case A_OPEN: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8)); break; case A_WRTE: proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4)); break; case A_CLSE: case A_OKAY: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4)); break; case A_SYNC: proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4)); break; } proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (data_length > 0) col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length); crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); crc32 = tvb_get_letohl(tvb, offset); offset += 4; magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN); if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) { proto_tree *expert_tree; expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic); proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4); } if (!pinfo->fd->flags.visited) save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data); offset += 4; } if (!pinfo->fd->flags.visited && command_data) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) || (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24) ) { command_data->reassemble_data_length = command_data->data_length; command_data->completed_in_frame = frame_number; } } if (is_next_fragment && command_data) { sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length); PROTO_ITEM_SET_GENERATED(sub_item); crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); PROTO_ITEM_SET_GENERATED(crc_item); } if (command_data && command_data->completed_in_frame != frame_number) { sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) { guint32 crc = 0; guint32 i_offset; if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */ if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) { tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset)); command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset); if (command_data->reassemble_data_length >= command_data->data_length) command_data->completed_in_frame = frame_number; } proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment"); offset = tvb_captured_length(tvb); if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length); add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data"); adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } } else { /* full message */ for (i_offset = 0; i_offset < data_length; ++i_offset) crc += tvb_get_guint8(tvb, offset + i_offset); if (crc32 > 0 && crc32 != crc) proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1); if (is_service) { proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA); if (!pinfo->fd->flags.visited && service_data) { service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII); } col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII)); offset = tvb_captured_length(tvb); } else if (command_data && command_data->command == A_CNXN) { gchar *info; gint len; info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info); proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA); offset += len; } else { col_append_str(pinfo->cinfo, COL_INFO, "Data"); /* Decode service payload */ if (service_data) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } next_tvb = tvb_new_subset(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset)); call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } else { proto_item *data_item; gchar *data_str; data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA); data_str = tvb_format_text(tvb, offset, data_length); proto_item_append_text(data_item, ": %s", data_str); col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str); } offset = tvb_captured_length(tvb); } } } return offset; }
/* note that even if ajp13_tree is null on the first pass, we still * need to dissect the packet in order to determine if there is a * content-length, and thus if there is a subsequent automatic * request-body transmitted in the next request packet. if there is a * content-length, we record the fact in the conversation context. * ref the top of this file for comments explaining the multi-pass * thing. */ static void display_req_forward(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ajp13_tree, ajp13_conv_data* cd) { int pos = 0; guint8 meth; guint8 cod; const gchar *ver; guint16 ver_len; const gchar *uri; guint16 uri_len; const gchar *raddr; guint16 raddr_len; const gchar *rhost; guint16 rhost_len; const gchar *srv; guint16 srv_len; guint nhdr; guint i; if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, ENC_NA); pos+=2; if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* PACKET CODE */ cod = tvb_get_guint8(tvb, 4); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_code, tvb, pos, 1, ENC_BIG_ENDIAN); pos+=1; if ( cod == MTYPE_CPING ) { col_append_str(pinfo->cinfo, COL_INFO, "CPING" ); return; } /* HTTP METHOD (ENCODED AS INTEGER) */ meth = tvb_get_guint8(tvb, pos); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(meth, http_method_codes, "Unknown method %u")); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_method, tvb, pos, 1, ENC_BIG_ENDIAN); pos+=1; /* HTTP VERSION STRING */ ver = ajp13_get_nstring(tvb, pos, &ver_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_ver, tvb, pos, ver_len+2, ver); pos=pos+ver_len+2; /* skip over size + chars + trailing null */ /* URI */ uri = ajp13_get_nstring(tvb, pos, &uri_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_uri, tvb, pos, uri_len+2, uri); pos=pos+uri_len+2; /* skip over size + chars + trailing null */ col_append_fstr(pinfo->cinfo, COL_INFO, " %s %s", uri, ver); /* REMOTE ADDRESS */ raddr = ajp13_get_nstring(tvb, pos, &raddr_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_raddr, tvb, pos, raddr_len+2, raddr); pos=pos+raddr_len+2; /* skip over size + chars + trailing null */ /* REMOTE HOST */ rhost = ajp13_get_nstring(tvb, pos, &rhost_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_rhost, tvb, pos, rhost_len+2, rhost); pos=pos+rhost_len+2; /* skip over size + chars + trailing null */ /* SERVER NAME */ srv = ajp13_get_nstring(tvb, pos, &srv_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_srv, tvb, pos, srv_len+2, srv); pos=pos+srv_len+2; /* skip over size + chars + trailing null */ /* SERVER PORT */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_port, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* IS SSL? */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_sslp, tvb, pos, 1, ENC_NA); pos+=1; /* NUM HEADERS */ nhdr = tvb_get_ntohs(tvb, pos); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; cd->content_length = 0; /* HEADERS */ for(i=0; i<nhdr; i++) { guint8 hcd; guint8 hid; const gchar* hname = NULL; int hpos = pos; int cl = 0; const gchar *hval; guint16 hval_len, hname_len; /* HEADER CODE/NAME */ hcd = tvb_get_guint8(tvb, pos); if (hcd == 0xA0) { pos+=1; hid = tvb_get_guint8(tvb, pos); pos+=1; if (hid >= array_length(req_headers)) hid = 0; hval = ajp13_get_nstring(tvb, pos, &hval_len); proto_tree_add_string_format(ajp13_tree, *req_headers[hid], tvb, hpos, 2+hval_len+2, hval, "%s", hval); pos+=hval_len+2; if (hid == 0x08) cl = 1; } else { hname = ajp13_get_nstring(tvb, pos, &hname_len); pos+=hname_len+2; hval = ajp13_get_nstring(tvb, pos, &hval_len); proto_tree_add_string_format(ajp13_tree, hf_ajp13_additional_header, tvb, hpos, hname_len+2+hval_len+2, wmem_strdup_printf(wmem_packet_scope(), "%s: %s", hname, hval), "%s: %s", hname, hval); pos+=hval_len+2; } if (cl) { cl = atoi(hval); cd->content_length = cl; } } /* ATTRIBUTES */ while(tvb_reported_length_remaining(tvb, pos) > 0) { guint8 aid; const gchar* aname = NULL; const gchar* aval; guint16 aval_len, aname_len; int apos = pos; /* ATTRIBUTE CODE/NAME */ aid = tvb_get_guint8(tvb, pos); pos+=1; if (aid == 0xFF) { /* request terminator */ break; } if (aid == 0x0A) { /* req_attribute - name and value follow */ aname = ajp13_get_nstring(tvb, pos, &aname_len); pos+=aname_len+2; aval = ajp13_get_nstring(tvb, pos, &aval_len); pos+=aval_len+2; proto_tree_add_string_format(ajp13_tree, hf_ajp13_req_attribute, tvb, apos, 1+aname_len+2+aval_len+2, wmem_strdup_printf(wmem_packet_scope(), "%s: %s", aname, aval), "%s: %s", aname, aval); } else if (aid == 0x0B ) { /* ssl_key_length */ if (ajp13_tree) { proto_tree_add_uint(ajp13_tree, hf_ajp13_ssl_key_size, tvb, apos, 1+2, tvb_get_ntohs(tvb, pos)); } pos+=2; } else { if (aid >= array_length(req_attributes)) aid = 0; aval = ajp13_get_nstring(tvb, pos, &aval_len); pos+=aval_len+2; proto_tree_add_string_format(ajp13_tree, *req_attributes[aid], tvb, apos, 1+aval_len+2, aval, "%s", aval); } } }
/* dissect a response. more work to do here. */ static void display_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ajp13_tree, ajp13_conv_data* cd) { int pos = 0; guint8 mcode = 0; int i; /* MAGIC */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, ENC_NA); pos+=2; /* PDU LENGTH */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* MESSAGE TYPE CODE */ mcode = tvb_get_guint8(tvb, pos); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(mcode, mtype_codes, "Unknown message code %u")); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_code, tvb, pos, 1, ENC_BIG_ENDIAN); pos+=1; switch (mcode) { case MTYPE_END_RESPONSE: if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_reusep, tvb, pos, 1, ENC_BIG_ENDIAN); /*pos+=1;*/ break; case MTYPE_SEND_HEADERS: { const gchar *rsmsg; guint16 rsmsg_len; guint16 nhdr; guint16 rcode_num; /* HTTP RESPONSE STATUS CODE */ rcode_num = tvb_get_ntohs(tvb, pos); col_append_fstr(pinfo->cinfo, COL_INFO, ":%d", rcode_num); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_rstatus, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* HTTP RESPONSE STATUS MESSAGE */ rsmsg = ajp13_get_nstring(tvb, pos, &rsmsg_len); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", rsmsg); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_rsmsg, tvb, pos, rsmsg_len+2, rsmsg); pos+=rsmsg_len+2; /* NUMBER OF HEADERS */ nhdr = tvb_get_ntohs(tvb, pos); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* HEADERS */ for(i=0; i<nhdr; i++) { guint8 hcd; guint8 hid; const gchar *hval; guint16 hval_len, hname_len; const gchar* hname = NULL; int hpos = pos; /* int cl = 0; TODO: Content-Length header (encoded by 0x08) is special */ /* HEADER CODE/NAME */ hcd = tvb_get_guint8(tvb, pos); if (hcd == 0xA0) { pos+=1; hid = tvb_get_guint8(tvb, pos); pos+=1; if (hid >= array_length(rsp_headers)) hid = 0; hval = ajp13_get_nstring(tvb, pos, &hval_len); proto_tree_add_string_format_value(ajp13_tree, *rsp_headers[hid], tvb, hpos, 2+hval_len+2, hval, "%s", hval); pos+=hval_len+2; #if 0 /* TODO: Content-Length header (encoded by 0x08) is special */ if (hid == 0x08) cl = 1; #endif } else { hname = ajp13_get_nstring(tvb, pos, &hname_len); pos+=hname_len+2; hval = ajp13_get_nstring(tvb, pos, &hval_len); proto_tree_add_string_format(ajp13_tree, hf_ajp13_additional_header, tvb, hpos, hname_len+2+hval_len+2, wmem_strdup_printf(wmem_packet_scope(), "%s: %s", hname, hval), "%s: %s", hname, hval); pos+=hval_len+2; } } break; } case MTYPE_GET_BODY_CHUNK: { guint16 rlen; rlen = tvb_get_ntohs(tvb, pos); cd->content_length = rlen; if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_rlen, tvb, pos, 2, ENC_BIG_ENDIAN); /*pos+=2;*/ break; } case MTYPE_CPONG: break; default: /* MESSAGE DATA (COPOUT) */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_data, tvb, pos+2, -1, ENC_UTF_8|ENC_NA); break; } }
for (offset = 0; offset < len; offset++) { val = tvb_get_guint8(tvb, offset); if (!(g_ascii_isprint(val) || (val == 0x0a) || (val == 0x0d))) return (FALSE); } return (TRUE); } /* The dissector itself */ static int dissect_at(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { proto_item *item; proto_tree *at_tree; gchar *string; string = tvb_format_text_wsp(wmem_packet_scope(), tvb, 0, tvb_captured_length(tvb)); col_append_sep_str(pinfo->cinfo, COL_PROTOCOL, "/", "AT"); col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "AT Command: %s", string); /* Start with a top-level item to add everything else to */ item = proto_tree_add_item(tree, proto_at, tvb, 0, -1, ENC_NA); proto_item_append_text(item, ": %s", string); at_tree = proto_item_add_subtree(item, ett_at); /* Command */ proto_tree_add_item(at_tree, hf_at_command, tvb, 0, tvb_reported_length(tvb), ENC_ASCII|ENC_NA); return tvb_captured_length(tvb); }
void dissect_umts_cell_broadcast_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 sms_encoding; guint32 offset = 0; guint32 len; proto_item *cbs_item = NULL, *cbs_item2 = NULL; proto_tree *cbs_tree = NULL, *cbs_subtree = NULL; guint msg_len; tvbuff_t * cbs_msg_tvb = NULL; len = tvb_length(tvb); col_append_str(pinfo->cinfo, COL_PROTOCOL, " Cell Broadcast"); col_append_str(pinfo->cinfo, COL_INFO, " (CBS Message)"); cbs_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, tvb, 0, len, "Cell Broadcast"); cbs_tree = proto_item_add_subtree(cbs_item, ett_cbs_msg); sms_encoding = dissect_cbs_data_coding_scheme(tvb, pinfo, cbs_tree, 0); offset++; cbs_msg_tvb = dissect_cbs_data(sms_encoding, tvb, cbs_tree, pinfo, offset ); msg_len = tvb_length(cbs_msg_tvb); cbs_item2 = proto_tree_add_text(cbs_tree, tvb, offset, -1, "Cell Broadcast Message Contents (length: %d)", msg_len); cbs_subtree = proto_item_add_subtree(cbs_item2, ett_cbs_msg); proto_tree_add_text(cbs_subtree, cbs_msg_tvb , 0, tvb_length(cbs_msg_tvb), "%s", tvb_get_string(wmem_packet_scope(), cbs_msg_tvb, 0, msg_len)); }
/* Code to actually dissect the packets */ static void dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { char *szInfo; int offCur = 0; /* current offset from start of WTP data */ gint returned_length, str_index = 0; unsigned char b0; /* continuation flag */ unsigned char fCon; /* Continue flag */ unsigned char fRID; /* Re-transmission indicator*/ unsigned char fTTR = '\0'; /* Transmission trailer */ guint cbHeader = 0; /* Fixed header length */ guint vHeader = 0; /* Variable header length*/ int abortType = 0; /* Set up structures we'll need to add the protocol subtree and manage it */ proto_item *ti = NULL; proto_tree *wtp_tree = NULL; char pdut; char clsTransaction = 3; int numMissing = 0; /* Number of missing packets in a negative ack */ int i; tvbuff_t *wsp_tvb = NULL; guint8 psn = 0; /* Packet sequence number*/ guint16 TID = 0; /* Transaction-Id */ int dataOffset; gint dataLen; #define SZINFO_SIZE 256 szInfo=(char *)wmem_alloc(wmem_packet_scope(), SZINFO_SIZE); b0 = tvb_get_guint8 (tvb, offCur + 0); /* Discover Concatenated PDUs */ if (b0 == 0) { guint c_fieldlen = 0; /* Length of length-field */ guint c_pdulen = 0; /* Length of conc. PDU */ if (tree) { ti = proto_tree_add_item(tree, proto_wtp, tvb, offCur, 1, ENC_NA); wtp_tree = proto_item_add_subtree(ti, ett_wtp_sub_pdu_tree); proto_item_append_text(ti, ", PDU concatenation"); } offCur = 1; i = 1; while (offCur < (int) tvb_reported_length(tvb)) { tvbuff_t *wtp_tvb; /* The length of an embedded WTP PDU is coded as either: * - a 7-bit value contained in one octet with highest bit == 0. * - a 15-bit value contained in two octets (little endian) * if the 1st octet has its highest bit == 1. * This means that this is NOT encoded as an uintvar-integer!!! */ b0 = tvb_get_guint8(tvb, offCur + 0); if (b0 & 0x80) { c_fieldlen = 2; c_pdulen = ((b0 & 0x7f) << 8) | tvb_get_guint8(tvb, offCur + 1); } else { c_fieldlen = 1; c_pdulen = b0; } if (tree) { proto_tree_add_uint(wtp_tree, hf_wtp_header_sub_pdu_size, tvb, offCur, c_fieldlen, c_pdulen); } if (i > 1) { col_append_str(pinfo->cinfo, COL_INFO, ", "); } /* Skip the length field for the WTP sub-tvb */ wtp_tvb = tvb_new_subset_length(tvb, offCur + c_fieldlen, c_pdulen); dissect_wtp_common(wtp_tvb, pinfo, wtp_tree); offCur += c_fieldlen + c_pdulen; i++; } if (tree) { proto_item_append_text(ti, ", PDU count: %u", i); } return; } /* No concatenation */ fCon = b0 & 0x80; fRID = retransmission_indicator(b0); pdut = pdu_type(b0); #ifdef DEBUG printf("WTP packet %u: tree = %p, pdu = %s (%u) length: %u\n", pinfo->fd->num, tree, val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"), pdut, tvb_captured_length(tvb)); #endif /* Develop the string to put in the Info column */ returned_length = g_snprintf(szInfo, SZINFO_SIZE, "WTP %s", val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x")); str_index += MIN(returned_length, SZINFO_SIZE-str_index); switch (pdut) { case INVOKE: fTTR = transmission_trailer(b0); TID = tvb_get_ntohs(tvb, offCur + 1); psn = 0; clsTransaction = transaction_class(tvb_get_guint8(tvb, offCur + 3)); returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " Class %d", clsTransaction); str_index += MIN(returned_length, SZINFO_SIZE-str_index); cbHeader = 4; break; case SEGMENTED_INVOKE: case SEGMENTED_RESULT: fTTR = transmission_trailer(b0); TID = tvb_get_ntohs(tvb, offCur + 1); psn = tvb_get_guint8(tvb, offCur + 3); if (psn != 0) { returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " (%u)", psn); str_index += MIN(returned_length, SZINFO_SIZE-str_index); } cbHeader = 4; break; case ABORT: cbHeader = 4; break; case RESULT: fTTR = transmission_trailer(b0); TID = tvb_get_ntohs(tvb, offCur + 1); psn = 0; cbHeader = 3; break; case ACK: cbHeader = 3; break; case NEGATIVE_ACK: /* Variable number of missing packets */ numMissing = tvb_get_guint8(tvb, offCur + 3); cbHeader = numMissing + 4; break; default: break; }; if (fRID) { /*returned_length =*/ g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " R" ); /*str_index += MIN(returned_length, SZINFO_SIZE-str_index);*/ }; /* In the interest of speed, if "tree" is NULL, don't do any work not necessary to generate protocol tree items. */ if (tree) { #ifdef DEBUG fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader); #endif /* NOTE - Length will be set when we process the TPI */ ti = proto_tree_add_item(tree, proto_wtp, tvb, offCur, 0, ENC_NA); #ifdef DEBUG fprintf(stderr, "dissect_wtp: (7) Returned from proto_tree_add_item\n"); #endif wtp_tree = proto_item_add_subtree(ti, ett_wtp); /* Code to process the packet goes here */ #ifdef DEBUG fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader); fprintf(stderr, "dissect_wtp: offCur = %d\n", offCur); #endif /* Add common items: only CON and PDU Type */ proto_tree_add_item( wtp_tree, /* tree */ hf_wtp_header_flag_continue, /* id */ tvb, offCur, /* start of highlight */ 1, /* length of highlight*/ b0 /* value */ ); proto_tree_add_item(wtp_tree, hf_wtp_header_pdu_type, tvb, offCur, 1, ENC_LITTLE_ENDIAN); switch(pdut) { case INVOKE: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_version , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_TIDNew, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_UP, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_Reserved, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_TransactionClass, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Invoke (%u)" ", Transaction Class: %s (%u)", INVOKE, val_to_str_const(clsTransaction, vals_transaction_classes, "Undefined"), clsTransaction); break; case RESULT: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_item_append_text(ti, ", PDU: Result (%u)", RESULT); break; case ACK: proto_tree_add_item(wtp_tree, hf_wtp_header_Ack_flag_TVETOK, tvb, offCur, 1, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_item_append_text(ti, ", PDU: ACK (%u)", ACK); break; case ABORT: abortType = tvb_get_guint8 (tvb, offCur) & 0x07; proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_type , tvb, offCur , 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); if (abortType == PROVIDER) { guint8 reason = tvb_get_guint8(tvb, offCur + 3); proto_tree_add_item( wtp_tree, hf_wtp_header_Abort_reason_provider , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Abort (%u)" ", Type: Provider (%u)" ", Reason: %s (%u)", ABORT, PROVIDER, val_to_str_const(reason, vals_abort_reason_provider, "Undefined"), reason); } else if (abortType == USER) { guint8 reason = tvb_get_guint8(tvb, offCur + 3); proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_reason_user , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Abort (%u)" ", Type: User (%u)" ", Reason: %s (%u)", ABORT, PROVIDER, val_to_str_ext_const(reason, &vals_wsp_reason_codes_ext, "Undefined"), reason); } break; case SEGMENTED_INVOKE: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Segmented Invoke (%u)" ", Packet Sequence Number: %u", SEGMENTED_INVOKE, psn); break; case SEGMENTED_RESULT: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Segmented Result (%u)" ", Packet Sequence Number: %u", SEGMENTED_RESULT, psn); break; case NEGATIVE_ACK: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_missing_packets , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); /* Iterate through missing packets */ for (i = 0; i < numMissing; i++) { proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number, tvb, offCur + 4 + i, 1, ENC_LITTLE_ENDIAN); } proto_item_append_text(ti, ", PDU: Negative Ack (%u)" ", Missing Packets: %u", NEGATIVE_ACK, numMissing); break; default: break; }; if (fRID) { proto_item_append_text(ti, ", Retransmission"); } } else { /* tree is NULL */ #ifdef DEBUG fprintf(stderr, "dissect_wtp: (4) tree was %p\n", tree); #endif } /* Process the variable part */ if (fCon) { /* Now, analyze variable part */ guint8 tCon; guint8 tByte; guint tpiLen; tvbuff_t *tmp_tvb; vHeader = 0; /* Start scan all over */ do { tByte = tvb_get_guint8(tvb, offCur + cbHeader + vHeader); tCon = tByte & 0x80; if (tByte & 0x04) /* Long TPI */ tpiLen = 2 + tvb_get_guint8(tvb, offCur + cbHeader + vHeader + 1); else tpiLen = 1 + (tByte & 0x03); if (tree) { tmp_tvb = tvb_new_subset_length(tvb, offCur + cbHeader + vHeader, tpiLen); wtp_handle_tpi(wtp_tree, tmp_tvb); } vHeader += tpiLen; } while (tCon); } else { /* There is no variable part */ } /* End of variable part of header */ /* Set the length of the WTP protocol part now we know the length of the * fixed and variable WTP headers */ if (tree) proto_item_set_len(ti, cbHeader + vHeader); #ifdef DEBUG fprintf( stderr, "dissect_wtp: cbHeader = %d\n", cbHeader ); #endif /* * Any remaining data ought to be WSP data (if not WTP ACK, NACK * or ABORT pdu), so, if we have any remaining data, and it's * not an ACK, NACK, or ABORT PDU, hand it off (defragmented) to the * WSP dissector. * Note that the last packet of a fragmented WTP message needn't * contain any data, so we allow payloadless packets to be * reassembled. (XXX - does the reassembly code handle this * for packets other than the last packet?) * * Try calling a subdissector only if: * - The WTP payload is ressembled in this very packet, * - The WTP payload is not fragmented across packets. */ dataOffset = offCur + cbHeader + vHeader; dataLen = tvb_reported_length_remaining(tvb, dataOffset); if ((dataLen >= 0) && ! ((pdut==ACK) || (pdut==NEGATIVE_ACK) || (pdut==ABORT))) { /* Try to reassemble if needed, and hand over to WSP * A fragmented WTP packet is either: * - An INVOKE with fTTR (transmission trailer) not set, * - a SEGMENTED_INVOKE, * - A RESULT with fTTR (transmission trailer) not set, * - a SEGMENTED_RESULT. */ if ( ( (pdut == SEGMENTED_INVOKE) || (pdut == SEGMENTED_RESULT) || ( ((pdut == INVOKE) || (pdut == RESULT)) && (!fTTR) ) ) && tvb_bytes_exist(tvb, dataOffset, dataLen) ) { /* Try reassembling fragments */ fragment_head *fd_wtp = NULL; guint32 reassembled_in = 0; gboolean save_fragmented = pinfo->fragmented; pinfo->fragmented = TRUE; fd_wtp = fragment_add_seq(&wtp_reassembly_table, tvb, dataOffset, pinfo, TID, NULL, psn, dataLen, !fTTR, 0); /* XXX - fragment_add_seq() yields NULL unless Wireshark knows * that the packet is part of a reassembled whole. This means * that fd_wtp will be NULL as long as Wireshark did not encounter * (and process) the packet containing the last fragment. * This implies that Wireshark needs two passes over the data for * correct reassembly. At the first pass, a capture containing * three fragments plus a retransmssion of the last fragment * will progressively show: * * Packet 1: (Unreassembled fragment 1) * Packet 2: (Unreassembled fragment 2) * Packet 3: (Reassembled WTP) * Packet 4: (WTP payload reassembled in packet 3) * * However at subsequent evaluation (e.g., by applying a display * filter) the packet summary will show: * * Packet 1: (WTP payload reassembled in packet 3) * Packet 2: (WTP payload reassembled in packet 3) * Packet 3: (Reassembled WTP) * Packet 4: (WTP payload reassembled in packet 3) * * This is important to know, and also affects read filters! */ wsp_tvb = process_reassembled_data(tvb, dataOffset, pinfo, "Reassembled WTP", fd_wtp, &wtp_frag_items, NULL, wtp_tree); #ifdef DEBUG printf("WTP: Packet %u %s -> %d: wsp_tvb = %p, fd_wtp = %p, frame = %u\n", pinfo->fd->num, fd_wtp ? "Reassembled" : "Not reassembled", fd_wtp ? fd_wtp->reassembled_in : -1, wsp_tvb, fd_wtp ); #endif if (fd_wtp) { /* Reassembled */ reassembled_in = fd_wtp->reassembled_in; if (pinfo->fd->num == reassembled_in) { /* Reassembled in this very packet: * We can safely hand the tvb to the WSP dissector */ call_dissector(wsp_handle, wsp_tvb, pinfo, tree); } else { /* Not reassembled in this packet */ col_append_fstr(pinfo->cinfo, COL_INFO, "%s (WTP payload reassembled in packet %u)", szInfo, fd_wtp->reassembled_in); proto_tree_add_item(wtp_tree, hf_wtp_payload, tvb, dataOffset, -1, ENC_NA); } } else { /* Not reassembled yet, or not reassembled at all */ col_append_fstr(pinfo->cinfo, COL_INFO, "%s (Unreassembled fragment %u)", szInfo, psn); proto_tree_add_item(wtp_tree, hf_wtp_payload, tvb, dataOffset, -1, ENC_NA); } /* Now reset fragmentation information in pinfo */ pinfo->fragmented = save_fragmented; } else if ( ((pdut == INVOKE) || (pdut == RESULT)) && (fTTR) ) { /* Non-fragmented payload */ wsp_tvb = tvb_new_subset_remaining(tvb, dataOffset); /* We can safely hand the tvb to the WSP dissector */ call_dissector(wsp_handle, wsp_tvb, pinfo, tree); } else { /* Nothing to hand to subdissector */ col_append_str(pinfo->cinfo, COL_INFO, szInfo); } } else { /* Nothing to hand to subdissector */ col_append_str(pinfo->cinfo, COL_INFO, szInfo); } }
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 void dissect_applemidi_common( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 command ) { guint16 seq_num; guint8 count; guint8 *name; gint offset = 0; gint len; gint string_size; proto_tree *applemidi_tree; proto_tree *applemidi_tree_seq_num; col_set_str( pinfo->cinfo, COL_PROTOCOL, APPLEMIDI_DISSECTOR_SHORTNAME ); col_add_fstr( pinfo->cinfo, COL_INFO, "%s", val_to_str( command, applemidi_commands, applemidi_unknown_command ) ); if ( tree ) { proto_item *ti; ti = proto_tree_add_item( tree, proto_applemidi, tvb, 0, -1, ENC_NA ); applemidi_tree = proto_item_add_subtree( ti, ett_applemidi ); proto_tree_add_item( applemidi_tree, hf_applemidi_signature, tvb, offset, 2, ENC_BIG_ENDIAN ); offset += 2; proto_tree_add_item( applemidi_tree, hf_applemidi_command, tvb, offset, 2, ENC_BIG_ENDIAN ); offset += 2; /* the format of packets for "IN", "NO", "OK" and "BY" is identical and contains * the protocol version, a random number generated by the initiator of the session, * the SSRC that is used by the respective sides RTP-entity and optionally the * name of the participant */ if ( ( APPLEMIDI_COMMAND_INVITATION == command ) || ( APPLEMIDI_COMMAND_INVITATION_REJECTED == command ) || ( APLLEMIDI_COMMAND_INVITATION_ACCEPTED == command ) || ( APPLEMIDI_COMMAND_ENDSESSION == command ) ) { proto_tree_add_item( applemidi_tree, hf_applemidi_protocol_version, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; proto_tree_add_item( applemidi_tree, hf_applemidi_token, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; len = tvb_reported_length(tvb) - offset; /* Name is optional */ if ( len > 0 ) { name = tvb_get_string_enc( wmem_packet_scope(), tvb, offset, len, ENC_UTF_8|ENC_NA ); string_size = (gint)( strlen( name ) + 1 ); proto_tree_add_item( applemidi_tree, hf_applemidi_name, tvb, offset, string_size, ENC_UTF_8|ENC_NA ); col_append_fstr( pinfo->cinfo, COL_INFO, ": peer = \"%s\"", name ); offset += string_size; } /* the synchronization packet contains three 64bit timestamps, and a value to define how * many of the timestamps transmitted are valid */ } else if ( APPLEMIDI_COMMAND_SYNCHRONIZATION == command ) { proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; count = tvb_get_guint8( tvb, offset ); proto_tree_add_item( applemidi_tree, hf_applemidi_count, tvb, offset, 1, ENC_BIG_ENDIAN ); col_append_fstr( pinfo->cinfo, COL_INFO, ": count = %u", count ); offset += 1; proto_tree_add_item( applemidi_tree, hf_applemidi_padding, tvb, offset, 3, ENC_BIG_ENDIAN ); offset += 3; proto_tree_add_item( applemidi_tree, hf_applemidi_timestamp1, tvb, offset, 8, ENC_BIG_ENDIAN ); offset += 8; proto_tree_add_item( applemidi_tree, hf_applemidi_timestamp2, tvb, offset, 8, ENC_BIG_ENDIAN ); offset += 8; proto_tree_add_item( applemidi_tree, hf_applemidi_timestamp3, tvb, offset, 8, ENC_BIG_ENDIAN ); offset += 8; /* With the receiver feedback packet, the recipient can tell the sender up to what sequence * number in the RTP-stream the packets have been received; this can be used to shorten the * recovery-journal-section in the RTP-session */ } else if ( APPLEMIDI_COMMAND_RECEIVER_FEEDBACK == command ) { proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; ti = proto_tree_add_item( applemidi_tree, hf_applemidi_sequence_num, tvb, offset, 4, ENC_BIG_ENDIAN ); /* Apple includes a 32bit sequence-number, but the RTP-packet only specifies 16bit. * this subtree and subitem are added to be able to associate the sequence-number * here easier with the one specified in the corresponding RTP-packet */ applemidi_tree_seq_num = proto_item_add_subtree( ti, ett_applemidi_seq_num ); seq_num = tvb_get_ntohs( tvb, offset ); proto_tree_add_uint( applemidi_tree_seq_num, hf_applemidi_rtp_sequence_num, tvb, offset, 2, seq_num ); offset += 4; col_append_fstr( pinfo->cinfo, COL_INFO, ": seq = %u", seq_num ); /* With the bitrate receive limit packet, the recipient can tell the sender to limit the transmission to a certain bitrate. This is important if the peer is a gateway to a hardware-device that only supports a certain speed. Like the MIDI 1.0 DIN-cable MIDI-implementation which is limited to 31250. */ } else if ( APPLEMIDI_COMMAND_BITRATE_RECEIVE_LIMIT == command ) { proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; proto_tree_add_item( applemidi_tree, hf_applemidi_rtp_bitrate_limit, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; } /* If there is any remaining data (possibly because an unknown command was encountered), * we just dump it here */ len = tvb_length_remaining( tvb, offset ); if ( len > 0 ) { proto_tree_add_item( applemidi_tree, hf_applemidi_unknown_data, tvb, offset, len, ENC_NA ); } } }
/* * Parse the address and port information in a PORT command or in the * response to a PASV command. Return TRUE if we found an address and * port, and supply the address and port; return FALSE if we didn't find * them. * * We ignore the IP address in the reply, and use the address from which * the request came. * * XXX - are there cases where they differ? What if the FTP server is * behind a NAT box, so that the address it puts into the reply isn't * the address at which you should contact it? Do all NAT boxes detect * FTP PASV replies and rewrite the address? (I suspect not.) * * RFC 959 doesn't say much about the syntax of the 227 reply. * * A proposal from Dan Bernstein at * * http://cr.yp.to/ftp/retr.html * * "recommend[s] that clients use the following strategy to parse the * response line: look for the first digit after the initial space; look * for the fourth comma after that digit; read two (possibly negative) * integers, separated by a comma; the TCP port number is p1*256+p2, where * p1 is the first integer modulo 256 and p2 is the second integer modulo * 256." * * wget 1.5.3 looks for a digit, although it doesn't handle negative * integers. * * The FTP code in the source of the cURL library, at * * http://curl.haxx.se/lxr/source/lib/ftp.c * * says that cURL "now scans for a sequence of six comma-separated numbers * and will take them as IP+port indicators"; it loops, doing "sscanf"s * looking for six numbers separated by commas, stepping the start pointer * in the scanf one character at a time - i.e., it tries rather exhaustively. * * An optimization would be to scan for a digit, and start there, and if * the scanf doesn't find six values, scan for the next digit and try * again; this will probably succeed on the first try. * * The cURL code also says that "found reply-strings include": * * "227 Entering Passive Mode (127,0,0,1,4,51)" * "227 Data transfer will passively listen to 127,0,0,1,4,51" * "227 Entering passive mode. 127,0,0,1,4,51" * * so it appears that you can't assume there are parentheses around * the address and port number. */ static gboolean parse_port_pasv(const guchar *line, int linelen, guint32 *ftp_ip, guint16 *ftp_port, guint32 *pasv_offset, guint *ftp_ip_len, guint *ftp_port_len) { char *args; char *p; guchar c; int i; int ip_address[4], port[2]; gboolean ret = FALSE; /* * Copy the rest of the line into a null-terminated buffer. */ args = wmem_strndup(wmem_packet_scope(), line, linelen); p = args; for (;;) { /* * Look for a digit. */ while ((c = *p) != '\0' && !g_ascii_isdigit(c)) p++; if (*p == '\0') { /* * We ran out of text without finding anything. */ break; } /* * See if we have six numbers. */ i = sscanf(p, "%d,%d,%d,%d,%d,%d", &ip_address[0], &ip_address[1], &ip_address[2], &ip_address[3], &port[0], &port[1]); if (i == 6) { /* * We have a winner! */ *ftp_port = ((port[0] & 0xFF)<<8) | (port[1] & 0xFF); *ftp_ip = g_htonl((ip_address[0] << 24) | (ip_address[1] <<16) | (ip_address[2] <<8) | ip_address[3]); *pasv_offset = (guint32)(p - args); *ftp_port_len = (port[0] < 10 ? 1 : (port[0] < 100 ? 2 : 3 )) + 1 + (port[1] < 10 ? 1 : (port[1] < 100 ? 2 : 3 )); *ftp_ip_len = (ip_address[0] < 10 ? 1 : (ip_address[0] < 100 ? 2 : 3)) + 1 + (ip_address[1] < 10 ? 1 : (ip_address[1] < 100 ? 2 : 3)) + 1 + (ip_address[2] < 10 ? 1 : (ip_address[2] < 100 ? 2 : 3)) + 1 + (ip_address[3] < 10 ? 1 : (ip_address[3] < 100 ? 2 : 3)); ret = TRUE; break; } /* * Well, that didn't work. Skip the first number we found, * and keep trying. */ while ((c = *p) != '\0' && g_ascii_isdigit(c)) p++; } return ret; }
static void dissect_nstrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *ns_tree = NULL, *flagtree = NULL; proto_item *ti = NULL, *flagitem = NULL; struct nstr_phdr *pnstr = &(pinfo->pseudo_header->nstr); tvbuff_t *next_tvb_eth_client; guint8 offset; wmem_strbuf_t *flags_strbuf = wmem_strbuf_new_label(wmem_packet_scope()); guint8 flagoffset; guint8 src_vmname_len = 0, dst_vmname_len = 0; guint8 variable_ns_len = 0; wmem_strbuf_append(flags_strbuf, "None"); if (pnstr->rec_type == NSPR_HEADER_VERSION205 || pnstr->rec_type == NSPR_HEADER_VERSION300 || pnstr->rec_type == NSPR_HEADER_VERSION206) { src_vmname_len = tvb_get_guint8(tvb,pnstr->src_vmname_len_offset); dst_vmname_len = tvb_get_guint8(tvb,pnstr->dst_vmname_len_offset); variable_ns_len = src_vmname_len + dst_vmname_len; pnstr->eth_offset += variable_ns_len; } ti = proto_tree_add_protocol_format(tree, proto_nstrace, tvb, 0, pnstr->eth_offset, "NetScaler Packet Trace"); ns_tree = proto_item_add_subtree(ti, ett_ns); proto_tree_add_item(ns_tree, hf_ns_dir, tvb, pnstr->dir_offset, pnstr->dir_len, ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_nicno, tvb, pnstr->nicno_offset, pnstr->nicno_len, ENC_LITTLE_ENDIAN); switch (pnstr->rec_type) { case NSPR_HEADER_VERSION300: case NSPR_HEADER_VERSION206: flagoffset = pnstr->ns_activity_offset; flagitem = proto_tree_add_item(ns_tree, hf_ns_activity, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); flagtree = proto_item_add_subtree(flagitem, ett_ns_activity_flags); proto_tree_add_item(flagtree, hf_ns_activity_perf_collection, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_pcb_zombie, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_natpcb_zombie, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_lbstats_sync, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_stats_req, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_snd_cwnd, tvb, (flagoffset + 4), 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_realtime_rtt, tvb, (flagoffset + 8), 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_ts_recent, tvb, (flagoffset + 12), 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_http_abort_tracking_reason, tvb, (pnstr->dst_vmname_len_offset + 1), 1, ENC_LITTLE_ENDIAN); /* fall through to next case */ case NSPR_HEADER_VERSION205: if(src_vmname_len){ proto_tree_add_item(ns_tree,hf_ns_src_vm,tvb,pnstr->data_offset,src_vmname_len,ENC_ASCII|ENC_NA); } if(dst_vmname_len){ proto_tree_add_item(ns_tree,hf_ns_dst_vm,tvb,pnstr->data_offset+src_vmname_len,dst_vmname_len,ENC_ASCII|ENC_NA); } /* fall through to next case */ case NSPR_HEADER_VERSION204: { static const int * clflags[] = { &hf_ns_clflags_res, &hf_ns_clflags_rssh, &hf_ns_clflags_rss, &hf_ns_clflags_dfd, &hf_ns_clflags_fr, &hf_ns_clflags_fp, NULL }; proto_tree_add_item(ns_tree, hf_ns_snode, tvb, pnstr->srcnodeid_offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_dnode, tvb, pnstr->destnodeid_offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_bitmask(ns_tree, tvb, pnstr->clflags_offset, hf_ns_clflags, ett_ns_flags, clflags, ENC_NA); } /* fall through to next case */ case NSPR_HEADER_VERSION203: proto_tree_add_item(ns_tree, hf_ns_coreid, tvb, pnstr->coreid_offset, 2, ENC_LITTLE_ENDIAN); /* fall through to next case */ case NSPR_HEADER_VERSION202: col_add_fstr(pinfo->cinfo, COL_8021Q_VLAN_ID, "%d", tvb_get_letohs(tvb, pnstr->vlantag_offset)); proto_tree_add_item(ns_tree, hf_ns_vlantag, tvb, pnstr->vlantag_offset, 2, ENC_LITTLE_ENDIAN); /* fall through to next case */ case NSPR_HEADER_VERSION201: proto_tree_add_item(ns_tree, hf_ns_pcbdevno, tvb, pnstr->pcb_offset, 4, ENC_LITTLE_ENDIAN); ti = proto_tree_add_item(ns_tree, hf_ns_devno, tvb, pnstr->pcb_offset, 4, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(ti); proto_tree_add_item(ns_tree, hf_ns_l_pcbdevno, tvb, pnstr->l_pcb_offset, 4, ENC_LITTLE_ENDIAN); ti = proto_tree_add_item(ns_tree, hf_ns_devno, tvb, pnstr->l_pcb_offset, 4, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(ti); break; case NSPR_HEADER_VERSION350: { proto_tree *capflagtree = NULL; proto_item *capflagitem = NULL; flagoffset = pnstr->ns_activity_offset; flagitem = proto_tree_add_item(ns_tree, hf_ns_activity, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); flagtree = proto_item_add_subtree(flagitem, ett_ns_activity_flags); proto_tree_add_item(flagtree, hf_ns_activity_perf_collection, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_pcb_zombie, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_natpcb_zombie, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_lbstats_sync, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_stats_req, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); capflagitem = proto_tree_add_item(ns_tree, hf_ns_capflags, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); capflagtree = proto_item_add_subtree(capflagitem, ett_ns_capflags); proto_tree_add_item(capflagtree, hf_ns_capflags_dbg, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(capflagtree, hf_ns_capflags_int, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(capflagtree, hf_ns_capflags_skipnwhdr, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_errorcode, tvb, NSHDR_OFFSET_35(fp_errorcode), sizeof(guint8), ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_app, tvb, NSHDR_OFFSET_35(fp_app), sizeof(guint8), ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_coreid, tvb, pnstr->coreid_offset, 2, ENC_LITTLE_ENDIAN); /* NSPR_HEADER_VERSION202 stuff */ col_add_fstr(pinfo->cinfo, COL_8021Q_VLAN_ID, "%d", tvb_get_letohs(tvb, pnstr->vlantag_offset)); proto_tree_add_item(ns_tree, hf_ns_vlantag, tvb, pnstr->vlantag_offset, 2, ENC_LITTLE_ENDIAN); /* NSPR_HEADER_VERSION201 stuff */ proto_tree_add_item(ns_tree, hf_ns_pcbdevno, tvb, pnstr->pcb_offset, 4, ENC_LITTLE_ENDIAN); ti = proto_tree_add_item(ns_tree, hf_ns_devno, tvb, pnstr->pcb_offset, 4, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(ti); proto_tree_add_item(ns_tree, hf_ns_l_pcbdevno, tvb, pnstr->l_pcb_offset, 4, ENC_LITTLE_ENDIAN); ti = proto_tree_add_item(ns_tree, hf_ns_devno, tvb, pnstr->l_pcb_offset, 4, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(ti); add35records(tvb, pinfo, tree, ns_tree); } break; /* we can return here. break;ing in case some compilers are unhappy */ default: break; } if(pnstr->rec_type != NSPR_HEADER_VERSION350){ /* Dissect as Ethernet */ offset = pnstr->eth_offset; next_tvb_eth_client = tvb_new_subset_remaining(tvb, offset); call_dissector(eth_withoutfcs_handle, next_tvb_eth_client, pinfo, tree); } }
/* * RFC2428 states... * * AF Number Protocol * --------- -------- * 1 Internet Protocol, Version 4 * 2 Internet Protocol, Version 6 * * AF Number Address Format Example * --------- -------------- ------- * 1 dotted decimal 132.235.1.2 * 2 IPv6 string 1080::8:800:200C:417A * representations * defined in * * The following are sample EPRT commands: * EPRT |1|132.235.1.2|6275| * EPRT |2|1080::8:800:200C:417A|5282| * * The first command specifies that the server should use IPv4 to open a * data connection to the host "132.235.1.2" on TCP port 6275. The * second command specifies that the server should use the IPv6 network * protocol and the network address "1080::8:800:200C:417A" to open a * TCP data connection on port 5282. * * ... which means in fact that RFC2428 is capable to handle both, * IPv4 and IPv6 so we have to care about the address family and properly * act depending on it. * */ static gboolean parse_eprt_request(const guchar* line, gint linelen, guint32 *eprt_af, guint32 *eprt_ip, guint16 *eprt_ipv6, guint16 *ftp_port, guint32 *eprt_ip_len, guint32 *ftp_port_len) { gint delimiters_seen = 0; gchar delimiter; gint fieldlen; gchar *field; gint n; gint lastn; char *args, *p; gboolean ret = TRUE; /* line contains the EPRT parameters, we need at least the 4 delimiters */ if (!line || linelen<4) return FALSE; /* Copy the rest of the line into a null-terminated buffer. */ args = wmem_strndup(wmem_packet_scope(), line, linelen); p = args; /* * Handle a NUL being in the line; if there's a NUL in the line, * strlen(args) will terminate at the NUL and will thus return * a value less than linelen. */ if ((gint)strlen(args) < linelen) linelen = (gint)strlen(args); /* * RFC2428 sect. 2 states ... * * The EPRT command keyword MUST be followed by a single space (ASCII * 32). Following the space, a delimiter character (<d>) MUST be * specified. * * ... the preceding <space> is already stripped so we know that the first * character must be the delimiter and has just to be checked to be valid. */ if (!isvalid_rfc2428_delimiter(*p)) return FALSE; /* EPRT command does not follow a vaild delimiter; * malformed EPRT command - immediate escape */ delimiter = *p; /* Validate that the delimiter occurs 4 times in the string */ for (n = 0; n < linelen; n++) { if (*(p+n) == delimiter) delimiters_seen++; } if (delimiters_seen != 4) return FALSE; /* delimiter doesn't occur 4 times * probably no EPRT request - immediate escape */ /* we know that the first character is a delimiter... */ delimiters_seen = 1; lastn = 0; /* ... so we can start searching from the 2nd onwards */ for (n=1; n < linelen; n++) { if (*(p+n) != delimiter) continue; /* we found a delimiter */ delimiters_seen++; fieldlen = n - lastn - 1; if (fieldlen<=0) return FALSE; /* all fields must have data in them */ field = p + lastn + 1; if (delimiters_seen == 2) { /* end of address family field */ gchar *af_str; af_str = wmem_strndup(wmem_packet_scope(), field, fieldlen); if (!ws_strtou32(af_str, NULL, eprt_af)) return FALSE; } else if (delimiters_seen == 3) {/* end of IP address field */ gchar *ip_str; ip_str = wmem_strndup(wmem_packet_scope(), field, fieldlen); if (*eprt_af == EPRT_AF_IPv4) { if (str_to_ip(ip_str, eprt_ip)) ret = TRUE; else ret = FALSE; } else if (*eprt_af == EPRT_AF_IPv6) { if (str_to_ip6(ip_str, eprt_ipv6)) ret = TRUE; else ret = FALSE; } else return FALSE; /* invalid/unknown address family */ *eprt_ip_len = fieldlen; } else if (delimiters_seen == 4) {/* end of port field */ gchar *pt_str; pt_str = wmem_strndup(wmem_packet_scope(), field, fieldlen); if (!ws_strtou16(pt_str, NULL, ftp_port)) return FALSE; *ftp_port_len = fieldlen; } lastn = n; } return ret; }
static void dissect_epmd_request(packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *tree) { guint8 type; guint16 name_length = 0; const gchar *name = NULL; proto_tree_add_item(tree, hf_epmd_len, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; type = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_epmd_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, VALS(message_types), "unknown (0x%02X)")); switch (type) { case EPMD_ALIVE2_REQ: proto_tree_add_item(tree, hf_epmd_port_no, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_epmd_node_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(tree, hf_epmd_protocol, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(tree, hf_epmd_dist_high, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_epmd_dist_low, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; name_length = tvb_get_ntohs(tvb, offset); proto_tree_add_item(tree, hf_epmd_name_len, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_epmd_name, tvb, offset + 2, name_length, ENC_ASCII|ENC_NA); name = tvb_get_string(wmem_packet_scope(), tvb, offset + 2, name_length); offset += 2 + name_length; if (tvb_length_remaining(tvb, offset) >= 2) { guint16 elen=0; elen = tvb_get_ntohs(tvb, offset); proto_tree_add_item(tree, hf_epmd_elen, tvb, offset, 2, ENC_BIG_ENDIAN); if (elen > 0) proto_tree_add_item(tree, hf_epmd_edata, tvb, offset + 2, elen, ENC_NA); /*offset += 2 + elen;*/ } break; case EPMD_PORT_REQ: case EPMD_PORT2_REQ: name_length = tvb_length_remaining(tvb, offset); proto_tree_add_item(tree, hf_epmd_name, tvb, offset, name_length, ENC_ASCII|ENC_NA); name = tvb_get_string(wmem_packet_scope(), tvb, offset, name_length); break; case EPMD_ALIVE_REQ: proto_tree_add_item(tree, hf_epmd_port_no, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; name_length = tvb_length_remaining(tvb, offset); proto_tree_add_item(tree, hf_epmd_name, tvb, offset, name_length, ENC_ASCII|ENC_NA); name = tvb_get_string(wmem_packet_scope(), tvb, offset, name_length); break; case EPMD_NAMES_REQ: break; } if (name) { col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name); } }
/* * RFC2428 states .... * * The first two fields contained in the parenthesis MUST be blank. The * third field MUST be the string representation of the TCP port number * on which the server is listening for a data connection. * * The network protocol used by the data connection will be the same network * protocol used by the control connection. In addition, the network * address used to establish the data connection will be the same * network address used for the control connection. * * An example response string follows: * * Entering Extended Passive Mode (|||6446|) * * ... which in fact means that again both address families IPv4 and IPv6 * are supported. But gladly it's not necessary to parse because it doesn't * occur in EPSV responses. We can leverage ftp_ip_address which is * protocol independent and already set. * */ static gboolean parse_extended_pasv_response(const guchar *line, gint linelen, guint16 *ftp_port, guint *pasv_offset, guint *ftp_port_len) { gint n; gchar *args; gchar *p; gchar *e; guchar c; gboolean ret = FALSE; gboolean delimiters_seen = FALSE; /* * Copy the rest of the line into a null-terminated buffer. */ args = wmem_strndup(wmem_packet_scope(), line, linelen); p = args; /* * Look for ( <d> <d> <d> (Try to cope with '(' in description) */ for (; !delimiters_seen;) { guchar delimiter = '\0'; while ((c = *p) != '\0' && (c != '(')) p++; if (*p == '\0') { return FALSE; } /* Skip '(' */ p++; /* Make sure same delimiter is used 3 times */ for (n=0; n<3; n++) { if ((c = *p) != '\0') { if (delimiter == '\0' && isvalid_rfc2428_delimiter(c)) { delimiter = c; } if (c != delimiter) { break; } p++; } else { break; } } delimiters_seen = TRUE; } /* * Should now be at digits. */ if (*p != '\0') { const gchar* endptr; gboolean port_valid; /* * We didn't run out of text without finding anything. */ port_valid = ws_strtou16(p, &endptr, ftp_port); /* the conversion returned false, but the converted value could be valid instead, check it out */ if (!port_valid && *endptr == '|') port_valid = TRUE; if (port_valid) { *pasv_offset = (guint32)(p - args); ret = TRUE; /* get port string length */ if ((e=strchr(p,')')) == NULL) { ret = FALSE; } else { *ftp_port_len = (guint)(--e - p); } } } return ret; }
static void dissect_fip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint op; guint sub; guint rlen; proto_item *ti; proto_item *item; proto_tree *fip_tree; proto_tree *subtree; guint dtype; guint dlen; guint desc_offset; guint val; tvbuff_t *desc_tvb; const char *info; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FIP"); col_clear(pinfo->cinfo, COL_INFO); if (!tvb_bytes_exist(tvb, 0, FIP_HEADER_LEN)) { col_set_str(pinfo->cinfo, COL_INFO, "[packet too short]"); if (tree) proto_tree_add_protocol_format(tree, proto_fip, tvb, 0, -1, "FIP [packet too short]"); return; } op = tvb_get_ntohs(tvb, 2); sub = tvb_get_guint8(tvb, 5); switch (op) { case FIP_OP_DISC: info = val_to_str(sub, fip_disc_subcodes, "Discovery 0x%x"); break; case FIP_OP_LS: info = val_to_str(sub, fip_ls_subcodes, "Link Service 0x%x"); break; case FIP_OP_CTRL: info = val_to_str(sub, fip_ctrl_subcodes, "Control 0x%x"); break; case FIP_OP_VLAN: info = val_to_str(sub, fip_vlan_subcodes, "VLAN 0x%x"); break; case FIP_OP_VN2VN: info = val_to_str(sub, fip_vn2vn_subcodes, "VN2VN 0x%x"); break; default: info = val_to_str(op, fip_opcodes, "Unknown op 0x%x"); break; } col_add_str(pinfo->cinfo, COL_INFO, info); rlen = tvb_get_ntohs(tvb, 6); ti = proto_tree_add_protocol_format(tree, proto_fip, tvb, 0, FIP_HEADER_LEN + rlen * FIP_BPW, "FIP %s", info); fip_tree = proto_item_add_subtree(ti, ett_fip); proto_tree_add_item(fip_tree, hf_fip_ver, tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(fip_tree, hf_fip_reserved12, tvb, 0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(fip_tree, hf_fip_op, tvb, 2, 2, ENC_BIG_ENDIAN); proto_tree_add_item(fip_tree, hf_fip_reserved8, tvb, 4, 1, ENC_NA); switch (op) { case FIP_OP_DISC: proto_tree_add_item(fip_tree, hf_fip_disc_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; case FIP_OP_LS: proto_tree_add_item(fip_tree, hf_fip_ls_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; case FIP_OP_CTRL: proto_tree_add_item(fip_tree, hf_fip_ctrl_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; case FIP_OP_VLAN: proto_tree_add_item(fip_tree, hf_fip_vlan_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; case FIP_OP_VN2VN: proto_tree_add_item(fip_tree, hf_fip_vn2vn_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; default: proto_tree_add_item(fip_tree, hf_fip_hex_subcode, tvb, 5, 1, ENC_BIG_ENDIAN); break; } proto_tree_add_item(fip_tree, hf_fip_dlen, tvb, 6, 2, ENC_BIG_ENDIAN); proto_tree_add_bitmask(fip_tree, tvb, 8, hf_fip_flags, ett_fip_flags, hf_fip_flags_fields, ENC_BIG_ENDIAN); desc_offset = FIP_HEADER_LEN; rlen *= FIP_BPW; proto_tree_add_bytes_format(fip_tree, hf_fip_descriptors, tvb, desc_offset, rlen, NULL, "Descriptors"); while ((rlen > 0) && tvb_bytes_exist(tvb, desc_offset, 2)) { dlen = tvb_get_guint8(tvb, desc_offset + 1) * FIP_BPW; if (!dlen) { proto_tree_add_expert(fip_tree, pinfo, &ei_fip_descriptors, tvb, desc_offset, -1); break; } if (!tvb_bytes_exist(tvb, desc_offset, dlen) || dlen > rlen) { break; } desc_tvb = tvb_new_subset(tvb, desc_offset, dlen, -1); dtype = tvb_get_guint8(desc_tvb, 0); desc_offset += dlen; rlen -= dlen; switch (dtype) { case FIP_DT_PRI: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_pri, &item); proto_tree_add_item(subtree, hf_fip_desc_pri, desc_tvb, 3, 1, ENC_BIG_ENDIAN); proto_item_append_text(item, "%u", tvb_get_guint8(desc_tvb, 3)); break; case FIP_DT_MAC: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_mac, &item); proto_tree_add_item(subtree, hf_fip_desc_mac, desc_tvb, 2, 6, ENC_NA); proto_item_append_text(item, "%s", tvb_bytes_to_str_punct(wmem_packet_scope(), desc_tvb, 2, 6, ':')); break; case FIP_DT_MAP_OUI: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_map, &item); proto_tree_add_item(subtree, hf_fip_desc_map, desc_tvb, 5, 3, ENC_NA); proto_item_append_text(item, "%s", tvb_fc_to_str(desc_tvb, 5)); break; case FIP_DT_NAME: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_name, &item); proto_tree_add_item(subtree, hf_fip_desc_name, desc_tvb, 4, 8, ENC_NA); proto_item_append_text(item, "%s", tvb_fcwwn_to_str(desc_tvb, 4)); break; case FIP_DT_FAB: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fab, &item); proto_tree_add_item(subtree, hf_fip_desc_fab_vfid, desc_tvb, 2, 2, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_fip_desc_fab_map, desc_tvb, 5, 3, ENC_NA); proto_tree_add_item(subtree, hf_fip_desc_fab_name, desc_tvb, 8, 8, ENC_NA); proto_item_append_text(item, "%s", tvb_fcwwn_to_str(desc_tvb, 8)); break; case FIP_DT_FCOE_SIZE: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_mdl, &item); proto_tree_add_item(subtree, hf_fip_desc_fcoe_size, desc_tvb, 2, 2, ENC_BIG_ENDIAN); proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2)); break; case FIP_DT_FLOGI: case FIP_DT_FDISC: case FIP_DT_LOGO: case FIP_DT_ELP: { tvbuff_t *ls_tvb; fc_data_t fc_data = {ETHERTYPE_FIP, 0}; subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_caps, &item); ls_tvb = tvb_new_subset(desc_tvb, 4, dlen - 4, -1); call_dissector_with_data(fc_handle, ls_tvb, pinfo, subtree, &fc_data); proto_item_append_text(item, "%u bytes", dlen - 4); } break; case FIP_DT_VN: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vn, &item); proto_tree_add_item(subtree, hf_fip_desc_vn_mac, desc_tvb, 2, 6, ENC_NA); proto_tree_add_item(subtree, hf_fip_desc_vn_fid, desc_tvb, 9, 3, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_fip_desc_vn_wwpn, desc_tvb, 12, 8, ENC_NA); proto_item_append_text(item, "MAC %s FC_ID %6.6x", tvb_bytes_to_str_punct(wmem_packet_scope(), desc_tvb, 2, 6, ':'), tvb_get_ntoh24(desc_tvb, 9)); break; case FIP_DT_FKA: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fka, &item); val = tvb_get_ntohl(desc_tvb, 4); proto_tree_add_uint_format_value(subtree, hf_fip_desc_fka, desc_tvb, 4, 4, val, "%u ms", val); proto_item_append_text(item, "%u ms", val); break; case FIP_DT_VEND: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vend, &item); proto_tree_add_item(subtree, hf_fip_desc_vend, desc_tvb, 4, 8, ENC_NA); if (tvb_bytes_exist(desc_tvb, 9, -1)) { proto_tree_add_item(subtree, hf_fip_desc_vend_data, desc_tvb, 9, -1, ENC_NA); } break; case FIP_DT_VLAN: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vlan, &item); proto_tree_add_item(subtree, hf_fip_desc_vlan, desc_tvb, 2, 2, ENC_BIG_ENDIAN); proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2)); break; case FIP_DT_FC4F: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fc4f, &item); fip_desc_fc4f(desc_tvb, subtree, item); break; default: subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_unk, &item); proto_tree_add_item(subtree, hf_fip_desc_unk, desc_tvb, 2, -1, ENC_NA); break; } } }
static void client_display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, socks_hash_entry_t *hash_info, sock_state_t* state_info) { /* Display the protocol tree for the version. This routine uses the */ /* stored conversation information to decide what to do with the row. */ /* Per packet information would have been better to do this, but we */ /* didn't have that when I wrote this. And I didn't expect this to get */ /* so messy. */ unsigned int i; const char *AuthMethodStr; sock_state_t new_state_info; /* Either there is an error, or we're done with the state machine (so there's nothing to display) */ if (state_info == NULL) return; proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (state_info->client == clientStart) { proto_tree *AuthTree; proto_item *ti; guint8 num_auth_methods, auth; ti = proto_tree_add_text( tree, tvb, offset, -1, "Client Authentication Methods"); AuthTree = proto_item_add_subtree(ti, ett_socks_auth); num_auth_methods = tvb_get_guint8(tvb, offset); proto_item_set_len(ti, num_auth_methods+1); proto_tree_add_item( AuthTree, hf_client_auth_method_count, tvb, offset, 1, ENC_NA); offset += 1; for( i = 0; i < num_auth_methods; ++i) { auth = tvb_get_guint8( tvb, offset); AuthMethodStr = get_auth_method_name(auth); proto_tree_add_uint_format(AuthTree, hf_client_auth_method, tvb, offset, 1, auth, "Method[%u]: %u (%s)", i, auth, AuthMethodStr); offset += 1; } if ((num_auth_methods == 1) && (tvb_bytes_exist(tvb, offset + 2, 1)) && (tvb_get_guint8(tvb, offset + 2) == 0) && (tvb_reported_length_remaining(tvb, offset + 2 + num_auth_methods) > 0)) { new_state_info.client = clientV5Command; client_display_socks_v5(tvb, offset, pinfo, tree, hash_info, &new_state_info); } } else if (state_info->client == clientV5Command) { proto_tree_add_item( tree, hf_socks_cmd, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item( tree, hf_socks_reserved, tvb, offset, 1, ENC_NA); offset += 1; offset = display_address(tvb, offset, tree); proto_tree_add_item( tree, hf_client_port, tvb, offset, 2, ENC_BIG_ENDIAN); } else if ((state_info->client == clientWaitForAuthReply) && (state_info->server == serverInitReply)) { guint16 len; gchar* str; switch(hash_info->authentication_method) { case NO_AUTHENTICATION: break; case USER_NAME_AUTHENTICATION: /* process user name */ len = tvb_get_guint8(tvb, offset); str = tvb_get_string(wmem_packet_scope(), tvb, offset+1, len); proto_tree_add_string(tree, hf_socks_username, tvb, offset, len+1, str); offset += (len+1); len = tvb_get_guint8(tvb, offset); str = tvb_get_string(wmem_packet_scope(), tvb, offset+1, len); proto_tree_add_string(tree, hf_socks_password, tvb, offset, len+1, str); /* offset += (len+1); */ break; case GSS_API_AUTHENTICATION: proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, ENC_BIG_ENDIAN); len = tvb_get_ntohs(tvb, offset+1); if (len > 0) proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, ENC_NA); break; default: break; } } }
/* * Unfold and clean up a MIME-like header, and process LWS as follows: * o Preserves LWS in quoted text * o Remove LWS before and after a separator * o Remove trailing LWS * o Replace other LWS with a single space * Set value to the start of the value * Return the cleaned-up RFC2822 header (buffer must be freed). */ static char * unfold_and_compact_mime_header(const char *lines, gint *first_colon_offset) { const char *p = lines; char c; char *ret, *q; char sep_seen = 0; /* Did we see a separator ":;," */ char lws = FALSE; /* Did we see LWS (incl. folding) */ gint colon = -1; if (! lines) return NULL; c = *p; ret = (char *)wmem_alloc(wmem_packet_scope(), strlen(lines) + 1); q = ret; while (c) { if (c == ':') { lws = FALSE; /* Prevent leading LWS from showing up */ if (colon == -1) {/* First colon */ colon = (gint) (q - ret); } *(q++) = sep_seen = c; p++; } else if (c == ';' || c == ',' || c == '=') { lws = FALSE; /* Prevent leading LWS from showing up */ *(q++) = sep_seen = c; p++; } else if (c == ' ' || c == '\t') { lws = TRUE; p++; } else if (c == '\n') { lws = FALSE; /* Skip trailing LWS */ if ((c = *(p+1))) { if (c == ' ' || c == '\t') { /* Header unfolding */ lws = TRUE; p += 2; } else { *q = c = 0; /* Stop */ } } } else if (c == '\r') { lws = FALSE; if ((c = *(p+1))) { if (c == '\n') { if ((c = *(p+2))) { if (c == ' ' || c == '\t') { /* Header unfolding */ lws = TRUE; p += 3; } else { *q = c = 0; /* Stop */ } } } else if (c == ' ' || c == '\t') { /* Header unfolding */ lws = TRUE; p += 2; } else { *q = c = 0; /* Stop */ } } } else if (c == '"') { /* Start of quoted-string */ lws = FALSE; *(q++) = c; while (c) { c = *(q++) = *(++p); if (c == '"') { p++; /* Skip closing quote */ break; } } /* if already zero terminated now, rewind one char to avoid an "off by one" */ if(c == 0) { q--; } } else { /* Regular character */ if (sep_seen) { sep_seen = 0; } else { if (lws) { *(q++) = ' '; } } lws = FALSE; *(q++) = c; p++; /* OK */ } if (c) { c = *p; } } *q = 0; *first_colon_offset = colon; return (ret); }
static void dissect_gsm_cell_broadcast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 sms_encoding, total_pages, current_page; guint32 offset = 0; guint len, text_len; guint32 msg_key; proto_item *cbs_page_item = NULL; proto_tree *cbs_page_tree = NULL; guint16 serial_number, message_id; tvbuff_t *cbs_page_tvb = NULL; tvbuff_t *cbs_msg_tvb = NULL; fragment_head * frag_data = NULL; len = tvb_length(tvb); col_append_str(pinfo->cinfo, COL_PROTOCOL, " Cell Broadcast"); col_append_str(pinfo->cinfo, COL_INFO, " (CBS Page)"); cbs_page_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, tvb, 0, len, "GSM Cell Broadcast"); cbs_page_tree = proto_item_add_subtree(cbs_page_item, ett_gsm_cbs_page); serial_number = tvb_get_ntohs(tvb, offset); offset = dissect_cbs_serial_number(tvb, cbs_page_tree, offset); message_id = tvb_get_ntohs(tvb, offset); offset = dissect_cbs_message_identifier(tvb, cbs_page_tree, offset); sms_encoding = dissect_cbs_data_coding_scheme(tvb, pinfo, cbs_page_tree, offset++); total_pages = tvb_get_guint8(tvb, offset); current_page = (total_pages & 0xF0) >> 4; total_pages &= 0x0F; proto_tree_add_item(cbs_page_tree, hf_gsm_cbs_current_page, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(cbs_page_tree, hf_gsm_cbs_total_pages, tvb, offset++, 1, ENC_BIG_ENDIAN); cbs_page_tvb = dissect_cbs_data(sms_encoding, tvb, cbs_page_tree, pinfo, offset ); if (cbs_page_tvb != NULL) { text_len = tvb_length(cbs_page_tvb); while (text_len && (tvb_get_guint8(cbs_page_tvb, text_len-1) == '\r')) { text_len--; } if (tree != NULL) { proto_tree *cbs_page_subtree = proto_tree_add_subtree(cbs_page_tree, tvb, offset, -1, ett_gsm_cbs_page_content, NULL, "Cell Broadcast Page Contents"); len = tvb_length(cbs_page_tvb); proto_tree_add_string(cbs_page_subtree, hf_gsm_cbs_page_content, cbs_page_tvb, 0, text_len, tvb_get_string_enc(wmem_packet_scope(), cbs_page_tvb, 0, text_len, ENC_ASCII)); len -= text_len; if (len) { proto_tree_add_string(cbs_page_subtree, hf_gsm_cbs_page_content_padding, cbs_page_tvb, text_len, len, tvb_get_string_enc(wmem_packet_scope(), cbs_page_tvb, text_len, len, ENC_ASCII)); } } if (text_len) { cbs_page_tvb = tvb_new_subset_length(cbs_page_tvb, 0, text_len); if (total_pages == 1) { /* no need for reassembly */ cbs_msg_tvb = cbs_page_tvb; } else { /* now we have a complete page, try to concatenate the full message */ /* we can use the serial number and message ID as keys, as they are the same for all pages of a message */ msg_key = (serial_number << 16) + message_id; frag_data = fragment_add_seq_check(&gsm_cbs_reassembly_table, cbs_page_tvb, 0, pinfo, msg_key, NULL, (current_page -1), text_len, (current_page!=total_pages)); cbs_msg_tvb = process_reassembled_data(cbs_page_tvb, 0, pinfo, "Reassembled Cell Broadcast message", frag_data, &gsm_page_items, NULL, cbs_page_tree); } } } if (cbs_msg_tvb != NULL) { proto_item *cbs_msg_item = NULL; proto_tree *cbs_msg_tree = NULL; len = tvb_length(cbs_msg_tvb); col_append_str(pinfo->cinfo, COL_INFO, " (CBS Message)"); cbs_msg_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, cbs_msg_tvb, 0, len, "GSM Cell Broadcast Message"); cbs_msg_tree = proto_item_add_subtree(cbs_msg_item, ett_cbs_msg); proto_tree_add_string(cbs_msg_tree, hf_gsm_cbs_message_content, cbs_msg_tvb, 0, len, tvb_get_string_enc(wmem_packet_scope(), cbs_msg_tvb, 0, len, ENC_ASCII)); } }
static int get_form_key_value(tvbuff_t *tvb, char **ptr, int offset, char stop) { const int orig_offset = offset; char *tmp; int len; len = 0; while (tvb_reported_length_remaining(tvb, offset) > 0) { guint8 ch; ch = tvb_get_guint8(tvb, offset); if (!ch) return -1; if (ch == stop) break; if (ch == '%') { offset++; ch = tvb_get_guint8(tvb, offset); if (ws_xton(ch) == -1) return -1; offset++; ch = tvb_get_guint8(tvb, offset); if (ws_xton(ch) == -1) return -1; } len++; offset++; } *ptr = tmp = (char*)wmem_alloc(wmem_packet_scope(), len + 1); tmp[len] = '\0'; len = 0; offset = orig_offset; while (tvb_reported_length_remaining(tvb, offset) > 0) { guint8 ch; ch = tvb_get_guint8(tvb, offset); if (!ch) return -1; if (ch == stop) break; if (ch == '%') { guint8 ch1, ch2; offset++; ch1 = tvb_get_guint8(tvb, offset); offset++; ch2 = tvb_get_guint8(tvb, offset); tmp[len] = ws_xton(ch1) << 4 | ws_xton(ch2); } else if (ch == '+') tmp[len] = ' '; else tmp[len] = ch; len++; offset++; } return offset; }
static void dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *prism_tree = NULL, *prism_did_tree = NULL; proto_item *ti = NULL, *ti_did = NULL; tvbuff_t *next_tvb; int offset; guint32 msgcode, msglen, did; guint byte_order; guint16 status; guint8 *devname_p; offset = 0; did = 0; /* handle the AVS header */ msgcode = tvb_get_ntohl(tvb, offset); if ((msgcode == WLANCAP_MAGIC_COOKIE_V1) || (msgcode == WLANCAP_MAGIC_COOKIE_V2)) { call_dissector(wlancap_handle, tvb, pinfo, tree); return; } /* * If we don't see a valid message type, assume the Prism or AVS * header was omitted and just hand off to the 802.11 dissector; * at least one capture has AVS headers on some packets and no * radio headers on others (incoming vs. outgoing?). * * Check for both byte orders and use that to determine * the byte order of the fields in the Prism header. */ if ((msgcode == PRISM_TYPE1_MSGCODE) || (msgcode == PRISM_TYPE2_MSGCODE)) { /* big-endian fetch matched */ byte_order = ENC_BIG_ENDIAN; } else if (((msgcode = tvb_get_letohl(tvb, offset)) == PRISM_TYPE1_MSGCODE) || (msgcode == PRISM_TYPE2_MSGCODE)) { /* little-endian fetch matched */ byte_order = ENC_LITTLE_ENDIAN; } else { /* neither matched - try it as just 802.11 with no Prism header */ call_dissector(ieee80211_handle, tvb, pinfo, tree); return; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism"); col_clear(pinfo->cinfo, COL_INFO); if(tree) { ti = proto_tree_add_item(tree, proto_prism, tvb, 0, 144, ENC_NA); prism_tree = proto_item_add_subtree(ti, ett_prism); } /* Message Code */ if(tree) { proto_tree_add_item(prism_tree, hf_ieee80211_prism_msgcode, tvb, offset, 4, byte_order); } msgcode = tvb_get_enctohl(tvb, offset, byte_order); offset += 4; /* Message Length */ if(tree) { proto_tree_add_item(prism_tree, hf_ieee80211_prism_msglen, tvb, offset, 4, byte_order); } msglen = tvb_get_enctohl(tvb, offset, byte_order); offset += 4; /* Device Name */ if(tree) { proto_tree_add_item(prism_tree, hf_ieee80211_prism_devname, tvb, offset, 16, ENC_ASCII|ENC_NA); } devname_p = tvb_get_string(wmem_packet_scope(), tvb, offset, 16); offset += 16; col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %s, Message 0x%x, Length %d", devname_p, msgcode, msglen); while(offset < PRISM_HEADER_LENGTH) { /* DID */ if(tree) { ti_did = proto_tree_add_item(prism_tree, hf_ieee80211_prism_did, tvb, offset, 12, ENC_NA); prism_did_tree = proto_item_add_subtree(ti_did, ett_prism_did); proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_type, tvb, offset, 4, byte_order); did = tvb_get_enctohl(tvb, offset, byte_order); proto_item_append_text(ti_did, " %s", val_to_str(did, prism_did_vals, "Unknown %x") ); } offset += 4; /* Status */ status = tvb_get_enctohs(tvb, offset, byte_order); if(tree) { proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_status, tvb, offset, 2, byte_order); } offset += 2; /* Length */ if(tree) { proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_length, tvb, offset, 2, byte_order); } offset += 2; /* Data, if present... */ if (status == 0) { switch(did){ case PRISM_TYPE1_HOSTTIME: case PRISM_TYPE2_HOSTTIME: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_hosttime, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " %d", tvb_get_enctohl(tvb, offset, byte_order) ); } break; case PRISM_TYPE1_MACTIME: case PRISM_TYPE2_MACTIME: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_mactime, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " %d", tvb_get_enctohl(tvb, offset, byte_order) ); } break; case PRISM_TYPE1_CHANNEL: case PRISM_TYPE2_CHANNEL: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_channel, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " %d", tvb_get_enctohl(tvb, offset, byte_order) ); } col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", tvb_get_enctohl(tvb, offset, byte_order)); break; case PRISM_TYPE1_RSSI: case PRISM_TYPE2_RSSI: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rssi, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " 0x%x", tvb_get_enctohl(tvb, offset, byte_order) ); } col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", tvb_get_enctohl(tvb, offset, byte_order)); break; case PRISM_TYPE1_SQ: case PRISM_TYPE2_SQ: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sq, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " 0x%x", tvb_get_enctohl(tvb, offset, byte_order) ); } break; case PRISM_TYPE1_SIGNAL: case PRISM_TYPE2_SIGNAL: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_signal, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " 0x%x", tvb_get_enctohl(tvb, offset, byte_order) ); } break; case PRISM_TYPE1_NOISE: case PRISM_TYPE2_NOISE: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_noise, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " 0x%x", tvb_get_enctohl(tvb, offset, byte_order) ); } break; case PRISM_TYPE1_RATE: case PRISM_TYPE2_RATE: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rate, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " %s Mb/s", prism_rate_return(tvb_get_enctohl(tvb, offset, byte_order)) ); } col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%s", prism_rate_return(tvb_get_enctohl(tvb, offset, byte_order)) ); break; case PRISM_TYPE1_ISTX: case PRISM_TYPE2_ISTX: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_istx, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " 0x%x", tvb_get_enctohl(tvb, offset, byte_order) ); } break; case PRISM_TYPE1_FRMLEN: case PRISM_TYPE2_FRMLEN: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_frmlen, tvb, offset, 4, byte_order); proto_item_append_text(ti_did, " %d", tvb_get_enctohl(tvb, offset, byte_order)); } break; default: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_unknown, tvb, offset, 4, byte_order); } break; } } offset += 4; } /* dissect the 802.11 header next */ next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(ieee80211_handle, next_tvb, pinfo, tree); }
static gint dissect_lower_address(proto_item *ti_arg, gint ett_arg, tvbuff_t *tvb, gint arg_offset, int hf_endian, int hf_ip, int hf_port, int hf_suff) { gint offset = arg_offset; guint8 len1, len2; guint8 *suffix; proto_tree *tree; proto_item *ti; tree = proto_item_add_subtree(ti_arg, ett_arg); /* * Coding of address: * ELCOM-90 TRA3825.02 User Element conventions, p. 5-2 and Appendix G */ len1 = tvb_get_guint8(tvb, offset); if (tvb_captured_length_remaining(tvb, offset+len1+1) <= 0) return offset; len2 = tvb_get_guint8(tvb, offset+len1+1); if (tvb_reported_length_remaining(tvb, offset+len1+len2+2) <= 0) return offset; if ((len1 != LOWADR_LEN) || (len2 != SUFFIX_LEN)) { proto_item_append_text(tree, " Invalid structure"); return offset; } /* Show pre stuff */ if (0x82 != tvb_get_guint8(tvb, offset+1)) { proto_item_append_text(tree, " Not IPV4 address"); return offset; } offset += 2; /* endian */ proto_tree_add_item(tree, hf_endian, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* port */ proto_tree_add_item(tree, hf_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* ip-addr */ proto_tree_add_item(tree, hf_ip, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; offset += 8; /* skip the zero bytes */ /* SUFFIX */ suffix = tvb_get_string_enc(wmem_packet_scope(), tvb, offset+1, len2, ENC_ASCII); /* hf_suff FIELDTYPE must be FT_UINT_STRING */ ti = proto_tree_add_item(tree, hf_suff, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN); offset += len2+1; if (!(suffix[0] == 'A' || suffix[0] == 'B')) { proto_item_append_text(ti, " (invalid)"); return offset; } proto_item_append_text(ti, " (%s)", val_to_str_const(suffix[1], suffix_vals, "<<-- WHAT?") ); return offset; }
/* XXX - "packet comment" is passed into dissector as data, but currently doesn't have a use */ static int dissect_file_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data) { proto_item *volatile ti = NULL; guint cap_len = 0, frame_len = 0; proto_tree *volatile fh_tree = NULL; proto_tree *volatile tree; proto_item *item; const gchar *cap_plurality, *frame_plurality; const color_filter_t *color_filter; file_data_t *file_data = (file_data_t*)data; tree=parent_tree; pinfo->current_proto = "File"; /* if FILE is not referenced from any filters we don't need to worry about generating any tree items. */ if(!proto_field_is_referenced(tree, proto_file)) { tree=NULL; } else { /* 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_file, tvb, 0, -1, "File record %u: %u byte%s", pinfo->num, frame_len, frame_plurality); proto_item_append_text(ti, ", %u byte%s", cap_len, cap_plurality); fh_tree = proto_item_add_subtree(ti, ett_file); proto_tree_add_int(fh_tree, hf_file_ftap_encap, tvb, 0, 0, pinfo->pkt_encap); proto_tree_add_uint(fh_tree, hf_file_record_number, tvb, 0, 0, pinfo->num); proto_tree_add_uint_format(fh_tree, hf_file_record_len, tvb, 0, 0, frame_len, "Record Length: %u byte%s (%u bits)", frame_len, frame_plurality, frame_len * 8); ti = proto_tree_add_boolean(fh_tree, hf_file_marked, tvb, 0, 0,pinfo->fd->flags.marked); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_boolean(fh_tree, hf_file_ignored, tvb, 0, 0,pinfo->fd->flags.ignored); PROTO_ITEM_SET_GENERATED(ti); if(pinfo->fd->pfd != 0){ proto_item *ppd_item; guint num_entries = g_slist_length(pinfo->fd->pfd); guint i; ppd_item = proto_tree_add_uint(fh_tree, hf_file_num_p_prot_data, tvb, 0, 0, num_entries); PROTO_ITEM_SET_GENERATED(ppd_item); for(i=0; i<num_entries; i++){ gchar* str = p_get_proto_name_and_key(wmem_file_scope(), pinfo, i); proto_tree_add_string_format(fh_tree, hf_file_proto_name_and_key, tvb, 0, 0, str, "%s", str); } } #if 0 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); } #endif } 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_file_ignored, tvb, 0, -1, TRUE, "This record 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 if (!dissector_try_uint(file_encap_dissector_table, pinfo->pkt_encap, tvb, pinfo, parent_tree)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN"); col_add_fstr(pinfo->cinfo, COL_INFO, "FTAP_ENCAP = %d", pinfo->pkt_encap); call_data_dissector(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; if(proto_field_is_referenced(tree, hf_file_protocols)) { wmem_strbuf_t *val = wmem_strbuf_new(wmem_packet_scope(), ""); 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); } ti = proto_tree_add_string(fh_tree, hf_file_protocols, tvb, 0, 0, wmem_strbuf_get_str(val)); PROTO_ITEM_SET_GENERATED(ti); } /* 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(file_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) { pinfo->fd->color_filter = color_filter; item = proto_tree_add_string(fh_tree, hf_file_color_filter_name, tvb, 0, 0, color_filter->filter_name); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_string(fh_tree, hf_file_color_filter_text, tvb, 0, 0, color_filter->filter_text); PROTO_ITEM_SET_GENERATED(item); } tap_queue_packet(file_tap, pinfo, NULL); if (pinfo->frame_end_routines) { g_slist_foreach(pinfo->frame_end_routines, &call_file_record_end_routine, NULL); g_slist_free(pinfo->frame_end_routines); pinfo->frame_end_routines = NULL; } return tvb_captured_length(tvb); }