/* set's the PI_ flags to a protocol item * (and its parent items till the toplevel) */ static void expert_set_item_flags(proto_item *pi, int group, int severity) { if (proto_item_set_expert_flags(pi, group, severity)) { /* propagate till toplevel item */ pi = proto_item_get_parent(pi); expert_set_item_flags(pi, group, severity); } }
void gcp_analyze_msg(proto_tree* gcp_tree, tvbuff_t* gcp_tvb, gcp_msg_t* m, gcp_hf_ett_t* ids) { gcp_trx_msg_t* t; gcp_ctxs_t contexts = {NULL,NULL}; gcp_ctxs_t* ctx_node; gcp_cmd_msg_t* c; for (t = m->trxs; t; t = t->next) { for (c = t->trx->cmds; c; c = c->next) { gcp_ctx_t* ctx = c->cmd->ctx; for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) { if (ctx_node->ctx->id == ctx->id) { break; } } if (! ctx_node) { ctx_node = ep_new(gcp_ctxs_t); ctx_node->ctx = ctx; ctx_node->next = contexts.next; contexts.next = ctx_node; } } } for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) { gcp_ctx_t* ctx = ctx_node->ctx; proto_item* ctx_item = proto_tree_add_uint(gcp_tree,ids->hf.ctx,gcp_tvb,0,0,ctx->id); proto_tree* ctx_tree = proto_item_add_subtree(ctx_item,ids->ett.ctx); gcp_terms_t *ctx_term; PROTO_ITEM_SET_GENERATED(ctx_item); if (ctx->cmds) { proto_item* history_item = proto_tree_add_text(ctx_tree,gcp_tvb,0,0,"[ Command History ]"); proto_tree* history_tree = proto_item_add_subtree(history_item,ids->ett.ctx_cmds); for (c = ctx->cmds; c; c = c->next) { proto_item* cmd_item = proto_tree_add_uint(history_tree,ids->hf.ctx_cmd,gcp_tvb,0,0,c->cmd->msg->framenum); if (c->cmd->str) proto_item_append_text(cmd_item," %s ",c->cmd->str); PROTO_ITEM_SET_GENERATED(cmd_item); if (c->cmd->error) { proto_item_set_expert_flags(cmd_item, PI_RESPONSE_CODE, PI_WARN); } } } if (( ctx_term = ctx->terms.next )) { proto_item* terms_item = proto_tree_add_text(ctx_tree,gcp_tvb,0,0,"[ Terminations Used ]"); proto_tree* terms_tree = proto_item_add_subtree(terms_item,ids->ett.ctx_terms); for (; ctx_term; ctx_term = ctx_term->next ) { if ( ctx_term->term && ctx_term->term->str) { proto_item* pi = proto_tree_add_string(terms_tree,ids->hf.ctx_term,gcp_tvb,0,0,ctx_term->term->str); proto_tree* term_tree = proto_item_add_subtree(pi,ids->ett.ctx_term); PROTO_ITEM_SET_GENERATED(pi); if (ctx_term->term->type) { pi = proto_tree_add_uint(term_tree,ids->hf.ctx_term_type,gcp_tvb,0,0,ctx_term->term->type); PROTO_ITEM_SET_GENERATED(pi); } if (ctx_term->term->bir) { pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_bir,gcp_tvb,0,0,ctx_term->term->bir); PROTO_ITEM_SET_GENERATED(pi); } if (ctx_term->term->nsap) { pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_nsap,gcp_tvb,0,0,ctx_term->term->nsap); PROTO_ITEM_SET_GENERATED(pi); } if (ctx_term->term->bir && ctx_term->term->nsap) { gchar* key = ep_strdup_printf("%s:%s",ctx_term->term->nsap,ctx_term->term->bir); g_strdown(key); alcap_tree_from_bearer_key(term_tree, gcp_tvb, key); } } } } } }
/* * This function for CRC16 only is based on the decode_fcs of packet_ppp.c */ static tvbuff_t * mtp2_decode_crc16(tvbuff_t *tvb, proto_tree *fh_tree, packet_info *pinfo) { tvbuff_t *next_tvb; gint len, reported_len; int rx_fcs_offset; guint32 rx_fcs_exp; guint32 rx_fcs_got; int proto_offset=0; proto_item *cause; /* * Do we have the entire packet, and does it include a 2-byte FCS? */ len = tvb_length_remaining(tvb, proto_offset); reported_len = tvb_reported_length_remaining(tvb, proto_offset); if (reported_len < 2 || len < 0) { /* * The packet is claimed not to even have enough data for a 2-byte FCS, * or we're already past the end of the captured data. * Don't slice anything off. */ next_tvb = tvb_new_subset_remaining(tvb, proto_offset); } else if (len < reported_len) { /* * The packet is claimed to have enough data for a 2-byte FCS, but * we didn't capture all of the packet. * Slice off the 2-byte FCS from the reported length, and trim the * captured length so it's no more than the reported length; that * will slice off what of the FCS, if any, is in the captured * length. */ reported_len -= 2; if (len > reported_len) len = reported_len; next_tvb = tvb_new_subset(tvb, proto_offset, len, reported_len); } else { /* * We have the entire packet, and it includes a 2-byte FCS. * Slice it off. */ len -= 2; reported_len -= 2; next_tvb = tvb_new_subset(tvb, proto_offset, len, reported_len); /* * Compute the FCS and put it into the tree. */ rx_fcs_offset = proto_offset + len; rx_fcs_exp = mtp2_fcs16(tvb); rx_fcs_got = tvb_get_letohs(tvb, rx_fcs_offset); if (rx_fcs_got != rx_fcs_exp) { cause=proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 2, "FCS 16: 0x%04x [incorrect, should be 0x%04x]", rx_fcs_got, rx_fcs_exp); proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN); expert_add_info_format(pinfo, cause, PI_MALFORMED, PI_WARN, "MTP2 Frame CheckFCS 16 Error"); } else { proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 2, "FCS 16: 0x%04x [correct]", rx_fcs_got); } } return next_tvb; }
/* dissects MPA FPDU */ static guint16 dissect_mpa_fpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mpa_state_t *state, struct tcpinfo *tcpinfo, guint8 endpoint) { proto_item *mpa_item = NULL; proto_item *mpa_header_item = NULL; proto_tree *mpa_tree = NULL; proto_tree *mpa_header_tree = NULL; proto_item* bad_ulpdu_length_pi = NULL; guint8 pad_length; guint16 ulpdu_length, exp_ulpdu_length; guint32 offset, total_length; guint32 num_of_m = 0; /* * Initialize starting offset for this FPDU. Deals with the case that this * FPDU may start with a Marker instead of the ULPDU_LENTH header field. */ if (state->minfo[endpoint].valid && get_first_marker_offset(state, tcpinfo, endpoint) == 0) { offset = MPA_MARKER_LEN; } else { offset = 0; } /* get ULPDU length of this FPDU */ ulpdu_length = (guint16) tvb_get_ntohs(tvb, offset); mpa_packetlist(pinfo, MPA_FPDU); if (state->minfo[endpoint].valid) { num_of_m = number_of_markers(state, tcpinfo, endpoint); } if (tree) { /* * Stop FPDU dissection if the read ULPDU_LENGTH field does NOT contain * what is expected. * Reasons for getting a wrong ULPDU_LENGTH can be lost packets (because * libpcap was not able to capture every packet) or lost alignment (the * MPA FPDU header does not start right after TCP header). * We consider the above to be an error since we make the assumption * that exactly one MPA FPDU is contained in one TCP segement and starts * always either with a Marker or the ULPDU_LENGTH header field. */ exp_ulpdu_length = expected_ulpdu_length(state, tcpinfo, endpoint); if (!exp_ulpdu_length || exp_ulpdu_length != ulpdu_length) { bad_ulpdu_length_pi = proto_tree_add_text(tree, tvb, offset, MPA_ULPDU_LENGTH_LEN, "[ULPDU length field does not contain the expected length]"); proto_item_set_expert_flags(bad_ulpdu_length_pi, PI_MALFORMED, PI_ERROR); return 0; } mpa_item = proto_tree_add_item(tree, proto_iwarp_mpa, tvb, 0, -1, FALSE); mpa_tree = proto_item_add_subtree(mpa_item, ett_mpa); mpa_header_item = proto_tree_add_item(mpa_tree, hf_mpa_fpdu, tvb, offset, -1, FALSE); mpa_header_tree = proto_item_add_subtree(mpa_header_item, ett_mpa); /* ULPDU Length header field */ proto_tree_add_uint_format_value(mpa_header_tree, hf_mpa_ulpdu_length, tvb, offset, MPA_ULPDU_LENGTH_LEN, ulpdu_length, "%u bytes", ulpdu_length); pad_length = fpdu_pad_length(ulpdu_length); /* Markers are present in this FPDU */ if (state->minfo[endpoint].valid && num_of_m > 0) { total_length = fpdu_total_length(tcpinfo); if (pad_length > 0) { proto_tree_add_item(mpa_header_tree, hf_mpa_pad, tvb, pad_offset(tcpinfo, total_length, pad_length), pad_length, FALSE); } dissect_fpdu_crc(tvb, mpa_header_tree, state, total_length-MPA_CRC_LEN, num_of_m * MPA_MARKER_LEN + ulpdu_length + pad_length + MPA_ULPDU_LENGTH_LEN); dissect_fpdu_markers(tvb, mpa_tree, state, tcpinfo, endpoint); } else { /* Markers are not present or not enabled */ offset += MPA_ULPDU_LENGTH_LEN + ulpdu_length; if (pad_length > 0) { proto_tree_add_item(mpa_header_tree, hf_mpa_pad, tvb, offset, pad_length, FALSE); offset += pad_length; } dissect_fpdu_crc(tvb, mpa_header_tree, state, offset, ulpdu_length+pad_length+MPA_ULPDU_LENGTH_LEN); } } return ulpdu_length; }
/* dissects MPA REQUEST or MPA REPLY */ static gboolean dissect_mpa_req_rep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint message_type) { proto_tree *mpa_tree = NULL; proto_tree *mpa_header_tree = NULL; proto_item *mpa_item = NULL; proto_item *mpa_header_item = NULL; proto_item* bad_pd_length_pi = NULL; guint16 pd_length; guint32 offset = 0; mpa_packetlist(pinfo, message_type); if (tree) { mpa_item = proto_tree_add_item(tree, proto_iwarp_mpa, tvb, 0, -1, FALSE); mpa_tree = proto_item_add_subtree(mpa_item, ett_mpa); if (message_type == MPA_REQUEST_FRAME) { mpa_header_item = proto_tree_add_item(mpa_tree, hf_mpa_req, tvb, offset, -1, FALSE); mpa_header_tree = proto_item_add_subtree( mpa_header_item, ett_mpa); proto_tree_add_item(mpa_header_tree, hf_mpa_key_req, tvb, offset, MPA_REQ_REP_KEY_LEN, FALSE); } if (message_type == MPA_REPLY_FRAME) { mpa_header_item = proto_tree_add_item(mpa_tree, hf_mpa_rep, tvb, offset, -1, FALSE); mpa_header_tree = proto_item_add_subtree( mpa_header_item, ett_mpa); proto_tree_add_item(mpa_header_tree, hf_mpa_key_rep, tvb, offset, MPA_REQ_REP_KEY_LEN, FALSE); } offset += MPA_REQ_REP_KEY_LEN; proto_tree_add_item(mpa_header_tree, hf_mpa_flag_m, tvb, offset, MPA_REQ_REP_FLAG_LEN, FALSE); proto_tree_add_item(mpa_header_tree, hf_mpa_flag_c, tvb, offset, MPA_REQ_REP_FLAG_LEN, FALSE); proto_tree_add_item(mpa_header_tree, hf_mpa_flag_r, tvb, offset, MPA_REQ_REP_FLAG_LEN, FALSE); proto_tree_add_item(mpa_header_tree, hf_mpa_flag_res, tvb, offset, MPA_REQ_REP_FLAG_LEN, FALSE); offset += MPA_REQ_REP_FLAG_LEN; proto_tree_add_item(mpa_header_tree, hf_mpa_rev, tvb, offset, MPA_REQ_REP_REV_LEN, FALSE); offset += MPA_REQ_REP_REV_LEN; /* check whether the Private Data Length conforms to RFC 5044 */ pd_length = tvb_get_ntohs(tvb, offset); if (pd_length > MPA_MAX_PD_LENGTH) { bad_pd_length_pi = proto_tree_add_text(tree, tvb, offset, 2, "[PD length field indicates more 512 bytes of Private Data]"); proto_item_set_expert_flags(bad_pd_length_pi, PI_MALFORMED, PI_ERROR); return FALSE; } proto_tree_add_uint_format_value(mpa_header_tree, hf_mpa_pd_length, tvb, offset, MPA_REQ_REP_PDLENGTH_LEN, pd_length, "%u bytes", pd_length); offset += MPA_REQ_REP_PDLENGTH_LEN; if (pd_length) { proto_tree_add_item(mpa_header_tree, hf_mpa_private_data, tvb, offset, pd_length, FALSE); } } return TRUE; }
static void dissect_asterix_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree* asterix_tree[5]; int tree_depth = 0; proto_item* t_head_item; proto_item* t_item = NULL; static fulliautomatix_data* pDataList = NULL; fulliautomatix_data* pData = NULL; guint32 offset = 0; guint8 category; guint32 payload_len; char tmpstr[256]; char tmp2[64]; int error=0; tmpstr[0] = 0; while(offset < tvb_length(tvb) && strlen(tmpstr)<200) { category = tvb_get_guint8(tvb,offset); offset+=1; payload_len = tvb_get_ntohs(tvb,offset); offset+=2; offset += payload_len-3; sprintf(tmp2,"CAT%03d (%-3d bytes),", category, payload_len); strcat(tmpstr, tmp2); } if (offset != tvb_length(tvb)) { sprintf(tmp2, "Total= %d bytes - Wrong length !!!! ", offset); } else { sprintf(tmp2, "Total = %d bytes", offset); } strcat(tmpstr, tmp2); if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "Asterix"); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, tmpstr); if(!tree) return; t_head_item = proto_tree_add_protocol_format(tree, proto_asterix, tvb, 0, -1, "All Purpose Structured Eurocontrol Surveillance Information Exhange (Asterix) Protocol"); asterix_tree[tree_depth] = proto_item_add_subtree(t_head_item, ett_asterix[tree_depth]); pDataList = fulliautomatix_parse(tvb_get_ptr(tvb,0,tvb_length(tvb)), tvb_length(tvb)); pData = pDataList; while(pData) { if (pData->tree == 1) { t_item = proto_tree_add_text(asterix_tree[tree_depth], tvb, pData->bytenr, pData->length, pData->description); if (tree_depth < MAX_TREE_DEPTH-1) { tree_depth++; } asterix_tree[tree_depth] = proto_item_add_subtree(t_item, ett_asterix[tree_depth]); } else if (pData->tree == -1) { if (tree_depth > 0) { tree_depth--; } } else { if (pData->pid < 0 || pData->pid > maxpid) { logTraceFunc("Wrong PID.\n"); } else if (pData->type == FT_STRINGZ) { t_item = proto_tree_add_string(asterix_tree[tree_depth], def_pid[pData->pid], tvb, pData->bytenr, pData->length, pData->val.str); } else if (pData->type == FT_UINT32) { t_item = proto_tree_add_uint(asterix_tree[tree_depth], def_pid[pData->pid], tvb, pData->bytenr, pData->length, pData->val.ul); } else if (pData->type == FT_INT32) { t_item = proto_tree_add_int(asterix_tree[tree_depth], def_pid[pData->pid], tvb, pData->bytenr, pData->length, pData->val.sl); } else if (pData->type == FT_BYTES) { t_item = proto_tree_add_bytes(asterix_tree[tree_depth], def_pid[pData->pid], tvb, pData->bytenr, pData->length, pData->val.str); } else if (pData->type == FT_NONE) { t_item = proto_tree_add_text(asterix_tree[tree_depth], tvb, pData->bytenr, pData->length, pData->val.str); } //TODO add other types } if (pData->value_description) { proto_item_append_text(t_item, pData->value_description); } if (pData->err == 1) { proto_item_set_expert_flags(t_item, PI_GROUP_MASK, PI_WARN); expert_add_info_format(pinfo, t_item, PI_UNDECODED, PI_WARN, "Warning in Asterix message"); if (error==0) error=1; } else if (pData->err == 2) { proto_item_set_expert_flags(t_item, PI_REASSEMBLE, PI_ERROR); expert_add_info_format(pinfo, t_item, PI_MALFORMED, PI_ERROR, "Error in Asterix message"); if (error<2) error=2; } pData = pData->next; } if (error == 1) { proto_item_set_expert_flags(t_head_item, PI_GROUP_MASK, PI_WARN); } else if (error == 2) { proto_item_set_expert_flags(t_head_item, PI_REASSEMBLE, PI_ERROR); } fulliautomatix_data_destroy(pDataList); }