static void add_request(ipmi_packet_data_t * data, const ipmi_header_t * hdr) { /* get current frame */ ipmi_frame_data_t * rq_frame = data->curr_frame; /* get current command data */ ipmi_cmd_data_t * rq_data = rq_frame->cmd_data[data->curr_level]; /* check if parse response for the first time */ if (!rq_data) { ipmi_request_t * rq; /* allocate command data */ rq_data = wmem_new0(wmem_file_scope(), ipmi_cmd_data_t); /* set command data pointer */ rq_frame->cmd_data[data->curr_level] = rq_data; /* allocate request data */ rq = wmem_new0(wmem_file_scope(), ipmi_request_t); /* copy request header */ memcpy(&rq->hdr, hdr, sizeof(rq->hdr)); /* override context, channel and direction */ rq->hdr.context = 0; rq->hdr.channel = data->curr_channel; rq->hdr.dir = data->curr_dir; /* set request frame number */ rq->frame_num = data->curr_frame_num; /* set command nest level */ rq->nest_level = data->curr_level; /* append request to list */ wmem_list_append(data->request_list, rq); #ifdef DEBUG fprintf(stderr, "%d, %d: hdr : {\n" "\tchannel=%d\n" "\tdir=%d\n" "\trs_sa=%x\n" "\trs_lun=%d\n" "\tnetfn=%x\n" "\trq_sa=%x\n" "\trq_lun=%d\n" "\trq_seq=%x\n" "\tcmd=%x\n}\n", data->curr_frame_num, data->curr_level, rq->hdr.channel, rq->hdr.dir, rq->hdr.rs_sa, rq->hdr.rs_lun, rq->hdr.netfn, rq->hdr.rq_sa, rq->hdr.rq_lun, rq->hdr.rq_seq, rq->hdr.cmd); #endif } }
/* split out some common FEC handling */ static guint dissect_feccode(proto_tree *tree, tvbuff_t *tvb, guint offset, packet_info *pinfo, gint reserved) { norm_packet_data_t *norm_data; guint8 encoding_id = tvb_get_guint8(tvb, offset); /* Save encoding ID */ norm_data = wmem_new0(wmem_file_scope(), norm_packet_data_t); norm_data->encoding_id = encoding_id; p_add_proto_data(wmem_file_scope(), pinfo, proto_rmt_norm, 0, norm_data); proto_tree_add_item(tree, hf_fec_encoding_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (reserved) { proto_tree_add_item(tree, hf_reserved, tvb, offset, 1, ENC_NA); offset += 1; } proto_tree_add_item(tree, hf_object_transport_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; if (tvb_reported_length_remaining(tvb, offset) > 0) { fec_data_exchange_t fec; tvbuff_t *new_tvb; int len; new_tvb = tvb_new_subset_remaining(tvb, offset); fec.encoding_id = encoding_id; len = call_dissector_with_data(rmt_fec_handle, new_tvb, pinfo, tree, &fec); if (len > 0) offset += len; } return offset; }
static ipmi_packet_data_t * get_packet_data(packet_info * pinfo) { ipmi_packet_data_t * data; /* get conversation data */ conversation_t * conv = find_or_create_conversation(pinfo); /* get protocol-specific data */ data = (ipmi_packet_data_t *) conversation_get_proto_data(conv, proto_ipmi); if (!data) { /* allocate per-packet data */ data = wmem_new0(wmem_file_scope(), ipmi_packet_data_t); /* allocate request list and frame tree */ data->frame_tree = wmem_tree_new(wmem_file_scope()); data->request_list = wmem_list_new(wmem_file_scope()); /* add protocol data */ conversation_add_proto_data(conv, proto_ipmi, data); } /* check if packet has changed */ if (pinfo->num != data->curr_frame_num) { data->curr_level = 0; data->next_level = 0; } return data; }
/* code to dissect NORM info packets */ static void dissect_norm_info(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint8 hlen) { proto_item *ti; proto_tree *flag_tree; norm_packet_data_t *norm_data; offset = dissect_grrtetc(tree, tvb, offset); ti = proto_tree_add_item(tree, hf_flags, tvb, offset, 1, ENC_BIG_ENDIAN); flag_tree = proto_item_add_subtree(ti, ett_flags); proto_tree_add_item(flag_tree, hf_flag_repair, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flag_tree, hf_flag_norm_explicit, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flag_tree, hf_flag_info, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flag_tree, hf_flag_unreliable, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flag_tree, hf_flag_file, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flag_tree, hf_flag_stream, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flag_tree, hf_flag_msgstart, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Save encoding ID */ norm_data = wmem_new0(wmem_file_scope(), norm_packet_data_t); norm_data->encoding_id = tvb_get_guint8(tvb, offset); p_add_proto_data(wmem_file_scope(), pinfo, proto_rmt_norm, 0, norm_data); proto_tree_add_item(tree, hf_fec_encoding_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_object_transport_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (offset < hdrlen2bytes(hlen)) { offset = dissect_norm_hdrext(tree, pinfo, tvb, offset, hlen); } if (tvb_reported_length_remaining(tvb, offset) > 0) proto_tree_add_item(tree, hf_payload, tvb, offset, -1, ENC_NA); }
static ulp_private_data_t* ulp_get_private_data(asn1_ctx_t *actx) { if (actx->private_data == NULL) { actx->private_data = wmem_new0(wmem_packet_scope(), ulp_private_data_t); } return (ulp_private_data_t*)actx->private_data; }
void asn1_stack_frame_push(asn1_ctx_t *actx, const gchar *name) { asn1_stack_frame_t *frame; frame = wmem_new0(wmem_packet_scope(), asn1_stack_frame_t); frame->name = name; frame->next = actx->stack; actx->stack = frame; }
/* Generic Extensible Framework */ gef_ctx_t* gef_ctx_alloc(gef_ctx_t *parent, const gchar *type) { gef_ctx_t *gefx; gefx = wmem_new0(wmem_packet_scope(), gef_ctx_t); gefx->signature = GEF_CTX_SIGNATURE; gefx->parent = parent; gefx->type = type; return gefx; }
static usb_i1d3_transaction_t *usb_i1d3_create_transaction( usb_i1d3_conversation_t *conversation, guint32 request) { usb_i1d3_transaction_t *transaction = wmem_new0( wmem_file_scope(), usb_i1d3_transaction_t); transaction->request = request; wmem_map_insert( conversation->request_to_transaction, GUINT_TO_POINTER(transaction->request), (void *)transaction); return transaction; }
static void set_do_address(asn1_ctx_t* actx, gboolean do_address) { p1_address_ctx_t* ctx; if (actx->subtree.tree_ctx == NULL) { actx->subtree.tree_ctx = wmem_new0(wmem_packet_scope(), p1_address_ctx_t); } ctx = (p1_address_ctx_t*)actx->subtree.tree_ctx; ctx->do_address = do_address; }
wmem_tree_t * wmem_tree_new(wmem_allocator_t *allocator) { wmem_tree_t *tree; tree = wmem_new0(allocator, wmem_tree_t); tree->master = allocator; tree->allocator = allocator; return tree; }
static ipmi_frame_data_t * get_frame_data(ipmi_packet_data_t * data, guint32 frame_num) { ipmi_frame_data_t * frame = (ipmi_frame_data_t *) wmem_tree_lookup32(data->frame_tree, frame_num); if (frame == NULL) { frame = wmem_new0(wmem_file_scope(), ipmi_frame_data_t); wmem_tree_insert32(data->frame_tree, frame_num, frame); } return frame; }
static asn1_par_t *push_new_par(asn1_ctx_t *actx) { asn1_par_t *par, **pp; DISSECTOR_ASSERT(actx->stack); par = wmem_new0(wmem_packet_scope(), asn1_par_t); pp = &(actx->stack->par); while (*pp) pp = &((*pp)->next); *pp = par; return par; }
void p1_initialize_content_globals (asn1_ctx_t* actx, proto_tree *tree, gboolean report_unknown_cont_type) { p1_address_ctx_t* ctx; if (actx->subtree.tree_ctx == NULL) { actx->subtree.tree_ctx = wmem_new0(wmem_packet_scope(), p1_address_ctx_t); } ctx = (p1_address_ctx_t*)actx->subtree.tree_ctx; actx->subtree.top_tree = tree; actx->external.direct_reference = NULL; ctx->content_type_id = NULL; ctx->report_unknown_content_type = report_unknown_cont_type; }
/* When seeing a broadcast talking about an open TCP port on a host, create * a conversation to dissect anything sent/received at that address. Setup * protocol data so the TCP dissection knows what broadcast triggered it. */ static void prepare_ldss_transfer_conv(ldss_broadcast_t *broadcast) { conversation_t *transfer_conv; ldss_transfer_info_t *transfer_info; transfer_info = wmem_new0(wmem_file_scope(), ldss_transfer_info_t); transfer_info->broadcast = broadcast; /* Preparation for later push/pull dissection */ transfer_conv = conversation_new (broadcast->num, &broadcast->broadcaster->addr, &broadcast->broadcaster->addr, PT_TCP, broadcast->broadcaster->port, broadcast->broadcaster->port, NO_ADDR2|NO_PORT2); conversation_add_proto_data(transfer_conv, proto_ldss, transfer_info); conversation_set_dissector(transfer_conv, ldss_tcp_handle); }
static void match_request_response(ipmi_packet_data_t * data, const ipmi_header_t * hdr, guint flags) { /* get current frame */ ipmi_frame_data_t * rs_frame = data->curr_frame; /* get current command data */ ipmi_cmd_data_t * rs_data = rs_frame->cmd_data[data->curr_level]; /* check if parse response for the first time */ if (!rs_data) { ipmi_request_t * rq; /* allocate command data */ rs_data = wmem_new0(wmem_file_scope(), ipmi_cmd_data_t); /* search for matching request */ rq = get_matched_request(data, hdr, flags); /* check if matching request is found */ if (rq) { /* get request frame data */ ipmi_frame_data_t * rq_frame = get_frame_data(data, rq->frame_num); /* get command data */ ipmi_cmd_data_t * rq_data = rq_frame->cmd_data[rq->nest_level]; /* save matched frame numbers */ rq_data->matched_frame_num = data->curr_frame_num; rs_data->matched_frame_num = rq->frame_num; /* copy saved command data information */ rs_data->saved_data[0] = rq_data->saved_data[0]; rs_data->saved_data[1] = rq_data->saved_data[1]; /* remove request from the list */ wmem_list_remove(data->request_list, rq); /* delete request data */ wmem_free(wmem_file_scope(), rq); } /* save command data pointer in frame */ rs_frame->cmd_data[data->curr_level] = rs_data; } }
static usb_i1d3_conversation_t *usb_i1d3_get_conversation(packet_info *pinfo) { conversation_t *conversation = find_or_create_conversation(pinfo); usb_i1d3_conversation_t* i1d3_conversation = (usb_i1d3_conversation_t *)conversation_get_proto_data( conversation, proto_usb_i1d3); if (!i1d3_conversation) { i1d3_conversation = wmem_new0( wmem_file_scope(), usb_i1d3_conversation_t); i1d3_conversation->request_to_transaction = wmem_map_new( wmem_file_scope(), g_direct_hash, g_direct_equal); i1d3_conversation->response_to_transaction = wmem_map_new( wmem_file_scope(), g_direct_hash, g_direct_equal); conversation_add_proto_data( conversation, proto_usb_i1d3, i1d3_conversation); } return i1d3_conversation; }
void register_seq_analysis(const char* name, const char* ui_name, const int proto_id, const char* tap_listener, guint tap_flags, tap_packet_cb tap_func) { register_analysis_t* analysis; DISSECTOR_ASSERT(tap_func); analysis = wmem_new0(wmem_epan_scope(), register_analysis_t); analysis->name = name; analysis->ui_name = ui_name; analysis->proto_id = proto_id; if (tap_listener != NULL) analysis->tap_listen_str = tap_listener; else analysis->tap_listen_str = proto_get_protocol_filter_name(proto_id); analysis->tap_flags = tap_flags; analysis->analysis_func = tap_func; if (registered_seq_analysis == NULL) registered_seq_analysis = wmem_tree_new(wmem_epan_scope()); wmem_tree_insert_string(registered_seq_analysis, name, analysis, 0); }
static int dissect_ppcap_source_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree * ppcap_tree1, int offset) { int key1; guint16 msg_len; msg_len = tvb_get_ntohs(tvb, offset); proto_tree_add_item( ppcap_tree1, hf_ppcap_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; proto_tree_add_item(ppcap_tree1, hf_ppcap_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; key1 = tvb_get_ntohs(tvb, offset); proto_tree_add_item(ppcap_tree1, hf_ppcap_address_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (key1 == 1) { proto_tree_add_item(ppcap_tree1, hf_ppcap_ssn, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(ppcap_tree1, hf_ppcap_spc, tvb, offset, 3, ENC_BIG_ENDIAN); /*src_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/ mtp3_addr_opc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t); mtp3_addr_opc->pc = (guint32 )tvb_get_ntoh24(tvb, offset); mtp3_addr_opc->type = ITU_STANDARD; mtp3_addr_opc->ni = 0; /*SET_ADDRESS(&pinfo->net_src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);*/ SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc); if (msg_len%4) msg_len = msg_len + (4 - (msg_len%4)); offset += msg_len-1; return offset; } else if (key1 == 2) { proto_tree_add_item(ppcap_tree1, hf_ppcap_opc, tvb, offset, msg_len, ENC_BIG_ENDIAN); /*src_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/ mtp3_addr_opc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t); mtp3_addr_opc->pc = tvb_get_ntohl(tvb, offset); mtp3_addr_opc->type = ITU_STANDARD; mtp3_addr_opc->ni = 0; SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc); } else if (key1 == 3) { if (msg_len%16 != 0) { proto_tree_add_ipv4(ppcap_tree1, hf_ppcap_source_ip_address1, tvb, offset, msg_len, tvb_get_ipv4(tvb, offset)); TVB_SET_ADDRESS(&pinfo->net_src, AT_IPv4, tvb, offset, 4); COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src); } else { struct e_in6_addr value; tvb_get_ipv6(tvb, offset, &value); proto_tree_add_ipv6(ppcap_tree1, hf_ppcap_source_ip_address2, tvb, offset, msg_len, &value); TVB_SET_ADDRESS(&pinfo->net_src, AT_IPv6, tvb, offset, 6); COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src); } } else if (key1 == 4) { proto_tree_add_item(ppcap_tree1, hf_ppcap_source_nodeid, tvb, offset, msg_len, ENC_ASCII|ENC_NA); TVB_SET_ADDRESS(&pinfo->net_src, AT_STRINGZ, tvb, offset, msg_len); COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src); } if (msg_len%4) msg_len = msg_len + (4 - (msg_len%4)); offset += msg_len; return offset; }
/* 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); }
/* Broadcasts are searches, offers or promises. * * Searches are sent by * a peer when it needs a file (ie. while applying its policy, when it needs * files such as installers to install software.) * * Each broadcast relates to one file and each file is identified only by its * checksum - no file names are ever used. A search times out after 10 seconds * (configurable) and the peer will then attempt to act on any offers by * downloading (via push or pull - see dissect_ldss_transfer) from those peers. * * If no offers are received, the search fails and the peer fetches the file * from a remote server, generally a HTTP server on the other side of a WAN. * The protocol exists to minimize the number of WAN downloads needed. * * While downloading from WAN the peer sends promises to inform other peers * when it will be available for them to download. This prevents multiple peers * simultaneously downloading the same file. Promises also inform other peers * how much download bandwidth is being used by their download. Other peers use * this information and the configured knowledge of the WAN bandwidth to avoid * saturating the WAN link, as file downloads are a non-time-critical and * non-business-critical network function. LDSS is intended for networks of * 5-20 machines connected by slow WAN link. The current implementation of the * protocol allows administrator to configure "time windows" when WAN usage is * throttled/unthrottled, though this isn't visible in LDSS. * * Once a WAN download or a LAN transfer (see below above dissect_ldss_transfer) * has complete the peer will offer the file to other peers on the LAN so they * don't need to download it themselves. * * Peers also notify when they shut down in case any other peer is waiting for * a file. */ static int dissect_ldss_broadcast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 messageID; guint8 digest_type; guint8 compression; guint32 cookie; guint8 *digest; guint64 size; guint64 offset; guint32 targetTime; guint16 port; guint16 rate; guint16 messageDetail = INFERRED_NONE; proto_tree *ti, *ldss_tree; const gchar *packet_type, *packet_detail; messageID = tvb_get_ntohs (tvb, 0); digest_type = tvb_get_guint8 (tvb, 2); compression = tvb_get_guint8 (tvb, 3); cookie = tvb_get_ntohl (tvb, 4); digest = (guint8 *)tvb_memdup (NULL, tvb, 8, DIGEST_LEN); size = tvb_get_ntoh64 (tvb, 40); offset = tvb_get_ntoh64 (tvb, 48); targetTime = tvb_get_ntohl (tvb, 56); port = tvb_get_ntohs (tvb, 64); rate = tvb_get_ntohs (tvb, 66); packet_type = val_to_str_const(messageID, ldss_message_id_value, "unknown"); if (messageID == MESSAGE_ID_WILLSEND) { if (cookie == 0) { /* Shutdown: Dishonor promises from this peer. Current * implementation abuses WillSend for this. */ messageDetail = INFERRED_PEERSHUTDOWN; } else if (size == 0 && offset == 0) { /* NeedFile search failed - going to WAN */ messageDetail = INFERRED_WANDOWNLOAD; } else if (size > 0) { /* Size is known (not always the case) */ if (size == offset) { /* File is available for pull on this peer's TCP port */ messageDetail = INFERRED_OFFER; } else { /* WAN download progress announcement from this peer */ messageDetail = INFERRED_PROMISE; } } } else if (messageID == MESSAGE_ID_NEEDFILE) { messageDetail = INFERRED_SEARCH; } packet_detail = val_to_str_const(messageDetail, ldss_inferred_info, "unknown"); /* Set the info column */ col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS Broadcast (%s%s)", packet_type, packet_detail); /* If we have a non-null tree (ie we are building the proto_tree * instead of just filling out the columns), then give more detail. */ if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, (tvb_captured_length(tvb) > 72) ? tvb_captured_length(tvb) : 72, ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_broadcast); proto_tree_add_item(ldss_tree, hf_ldss_message_id, tvb, 0, 2, ENC_BIG_ENDIAN); ti = proto_tree_add_uint(ldss_tree, hf_ldss_message_detail, tvb, 0, 0, messageDetail); PROTO_ITEM_SET_GENERATED(ti); proto_tree_add_item(ldss_tree, hf_ldss_digest_type, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ldss_tree, hf_ldss_compression, tvb, 3, 1, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_cookie, tvb, 4, 4, FALSE, "0x%x%s", cookie, (cookie == 0) ? " - shutdown (promises from this peer are no longer valid)" : ""); proto_tree_add_item(ldss_tree, hf_ldss_digest, tvb, 8, DIGEST_LEN, ENC_NA); proto_tree_add_item(ldss_tree, hf_ldss_size, tvb, 40, 8, ENC_BIG_ENDIAN); proto_tree_add_item(ldss_tree, hf_ldss_offset, tvb, 48, 8, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_target_time, tvb, 56, 4, FALSE, "%d:%02d:%02d", (int)(targetTime / 3600), (int)((targetTime / 60) % 60), (int)(targetTime % 60)); proto_tree_add_item(ldss_tree, hf_ldss_reserved_1, tvb, 60, 4, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_port, tvb, 64, 2, FALSE, "%d%s", port, (messageID == MESSAGE_ID_WILLSEND && size > 0 && size == offset) ? " - file can be pulled at this TCP port" : (messageID == MESSAGE_ID_NEEDFILE ? " - file can be pushed to this TCP port" : "")); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_rate, tvb, 66, 2, FALSE, "%ld", (rate > 0) ? (long)floor(exp(rate * G_LN2 / 2048)) : 0); proto_tree_add_item(ldss_tree, hf_ldss_priority, tvb, 68, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ldss_tree, hf_ldss_property_count, tvb, 70, 2, ENC_BIG_ENDIAN); if (tvb_reported_length(tvb) > 72) { proto_tree_add_item(ldss_tree, hf_ldss_properties, tvb, 72, tvb_captured_length(tvb) - 72, ENC_NA); } } /* Finally, store the broadcast and register ourselves to dissect * any pushes or pulls that result from this broadcast. All data * is pushed/pulled over TCP using the port from the broadcast * packet's port field. * Track each by a TCP conversation with the remote end wildcarded. * The TCP conv tracks back to a broadcast conv to determine what it * is in response to. * * These steps only need to be done once per packet, so a variable * tracks the highest frame number seen. Handles the case of first frame * being frame zero. */ if (messageDetail != INFERRED_PEERSHUTDOWN && (highest_num_seen == 0 || highest_num_seen < pinfo->num)) { ldss_broadcast_t *data; /* Populate data from the broadcast */ data = wmem_new0(wmem_file_scope(), ldss_broadcast_t); data->num = pinfo->num; data->ts = pinfo->abs_ts; data->message_id = messageID; data->message_detail = messageDetail; data->port = port; data->size = size; data->offset = offset; data->compression = compression; data->file = wmem_new0(wmem_file_scope(), ldss_file_t); data->file->digest = digest; data->file->digest_type = digest_type; data->broadcaster = wmem_new0(wmem_file_scope(), ldss_broadcaster_t); copy_address(&data->broadcaster->addr, &pinfo->src); data->broadcaster->port = port; /* Dissect any future pushes/pulls */ if (port > 0) { prepare_ldss_transfer_conv(data); } /* Record that the frame was processed */ highest_num_seen = pinfo->num; } 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 */ } } }
/* Decode an EXT_FTI extension and fill FEC array */ void fec_decode_ext_fti(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint8 encoding_id) { guint64 transfer_length; fec_packet_data_t *fec_data; guint8 instance_id = 0; proto_item *ti; if (encoding_id == 6){ /* Raptor Q uses 40-bit transfer length */ transfer_length = tvb_get_ntoh40(tvb, offset+2); } else { /* Decode 48-bit length field */ transfer_length = tvb_get_ntoh48(tvb, offset+2); } if (encoding_id >= 128) { instance_id = (guint8) tvb_get_ntohs(tvb, offset+8); /* Decode FEC Instance ID */ fec_data = wmem_new0(wmem_file_scope(), fec_packet_data_t); fec_data->instance_id = instance_id; p_add_proto_data(wmem_file_scope(), pinfo, proto_rmt_fec, 0, fec_data); } if (encoding_id == 6){ /* Raptor Q uses 40-bit transfer length */ proto_tree_add_uint64(tree, hf_fti_transfer_length, tvb, offset+2, 5, transfer_length); } else { proto_tree_add_uint64(tree, hf_fti_transfer_length, tvb, offset+2, 6, transfer_length); ti = proto_tree_add_item(tree, hf_instance_id, tvb, offset+8, 2, ENC_BIG_ENDIAN); if ((encoding_id < 128) && (encoding_id != 0)) { expert_add_info(pinfo, ti, &ei_fec_encoding_id); } } switch (encoding_id) { case 1: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_num_blocks, tvb, offset+12, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_num_subblocks, tvb, offset+14, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_alignment, tvb, offset+15, 1, ENC_BIG_ENDIAN); break; case 6: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+8, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_num_blocks, tvb, offset+10, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_num_subblocks, tvb, offset+11, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_alignment, tvb, offset+13, 1, ENC_BIG_ENDIAN); break; case 0: case 2: case 128: case 130: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_source_block_length, tvb, offset+12, 4, ENC_BIG_ENDIAN); break; case 129: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_source_block_length, tvb, offset+12, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_number_encoding_symbols, tvb, offset+14, 2, ENC_BIG_ENDIAN); break; case 132: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_source_block_length, tvb, offset+12, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_number_encoding_symbols, tvb, offset+16, 4, ENC_BIG_ENDIAN); break; } }
static int dissect_ppcap_destination_address(tvbuff_t *tvb, packet_info * pinfo, proto_tree * ppcap_tree1, int offset) { int key2; guint16 msg_len; msg_len = tvb_get_ntohs(tvb, offset); proto_tree_add_item( ppcap_tree1, hf_ppcap_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; proto_tree_add_item(ppcap_tree1, hf_ppcap_destreserved, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; key2 = tvb_get_ntohs(tvb, offset); proto_tree_add_item(ppcap_tree1, hf_ppcap_address_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (key2 == 1) { ssn = tvb_get_guint8(tvb, offset); proto_tree_add_item(ppcap_tree1, hf_ppcap_ssn1, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(ppcap_tree1, hf_ppcap_spc1, tvb, offset, 3, ENC_BIG_ENDIAN); /*dst_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/ mtp3_addr_dpc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t); mtp3_addr_dpc->pc = (guint32)tvb_get_ntoh24(tvb, offset); mtp3_addr_dpc->type = ITU_STANDARD; mtp3_addr_dpc->ni = 0; SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc); if (msg_len%4) msg_len = msg_len + (4 - (msg_len%4)); offset += msg_len-1; return offset; } else if (key2 == 2) { proto_tree_add_item(ppcap_tree1, hf_ppcap_dpc, tvb, offset, 4, ENC_BIG_ENDIAN); /*dst_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/ mtp3_addr_dpc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t); mtp3_addr_dpc->pc = tvb_get_ntohl(tvb, offset); mtp3_addr_dpc->type = ITU_STANDARD; mtp3_addr_dpc->ni = 0; SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc); } else if (key2 == 3) { if (msg_len%16 != 0) { proto_tree_add_ipv4(ppcap_tree1, hf_ppcap_destination_ip_address1, tvb, offset, msg_len, tvb_get_ipv4(tvb, offset)); TVB_SET_ADDRESS(&pinfo->net_dst, AT_IPv4, tvb, offset, 4); COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst); } else { struct e_in6_addr value; tvb_get_ipv6(tvb, offset,&value); proto_tree_add_ipv6(ppcap_tree1, hf_ppcap_destination_ip_address2, tvb, offset, msg_len, &value); TVB_SET_ADDRESS(&pinfo->net_dst, AT_IPv6, tvb, offset, 6); COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst); } } else if (key2 == 4) { char *string; string = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, msg_len, ENC_UTF_8|ENC_NA); proto_tree_add_string(ppcap_tree1, hf_ppcap_destination_nodeid, tvb, offset, msg_len, string); TVB_SET_ADDRESS(&pinfo->net_dst, AT_STRINGZ, tvb, offset, msg_len); COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst); } if (msg_len%4) msg_len = msg_len+(4-(msg_len%4)); offset += msg_len; return offset; }
/* 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 = wmem_new0(wmem_packet_scope(), mtp3_tap_rec_t); gint heuristic_standard; guint8 si; mtp3_addr_pc_t* mtp3_addr_dpc; mtp3_addr_pc_t* mtp3_addr_opc; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *mtp3_item = NULL, *gen_item; proto_tree *mtp3_tree; 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; }; /* 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, mtp3_addr_opc, mtp3_addr_dpc); dissect_mtp3_routing_label(tvb, pinfo, mtp3_tree, mtp3_addr_opc, mtp3_addr_dpc); 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; }
void decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int uh_sport, int uh_dport, int uh_ulen) { tvbuff_t *next_tvb; int low_port, high_port; gint len, reported_len; udp_p_info_t *udp_p_info = NULL; /* Save curr_layer_num as it might be changed by subdissector */ guint8 curr_layer_num = pinfo->curr_layer_num; heur_dtbl_entry_t *hdtbl_entry; len = tvb_captured_length_remaining(tvb, offset); reported_len = tvb_reported_length_remaining(tvb, offset); if (uh_ulen != -1) { /* This is the length from the UDP header; the payload should be cut off at that length. (If our caller passed a value here, they are assumed to have checked that it's >= 8, and hence >= offset.) XXX - what if it's *greater* than the reported length? */ if ((uh_ulen - offset) < reported_len) reported_len = uh_ulen - offset; if (len > reported_len) len = reported_len; } next_tvb = tvb_new_subset(tvb, offset, len, reported_len); /* If the user has a "Follow UDP Stream" window loading, pass a pointer * to the payload tvb through the tap system. */ if (have_tap_listener(udp_follow_tap)) tap_queue_packet(udp_follow_tap, pinfo, next_tvb); if (pinfo->fd->flags.visited) { udp_p_info = (udp_p_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, pinfo->curr_layer_num); if (udp_p_info) { call_heur_dissector_direct(udp_p_info->heur_dtbl_entry, next_tvb, pinfo, tree, NULL); return; } } /* determine if this packet is part of a conversation and call dissector */ /* for the conversation if available */ if (try_conversation_dissector(&pinfo->dst, &pinfo->src, PT_UDP, uh_dport, uh_sport, next_tvb, pinfo, tree, NULL)) { return; } if (try_heuristic_first) { /* Do lookup with the heuristic subdissector table */ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) { if (!udp_p_info) { udp_p_info = wmem_new0(wmem_file_scope(), udp_p_info_t); udp_p_info->heur_dtbl_entry = hdtbl_entry; p_add_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, curr_layer_num, udp_p_info); } return; } } /* Do lookups with the subdissector table. We try the port number with the lower value first, followed by the port number with the higher value. This means that, for packets where a dissector is registered for *both* port numbers: 1) we pick the same dissector for traffic going in both directions; 2) we prefer the port number that's more likely to be the right one (as that prefers well-known ports to reserved ports); although there is, of course, no guarantee that any such strategy will always pick the right port number. XXX - we ignore port numbers of 0, as some dissectors use a port number of 0 to disable the port, and as RFC 768 says that the source port in UDP datagrams is optional and is 0 if not used. */ if (uh_sport > uh_dport) { low_port = uh_dport; high_port = uh_sport; } else { low_port = uh_sport; high_port = uh_dport; } if ((low_port != 0) && dissector_try_uint(udp_dissector_table, low_port, next_tvb, pinfo, tree)) return; if ((high_port != 0) && dissector_try_uint(udp_dissector_table, high_port, next_tvb, pinfo, tree)) return; if (!try_heuristic_first) { /* Do lookup with the heuristic subdissector table */ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) { if (!udp_p_info) { udp_p_info = wmem_new0(wmem_file_scope(), udp_p_info_t); udp_p_info->heur_dtbl_entry = hdtbl_entry; p_add_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, curr_layer_num, udp_p_info); } return; } } call_dissector(data_handle,next_tvb, pinfo, tree); }
gcp_msg_t* gcp_msg(packet_info* pinfo, int o, gboolean keep_persistent_data) { gcp_msg_t* m; guint32 framenum = (guint32)pinfo->fd->num; guint32 offset = (guint32)o; address* src = &(pinfo->src); address* dst = &(pinfo->dst); address* lo_addr; address* hi_addr; if (keep_persistent_data) { wmem_tree_key_t key[3]; key[0].length = 1; key[0].key = &(framenum); key[1].length = 1; key[1].key = &offset; key[2].length = 0; key[2].key =NULL; if (( m = (gcp_msg_t *)wmem_tree_lookup32_array(msgs,key) )) { m->committed = TRUE; return m; } else { m = wmem_new(wmem_file_scope(), gcp_msg_t); m->framenum = framenum; m->time = pinfo->fd->abs_ts; m->trxs = NULL; m->committed = FALSE; wmem_tree_insert32_array(msgs,key,m); } } else { m = wmem_new0(wmem_packet_scope(), gcp_msg_t); m->framenum = framenum; m->trxs = NULL; m->committed = FALSE; } if (CMP_ADDRESS(src, dst) < 0) { lo_addr = src; hi_addr = dst; } else { lo_addr = dst; hi_addr = src; } switch(lo_addr->type) { case AT_NONE: m->lo_addr = 0; m->hi_addr = 0; break; case AT_IPv4: memcpy((guint8*)&(m->hi_addr),hi_addr->data,4); memcpy((guint8*)&(m->lo_addr),lo_addr->data,4); break; case AT_SS7PC: m->hi_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)hi_addr->data); m->lo_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)lo_addr->data); break; default: /* XXX: heuristic and error prone */ m->hi_addr = g_str_hash(ep_address_to_str(hi_addr)); m->lo_addr = g_str_hash(ep_address_to_str(lo_addr)); break; } return m; }