void dissect_sss_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, ncp_req_hash_value *request_value) { guint8 /*func,*/ subfunc = 0; guint32 subverb=0; guint32 msg_length=0; guint32 foffset= 0; proto_tree *atree; proto_item *aitem; if (tvb_length_remaining(tvb, foffset)<4) { return; } foffset = 6; /*func = tvb_get_guint8(tvb, foffset);*/ foffset += 1; subfunc = tvb_get_guint8(tvb, foffset); foffset += 1; /* Fill in the PROTOCOL & INFO columns. */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSSS"); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "C SecretStore - %s", val_to_str(subfunc, sss_func_enum, "Unknown (%d)")); } switch (subfunc) { case 1: aitem = proto_tree_add_text(ncp_tree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Packet Type: %s", val_to_str(subfunc, sss_func_enum, "Unknown (%d)")); atree = proto_item_add_subtree(aitem, ett_sss); proto_tree_add_item(atree, hf_ping_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; proto_tree_add_item(atree, hf_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; break; case 2: proto_tree_add_item(ncp_tree, hf_frag_handle, tvb, foffset, 4, ENC_LITTLE_ENDIAN); if (tvb_get_letohl(tvb, foffset)==0xffffffff) /* Fragment handle of -1 means no fragment. So process packet */ { foffset += 4; proto_tree_add_item(ncp_tree, hf_buffer_size, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; proto_tree_add_item(ncp_tree, hf_length, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; foffset += 12; /* Blank Context */ subverb = tvb_get_letohl(tvb, foffset); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str(subverb, sss_verb_enum, "Unknown (%d)")); } aitem = proto_tree_add_item(ncp_tree, hf_verb, tvb, foffset, 4, ENC_LITTLE_ENDIAN); atree = proto_item_add_subtree(aitem, ett_sss); if (request_value) { request_value->req_nds_flags=subverb; } foffset += 4; process_flags(atree, tvb, foffset); foffset += 4; proto_tree_add_item(atree, hf_context, tvb, foffset, 4, ENC_BIG_ENDIAN); foffset += 4; switch (subverb) { case 0: foffset += 4; foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0); break; case 1: foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0); msg_length = tvb_get_letohl(tvb, foffset); foffset += (msg_length+4); /* Unsure of what this length and parameter are */ /* A bad secret of length greater then 256 characters will cause frag packets and then we will see these as malformed packets. So check to make sure we still have data in the packet anytime we read a secret. */ if (tvb_length_remaining(tvb, foffset) > 4) { foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0); } break; case 2: foffset += 4; foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0); if (tvb_length_remaining(tvb, foffset) > 4) { msg_length = tvb_get_letohl(tvb, foffset); foffset += 4; if (tvb_length_remaining(tvb, foffset) < (gint) msg_length) { proto_tree_add_item(atree, hf_enc_data, tvb, foffset, -1, ENC_NA); } else { proto_tree_add_item(atree, hf_enc_data, tvb, foffset, msg_length, ENC_NA); } } break; case 3: case 4: foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0); if (tvb_length_remaining(tvb, foffset) > 4) { foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0); } break; case 5: break; case 6: foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0); if (tvb_length_remaining(tvb, foffset) > 4) { foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0); } break; case 7: msg_length = tvb_get_letohl(tvb, foffset); foffset += 4; proto_tree_add_item(atree, hf_enc_cred, tvb, foffset, msg_length, ENC_NA); break; case 8: case 9: default: break; } } else { if (check_col(pinfo->cinfo, COL_INFO)) { col_set_str(pinfo->cinfo, COL_INFO, "C SecretStore - fragment"); proto_tree_add_text(ncp_tree, tvb, foffset, 4, "Fragment"); } /* Fragments don't really carry a subverb so store 0xff as the subverb number */ if (request_value) { request_value->req_nds_flags=255; } if (tvb_length_remaining(tvb, foffset) > 8) { foffset += 4; proto_tree_add_item(ncp_tree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), ENC_NA); } } break; case 3: /* No Op */ break; default: break; } }
static void dissect_xtp_ecntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *top_ti; proto_tree *xtp_subtree; struct xtp_ecntl ecntl[1]; guint64 *spans, *p; guint32 spans_len; guint i; top_ti = proto_tree_add_text(tree, tvb, offset, len, "Error Control Segment"); xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_ecntl); if (len < MIN_XTP_ECNTL_PKT_LEN) { proto_item_append_text(top_ti, ", bogus length (%u, must be at least %u)", len, MIN_XTP_ECNTL_PKT_LEN); return; } /** parse **/ /* rseq(8) */ ecntl->rseq = tvb_get_ntohl(tvb, offset); ecntl->rseq <<= 32; ecntl->rseq += tvb_get_ntohl(tvb, offset+4); offset += 8; /* alloc(8) */ ecntl->alloc = tvb_get_ntohl(tvb, offset); ecntl->alloc <<= 32; ecntl->alloc += tvb_get_ntohl(tvb, offset+4); offset += 8; /* echo(4) */ ecntl->echo = tvb_get_ntohl(tvb, offset); offset += 4; /* nspan(4) */ ecntl->nspan = tvb_get_ntohl(tvb, offset); offset += 4; len = len + XTP_HEADER_LEN - offset; spans_len = 16 * ecntl->nspan; if (len != spans_len) { proto_item_append_text(top_ti, ", bogus spans field length (%u, must be %u)", len, spans_len); return; } /* spans(16n) */ spans = ep_alloc0(spans_len); p = spans; for (i = 0; i < ecntl->nspan*2; i++) { guint64 span = tvb_get_ntohl(tvb, offset); span <<= 32; span += tvb_get_ntohl(tvb, offset+4); *p++ = span; offset += 8; } /** add summary **/ if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " Recv-Seq=%" G_GINT64_MODIFIER "u", ecntl->rseq); col_append_fstr(pinfo->cinfo, COL_INFO, " Alloc=%" G_GINT64_MODIFIER "u", ecntl->alloc); } proto_item_append_text(top_ti, ", Recv-Seq: %" G_GINT64_MODIFIER "u", ecntl->rseq); /** display **/ offset = start; /* rseq(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_rseq, tvb, offset, 8, ecntl->rseq); offset += 8; /* alloc(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_alloc, tvb, offset, 8, ecntl->alloc); offset += 8; /* echo(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_echo, tvb, offset, 4, ecntl->echo); offset += 4; /* nspan(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_nspan, tvb, offset, 4, ecntl->nspan); offset += 4; /* spans(16n) */ p = spans; for (i = 0; i < ecntl->nspan; i++) { proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_span_left, tvb, offset, 8, *p); p++; offset += 8; proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_span_right, tvb, offset, 8, *p); p++; offset += 8; } return; }
static void dissect_turbocell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti, *name_item; proto_tree *turbocell_tree = NULL, *network_tree; tvbuff_t *next_tvb; int i=0; guint8 packet_type; guint8 * str_name; guint str_len; gint remaining_length; packet_type = tvb_get_guint8(tvb, 0); if (!(packet_type & 0x0F)){ col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Beacon)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } else if ( packet_type == TURBOCELL_TYPE_MANAGEMENT ) { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Management)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } else if ( packet_type == TURBOCELL_TYPE_DATA ) { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Data)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } else { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Unknown)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } if (tree) { ti = proto_tree_add_item(tree, proto_turbocell, tvb, 0, 20, ENC_NA); turbocell_tree = proto_item_add_subtree(ti, ett_turbocell); proto_tree_add_item(turbocell_tree, hf_turbocell_type, tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_satmode, tvb, 1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_nwid, tvb, 1, 1, ENC_BIG_ENDIAN); /* it seem when we have this magic number,that means an alternate header version */ if (tvb_get_bits64(tvb, 64,48,ENC_BIG_ENDIAN) != G_GINT64_CONSTANT(0x000001fe23dc45ba)){ proto_tree_add_item(turbocell_tree, hf_turbocell_counter, tvb, 0x02, 2, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_dst, tvb, 0x04, 6, ENC_NA); proto_tree_add_item(turbocell_tree, hf_turbocell_timestamp, tvb, 0x0A, 3, ENC_BIG_ENDIAN); } else { proto_tree_add_item(turbocell_tree, hf_turbocell_timestamp, tvb, 0x02, 3, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_counter, tvb, 0x05, 3, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_dst, tvb, 0x08, 6, ENC_NA); } proto_tree_add_item(turbocell_tree, hf_turbocell_unknown, tvb, 0x0E, 2, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_ip, tvb, 0x10, 4, ENC_BIG_ENDIAN); } remaining_length=tvb_length_remaining(tvb, 0x14); if (remaining_length > 6) { /* If the first character is a printable character that means we have a payload with network info */ /* I couldn't find anything in the header that would definitvely indicate if payload is either data or network info */ /* Since the frame size is limited this should work ok */ if (tvb_get_guint8(tvb, 0x14)>=0x20){ name_item = proto_tree_add_item(turbocell_tree, hf_turbocell_name, tvb, 0x14, 30, ENC_ASCII|ENC_NA); network_tree = proto_item_add_subtree(name_item, ett_network); str_name=tvb_get_stringz(wmem_packet_scope(), tvb, 0x14, &str_len); col_append_fstr(pinfo->cinfo, COL_INFO, ", Network=\"%s\"",format_text(str_name, str_len-1)); while(tvb_get_guint8(tvb, 0x34 + 8*i)==0x00 && (tvb_length_remaining(tvb,0x34 + 8*i) > 6) && (i<32)) { proto_tree_add_item(network_tree, hf_turbocell_station[i], tvb, 0x34+8*i, 6, ENC_NA); i++; } /*Couldn't make sense of the apparently random data in the end*/ next_tvb = tvb_new_subset_remaining(tvb, 0x34 + 8*i); call_dissector(data_handle, next_tvb, pinfo, tree); } else { tvbuff_t *volatile msdu_tvb = NULL; guint32 msdu_offset = 0x04; guint16 j = 1; guint16 msdu_length; proto_item *parent_item; proto_tree *mpdu_tree; proto_tree *subframe_tree; next_tvb = tvb_new_subset(tvb, 0x14, -1, tvb_get_ntohs(tvb, 0x14)); parent_item = proto_tree_add_protocol_format(tree, proto_aggregate, next_tvb, 0, tvb_reported_length_remaining(next_tvb, 0), "Turbocell Aggregate Frames"); mpdu_tree = proto_item_add_subtree(parent_item, ett_msdu_aggregation_parent_tree); proto_tree_add_item(mpdu_tree, hf_turbocell_aggregate_len, next_tvb, 0x00, 2, ENC_BIG_ENDIAN); proto_tree_add_item(mpdu_tree, hf_turbocell_aggregate_unknown1, next_tvb, 0x02, 2, ENC_BIG_ENDIAN); remaining_length=tvb_length_remaining(next_tvb, msdu_offset); do { msdu_length = (tvb_get_letohs(next_tvb, msdu_offset) & 0x0FFF); if (msdu_length==0) break; parent_item = proto_tree_add_uint_format(mpdu_tree, hf_turbocell_aggregate_msdu_header_text, next_tvb,msdu_offset, msdu_length + 0x02,j, "A-MSDU Subframe #%u", j); subframe_tree = proto_item_add_subtree(parent_item, ett_msdu_aggregation_subframe_tree); j++; proto_tree_add_item(subframe_tree, hf_turbocell_aggregate_msdu_len, next_tvb, msdu_offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(subframe_tree, hf_turbocell_aggregate_unknown2, next_tvb, msdu_offset+1, 1, ENC_BIG_ENDIAN); msdu_offset += 0x02; remaining_length -= 0x02; msdu_tvb = tvb_new_subset(next_tvb, msdu_offset, (msdu_length>remaining_length)?remaining_length:msdu_length, msdu_length); call_dissector(eth_handle, msdu_tvb, pinfo, subframe_tree); msdu_offset += msdu_length; remaining_length -= msdu_length; } while (remaining_length > 6); if (remaining_length > 2) { next_tvb = tvb_new_subset_remaining(next_tvb, msdu_offset); call_dissector(data_handle, next_tvb, pinfo, tree); } } } }
static int dissect_rx_acks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber) { proto_tree *tree; proto_item *item; guint8 num; int old_offset = offset; if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "ACK " "Seq: %lu " "Call: %lu " "Source Port: %s " "Destination Port: %s ", (unsigned long)seq, (unsigned long)callnumber, get_udp_port(pinfo->srcport), get_udp_port(pinfo->destport) ); } item = proto_tree_add_item(parent_tree, hf_rx_ack, tvb, offset, -1, FALSE); tree = proto_item_add_subtree(item, ett_rx_ack); /* bufferspace: 2 bytes*/ proto_tree_add_item(tree, hf_rx_bufferspace, tvb, offset, 2, FALSE); offset += 2; /* maxskew: 2 bytes*/ proto_tree_add_item(tree, hf_rx_maxskew, tvb, offset, 2, FALSE); offset += 2; /* first packet: 4 bytes*/ proto_tree_add_item(tree, hf_rx_first_packet, tvb, offset, 4, FALSE); offset += 4; /* prev packet: 4 bytes*/ proto_tree_add_item(tree, hf_rx_prev_packet, tvb, offset, 4, FALSE); offset += 4; /* serial : 4 bytes */ proto_tree_add_item(tree, hf_rx_serial, tvb, offset, 4, FALSE); offset += 4; /* reason : 1 byte */ proto_tree_add_item(tree, hf_rx_reason, tvb, offset, 1, FALSE); offset += 1; /* nACKs */ num = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_rx_numacks, tvb, offset, 1, num); offset += 1; while(num--){ proto_tree_add_item(tree, hf_rx_ack_type, tvb, offset, 1, FALSE); offset += 1; } /* Some implementations adds some extra fields. * As far as I can see, these first add 3 padding bytes and then * up to 4 32-bit values. (0,3,4 have been witnessed) * * RX as a protocol seems to be completely nondefined and seems to lack * any sort of documentation other than "read the source of any of the * (compatible?) implementations. */ if (tvb_length_remaining(tvb, offset)>3) { offset += 3; /* guess. some implementations adds 3 bytes */ if (tvb_reported_length_remaining(tvb, offset) >= 4){ proto_tree_add_item(tree, hf_rx_ifmtu, tvb, offset, 4, FALSE); offset += 4; } if (tvb_reported_length_remaining(tvb, offset) >= 4){ proto_tree_add_item(tree, hf_rx_maxmtu, tvb, offset, 4, FALSE); offset += 4; } if (tvb_reported_length_remaining(tvb, offset) >= 4){ proto_tree_add_item(tree, hf_rx_rwind, tvb, offset, 4, FALSE); offset += 4; } if (tvb_reported_length_remaining(tvb, offset) >= 4){ proto_tree_add_item(tree, hf_rx_maxpackets, tvb, offset, 4, FALSE); offset += 4; } } proto_item_set_len(item, offset-old_offset); return offset; }
static int dissect_xtp_traffic_cntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *top_ti; proto_tree *xtp_subtree; struct xtp_traffic_cntl tcntl[1]; top_ti = proto_tree_add_text(tree, tvb, offset, len, "Traffic Control Segment"); xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_tcntl); if (len < XTP_TRAFFIC_CNTL_LEN) { proto_item_append_text(top_ti, ", bogus length(%u, must be at least %u)", len, XTP_TRAFFIC_CNTL_LEN); return 0; } /** parse **/ /* rseq(8) */ tcntl->rseq = tvb_get_ntohl(tvb, offset); tcntl->rseq <<= 32; tcntl->rseq += tvb_get_ntohl(tvb, offset+4); offset += 8; /* alloc(8) */ tcntl->alloc = tvb_get_ntohl(tvb, offset); tcntl->alloc <<= 32; tcntl->alloc += tvb_get_ntohl(tvb, offset+4); offset += 8; /* echo(4) */ tcntl->echo = tvb_get_ntohl(tvb, offset); offset += 4; /* rsvd(4) */ tcntl->rsvd = tvb_get_ntohl(tvb, offset); offset += 4; /* xkey(8) */ tcntl->xkey = tvb_get_ntohl(tvb, offset); tcntl->xkey <<= 32; tcntl->xkey += tvb_get_ntohl(tvb, offset+4); /** add summary **/ if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " Recv-Seq=%" G_GINT64_MODIFIER "u", tcntl->rseq); col_append_fstr(pinfo->cinfo, COL_INFO, " Alloc=%" G_GINT64_MODIFIER "u", tcntl->alloc); } proto_item_append_text(top_ti, ", Recv-Seq: %" G_GINT64_MODIFIER "u", tcntl->rseq); /** display **/ offset = start; /* rseq(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_rseq, tvb, offset, 8, tcntl->rseq); offset += 8; /* alloc(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_alloc, tvb, offset, 8, tcntl->alloc); offset += 4; /* echo(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_echo, tvb, offset, 4, tcntl->echo); offset += 4; /* rsvd(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_rsvd, tvb, offset, 4, tcntl->rsvd); offset += 4; /* xkey(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_xkey, tvb, offset, 8, tcntl->xkey); offset += 8; return (offset - start); }
static void dissect_icep_reply(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *icep_tree, proto_item* icep_item) { /* p. 614, chapter 23.3.4: * * struct ReplyData { * int requestId; * byte replyStatus; * [... messageSize - 19 bytes ... ] * } */ gint32 messageSize = 0; guint32 tvb_data_remained = 0; guint32 reported_reply_data = 0; proto_item *ti = NULL; proto_tree *icep_sub_tree = NULL; DBG0("dissect reply\n"); /* get at least a full reply message header */ if ( !tvb_bytes_exist(tvb, offset, ICEP_MIN_REPLY_SIZE) ) { if (icep_item) expert_add_info_format(pinfo, icep_item, PI_MALFORMED, PI_ERROR, "too short header"); col_append_str(mypinfo->cinfo, COL_INFO, " (too short header)"); return; } /* got 5 bytes, then data */ /* create display subtree for this message type */ if (icep_tree) { ti = proto_tree_add_text(icep_tree, tvb, offset, -1, "Reply Message Body"); icep_sub_tree = proto_item_add_subtree(ti, ett_icep_msg); proto_tree_add_item(icep_sub_tree, hf_icep_request_id, tvb, offset, 4, ENC_LITTLE_ENDIAN); } if ( check_col(mypinfo->cinfo, COL_INFO) ) { col_append_fstr(mypinfo->cinfo, COL_INFO, "(%d):", tvb_get_letohl(tvb, offset)); } offset += 4; if (icep_tree) proto_tree_add_item(icep_sub_tree, hf_icep_reply_status, tvb, offset, 1, ENC_LITTLE_ENDIAN); if ( check_col(mypinfo->cinfo, COL_INFO) ) { col_append_fstr(mypinfo->cinfo, COL_INFO, " %s", val_to_str_const(tvb_get_guint8(tvb, offset), icep_replystatus_vals, "unknown reply status")); } offset++; DBG1("consumed --> %d\n", 5); /* check if I got all reply data */ tvb_data_remained = tvb_length_remaining(tvb, offset); messageSize = tvb_get_letohl(tvb, 10); reported_reply_data = messageSize - (ICEP_HEADER_SIZE + ICEP_MIN_REPLY_SIZE); /* no */ if ( tvb_data_remained < reported_reply_data ) { if (icep_sub_tree) expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Reply Data (missing %d bytes out of %d)", reported_reply_data - tvb_data_remained, reported_reply_data); if ( check_col(mypinfo->cinfo, COL_INFO) ) { col_append_fstr(mypinfo->cinfo, COL_INFO, " (missing reply data, %d bytes)", reported_reply_data - tvb_data_remained); } /*offset += tvb_data_remained;*/ DBG1("consumed --> %d\n", tvb_data_remained); return; } /* yes (reported_reply_data can be 0) */ if (icep_sub_tree) { proto_tree_add_item(icep_sub_tree, hf_icep_reply_data, tvb, offset, reported_reply_data, ENC_NA); } /*offset += reported_reply_data;*/ DBG1("consumed --> %d\n", reported_reply_data); }
static void dissect_dccreq (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) { guint16 pos; guint8 type, length; proto_tree *dcc_tree; proto_item *dcc_item; guint16 len; len = tvb_length_remaining (tvb, 0); col_set_str(pinfo->cinfo, COL_INFO, "DCC-REQ Message: "); if (tree) { dcc_item = proto_tree_add_protocol_format (tree, proto_docsis_dccreq, tvb, 0, -1, "DCC-REQ Message"); dcc_tree = proto_item_add_subtree (dcc_item, ett_docsis_dccreq); proto_tree_add_item (dcc_tree, hf_docsis_dccreq_tran_id, tvb, 0, 2, ENC_BIG_ENDIAN); pos = 2; while (pos < len) { type = tvb_get_guint8 (tvb, pos++); length = tvb_get_guint8 (tvb, pos++); switch (type) { case DCCREQ_UP_CHAN_ID: if (length == 1) { proto_tree_add_item (dcc_tree, hf_docsis_dccreq_up_chan_id, tvb, pos, length, ENC_BIG_ENDIAN); } else { THROW (ReportedBoundsError); } break; case DCCREQ_DS_PARAMS: dissect_dccreq_ds_params (tvb , dcc_tree , pos , length ); break; case DCCREQ_INIT_TECH: if (length == 1) { proto_tree_add_item (dcc_tree, hf_docsis_dccreq_init_tech, tvb, pos, length, ENC_BIG_ENDIAN); } else { THROW (ReportedBoundsError); } break; case DCCREQ_UCD_SUB: proto_tree_add_item (dcc_tree, hf_docsis_dccreq_ucd_sub, tvb, pos, length, ENC_NA); break; case DCCREQ_SAID_SUB: if (length == 4) { proto_tree_add_item (dcc_tree, hf_docsis_dccreq_said_sub_cur, tvb, pos, 2, ENC_BIG_ENDIAN); proto_tree_add_item (dcc_tree, hf_docsis_dccreq_said_sub_new, tvb, pos + 2, 2, ENC_BIG_ENDIAN); } else { THROW (ReportedBoundsError); } break; case DCCREQ_SF_SUB: dissect_dccreq_sf_sub (tvb , dcc_tree , pos , length ); break; case DCCREQ_CMTS_MAC_ADDR: if (length == 6) { proto_tree_add_item (dcc_tree, hf_docsis_dccreq_cmts_mac_addr, tvb, pos, length, ENC_NA); } else { THROW (ReportedBoundsError); } break; case DCCREQ_KEY_SEQ_NUM: if (length == 1) { proto_tree_add_item (dcc_tree, hf_docsis_dccreq_key_seq_num, tvb, pos, length, ENC_BIG_ENDIAN); } else { THROW (ReportedBoundsError); } break; case DCCREQ_HMAC_DIGEST: if (length == 20) { proto_tree_add_item (dcc_tree, hf_docsis_dccreq_hmac_digest, tvb, pos, length, ENC_NA); } else { THROW (ReportedBoundsError); } break; } /* switch(type) */ pos = pos + length; } /* while (pos < len) */ } /* if (tree) */ }
/* Code to actually dissect the packets */ static void dissect_sndcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 addr_field, comp_field, npdu_field1, nsapi, dcomp=0, pcomp=0; guint16 offset=0, npdu=0, segment=0, npdu_field2; tvbuff_t *next_tvb, *npdu_tvb; gint len; gboolean first, more_frags, unack; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti, *address_field_item, *compression_field_item, *npdu_field_item; proto_tree *sndcp_tree = NULL, *address_field_tree, *compression_field_tree, *npdu_field_tree; /* Make entries in Protocol column and clear Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SNDCP"); col_clear(pinfo->cinfo, COL_INFO); /* create display subtree for the protocol */ if (tree) { ti = proto_tree_add_item(tree, proto_sndcp, tvb, 0, -1, ENC_NA); sndcp_tree = proto_item_add_subtree(ti, ett_sndcp); } /* get address field from next byte */ addr_field = tvb_get_guint8(tvb,offset); nsapi = addr_field & 0xF; first = addr_field & MASK_F; more_frags = addr_field & MASK_M; unack = addr_field & MASK_T; /* add subtree for the address field */ if (tree) { address_field_item = proto_tree_add_uint_format(sndcp_tree,hf_sndcp_nsapi, tvb, offset,1, nsapi, "Address field NSAPI: %d", nsapi ); address_field_tree = proto_item_add_subtree(address_field_item, ett_sndcp_address_field); proto_tree_add_boolean(address_field_tree, hf_sndcp_x, tvb,offset,1, addr_field ); proto_tree_add_boolean(address_field_tree, hf_sndcp_f, tvb,offset,1, addr_field ); proto_tree_add_boolean(address_field_tree, hf_sndcp_t, tvb,offset,1, addr_field ); proto_tree_add_boolean(address_field_tree, hf_sndcp_m, tvb,offset,1, addr_field ); proto_tree_add_uint(address_field_tree, hf_sndcp_nsapib, tvb, offset, 1, addr_field ); } offset++; /* get compression pointers from next byte if this is the first segment */ if (first) { comp_field = tvb_get_guint8(tvb,offset); dcomp = comp_field & 0xF0; pcomp = comp_field & 0x0F; /* add subtree for the compression field */ if (tree) { if (!pcomp) { if (!dcomp) { compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "No compression"); } else { compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Data compression"); } } else { if (!dcomp) { compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Protocol compression"); } else { compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Data and Protocol compression"); } } compression_field_tree = proto_item_add_subtree(compression_field_item, ett_sndcp_compression_field); proto_tree_add_uint(compression_field_tree, hf_sndcp_dcomp, tvb, offset, 1, comp_field ); proto_tree_add_uint(compression_field_tree, hf_sndcp_pcomp, tvb, offset, 1, comp_field ); } offset++; /* get N-PDU number from next byte for acknowledged mode (only for first segment) */ if (!unack) { npdu = npdu_field1 = tvb_get_guint8(tvb,offset); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "SN-DATA N-PDU %d", npdu_field1); if (tree) { npdu_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Acknowledged mode, N-PDU %d", npdu_field1 ); npdu_field_tree = proto_item_add_subtree(npdu_field_item, ett_sndcp_npdu_field); proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu1, tvb, offset, 1, npdu_field1 ); } offset++; } } /* get segment and N-PDU number from next two bytes for unacknowledged mode */ if (unack) { npdu_field2 = tvb_get_ntohs(tvb, offset); segment = (npdu_field2 & 0xF000) >> 12; npdu = (npdu_field2 & 0x0FFF); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "SN-UNITDATA N-PDU %d (segment %d)", npdu, segment); if (tree) { npdu_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,2, "Unacknowledged mode, N-PDU %d (segment %d)", npdu, segment ); npdu_field_tree = proto_item_add_subtree(npdu_field_item, ett_sndcp_npdu_field); proto_tree_add_uint(npdu_field_tree, hf_sndcp_segment, tvb, offset, 2, npdu_field2 ); proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu2, tvb, offset, 2, npdu_field2 ); } offset += 2; } /* handle N-PDU data, reassemble if necessary */ if (first && !more_frags) { next_tvb = tvb_new_subset_remaining (tvb, offset); if (!dcomp && !pcomp) { call_dissector(ip_handle, next_tvb, pinfo, tree); } else { call_dissector(data_handle, next_tvb, pinfo, tree); } } else { /* Try reassembling fragments */ fragment_data *fd_npdu = NULL; guint32 reassembled_in = 0; gboolean save_fragmented = pinfo->fragmented; len = tvb_length_remaining(tvb, offset); if(len<=0){ return; } pinfo->fragmented = TRUE; if (unack) fd_npdu = fragment_add_seq_check(tvb, offset, pinfo, npdu, npdu_fragment_table, sndcp_reassembled_table, segment, len, more_frags); else fd_npdu = fragment_add(tvb, offset, pinfo, npdu, npdu_fragment_table, offset, len, more_frags); npdu_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled N-PDU", fd_npdu, &npdu_frag_items, NULL, sndcp_tree); if (fd_npdu) { /* Reassembled */ reassembled_in = fd_npdu->reassembled_in; if (pinfo->fd->num == reassembled_in) { /* Reassembled in this very packet: * We can safely hand the tvb to the IP dissector */ call_dissector(ip_handle, npdu_tvb, pinfo, tree); } else { /* Not reassembled in this packet */ if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " (N-PDU payload reassembled in packet %u)", fd_npdu->reassembled_in); } if (tree) { proto_tree_add_text(sndcp_tree, tvb, offset, -1, "Payload"); } } } else { /* Not reassembled yet, or not reassembled at all */ if (check_col(pinfo->cinfo, COL_INFO)) { if (unack) col_append_fstr(pinfo->cinfo, COL_INFO, " (Unreassembled fragment %u)", segment); else col_append_str(pinfo->cinfo, COL_INFO, " (Unreassembled fragment)"); } if (tree) { proto_tree_add_text(sndcp_tree, tvb, offset, -1, "Payload"); } } /* Now reset fragmentation information in pinfo */ pinfo->fragmented = save_fragmented; } }
/* Dissect details of packet */ static void rlogin_display(rlogin_hash_entry_t *hash_info, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, struct tcpinfo *tcpinfo) { /* Display the proto tree */ int offset = 0; proto_tree *rlogin_tree, *user_info_tree, *window_tree; proto_item *ti; guint length; int str_len; gint ti_offset; proto_item *user_info_item, *window_info_item; /* Create rlogin subtree */ ti = proto_tree_add_item(tree, proto_rlogin, tvb, 0, -1, FALSE); rlogin_tree = proto_item_add_subtree(ti, ett_rlogin); /* Return if data empty */ length = tvb_length(tvb); if (length == 0) { return; } /* * XXX - this works only if the urgent pointer points to something * in this segment; to make it work if the urgent pointer points * to something past this segment, we'd have to remember the urgent * pointer setting for this conversation. */ if (tcpinfo->urgent && /* if urgent pointer set */ length >= tcpinfo->urgent_pointer) /* and it's in this frame */ { /* Get urgent byte into Temp */ int urgent_offset = tcpinfo->urgent_pointer - 1; guint8 control_byte; /* Check for text data in front */ if (urgent_offset > offset) { proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, urgent_offset, FALSE); } /* Show control byte */ proto_tree_add_item(rlogin_tree, hf_control_message, tvb, urgent_offset, 1, FALSE); control_byte = tvb_get_guint8(tvb, urgent_offset); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str(control_byte, control_message_vals, "Unknown")); } offset = urgent_offset + 1; /* adjust offset */ } else if (tvb_get_guint8(tvb, offset) == '\0') { /* Startup */ if (pinfo->srcport == RLOGIN_PORT) /* from server */ { proto_tree_add_item(rlogin_tree, hf_startup_info_received_flag, tvb, offset, 1, FALSE); } else { proto_tree_add_item(rlogin_tree, hf_client_startup_flag, tvb, offset, 1, FALSE); } ++offset; } if (!tvb_offset_exists(tvb, offset)) { /* No more data to check */ return; } if (hash_info->info_framenum == pinfo->fd->num) { gint info_len; gint slash_offset; /* First frame of conversation, assume user info... */ info_len = tvb_length_remaining(tvb, offset); /* User info tree */ user_info_item = proto_tree_add_string_format(rlogin_tree, hf_user_info, tvb, offset, info_len, FALSE, "User info (%s)", tvb_format_text(tvb, offset, info_len)); user_info_tree = proto_item_add_subtree(user_info_item, ett_rlogin_user_info); /* Client user name. */ str_len = tvb_strsize(tvb, offset); proto_tree_add_item(user_info_tree, hf_user_info_client_user_name, tvb, offset, str_len, FALSE); offset += str_len; /* Server user name. */ str_len = tvb_strsize(tvb, offset); proto_tree_add_item(user_info_tree, hf_user_info_server_user_name, tvb, offset, str_len, FALSE); offset += str_len; /* Terminal type/speed. */ slash_offset = tvb_find_guint8(tvb, offset, -1, '/'); if (slash_offset != -1) { /* Terminal type */ proto_tree_add_item(user_info_tree, hf_user_info_terminal_type, tvb, offset, slash_offset-offset, FALSE); offset = slash_offset + 1; /* Terminal speed */ str_len = tvb_strsize(tvb, offset); proto_tree_add_uint(user_info_tree, hf_user_info_terminal_speed, tvb, offset, str_len, atoi(tvb_format_text(tvb, offset, str_len))); offset += str_len; } } if (!tvb_offset_exists(tvb, offset)) { /* No more data to check */ return; } /* Test for terminal information, the data will have 2 0xff bytes */ /* look for first 0xff byte */ ti_offset = tvb_find_guint8(tvb, offset, -1, 0xff); /* Next byte must also be 0xff */ if (ti_offset != -1 && tvb_bytes_exist(tvb, ti_offset + 1, 1) && tvb_get_guint8(tvb, ti_offset + 1) == 0xff) { guint16 rows, columns; /* Have found terminal info. */ if (ti_offset > offset) { /* There's data before the terminal info. */ proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, ti_offset - offset, FALSE); } /* Create window info tree */ window_info_item = proto_tree_add_item(rlogin_tree, hf_window_info, tvb, offset, 12, FALSE); window_tree = proto_item_add_subtree(window_info_item, ett_rlogin_window); /* Cookie */ proto_tree_add_text(window_tree, tvb, offset, 2, "Magic Cookie: (0xff, 0xff)"); offset += 2; /* These bytes should be "ss" */ proto_tree_add_item(window_tree, hf_window_info_ss, tvb, offset, 2, FALSE); offset += 2; /* Character rows */ rows = tvb_get_ntohs(tvb, offset); proto_tree_add_item(window_tree, hf_window_info_rows, tvb, offset, 2, FALSE); offset += 2; /* Characters per row */ columns = tvb_get_ntohs(tvb, offset); proto_tree_add_item(window_tree, hf_window_info_cols, tvb, offset, 2, FALSE); offset += 2; /* x pixels */ proto_tree_add_item(window_tree, hf_window_info_x_pixels, tvb, offset, 2, FALSE); offset += 2; /* y pixels */ proto_tree_add_item(window_tree, hf_window_info_y_pixels, tvb, offset, 2, FALSE); offset += 2; /* Show setting highlights in info column */ if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " (rows=%u, cols=%u)", rows, columns); } } if (tvb_offset_exists(tvb, offset)) { /* There's more data in the frame. */ proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, -1, FALSE); } }
static void dissect_rsh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *rsh_tree=NULL; /* Variables for extracting and displaying data from the packet */ guchar *field_stringz; /* Temporary storage for each field we extract */ gint length; guint offset = 0; conversation_t *conversation; rsh_hash_entry_t *hash_info; conversation = find_or_create_conversation(pinfo); /* Retrieve information from conversation * or add it if it isn't there yet */ hash_info = conversation_get_proto_data(conversation, proto_rsh); if(!hash_info){ hash_info = se_alloc(sizeof(rsh_hash_entry_t)); hash_info->first_packet_number = pinfo->fd->num; hash_info->second_packet_number = 0; hash_info->third_packet_number = 0; hash_info->fourth_packet_number = 0; hash_info->state = WAIT_FOR_STDERR_PORT; /* The first field we'll see */ /* Start with empty username and command strings */ hash_info->client_username=NULL; hash_info->server_username=NULL; hash_info->command=NULL; /* These will be set on the first pass by the first * four packets of the conversation */ hash_info->first_packet_state = NONE; hash_info->second_packet_state = NONE; hash_info->third_packet_state = NONE; hash_info->fourth_packet_state = NONE; conversation_add_proto_data(conversation, proto_rsh, hash_info); } /* Store the number of the first three packets of this conversation * as we reach them the first time */ if(!hash_info->second_packet_number && pinfo->fd->num > hash_info->first_packet_number){ /* We're on the second packet of the conversation */ hash_info->second_packet_number = pinfo->fd->num; } else if(hash_info->second_packet_number && !hash_info->third_packet_number && pinfo->fd->num > hash_info->second_packet_number) { /* We're on the third packet of the conversation */ hash_info->third_packet_number = pinfo->fd->num; } else if(hash_info->third_packet_number && !hash_info->fourth_packet_number && pinfo->fd->num > hash_info->third_packet_number) { /* We're on the fourth packet of the conversation */ hash_info->fourth_packet_number = pinfo->fd->num; } /* Save this packet's state so we can retrieve it if this packet * is selected again later. If the packet's state was already stored, * then retrieve it */ if(pinfo->fd->num == hash_info->first_packet_number){ if(hash_info->first_packet_state == NONE){ hash_info->first_packet_state = hash_info->state; } else { hash_info->state = hash_info->first_packet_state; } } if(pinfo->fd->num == hash_info->second_packet_number){ if(hash_info->second_packet_state == NONE){ hash_info->second_packet_state = hash_info->state; } else { hash_info->state = hash_info->second_packet_state; } } if(pinfo->fd->num == hash_info->third_packet_number){ if(hash_info->third_packet_state == NONE){ hash_info->third_packet_state = hash_info->state; } else { hash_info->state = hash_info->third_packet_state; } } if(pinfo->fd->num == hash_info->fourth_packet_number){ if(hash_info->fourth_packet_state == NONE){ hash_info->fourth_packet_state = hash_info->state; } else { hash_info->state = hash_info->fourth_packet_state; } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSH"); if(check_col(pinfo->cinfo, COL_INFO)){ /* First, clear the info column */ col_clear(pinfo->cinfo, COL_INFO); /* Client username */ if(hash_info->client_username && preference_info_show_client_username == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Client username:%s ", hash_info->client_username); } /* Server username */ if(hash_info->server_username && preference_info_show_server_username == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Server username:%s ", hash_info->server_username); } /* Command */ if(hash_info->command && preference_info_show_command == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Command:%s ", hash_info->command); } } /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_rsh, tvb, 0, -1, ENC_NA); rsh_tree = proto_item_add_subtree(ti, ett_rsh); /* If this packet doesn't end with a null terminated string, * then it must be session data only and we can skip looking * for the other fields. */ if(tvb_find_guint8(tvb, tvb_length(tvb)-1, 1, '\0') == -1){ hash_info->state = WAIT_FOR_DATA; } if(hash_info->state == WAIT_FOR_STDERR_PORT && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the stderr_port field. * It is optional, so it may only be 1 character long * (the NULL) */ if(length == 1 || (isdigit_string(field_stringz) && length <= RSH_STDERR_PORT_LEN)){ proto_tree_add_string(rsh_tree, hf_rsh_stderr_port, tvb, offset, length, (gchar*)field_stringz); /* Next field we need */ hash_info->state = WAIT_FOR_CLIENT_USERNAME; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; } if(hash_info->state == WAIT_FOR_CLIENT_USERNAME && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the username field */ if(length != 1 && length <= RSH_CLIENT_USERNAME_LEN && isprint_string(field_stringz)){ proto_tree_add_string(rsh_tree, hf_rsh_client_username, tvb, offset, length, (gchar*)field_stringz); /* Store the client username so we can display it in the * info column of the entire conversation */ if(!hash_info->client_username){ hash_info->client_username=se_strdup((gchar*)field_stringz); } /* Next field we need */ hash_info->state = WAIT_FOR_SERVER_USERNAME; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; } if(hash_info->state == WAIT_FOR_SERVER_USERNAME && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the password field */ if(length != 1 && length <= RSH_SERVER_USERNAME_LEN && isprint_string(field_stringz)){ proto_tree_add_string(rsh_tree, hf_rsh_server_username, tvb, offset, length, (gchar*)field_stringz); /* Store the server username so we can display it in the * info column of the entire conversation */ if(!hash_info->server_username){ hash_info->server_username=se_strdup((gchar*)field_stringz); } /* Next field we need */ hash_info->state = WAIT_FOR_COMMAND; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; /* Next field we are looking for */ hash_info->state = WAIT_FOR_COMMAND; } if(hash_info->state == WAIT_FOR_COMMAND && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the command field */ if(length != 1 && length <= RSH_COMMAND_LEN && isprint_string(field_stringz)){ proto_tree_add_string(rsh_tree, hf_rsh_command, tvb, offset, length, (gchar*)field_stringz); /* Store the command so we can display it in the * info column of the entire conversation */ if(!hash_info->command){ hash_info->command=se_strdup((gchar*)field_stringz); } } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } } if(hash_info->state == WAIT_FOR_DATA && tvb_length_remaining(tvb, offset)){ if(pinfo->destport == RSH_PORT){ /* Packet going to the server */ /* offset = 0 since the whole packet is data */ proto_tree_add_text(rsh_tree, tvb, 0, -1, "Client -> Server Data"); col_append_str(pinfo->cinfo, COL_INFO, "Client -> Server data"); } else { /* This packet must be going back to the client */ /* offset = 0 since the whole packet is data */ proto_tree_add_text(rsh_tree, tvb, 0, -1, "Server -> Client Data"); col_append_str(pinfo->cinfo, COL_INFO, "Server -> Client Data"); } } /* We haven't seen all of the fields yet */ if(hash_info->state < WAIT_FOR_DATA){ col_set_str(pinfo->cinfo, COL_INFO, "Session Establishment"); } }
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->configuration && info->configuration_length > 0) { /* TODO: display current codec configuration */ } 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); pitem = proto_tree_add_double(sbc_tree, hf_sbc_avrcp_song_position, tvb, offset, 0, info->previous_media_packet_info->avrcp_song_position); 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; info->current_media_packet_info->avrcp_song_position += 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; }
/* Both Source-Active and Source-Active Response have the same format * with one exception. Encapsulated multicast data is not allowed in * SA Response. */ static void dissect_msdp_sa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, int length) { guint8 entries; if (length < 1) return; entries = tvb_get_guint8(tvb, *offset); proto_tree_add_uint(tree, hf_msdp_sa_entry_count, tvb, *offset, 1, entries); *offset += 1; length -= 1; if (length < 4) { *offset += length; length = 0; return; } proto_tree_add_item(tree, hf_msdp_sa_rp_addr, tvb, *offset, 4, FALSE); *offset += 4; length -= 4; /* Put each of the (S,G) entries in their own subtree. * This is probably visually better. */ while (entries-- > 0) { proto_item *ei; proto_tree *entry_tree; if (length < 12) { *offset += length; length = 0; return; } ei = proto_tree_add_text(tree, tvb, *offset, 12, "(S,G) block: %s/%u -> %s", ip_to_str(tvb_get_ptr(tvb, *offset + 8, 4)), tvb_get_guint8(tvb, *offset + 3), ip_to_str(tvb_get_ptr(tvb, *offset + 4, 4))); entry_tree = proto_item_add_subtree(ei, ett_msdp_sa_entry); proto_tree_add_item(entry_tree, hf_msdp_sa_reserved, tvb, *offset, 3, FALSE); *offset += 3; length -= 3; proto_tree_add_item(entry_tree, hf_msdp_sa_sprefix_len, tvb, *offset, 1, FALSE); *offset += 1; length -= 1; proto_tree_add_item(entry_tree, hf_msdp_sa_group_addr, tvb, *offset, 4, FALSE); *offset += 4; length -= 4; proto_tree_add_item(entry_tree, hf_msdp_sa_src_addr, tvb, *offset, 4, FALSE); *offset += 4; length -= 4; } /* * Check if an encapsulated multicast IPv4 packet follows */ if (length > 0) { proto_item *ei; proto_tree *enc_tree; gint available_length, reported_length; tvbuff_t *next_tvb; ei = proto_tree_add_text(tree, tvb, *offset, length, "Encapsulated IPv4 packet: %u bytes", length); enc_tree = proto_item_add_subtree(ei, ett_msdp_sa_enc_data); available_length = tvb_length_remaining(tvb, *offset); reported_length = tvb_reported_length_remaining(tvb, *offset); DISSECTOR_ASSERT(available_length >= 0); DISSECTOR_ASSERT(reported_length >= 0); if (available_length > reported_length) available_length = reported_length; if (available_length > length) available_length = length; if (reported_length > length) reported_length = length; next_tvb = tvb_new_subset(tvb, *offset, available_length, reported_length); /* Set the information columns read-only so that they * reflect the MSDP packet rather than the * encapsulated packet. */ col_set_writable(pinfo->cinfo, FALSE); call_dissector(ip_handle, next_tvb, pinfo, enc_tree); } *offset += length; return; }
static void dissect_msdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *msdp_tree; int offset; col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSDP"); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(tvb_get_guint8(tvb, 0), msdp_types, "<Unknown MSDP message type>")); if (tree) { guint8 type; guint16 length; ti = proto_tree_add_item(tree, proto_msdp, tvb, 0, -1, FALSE); msdp_tree = proto_item_add_subtree(ti, ett_msdp); offset = 0; while (tvb_reported_length_remaining(tvb, offset) >= 3) { type = tvb_get_guint8(tvb, offset); length = tvb_get_ntohs(tvb, offset + 1); if (length < 3) break; proto_tree_add_uint(msdp_tree, hf_msdp_type, tvb, offset, 1, type); proto_tree_add_uint(msdp_tree, hf_msdp_length, tvb, offset + 1, 2, length); offset += 3; length -= 3; switch (type) { case MSDP_SA: case MSDP_SA_RSP: dissect_msdp_sa(tvb, pinfo, msdp_tree, &offset, length); break; case MSDP_SA_REQ: proto_tree_add_item(msdp_tree, hf_msdp_sa_req_res, tvb, offset, 1, FALSE); proto_tree_add_item(msdp_tree, hf_msdp_sa_req_group, tvb, offset + 1, 4, FALSE); offset += 5; break; case MSDP_NOTIFICATION: dissect_msdp_notification(tvb, pinfo, msdp_tree, &offset, length); break; default: if (length > 0) proto_tree_add_text(msdp_tree, tvb, offset, length, "TLV contents"); offset += length; break; } } if (tvb_length_remaining(tvb, offset) > 0) proto_tree_add_text(msdp_tree, tvb, offset, -1, "Trailing junk"); } return; }
void dissect_sss_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, guint8 subfunc, ncp_req_hash_value *request_value) { guint32 foffset=0; guint32 subverb=0; guint32 msg_length=0; guint32 return_code=0; guint32 number_of_items=0; gint32 length_of_string=0; guint32 i = 0; const gchar *str; proto_tree *atree; proto_item *aitem; proto_item *expert_item; foffset = 8; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSSS"); if (tvb_length_remaining(tvb, foffset)<4) { return; } aitem = proto_tree_add_text(ncp_tree, tvb, foffset, -1, "Function: %s", val_to_str_const(subfunc, sss_func_enum, "Unknown")); atree = proto_item_add_subtree(aitem, ett_sss); switch (subfunc) { case 1: proto_tree_add_item(atree, hf_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; proto_tree_add_item(atree, hf_sss_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; break; case 2: if (request_value) { subverb = request_value->req_nds_flags; str = try_val_to_str(subverb, sss_verb_enum); if (str) { proto_tree_add_text(atree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Verb: %s", str); } } proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_LITTLE_ENDIAN); msg_length = tvb_get_letohl(tvb, foffset); return_code = tvb_get_ntohl(tvb, foffset+msg_length); foffset += 4; proto_tree_add_item(atree, hf_frag_handle, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; msg_length -= 4; if ((tvb_get_letohl(tvb, foffset-4)==0xffffffff) && (msg_length > 4)) { foffset += 4; return_code = tvb_get_letohl(tvb, foffset); str = try_val_to_str(return_code, sss_errors_enum); if (str) { expert_item = proto_tree_add_item(atree, hf_return_code, tvb, foffset, 4, ENC_LITTLE_ENDIAN); expert_add_info_format(pinfo, expert_item, PI_RESPONSE_CODE, PI_ERROR, "SSS Error: %s", str); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "R Error - %s", val_to_str(return_code, sss_errors_enum, "Unknown (%d)")); } foffset+=4; } else { proto_tree_add_text(atree, tvb, foffset, 4, "Return Code: Success (0x00000000)"); if (tvb_length_remaining(tvb, foffset) > 8) { foffset += 4; if (request_value && subverb == 6) { foffset += 4; number_of_items = tvb_get_letohl(tvb, foffset); foffset += 8; for (i=0; i<number_of_items; i++) { length_of_string = find_delimiter(tvb, foffset); if (length_of_string > tvb_length_remaining(tvb, foffset)) { return; } foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, length_of_string); if (tvb_length_remaining(tvb, foffset) < 8) { return; } foffset++; } } else { proto_tree_add_item(atree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), ENC_NA); } } } } else { proto_tree_add_text(atree, tvb, foffset, 4, "Return Code: Success (0x00000000)"); if (tvb_length_remaining(tvb, foffset) > 8) { foffset += 4; proto_tree_add_item(atree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), ENC_NA); } } break; case 3: break; default: break; } }
static void dissect_starteam(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "StarTeam"); if(check_col(pinfo->cinfo, COL_INFO)){ /* This is a trick to know whether this is the first PDU in this packet or not */ if(iPreviousFrameNumber != (gint) pinfo->fd->num){ col_clear(pinfo->cinfo, COL_INFO); } else { col_append_str(pinfo->cinfo, COL_INFO, " | "); } } iPreviousFrameNumber = pinfo->fd->num; if(tvb_length(tvb) >= 16){ guint32 iCommand = 0; gboolean bRequest = FALSE; if(tvb_get_ntohl(tvb, offset + 0) == STARTEAM_MAGIC){ /* This packet is a response */ bRequest = FALSE; if(check_col(pinfo->cinfo, COL_INFO)){ col_append_fstr(pinfo->cinfo, COL_INFO, "Reply: %d bytes", tvb_length(tvb)); } } else if(tvb_length_remaining(tvb, offset) >= 28 && tvb_get_ntohl(tvb, offset + 20) == STARTEAM_MAGIC){ /* This packet is a request */ bRequest = TRUE; if(tvb_length_remaining(tvb, offset) >= 66){ iCommand = tvb_get_letohl(tvb, offset + 62); } if(check_col(pinfo->cinfo, COL_INFO)){ col_append_str(pinfo->cinfo, COL_INFO, val_to_str_ext(iCommand, &starteam_opcode_vals_ext, "Unknown (0x%02x)")); } } if(tree){ proto_tree *starteam_tree; proto_tree *starteamroot_tree; proto_item *ti; ti = proto_tree_add_item(tree, proto_starteam, tvb, offset, -1, ENC_NA); if (bRequest) proto_item_append_text(ti, " (%s)", val_to_str_ext(iCommand, &starteam_opcode_vals_ext, "Unknown (0x%02x)")); starteamroot_tree = proto_item_add_subtree(ti, ett_starteam); if(bRequest){ if(tvb_length_remaining(tvb, offset) >= 20){ ti = proto_tree_add_text(starteamroot_tree, tvb, offset, 20, STARTEAM_TEXT_MDH); starteam_tree = proto_item_add_subtree(ti, ett_starteam_mdh); proto_tree_add_item(starteam_tree, hf_starteam_mdh_session_tag, tvb, offset + 0, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_mdh_ctimestamp, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_mdh_flags, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_mdh_keyid, tvb, offset + 12, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_mdh_reserved, tvb, offset + 16, 4, ENC_LITTLE_ENDIAN); offset += 20; } } if(tvb_length_remaining(tvb, offset) >= 16){ ti = proto_tree_add_text(starteamroot_tree, tvb, offset, 16, STARTEAM_TEXT_PH); starteam_tree = proto_item_add_subtree(ti, ett_starteam_ph); proto_tree_add_item(starteam_tree, hf_starteam_ph_signature, tvb, offset + 0, 4, ENC_ASCII|ENC_NA); proto_tree_add_item(starteam_tree, hf_starteam_ph_packet_size, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_ph_data_size, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_ph_data_flags, tvb, offset + 12, 4, ENC_LITTLE_ENDIAN); offset += 16; if(bRequest){ if(tvb_length_remaining(tvb, offset) >= 38){ ti = proto_tree_add_text(starteamroot_tree, tvb, offset, 38, STARTEAM_TEXT_ID); starteam_tree = proto_item_add_subtree(ti, ett_starteam_id); proto_tree_add_item(starteam_tree, hf_starteam_id_revision_level, tvb, offset + 0, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_id_client, tvb, offset + 2, 16, ENC_ASCII|ENC_NA); proto_tree_add_item(starteam_tree, hf_starteam_id_connect, tvb, offset + 18, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_id_component, tvb, offset + 22, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_id_command, tvb, offset + 26, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_id_command_time, tvb, offset + 30, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(starteam_tree, hf_starteam_id_command_userid, tvb, offset + 34, 4, ENC_LITTLE_ENDIAN); offset += 38; } } if(tvb_length_remaining(tvb, offset) > 0){ ti = proto_tree_add_text(starteamroot_tree, tvb, offset, -1, STARTEAM_TEXT_DATA); starteam_tree = proto_item_add_subtree(ti, ett_starteam_data); proto_tree_add_item(starteam_tree, hf_starteam_data_data, tvb, offset, tvb_length_remaining(tvb, offset), ENC_ASCII|ENC_NA); } } } } }
static int dissect_openvpn_msg_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *openvpn_tree, proto_tree *parent_tree, gint offset) { gboolean tls_auth; guint openvpn_keyid; guint openvpn_opcode; guint32 msg_mpid = -1; guint32 msg_sessionid = -1; guint8 openvpn_predict_tlsauth_arraylength; proto_item *ti2, *ti3; proto_tree *packetarray_tree, *type_tree; guint32 msg_length_remaining; gboolean msg_lastframe; fragment_head *frag_msg; tvbuff_t *new_tvb; gboolean save_fragmented; /* Clear out stuff in the info column */ col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME); col_clear(pinfo->cinfo,COL_INFO); /* read opcode and write to info column */ openvpn_opcode = tvb_get_bits8(tvb, offset*8, 5); col_append_fstr(pinfo->cinfo, COL_INFO, "MessageType: %s", val_to_str_const(openvpn_opcode, openvpn_message_types, "Unknown Messagetype")); openvpn_keyid = tvb_get_bits8(tvb, offset*8 + 5, 3); proto_item_append_text(parent_tree, ", Opcode: %s, Key ID: %d", val_to_str(openvpn_opcode, openvpn_message_types, "Unknown (0x%02x)"), openvpn_keyid); ti2 = proto_tree_add_item(openvpn_tree, hf_openvpn_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(ti2, " [opcode/key_id]"); type_tree = proto_item_add_subtree(ti2, ett_openvpn_type); proto_tree_add_item(type_tree, hf_openvpn_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_openvpn_keyid, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* if we have a P_CONTROL or P_ACK packet */ if (openvpn_opcode != P_DATA_V1) { /* read sessionid */ msg_sessionid = tvb_get_bits32(tvb, offset*8+32, 32, ENC_BIG_ENDIAN); proto_tree_add_item(openvpn_tree, hf_openvpn_sessionid, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* tls-auth detection (this can be overridden by preferences */ openvpn_predict_tlsauth_arraylength = tvb_get_guint8(tvb, offset); /* if the first 4 bytes that would, if tls-auth is used, contain part of the hmac, lack entropy, we asume no tls-auth is used */ if (pref_tls_auth_override == FALSE) { if ((openvpn_opcode != P_DATA_V1) && (openvpn_predict_tlsauth_arraylength > 0) && check_for_valid_hmac(tvb_get_ntohl(tvb, offset))) { tls_auth = TRUE; } else { tls_auth = FALSE; } } else { tls_auth = pref_tls_auth; } if (tls_auth == TRUE) { proto_tree_add_item(openvpn_tree, hf_openvpn_hmac, tvb, offset, tls_auth_hmac_size, ENC_NA); offset += tls_auth_hmac_size; if (tvb_length_remaining(tvb, offset) >= 8) { proto_tree_add_item(openvpn_tree, hf_openvpn_pid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; if (pref_long_format) { proto_tree_add_item(openvpn_tree, hf_openvpn_net_time, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } } } if (tvb_length_remaining(tvb, offset) >= 1) { /* read P_ACK packet-id array length */ gint pid_arraylength = tvb_get_guint8(tvb, offset); gint i; proto_tree_add_item(openvpn_tree, hf_openvpn_mpid_arraylength, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (pid_arraylength > 0) { ti3 = proto_tree_add_text(openvpn_tree, tvb, offset, 0, "Packet-ID Array"); packetarray_tree = proto_item_add_subtree(ti3, ett_openvpn_packetarray); for (i = 0; i < pid_arraylength; i++) { proto_tree_add_item(packetarray_tree, hf_openvpn_mpid_arrayelement, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } if (tvb_length_remaining(tvb, offset) >= 8) { proto_tree_add_item(openvpn_tree, hf_openvpn_rsessionid, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; } } } /* if we have a P_CONTROL packet */ if (openvpn_opcode != P_ACK_V1) { /* read Message Packet-ID */ if (tvb_length_remaining(tvb, offset) >= 4) { msg_mpid = tvb_get_bits32(tvb, offset*8, 32, ENC_BIG_ENDIAN); proto_tree_add_item(openvpn_tree, hf_openvpn_mpid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } } } /* if we have more data left, determine what to do */ msg_length_remaining = tvb_length_remaining(tvb, offset); if (msg_length_remaining == 0) { return tvb_length(tvb); } if (openvpn_opcode != P_CONTROL_V1) { proto_tree *data_tree; ti2 = proto_tree_add_text(openvpn_tree, tvb, offset, -1, "Data (%d bytes)", tvb_length_remaining(tvb, offset)); data_tree = proto_item_add_subtree(ti2, ett_openvpn_data); proto_tree_add_item(data_tree, hf_openvpn_data, tvb, offset, -1, ENC_NA); return tvb_length(tvb); } /* Try to reassemble */ /* an ordinary openvpn control packet contains 100 bytes only if it is part of a fragmented message and is not the last fragment of the current transmission. Note that the tvb contains exactly one openvpn PDU: UDP: by definition; TCP: because of the use of tcp_dissect_pdus(). */ if (msg_length_remaining == 100) { msg_lastframe = FALSE; } else { msg_lastframe = TRUE; } save_fragmented = pinfo->fragmented; pinfo->fragmented = TRUE; frag_msg = fragment_add_seq_next( &msg_reassembly_table, tvb, offset, pinfo, msg_sessionid, /* ID for fragments belonging together */ NULL, msg_length_remaining, /* fragment length - to the end */ !(msg_lastframe)); /* More fragments ? */ /* show "data" fragment on tree unless "reassembled" message has just one part. */ /* i.e., show if ("not reassembled") or ("reassembled" and "has multiple fragments") */ if ((frag_msg == NULL) || (frag_msg->next != NULL)) { proto_tree *data_tree; ti2 = proto_tree_add_text(openvpn_tree, tvb, offset, -1, "Message fragment (%d bytes)", tvb_length_remaining(tvb, offset)); data_tree = proto_item_add_subtree(ti2, ett_openvpn_data); proto_tree_add_item(data_tree, hf_openvpn_fragment_bytes, tvb, offset, -1, ENC_NA); } new_tvb = NULL; if (frag_msg) { if (msg_lastframe) { /* Reassembled */ new_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled Message", frag_msg, &openvpn_frag_items, NULL, openvpn_tree); if (frag_msg->next != NULL) { /* multiple frags ? */ col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled "); /* overwritten by next dissector */ } } else { /* Not last packet of reassembled Short Message */ col_append_fstr(pinfo->cinfo, COL_INFO, " (Message fragment %d) ", msg_mpid); if (pinfo->fd->num != frag_msg->reassembled_in) { /* Add a "Reassembled in" link if not reassembled in this frame */ proto_tree_add_uint(openvpn_tree, hf_openvpn_reassembled_in, tvb, 0, 0, frag_msg->reassembled_in); } } } /* if (frag_msg) */ pinfo->fragmented = save_fragmented; /* Now see if we need to call subdissector. new_tvb is non-null if we "reassembled* a message (even just one fragment) */ if (new_tvb) { /* call SSL/TLS dissector if we just processed the last fragment */ call_dissector(ssl_handle, new_tvb, pinfo, parent_tree); } return tvb_length(tvb); }
cksum_status_t check_and_get_checksum( tvbuff_t *tvb, int offset, guint len, guint checksum, int offset_check, guint16* result) { const gchar *buffer; guint available_len; const guint8 *p; guint8 discard = 0; guint32 c0, c1, factor; guint seglen, initlen = len; guint i; int block, x, y; if ( 0 == checksum ) return( NO_CKSUM ); available_len = tvb_length_remaining( tvb, offset ); offset_check -= offset; if ( ( available_len < len ) || ( offset_check < 0 ) || ( (guint)(offset_check+2) > len ) ) return( DATA_MISSING ); buffer = tvb_get_ptr( tvb, offset, len ); block = offset_check / 5803; /* * The maximum values of c0 and c1 will occur if all bytes have the * value 255; if so, then c0 will be len*255 and c1 will be * (len*255 + (len-1)*255 + ... + 255), which is * (len + (len - 1) + ... + 1)*255, or 255*(len*(len + 1))/2. * This means it can overflow if "len" is 5804 or greater. * * (A+B) mod 255 = ((A mod 255) + (B mod 255) mod 255, so * we can solve this by taking c0 and c1 mod 255 every * 5803 bytes. */ p = buffer; c0 = 0; c1 = 0; while (len != 0) { seglen = len; if ( block-- == 0 ) { seglen = offset_check % 5803; discard = 1; } else if ( seglen > 5803 ) seglen = 5803; for (i = 0; i < seglen; i++) { c0 = c0 + *(p++); c1 += c0; } if ( discard ) { /* * This works even if (offset_check % 5803) == 5802 */ p += 2; c1 += 2*c0; len -= 2; discard = 0; } c0 = c0 % 255; c1 = c1 % 255; len -= seglen; } factor = ( initlen - offset_check ) * c0; x = factor - c0 - c1; y = c1 - factor - 1; /* * This algorithm uses the 8 bits one's complement arithmetic. * Therefore, we must correct an effect produced * by the "standard" arithmetic (two's complement) */ if (x < 0 ) x--; if (y > 0 ) y++; x %= 255; y %= 255; if (x == 0) x = 0xFF; if (y == 0) y = 0x01; *result = ( x << 8 ) | ( y & 0xFF ); if (*result != checksum) return( CKSUM_NOT_OK ); /* XXX - what should the checksum field be? */ else return( CKSUM_OK ); }
static void dissect_btsmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; proto_item *ti; proto_tree *st; guint8 opcode; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMP"); switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_add_str(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_add_str(pinfo->cinfo, COL_INFO, "Rcvd "); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ", pinfo->p2p_dir); break; } if (tvb_length_remaining(tvb, 0) < 1) return; ti = proto_tree_add_item(tree, proto_btsmp, tvb, 0, -1, ENC_NA); st = proto_item_add_subtree(ti, ett_btsmp); proto_tree_add_item(st, hf_btsmp_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN); opcode = tvb_get_guint8(tvb, 0); offset++; col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_const(opcode, opcode_vals, "<unknown>")); switch (opcode) { case 0x01: /* Pairing Request */ case 0x02: /* Pairing Response */ { col_append_fstr(pinfo->cinfo, COL_INFO, ": "); proto_tree_add_item(st, hf_btsmp_io_capabilities, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; proto_tree_add_item(st, hf_btsmp_oob_data_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); proto_tree_add_item(st, hf_btsmp_max_enc_key_size, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, TRUE); offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, FALSE); break; } case 0x03: /* Pairing Confirm */ proto_tree_add_item(st, hf_btsmp_cfm_value, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x04: /* Pairing Random */ proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x05: /* Pairing Failed */ proto_tree_add_item(st, hf_btsmp_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(tvb_get_guint8(tvb, offset), reason_vals, "<unknown>")); offset++; break; case 0x06: /* Encryption Information */ proto_tree_add_item(st, hf_btsmp_long_term_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x07: /* Master Identification */ proto_tree_add_item(st, hf_btsmp_ediv, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 8, ENC_NA); offset += 8; break; case 0x08: /* Identity Information */ proto_tree_add_item(st, hf_btsmp_id_resolving_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x0a: /* Signing Informationn */ proto_tree_add_item(st, hf_btsmp_signature_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x0b: /* Security Request */ col_append_fstr(pinfo->cinfo, COL_INFO, ": "); offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); break; default: break; } }
static int dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree, int frame_offset) { guint64 rpt_sno; guint64 chkp_sno; guint64 upper_bound; guint64 lower_bound; int rcpt_clm_cnt; guint64 offset; guint64 length; int rpt_sno_size; int chkp_sno_size; int upper_bound_size; int lower_bound_size; int rcpt_clm_cnt_size; int offset_size; int length_size; int segment_offset = 0; int i; proto_item *ltp_rpt_item; proto_item *ltp_rpt_clm_item; proto_tree *ltp_rpt_tree; proto_tree *ltp_rpt_clm_tree; /* Create the subtree for report segment under the main LTP tree and all the report segment fields under it */ ltp_rpt_item = proto_tree_add_text(ltp_tree, tvb, frame_offset, -1, "Report Segment"); ltp_rpt_tree = proto_item_add_subtree(ltp_rpt_item, ett_rpt_segm); /* Extract the report segment info */ rpt_sno = evaluate_sdnv_64(tvb, frame_offset, &rpt_sno_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_sno, tvb, frame_offset + segment_offset, rpt_sno_size, rpt_sno); segment_offset += rpt_sno_size; chkp_sno = evaluate_sdnv_64(tvb, frame_offset + segment_offset, &chkp_sno_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_chkp, tvb, frame_offset + segment_offset, chkp_sno_size, chkp_sno); segment_offset += chkp_sno_size; upper_bound = evaluate_sdnv(tvb, frame_offset + segment_offset, &upper_bound_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_ub, tvb, frame_offset + segment_offset, upper_bound_size, upper_bound); segment_offset += upper_bound_size; lower_bound = evaluate_sdnv(tvb, frame_offset + segment_offset, &lower_bound_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_lb, tvb, frame_offset + segment_offset, lower_bound_size, lower_bound); segment_offset += lower_bound_size; rcpt_clm_cnt = evaluate_sdnv(tvb, frame_offset + segment_offset, &rcpt_clm_cnt_size); if (rcpt_clm_cnt < 0){ proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); expert_add_info_format_text(pinfo, ltp_tree, &ei_ltp_neg_reception_claim_count, "Negative reception claim count: %d", rcpt_clm_cnt); return 0; } /* Each reception claim is at least 2 bytes, so if the count is larger than the * max number of claims we can possibly squeeze into the remaining tvbuff, then * the packet is malformed. */ if (rcpt_clm_cnt > tvb_length_remaining(tvb, frame_offset + segment_offset) / 2) { proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); expert_add_info_format_text(pinfo, ltp_tree, &ei_ltp_mal_reception_claim, "Reception claim count impossibly large: %d > %d", rcpt_clm_cnt, tvb_length_remaining(tvb, frame_offset + segment_offset) / 2); return 0; } proto_tree_add_uint(ltp_rpt_tree, hf_ltp_rpt_clm_cnt, tvb, frame_offset + segment_offset, rcpt_clm_cnt_size, rcpt_clm_cnt); segment_offset += rcpt_clm_cnt_size; ltp_rpt_clm_item = proto_tree_add_text(ltp_rpt_tree, tvb, frame_offset + segment_offset, -1, "Reception claims"); ltp_rpt_clm_tree = proto_item_add_subtree(ltp_rpt_clm_item, ett_rpt_clm); /* There can be multiple reception claims in the same report segment */ for(i = 0; i<rcpt_clm_cnt; i++){ offset = evaluate_sdnv(tvb,frame_offset + segment_offset, &offset_size); proto_tree_add_uint64_format(ltp_rpt_clm_tree, hf_ltp_rpt_clm_off, tvb, frame_offset + segment_offset, offset_size, offset, "Offset[%d] : %"G_GINT64_MODIFIER"d", i, offset); segment_offset += offset_size; length = evaluate_sdnv(tvb,frame_offset + segment_offset, &length_size); proto_tree_add_uint64_format(ltp_rpt_clm_tree, hf_ltp_rpt_clm_len, tvb, frame_offset + segment_offset, length_size, length, "Length[%d] : %"G_GINT64_MODIFIER"d",i, length); segment_offset += length_size; } proto_item_set_end(ltp_rpt_clm_item, tvb, frame_offset + segment_offset); proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); return segment_offset; }
static void dissect_fcp_cmnd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, proto_tree *tree, conversation_t *conversation, fc_hdr *fchdr, fcp_conv_data_t *fcp_conv_data) { int offset = 0; int add_len = 0; guint8 flags, rwflags, lun0; guint16 lun = 0xffff; tvbuff_t *cdb_tvb; int tvb_len; fcp_request_data_t *request_data = NULL; itl_nexus_t itl; fcp_proto_data_t *proto_data; /* Determine the length of the FCP part of the packet */ flags = tvb_get_guint8(tvb, offset+10); if (flags) { add_len = tvb_get_guint8(tvb, offset+11) & 0x7C; add_len = add_len >> 2; } lun0 = tvb_get_guint8(tvb, offset); /* Display single-level LUNs in decimal for clarity */ /* I'm taking a shortcut here by assuming that if the first byte of the * LUN field is 0, it is a single-level LUN. This is not true. For a * real single-level LUN, all 8 bytes except byte 1 must be 0. */ if (lun0) { proto_tree_add_item(tree, hf_fcp_multilun, tvb, offset, 8, ENC_NA); lun = tvb_get_guint8(tvb, offset) & 0x3f; lun <<= 8; lun |= tvb_get_guint8(tvb, offset+1); } else { proto_tree_add_item(tree, hf_fcp_singlelun, tvb, offset+1, 1, ENC_BIG_ENDIAN); lun = tvb_get_guint8(tvb, offset+1); } if (!pinfo->fd->flags.visited) { proto_data = wmem_new(wmem_file_scope(), fcp_proto_data_t); proto_data->lun = lun; p_add_proto_data(wmem_file_scope(), pinfo, proto_fcp, 0, proto_data); } request_data = (fcp_request_data_t*)wmem_map_lookup(fcp_conv_data->luns, GUINT_TO_POINTER((guint)lun)); if (!request_data) { request_data = wmem_new(wmem_file_scope(), fcp_request_data_t); request_data->request_frame = pinfo->fd->num; request_data->response_frame = 0; request_data->request_time = pinfo->fd->abs_ts; request_data->itlq = wmem_new(wmem_file_scope(), itlq_nexus_t); request_data->itlq->first_exchange_frame=0; request_data->itlq->last_exchange_frame=0; request_data->itlq->lun=lun; request_data->itlq->scsi_opcode=0xffff; request_data->itlq->task_flags=0; request_data->itlq->data_length=0; request_data->itlq->bidir_data_length=0; request_data->itlq->fc_time=pinfo->fd->abs_ts; request_data->itlq->flags=0; request_data->itlq->alloc_len=0; request_data->itlq->extra_data=NULL; wmem_map_insert(fcp_conv_data->luns, GUINT_TO_POINTER((guint)lun), request_data); } /* populate the exchange struct */ if(!pinfo->fd->flags.visited){ if(fchdr->fctl&FC_FCTL_EXCHANGE_FIRST){ request_data->itlq->first_exchange_frame=pinfo->fd->num; request_data->itlq->fc_time = pinfo->fd->abs_ts; } if(fchdr->fctl&FC_FCTL_EXCHANGE_LAST){ request_data->itlq->last_exchange_frame=pinfo->fd->num; } } if (request_data->itlq) request_data->itlq->lun = lun; fchdr->lun = lun; proto_tree_add_item(tree, hf_fcp_crn, tvb, offset+8, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fcp_taskattr, tvb, offset+9, 1, ENC_BIG_ENDIAN); dissect_task_mgmt_flags(pinfo, tree, tvb, offset+10); proto_tree_add_item(tree, hf_fcp_addlcdblen, tvb, offset+11, 1, ENC_BIG_ENDIAN); rwflags = tvb_get_guint8(tvb, offset+11); if (request_data->itlq) { if (rwflags & 0x02) { request_data->itlq->task_flags |= SCSI_DATA_READ; } if (rwflags & 0x01) { request_data->itlq->task_flags |= SCSI_DATA_WRITE; } } proto_tree_add_item(tree, hf_fcp_rddata, tvb, offset+11, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fcp_wrdata, tvb, offset+11, 1, ENC_BIG_ENDIAN); tvb_len = tvb_length_remaining(tvb, offset+12); if (tvb_len > (16 + add_len)) tvb_len = 16 + add_len; itl.cmdset = 0xff; itl.conversation = conversation; cdb_tvb = tvb_new_subset_length(tvb, offset+12, tvb_len); dissect_scsi_cdb(cdb_tvb, pinfo, parent_tree, SCSI_DEV_UNKNOWN, request_data->itlq, &itl); proto_tree_add_item(tree, hf_fcp_dl, tvb, offset+12+16+add_len, 4, ENC_BIG_ENDIAN); if (request_data->itlq) { request_data->itlq->data_length = tvb_get_ntohl(tvb, offset+12+16+add_len); } if ( ((rwflags & 0x03) == 0x03) && tvb_length_remaining(tvb, offset+12+16+add_len+4) >= 4) { proto_tree_add_item(tree, hf_fcp_bidir_dl, tvb, offset+12+16+add_len+4, 4, ENC_BIG_ENDIAN); if (request_data->itlq) { request_data->itlq->bidir_data_length = tvb_get_ntohl(tvb, offset+12+16+add_len+4); } } }
/* * 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); expert_add_info(pinfo, cause, &ei_mtp2_checksum_error); } else { proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 2, "FCS 16: 0x%04x [correct]", rx_fcs_got); } } return next_tvb; }
/* entry point */ static gboolean dissect_pktgen(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti = NULL; proto_item *tmp = NULL; proto_tree *pktgen_tree = NULL; guint32 offset = 0; nstime_t tstamp; /* check for min size */ if(tvb_length(tvb) < 16) { /* Not a PKTGEN packet. */ return FALSE; } /* check for magic number */ if(tvb_memeql(tvb, 0, pktgen_magic, 4) == -1) { /* Not a PKTGEN packet. */ return FALSE; } /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PKTGEN"); if(check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "Seq: %u", tvb_get_ntohl(tvb, 4)); } if(tree) { /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_pktgen, tvb, 0, -1, FALSE); pktgen_tree = proto_item_add_subtree(ti, ett_pktgen); /* add items to the subtree */ proto_tree_add_item(pktgen_tree, hf_pktgen_magic, tvb, offset, 4, FALSE); offset+=4; proto_tree_add_item(pktgen_tree, hf_pktgen_seqnum, tvb, offset, 4, FALSE); offset+=4; tstamp.secs = tvb_get_ntohl(tvb, offset); tmp = proto_tree_add_item(pktgen_tree, hf_pktgen_tvsec, tvb, offset, 4, FALSE); PROTO_ITEM_SET_GENERATED(tmp); offset+=4; tstamp.nsecs = tvb_get_ntohl(tvb, offset) /* microsecond on the wire so... */ * 1000; tmp = proto_tree_add_item(pktgen_tree, hf_pktgen_tvusec, tvb, offset, 4, FALSE); PROTO_ITEM_SET_GENERATED(tmp); offset+=4; proto_tree_add_time(pktgen_tree, hf_pktgen_timestamp, tvb, offset - 8, 8, &tstamp); #if 0 if(tvb_length_remaining(tvb, offset)) /* random data */ proto_tree_add_text(pktgen_tree, tvb, offset, -1, "Data (%u bytes)", tvb_length_remaining(tvb, offset)); #else if(tvb_length_remaining(tvb, offset)) /* random data */ call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, pktgen_tree); #endif } return TRUE; }
/* dissector of each payload */ static int dissect_xtp_aseg(tvbuff_t *tvb, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *ti, *ti2, *top_ti; proto_tree *xtp_subtree; struct xtp_ip_addr_seg aseg[1]; int error = 0; top_ti = proto_tree_add_text(tree, tvb, offset, len, "Address Segment"); xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_aseg); if (len < XTP_NULL_ADDR_SEG_LEN) { proto_item_append_text(top_ti, ", bogus length(%u, must be at least %u)", len, XTP_NULL_ADDR_SEG_LEN); return 0; } /** parse common fields **/ /* alen(2) */ aseg->alen = tvb_get_ntohs(tvb, offset); offset += 2; /* adomain(1) */ aseg->adomain = tvb_get_guint8(tvb, offset); offset++; /* aformat(1) */ aseg->aformat = tvb_get_guint8(tvb, offset); /** display common fields **/ offset = start; /* alen(2) */ ti = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_alen, tvb, offset, 2, aseg->alen); offset += 2; if (aseg->alen > len) { proto_item_append_text(ti, ", bogus length(%u, must be at most %u)", aseg->alen, len); error = 1; } /* adomain(1) */ proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_adomain, tvb, offset, 1, aseg->adomain); offset++; /* aformat(1) */ ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_aformat, tvb, offset, 1, aseg->aformat); offset++; switch (aseg->aformat) { case 0: if (aseg->alen != XTP_NULL_ADDR_SEG_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be %u)", aseg->alen, XTP_NULL_ADDR_SEG_LEN); error = 1; } break; case 1: if (aseg->alen != XTP_IP_ADDR_SEG_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be %u)", aseg->alen, XTP_IP_ADDR_SEG_LEN); error = 1; } break; default: if (aseg->aformat < 128) { proto_item_append_text(ti2, ", Unsupported aformat(%u)", aseg->aformat); error = 1; } break; } if (error) return (offset - start); /** parse and display each address fileds */ switch (aseg->aformat) { case 0: /* address(4) */ aseg->dsthost = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_address, tvb, offset, 4, aseg->dsthost); offset += 4; break; case 1: /* dsthost(4) */ aseg->dsthost = tvb_get_ipv4(tvb, offset); proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_dsthost, tvb, offset, 4, aseg->dsthost); offset += 4; /* srchost(4) */ aseg->srchost = tvb_get_ipv4(tvb, offset); proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_srchost, tvb, offset, 4, aseg->srchost); offset += 4; /* dstport(2) */ aseg->dstport = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_dstport, tvb, offset, 2, aseg->dstport); offset += 2; /* srcport(2) */ aseg->srcport = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_srcport, tvb, offset, 2, aseg->srcport); offset += 2; /** add summary **/ proto_item_append_text(top_ti, ", Dst Port: %u", aseg->dstport); proto_item_append_text(top_ti, ", Src Port: %u", aseg->srcport); break; default: break; } return (offset - start); }
static void dissect_tacplus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tvbuff_t *new_tvb=NULL; proto_tree *tacplus_tree; proto_item *ti, *hidden_item; guint8 version,flags; proto_tree *flags_tree; proto_item *tf; proto_item *tmp_pi; guint32 len; gboolean request=( pinfo->destport == TCP_PORT_TACACS ); const char *key=NULL; len = tvb_get_ntohl(tvb, 8); if(len > (guint)tvb_length_remaining(tvb, 12) && pinfo->can_desegment && tacplus_preference_desegment) { pinfo->desegment_offset = 0; pinfo->desegment_len = len; return; } if( request ) { key=find_key( &pinfo->dst, &pinfo->src ); } else { key=find_key( &pinfo->src, &pinfo->dst ); } col_set_str(pinfo->cinfo, COL_PROTOCOL, "TACACS+"); if (check_col(pinfo->cinfo, COL_INFO)) { int type = tvb_get_guint8(tvb,1); col_add_fstr( pinfo->cinfo, COL_INFO, "%s: %s", request ? "Q" : "R", val_to_str(type, tacplus_type_vals, "Unknown (0x%02x)")); } if (tree) { ti = proto_tree_add_protocol_format(tree, proto_tacplus, tvb, 0, -1, "TACACS+"); tacplus_tree = proto_item_add_subtree(ti, ett_tacplus); if (pinfo->match_uint == pinfo->destport) { hidden_item = proto_tree_add_boolean(tacplus_tree, hf_tacplus_request, tvb, 0, 0, TRUE); } else { hidden_item = proto_tree_add_boolean(tacplus_tree, hf_tacplus_response, tvb, 0, 0, TRUE); } PROTO_ITEM_SET_HIDDEN(hidden_item); version = tvb_get_guint8(tvb,0); proto_tree_add_uint_format(tacplus_tree, hf_tacplus_majvers, tvb, 0, 1, version, "Major version: %s", (version&0xf0)==0xc0?"TACACS+":"Unknown Version"); proto_tree_add_uint(tacplus_tree, hf_tacplus_minvers, tvb, 0, 1, version&0xf); proto_tree_add_item(tacplus_tree, hf_tacplus_type, tvb, 1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tacplus_tree, hf_tacplus_seqno, tvb, 2, 1, ENC_BIG_ENDIAN); flags = tvb_get_guint8(tvb,3); tf = proto_tree_add_uint_format(tacplus_tree, hf_tacplus_flags, tvb, 3, 1, flags, "Flags: 0x%02x (%s payload, %s)", flags, (flags&FLAGS_UNENCRYPTED) ? "Unencrypted" : "Encrypted", (flags&FLAGS_SINGLE) ? "Single connection" : "Multiple Connections" ); flags_tree = proto_item_add_subtree(tf, ett_tacplus_flags); proto_tree_add_boolean(flags_tree, hf_tacplus_flags_payload_type, tvb, 3, 1, flags); proto_tree_add_boolean(flags_tree, hf_tacplus_flags_connection_type, tvb, 3, 1, flags); proto_tree_add_item(tacplus_tree, hf_tacplus_session_id, tvb, 4, 4, ENC_BIG_ENDIAN); if ((gint) len < 1) { proto_tree_add_text(tacplus_tree, tvb, 8, 4, "Invalid length: %u", len); THROW(ReportedBoundsError); } proto_tree_add_uint(tacplus_tree, hf_tacplus_packet_len, tvb, 8, 4, len); tmp_pi = proto_tree_add_text(tacplus_tree, tvb, TAC_PLUS_HDR_SIZE, len, "%s%s", ((flags&FLAGS_UNENCRYPTED)?"":"Encrypted "), request?"Request":"Reply" ); if( flags&FLAGS_UNENCRYPTED ) { new_tvb = tvb_new_subset( tvb, TAC_PLUS_HDR_SIZE, len, len ); } else { new_tvb=NULL; if( key && *key ){ tacplus_decrypted_tvb_setup( tvb, &new_tvb, pinfo, len, version, key ); } } if( new_tvb ) { /* Check to see if I've a decrypted tacacs packet */ if( !(flags&FLAGS_UNENCRYPTED) ){ tmp_pi = proto_tree_add_text(tacplus_tree, new_tvb, 0, len, "Decrypted %s", request?"Request":"Reply" ); } dissect_tacplus_body( tvb, new_tvb, proto_item_add_subtree( tmp_pi, ett_tacplus_body )); } } }
static int dissect_xtp_tspec(tvbuff_t *tvb, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *ti, *ti2; proto_tree *xtp_subtree; struct xtp_traffic_spec1 tspec[1]; int error = 0; ti = proto_tree_add_text(tree, tvb, offset, len, "Traffic Specifier"); xtp_subtree = proto_item_add_subtree(ti, ett_xtp_tspec); if (len < XTP_TRAFFIC_SPEC0_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be at least %u)", len, XTP_TRAFFIC_SPEC0_LEN); return 0; } /** parse common fields **/ /* tlen(2) */ tspec->tlen = tvb_get_ntohs(tvb, offset); offset += 2; /* service(1) */ tspec->service = tvb_get_guint8(tvb, offset); offset++; /* tformat(1) */ tspec->tformat = tvb_get_guint8(tvb, offset); /** display common fields */ offset = start; /* tlen(2) */ ti = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tlen, tvb, offset, 2, tspec->tlen); offset += 2; if (tspec->tlen > len) { proto_item_append_text(ti, ", bogus length(%u, must be at most %u)", tspec->tlen, len); error = 1; } /* service(1) */ proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_service, tvb, offset, 1, tspec->service); offset++; /* tformat(1) */ ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tformat, tvb, offset, 1, tspec->tformat); offset++; switch (tspec->tformat) { case 0: if (tspec->tlen != XTP_TRAFFIC_SPEC0_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be %u)", tspec->tlen, XTP_TRAFFIC_SPEC0_LEN); error = 1; } break; case 1: if (tspec->tlen != XTP_TRAFFIC_SPEC1_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be %u)", tspec->tlen, XTP_TRAFFIC_SPEC1_LEN); error = 1; } break; default: proto_item_append_text(ti2, ", Unsupported tformat(%u)", tspec->tformat); error = 1; break; } if (error) return (offset - start); /** parse and display each traffic fields **/ switch (tspec->tformat) { case 0: /* traffic(4) */ tspec->maxdata = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_traffic, tvb, offset, 4, tspec->maxdata); offset += 4; break; case 1: /* maxdata(4) */ tspec->maxdata = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_maxdata, tvb, offset, 4, tspec->maxdata); offset += 4; /* inrate(4) */ tspec->inrate = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inrate, tvb, offset, 4, tspec->inrate); offset += 4; /* inburst(4) */ tspec->inburst = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inburst, tvb, offset, 4, tspec->inburst); offset += 4; /* outrate(4) */ tspec->outrate = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outrate, tvb, offset, 4, tspec->outrate); offset += 4; /* outburst(4) */ tspec->outburst = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outburst, tvb, offset, 4, tspec->outburst); offset += 4; break; default: break; } return (offset - start); }
static int dissect_beep_tree(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, struct beep_request_val *request_val, struct beep_proto_data *beep_frame_data) { proto_tree *ti = NULL, *hdr = NULL; proto_item *hidden_item; int st_offset, msgno, ansno, seqno, size, channel, ackno, window, cc, more; const char * cmd_temp = NULL; int is_ANS = 0; st_offset = offset; if (tvb_strneql(tvb, offset, "MSG ", 4) == 0) cmd_temp = "Command: MSG"; if (tvb_strneql(tvb, offset, "RPY ", 4) == 0) cmd_temp = "Command: RPY"; if (tvb_strneql(tvb, offset, "ERR ", 4) == 0) cmd_temp = "Command: ERR"; if (tvb_strneql(tvb, offset, "NUL ", 4) == 0) cmd_temp = "Command: NUL"; if (tvb_strneql(tvb, offset, "ANS ", 4) == 0) { cmd_temp = "Command: ANS"; is_ANS = 1; } if (cmd_temp != NULL) { if (tree) { ti = proto_tree_add_text(tree, tvb, offset, header_len(tvb, offset) + 2, "Header"); hdr = proto_item_add_subtree(ti, ett_header); hidden_item = proto_tree_add_boolean(hdr, hf_beep_req, tvb, offset, 3, TRUE); proto_tree_add_text(hdr, tvb, offset, 3, "%s", cmd_temp); } offset += 4; /* Get the channel */ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_channel, &channel, req_chan_hfa); offset += 1; /* Skip the space */ /* Dissect the message number */ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_msgno, &msgno, req_msgno_hfa); offset += 1; /* skip the space */ /* Insert the more elements ... */ if ((more = dissect_beep_more(tvb, offset, hdr)) >= 0) { /* Figure out which direction this is in and what mime_hdr flag to * add to the beep_frame_data. If there are missing segments, this code * will get it wrong! */ set_mime_hdr_flags(more, request_val, beep_frame_data, pinfo); } else { /* Protocol violation, so dissect rest as undisectable */ if (tree) { proto_tree_add_text(hdr, tvb, offset, tvb_length_remaining(tvb, offset), "Undissected Payload: %s", tvb_format_text(tvb, offset, tvb_length_remaining(tvb, offset) ) ); } return -1; } offset += 2; /* Skip the flag and the space ... */ /* now for the seqno */ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_seqno, &seqno, req_seqno_hfa); offset += 1; /* skip the space */ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_size, &size, req_size_hfa); if (request_val) /* FIXME, is this the right order ... */ request_val -> size = size; /* Stash this away */ else { beep_frame_data->pl_size = size; if (beep_frame_data->pl_size < 0) beep_frame_data->pl_size = 0; /* FIXME: OK? */ } /* offset += 1; skip the space */ if (is_ANS) { /* We need to put in the ansno */ offset += 1; /* skip the space */ /* Dissect the message number */ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_ansno, &ansno, req_ansno_hfa); } if ((cc = check_term(tvb, offset, hdr)) <= 0) { /* We dissect the rest as data and bail ... */ if (tree) { proto_tree_add_text(hdr, tvb, offset, tvb_length_remaining(tvb, offset), "Undissected Payload: %s", tvb_format_text(tvb, offset, tvb_length_remaining(tvb, offset) ) ); } return -1; } offset += cc; /* Insert MIME header ... */ if (beep_frame_data && beep_frame_data->mime_hdr) offset += dissect_beep_mime_header(tvb, offset, beep_frame_data, hdr); /* Now for the payload, if any */ if (tvb_length_remaining(tvb, offset) > 0) { /* Dissect what is left as payload */ int pl_size = MIN(size, tvb_length_remaining(tvb, offset)); /* Except, check the payload length, and only dissect that much */ /* We need to keep track, in the conversation, of how much is left * so in the next packet, we can figure out what is part of the payload * and what is the next message */ if (tree) { proto_tree_add_text(tree, tvb, offset, pl_size, "Payload: %s", tvb_format_text(tvb, offset, pl_size)); } offset += pl_size; if (request_val) { request_val->size -= pl_size; if (request_val->size < 0) request_val->size = 0; } else { beep_frame_data->pl_size -= pl_size; if (beep_frame_data->pl_size < 0) beep_frame_data->pl_size = 0; } } /* If anything else left, dissect it ... */ if (tvb_length_remaining(tvb, offset) > 0) offset += dissect_beep_tree(tvb, offset, pinfo, tree, request_val, beep_frame_data); } else if (tvb_strneql(tvb, offset, "SEQ ", 4) == 0) { if (tree) { hidden_item = proto_tree_add_boolean(tree, hf_beep_seq, tvb, offset, 3, TRUE); proto_tree_add_text(tree, tvb, offset, 3, "Command: SEQ"); } offset += 3; /* Now check the space: FIXME */ offset += 1; offset += dissect_beep_int(tvb, offset, tree, hf_beep_channel, &channel, seq_chan_hfa); /* Check the space: FIXME */ offset += 1; offset += dissect_beep_int(tvb, offset, tree, hf_beep_ackno, &ackno, seq_ackno_hfa); /* Check the space: FIXME */ offset += 1; offset += dissect_beep_int(tvb, offset, tree, hf_beep_window, &window, seq_window_hfa); if ((cc = check_term(tvb, offset, tree)) <= 0) { /* We dissect the rest as data and bail ... */ if (tree) { proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "Undissected Payload: %s", tvb_format_text(tvb, offset, tvb_length_remaining(tvb, offset) ) ); } return -1; } offset += cc; } else if (tvb_strneql(tvb, offset, "END", 3) == 0) { proto_tree *tr = NULL; if (tree) { ti = proto_tree_add_text(tree, tvb, offset, MIN(5, tvb_length_remaining(tvb, offset)), "Trailer"); tr = proto_item_add_subtree(ti, ett_trailer); hidden_item = proto_tree_add_boolean(tr, hf_beep_end, tvb, offset, 3, TRUE); proto_tree_add_text(tr, tvb, offset, 3, "Command: END"); } offset += 3; if ((cc = check_term(tvb, offset, tr)) <= 0) { /* We dissect the rest as data and bail ... */ if (tree) { proto_tree_add_text(tr, tvb, offset, tvb_length_remaining(tvb, offset), "Undissected Payload: %s", tvb_format_text(tvb, offset, tvb_length_remaining(tvb, offset) ) ); } return -1; } offset += cc; } if (tvb_length_remaining(tvb, offset) > 0) { /* Dissect anything left over */ int pl_size = 0; if (request_val) { pl_size = MIN(request_val->size, tvb_length_remaining(tvb, offset)); if (pl_size == 0) { /* The whole of the rest must be payload */ pl_size = tvb_length_remaining(tvb, offset); /* Right place ? */ } } else if (beep_frame_data) { pl_size = MIN(beep_frame_data->pl_size, tvb_length_remaining(tvb, offset)); } else { /* Just in case */ pl_size = tvb_length_remaining(tvb, offset); } /* Take care here to handle the payload correctly, and if there is * another message here, then handle it correctly as well. */ /* If the pl_size == 0 and the offset == 0?, then we have not processed * anything in this frame above, so we better treat all this data as * payload to avoid recursion loops */ if (pl_size == 0 && offset == st_offset) pl_size = tvb_length_remaining(tvb, offset); if (pl_size > 0) { if (tree) { proto_tree_add_text(tree, tvb, offset, pl_size, "Payload: %s", tvb_format_text(tvb, offset, pl_size)); } offset += pl_size; /* Advance past the payload */ if (request_val){ request_val->size -= pl_size; /* Reduce payload by what we added */ if (request_val->size < 0) request_val->size = 0; } else { beep_frame_data->pl_size -= pl_size; if (beep_frame_data->pl_size < 0) beep_frame_data->pl_size = 0; } } if (tvb_length_remaining(tvb, offset) > 0) { offset += dissect_beep_tree(tvb, offset, pinfo, tree, request_val, beep_frame_data); } } return offset - st_offset; }
static void dissect_rpl_container(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 len, type, sublen, subtyp; proto_item *ti; proto_tree *rpl_container_tree; guint16 offset; gint ett_type; gint length, reported_length; len = tvb_get_ntohs(tvb, 0); proto_tree_add_text(tree, tvb, 0, 2, "Length: %u", len); type = tvb_get_ntohs(tvb, 2); proto_tree_add_text(tree, tvb, 2, 2, "Type: %s", val_to_str(type, rpl_type_vals, "Unknown Type")); offset = 4; switch (type) { case 1: case 2: case 4: case 8: case 0x10: case 0x20: while (len >= offset+4) { sublen = tvb_get_ntohs(tvb, offset); subtyp = tvb_get_ntohs(tvb, offset+2); ett_type = ett_rpl_unkn; if(subtyp == 0x0004) ett_type = ett_rpl_0004; if(subtyp == 0x0008) ett_type = ett_rpl_0008; if(subtyp == 0x4003) ett_type = ett_rpl_4003; if(subtyp == 0x4006) ett_type = ett_rpl_4006; if(subtyp == 0x4007) ett_type = ett_rpl_4007; if(subtyp == 0x4009) ett_type = ett_rpl_4009; if(subtyp == 0x400a) ett_type = ett_rpl_400a; if(subtyp == 0x400b) ett_type = ett_rpl_400b; if(subtyp == 0x400c) ett_type = ett_rpl_400c; if(subtyp == 0x4011) ett_type = ett_rpl_4011; if(subtyp == 0x4018) ett_type = ett_rpl_4018; if(subtyp == 0xc005) ett_type = ett_rpl_c005; if(subtyp == 0xc014) ett_type = ett_rpl_c014; ti = proto_tree_add_text(tree, tvb, offset, sublen, "%s", val_to_str(subtyp, rpl_type_vals, "Unknown Type")); rpl_container_tree = proto_item_add_subtree(ti, ett_type); length = tvb_length_remaining(tvb, offset); if (length > sublen) length = sublen; reported_length = tvb_reported_length_remaining(tvb, offset); if (reported_length > sublen) reported_length = sublen; if ( length > 0) { dissect_rpl_container(tvb_new_subset(tvb, offset, length, reported_length), pinfo, rpl_container_tree); offset += reported_length; } else { /* no more data, exit the loop */ offset += reported_length; break; } } break; case 0x4003: proto_tree_add_item(tree, hf_rpl_corrval, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case 0x4006: proto_tree_add_item(tree, hf_rpl_lmac, tvb, offset, 6, ENC_NA); offset += 6; break; case 0x4007: proto_tree_add_item(tree, hf_rpl_sap, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; break; case 0x4009: proto_tree_add_item(tree, hf_rpl_maxframe, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; case 0x400a: proto_tree_add_item(tree, hf_rpl_connclass, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; case 0x400b: proto_tree_add_item(tree, hf_rpl_respval, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; break; case 0x400c: proto_tree_add_item(tree, hf_rpl_smac, tvb, offset, 6, ENC_NA); offset += 6; break; case 0x4011: proto_tree_add_item(tree, hf_rpl_sequence, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case 0x4018: proto_tree_add_item(tree, hf_rpl_data, tvb, offset, len-4, ENC_NA); offset += len - 4; break; case 0xc005: proto_tree_add_item(tree, hf_rpl_config, tvb, offset, 8, ENC_NA); offset += 8; proto_tree_add_item(tree, hf_rpl_equipment, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_memsize, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_bsmversion, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_ec, tvb, offset, 6, ENC_NA); offset += 6; proto_tree_add_item(tree, hf_rpl_adapterid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_shortname, tvb, offset, 10, ENC_NA); offset += 10; break; case 0xc014: proto_tree_add_item(tree, hf_rpl_laddress, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_rpl_xaddress, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_rpl_flags, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; break; default: call_dissector(data_handle, tvb_new_subset_remaining(tvb, 4), pinfo, tree); break; } if (tvb_reported_length(tvb) > offset) call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); }
static void dissect_beep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset; struct beep_proto_data *beep_frame_data = NULL; proto_tree *beep_tree = NULL, *ti = NULL; conversation_t *conversation = NULL; struct beep_request_key request_key, *new_request_key; struct beep_request_val *request_val = NULL; offset = 0; /* If we have per frame data, use that, else, we must have lost the per- * frame data, and we have to do a full dissect pass again. * * The per-frame data tells us how much of this frame is left over from a * previous frame, so we dissect it as payload and then try to dissect the * rest. * * We use the conversation to build up info on the first pass over the * packets of type BEEP, and record anything that is needed if the user * does random dissects of packets in per packet data. * * Once we have per-packet data, we don't need the conversation stuff * anymore, but if per-packet data and conversation stuff gets deleted, as * it does under some circumstances when a rescan is done, it all gets * rebuilt. */ /* Find out what conversation this packet is part of ... but only * if we have no information on this packet, so find the per-frame * info first. */ beep_frame_data = p_get_proto_data(pinfo->fd, proto_beep); if (!beep_frame_data) { conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (conversation == NULL) { /* No conversation, create one */ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } /* * Check for and insert an entry in the request table if does not exist */ request_key.conversation = conversation->index; request_val = (struct beep_request_val *)g_hash_table_lookup(beep_request_hash, &request_key); if (!request_val) { /* Create one */ new_request_key = se_alloc(sizeof(struct beep_request_key)); new_request_key->conversation = conversation->index; request_val = se_alloc(sizeof(struct beep_request_val)); request_val->processed = 0; request_val->size = 0; g_hash_table_insert(beep_request_hash, new_request_key, request_val); } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "BEEP"); if (check_col(pinfo->cinfo, COL_INFO)) { /* Check the type ... */ /* "tvb_format_text()" is passed a value that won't go past the end * of the packet, so it won't throw an exception. */ col_add_str(pinfo->cinfo, COL_INFO, tvb_format_text(tvb, offset, tvb_length_remaining(tvb, offset))); } /* Here, we parse the message so we can retrieve the info we need, which * is that there is some payload left from a previous segment on the * front of this segment ... This all depends on TCP segments not getting * out of order ... * * As a huge kludge, we push the checking for the tree down into the code * and process as if we were given a tree but not call the routines that * adorn the protocol tree if they were NULL. */ if (tree) { /* Build the tree info ... */ ti = proto_tree_add_item(tree, proto_beep, tvb, offset, -1, FALSE); beep_tree = proto_item_add_subtree(ti, ett_beep); } /* Check the per-frame data and the conversation for any left-over * payload from the previous frame * * We check that per-frame data exists first, and if so, use it, * else we use the conversation data. * * We create per-frame data here as well, but we must ensure we create it * after we have done the check for per-frame or conversation data. * * We also depend on the first frame in a group having a pl_size of 0. */ if (beep_frame_data && beep_frame_data->pl_left > 0) { int pl_left = beep_frame_data->pl_left; pl_left = MIN(pl_left, tvb_length_remaining(tvb, offset)); /* Add the payload bit, only if we have a tree */ if (tree) { proto_tree_add_text(beep_tree, tvb, offset, pl_left, "Payload: %s", tvb_format_text(tvb, offset, pl_left)); } offset += pl_left; } else if (request_val && request_val->size > 0) { int pl_left = request_val->size; request_val->size = 0; /* We create the frame data here for this case, and * elsewhere for other frames */ beep_frame_data = se_alloc(sizeof(struct beep_proto_data)); beep_frame_data->pl_left = pl_left; beep_frame_data->pl_size = 0; beep_frame_data->mime_hdr = 0; p_add_proto_data(pinfo->fd, proto_beep, beep_frame_data); } /* Set up the per-frame data here if not already done so * This _must_ come after the checks above ... */ if (beep_frame_data == NULL) { beep_frame_data = se_alloc(sizeof(struct beep_proto_data)); beep_frame_data->pl_left = 0; beep_frame_data->pl_size = 0; beep_frame_data->mime_hdr = 0; p_add_proto_data(pinfo->fd, proto_beep, beep_frame_data); } if (tvb_length_remaining(tvb, offset) > 0) { offset += dissect_beep_tree(tvb, offset, pinfo, beep_tree, request_val, beep_frame_data); } }
static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *clnp_tree; proto_item *ti, *ti_len = NULL, *ti_pdu_len = NULL, *ti_tot_len = NULL; guint8 cnf_proto_id; guint8 cnf_hdr_len; guint8 cnf_vers; guint8 cnf_ttl; guint8 cnf_type; char flag_string[6+1]; const char *pdu_type_string; proto_tree *type_tree; guint16 segment_length; guint16 du_id = 0; guint16 segment_offset = 0; guint16 total_length; guint16 cnf_cksum; cksum_status_t cksum_status; int offset; guchar src_len, dst_len, nsel, opt_len = 0; const guint8 *dst_addr, *src_addr; guint next_length; proto_tree *discpdu_tree; gboolean save_in_error_pkt; fragment_head *fd_head; tvbuff_t *next_tvb; gboolean update_col_info = TRUE; gboolean save_fragmented; col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP"); col_clear(pinfo->cinfo, COL_INFO); cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID); if (cnf_proto_id == NLPID_NULL) { col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset"); ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA); clnp_tree = proto_item_add_subtree(ti, ett_clnp); proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1, cnf_proto_id, "Inactive subset"); next_tvb = tvb_new_subset_remaining(tvb, 1); if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0) call_dissector(data_handle,tvb, pinfo, tree); return; } /* return if version not known */ cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS); if (cnf_vers != ISO8473_V1) { call_dissector(data_handle,tvb, pinfo, tree); return; } /* fixed part decoding */ cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN); ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA); clnp_tree = proto_item_add_subtree(ti, ett_clnp); proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1, cnf_proto_id); ti_len = proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1, cnf_hdr_len); if (cnf_hdr_len < FIXED_PART_LEN) { /* Header length is less than the length of the fixed part of the header. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < minimum length %u", FIXED_PART_LEN); return; } proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1, cnf_vers); cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL); proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1, cnf_ttl, "Holding Time : %u (%u.%u secs)", cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5); cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE); pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals, "Unknown (0x%02x)"); flag_string[0] = '\0'; if (cnf_type & CNF_SEG_OK) g_strlcat(flag_string, "S ", 7); if (cnf_type & CNF_MORE_SEGS) g_strlcat(flag_string, "M ", 7); if (cnf_type & CNF_ERR_OK) g_strlcat(flag_string, "E ", 7); ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1, cnf_type, "PDU Type : 0x%02x (%s%s)", cnf_type, flag_string, pdu_type_string); type_tree = proto_item_add_subtree(ti, ett_clnp_type); proto_tree_add_item(type_tree, hf_clnp_cnf_segmentation, tvb, P_CLNP_TYPE, 1, ENC_NA); proto_tree_add_item(type_tree, hf_clnp_cnf_more_segments, tvb, P_CLNP_TYPE, 1, ENC_NA); proto_tree_add_item(type_tree, hf_clnp_cnf_report_error, tvb, P_CLNP_TYPE, 1, ENC_NA); proto_tree_add_item(type_tree, hf_clnp_cnf_type, tvb, P_CLNP_TYPE, 1, ENC_NA); /* If we don't have the full header - i.e., not enough to see the segmentation part and determine whether this datagram is segmented or not - set the Info column now; we'll get an exception before we set it otherwise. */ if (tvb_length(tvb) < cnf_hdr_len) { col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); } segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN); ti_pdu_len = proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2, segment_length); if (segment_length < cnf_hdr_len) { /* Segment length is less than the header length. */ expert_add_info_format(pinfo, ti_pdu_len, &ei_clnp_length, "PDU length < header length %u", cnf_hdr_len); return; } cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM); cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum); switch (cksum_status) { default: /* * No checksum present, or not enough of the header present to * checksum it. */ proto_tree_add_uint(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum); break; case CKSUM_OK: /* * Checksum is correct. */ proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "0x%04x (correct)", cnf_cksum); break; case CKSUM_NOT_OK: /* * Checksum is not correct. */ proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "0x%04x (incorrect)", cnf_cksum); break; } opt_len = cnf_hdr_len; opt_len -= FIXED_PART_LEN; /* Fixed part of Header */ /* address part */ offset = P_CLNP_ADDRESS_PART; if (opt_len < 1) { /* Header length is less than the minimum value in CLNP, including the destination address length. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1); return; } dst_len = tvb_get_guint8(tvb, offset); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1, dst_len); } offset += 1; opt_len -= 1; if (opt_len < dst_len) { /* Header length is less than the minimum value, including the destination address length and the destination address. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len); return; } dst_addr = tvb_get_ptr(tvb, offset, dst_len); nsel = tvb_get_guint8(tvb, offset + dst_len - 1); SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr); SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr); proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_dest, tvb, offset, dst_len, dst_addr, "%s", print_nsap_net(dst_addr, dst_len)); offset += dst_len; opt_len -= dst_len; if (opt_len < 1) { /* Header length is less than the minimum value, including the destination address length, the destination address, and the source address length. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1); return; } src_len = tvb_get_guint8(tvb, offset); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb, offset, 1, src_len); } offset += 1; opt_len -= 1; if (opt_len < src_len) { /* Header length is less than the minimum value, including the destination address length, the destination address, the source address length, and the source address. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1 + src_len); return; } src_addr = tvb_get_ptr(tvb, offset, src_len); SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr); SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr); proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_src, tvb, offset, src_len, src_addr, "%s", print_nsap_net(src_addr, src_len)); offset += src_len; opt_len -= src_len; /* Segmentation Part */ if (cnf_type & CNF_SEG_OK) { if (opt_len < SEGMENTATION_PART_LEN) { /* Header length is less than the minimum value, including the destination address length, the destination address, the source address length, the source address, and the segmentation part. */ expert_add_info_format(pinfo, ti_len, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN); return; } du_id = tvb_get_ntohs(tvb, offset); proto_tree_add_text(clnp_tree, tvb, offset, 2, "Data unit identifier: %06u", du_id); segment_offset = tvb_get_ntohs(tvb, offset + 2); proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2, "Segment offset : %6u", segment_offset); total_length = tvb_get_ntohs(tvb, offset + 4); ti_tot_len = proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2, "Total length : %6u", total_length); if (total_length < segment_length) { /* Reassembled length is less than the length of this segment. */ expert_add_info_format(pinfo, ti_tot_len, &ei_clnp_length, "Total length < segment length %u", segment_length); return; } offset += SEGMENTATION_PART_LEN; opt_len -= SEGMENTATION_PART_LEN; } dissect_osi_options(opt_len, tvb, offset, clnp_tree); offset += opt_len; /* If clnp_reassemble is on, this is a segment, we have all the * data in the segment, and the checksum is valid, then just add the * segment to the hashtable. */ save_fragmented = pinfo->fragmented; if (clnp_reassemble && (cnf_type & CNF_SEG_OK) && ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) && tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) && segment_length > cnf_hdr_len && cksum_status != CKSUM_NOT_OK) { fd_head = fragment_add_check(&clnp_reassembly_table, tvb, offset, pinfo, du_id, NULL, segment_offset, segment_length - cnf_hdr_len, cnf_type & CNF_MORE_SEGS); next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP", fd_head, &clnp_frag_items, &update_col_info, clnp_tree); } else { /* If this is the first segment, dissect its contents, otherwise just show it as a segment. XXX - if we eventually don't save the reassembled contents of all segmented datagrams, we may want to always reassemble. */ if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) { /* Not the first segment - don't dissect it. */ next_tvb = NULL; } else { /* First segment, or not segmented. Dissect what we have here. */ /* Get a tvbuff for the payload. Set its length to the segment length, and flag it as a fragment, so going past the end reports FragmentBoundsError, i.e. "there's data missing because this isn't reassembled", not ReportedBoundsError, i.e. "the dissector ran past the end of the packet, so the packet must not have been constructed properly". */ next_tvb = tvb_new_subset_length(tvb, offset, segment_length - cnf_hdr_len); tvb_set_fragment(next_tvb); /* * If this is the first segment, but not the only segment, * tell the next protocol that. */ if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS)) pinfo->fragmented = TRUE; else pinfo->fragmented = FALSE; } } if (next_tvb == NULL) { /* Just show this as a segment. */ col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)", pdu_type_string, flag_string, segment_offset); /* As we haven't reassembled anything, we haven't changed "pi", so we don't have to restore it. */ call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); pinfo->fragmented = save_fragmented; return; } if (tvb_offset_exists(tvb, offset)) { switch (cnf_type & CNF_TYPE) { case DT_NPDU: case MD_NPDU: /* Continue with COTP if any data. XXX - if this isn't the first Derived PDU of a segmented Initial PDU, skip that? */ if (nsel==NSEL_NET && tvb_get_guint8(next_tvb, 0)==NLPID_ISO10747_IDRP) { if(call_dissector(idrp_handle, next_tvb, pinfo, tree) != 0) { pinfo->fragmented = save_fragmented; return; } } if (nsel == (guchar)tp_nsap_selector || always_decode_transport) { if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) { pinfo->fragmented = save_fragmented; return; /* yes, it appears to be COTP or CLTP */ } } if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb, pinfo, tree, NULL)) { pinfo->fragmented = save_fragmented; return; /* yes, it appears to be one of the protocols in the heuristic list */ } break; case ER_NPDU: /* The payload is the header and "none, some, or all of the data part of the discarded PDU", i.e. it's like an ICMP error; dissect it as a CLNP PDU. */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); next_length = tvb_length_remaining(tvb, offset); if (next_length != 0) { /* We have payload; dissect it. */ ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length, "Discarded PDU"); discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu); /* Save the current value of the "we're inside an error packet" flag, and set that flag; subdissectors may treat packets that are the payload of error packets differently from "real" packets. */ save_in_error_pkt = pinfo->flags.in_error_pkt; pinfo->flags.in_error_pkt = TRUE; call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree); /* Restore the "we're inside an error packet" flag. */ pinfo->flags.in_error_pkt = save_in_error_pkt; } pinfo->fragmented = save_fragmented; return; /* we're done with this PDU */ case ERQ_NPDU: case ERP_NPDU: /* XXX - dissect this */ break; } } col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); call_dissector(data_handle,next_tvb, pinfo, tree); pinfo->fragmented = save_fragmented; } /* dissect_clnp */
static int sss_string(tvbuff_t* tvb, int hfinfo, proto_tree *sss_tree, int offset, gboolean little, guint32 length) { int foffset = offset; guint32 str_length; char buffer[1024]; guint32 i; guint8 c_char; gint length_remaining; if (length==0) { if (little) { str_length = tvb_get_letohl(tvb, foffset); } else { str_length = tvb_get_ntohl(tvb, foffset); } foffset += 4; } else { str_length = length; } length_remaining = tvb_length_remaining(tvb, foffset); if (length_remaining <= 0) { return foffset; } if (str_length > (guint)length_remaining || str_length > (sizeof(buffer)-1)) { proto_tree_add_string(sss_tree, hfinfo, tvb, foffset, length_remaining + 4, "<String too long to process>"); foffset += length_remaining; return foffset; } if (str_length == 0) { proto_tree_add_string(sss_tree, hfinfo, tvb, offset, 4, "<Not Specified>"); return foffset; } for ( i = 0; i < str_length; i++ ) { c_char = tvb_get_guint8(tvb, foffset); if (isprint(c_char)) { buffer[i] = c_char; } else { if (c_char) { buffer[i] = '.'; } else { /* Skip NULL-terminators */ i--; str_length--; } } foffset++; } buffer[i] = '\0'; if (length==0) { if (little) { str_length = tvb_get_letohl(tvb, offset); } else { str_length = tvb_get_ntohl(tvb, offset); } offset += 4; } else { str_length = length; } proto_tree_add_string(sss_tree, hfinfo, tvb, offset, str_length, buffer); return foffset; }