void frame_data_set_before_dissect(frame_data *fdata, nstime_t *elapsed_time, nstime_t *first_ts, nstime_t *prev_dis_ts, nstime_t *prev_cap_ts) { /* If we don't have the time stamp of the first packet in the capture, it's because this is the first packet. Save the time stamp of this packet as the time stamp of the first packet. */ if (nstime_is_unset(first_ts)) *first_ts = fdata->abs_ts; /* if this frames is marked as a reference time frame, reset firstsec and firstusec to this frame */ if(fdata->flags.ref_time) *first_ts = fdata->abs_ts; /* If we don't have the time stamp of the previous captured packet, it's because this is the first packet. Save the time stamp of this packet as the time stamp of the previous captured packet. */ if (nstime_is_unset(prev_cap_ts)) *prev_cap_ts = fdata->abs_ts; /* Get the time elapsed between the first packet and this packet. */ nstime_delta(&fdata->rel_ts, &fdata->abs_ts, first_ts); /* If it's greater than the current elapsed time, set the elapsed time to it (we check for "greater than" so as not to be confused by time moving backwards). */ if ((gint32)elapsed_time->secs < fdata->rel_ts.secs || ((gint32)elapsed_time->secs == fdata->rel_ts.secs && (gint32)elapsed_time->nsecs < fdata->rel_ts.nsecs)) { *elapsed_time = fdata->rel_ts; } /* Get the time elapsed between the previous displayed packet and this packet. */ if (nstime_is_unset(prev_dis_ts)) /* If we don't have the time stamp of the previous displayed packet, it's because we have no displayed packets prior to this. Set the delta time to zero. */ nstime_set_zero(&fdata->del_dis_ts); else nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, prev_dis_ts); /* Get the time elapsed between the previous captured packet and this packet. */ nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, prev_cap_ts); *prev_cap_ts = fdata->abs_ts; }
void frame_data_set_before_dissect(frame_data *fdata, nstime_t *elapsed_time, nstime_t *first_ts, const frame_data *prev_dis, const frame_data *prev_cap) { /* If we don't have the time stamp of the first packet in the capture, it's because this is the first packet. Save the time stamp of this packet as the time stamp of the first packet. */ if (nstime_is_unset(first_ts)) *first_ts = fdata->abs_ts; /* if this frames is marked as a reference time frame, reset firstsec and firstusec to this frame */ if(fdata->flags.ref_time) *first_ts = fdata->abs_ts; /* Get the time elapsed between the first packet and this packet. */ nstime_delta(&fdata->rel_ts, &fdata->abs_ts, first_ts); /* If it's greater than the current elapsed time, set the elapsed time to it (we check for "greater than" so as not to be confused by time moving backwards). */ if ((gint32)elapsed_time->secs < fdata->rel_ts.secs || ((gint32)elapsed_time->secs == fdata->rel_ts.secs && (gint32)elapsed_time->nsecs < fdata->rel_ts.nsecs)) { *elapsed_time = fdata->rel_ts; } fdata->prev_dis = prev_dis; fdata->prev_cap = prev_cap; }
void frame_data_set_before_dissect(frame_data *fdata, nstime_t *elapsed_time, const frame_data **frame_ref, const frame_data *prev_dis) { nstime_t rel_ts; /* Don't have the reference frame, set to current */ if (*frame_ref == NULL) *frame_ref = fdata; /* if this frames is marked as a reference time frame, set reference frame this frame */ if(fdata->flags.ref_time) *frame_ref = fdata; /* Get the time elapsed between the first packet and this packet. */ nstime_delta(&rel_ts, &fdata->abs_ts, &(*frame_ref)->abs_ts); /* If it's greater than the current elapsed time, set the elapsed time to it (we check for "greater than" so as not to be confused by time moving backwards). */ if ((gint32)elapsed_time->secs < rel_ts.secs || ((gint32)elapsed_time->secs == rel_ts.secs && (gint32)elapsed_time->nsecs < rel_ts.nsecs)) { *elapsed_time = rel_ts; } fdata->frame_ref_num = (*frame_ref != fdata) ? (*frame_ref)->num : 0; fdata->prev_dis_num = (prev_dis) ? prev_dis->num : 0; }
static void remove_old_requests(ipmi_packet_data_t * data, const nstime_t * curr_time) { wmem_list_frame_t * iter = wmem_list_head(data->request_list); while (iter) { ipmi_request_t * rq = (ipmi_request_t *) wmem_list_frame_data(iter); ipmi_frame_data_t * frame = get_frame_data(data, rq->frame_num); nstime_t delta; /* calculate time delta */ nstime_delta(&delta, curr_time, &frame->ts); if (nstime_to_msec(&delta) > response_after_req) { wmem_list_frame_t * del = iter; /* proceed to next request */ iter = wmem_list_frame_next(iter); /* free request data */ wmem_free(wmem_file_scope(), rq); /* remove list item */ wmem_list_remove_frame(data->request_list, del); } else { break; } } }
const gchar * time_shift_settime(capture_file *cf, guint packet_num, const gchar *time_text) { nstime_t set_time, diff_time, packet_time; frame_data *fd, *packetfd; guint32 i; const gchar *err_str; if (!cf || !time_text) return "Nothing to work with."; if (packet_num < 1 || packet_num > cf->count) return "Packet out of range."; /* * Get a copy of the real time (abs_ts - shift_offset) do we can find out the * difference between the specified time and the original packet */ if ((packetfd = frame_data_sequence_find(cf->frames, packet_num)) == NULL) return "No packets found."; nstime_delta(&packet_time, &(packetfd->abs_ts), &(packetfd->shift_offset)); if ((err_str = time_string_to_nstime(time_text, &packet_time, &set_time)) != NULL) return err_str; /* Calculate difference between packet time and requested time */ nstime_delta(&diff_time, &set_time, &packet_time); /* Up to here nothing is changed */ if ((fd = frame_data_sequence_find(cf->frames, 1)) == NULL) return "No frames found."; /* Shouldn't happen */ modify_time_init(fd); /* Set everything back to the original time */ for (i = 1; i <= cf->count; i++) { if ((fd = frame_data_sequence_find(cf->frames, i)) == NULL) continue; /* Shouldn't happen */ modify_time_perform(fd, SHIFT_POS, &diff_time, SHIFT_SETTOZERO); } packet_list_queue_draw(); return NULL; }
WSLUA_METAMETHOD NSTime__sub(lua_State* L) { /* Calculates the diff of two NSTimes */ NSTime time1 = checkNSTime(L,1); NSTime time2 = checkNSTime(L,2); NSTime time3 = g_malloc (sizeof (nstime_t)); nstime_delta (time3, time1, time2); pushNSTime (L, time3); return 1; }
void frame_delta_abs_time(const frame_data *fdata, const frame_data *prev, nstime_t *delta) { if (prev) { nstime_delta(delta, &fdata->abs_ts, &prev->abs_ts); } else { /* If we don't have the time stamp of the previous packet, it's because we have no displayed/captured packets prior to this. Set the delta time to zero. */ nstime_set_zero(delta); } }
static void nlm_print_msgres_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb) { nlm_msg_res_matched_data *md; md=(nlm_msg_res_matched_data *)g_hash_table_lookup(nlm_msg_res_matched, GINT_TO_POINTER(pinfo->fd->num)); if(md){ nstime_t ns; proto_tree_add_uint(tree, hf_nlm_request_in, tvb, 0, 0, md->req_frame); nstime_delta(&ns, &pinfo->fd->abs_ts, &md->ns); proto_tree_add_time(tree, hf_nlm_time, tvb, 0, 0, &ns); } }
void frame_delta_abs_time(const struct epan_session *epan, const frame_data *fdata, guint32 prev_num, nstime_t *delta) { const nstime_t *prev_abs_ts = (prev_num) ? epan_get_frame_ts(epan, prev_num) : NULL; if (prev_abs_ts) { nstime_delta(delta, &fdata->abs_ts, prev_abs_ts); } else { /* If we don't have the time stamp of the previous packet, it's because we have no displayed/captured packets prior to this. Set the delta time to zero. */ nstime_set_zero(delta); } }
void nvme_publish_cmd_latency(proto_tree *tree, struct nvme_cmd_ctx *cmd_ctx, int field_index) { proto_item *cmd_ref_item; nstime_t ns; double cmd_latency; nstime_delta(&ns, &cmd_ctx->cmd_end_time, &cmd_ctx->cmd_start_time); cmd_latency = nstime_to_msec(&ns); cmd_ref_item = proto_tree_add_double_format_value(tree, field_index, NULL, 0, 0, cmd_latency, "%.3f ms", cmd_latency); proto_item_set_generated(cmd_ref_item); }
static rtpproxy_info_t * rtpproxy_add_tid(gboolean is_request, tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtpproxy_tree, rtpproxy_conv_info_t *rtpproxy_conv, gchar* cookie) { rtpproxy_info_t *rtpproxy_info; proto_item *pi; if (!PINFO_FD_VISITED(pinfo)) { if (is_request) { rtpproxy_info = wmem_new(wmem_file_scope(), rtpproxy_info_t); rtpproxy_info->req_frame = PINFO_FD_NUM(pinfo); rtpproxy_info->resp_frame = 0; rtpproxy_info->req_time = pinfo->fd->abs_ts; rtpproxy_info->callid = NULL; wmem_tree_insert_string(rtpproxy_conv->trans, cookie, rtpproxy_info, 0); } else { rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0); if (rtpproxy_info) { rtpproxy_info->resp_frame = PINFO_FD_NUM(pinfo); } } } else { rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0); if (rtpproxy_info && (is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame)) { nstime_t ns; pi = proto_tree_add_uint(rtpproxy_tree, is_request ? hf_rtpproxy_response_in : hf_rtpproxy_request_in, tvb, 0, 0, is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame); PROTO_ITEM_SET_GENERATED(pi); /* If reply then calculate response time */ if (!is_request) { nstime_delta(&ns, &pinfo->fd->abs_ts, &rtpproxy_info->req_time); pi = proto_tree_add_time(rtpproxy_tree, hf_rtpproxy_response_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(pi); if (nstime_cmp(&rtpproxy_timeout_ns, &ns) < 0) expert_add_info_format(pinfo, rtpproxy_tree, &ei_rtpproxy_timeout, "Response timeout %.3f seconds", nstime_to_sec(&ns)); } } } /* Could be NULL so we should check it before dereferencing */ return rtpproxy_info; }
static int dissect_ipmi_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint hf_parent_item, gint ett_tree, const ipmi_context_t * ctx) { ipmi_packet_data_t * data; ipmi_netfn_t * cmd_list; ipmi_cmd_t * cmd; proto_item * ti; proto_tree * cmd_tree = NULL, * tmp_tree; guint8 prev_level, cc_val; guint offset, siglen, is_resp; const char * cc_str, * netfn_str; /* get packet data */ data = get_packet_data(pinfo); if (!data) { return 0; } /* get prefix length */ siglen = ipmi_getsiglen(ctx->hdr.netfn); /* get response flag */ is_resp = ctx->hdr.netfn & 1; /* check message length */ if (tvb_captured_length(tvb) < ctx->hdr_len + siglen + is_resp + !(ctx->flags & IPMI_D_NO_CKS)) { /* don bother with anything */ return call_data_dissector(tvb, pinfo, tree); } /* save nest level */ prev_level = data->curr_level; /* assign next nest level */ data->curr_level = data->next_level; /* increment next nest level */ data->next_level++; /* check for the first invocation */ if (!data->curr_level) { /* get current frame data */ data->curr_frame = get_frame_data(data, pinfo->num); data->curr_frame_num = pinfo->num; /* copy frame timestamp */ memcpy(&data->curr_frame->ts, &pinfo->abs_ts, sizeof(nstime_t)); /* cache channel and direction */ data->curr_channel = ctx->hdr.channel; data->curr_dir = ctx->hdr.dir; /* remove requests which are too old */ remove_old_requests(data, &pinfo->abs_ts); } if (data->curr_level < MAX_NEST_LEVEL) { if (ctx->hdr.netfn & 1) { /* perform request/response matching */ match_request_response(data, &ctx->hdr, ctx->flags); } else { /* add request to the list for later matching */ add_request(data, &ctx->hdr); } } /* get command list by network function code */ cmd_list = ipmi_getnetfn(ctx->hdr.netfn, tvb_get_ptr(tvb, ctx->hdr_len + is_resp, siglen)); /* get command descriptor */ cmd = ipmi_getcmd(cmd_list, ctx->hdr.cmd); /* check if response */ if (is_resp) { /* get completion code */ cc_val = tvb_get_guint8(tvb, ctx->hdr_len); /* get completion code desc */ cc_str = ipmi_get_completion_code(cc_val, cmd); } else { cc_val = 0; cc_str = NULL; } /* check if not inside a message */ if (!data->curr_level) { /* add packet info */ add_command_info(pinfo, cmd, is_resp, cc_val, cc_str, ctx->flags & IPMI_D_BROADCAST ? TRUE : FALSE); } if (tree) { /* add parent node */ if (!data->curr_level) { ti = proto_tree_add_item(tree, hf_parent_item, tvb, 0, -1, ENC_NA); cmd_tree = proto_item_add_subtree(ti, ett_tree); } else { char str[ITEM_LABEL_LENGTH]; if (is_resp) { g_snprintf(str, ITEM_LABEL_LENGTH, "Rsp, %s, %s", cmd->desc, cc_str); } else { g_snprintf(str, ITEM_LABEL_LENGTH, "Req, %s", cmd->desc); } if (proto_registrar_get_ftype(hf_parent_item) == FT_STRING) { ti = proto_tree_add_string(tree, hf_parent_item, tvb, 0, -1, str); cmd_tree = proto_item_add_subtree(ti, ett_tree); } else cmd_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tree, NULL, str); } if (data->curr_level < MAX_NEST_LEVEL) { /* check if response */ if (ctx->hdr.netfn & 1) { /* get current command data */ ipmi_cmd_data_t * rs_data = data->curr_frame->cmd_data[data->curr_level]; if (rs_data->matched_frame_num) { nstime_t ns; /* add "Request to:" field */ ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_to, tvb, 0, 0, rs_data->matched_frame_num); /* mark field as a generated one */ PROTO_ITEM_SET_GENERATED(ti); /* calculate delta time */ nstime_delta(&ns, &pinfo->abs_ts, &get_frame_data(data, rs_data->matched_frame_num)->ts); /* add "Response time" field */ ti = proto_tree_add_time(cmd_tree, hf_ipmi_response_time, tvb, 0, 0, &ns); /* mark field as a generated one */ PROTO_ITEM_SET_GENERATED(ti); } } else { /* get current command data */ ipmi_cmd_data_t * rq_data = data->curr_frame->cmd_data[data->curr_level]; if (rq_data->matched_frame_num) { /* add "Response in:" field */ ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_in, tvb, 0, 0, rq_data->matched_frame_num); /* mark field as a generated one */ PROTO_ITEM_SET_GENERATED(ti); } } } /* set starting offset */ offset = 0; /* check if message is broadcast */ if (ctx->flags & IPMI_D_BROADCAST) { /* skip first byte */ offset++; } /* check if session handle is specified */ if (ctx->flags & IPMI_D_SESSION_HANDLE) { /* add session handle field */ proto_tree_add_item(cmd_tree, hf_ipmi_session_handle, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* check if responder address is specified */ if (ctx->flags & IPMI_D_TRG_SA) { /* add response address field */ proto_tree_add_item(cmd_tree, hf_ipmi_header_trg, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* get NetFn string */ netfn_str = ipmi_getnetfnname(ctx->hdr.netfn, cmd_list); /* Network function + target LUN */ tmp_tree = proto_tree_add_subtree_format(cmd_tree, tvb, offset, 1, ett_header_byte_1, NULL, "Target LUN: 0x%02x, NetFN: %s %s (0x%02x)", ctx->hdr.rs_lun, netfn_str, is_resp ? "Response" : "Request", ctx->hdr.netfn); /* add Net Fn */ proto_tree_add_uint_format(tmp_tree, hf_ipmi_header_netfn, tvb, offset, 1, ctx->hdr.netfn << 2, "NetFn: %s %s (0x%02x)", netfn_str, is_resp ? "Response" : "Request", ctx->hdr.netfn); proto_tree_add_item(tmp_tree, hf_ipmi_header_trg_lun, tvb, offset++, 1, ENC_LITTLE_ENDIAN); /* check if cks1 is specified */ if (!(ctx->flags & IPMI_D_NO_CKS)) { guint8 cks = tvb_get_guint8(tvb, offset); /* Header checksum */ if (ctx->cks1) { guint8 correct = cks - ctx->cks1; proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc, tvb, offset++, 1, cks, "0x%02x (incorrect, expected 0x%02x)", cks, correct); } else { proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc, tvb, offset++, 1, cks, "0x%02x (correct)", cks); } } /* check if request address is specified */ if (!(ctx->flags & IPMI_D_NO_RQ_SA)) { /* add request address field */ proto_tree_add_item(cmd_tree, hf_ipmi_header_src, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* check if request sequence is specified */ if (!(ctx->flags & IPMI_D_NO_SEQ)) { /* Sequence number + source LUN */ tmp_tree = proto_tree_add_subtree_format(cmd_tree, tvb, offset, 1, ett_header_byte_4, NULL, "%s: 0x%02x, SeqNo: 0x%02x", (ctx->flags & IPMI_D_TMODE) ? "Bridged" : "Source LUN", ctx->hdr.rq_lun, ctx->hdr.rq_seq); if (ctx->flags & IPMI_D_TMODE) { proto_tree_add_item(tmp_tree, hf_ipmi_header_bridged, tvb, offset, 1, ENC_LITTLE_ENDIAN); } else { proto_tree_add_item(tmp_tree, hf_ipmi_header_src_lun, tvb, offset, 1, ENC_LITTLE_ENDIAN); } /* print seq no */ proto_tree_add_item(tmp_tree, hf_ipmi_header_sequence, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* command code */ proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_command, tvb, offset++, 1, ctx->hdr.cmd, "%s (0x%02x)", cmd->desc, ctx->hdr.cmd); if (is_resp) { /* completion code */ proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_completion, tvb, offset++, 1, cc_val, "%s (0x%02x)", cc_str, cc_val); } if (siglen) { /* command prefix (if present) */ ti = proto_tree_add_item(cmd_tree, hf_ipmi_header_sig, tvb, offset, siglen, ENC_NA); proto_item_append_text(ti, " (%s)", netfn_str); } } if (tree || (cmd->flags & CMD_CALLRQ)) { /* calculate message data length */ guint data_len = tvb_captured_length(tvb) - ctx->hdr_len - siglen - (is_resp ? 1 : 0) - !(ctx->flags & IPMI_D_NO_CKS); /* create data subset */ tvbuff_t * data_tvb = tvb_new_subset_length(tvb, ctx->hdr_len + siglen + (is_resp ? 1 : 0), data_len); /* Select sub-handler */ ipmi_cmd_handler_t hnd = is_resp ? cmd->parse_resp : cmd->parse_req; if (hnd && tvb_captured_length(data_tvb)) { /* create data field */ tmp_tree = proto_tree_add_subtree(cmd_tree, data_tvb, 0, -1, ett_data, NULL, "Data"); /* save current command */ data->curr_hdr = &ctx->hdr; /* save current completion code */ data->curr_ccode = cc_val; /* call command parser */ hnd(data_tvb, pinfo, tmp_tree); } } /* check if cks2 is specified */ if (tree && !(ctx->flags & IPMI_D_NO_CKS)) { guint8 cks; /* get cks2 offset */ offset = tvb_captured_length(tvb) - 1; /* get cks2 */ cks = tvb_get_guint8(tvb, offset); /* Header checksum */ if (ctx->cks2) { guint8 correct = cks - ctx->cks2; proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc, tvb, offset, 1, cks, "0x%02x (incorrect, expected 0x%02x)", cks, correct); } else { proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc, tvb, offset, 1, cks, "0x%02x (correct)", cks); } } /* decrement next nest level */ data->next_level = data->curr_level; /* restore previous nest level */ data->curr_level = prev_level; return tvb_captured_length(tvb); }
void CaptureFile::fill_in_fdata(frame_data *fdata, gint64 offset) { const struct wtap_pkthdr *phdr = wtap_phdr(wth); guint32 cum_bytes = 0; fdata->next = NULL; fdata->prev = NULL; fdata->pfd = NULL; fdata->num = count; fdata->pkt_len = phdr->len; cum_bytes += phdr->len; fdata->cum_bytes = cum_bytes; fdata->cap_len = phdr->caplen; fdata->file_off = offset; fdata->lnk_t = phdr->pkt_encap; fdata->abs_ts.secs = phdr->ts.secs; fdata->abs_ts.nsecs = phdr->ts.nsecs; fdata->flags.passed_dfilter = 0; //fdata->flags.encoding = PACKET_CHAR_ENC_CHAR_ASCII; fdata->flags.encoding = CHAR_ASCII; fdata->flags.visited = 0; fdata->flags.marked = 0; fdata->flags.ref_time = 0; fdata->color_filter = NULL; /* If we don't have the time stamp of the first packet in the capture, it's because this is the first packet. Save the time stamp of this packet as the time stamp of the first packet. */ if (nstime_is_unset(&first_ts)) { first_ts = fdata->abs_ts; } /* If we don't have the time stamp of the previous captured packet, it's because this is the first packet. Save the time stamp of this packet as the time stamp of the previous captured packet. */ if (nstime_is_unset(&prev_cap_ts)) { prev_cap_ts = fdata->abs_ts; } /* Get the time elapsed between the first packet and this packet. */ nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts); /* If it's greater than the current elapsed time, set the elapsed time to it (we check for "greater than" so as not to be confused by time moving backwards). */ if ((gint32) elapsed_time.secs < fdata->rel_ts.secs || ((gint32) elapsed_time.secs == fdata->rel_ts.secs && (gint32) elapsed_time.nsecs < fdata->rel_ts.nsecs)) { elapsed_time = fdata->rel_ts; } /* If we don't have the time stamp of the previous displayed packet, it's because this is the first packet that's being displayed. Save the time stamp of this packet as the time stamp of the previous displayed packet. */ if (nstime_is_unset(&prev_dis_ts)) prev_dis_ts = fdata->abs_ts; /* Get the time elapsed between the previous displayed packet and this packet. */ nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts); /* Get the time elapsed between the previous captured packet and this packet. */ nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, &prev_cap_ts); prev_cap_ts = fdata->abs_ts; }
static void dissect_ata_pdu(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean response, guint32 tag) { proto_item *tmp_item; guint8 aflags; guint64 lba; ata_info_t *ata_info=NULL; conversation_t *conversation; /* only create a conversation for ATA commands */ conversation = find_or_create_conversation(pinfo); if( !(pinfo->fd->flags.visited) ){ if(!response){ ata_info_t *tmp_ata_info; /* first time we see this request so add a struct for request/response matching */ ata_info=se_new(ata_info_t); ata_info->tag=tag; ata_info->conversation=conversation; ata_info->request_frame=pinfo->fd->num; ata_info->response_frame=0; ata_info->cmd=tvb_get_guint8(tvb, offset+3); ata_info->req_time=pinfo->fd->abs_ts; tmp_ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_unmatched, ata_info); if(tmp_ata_info){ g_hash_table_remove(ata_cmd_unmatched, tmp_ata_info); } g_hash_table_insert(ata_cmd_unmatched, ata_info, ata_info); } else { ata_info_t tmp_ata_info; /* first time we see this response so see if we can match it with a request */ tmp_ata_info.tag=tag; tmp_ata_info.conversation=conversation; ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_unmatched, &tmp_ata_info); /* woo hoo we could, so no need to store this in unmatched any more, move both request and response to the matched table */ if(ata_info){ ata_info->response_frame=pinfo->fd->num; g_hash_table_remove(ata_cmd_unmatched, ata_info); g_hash_table_insert(ata_cmd_matched, GUINT_TO_POINTER(ata_info->request_frame), ata_info); g_hash_table_insert(ata_cmd_matched, GUINT_TO_POINTER(ata_info->response_frame), ata_info); } } } else { ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_matched, GUINT_TO_POINTER(pinfo->fd->num)); } if(ata_info){ if(response){ if(ata_info->request_frame){ nstime_t delta_ts; tmp_item=proto_tree_add_uint(tree, hf_aoe_response_to, tvb, 0, 0, ata_info->request_frame); PROTO_ITEM_SET_GENERATED(tmp_item); nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &ata_info->req_time); tmp_item=proto_tree_add_time(tree, hf_aoe_time, tvb, offset, 0, &delta_ts); PROTO_ITEM_SET_GENERATED(tmp_item); } } else { if(ata_info->response_frame){ tmp_item=proto_tree_add_uint(tree, hf_aoe_response_in, tvb, 0, 0, ata_info->response_frame); PROTO_ITEM_SET_GENERATED(tmp_item); } } } /* aflags */ aflags=tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_aoe_aflags_e, tvb, offset, 1, ENC_BIG_ENDIAN); if(aflags&AOE_AFLAGS_E){ proto_tree_add_item(tree, hf_aoe_aflags_d, tvb, offset, 1, ENC_BIG_ENDIAN); } if(aflags&AOE_AFLAGS_W){ proto_tree_add_item(tree, hf_aoe_aflags_a, tvb, offset, 1, ENC_BIG_ENDIAN); } proto_tree_add_item(tree, hf_aoe_aflags_w, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* err/feature */ proto_tree_add_item(tree, hf_aoe_err_feature, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* sector count */ proto_tree_add_item(tree, hf_aoe_sector_count, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* ata command/status */ if(!response){ proto_tree_add_item(tree, hf_aoe_acmd, tvb, offset, 1, ENC_BIG_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, " ATA:%s", val_to_str(tvb_get_guint8(tvb, offset), ata_cmd_vals, " Unknown ATA<0x%02x>")); } else { proto_tree_add_item(tree, hf_aoe_astatus, tvb, offset, 1, ENC_BIG_ENDIAN); if(ata_info != NULL && ata_info->request_frame){ /* we dont know what command it was unless we saw the request_frame */ tmp_item=proto_tree_add_uint(tree, hf_aoe_acmd, tvb, 0, 0, ata_info->cmd); PROTO_ITEM_SET_GENERATED(tmp_item); col_append_fstr(pinfo->cinfo, COL_INFO, " ATA:%s", val_to_str(ata_info->cmd, ata_cmd_vals, " Unknown ATA<0x%02x>")); } } offset++; /*lba probably complete wrong */ lba=tvb_get_letohs(tvb, offset+4); lba=(lba<<32)|tvb_get_letohl(tvb, offset); offset+=8; proto_tree_add_uint64(tree, hf_aoe_lba, tvb, offset-8, 6, lba); }
static gint dissect_sbc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *ti; proto_tree *sbc_tree; proto_item *pitem; proto_tree *rtree; gint offset = 0; guint8 number_of_frames; guint8 syncword; guint8 byte; guint8 blocks; guint8 channels; guint8 subbands; guint8 bitpool; guint frequency; guint8 sbc_blocks; gint sbc_channels; guint8 sbc_subbands; gint val; gint counter = 1; gint frame_length; gint expected_speed_data; gdouble frame_duration; gdouble cummulative_frame_duration = 0; bta2dp_codec_info_t *info; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SBC"); info = (bta2dp_codec_info_t *) data; ti = proto_tree_add_item(tree, proto_sbc, tvb, offset, -1, ENC_NA); sbc_tree = proto_item_add_subtree(ti, ett_sbc); proto_tree_add_item(sbc_tree, hf_sbc_fragmented, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sbc_tree, hf_sbc_starting_packet, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sbc_tree, hf_sbc_last_packet, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sbc_tree, hf_sbc_rfa, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sbc_tree, hf_sbc_number_of_frames, tvb, offset, 1, ENC_BIG_ENDIAN); number_of_frames = tvb_get_guint8(tvb, offset) & 0x0F; offset += 1; while (tvb_length_remaining(tvb, offset) > 0) { byte = tvb_get_guint8(tvb, offset + 1); frequency = (byte & 0xC0) >> 6; blocks = (byte & 0x30) >> 4; channels = (byte & 0x0C)>> 2; subbands = byte & 0x01; bitpool = tvb_get_guint8(tvb, offset + 2); if (channels == CHANNELS_MONO) sbc_channels = 1; else sbc_channels = 2; switch (frequency) { case FREQUENCY_16000: frequency = 16000; break; case FREQUENCY_32000: frequency = 32000; break; case FREQUENCY_44100: frequency = 44100; break; case FREQUENCY_48000: frequency = 48000; break; default: frequency = 0; } sbc_subbands = 4 * (subbands + 1); sbc_blocks = 4 * (blocks + 1); frame_length = (4 * sbc_subbands * sbc_channels) / 8; if (sbc_channels == 1) val = sbc_blocks * sbc_channels * bitpool; else val = (((channels == CHANNELS_JOINT_STEREO) ? 1 : 0) * sbc_subbands + sbc_blocks * bitpool); frame_length += val / 8; if (val % 8) frame_length += 1; expected_speed_data = (frame_length * frequency) / (sbc_subbands * sbc_blocks); rtree = proto_tree_add_subtree_format(sbc_tree, tvb, offset, 4 + frame_length, ett_sbc_list, NULL, "Frame: %3u/%3u", counter, number_of_frames); pitem = proto_tree_add_item(rtree, hf_sbc_syncword, tvb, offset, 1, ENC_BIG_ENDIAN); syncword = tvb_get_guint8(tvb, offset); if (syncword != 0x9C) { expert_add_info(pinfo, pitem, &ei_sbc_syncword); } offset += 1; proto_tree_add_item(rtree, hf_sbc_sampling_frequency, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(rtree, hf_sbc_blocks, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(rtree, hf_sbc_channel_mode, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(rtree, hf_sbc_allocation_method, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(rtree, hf_sbc_subbands, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rtree, hf_sbc_bitpool, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rtree, hf_sbc_crc_check, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rtree, hf_sbc_data, tvb, offset, frame_length, ENC_NA); offset += frame_length; /* TODO: expert_info for invalid CRC */ pitem = proto_tree_add_uint(rtree, hf_sbc_expected_data_speed, tvb, offset, 0, expected_speed_data / 1024); proto_item_append_text(pitem, " KiB/s"); PROTO_ITEM_SET_GENERATED(pitem); frame_duration = (((double) frame_length / (double) expected_speed_data) * 1000.0); cummulative_frame_duration += frame_duration; pitem = proto_tree_add_double(rtree, hf_sbc_frame_duration, tvb, offset, 0, frame_duration); proto_item_append_text(pitem, " ms"); PROTO_ITEM_SET_GENERATED(pitem); counter += 1; } pitem = proto_tree_add_double(sbc_tree, hf_sbc_cummulative_frame_duration, tvb, offset, 0, cummulative_frame_duration); proto_item_append_text(pitem, " ms"); PROTO_ITEM_SET_GENERATED(pitem); if (info && info->previous_media_packet_info && info->current_media_packet_info) { nstime_t delta; nstime_delta(&delta, &pinfo->fd->abs_ts, &info->previous_media_packet_info->abs_ts); pitem = proto_tree_add_double(sbc_tree, hf_sbc_delta_time, tvb, offset, 0, nstime_to_msec(&delta)); proto_item_append_text(pitem, " ms"); PROTO_ITEM_SET_GENERATED(pitem); nstime_delta(&delta, &pinfo->fd->abs_ts, &info->previous_media_packet_info->first_abs_ts); pitem = proto_tree_add_double(sbc_tree, hf_sbc_delta_time_from_the_beginning, tvb, offset, 0, nstime_to_msec(&delta)); proto_item_append_text(pitem, " ms"); PROTO_ITEM_SET_GENERATED(pitem); if (!pinfo->fd->flags.visited) info->current_media_packet_info->cummulative_frame_duration += cummulative_frame_duration; pitem = proto_tree_add_double(sbc_tree, hf_sbc_cummulative_duration, tvb, offset, 0, info->previous_media_packet_info->cummulative_frame_duration); proto_item_append_text(pitem, " ms"); PROTO_ITEM_SET_GENERATED(pitem); pitem = proto_tree_add_double(sbc_tree, hf_sbc_diff, tvb, offset, 0, info->previous_media_packet_info->cummulative_frame_duration - nstime_to_msec(&delta)); proto_item_append_text(pitem, " ms"); PROTO_ITEM_SET_GENERATED(pitem); } /* TODO: more precise dissection: blocks, channels, subbands, padding */ col_append_fstr(pinfo->cinfo, COL_INFO, " Frames=%u", number_of_frames); return offset; }
/* * Function for the PANA PDU dissector. */ static void dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *pana_tree = NULL; guint16 flags; guint16 msg_type; guint32 msg_length; guint32 avp_length; guint32 seq_num; conversation_t *conversation; pana_conv_info_t *pana_info; pana_transaction_t *pana_trans; int offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PANA"); col_clear(pinfo->cinfo, COL_INFO); /* Get message length, type and flags */ msg_length = tvb_get_ntohs(tvb, 2); flags = tvb_get_ntohs(tvb, 4); msg_type = tvb_get_ntohs(tvb, 6); seq_num = tvb_get_ntohl(tvb, 12); avp_length = msg_length - 16; col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s-%s", val_to_str(msg_type, msg_type_names, "Unknown (%d)"), val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)")); /* Make the protocol tree */ if (tree) { proto_item *ti; ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, ENC_NA); pana_tree = proto_item_add_subtree(ti, ett_pana); } /* * We need to track some state for this protocol on a per conversation * basis so we can do neat things like request/response tracking */ conversation = find_or_create_conversation(pinfo); /* * Do we already have a state structure for this conv */ pana_info = (pana_conv_info_t *)conversation_get_proto_data(conversation, proto_pana); if (!pana_info) { /* No. Attach that information to the conversation, and add * it to the list of information structures. */ pana_info = wmem_new(wmem_file_scope(), pana_conv_info_t); pana_info->pdus=wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); conversation_add_proto_data(conversation, proto_pana, pana_info); } if(!pinfo->fd->flags.visited){ if(flags&PANA_FLAG_R){ /* This is a request */ pana_trans=wmem_new(wmem_file_scope(), pana_transaction_t); pana_trans->req_frame=pinfo->num; pana_trans->rep_frame=0; pana_trans->req_time=pinfo->abs_ts; wmem_map_insert(pana_info->pdus, GUINT_TO_POINTER(seq_num), (void *)pana_trans); } else { pana_trans=(pana_transaction_t *)wmem_map_lookup(pana_info->pdus, GUINT_TO_POINTER(seq_num)); if(pana_trans){ pana_trans->rep_frame=pinfo->num; } } } else { pana_trans=(pana_transaction_t *)wmem_map_lookup(pana_info->pdus, GUINT_TO_POINTER(seq_num)); } if(!pana_trans){ /* create a "fake" pana_trans structure */ pana_trans=wmem_new(wmem_packet_scope(), pana_transaction_t); pana_trans->req_frame=0; pana_trans->rep_frame=0; pana_trans->req_time=pinfo->abs_ts; } /* print state tracking in the tree */ if(flags&PANA_FLAG_R){ /* This is a request */ if(pana_trans->rep_frame){ proto_item *it; it=proto_tree_add_uint(pana_tree, hf_pana_response_in, tvb, 0, 0, pana_trans->rep_frame); PROTO_ITEM_SET_GENERATED(it); } } else { /* This is a reply */ if(pana_trans->req_frame){ proto_item *it; nstime_t ns; it=proto_tree_add_uint(pana_tree, hf_pana_response_to, tvb, 0, 0, pana_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); nstime_delta(&ns, &pinfo->abs_ts, &pana_trans->req_time); it=proto_tree_add_time(pana_tree, hf_pana_response_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(it); } } /* Reserved field */ proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 2, ENC_NA); offset += 2; /* Length */ proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Flags */ dissect_pana_flags(pana_tree, tvb, offset, flags); offset += 2; /* Message Type */ proto_tree_add_uint_format_value(pana_tree, hf_pana_msg_type, tvb, offset, 2, msg_type, "%s-%s (%d)", val_to_str(msg_type, msg_type_names, "Unknown (%d)"), val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"), msg_type); offset += 2; /* Session ID */ proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Sequence Number */ proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* AVPs */ if(avp_length != 0){ tvbuff_t *avp_tvb; proto_tree *avp_tree; avp_tvb = tvb_new_subset_length(tvb, offset, avp_length); avp_tree = proto_tree_add_subtree(pana_tree, tvb, offset, avp_length, ett_pana_avp, NULL, "Attribute Value Pairs"); dissect_avps(avp_tvb, pinfo, avp_tree); } }
/* 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 ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi) { proto_item *hidden_item; conversation_t* conversation = NULL; h225ras_call_info_key h225ras_call_key; h225ras_call_t *h225ras_call = NULL; nstime_t delta; guint msg_category; if(pi->msg_type == H225_RAS && pi->msg_tag < 21) { /* make RAS request/response matching only for tags from 0 to 20 for now */ msg_category = pi->msg_tag / 3; if(pi->msg_tag % 3 == 0) { /* Request Message */ conversation = find_or_create_conversation(pinfo); /* prepare the key data */ h225ras_call_key.reqSeqNum = pi->requestSeqNum; h225ras_call_key.conversation = conversation; /* look up the request */ h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category); if (h225ras_call != NULL) { /* We've seen requests with this reqSeqNum, with the same source and destination, before - do we have *this* request already? */ /* Walk through list of ras requests with identical keys */ do { if (pinfo->fd->num == h225ras_call->req_num) { /* We have seen this request before -> do nothing */ break; } /* if end of list is reached, exit loop and decide if request is duplicate or not. */ if (h225ras_call->next_call == NULL) { if ( (pinfo->fd->num > h225ras_call->rsp_num && h225ras_call->rsp_num != 0 && pinfo->fd->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_RESPONDED_CALL) ) ||(pinfo->fd->num > h225ras_call->req_num && h225ras_call->rsp_num == 0 && pinfo->fd->abs_ts.secs > (h225ras_call->req_time.secs + THRESHOLD_REPEATED_NOT_RESPONDED_CALL) ) ) { /* if last request has been responded and this request appears after last response (has bigger frame number) and last request occured more than 300 seconds ago, or if last request hasn't been responded and this request appears after last request (has bigger frame number) and last request occured more than 1800 seconds ago, we decide that we have a new request */ /* Append new ras call to list */ h225ras_call = append_h225ras_call(h225ras_call, pinfo, &pi->guid, msg_category); } else { /* No, so it's a duplicate request. Mark it as such. */ pi->is_duplicate = TRUE; hidden_item = proto_tree_add_uint(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum); PROTO_ITEM_SET_HIDDEN(hidden_item); } break; } h225ras_call = h225ras_call->next_call; } while (h225ras_call != NULL ); } else { h225ras_call = new_h225ras_call(&h225ras_call_key, pinfo, &pi->guid, msg_category); } /* add link to response frame, if available */ if(h225ras_call && h225ras_call->rsp_num != 0){ proto_item *ti = proto_tree_add_uint_format(tree, hf_h225_ras_rsp_frame, tvb, 0, 0, h225ras_call->rsp_num, "The response to this request is in frame %u", h225ras_call->rsp_num); PROTO_ITEM_SET_GENERATED(ti); } /* end of request message handling*/ } else { /* Confirm or Reject Message */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (conversation != NULL) { /* look only for matching request, if matching conversation is available. */ h225ras_call_key.reqSeqNum = pi->requestSeqNum; h225ras_call_key.conversation = conversation; h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category); if(h225ras_call) { /* find matching ras_call in list of ras calls with identical keys */ do { if (pinfo->fd->num == h225ras_call->rsp_num) { /* We have seen this response before -> stop now with matching ras call */ break; } /* Break when list end is reached */ if(h225ras_call->next_call == NULL) { break; } h225ras_call = h225ras_call->next_call; } while (h225ras_call != NULL) ; if (!h225ras_call) { return; } /* if this is an ACF, ARJ or DCF, DRJ, give guid to tap and make it filterable */ if (msg_category == 3 || msg_category == 5) { pi->guid = h225ras_call->guid; hidden_item = proto_tree_add_guid(tree, hf_h225_guid, tvb, 0, GUID_LEN, &pi->guid); PROTO_ITEM_SET_HIDDEN(hidden_item); } if (h225ras_call->rsp_num == 0) { /* We have not yet seen a response to that call, so this must be the first response; remember its frame number. */ h225ras_call->rsp_num = pinfo->fd->num; } else { /* We have seen a response to this call - but was it *this* response? */ if (h225ras_call->rsp_num != pinfo->fd->num) { /* No, so it's a duplicate response. Mark it as such. */ pi->is_duplicate = TRUE; hidden_item = proto_tree_add_uint(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum); PROTO_ITEM_SET_HIDDEN(hidden_item); } } if(h225ras_call->req_num != 0){ proto_item *ti; h225ras_call->responded = TRUE; pi->request_available = TRUE; /* Indicate the frame to which this is a reply. */ ti = proto_tree_add_uint_format(tree, hf_h225_ras_req_frame, tvb, 0, 0, h225ras_call->req_num, "This is a response to a request in frame %u", h225ras_call->req_num); PROTO_ITEM_SET_GENERATED(ti); /* Calculate RAS Service Response Time */ nstime_delta(&delta, &pinfo->fd->abs_ts, &h225ras_call->req_time); pi->delta_time = delta; /* give it to tap */ /* display Ras Service Response Time and make it filterable */ ti = proto_tree_add_time(tree, hf_h225_ras_deltatime, tvb, 0, 0, &(pi->delta_time)); PROTO_ITEM_SET_GENERATED(ti); } } } } } }
static void dissect_nbd_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { guint32 magic, error, packet; guint32 handle[2]; guint64 from; int offset=0; proto_tree *tree=NULL; proto_item *item=NULL; conversation_t *conversation; nbd_conv_info_t *nbd_info; nbd_transaction_t *nbd_trans=NULL; emem_tree_key_t hkey[3]; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBD"); col_clear(pinfo->cinfo, COL_INFO); item = proto_tree_add_item(parent_tree, proto_nbd, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_nbd); magic=tvb_get_ntohl(tvb, offset); proto_tree_add_item(tree, hf_nbd_magic, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; /* grab what we need to do the request/response matching */ switch(magic){ case NBD_REQUEST_MAGIC: case NBD_RESPONSE_MAGIC: handle[0]=tvb_get_ntohl(tvb, offset+4); handle[1]=tvb_get_ntohl(tvb, offset+8); break; default: return; } conversation = find_or_create_conversation(pinfo); /* * Do we already have a state structure for this conv */ nbd_info = (nbd_conv_info_t *)conversation_get_proto_data(conversation, proto_nbd); if (!nbd_info) { /* No. Attach that information to the conversation, and add * it to the list of information structures. */ nbd_info = se_new(nbd_conv_info_t); nbd_info->unacked_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "nbd_unacked_pdus"); nbd_info->acked_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "nbd_acked_pdus"); conversation_add_proto_data(conversation, proto_nbd, nbd_info); } if(!pinfo->fd->flags.visited){ if(magic==NBD_REQUEST_MAGIC){ /* This is a request */ nbd_trans=se_new(nbd_transaction_t); nbd_trans->req_frame=pinfo->fd->num; nbd_trans->rep_frame=0; nbd_trans->req_time=pinfo->fd->abs_ts; nbd_trans->type=tvb_get_ntohl(tvb, offset); nbd_trans->datalen=tvb_get_ntohl(tvb, offset+20); hkey[0].length=2; hkey[0].key=handle; hkey[1].length=0; se_tree_insert32_array(nbd_info->unacked_pdus, hkey, (void *)nbd_trans); } else if(magic==NBD_RESPONSE_MAGIC){ hkey[0].length=2; hkey[0].key=handle; hkey[1].length=0; nbd_trans=(nbd_transaction_t *)se_tree_lookup32_array(nbd_info->unacked_pdus, hkey); if(nbd_trans){ nbd_trans->rep_frame=pinfo->fd->num; hkey[0].length=1; hkey[0].key=&nbd_trans->rep_frame; hkey[1].length=2; hkey[1].key=handle; hkey[2].length=0; se_tree_insert32_array(nbd_info->acked_pdus, hkey, (void *)nbd_trans); hkey[0].length=1; hkey[0].key=&nbd_trans->req_frame; hkey[1].length=2; hkey[1].key=handle; hkey[2].length=0; se_tree_insert32_array(nbd_info->acked_pdus, hkey, (void *)nbd_trans); } } } else { packet=pinfo->fd->num; hkey[0].length=1; hkey[0].key=&packet; hkey[1].length=2; hkey[1].key=handle; hkey[2].length=0; nbd_trans=(nbd_transaction_t *)se_tree_lookup32_array(nbd_info->acked_pdus, hkey); } /* The bloody handles are reused !!! eventhough they are 64 bits. * So we must verify we got the "correct" one */ if( (magic==NBD_RESPONSE_MAGIC) && (nbd_trans) && (pinfo->fd->num<nbd_trans->req_frame) ){ /* must have been the wrong one */ nbd_trans=NULL; } if(!nbd_trans){ /* create a "fake" nbd_trans structure */ nbd_trans=ep_new(nbd_transaction_t); nbd_trans->req_frame=0; nbd_trans->rep_frame=0; nbd_trans->req_time=pinfo->fd->abs_ts; nbd_trans->type=0xff; nbd_trans->datalen=0; } /* print state tracking in the tree */ if(magic==NBD_REQUEST_MAGIC){ /* This is a request */ if(nbd_trans->rep_frame){ proto_item *it; it=proto_tree_add_uint(tree, hf_nbd_response_in, tvb, 0, 0, nbd_trans->rep_frame); PROTO_ITEM_SET_GENERATED(it); } } else if(magic==NBD_RESPONSE_MAGIC){ /* This is a reply */ if(nbd_trans->req_frame){ proto_item *it; nstime_t ns; it=proto_tree_add_uint(tree, hf_nbd_response_to, tvb, 0, 0, nbd_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); nstime_delta(&ns, &pinfo->fd->abs_ts, &nbd_trans->req_time); it=proto_tree_add_time(tree, hf_nbd_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(it); } } switch(magic){ case NBD_REQUEST_MAGIC: proto_tree_add_item(tree, hf_nbd_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; proto_tree_add_item(tree, hf_nbd_handle, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; from=tvb_get_ntoh64(tvb, offset); proto_tree_add_item(tree, hf_nbd_from, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; proto_tree_add_item(tree, hf_nbd_len, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; switch(nbd_trans->type){ case NBD_CMD_WRITE: col_add_fstr(pinfo->cinfo, COL_INFO, "Write Request Offset:0x%" G_GINT64_MODIFIER "x Length:%d", from, nbd_trans->datalen); break; case NBD_CMD_READ: col_add_fstr(pinfo->cinfo, COL_INFO, "Read Request Offset:0x%" G_GINT64_MODIFIER "x Length:%d", from, nbd_trans->datalen); break; case NBD_CMD_DISC: col_set_str(pinfo->cinfo, COL_INFO, "Disconnect Request"); break; } if(nbd_trans->type==NBD_CMD_WRITE){ proto_tree_add_item(tree, hf_nbd_data, tvb, offset, nbd_trans->datalen, ENC_NA); } break; case NBD_RESPONSE_MAGIC: item=proto_tree_add_uint(tree, hf_nbd_type, tvb, 0, 0, nbd_trans->type); PROTO_ITEM_SET_GENERATED(item); error=tvb_get_ntohl(tvb, offset); proto_tree_add_item(tree, hf_nbd_error, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; proto_tree_add_item(tree, hf_nbd_handle, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; col_add_fstr(pinfo->cinfo, COL_INFO, "%s Response Error:%d", (nbd_trans->type==NBD_CMD_WRITE)?"Write":"Read", error); if(nbd_trans->type==NBD_CMD_READ){ proto_tree_add_item(tree, hf_nbd_data, tvb, offset, nbd_trans->datalen, ENC_NA); } break; } return; }
static void adwin_request_response_handling(tvbuff_t *tvb, packet_info *pinfo, proto_tree *adwin_tree, guint32 seq_num, adwin_direction_t direction) { conversation_t *conversation; adwin_conv_info_t *adwin_info; adwin_transaction_t *adwin_trans; /* * Find or create a conversation for this connection. */ conversation = find_or_create_conversation(pinfo); /* * Do we already have a state structure for this conv */ adwin_info = (adwin_conv_info_t *)conversation_get_proto_data(conversation, proto_adwin); if (!adwin_info) { /* * No. Attach that information to the conversation, and add * it to the list of information structures. */ adwin_info = se_new(adwin_conv_info_t); adwin_info->pdus = se_tree_create_non_persistent( EMEM_TREE_TYPE_RED_BLACK, "adwin_pdus"); conversation_add_proto_data(conversation, proto_adwin, adwin_info); } if (!pinfo->fd->flags.visited) { if (direction == ADWIN_REQUEST) { /* This is a request */ adwin_trans = se_new(adwin_transaction_t); adwin_trans->req_frame = pinfo->fd->num; adwin_trans->rep_frame = 0; adwin_trans->req_time = pinfo->fd->abs_ts; se_tree_insert32(adwin_info->pdus, seq_num, (void *)adwin_trans); } else { adwin_trans = (adwin_transaction_t *)se_tree_lookup32(adwin_info->pdus, seq_num); if (adwin_trans) { adwin_trans->rep_frame = pinfo->fd->num; } } } else { adwin_trans = (adwin_transaction_t *)se_tree_lookup32(adwin_info->pdus, seq_num); } if (!adwin_trans) { /* create a "fake" adwin_trans structure */ adwin_trans = ep_new(adwin_transaction_t); adwin_trans->req_frame = 0; adwin_trans->rep_frame = 0; adwin_trans->req_time = pinfo->fd->abs_ts; } /* print state tracking in the tree */ if (direction == ADWIN_REQUEST) { /* This is a request */ if (adwin_trans->rep_frame) { proto_item *it; it = proto_tree_add_uint(adwin_tree, hf_adwin_response_in, tvb, 0, 0, adwin_trans->rep_frame); PROTO_ITEM_SET_GENERATED(it); } } else { /* This is a reply */ if (adwin_trans->req_frame) { proto_item *it; nstime_t ns; it = proto_tree_add_uint(adwin_tree, hf_adwin_response_to, tvb, 0, 0, adwin_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); nstime_delta(&ns, &pinfo->fd->abs_ts, &adwin_trans->req_time); it = proto_tree_add_time(adwin_tree, hf_adwin_response_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(it); } } }
static ros_call_response_t * ros_match_call_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint invokeId, gboolean isInvoke) { ros_call_response_t rcr, *rcrp=NULL; ros_conv_info_t *ros_info = ros_info_items; /* first see if we have already matched this */ rcr.invokeId=invokeId; rcr.is_request = isInvoke; if(isInvoke) { rcr.req_frame=pinfo->fd->num; rcr.rep_frame=0; } else { rcr.req_frame=0; rcr.rep_frame=pinfo->fd->num; } rcrp=(ros_call_response_t *)g_hash_table_lookup(ros_info->matched, &rcr); if(rcrp) { /* we have found a match */ rcrp->is_request=rcr.is_request; } else { /* we haven't found a match - try and match it up */ if(isInvoke) { /* this a a request - add it to the unmatched list */ /* check that we dont already have one of those in the unmatched list and if so remove it */ rcr.invokeId=invokeId; rcrp=(ros_call_response_t *)g_hash_table_lookup(ros_info->unmatched, &rcr); if(rcrp){ g_hash_table_remove(ros_info->unmatched, rcrp); } /* if we cant reuse the old one, grab a new chunk */ if(!rcrp){ rcrp=wmem_new(wmem_file_scope(), ros_call_response_t); } rcrp->invokeId=invokeId; rcrp->req_frame=pinfo->fd->num; rcrp->req_time=pinfo->fd->abs_ts; rcrp->rep_frame=0; rcrp->is_request=TRUE; g_hash_table_insert(ros_info->unmatched, rcrp, rcrp); return NULL; } else { /* this is a result - it should be in our unmatched list */ rcr.invokeId=invokeId; rcrp=(ros_call_response_t *)g_hash_table_lookup(ros_info->unmatched, &rcr); if(rcrp){ if(!rcrp->rep_frame){ g_hash_table_remove(ros_info->unmatched, rcrp); rcrp->rep_frame=pinfo->fd->num; rcrp->is_request=FALSE; g_hash_table_insert(ros_info->matched, rcrp, rcrp); } } } } if(rcrp){ /* we have found a match */ proto_item *item = NULL; if(rcrp->is_request){ item=proto_tree_add_uint(tree, hf_ros_response_in, tvb, 0, 0, rcrp->rep_frame); PROTO_ITEM_SET_GENERATED (item); } else { nstime_t ns; item=proto_tree_add_uint(tree, hf_ros_response_to, tvb, 0, 0, rcrp->req_frame); PROTO_ITEM_SET_GENERATED (item); nstime_delta(&ns, &pinfo->fd->abs_ts, &rcrp->req_time); item=proto_tree_add_time(tree, hf_ros_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED (item); } } return rcrp; }
/* * Function for the PANA PDU dissector. */ static void dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *pana_tree=NULL; proto_tree *avp_tree=NULL; proto_item *ti=NULL; proto_item *avp_item=NULL; tvbuff_t *avp_tvb; guint16 flags = 0; guint16 msg_type; gint16 msg_length; gint16 avp_length; guint32 session_id; guint32 seq_num; conversation_t *conversation; pana_conv_info_t *pana_info; pana_transaction_t *pana_trans; int offset = 0; /* Get message length, type and flags */ msg_length = tvb_get_ntohs(tvb, 2); flags = tvb_get_ntohs(tvb, 4); msg_type = tvb_get_ntohs(tvb, 6); session_id = tvb_get_ntohl(tvb, 8); seq_num = tvb_get_ntohl(tvb, 12); avp_length = msg_length-16; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PANA"); if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s-%s", val_to_str(msg_type, msg_type_names, "Unknown (%d)"), val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)")); } /* Make the protocol tree */ if (tree) { ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, FALSE); pana_tree = proto_item_add_subtree(ti, ett_pana); } /* * We need to track some state for this protocol on a per conversation * basis so we can do neat things like request/response tracking */ /* * Do we have a conversation for this connection? */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (conversation == NULL) { /* We don't yet have a conversation, so create one. */ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } /* * Do we already have a state structure for this conv */ pana_info = conversation_get_proto_data(conversation, proto_pana); if (!pana_info) { /* No. Attach that information to the conversation, and add * it to the list of information structures. */ pana_info = se_alloc(sizeof(pana_conv_info_t)); pana_info->pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "pana_pdus"); conversation_add_proto_data(conversation, proto_pana, pana_info); } if(!pinfo->fd->flags.visited){ if(flags&PANA_FLAG_R){ /* This is a request */ pana_trans=se_alloc(sizeof(pana_transaction_t)); pana_trans->req_frame=pinfo->fd->num; pana_trans->rep_frame=0; pana_trans->req_time=pinfo->fd->abs_ts; se_tree_insert32(pana_info->pdus, seq_num, (void *)pana_trans); } else { pana_trans=se_tree_lookup32(pana_info->pdus, seq_num); if(pana_trans){ pana_trans->rep_frame=pinfo->fd->num; } } } else { pana_trans=se_tree_lookup32(pana_info->pdus, seq_num); } if(!pana_trans){ /* create a "fake" pana_trans structure */ pana_trans=ep_alloc(sizeof(pana_transaction_t)); pana_trans->req_frame=0; pana_trans->rep_frame=0; pana_trans->req_time=pinfo->fd->abs_ts; } /* print state tracking in the tree */ if(flags&PANA_FLAG_R){ /* This is a request */ if(pana_trans->rep_frame){ proto_item *it; it=proto_tree_add_uint(pana_tree, hf_pana_response_in, tvb, 0, 0, pana_trans->rep_frame); PROTO_ITEM_SET_GENERATED(it); } } else { /* This is a reply */ if(pana_trans->req_frame){ proto_item *it; nstime_t ns; it=proto_tree_add_uint(pana_tree, hf_pana_response_to, tvb, 0, 0, pana_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); nstime_delta(&ns, &pinfo->fd->abs_ts, &pana_trans->req_time); it=proto_tree_add_time(pana_tree, hf_pana_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(it); } } /* Reserved field */ proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 2, FALSE); offset += 2; /* Length */ proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, FALSE); offset += 2; /* Flags */ dissect_pana_flags(pana_tree, tvb, offset, flags); offset += 2; /* Message Type */ proto_tree_add_uint_format_value(pana_tree, hf_pana_msg_type, tvb, offset, 2, msg_type, "%s-%s (%d)", val_to_str(msg_type, msg_type_names, "Unknown (%d)"), val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"), msg_type); offset += 2; /* Session ID */ proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, FALSE); offset += 4; /* Sequence Number */ proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, FALSE); offset += 4; /* AVPs */ if(avp_length>0){ avp_tvb = tvb_new_subset(tvb, offset, avp_length, avp_length); avp_item = proto_tree_add_text(pana_tree, tvb, offset, avp_length, "Attribute Value Pairs"); avp_tree = proto_item_add_subtree(avp_item, ett_pana_avp); if (avp_tree != NULL) { dissect_avps(avp_tvb, pinfo, avp_tree); } } }
static gboolean is_duplicate_rel_time(guint8* fd, guint32 len, const nstime_t *current) { int i; md5_state_t ms; cur_dup_entry++; if (cur_dup_entry >= dup_window) cur_dup_entry = 0; /* Calculate our digest */ md5_init(&ms); md5_append(&ms, fd, len); md5_finish(&ms, fd_hash[cur_dup_entry].digest); fd_hash[cur_dup_entry].len = len; fd_hash[cur_dup_entry].time.secs = current->secs; fd_hash[cur_dup_entry].time.nsecs = current->nsecs; /* * Look for relative time related duplicates. * This is hopefully a reasonably efficient mechanism for * finding duplicates by rel time in the fd_hash[] cache. * We check starting from the most recently added hash * entries and work backwards towards older packets. * This approach allows the dup test to be terminated * when the relative time of a cached entry is found to * be beyond the dup time window. * * Of course this assumes that the input trace file is * "well-formed" in the sense that the packet timestamps are * in strict chronologically increasing order (which is NOT * always the case!!). * * The fd_hash[] table was deliberatly created large (1,000,000). * Looking for time related duplicates in large trace files with * non-fractional dup time window values can potentially take * a long time to complete. */ for (i = cur_dup_entry - 1;; i--) { nstime_t delta; int cmp; if (i < 0) { i = dup_window - 1; } if (i == cur_dup_entry) { /* * We've decremented back to where we started. * Check no more! */ break; } if (nstime_is_unset(&(fd_hash[i].time))) { /* * We've decremented to an unused fd_hash[] entry. * Check no more! */ break; } nstime_delta(&delta, current, &fd_hash[i].time); if(delta.secs < 0 || delta.nsecs < 0) { /* * A negative delta implies that the current packet * has an absolute timestamp less than the cached packet * that it is being compared to. This is NOT a normal * situation since trace files usually have packets in * chronological order (oldest to newest). * * There are several possible ways to deal with this: * 1. 'continue' dup checking with the next cached frame. * 2. 'break' from looking for a duplicate of the current frame. * 3. Take the absolute value of the delta and see if that * falls within the specifed dup time window. * * Currently this code does option 1. But it would pretty * easy to add yet-another-editcap-option to select one of * the other behaviors for dealing with out-of-sequence * packets. */ continue; } cmp = nstime_cmp(&delta, &relative_time_window); if(cmp > 0) { /* * The delta time indicates that we are now looking at * cached packets beyond the specified dup time window. * Check no more! */ break; } else if (fd_hash[i].len == fd_hash[cur_dup_entry].len && memcmp(fd_hash[i].digest, fd_hash[cur_dup_entry].digest, 16) == 0) { return TRUE; } } return FALSE; }
static void request_response_handling(tvbuff_t *tvb, packet_info *pinfo, proto_tree *djiuav_tree, guint32 offset) { conversation_t *conversation; djiuav_conv_info_t *djiuav_info; djiuav_transaction_t *djiuav_trans; guint16 seq_no; gboolean is_cmd; guint8 packet_type; is_cmd = (pinfo->match_uint == pinfo->destport); seq_no = tvb_get_letohs(tvb, offset + 4); packet_type = tvb_get_guint8(tvb, offset + 6); conversation = find_or_create_conversation(pinfo); djiuav_info = (djiuav_conv_info_t *)conversation_get_proto_data(conversation, proto_djiuav); if (!djiuav_info) { djiuav_info = wmem_new(wmem_file_scope(), djiuav_conv_info_t); djiuav_info->pdus=wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); conversation_add_proto_data(conversation, proto_djiuav, djiuav_info); } if (!pinfo->fd->flags.visited) { if (is_cmd) { djiuav_trans=wmem_new(wmem_file_scope(), djiuav_transaction_t); djiuav_trans->request_frame=pinfo->fd->num; djiuav_trans->reply_frame=0; djiuav_trans->request_time=pinfo->fd->abs_ts; djiuav_trans->seqno=seq_no; djiuav_trans->command=packet_type; wmem_map_insert(djiuav_info->pdus, GUINT_TO_POINTER((guint)seq_no), (void *)djiuav_trans); } else { djiuav_trans=(djiuav_transaction_t *)wmem_map_lookup(djiuav_info->pdus, GUINT_TO_POINTER((guint)seq_no)); if (djiuav_trans) { /* Special case: djiuav seems to send 0x24 replies with seqno 0 and without a request */ if (djiuav_trans->reply_frame == 0) djiuav_trans->reply_frame=pinfo->fd->num; } } } else { djiuav_trans=(djiuav_transaction_t *)wmem_map_lookup(djiuav_info->pdus, GUINT_TO_POINTER((guint)seq_no)); } /* djiuav_trans may be 0 in case it's a reply without a matching request */ if (djiuav_tree && djiuav_trans) { if (is_cmd) { if (djiuav_trans->reply_frame) { proto_item *it; it = proto_tree_add_uint(djiuav_tree, hf_djiuav_response_in, tvb, 0, 0, djiuav_trans->reply_frame); PROTO_ITEM_SET_GENERATED(it); } } else { if (djiuav_trans->request_frame) { proto_item *it; nstime_t ns; it = proto_tree_add_uint(djiuav_tree, hf_djiuav_response_to, tvb, 0, 0, djiuav_trans->request_frame); PROTO_ITEM_SET_GENERATED(it); nstime_delta(&ns, &pinfo->fd->abs_ts, &djiuav_trans->request_time); it = proto_tree_add_time(djiuav_tree, hf_djiuav_response_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(it); } } } }