static void wmem_test_allocator_jumbo(wmem_allocator_type_t type, wmem_verify_func verify) { wmem_allocator_t *allocator; char *ptr, *ptr1; allocator = wmem_allocator_force_new(type); ptr = (char*)wmem_alloc0(allocator, 4*1024*1024); wmem_free(allocator, ptr); wmem_gc(allocator); ptr = (char*)wmem_alloc0(allocator, 4*1024*1024); if (verify) (*verify)(allocator); wmem_free(allocator, ptr); wmem_gc(allocator); if (verify) (*verify)(allocator); ptr = (char *)wmem_alloc0(allocator, 10*1024*1024); ptr1 = (char *)wmem_alloc0(allocator, 13*1024*1024); ptr1 = (char *)wmem_realloc(allocator, ptr1, 10*1024*1024); memset(ptr1, 0, 10*1024*1024); ptr = (char *)wmem_realloc(allocator, ptr, 13*1024*1024); memset(ptr, 0, 13*1024*1024); if (verify) (*verify)(allocator); wmem_gc(allocator); if (verify) (*verify)(allocator); wmem_free(allocator, ptr1); if (verify) (*verify)(allocator); wmem_free_all(allocator); wmem_gc(allocator); if (verify) (*verify)(allocator); wmem_destroy_allocator(allocator); }
static void wmem_test_allocator_det(wmem_allocator_t *allocator, wmem_verify_func verify, guint len) { int i; char *ptrs[MAX_SIMULTANEOUS_ALLOCS]; /* we use wmem_alloc0 in part because it tests slightly more code, but * primarily so that if the allocator doesn't give us enough memory or * gives us memory that includes its own metadata, we write to it and * things go wrong, causing the tests to fail */ for (i=0; i<MAX_SIMULTANEOUS_ALLOCS; i++) { ptrs[i] = (char *)wmem_alloc0(allocator, len); } for (i=MAX_SIMULTANEOUS_ALLOCS-1; i>=0; i--) { /* no wmem_realloc0 so just use memset manually */ ptrs[i] = (char *)wmem_realloc(allocator, ptrs[i], 4*len); memset(ptrs[i], 0, 4*len); } for (i=0; i<MAX_SIMULTANEOUS_ALLOCS; i++) { wmem_free(allocator, ptrs[i]); } if (verify) (*verify)(allocator); wmem_free_all(allocator); wmem_gc(allocator); if (verify) (*verify)(allocator); }
/* * Returns an initialized MPA connection state or throws an out of * memory exception. */ static mpa_state_t * init_mpa_state(void) { mpa_state_t *state; state = (mpa_state_t *) wmem_alloc0(wmem_file_scope(), sizeof(mpa_state_t)); state->revision = -1; return state; }
/* Main dissection function. */ static void dissect_mac_lte_framed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint offset = 0; struct mac_lte_info *p_mac_lte_info; tvbuff_t *mac_tvb; gboolean infoAlreadySet = FALSE; /* Need to find enabled mac-lte dissector */ dissector_handle_t mac_lte_handle = find_dissector("mac-lte"); if (!mac_lte_handle) { return; } /* Do this again on re-dissection to re-discover offset of actual PDU */ /* Needs to be at least as long as: - fixed header bytes - tag for data - at least one byte of MAC PDU payload */ if ((size_t)tvb_length_remaining(tvb, offset) < (3+2)) { return; } /* If redissecting, use previous info struct (if available) */ p_mac_lte_info = (struct mac_lte_info*)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0); if (p_mac_lte_info == NULL) { /* Allocate new info struct for this frame */ p_mac_lte_info = (struct mac_lte_info*)wmem_alloc0(wmem_file_scope(), sizeof(struct mac_lte_info)); infoAlreadySet = FALSE; } else { infoAlreadySet = TRUE; } /* Dissect the fields to populate p_mac_lte */ if (!dissect_mac_lte_context_fields(p_mac_lte_info, tvb, &offset)) { return; } /* Store info in packet (first time) */ if (!infoAlreadySet) { p_add_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0, p_mac_lte_info); } /**************************************/ /* OK, now dissect as MAC LTE */ /* Create tvb that starts at actual MAC PDU */ mac_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector_only(mac_lte_handle, mac_tvb, pinfo, tree, NULL); }
char * fvalue_to_string_repr(wmem_allocator_t *scope, fvalue_t *fv, ftrepr_t rtype, int field_display) { char *buf; int len; if (fv->ftype->val_to_string_repr == NULL) { /* no value-to-string-representation function, so the value cannot be represented */ return NULL; } if ((len = fvalue_string_repr_len(fv, rtype, field_display)) >= 0) { buf = (char *)wmem_alloc0(scope, len + 1); } else { /* the value cannot be represented in the given representation type (rtype) */ return NULL; } fv->ftype->val_to_string_repr(fv, rtype, field_display, buf, (unsigned int)len+1); return buf; }
/* 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; } }
/* Transfers happen in response to broadcasts, they are always TCP and are * used to send the file to the port mentioned in the broadcast. There are * 2 types of transfers: Pushes, which are direct responses to searches, * in which the peer that has the file connects to the peer that doesn't and * sends it, then disconnects. The other type of transfer is a pull, where * the peer that doesn't have the file connects to the peer that does and * requests it be sent. * * Pulls have a file request which identifies the desired file, * while pushes simply send the file. In practice this works because every * file the implementation sends searches for is on a different TCP port * on the searcher's machine. */ static int dissect_ldss_transfer (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { conversation_t *transfer_conv; ldss_transfer_info_t *transfer_info; struct tcpinfo *transfer_tcpinfo; proto_tree *ti, *line_tree = NULL, *ldss_tree = NULL; nstime_t broadcast_response_time; /* Reject the packet if data is NULL */ if (data == NULL) return 0; transfer_tcpinfo = (struct tcpinfo *)data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDSS"); /* Look for the transfer conversation; this was created during * earlier broadcast dissection (see prepare_ldss_transfer_conv) */ transfer_conv = find_conversation (pinfo->num, &pinfo->src, &pinfo->dst, PT_TCP, pinfo->srcport, pinfo->destport, 0); transfer_info = (ldss_transfer_info_t *)conversation_get_proto_data(transfer_conv, proto_ldss); /* For a pull, the first packet in the TCP connection is the file request. * First packet is identified by relative seq/ack numbers of 1. * File request only appears on a pull (triggered by an offer - see above * about broadcasts) */ if (transfer_tcpinfo->seq == 1 && transfer_tcpinfo->lastackseq == 1 && transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND) { /* LDSS pull transfers look a lot like HTTP. * Sample request: * md5:01234567890123... * Size: 2550 * Start: 0 * Compression: 0 * (remote end sends the file identified by the digest) */ guint offset = 0; gboolean already_dissected = TRUE; col_set_str(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Requesting file - pull)"); if (highest_num_seen == 0 || highest_num_seen < pinfo->num) { already_dissected = FALSE; transfer_info->req = wmem_new0(wmem_file_scope(), ldss_file_request_t); transfer_info->req->file = wmem_new0(wmem_file_scope(), ldss_file_t); highest_num_seen = pinfo->num; } if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, tvb_reported_length(tvb), ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer); } /* Populate digest data into the file struct in the request */ transfer_info->file = transfer_info->req->file; /* Grab each line from the packet, there should be 4 but lets * not walk off the end looking for more. */ while (tvb_offset_exists(tvb, offset)) { gint next_offset; const guint8 *line; int linelen; gboolean is_digest_line; guint digest_type_len; linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); /* Include new-line in line */ line = (guint8 *)tvb_memdup(NULL, tvb, offset, linelen+1); /* XXX - memory leak? */ line_tree = proto_tree_add_subtree(ldss_tree, tvb, offset, linelen, ett_ldss_transfer_req, NULL, tvb_format_text(tvb, offset, next_offset-offset)); /* Reduce code duplication processing digest lines. * There are too many locals to pass to a function - the signature * looked pretty ugly when I tried! */ is_digest_line = FALSE; if (strncmp(line,"md5:",4)==0) { is_digest_line = TRUE; digest_type_len = 4; transfer_info->file->digest_type = DIGEST_TYPE_MD5; } else if (strncmp(line, "sha1:", 5)==0) { is_digest_line = TRUE; digest_type_len = 5; transfer_info->file->digest_type = DIGEST_TYPE_SHA1; } else if (strncmp(line, "sha256:", 7)==0) { is_digest_line = TRUE; digest_type_len = 7; transfer_info->file->digest_type = DIGEST_TYPE_SHA256; } else if (strncmp(line, "unknown:", 8)==0) { is_digest_line = TRUE; digest_type_len = 8; transfer_info->file->digest_type = DIGEST_TYPE_UNKNOWN; } else if (strncmp(line, "Size: ", 6)==0) { /* Sample size line: * Size: 2550\n */ transfer_info->req->size = g_ascii_strtoull(line+6, NULL, 10); if (tree) { ti = proto_tree_add_uint64(line_tree, hf_ldss_size, tvb, offset+6, linelen-6, transfer_info->req->size); PROTO_ITEM_SET_GENERATED(ti); } } else if (strncmp(line, "Start: ", 7)==0) { /* Sample offset line: * Start: 0\n */ transfer_info->req->offset = g_ascii_strtoull(line+7, NULL, 10); if (tree) { ti = proto_tree_add_uint64(line_tree, hf_ldss_offset, tvb, offset+7, linelen-7, transfer_info->req->offset); PROTO_ITEM_SET_GENERATED(ti); } } else if (strncmp(line, "Compression: ", 13)==0) { /* Sample compression line: * Compression: 0\n */ transfer_info->req->compression = (gint8)strtol(line+13, NULL, 10); /* XXX - bad cast */ if (tree) { ti = proto_tree_add_uint(line_tree, hf_ldss_compression, tvb, offset+13, linelen-13, transfer_info->req->compression); PROTO_ITEM_SET_GENERATED(ti); } } else { proto_tree_add_expert(line_tree, pinfo, &ei_ldss_unrecognized_line, tvb, offset, linelen); } if (is_digest_line) { /* Sample digest-type/digest line: * md5:0123456789ABCDEF\n */ if (!already_dissected) { GByteArray *digest_bytes; digest_bytes = g_byte_array_new(); hex_str_to_bytes( tvb_get_ptr(tvb, offset+digest_type_len, linelen-digest_type_len), digest_bytes, FALSE); if(digest_bytes->len >= DIGEST_LEN) digest_bytes->len = (DIGEST_LEN-1); /* Ensure the digest is zero-padded */ transfer_info->file->digest = (guint8 *)wmem_alloc0(wmem_file_scope(), DIGEST_LEN); memcpy(transfer_info->file->digest, digest_bytes->data, digest_bytes->len); g_byte_array_free(digest_bytes, TRUE); } if (tree) { proto_item *tii = NULL; tii = proto_tree_add_uint(line_tree, hf_ldss_digest_type, tvb, offset, digest_type_len, transfer_info->file->digest_type); PROTO_ITEM_SET_GENERATED(tii); tii = proto_tree_add_bytes(line_tree, hf_ldss_digest, tvb, offset+digest_type_len, MIN(linelen-digest_type_len, DIGEST_LEN), transfer_info->file->digest); PROTO_ITEM_SET_GENERATED(tii); } } offset = next_offset; } /* Link forwards to the response for this pull. */ if (tree && transfer_info->resp_num != 0) { ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_in, tvb, 0, 0, transfer_info->resp_num); PROTO_ITEM_SET_GENERATED(ti); } transfer_info->req->num = pinfo->num; transfer_info->req->ts = pinfo->abs_ts; } /* Remaining packets are the file response */ else { guint64 size; guint64 offset; guint8 compression; /* size, digest, compression come from the file request for a pull but * they come from the broadcast for a push. Pushes don't bother * with a file request - they just send the data. We have to get file * info from the offer broadcast which triggered this transfer. * If we cannot find the file request, default to the broadcast. */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL) { transfer_info->file = transfer_info->req->file; size = transfer_info->req->size; offset = transfer_info->req->offset; compression = transfer_info->req->compression; } else { transfer_info->file = transfer_info->broadcast->file; size = transfer_info->broadcast->size; offset = transfer_info->broadcast->offset; compression = transfer_info->broadcast->compression; } /* Remaining data in this TCP connection is all file data. * Always desegment if the size is 0 (ie. unknown) */ if (pinfo->can_desegment) { if (size == 0 || tvb_captured_length(tvb) < size) { pinfo->desegment_offset = 0; pinfo->desegment_len = DESEGMENT_UNTIL_FIN; return 0; } } /* OK. Now we have the whole file that was transferred. */ transfer_info->resp_num = pinfo->num; transfer_info->resp_ts = pinfo->abs_ts; col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Sending file - %s)", transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND ? "pull" : "push"); if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, tvb_reported_length(tvb), ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer); proto_tree_add_bytes_format(ldss_tree, hf_ldss_file_data, tvb, 0, tvb_captured_length(tvb), NULL, compression == COMPRESSION_GZIP ? "Gzip compressed data: %d bytes" : "File data: %d bytes", tvb_captured_length(tvb)); #ifdef HAVE_ZLIB /* Be nice and uncompress the file data. */ if (compression == COMPRESSION_GZIP) { tvbuff_t *uncomp_tvb; uncomp_tvb = tvb_child_uncompress(tvb, tvb, 0, tvb_captured_length(tvb)); if (uncomp_tvb != NULL) { /* XXX: Maybe not a good idea to add a data_source for what may very well be a large buffer since then the full uncompressed buffer will be shown in a tab in the hex bytes pane ? However, if we don't, bytes in an unrelated tab will be highlighted. */ add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Data"); proto_tree_add_bytes_format_value(ldss_tree, hf_ldss_file_data, uncomp_tvb, 0, tvb_captured_length(uncomp_tvb), NULL, "Uncompressed data: %d bytes", tvb_captured_length(uncomp_tvb)); } } #endif ti = proto_tree_add_uint(ldss_tree, hf_ldss_digest_type, tvb, 0, 0, transfer_info->file->digest_type); PROTO_ITEM_SET_GENERATED(ti); if (transfer_info->file->digest != NULL) { /* This is ugly. You can't add bytes of nonzero length and have * filtering work correctly unless you give a valid location in * the packet. This hack pretends the first 32 bytes of the packet * are the digest, which they aren't: they're actually the first 32 * bytes of the file that was sent. */ ti = proto_tree_add_bytes(ldss_tree, hf_ldss_digest, tvb, 0, DIGEST_LEN, transfer_info->file->digest); } PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint64(ldss_tree, hf_ldss_size, tvb, 0, 0, size); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint64(ldss_tree, hf_ldss_offset, tvb, 0, 0, offset); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint(ldss_tree, hf_ldss_compression, tvb, 0, 0, compression); PROTO_ITEM_SET_GENERATED(ti); /* Link to the request for a pull. */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL && transfer_info->req->num != 0) { ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_to, tvb, 0, 0, transfer_info->req->num); PROTO_ITEM_SET_GENERATED(ti); } } } /* Print the pull response time */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL && transfer_info->resp_num != 0) { nstime_t pull_response_time; nstime_delta(&pull_response_time, &transfer_info->resp_ts, &transfer_info->req->ts); ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_response_time, tvb, 0, 0, &pull_response_time); PROTO_ITEM_SET_GENERATED(ti); } /* Link the transfer back to the initiating broadcast. Response time is * calculated as the time from broadcast to completed transfer. */ ti = proto_tree_add_uint(ldss_tree, hf_ldss_initiated_by, tvb, 0, 0, transfer_info->broadcast->num); PROTO_ITEM_SET_GENERATED(ti); if (transfer_info->resp_num != 0) { nstime_delta(&broadcast_response_time, &transfer_info->resp_ts, &transfer_info->broadcast->ts); ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_completed_in, tvb, 0, 0, &broadcast_response_time); PROTO_ITEM_SET_GENERATED(ti); } /* This conv got its addr2/port2 set by the TCP dissector because a TCP * connection was established. Make a new one to handle future connections * to the addr/port mentioned in the broadcast, because that socket is * still open. */ if (transfer_tcpinfo->seq == 1 && transfer_tcpinfo->lastackseq == 1) { prepare_ldss_transfer_conv(transfer_info->broadcast); } return tvb_captured_length(tvb); }
static void dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request; proto_tree *imap_tree, *reqresp_tree; proto_item *ti, *hidden_item; gint offset = 0; gint uid_offset = 0; gint folder_offset = 0; const guchar *line; const guchar *uid_line; const guchar *folder_line; gint next_offset; int linelen; int tokenlen; int uid_tokenlen; int folder_tokenlen; const guchar *next_token; const guchar *uid_next_token; const guchar *folder_next_token; guchar *tokenbuf; guchar *command_token; int iter; int commandlen; conversation_t *conversation; imap_state_t *session_state; conversation = find_or_create_conversation(pinfo); session_state = (imap_state_t *)conversation_get_proto_data(conversation, proto_imap); if (!session_state) { session_state = wmem_new0(wmem_file_scope(), imap_state_t); session_state->ssl_requested = FALSE; conversation_add_proto_data(conversation, proto_imap, session_state); } tokenbuf = (guchar *)wmem_alloc0(wmem_packet_scope(), MAX_BUFFER); command_token = (guchar *)wmem_alloc0(wmem_packet_scope(), MAX_BUFFER); commandlen = 0; folder_offset = 0; folder_tokenlen = 0; folder_line = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IMAP"); if (pinfo->match_uint == pinfo->destport) is_request = TRUE; else is_request = FALSE; /* * Put the first line from the buffer into the summary * (but leave out the line terminator). */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); { ti = proto_tree_add_item(tree, proto_imap, tvb, offset, -1, ENC_NA); imap_tree = proto_item_add_subtree(ti, ett_imap); hidden_item = proto_tree_add_boolean(imap_tree, hf_imap_isrequest, tvb, 0, 0, is_request); PROTO_ITEM_SET_HIDDEN(hidden_item); while(tvb_offset_exists(tvb, offset)) { /* * Find the end of each line * * Note that "tvb_find_line_end()" will return a value that is * not longer than what's in the buffer, so the "tvb_get_ptr()" * call won't throw an exception. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); /* * Put the line into the protocol tree. */ ti = proto_tree_add_item(imap_tree, hf_imap_line, tvb, offset, next_offset - offset, ENC_ASCII|ENC_NA); reqresp_tree = proto_item_add_subtree(ti, ett_imap_reqresp); /* * Check that the line doesn't begin with '*', because that's a continuation line. * Otherwise if a tag is present then extract tokens. */ if ( (line) && ((line[0] != '*') || (TRUE == is_request)) ) { /* * Show each line as tags + requests or replies. */ /* * Extract the first token, and, if there is a first * token, add it as the request or reply tag. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_tag : hf_imap_response_tag, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); offset += (gint) (next_token - line); linelen -= (int) (next_token - line); line = next_token; } /* * Extract second token, and, if there is a second * token, and it's not uid, add it as the request or reply command. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { for (iter = 0; iter < tokenlen && iter < MAX_BUFFER-1; iter++) { tokenbuf[iter] = g_ascii_tolower(line[iter]); } if (tree && is_request && strncmp(tokenbuf, "uid", tokenlen) == 0) { proto_tree_add_item(reqresp_tree, hf_imap_request_uid, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); /* * UID is a precursor to a command, if following the tag, * so move to next token to grab the actual command. */ uid_offset = offset; uid_offset += (gint) (next_token - line); uid_line = next_token; uid_tokenlen = get_token_len(uid_line, uid_line + (linelen - tokenlen), &uid_next_token); if (tokenlen != 0) { proto_tree_add_item(reqresp_tree, hf_imap_request_command, tvb, uid_offset, uid_tokenlen, ENC_ASCII|ENC_NA); /* * Save command string to do specialized processing. */ for (iter = 0; iter < uid_tokenlen && iter < MAX_BUFFER-1; iter++) { command_token[iter] = g_ascii_tolower(uid_line[iter]); } commandlen = uid_tokenlen; folder_offset = uid_offset; folder_offset += (gint) (uid_next_token - uid_line); folder_line = uid_next_token; folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - uid_tokenlen), &folder_next_token); } } else { /* * Not a UID request so perform normal parsing. */ proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_command : hf_imap_response_status, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); if (is_request) { /* * Save command string to do specialized processing. */ for (iter = 0; iter < tokenlen && iter < 256; iter++) { command_token[iter] = g_ascii_tolower(line[iter]); } commandlen = tokenlen; folder_offset = offset; folder_offset += (gint) (next_token - line); folder_line = next_token; folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - 1), &folder_next_token); } } if (tree && commandlen > 0 && ( strncmp(command_token, "select", commandlen) == 0 || strncmp(command_token, "examine", commandlen) == 0 || strncmp(command_token, "create", commandlen) == 0 || strncmp(command_token, "delete", commandlen) == 0 || strncmp(command_token, "rename", commandlen) == 0 || strncmp(command_token, "subscribe", commandlen) == 0 || strncmp(command_token, "unsubscribe", commandlen) == 0 || strncmp(command_token, "status", commandlen) == 0 || strncmp(command_token, "append", commandlen) == 0 || strncmp(command_token, "search", commandlen) == 0)) { /* * These commands support folder as an argument, * so parse out the folder name. */ if (folder_tokenlen != 0) proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA); } if (tree && is_request && (NULL != folder_line) && strncmp(command_token, "copy", commandlen) == 0) { /* * Handle the copy command separately since folder * is the second argument for this command. */ folder_offset += (gint) (folder_next_token - folder_line); folder_line = folder_next_token; folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen), &folder_next_token); if (folder_tokenlen != 0) proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA); } /* If not yet switched to TLS, check for STARTTLS. */ if (session_state->ssl_requested) { if (!is_request && session_state->ssl_requested && strncmp(tokenbuf, "ok", tokenlen) == 0) { /* STARTTLS accepted, next reply will be TLS. */ ssl_starttls_ack(ssl_handle, pinfo, imap_handle); } session_state->ssl_requested = FALSE; } if (is_request && commandlen > 0 && strncmp(command_token, "starttls", commandlen) == 0) { /* If next response is OK, then TLS should be commenced. */ session_state->ssl_requested = TRUE; } } /* * Add the rest of the line as request or reply data. */ if (linelen != 0) { proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request : hf_imap_response, tvb, offset, linelen, ENC_ASCII|ENC_NA); } } offset = next_offset; /* Skip over last line and \r\n at the end of it */ } } }
static void wmem_test_allocator(wmem_allocator_type_t type, wmem_verify_func verify, int iterations) { int i; char *ptrs[MAX_SIMULTANEOUS_ALLOCS]; wmem_allocator_t *allocator; allocator = wmem_allocator_force_new(type); if (verify) (*verify)(allocator); /* start with some fairly simple deterministic tests */ wmem_test_allocator_det(allocator, verify, 8); wmem_test_allocator_det(allocator, verify, 64); wmem_test_allocator_det(allocator, verify, 512); for (i=0; i<MAX_SIMULTANEOUS_ALLOCS; i++) { ptrs[i] = wmem_alloc0_array(allocator, char, 32); } if (verify) (*verify)(allocator); wmem_free_all(allocator); wmem_gc(allocator); if (verify) (*verify)(allocator); /* now do some random fuzz-like tests */ /* reset our ptr array */ for (i=0; i<MAX_SIMULTANEOUS_ALLOCS; i++) { ptrs[i] = NULL; } /* Run enough iterations to fill the array 32 times */ for (i=0; i<iterations; i++) { gint ptrs_index; gint new_size; /* returns value 0 <= x < MAX_SIMULTANEOUS_ALLOCS which is a valid * index into ptrs */ ptrs_index = g_test_rand_int_range(0, MAX_SIMULTANEOUS_ALLOCS); if (ptrs[ptrs_index] == NULL) { /* if that index is unused, allocate some random amount of memory * between 0 and MAX_ALLOC_SIZE */ new_size = g_test_rand_int_range(0, MAX_ALLOC_SIZE); ptrs[ptrs_index] = (char *) wmem_alloc0(allocator, new_size); } else if (g_test_rand_bit()) { /* the index is used, and our random bit has determined we will be * reallocating instead of freeing. Do so to some random size * between 0 and MAX_ALLOC_SIZE, then manually zero the * new memory */ new_size = g_test_rand_int_range(0, MAX_ALLOC_SIZE); ptrs[ptrs_index] = (char *) wmem_realloc(allocator, ptrs[ptrs_index], new_size); memset(ptrs[ptrs_index], 0, new_size); } else { /* the index is used, and our random bit has determined we will be * freeing instead of reallocating. Do so and NULL the pointer for * the next iteration. */ wmem_free(allocator, ptrs[ptrs_index]); ptrs[ptrs_index] = NULL; } if (verify) (*verify)(allocator); } wmem_destroy_allocator(allocator); }
/* Code to actually dissect the packets */ static void dissect_mtp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { mtp3_tap_rec_t* tap_rec = ep_new0(mtp3_tap_rec_t); gint heuristic_standard; guint8 si; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *mtp3_item = NULL, *gen_item; proto_tree *mtp3_tree = NULL; pref_mtp3_standard = mtp3_standard; mtp3_item = proto_tree_add_item(tree, proto_mtp3, tvb, 0, 0, ENC_NA); si = tvb_get_guint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK; if (mtp3_heuristic_standard) { heuristic_standard = heur_mtp3_standard(tvb, pinfo, si); if (heuristic_standard == HEURISTIC_FAILED_STANDARD) { gen_item = proto_tree_add_text(tree, tvb, 0, 0, "Could not determine Heuristic using %s", val_to_str_const(mtp3_standard, mtp3_standard_vals, "unknown")); } else { gen_item = proto_tree_add_text(tree, tvb, 0, 0, "%s", val_to_str_const(heuristic_standard, mtp3_standard_vals, "unknown")); mtp3_standard = heuristic_standard; /* Register a frame-end routine to ensure mtp3_standard is set * back even if an exception is thrown. */ register_frame_end_routine(pinfo, reset_mtp3_standard); } PROTO_ITEM_SET_GENERATED(gen_item); } /* Make entries in Protocol column on summary display */ switch(mtp3_standard) { case ITU_STANDARD: col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Int. ITU)"); proto_item_set_len(mtp3_item, ITU_HEADER_LENGTH); break; case ANSI_STANDARD: col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (ANSI)"); proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH); break; case CHINESE_ITU_STANDARD: col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Chin. ITU)"); proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH); break; case JAPAN_STANDARD: col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Japan)"); proto_item_set_len(mtp3_item, JAPAN_HEADER_LENGTH); break; }; if (tree) { /* create display subtree for the protocol */ mtp3_tree = proto_item_add_subtree(mtp3_item, ett_mtp3); } mtp3_addr_opc = (mtp3_addr_pc_t *)wmem_alloc0(pinfo->pool, sizeof(mtp3_addr_pc_t)); mtp3_addr_dpc = (mtp3_addr_pc_t *)wmem_alloc0(pinfo->pool, sizeof(mtp3_addr_pc_t)); /* Dissect the packet (even if !tree so can call sub-dissectors and update * the source and destination address columns) */ dissect_mtp3_sio(tvb, mtp3_tree); dissect_mtp3_routing_label(tvb, pinfo, mtp3_tree); memcpy(&(tap_rec->addr_opc), mtp3_addr_opc, sizeof(mtp3_addr_pc_t)); memcpy(&(tap_rec->addr_dpc), mtp3_addr_dpc, sizeof(mtp3_addr_pc_t)); tap_rec->si_code = (tvb_get_guint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK); tap_rec->size = tvb_length(tvb); tap_queue_packet(mtp3_tap, pinfo, tap_rec); dissect_mtp3_payload(tvb, pinfo, tree); mtp3_standard = pref_mtp3_standard; }
static gint ett_http = -1; static int proto_http = -1; static int hf_http_is_response = -1; static int hf_http_request_method = -1; static int hf_http_response_code = -1; static int hf_http_transfer_encoding = -1; static int hf_http_content_length = -1; static int hf_http_media = -1; static int hf_http_host = -1; static int hf_http_request_uri = -1; static dissector_handle_t http_handle; static int dissect_http(tvbuff_t* tvb, packet_info* pinfo _U_, proto_tree* tree, void* data _U_) { http_info_value_t* msgdata = wmem_alloc0(wmem_packet_scope(), sizeof(http_info_value_t)); tvbparse_elem_t* reqresp; tpg_parser_data_t* tpg; proto_item* pi = proto_tree_add_item(tree,proto_http,tvb,0,-1,ENC_NA); proto_tree* pt = proto_item_add_subtree(pi,ett_http); tpg = tpg_start(pt,tvb,0,-1,http_tpg_data.wanted_http_sp, msgdata); if (( reqresp = TPG_GET(tpg,http_tpg_data.wanted_http_req_resp) )) { tvbparse_elem_t* hdr; while(( hdr = TPG_GET(tpg,http_tpg_data.wanted_http_header) )) ; if ( TPG_GET(tpg,http_tpg_data.wanted_http_crlf) ) { pi = proto_tree_add_boolean(pt,hf_http_is_response,tvb,0,0,msgdata->is_response);
static void dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *ssh_tree = NULL; proto_item *ti; conversation_t *conversation; int last_offset, offset = 0; gboolean is_response = (pinfo->destport != pinfo->match_uint), need_desegmentation; guint version; struct ssh_flow_data *global_data=NULL; struct ssh_peer_data *peer_data; conversation = find_or_create_conversation(pinfo); global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh); if (!global_data) { global_data = (struct ssh_flow_data *)wmem_alloc0(wmem_file_scope(), sizeof(struct ssh_flow_data)); global_data->version=SSH_VERSION_UNKNOWN; global_data->kex_specific_dissector=ssh_dissect_kex_dh; global_data->peer_data[CLIENT_PEER_DATA].mac_length=-1; global_data->peer_data[SERVER_PEER_DATA].mac_length=-1; conversation_add_proto_data(conversation, proto_ssh, global_data); } peer_data = &global_data->peer_data[is_response]; if (tree) { ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA); ssh_tree = proto_item_add_subtree(ti, ett_ssh); } version = global_data->version; switch(version) { case SSH_VERSION_UNKNOWN: col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH"); break; case SSH_VERSION_1: col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1"); break; case SSH_VERSION_2: col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2"); break; } col_clear(pinfo->cinfo, COL_INFO); while(tvb_reported_length_remaining(tvb, offset)> 0) { gboolean after_version_start = (peer_data->frame_version_start == 0 || pinfo->fd->num >= peer_data->frame_version_start); gboolean before_version_end = (peer_data->frame_version_end == 0 || pinfo->fd->num <= peer_data->frame_version_end); need_desegmentation = FALSE; last_offset = offset; peer_data->counter++; if (after_version_start && before_version_end && (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) { if (peer_data->frame_version_start == 0) peer_data->frame_version_start = pinfo->fd->num; offset = ssh_dissect_protocol(tvb, pinfo, global_data, offset, ssh_tree, is_response, &version, &need_desegmentation); if (!need_desegmentation) { peer_data->frame_version_end = pinfo->fd->num; global_data->version = version; } } else { switch(version) { case SSH_VERSION_UNKNOWN: offset = ssh_dissect_encrypted_packet(tvb, pinfo, &global_data->peer_data[is_response], offset, ssh_tree); break; case SSH_VERSION_1: offset = ssh_dissect_ssh1(tvb, pinfo, global_data, offset, ssh_tree, is_response, &need_desegmentation); break; case SSH_VERSION_2: offset = ssh_dissect_ssh2(tvb, pinfo, global_data, offset, ssh_tree, is_response, &need_desegmentation); break; } } if (need_desegmentation) return; if (offset <= last_offset) THROW(ReportedBoundsError); } col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client"); }
int decompress_packet (const guint8 *in, gint in_length, guint8 *out, guint *out_length) { class CsObjectInt csObject; int rt = 0, finished = false; SAP_BYTE *bufin = NULL, *bufin_pos = NULL, *bufout = NULL, *bufout_pos = NULL; SAP_INT bufin_length = 0, bufin_rest = 0, bufout_length = 0, bufout_rest = 0, data_length = 0, bytes_read = 0, bytes_decompressed = 0, total_decompressed = 0; #ifdef DEBUG printf("sapdecompress.cpp: Decompressing (%d bytes, reported length of %d bytes)...\n", in_length, *out_length); #endif /* Check for invalid inputs */ if (in == NULL) return (CS_E_INVALID_ADDR); if (in_length <= 0) return (CS_E_IN_BUFFER_LEN); if (out == NULL) return (CS_E_INVALID_ADDR); if (*out_length <= 0) return (CS_E_OUT_BUFFER_LEN); /* Allocate buffers */ bufin_length = bufin_rest = (SAP_INT)in_length; bufin = bufin_pos = (SAP_BYTE*) wmem_alloc0(wmem_packet_scope(), in_length); if (!bufin){ return (CS_E_MEMORY_ERROR); } /* Copy the in parameter into the buffer */ for (int i = 0; i < in_length; i++) { bufin[i] = (SAP_BYTE) in[i]; } /* Initialize and obtain the reported uncompressed data length */ rt = csObject.CsInitDecompr(bufin); if (rt != 0){ #ifdef DEBUG printf("sapdecompress.cpp: Initialization failed !\n"); #endif wmem_free(wmem_packet_scope(), bufin); *out_length = 0; return (rt); } /* Check the length in the header vs the reported one */ data_length = csObject.CsGetLen(bufin); if (data_length != (SAP_INT)*out_length){ #ifdef DEBUG printf("sapdecompress.cpp: Length reported (%d) doesn't match with the one in the header (%d)\n", *out_length, data_length); #endif wmem_free(wmem_packet_scope(), bufin); *out_length = 0; return (CS_E_OUT_BUFFER_LEN); } /* Advance the buffer pointer as we've already read the header */ bufin_pos += CS_HEAD_SIZE; #ifdef DEBUG printf("sapdecompress.cpp: Initialized, reported length in header: %d bytes\n", data_length); #endif /* Allocate the output buffer. We use the reported output size * as the output buffer size. */ bufout_length = bufout_rest = *out_length; bufout = bufout_pos = (SAP_BYTE*) wmem_alloc0(wmem_packet_scope(), bufout_length); if (!bufout){ *out_length = 0; wmem_free(wmem_packet_scope(), bufin); return (CS_E_MEMORY_ERROR); } memset(bufout, 0, bufout_length); #ifdef DEBUG_TRACE printf("sapdecompress.cpp: Input buffer %p (%d bytes), output buffer %p (%d bytes)\n", bufin, bufin_length, bufout, bufout_length); #endif while (finished == false && bufin_rest > 0 && bufout_rest > 0) { #ifdef DEBUG_TRACE printf("sapdecompress.cpp: Input position %p (rest %d bytes), output position %p\n", bufin_pos, bufin_rest, bufout_pos); #endif rt = csObject.CsDecompr(bufin_pos, bufin_rest, bufout_pos, bufout_rest, 0, &bytes_read, &bytes_decompressed); #ifdef DEBUG printf("sapdecompress.cpp: Return code %d (%s) (%d bytes read, %d bytes decompressed)\n", rt, decompress_error_string(rt), bytes_read, bytes_decompressed); #endif /* Successful decompression, we've finished with the stream */ if (rt == CS_END_OF_STREAM){ finished = true; } /* Some error occurred */ if (rt != CS_END_INBUFFER && rt != CS_END_OUTBUFFER){ finished = true; } /* Advance the input buffer */ bufin_pos += bytes_read; bufin_rest -= bytes_read; /* Advance the output buffer */ bufout_pos += bytes_decompressed; bufout_rest -= bytes_decompressed; total_decompressed += bytes_decompressed; } /* Successful decompression */ if (rt == CS_END_OF_STREAM) { *out_length = total_decompressed; /* Copy the buffer in the out parameter */ for (int i = 0; i < total_decompressed; i++) (out)[i] = (char) bufout[i]; #ifdef DEBUG_TRACE printf("sapdecompress.cpp: Out buffer:\n"); hexdump(out, total_decompressed); #endif } /* Free the buffers */ wmem_free(wmem_packet_scope(), bufin); wmem_free(wmem_packet_scope(), bufout); #ifdef DEBUG printf("sapdecompress.cpp: Out Length: %d\n", *out_length); #endif return (rt); };