/* returns TRUE if this TCP segment carries a MPA REQUEST and FLASE otherwise */ static gboolean is_mpa_req(tvbuff_t *tvb, packet_info *pinfo) { conversation_t *conversation = NULL; mpa_state_t *state = NULL; guint8 mcrres; if (tvb_get_ntoh64(tvb, 0) != MPA_REQ_REP_FRAME || tvb_get_ntoh64(tvb, 8) != MPA_ID_REQ_FRAME) return FALSE; conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (!conversation) { conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } if (!get_mpa_state(conversation)) { /* associate a MPA connection state to this conversation if * there is no MPA state already associated to this connection */ state = init_mpa_state(); /* anaylize MPA connection parameter and record them */ mcrres = tvb_get_guint8(tvb, 16); state->ini_exp_m_res = mcrres & MPA_MARKER_FLAG; state->crc = mcrres & MPA_CRC_FLAG; state->revision = tvb_get_guint8(tvb, 17); state->req_frame_num = pinfo->fd->num; state->minfo[MPA_INITIATOR].port = pinfo->srcport; state->minfo[MPA_RESPONDER].port = pinfo->destport; conversation_add_proto_data(conversation, proto_iwarp_mpa, state); /* update expert info */ if (mcrres & MPA_RESERVED_FLAG) expert_add_info_format(pinfo, NULL, PI_REQUEST_CODE, PI_WARN, "Res field is NOT set to zero as required by RFC 5044"); if (state->revision != 1) expert_add_info_format(pinfo, NULL, PI_REQUEST_CODE, PI_WARN, "Rev field is NOT set to one as required by RFC 5044"); } return TRUE; }
/* * get a Blefuscuoan signed 64 bit integer from a tvb */ WSLUA_METHOD TvbRange_int64(lua_State* L) { /* Get a Big Endian (network order) signed 64 bit integer from a TvbRange. The range must be 1-8 octets long. */ TvbRange tvbr = checkTvbRange(L,1); if (!(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } switch (tvbr->len) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: { Int64 num = (Int64)g_malloc(sizeof(gint64)); *num = (gint64)tvb_get_ntoh64(tvbr->tvb->ws_tvb,tvbr->offset); pushInt64(L,num); WSLUA_RETURN(1); } default: luaL_error(L,"TvbRange:int64() does not handle %d byte integers",tvbr->len); return 0; } }
/* * get a Blefuscuoan signed 64 bit integer from a tvb */ WSLUA_METHOD TvbRange_int64(lua_State* L) { /* Get a Big Endian (network order) signed 64 bit integer from a `TvbRange`, as an `Int64` object. The range must be 1, 2, 4 or 8 octets long. */ TvbRange tvbr = checkTvbRange(L,1); if (!(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } switch (tvbr->len) { case 1: pushInt64(L,(gint8)tvb_get_guint8(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 2: pushInt64(L,(gint16)tvb_get_ntohs(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 4: pushInt64(L,(gint32)tvb_get_ntohl(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 8: pushInt64(L,(gint64)tvb_get_ntoh64(tvbr->tvb->ws_tvb,tvbr->offset)); WSLUA_RETURN(1); /* The `Int64` object. */ default: luaL_error(L,"TvbRange:int64() does not handle %d byte integers",tvbr->len); return 0; } }
static void add_time_details( proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, guint32 offset) { guint64 time; time = tvb_get_ntoh64(tvb, offset + 1 ); proto_tree_add_item(tree, hf_mc_time, tvb, offset + 1, 8, FALSE); }
static guint64 corosync_totemsrp_get_guint64(tvbuff_t* tvb, gint offset, const guint encoding) { if (encoding == ENC_LITTLE_ENDIAN) return tvb_get_letoh64(tvb, offset); return tvb_get_ntoh64(tvb, offset); }
/* returns TRUE if this TCP segment carries a MPA REPLY and FALSE otherwise */ static gboolean is_mpa_rep(tvbuff_t *tvb, packet_info *pinfo) { conversation_t *conversation = NULL; mpa_state_t *state = NULL; guint8 mcrres; if (tvb_get_ntoh64(tvb, 0) != MPA_REQ_REP_FRAME || tvb_get_ntoh64(tvb, 8) != MPA_ID_REP_FRAME) { return FALSE; } conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (!conversation) { return FALSE; } state = get_mpa_state(conversation); if (!state) { return FALSE; } if (!state->full_operation) { /* update state of this conversation */ mcrres = tvb_get_guint8(tvb, 16); state->res_exp_m_ini = mcrres & MPA_MARKER_FLAG; state->crc = state->crc | (mcrres & MPA_CRC_FLAG); state->rep_frame_num = pinfo->fd->num; /* enter Full Operation Phase only if the Reject bit is not set */ if (!(mcrres & MPA_REJECT_FLAG)) state->full_operation = TRUE; else expert_add_info_format(pinfo, NULL, PI_RESPONSE_CODE, PI_NOTE, "Reject bit set by Responder"); } return TRUE; }
/* returns TRUE if this TCP segment carries a MPA REQUEST and FLASE otherwise */ static gboolean is_mpa_req(tvbuff_t *tvb, packet_info *pinfo) { conversation_t *conversation = NULL; mpa_state_t *state = NULL; guint8 mcrres; if (tvb_get_ntoh64(tvb, 0) != MPA_REQ_REP_FRAME || tvb_get_ntoh64(tvb, 8) != MPA_ID_REQ_FRAME) return FALSE; conversation = find_or_create_conversation(pinfo); if (!get_mpa_state(conversation)) { /* associate a MPA connection state to this conversation if * there is no MPA state already associated to this connection */ state = init_mpa_state(); /* anaylize MPA connection parameter and record them */ mcrres = tvb_get_guint8(tvb, 16); state->ini_exp_m_res = mcrres & MPA_MARKER_FLAG; state->crc = mcrres & MPA_CRC_FLAG; state->revision = tvb_get_guint8(tvb, 17); state->req_frame_num = pinfo->fd->num; state->minfo[MPA_INITIATOR].port = pinfo->srcport; state->minfo[MPA_RESPONDER].port = pinfo->destport; conversation_add_proto_data(conversation, proto_iwarp_mpa, state); /* update expert info */ if (mcrres & MPA_RESERVED_FLAG) expert_add_info(pinfo, NULL, &ei_mpa_res_field_not_set0); if (state->revision != 1) expert_add_info(pinfo, NULL, &ei_mpa_rev_field_not_set1); } return TRUE; }
static int dlm_name_handler(proto_tree *tree, tvbuff_t *tvb, guint offset, int namelen) { guint8 lock_type; guint64 blkno; proto_item *ti; ti = proto_tree_add_item(tree, hf_dlm_name, tvb, offset, namelen, ENC_ASCII|ENC_NA); lock_type = tvb_get_guint8(tvb, offset); if (lock_type == 'N') { blkno = tvb_get_ntoh64(tvb, offset + OCFS2_DENTRY_LOCK_INO_START); proto_item_append_text(ti, "%08x", (unsigned int)blkno); } return offset + namelen; }
static int dissect_kt_replication(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset) { gint new_offset; guint32 next32, size; guint64 ts; nstime_t ns_ts; proto_item *pi; new_offset = offset; proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN); new_offset++; if (tvb_reported_length_remaining(tvb, new_offset) > 0) { next32 = tvb_get_ntohl(tvb, new_offset); if (next32 <= 1) { /* This means request. the 32 bits are flags */ proto_tree_add_item(tree, hf_kt_flags, tvb, new_offset, 4, ENC_BIG_ENDIAN); new_offset += 4; proto_tree_add_item(tree, hf_kt_ts, tvb, new_offset, 8, ENC_BIG_ENDIAN); new_offset += 8; proto_tree_add_item(tree, hf_kt_sid, tvb, new_offset, 2, ENC_BIG_ENDIAN); new_offset += 2; } else { /* This is a response. The 32 bits are the first half of the ts */ ts = tvb_get_ntoh64(tvb, new_offset); ns_ts.secs = (time_t)(ts/1000000000); ns_ts.nsecs = (int)(ts%1000000000); proto_tree_add_time(tree, hf_kt_ts, tvb, new_offset, 8, &ns_ts); new_offset += 8; size = tvb_get_ntohl(tvb, new_offset); proto_tree_add_uint(tree, hf_kt_size, tvb, new_offset, 4, size); new_offset += 4; proto_tree_add_item(tree, hf_kt_log, tvb, new_offset, size, ENC_NA); new_offset += size; } } else { /* This is an empty ack to the message with magic 0xB0. */ pi = proto_tree_add_uint(tree, hf_kt_type, tvb, offset, 1, KT_OPER_RESPONSE); PROTO_ITEM_SET_GENERATED(pi); col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[response]"); } return new_offset; }
static gint32 tvb_get_ntohint(tvbuff_t * tvb, guint offset, guint size) { switch(size) { case 1: return (gint32)tvb_get_guint8(tvb, offset); case 2: return (gint32)tvb_get_ntohs(tvb, offset); case 3: return (gint32)tvb_get_ntoh24(tvb, offset); case 4: return (gint32)tvb_get_ntohl(tvb, offset); /*case 5: return (gint32)tvb_get_ntoh40(tvb, offset); */ /*case 6: return (gint32)tvb_get_ntoh48(tvb, offset); */ /*case 7: return (gint32)tvb_get_ntoh56(tvb, offset); */ case 8: return (gint32)tvb_get_ntoh64(tvb, offset); default: break; } DISSECTOR_ASSERT(FALSE); return 0; }
static int dlm_cookie_handler(proto_tree *tree, tvbuff_t *tvb, guint offset, int hf_cookie) { proto_item *item; guint64 cookie; guint64 seq; guint8 node_idx; item = proto_tree_add_item(tree, hf_cookie, tvb, offset, 8, ENC_BIG_ENDIAN); cookie = tvb_get_ntoh64(tvb, offset); cookie >>= 56; node_idx = (guint8)((cookie >> 56) & G_GINT64_CONSTANT(0xff)); seq = cookie & G_GINT64_CONSTANT(0x00ffffffffffffff); proto_item_append_text(item, " (%u:%" G_GINT64_MODIFIER "u)", node_idx, seq); return offset + 8; }
/* Dissection routines */ static int dissect_kt_replication_wait(tvbuff_t *tvb, proto_tree *tree, gint offset) { gint new_offset; guint64 ts; nstime_t ns_ts; new_offset = offset; proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN); new_offset++; ts = tvb_get_ntoh64(tvb, new_offset); ns_ts.secs = (time_t)(ts/1000000000); ns_ts.nsecs = (int)(ts%1000000000); proto_tree_add_time(tree, hf_kt_ts, tvb, new_offset, 8, &ns_ts); new_offset += 8; return new_offset; }
/* Dissection routines */ static int dissect_kt_replication_wait(tvbuff_t *tvb, proto_tree *tree) { int offset; guint64 ts; nstime_t ns_ts; proto_item *pi; pi = proto_tree_add_uint(tree, hf_kt_type, tvb, 0, 1, KT_OPER_REQUEST); PROTO_ITEM_SET_GENERATED(pi); offset = 1; ts = tvb_get_ntoh64(tvb, offset); ns_ts.secs = (time_t)(ts/1000000000); ns_ts.nsecs = (int)(ts%1000000000); proto_tree_add_time(tree, hf_kt_ts, tvb, offset, 8, &ns_ts); offset += 8; return offset; }
static int dissect_daap_one_tag(proto_tree *tree, tvbuff_t *tvb, int offset, int length) { unsigned int tagname; int tagsize; int new_offset; proto_item *ti = NULL; proto_item *ti2 = NULL; proto_tree *new_tree = NULL; do { if (!tvb_offset_exists(tvb, offset)) break; tagname = tvb_get_ntohl(tvb, offset); tagsize = tvb_get_ntohl(tvb, offset+4); tvb_ensure_bytes_exist(tvb, offset, tagsize+8); ti = proto_tree_add_text(tree, tvb, offset, tagsize+8, "Tag: %c%c%c%c, Size: %d", tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3), tagsize); ti2 = proto_tree_add_item(tree, hf_daap_name, tvb, offset, 4, FALSE); PROTO_ITEM_SET_HIDDEN(ti2); ti2 = proto_tree_add_item(tree, hf_daap_size, tvb, offset+4, 4, FALSE); PROTO_ITEM_SET_HIDDEN(ti2); offset += 8; length -= 8; switch (tagname) { case daap_mcon: case daap_msrv: case daap_mccr: case daap_mdcl: case daap_mlog: case daap_mupd: case daap_avdb: case daap_mlcl: case daap_mlit: case daap_mbcl: case daap_adbs: case daap_aply: case daap_apso: case daap_mudl: case daap_abro: case daap_abal: case daap_abcp: case daap_abgn: case daap_prsv: case daap_arif: /* Container tags */ new_tree = proto_item_add_subtree(ti, ett_daap_sub); new_offset = dissect_daap_one_tag(new_tree, tvb, offset, tagsize); break; case daap_minm: case daap_msts: case daap_mcnm: case daap_mcna: case daap_asal: case daap_asar: case daap_ascm: case daap_asfm: case daap_aseq: case daap_asgn: case daap_asdt: case daap_asul: /* Tags contain strings */ proto_item_append_text(ti, ", Data: %s", tvb_format_text(tvb, offset, tagsize)); break; case daap_mper: /* Tags conain uint64 */ proto_item_append_text(ti, ", Persistent Id: %" G_GINT64_MODIFIER "u", tvb_get_ntoh64(tvb, offset)); break; case daap_mstt: proto_item_append_text(ti, ", Status: %d", tvb_get_ntohl(tvb, offset)); break; case daap_musr: case daap_msur: proto_item_append_text(ti, ", Revision: %d", tvb_get_ntohl(tvb, offset)); break; case daap_miid: case daap_mcti: case daap_mpco: case daap_mlid: proto_item_append_text(ti, ", Id: %d", tvb_get_ntohl(tvb, offset)); break; case daap_mrco: case daap_mtco: case daap_mimc: case daap_msdc: proto_item_append_text(ti, ", Count: %d", tvb_get_ntohl(tvb, offset)); break; case daap_mstm: proto_item_append_text(ti, ", Timeout: %d seconds", tvb_get_ntohl(tvb, offset)); break; case daap_asda: case daap_asdm: case daap_assr: case daap_assz: case daap_asst: case daap_assp: case daap_astm: case daap_aeNV: /* Tags conain uint32 */ proto_item_append_text(ti, ", Data: %d", tvb_get_ntohl(tvb, offset)); break; case daap_mcty: case daap_asbt: case daap_asbr: case daap_asdc: case daap_asdn: case daap_astc: case daap_astn: case daap_asyr: /* Tags conain uint16 */ proto_item_append_text(ti, ", Data: %d", tvb_get_ntohs(tvb, offset)); break; case daap_mikd: case daap_msau: case daap_msty: case daap_asrv: case daap_asur: case daap_asdk: /* Tags conain uint8 */ proto_item_append_text(ti, ", Data: %d", tvb_get_guint8(tvb, offset)); break; case daap_mslr: case daap_msal: case daap_msup: case daap_mspi: case daap_msex: case daap_msbr: case daap_msqy: case daap_msix: case daap_msrs: case daap_asco: case daap_asdb: case daap_abpl: case daap_aeSP: /* Tags ARE boolean. Data is (uint8), but it seems * the value is always zero. So, if the tag is present * the "bool" is true. */ proto_item_append_text(ti, ", Data: True"); break; case daap_mpro: case daap_apro: /* Tags conain version (uint32) */ proto_item_append_text(ti, ", Version: %d.%d.%d.%d", tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3)); break; default: break; } offset += tagsize; length -= tagsize; } while (length > 0); return offset; }
/* Decode an EXT_FTI extension and fill FEC array */ void fec_decode_ext_fti(struct _ext *e, tvbuff_t *tvb, proto_tree *tree, gint ett, struct _fec_ptr f) { proto_item* ti = NULL; proto_tree *ext_tree; if (tree) ti = proto_tree_add_none_format(tree, f.hf->fti_header, tvb, e->offset, e->length, "EXT_FTI, FEC Object Transmission Information (%u)", e->het); if (f.fec->encoding_id_present) { ext_tree = proto_item_add_subtree(ti, ett); rmt_ext_decode_default_header(e, tvb, ext_tree); /* Decode 48-bit length field */ f.fec->transfer_length = tvb_get_ntoh64(tvb, e->offset) & G_GINT64_CONSTANT(0xFFFFFFFFFFFFU); if (f.fec->encoding_id >= 128) { /* Decode FEC Instance ID */ f.fec->instance_id_present = TRUE; f.fec->instance_id = (guint8) tvb_get_ntohs(tvb, e->offset+8); } if (tree) proto_tree_add_uint64(ext_tree, f.hf->fti_transfer_length, tvb, e->offset+2, 6, f.fec->transfer_length); switch (f.fec->encoding_id) { case 0: case 2: case 128: case 130: f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10); f.fec->max_source_block_length = tvb_get_ntohl(tvb, e->offset+12); if (tree) { proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 4, f.fec->max_source_block_length); } break; case 129: f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10); f.fec->max_source_block_length = tvb_get_ntohs(tvb, e->offset+12); f.fec->max_number_encoding_symbols = tvb_get_ntohs(tvb, e->offset+14); if (tree) { proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 2, f.fec->max_source_block_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_number_encoding_symbols, tvb, e->offset+14, 2, f.fec->max_number_encoding_symbols); } break; case 132: f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10); f.fec->max_source_block_length = tvb_get_ntohl(tvb, e->offset+12); f.fec->max_number_encoding_symbols = tvb_get_ntohl(tvb, e->offset+16); if (tree) { proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 4, f.fec->max_source_block_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_number_encoding_symbols, tvb, e->offset+16, 4, f.fec->max_number_encoding_symbols); } break; } } else if (tree) rmt_ext_decode_default_subtree(e, tvb, ti, ett); }
static void dissect_nflog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { const int start_tlv_offset = 4; proto_tree *nflog_tree = NULL; proto_item *ti; int offset = 0; tvbuff_t *next_tvb = NULL; int aftype; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NFLOG"); col_clear(pinfo->cinfo, COL_INFO); aftype = tvb_get_guint8(tvb, 0); /* Header */ if (proto_field_is_referenced(tree, hfi_nflog->id)) { ti = proto_tree_add_item(tree, hfi_nflog, tvb, 0, -1, ENC_NA); nflog_tree = proto_item_add_subtree(ti, ett_nflog); proto_tree_add_item(nflog_tree, &hfi_nflog_family, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(nflog_tree, &hfi_nflog_version, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(nflog_tree, &hfi_nflog_resid, tvb, offset, 2, ENC_BIG_ENDIAN); /*offset += 2;*/ } offset = start_tlv_offset; /* TLVs */ while (tvb_reported_length_remaining(tvb, offset) >= 4) { guint16 tlv_len = tvb_get_h_guint16(tvb, offset + 0); guint16 tlv_type; guint16 value_len; proto_tree *tlv_tree; /* malformed */ if (tlv_len < 4) return; value_len = tlv_len - 4; tlv_type = (tvb_get_h_guint16(tvb, offset + 2) & 0x7fff); if (nflog_tree) { gboolean handled = FALSE; ti = proto_tree_add_bytes_format(nflog_tree, hfi_nflog_tlv.id, tvb, offset, tlv_len, NULL, "TLV Type: %s (%u), Length: %u", val_to_str_const(tlv_type, nflog_tlv_vals, "Unknown"), tlv_type, tlv_len); tlv_tree = proto_item_add_subtree(ti, ett_nflog_tlv); proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_length, tvb, offset + 0, 2, ENC_HOST_ENDIAN); proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_type, tvb, offset + 2, 2, ENC_HOST_ENDIAN); switch (tlv_type) { case WS_NFULA_PAYLOAD: handled = TRUE; break; case WS_NFULA_PREFIX: if (value_len >= 1) { proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_prefix, tvb, offset + 4, value_len, ENC_NA); handled = TRUE; } break; case WS_NFULA_UID: if (value_len == 4) { proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_uid, tvb, offset + 4, value_len, ENC_BIG_ENDIAN); handled = TRUE; } break; case WS_NFULA_GID: if (value_len == 4) { proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_gid, tvb, offset + 4, value_len, ENC_BIG_ENDIAN); handled = TRUE; } break; case WS_NFULA_TIMESTAMP: if (value_len == 16) { nstime_t ts; ts.secs = (time_t)tvb_get_ntoh64(tvb, offset + 4); /* XXX - add an "expert info" warning if this is >= 10^9? */ ts.nsecs = (int)tvb_get_ntoh64(tvb, offset + 12); proto_tree_add_time(tlv_tree, &hfi_nflog_tlv_timestamp, tvb, offset + 4, value_len, &ts); handled = TRUE; } break; } if (!handled) proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_unknown, tvb, offset + 4, value_len, ENC_NA); } if (tlv_type == WS_NFULA_PAYLOAD) next_tvb = tvb_new_subset_length(tvb, offset + 4, value_len); offset += ((tlv_len + 3) & ~3); /* next TLV aligned to 4B */ } if (next_tvb) { switch (aftype) { case LINUX_AF_INET: call_dissector(ip_handle, next_tvb, pinfo, tree); break; case LINUX_AF_INET6: call_dissector(ip6_handle, next_tvb, pinfo, tree); break; default: call_dissector(data_handle, next_tvb, pinfo, tree); break; } } }
/* dissect EDID data from the receiver return the offset after the dissected data */ static gint dissect_hdmi_edid(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree) { proto_item *yi; proto_tree *edid_tree; guint64 edid_hdr; guint16 manf_id; gchar manf_id_str[4]; /* 3 letters + 0-termination */ guint8 week, year; int year_hf; edid_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_hdmi_edid, NULL, "Extended Display Identification Data (EDID)"); edid_hdr = tvb_get_ntoh64(tvb, offset); if (edid_hdr != EDID_HDR_VALUE) return offset; /* XXX handle fragmented EDID messages */ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "EDID"); proto_tree_add_item(edid_tree, hf_hdmi_edid_hdr, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* read as big endian for easier splitting */ manf_id = tvb_get_ntohs(tvb, offset); /* XXX check that MSB is 0 */ manf_id_str[0] = CAPITAL_LETTER(manf_id, 10); manf_id_str[1] = CAPITAL_LETTER(manf_id, 5); manf_id_str[2] = CAPITAL_LETTER(manf_id, 0); manf_id_str[3] = 0; proto_tree_add_string(edid_tree, hf_hdmi_edid_manf_id, tvb, offset, 2, manf_id_str); offset += 2; proto_tree_add_item(edid_tree, hf_hdmi_edid_manf_prod_code, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(edid_tree, hf_hdmi_edid_manf_serial, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; week = tvb_get_guint8(tvb, offset); proto_tree_add_item(edid_tree, hf_hdmi_edid_manf_week, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; year_hf = week == 255 ? hf_hdmi_edid_mod_year : hf_hdmi_edid_manf_year; year = tvb_get_guint8(tvb, offset); yi = proto_tree_add_item(edid_tree, year_hf, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(yi, " (year %d)", 1990+year); offset += 1; proto_tree_add_item(edid_tree, hf_hdmi_edid_version, tvb, offset, 2, ENC_BIG_ENDIAN); /* XXX dissect the parts following the EDID header */ return tvb_reported_length(tvb); }
static int dissect_kt_get_bulk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset) { guint32 next32, rnum, ksiz, vsiz; guint64 xt; nstime_t ts; gint new_offset, rec_start_offset; proto_item *ti; proto_item *pi; proto_tree *rec_tree; new_offset = offset; proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN); new_offset++; next32 = tvb_get_ntohl(tvb, new_offset); if (next32 == 0) { if (tvb_reported_length_remaining(tvb, (new_offset + 4)) > 0) { /* request */ pi = proto_tree_add_uint(tree, hf_kt_type, tvb, offset, 1, KT_OPER_REQUEST); PROTO_ITEM_SET_GENERATED(pi); proto_tree_add_uint(tree, hf_kt_flags, tvb, new_offset, 4, next32); new_offset += 4; rnum = tvb_get_ntohl(tvb, new_offset); proto_tree_add_uint(tree, hf_kt_rnum, tvb, new_offset, 4, rnum); new_offset += 4; while (rnum > 0) { /* Create a sub-tree for each record */ ti = proto_tree_add_item(tree, hf_kt_rec, tvb, new_offset, -1, ENC_NA); rec_tree = proto_item_add_subtree(ti, ett_kt_rec); rec_start_offset = new_offset; proto_tree_add_item(rec_tree, hf_kt_dbidx, tvb, new_offset, 2, ENC_BIG_ENDIAN); new_offset += 2; ksiz = tvb_get_ntohl(tvb, new_offset); proto_tree_add_uint(rec_tree, hf_kt_ksiz, tvb, new_offset, 4, ksiz); new_offset += 4; proto_tree_add_item(rec_tree, hf_kt_key, tvb, new_offset, ksiz, ENC_NA); if (kt_present_key_val_as_ascii) { pi = proto_tree_add_item(rec_tree, hf_kt_key_str, tvb, new_offset, ksiz, ENC_ASCII|ENC_NA); PROTO_ITEM_SET_GENERATED(pi); } new_offset += ksiz; proto_item_set_len(ti, new_offset - rec_start_offset); rnum--; } } else { /* response - no records */ pi = proto_tree_add_uint(tree, hf_kt_type, tvb, offset, 1, KT_OPER_RESPONSE); PROTO_ITEM_SET_GENERATED(pi); col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[response]"); proto_tree_add_uint(tree, hf_kt_hits, tvb, new_offset, 4, next32); new_offset += 4; } } else { /* response - one or more records */ pi = proto_tree_add_uint(tree, hf_kt_type, tvb, offset, 1, KT_OPER_RESPONSE); PROTO_ITEM_SET_GENERATED(pi); col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[response]"); rnum = tvb_get_ntohl(tvb, new_offset); proto_tree_add_uint(tree, hf_kt_hits, tvb, new_offset, 4, rnum); new_offset += 4; while (rnum > 0) { /* Create a sub-tree for each record */ ti = proto_tree_add_item(tree, hf_kt_rec, tvb, new_offset, -1, ENC_NA); rec_tree = proto_item_add_subtree(ti, ett_kt_rec); rec_start_offset = new_offset; proto_tree_add_item(rec_tree, hf_kt_dbidx, tvb, new_offset, 2, ENC_BIG_ENDIAN); new_offset += 2; ksiz = tvb_get_ntohl(tvb, new_offset); proto_tree_add_uint(rec_tree, hf_kt_ksiz, tvb, new_offset, 4, ksiz); new_offset += 4; vsiz = tvb_get_ntohl(tvb, new_offset); proto_tree_add_uint(rec_tree, hf_kt_vsiz, tvb, new_offset, 4, vsiz); new_offset += 4; xt = tvb_get_ntoh64(tvb, new_offset); ts.secs = (time_t)(xt&0xFFFFFFFF); ts.nsecs = 0; proto_tree_add_time(rec_tree, hf_kt_xt_resp, tvb, new_offset, 8, &ts); new_offset += 8; proto_tree_add_item(rec_tree, hf_kt_key, tvb, new_offset, ksiz, ENC_NA); if (kt_present_key_val_as_ascii) { pi = proto_tree_add_item(rec_tree, hf_kt_key_str, tvb, new_offset, ksiz, ENC_ASCII|ENC_NA); PROTO_ITEM_SET_GENERATED(pi); } new_offset += ksiz; proto_tree_add_item(rec_tree, hf_kt_val, tvb, new_offset, vsiz, ENC_NA); if (kt_present_key_val_as_ascii) { pi = proto_tree_add_item(rec_tree, hf_kt_val_str, tvb, new_offset, vsiz, ENC_ASCII|ENC_NA); PROTO_ITEM_SET_GENERATED(pi); } new_offset += vsiz; proto_item_set_len(ti, new_offset - rec_start_offset); rnum--; } } return new_offset; }
static int dissect_lisp_tcp_membership_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *message_tree, guint offset, guint16 type, guint16 data_len, proto_item *tim) { guint32 iid, sid, rid; guint8 err; guint64 siteid; guint16 afi; /* EID AFI (2 bytes) */ proto_tree_add_item(message_tree, hf_lisp_tcp_message_eid_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; data_len -= 2; /* Instance ID (4 bytes) */ iid = tvb_get_ntohl(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_iid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; data_len -= 4; proto_item_append_text(tim, ", IID: %u", iid); switch (type) { case MEMBERSHIP_BASE + 1: case MEMBERSHIP_BASE + 2: /* Subscribe ID (4 bytes) */ sid = tvb_get_ntohl(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_sid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; data_len -= 4; col_append_fstr(pinfo->cinfo, COL_INFO, ", Sub ID: %u", sid); proto_item_append_text(tim, ", Sub ID: %u", sid); if (type == MEMBERSHIP_BASE + 2) { /* Error code (1 byte) */ err = tvb_get_guint8(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_err, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; data_len -= 1; proto_item_append_text(tim, ", Error code: %s", val_to_str(err, lisp_tcp_membership_subscribe_errors, "Unknown error code (%u)")); } break; case MEMBERSHIP_BASE + 4: case MEMBERSHIP_BASE + 5: /* Site ID (8 bytes) */ siteid = tvb_get_ntoh64(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_site_id, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; data_len -= 8; proto_item_append_text(tim, ", Site-ID: %"G_GINT64_MODIFIER"u", siteid); /* RLOC AFI (2 bytes) */ afi = tvb_get_ntohs(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_rloc_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; data_len -= 2; switch (afi) { case AFNUM_INET: proto_tree_add_item(message_tree, hf_lisp_tcp_message_rloc_ipv4, tvb, offset, INET_ADDRLEN, ENC_NA); proto_item_append_text(tim, ", RLOC: %s", tvb_ip_to_str(tvb, offset)); col_append_fstr(pinfo->cinfo, COL_INFO, " [%u] %s", iid, tvb_ip_to_str(tvb, offset)); offset += INET_ADDRLEN; data_len -= INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(message_tree, hf_lisp_tcp_message_rloc_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); proto_item_append_text(tim, ", RLOC: %s", tvb_ip6_to_str(tvb, offset)); col_append_fstr(pinfo->cinfo, COL_INFO, " [%u] %s", iid, tvb_ip6_to_str(tvb, offset)); offset += INET6_ADDRLEN; data_len -= INET6_ADDRLEN; break; } break; case MEMBERSHIP_BASE + 7: case MEMBERSHIP_BASE + 8: /* Request ID (4 bytes) */ rid = tvb_get_ntohl(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_rid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; data_len -= 4; proto_item_append_text(tim, ", Req ID: %u", rid); break; } if (data_len) { proto_tree_add_item(message_tree, hf_lisp_tcp_message_data, tvb, offset, data_len, ENC_NA); offset += data_len; expert_add_info_format(pinfo, message_tree, &ei_lisp_tcp_undecoded, "Work-in-progress"); } return offset; }
/* Broadcasts are searches, offers or promises. * * Searches are sent by * a peer when it needs a file (ie. while applying its policy, when it needs * files such as installers to install software.) * * Each broadcast relates to one file and each file is identified only by its * checksum - no file names are ever used. A search times out after 10 seconds * (configurable) and the peer will then attempt to act on any offers by * downloading (via push or pull - see dissect_ldss_transfer) from those peers. * * If no offers are received, the search fails and the peer fetches the file * from a remote server, generally a HTTP server on the other side of a WAN. * The protocol exists to minimize the number of WAN downloads needed. * * While downloading from WAN the peer sends promises to inform other peers * when it will be available for them to download. This prevents multiple peers * simultaneously downloading the same file. Promises also inform other peers * how much download bandwidth is being used by their download. Other peers use * this information and the configured knowledge of the WAN bandwidth to avoid * saturating the WAN link, as file downloads are a non-time-critical and * non-business-critical network function. LDSS is intended for networks of * 5-20 machines connected by slow WAN link. The current implementation of the * protocol allows administrator to configure "time windows" when WAN usage is * throttled/unthrottled, though this isn't visible in LDSS. * * Once a WAN download or a LAN transfer (see below above dissect_ldss_transfer) * has complete the peer will offer the file to other peers on the LAN so they * don't need to download it themselves. * * Peers also notify when they shut down in case any other peer is waiting for * a file. */ static int dissect_ldss_broadcast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 messageID; guint8 digest_type; guint8 compression; guint32 cookie; guint8 *digest; guint64 size; guint64 offset; guint32 targetTime; guint16 port; guint16 rate; guint16 messageDetail = INFERRED_NONE; proto_tree *ti, *ldss_tree; const gchar *packet_type, *packet_detail; messageID = tvb_get_ntohs (tvb, 0); digest_type = tvb_get_guint8 (tvb, 2); compression = tvb_get_guint8 (tvb, 3); cookie = tvb_get_ntohl (tvb, 4); digest = (guint8 *)tvb_memdup (NULL, tvb, 8, DIGEST_LEN); size = tvb_get_ntoh64 (tvb, 40); offset = tvb_get_ntoh64 (tvb, 48); targetTime = tvb_get_ntohl (tvb, 56); port = tvb_get_ntohs (tvb, 64); rate = tvb_get_ntohs (tvb, 66); packet_type = val_to_str_const(messageID, ldss_message_id_value, "unknown"); if (messageID == MESSAGE_ID_WILLSEND) { if (cookie == 0) { /* Shutdown: Dishonor promises from this peer. Current * implementation abuses WillSend for this. */ messageDetail = INFERRED_PEERSHUTDOWN; } else if (size == 0 && offset == 0) { /* NeedFile search failed - going to WAN */ messageDetail = INFERRED_WANDOWNLOAD; } else if (size > 0) { /* Size is known (not always the case) */ if (size == offset) { /* File is available for pull on this peer's TCP port */ messageDetail = INFERRED_OFFER; } else { /* WAN download progress announcement from this peer */ messageDetail = INFERRED_PROMISE; } } } else if (messageID == MESSAGE_ID_NEEDFILE) { messageDetail = INFERRED_SEARCH; } packet_detail = val_to_str_const(messageDetail, ldss_inferred_info, "unknown"); /* Set the info column */ col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS Broadcast (%s%s)", packet_type, packet_detail); /* If we have a non-null tree (ie we are building the proto_tree * instead of just filling out the columns), then give more detail. */ if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, (tvb_captured_length(tvb) > 72) ? tvb_captured_length(tvb) : 72, ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_broadcast); proto_tree_add_item(ldss_tree, hf_ldss_message_id, tvb, 0, 2, ENC_BIG_ENDIAN); ti = proto_tree_add_uint(ldss_tree, hf_ldss_message_detail, tvb, 0, 0, messageDetail); PROTO_ITEM_SET_GENERATED(ti); proto_tree_add_item(ldss_tree, hf_ldss_digest_type, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ldss_tree, hf_ldss_compression, tvb, 3, 1, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_cookie, tvb, 4, 4, FALSE, "0x%x%s", cookie, (cookie == 0) ? " - shutdown (promises from this peer are no longer valid)" : ""); proto_tree_add_item(ldss_tree, hf_ldss_digest, tvb, 8, DIGEST_LEN, ENC_NA); proto_tree_add_item(ldss_tree, hf_ldss_size, tvb, 40, 8, ENC_BIG_ENDIAN); proto_tree_add_item(ldss_tree, hf_ldss_offset, tvb, 48, 8, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_target_time, tvb, 56, 4, FALSE, "%d:%02d:%02d", (int)(targetTime / 3600), (int)((targetTime / 60) % 60), (int)(targetTime % 60)); proto_tree_add_item(ldss_tree, hf_ldss_reserved_1, tvb, 60, 4, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_port, tvb, 64, 2, FALSE, "%d%s", port, (messageID == MESSAGE_ID_WILLSEND && size > 0 && size == offset) ? " - file can be pulled at this TCP port" : (messageID == MESSAGE_ID_NEEDFILE ? " - file can be pushed to this TCP port" : "")); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_rate, tvb, 66, 2, FALSE, "%ld", (rate > 0) ? (long)floor(exp(rate * G_LN2 / 2048)) : 0); proto_tree_add_item(ldss_tree, hf_ldss_priority, tvb, 68, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ldss_tree, hf_ldss_property_count, tvb, 70, 2, ENC_BIG_ENDIAN); if (tvb_reported_length(tvb) > 72) { proto_tree_add_item(ldss_tree, hf_ldss_properties, tvb, 72, tvb_captured_length(tvb) - 72, ENC_NA); } } /* Finally, store the broadcast and register ourselves to dissect * any pushes or pulls that result from this broadcast. All data * is pushed/pulled over TCP using the port from the broadcast * packet's port field. * Track each by a TCP conversation with the remote end wildcarded. * The TCP conv tracks back to a broadcast conv to determine what it * is in response to. * * These steps only need to be done once per packet, so a variable * tracks the highest frame number seen. Handles the case of first frame * being frame zero. */ if (messageDetail != INFERRED_PEERSHUTDOWN && (highest_num_seen == 0 || highest_num_seen < pinfo->num)) { ldss_broadcast_t *data; /* Populate data from the broadcast */ data = wmem_new0(wmem_file_scope(), ldss_broadcast_t); data->num = pinfo->num; data->ts = pinfo->abs_ts; data->message_id = messageID; data->message_detail = messageDetail; data->port = port; data->size = size; data->offset = offset; data->compression = compression; data->file = wmem_new0(wmem_file_scope(), ldss_file_t); data->file->digest = digest; data->file->digest_type = digest_type; data->broadcaster = wmem_new0(wmem_file_scope(), ldss_broadcaster_t); copy_address(&data->broadcaster->addr, &pinfo->src); data->broadcaster->port = port; /* Dissect any future pushes/pulls */ if (port > 0) { prepare_ldss_transfer_conv(data); } /* Record that the frame was processed */ highest_num_seen = pinfo->num; } return tvb_captured_length(tvb); }
static void dissect_btmcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *main_item; proto_tree *main_tree; proto_item *pitem; gint offset = 0; guint32 op_code; guint32 response_code; guint32 mdl_id; guint32 mdep_id; guint32 bluetooth_clock_sync_time; guint64 timestamp_sync_time; col_set_str(pinfo->cinfo, COL_PROTOCOL, "MCAP"); col_clear(pinfo->cinfo, COL_INFO); 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; } main_item = proto_tree_add_item(tree, proto_btmcap, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_btmcap); pitem = proto_tree_add_item(main_tree, hf_btmcap_op_code, tvb, offset, 1, ENC_BIG_ENDIAN); op_code = tvb_get_guint8(tvb, offset); offset += 1; col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(op_code, op_code_vals, "Unknown Op Code")); if (op_code >= 0x11 && op_code <= 0x20) { proto_item_append_text(pitem, " (Clock Sync)"); col_append_fstr(pinfo->cinfo, COL_INFO, " (Clock Sync)"); } else { proto_item_append_text(pitem, " (Standard)"); col_append_fstr(pinfo->cinfo, COL_INFO, " (Standard)"); } if (op_code & 0x01) { /* isRequest */ switch(op_code) { case 0x01: /* MD_CREATE_MDL_REQ */ case 0x03: /* MD_RECONNECT_MDL_REQ */ case 0x05: /* MD_ABORT_MDL_REQ */ case 0x07: /* MD_DELETE_MDL_REQ */ pitem = proto_tree_add_item(main_tree, hf_btmcap_mdl_id, tvb, offset, 2, ENC_BIG_ENDIAN); mdl_id = tvb_get_ntohs(tvb, offset); offset += 2; col_append_fstr(pinfo->cinfo, COL_INFO, " - MDL ID: %u", mdl_id); if (mdl_id == 0xFFFF) { proto_item_append_text(pitem, " (Indicates all MDLs)"); col_append_fstr(pinfo->cinfo, COL_INFO, " (Indicates all MDLs)"); } else if (mdl_id >= 0x0001 && mdl_id <= 0xFEFF) { proto_item_append_text(pitem, " (Dynamic Range)"); col_append_fstr(pinfo->cinfo, COL_INFO, " (Dynamic Range)"); } else if (mdl_id == 0x0000) { proto_item_append_text(pitem, " (Reserved)"); col_append_fstr(pinfo->cinfo, COL_INFO, " (Reserved)"); } if (op_code != 0x07 && mdl_id == 0xFFFF) { expert_add_info_format(pinfo, pitem, PI_PROTOCOL, PI_WARN, " The value 0xFFFF is not a valid MDL ID for this request and shall not be used."); } if (op_code == 0x01) { /* only MD_CREATE_MDL_REQ */ pitem = proto_tree_add_item(main_tree, hf_btmcap_mdep_id, tvb, offset, 1, ENC_BIG_ENDIAN); mdep_id = tvb_get_guint8(tvb, offset); offset += 1; if (mdep_id <= 0x7F) { proto_item_append_text(pitem, " (Available for use)"); } else { proto_item_append_text(pitem, " (Reserved)"); } proto_tree_add_item(main_tree, hf_btmcap_configuration, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } break; case 0x11: /* MD_SYNC_CAP_REQ */ pitem = proto_tree_add_item(main_tree, hf_btmcap_timestamp_required_accuracy, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(pitem, " ppm"); offset += 2; break; case 0x13: /* MD_SYNC_SET_REQ */ proto_tree_add_item(main_tree, hf_btmcap_timestamp_update_information, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; pitem = proto_tree_add_item(main_tree, hf_btmcap_bluetooth_clock_sync_time, tvb, offset, 4, ENC_BIG_ENDIAN); bluetooth_clock_sync_time = tvb_get_ntohl(tvb, offset); if (bluetooth_clock_sync_time == 0xFFFFFFFF) proto_item_append_text(pitem, " (Instant Synchronization)"); else proto_item_append_text(pitem, " (Baseband Half-Slot Instant)");; offset += 4; pitem = proto_tree_add_item(main_tree, hf_btmcap_timestamp_sync_time, tvb, offset, 8, ENC_BIG_ENDIAN); timestamp_sync_time = tvb_get_ntoh64(tvb, offset); if (timestamp_sync_time == G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) proto_item_append_text(pitem, " (No Time Synchronization)"); else proto_item_append_text(pitem, " (Time-Stamp Clock Instant)"); offset += 8; break; case 0x15: /* MD_SYNC_INFO_IND */ pitem = proto_tree_add_item(main_tree, hf_btmcap_bluetooth_clock_sync_time, tvb, offset, 4, ENC_BIG_ENDIAN); proto_item_append_text(pitem, " (Baseband Half-Slot Instant)"); offset += 4; pitem = proto_tree_add_item(main_tree, hf_btmcap_timestamp_sync_time, tvb, offset, 8, ENC_BIG_ENDIAN); proto_item_append_text(pitem, " (Time-Stamp Clock Instant)"); offset += 8; pitem = proto_tree_add_item(main_tree, hf_btmcap_timestamp_sample_accuracy, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(pitem, " us"); offset += 2; break; } } else { /* isResponse */ proto_tree_add_item(main_tree, hf_btmcap_response_code, tvb, offset, 1, ENC_BIG_ENDIAN); response_code = tvb_get_guint8(tvb, offset); offset += 1; col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", val_to_str(response_code, response_code_vals, "Unknown ResponseCode")); if (op_code >= 0x11 && op_code <= 0x20) { /* Clock Sync */ switch(op_code) { case 0x12: /* MD_SYNC_CAP_RSP */ pitem = proto_tree_add_item(main_tree, hf_btmcap_bluetooth_clock_access_resolution, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(pitem, " (Baseband half-slots)"); offset += 1; pitem = proto_tree_add_item(main_tree, hf_btmcap_sync_lead_time, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(pitem, " ms"); offset += 2; pitem = proto_tree_add_item(main_tree, hf_btmcap_timestamp_native_resolution, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(pitem, " us"); offset += 2; pitem = proto_tree_add_item(main_tree, hf_btmcap_timestamp_native_accuracy, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(pitem, " ppm"); offset += 2; break; case 0x14: /* MD_SYNC_SET_RSP */ pitem = proto_tree_add_item(main_tree, hf_btmcap_bluetooth_clock_sync_time, tvb, offset, 4, ENC_BIG_ENDIAN); bluetooth_clock_sync_time = tvb_get_ntohl(tvb, offset); if (bluetooth_clock_sync_time == 0xFFFFFFFF) proto_item_append_text(pitem, " (Instant Synchronization)"); else proto_item_append_text(pitem, " (Baseband Half-Slot Instant)"); offset += 4; pitem = proto_tree_add_item(main_tree, hf_btmcap_timestamp_sync_time, tvb, offset, 8, ENC_BIG_ENDIAN); timestamp_sync_time = tvb_get_ntoh64(tvb, offset); if (timestamp_sync_time == G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) proto_item_append_text(pitem, " (No Time Synchronization)"); else proto_item_append_text(pitem, " (Time-Stamp Clock Instant)"); offset += 8; pitem = proto_tree_add_item(main_tree, hf_btmcap_timestamp_sample_accuracy, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(pitem, " us"); offset += 2; break; } } else { /* Standard Op Code */ pitem = proto_tree_add_item(main_tree, hf_btmcap_mdl_id, tvb, offset, 2, ENC_BIG_ENDIAN); mdl_id = tvb_get_ntohs(tvb, offset); offset += 2; col_append_fstr(pinfo->cinfo, COL_INFO, " - %u", mdl_id); if (mdl_id == 0xFFFF) { proto_item_append_text(pitem, " (Indicates all MDLs)"); col_append_fstr(pinfo->cinfo, COL_INFO, " (Indicates all MDLs)"); } else if (mdl_id >= 0x0001 && mdl_id <= 0xFEFF) { proto_item_append_text(pitem, " (Dynamic Range)"); col_append_fstr(pinfo->cinfo, COL_INFO, " (Dynamic Range)"); } else if (mdl_id == 0x0000) { proto_item_append_text(pitem, " (Reserved)"); col_append_fstr(pinfo->cinfo, COL_INFO, " (Reserved)"); } if ((op_code == 0x03 || op_code == 0x05 || op_code == 0x07) && tvb_length_remaining(tvb, offset)) { expert_add_info_format(pinfo, pitem, PI_PROTOCOL, PI_WARN, "The Response Parameters for MD_RECONNECT_MDL_RSP shall have length zero."); } else if (tvb_length_remaining(tvb, offset)) { pitem = proto_tree_add_item(main_tree, hf_btmcap_response_parameters, tvb, offset, -1, ENC_NA); if (response_code != 0x00) { expert_add_info_format(pinfo, pitem, PI_PROTOCOL, PI_WARN, "When the Response Code is not Success, the Response Parameters shall have length zero."); } offset += tvb_length_remaining(tvb, offset); } } } if (tvb_length_remaining(tvb, offset)) { pitem = proto_tree_add_item(main_tree, hf_btmcap_data, tvb, offset, -1, ENC_NA); expert_add_info_format(pinfo, pitem, PI_PROTOCOL, PI_WARN, "Unexpected data"); } }
static void dissect_nbd_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { guint32 magic, error, packet; guint32 handle[2]; guint64 from; int offset=0; proto_tree *tree=NULL; proto_item *item=NULL; conversation_t *conversation; nbd_conv_info_t *nbd_info; nbd_transaction_t *nbd_trans=NULL; emem_tree_key_t hkey[3]; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBD"); col_clear(pinfo->cinfo, COL_INFO); item = proto_tree_add_item(parent_tree, proto_nbd, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_nbd); magic=tvb_get_ntohl(tvb, offset); proto_tree_add_item(tree, hf_nbd_magic, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; /* grab what we need to do the request/response matching */ switch(magic){ case NBD_REQUEST_MAGIC: case NBD_RESPONSE_MAGIC: handle[0]=tvb_get_ntohl(tvb, offset+4); handle[1]=tvb_get_ntohl(tvb, offset+8); break; default: return; } conversation = find_or_create_conversation(pinfo); /* * Do we already have a state structure for this conv */ nbd_info = (nbd_conv_info_t *)conversation_get_proto_data(conversation, proto_nbd); if (!nbd_info) { /* No. Attach that information to the conversation, and add * it to the list of information structures. */ nbd_info = se_new(nbd_conv_info_t); nbd_info->unacked_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "nbd_unacked_pdus"); nbd_info->acked_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "nbd_acked_pdus"); conversation_add_proto_data(conversation, proto_nbd, nbd_info); } if(!pinfo->fd->flags.visited){ if(magic==NBD_REQUEST_MAGIC){ /* This is a request */ nbd_trans=se_new(nbd_transaction_t); nbd_trans->req_frame=pinfo->fd->num; nbd_trans->rep_frame=0; nbd_trans->req_time=pinfo->fd->abs_ts; nbd_trans->type=tvb_get_ntohl(tvb, offset); nbd_trans->datalen=tvb_get_ntohl(tvb, offset+20); hkey[0].length=2; hkey[0].key=handle; hkey[1].length=0; se_tree_insert32_array(nbd_info->unacked_pdus, hkey, (void *)nbd_trans); } else if(magic==NBD_RESPONSE_MAGIC){ hkey[0].length=2; hkey[0].key=handle; hkey[1].length=0; nbd_trans=(nbd_transaction_t *)se_tree_lookup32_array(nbd_info->unacked_pdus, hkey); if(nbd_trans){ nbd_trans->rep_frame=pinfo->fd->num; hkey[0].length=1; hkey[0].key=&nbd_trans->rep_frame; hkey[1].length=2; hkey[1].key=handle; hkey[2].length=0; se_tree_insert32_array(nbd_info->acked_pdus, hkey, (void *)nbd_trans); hkey[0].length=1; hkey[0].key=&nbd_trans->req_frame; hkey[1].length=2; hkey[1].key=handle; hkey[2].length=0; se_tree_insert32_array(nbd_info->acked_pdus, hkey, (void *)nbd_trans); } } } else { packet=pinfo->fd->num; hkey[0].length=1; hkey[0].key=&packet; hkey[1].length=2; hkey[1].key=handle; hkey[2].length=0; nbd_trans=(nbd_transaction_t *)se_tree_lookup32_array(nbd_info->acked_pdus, hkey); } /* The bloody handles are reused !!! eventhough they are 64 bits. * So we must verify we got the "correct" one */ if( (magic==NBD_RESPONSE_MAGIC) && (nbd_trans) && (pinfo->fd->num<nbd_trans->req_frame) ){ /* must have been the wrong one */ nbd_trans=NULL; } if(!nbd_trans){ /* create a "fake" nbd_trans structure */ nbd_trans=ep_new(nbd_transaction_t); nbd_trans->req_frame=0; nbd_trans->rep_frame=0; nbd_trans->req_time=pinfo->fd->abs_ts; nbd_trans->type=0xff; nbd_trans->datalen=0; } /* print state tracking in the tree */ if(magic==NBD_REQUEST_MAGIC){ /* This is a request */ if(nbd_trans->rep_frame){ proto_item *it; it=proto_tree_add_uint(tree, hf_nbd_response_in, tvb, 0, 0, nbd_trans->rep_frame); PROTO_ITEM_SET_GENERATED(it); } } else if(magic==NBD_RESPONSE_MAGIC){ /* This is a reply */ if(nbd_trans->req_frame){ proto_item *it; nstime_t ns; it=proto_tree_add_uint(tree, hf_nbd_response_to, tvb, 0, 0, nbd_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); nstime_delta(&ns, &pinfo->fd->abs_ts, &nbd_trans->req_time); it=proto_tree_add_time(tree, hf_nbd_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(it); } } switch(magic){ case NBD_REQUEST_MAGIC: proto_tree_add_item(tree, hf_nbd_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; proto_tree_add_item(tree, hf_nbd_handle, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; from=tvb_get_ntoh64(tvb, offset); proto_tree_add_item(tree, hf_nbd_from, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; proto_tree_add_item(tree, hf_nbd_len, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; switch(nbd_trans->type){ case NBD_CMD_WRITE: col_add_fstr(pinfo->cinfo, COL_INFO, "Write Request Offset:0x%" G_GINT64_MODIFIER "x Length:%d", from, nbd_trans->datalen); break; case NBD_CMD_READ: col_add_fstr(pinfo->cinfo, COL_INFO, "Read Request Offset:0x%" G_GINT64_MODIFIER "x Length:%d", from, nbd_trans->datalen); break; case NBD_CMD_DISC: col_set_str(pinfo->cinfo, COL_INFO, "Disconnect Request"); break; } if(nbd_trans->type==NBD_CMD_WRITE){ proto_tree_add_item(tree, hf_nbd_data, tvb, offset, nbd_trans->datalen, ENC_NA); } break; case NBD_RESPONSE_MAGIC: item=proto_tree_add_uint(tree, hf_nbd_type, tvb, 0, 0, nbd_trans->type); PROTO_ITEM_SET_GENERATED(item); error=tvb_get_ntohl(tvb, offset); proto_tree_add_item(tree, hf_nbd_error, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; proto_tree_add_item(tree, hf_nbd_handle, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; col_add_fstr(pinfo->cinfo, COL_INFO, "%s Response Error:%d", (nbd_trans->type==NBD_CMD_WRITE)?"Write":"Read", error); if(nbd_trans->type==NBD_CMD_READ){ proto_tree_add_item(tree, hf_nbd_data, tvb, offset, nbd_trans->datalen, ENC_NA); } break; } return; }