/* check to see if the message is an exclusive message send to host */ static gboolean csm_to_host(guint16 fc, guint16 ct) { if (fc == 0x0000) { return (try_val_to_str(ct, exclusive_to_host_ct_vals) != NULL); } else { return (try_val_to_str(fc, exclusive_to_host_vals) != NULL); } }
/*--- dissect_qsig_arg ------------------------------------------------------*/ static int dissect_qsig_arg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { int offset = 0; rose_ctx_t *rctx; gint32 opcode = 0, service; const qsig_op_t *op_ptr; const gchar *p; proto_item *ti, *ti_tmp; proto_tree *qsig_tree; /* Reject the packet if data is NULL */ if (data == NULL) return 0; rctx = get_rose_ctx(data); DISSECTOR_ASSERT(rctx); if (rctx->d.pdu != 1) /* invoke */ return offset; if (rctx->d.code == 0) { /* local */ opcode = rctx->d.code_local; op_ptr = get_op(opcode); } else if (rctx->d.code == 1) { /* global */ op_ptr = (qsig_op_t *)g_hash_table_lookup(qsig_oid2op_hashtable, rctx->d.code_global); if (op_ptr) opcode = op_ptr->opcode; } else { return offset; } if (!op_ptr) return offset; service = get_service(opcode); ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_captured_length(tvb), ENC_NA); qsig_tree = proto_item_add_subtree(ti, ett_qsig); proto_tree_add_uint(qsig_tree, hf_qsig_operation, tvb, 0, 0, opcode); p = try_val_to_str(opcode, VALS(qsig_str_operation)); if (p) { proto_item_append_text(ti, ": %s", p); proto_item_append_text(rctx->d.code_item, " - %s", p); if (rctx->apdu_depth >= 0) proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p); } ti_tmp = proto_tree_add_uint(qsig_tree, hf_qsig_service, tvb, 0, 0, service); p = try_val_to_str(service, VALS(qsig_str_service_name)); if (p) proto_item_append_text(ti_tmp, " - %s", p); if (op_ptr->arg_pdu) offset = op_ptr->arg_pdu(tvb, pinfo, qsig_tree, NULL); else if (tvb_reported_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(tree, pinfo, &ei_qsig_unsupported_error_type, tvb, offset, -1); offset += tvb_captured_length_remaining(tvb, offset); } return offset; }
/* * Here we get a special value_string, that return another value_string * pointer instead of string value. This let us use the try_val_to_str * to get val_to_str value from the value of a parameter on a more * easier way than using switch cases */ static const guint8 *dissect_mqpcf_parm_getintval(guint uPrm, guint uVal) { const value_string *pVs; pVs = (const value_string *)try_val_to_str(uPrm, GET_VALSV(MQCFINT_Parse)); if (pVs) { return (const guint8 *)try_val_to_str(uVal, pVs); } return NULL; }
/* * Check whether the control field of the packet looks valid. */ gboolean check_xdlc_control(tvbuff_t *tvb, int offset, const value_string *u_modifier_short_vals_cmd, const value_string *u_modifier_short_vals_resp, gboolean is_response, gboolean is_extended _U_) { guint16 control; if (!tvb_bytes_exist(tvb, offset, 1)) return FALSE; /* not enough data to check */ switch (tvb_get_guint8(tvb, offset) & 0x03) { case XDLC_S: /* * Supervisory frame. * No fields to check for validity here. */ return TRUE; case XDLC_U: /* * Unnumbered frame. * * XXX - is this two octets, with a P/F bit, in HDLC extended * operation? It's one octet in LLC, even though the control * field of I and S frames is a 2-byte extended-operation field * in LLC. Given that there are no sequence numbers in the * control field of a U frame, there doesn't appear to be any * need for it to be 2 bytes in extended operation. */ if (u_modifier_short_vals_cmd == NULL) u_modifier_short_vals_cmd = modifier_short_vals_cmd; if (u_modifier_short_vals_resp == NULL) u_modifier_short_vals_resp = modifier_short_vals_resp; control = tvb_get_guint8(tvb, offset); if (is_response) { if (try_val_to_str(control & XDLC_U_MODIFIER_MASK, u_modifier_short_vals_resp) == NULL) return FALSE; /* unknown modifier */ } else { if (try_val_to_str(control & XDLC_U_MODIFIER_MASK, u_modifier_short_vals_cmd) == NULL) return FALSE; /* unknown modifier */ } return TRUE; default: /* * Information frame. * No fields to check for validity here. */ return TRUE; } }
static void dissect_kt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint magic; proto_item *ti; proto_tree *kt_tree; gint offset, offset_start; offset = 0; while (tvb_reported_length_remaining(tvb, offset) > 0) { magic = tvb_get_guint8(tvb, offset); /* If the magic is not one of the known values, exit */ if (try_val_to_str(magic, kt_magic_vals) == NULL) return; /* Otherwise, the magic value is known. Continue */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "KT"); col_set_str(pinfo->cinfo, COL_INFO, try_val_to_str(magic, kt_magic_vals)); ti = proto_tree_add_item(tree, proto_kt, tvb, offset, -1, ENC_NA); kt_tree = proto_item_add_subtree(ti, ett_kt); offset_start=offset; switch (magic) { case KT_MAGIC_REPL_WAIT: offset = dissect_kt_replication_wait(tvb, kt_tree, offset); break; case KT_MAGIC_REPLICATION: offset = dissect_kt_replication(tvb, pinfo, kt_tree, offset); break; case KT_MAGIC_PLAY_SCRIPT: offset = dissect_kt_play_script(tvb, pinfo, kt_tree, offset); break; case KT_MAGIC_SET_BULK: offset = dissect_kt_set_bulk(tvb, pinfo, kt_tree, offset); break; case KT_MAGIC_REMOVE_BULK: offset = dissect_kt_remove_bulk(tvb, pinfo, kt_tree, offset); break; case KT_MAGIC_GET_BULK: offset = dissect_kt_get_bulk(tvb, pinfo, kt_tree, offset); break; case KT_MAGIC_ERROR: offset = dissect_kt_error(tvb, kt_tree, offset); break; } proto_item_set_len(ti, offset-offset_start); } }
static void dissect_operation_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, gint length_count) { proto_item *ti; proto_tree *oper_tree; guint type, length; while (tvb_reported_length_remaining(tvb, offset) >= TLV_TL_LENGTH) { oper_tree = proto_tree_add_subtree(tree, tvb, offset, length_count, ett_forces_lfbselect_tlv_type_operation, &ti, "Operation TLV"); type = tvb_get_ntohs(tvb,offset); ti = proto_tree_add_item(oper_tree, hf_forces_lfbselect_tlv_type_operation_type, tvb, offset, 2, ENC_BIG_ENDIAN); if (try_val_to_str(type, operation_type_vals) == NULL) expert_add_info_format(pinfo, ti, &ei_forces_lfbselect_tlv_type_operation_type, "Bogus: ForCES Operation TLV (Type:0x%04x) is not supported", type); proto_tree_add_item_ret_uint(oper_tree, hf_forces_lfbselect_tlv_type_operation_length, tvb, offset+2, 2, ENC_BIG_ENDIAN, &length); dissect_path_data_tlv(tvb, pinfo, oper_tree, offset+TLV_TL_LENGTH); if (length == 0) break; offset += length; } }
static const char* spx_conn_ctrl(guint8 ctrl) { const char *p; static const value_string conn_vals[] = { { 0x00, "Data, No Ack Required" }, { SPX_EOM, "End-of-Message" }, { SPX_ATTN, "Attention" }, { SPX_SEND_ACK, "Acknowledgment Required"}, { SPX_SEND_ACK|SPX_EOM, "Send Ack: End Message"}, { SPX_SYS_PACKET, "System Packet"}, { SPX_SYS_PACKET|SPX_SEND_ACK, "System Packet: Send Ack"}, { 0x00, NULL } }; p = try_val_to_str((ctrl & 0xf0), conn_vals ); if (p) { return p; } else { return "Unknown"; } }
static gboolean is_armagetronad_packet(tvbuff_t * tvb) { gint offset = 0; /* For each message in the frame */ while (tvb_captured_length_remaining(tvb, offset) > 2) { gint data_len = tvb_get_ntohs(tvb, offset + 4) * 2; #if 0 /* * If the descriptor_id is not in the table it's possibly * because the protocol evoluated, losing synchronization * with the table, that's why we don't consider that as * a heuristic */ if (!try_val_to_str(tvb_get_ntohs(tvb, offset), descriptors)) /* DescriptorID not found in the table */ return FALSE; #endif if (!tvb_bytes_exist(tvb, offset + 6, data_len)) /* Advertised length too long */ return FALSE; offset += 6 + data_len; } /* The packed should end with a 2 bytes ID */ return tvb_captured_length_remaining(tvb, offset) == 2; }
gchar * val_to_str_wmem(wmem_allocator_t *scope, const guint32 val, const value_string *vs, const char *fmt) { const gchar *ret; DISSECTOR_ASSERT(fmt != NULL); ret = try_val_to_str(val, vs); if (ret != NULL) return wmem_strdup(scope, ret); return wmem_strdup_printf(scope, fmt, val); }
/* Tries to match val against each element in the value_string array vs. Returns the associated string ptr on a match. Formats val with fmt, and returns the resulting string, on failure. */ const gchar * val_to_str(const guint32 val, const value_string *vs, const char *fmt) { const gchar *ret; DISSECTOR_ASSERT(fmt != NULL); ret = try_val_to_str(val, vs); if (ret != NULL) return ret; return wmem_strdup_printf(wmem_packet_scope(), fmt, val); }
int dissect_netlink_attributes(tvbuff_t *tvb, header_field_info *hfi_type, int ett, void *data, proto_tree *tree, int offset, netlink_attributes_cb_t cb) { /* align to 4 */ offset = (offset + 3) & ~3; while (tvb_length_remaining(tvb, offset) >= 4) { guint16 rta_len, rta_type; int end_offset; proto_item *ti; proto_tree *attr_tree; rta_len = tvb_get_letohs(tvb, offset); if (rta_len < 4) { /* XXX invalid expert */ break; } end_offset = (offset + rta_len + 3) & ~3; ti = proto_tree_add_text(tree, tvb, offset, end_offset - offset, "Attribute"); attr_tree = proto_item_add_subtree(ti, ett); proto_tree_add_text(attr_tree, tvb, offset, 2, "Len: %d", rta_len); offset += 2; rta_type = tvb_get_letohs(tvb, offset); proto_tree_add_item(attr_tree, hfi_type, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; if (hfi_type->strings) { /* XXX, export hf_try_val_to_str */ const char *rta_str = try_val_to_str(rta_type, (const value_string *) hfi_type->strings); if (rta_str) proto_item_append_text(ti, ": %s", rta_str); } if (!cb(tvb, data, attr_tree, rta_type, offset, rta_len - 4)) { /* not handled */ } if (end_offset <= offset) break; offset = end_offset; } return offset; }
/* Tries to match val against each element in the value_string array vs. Returns the associated string ptr on a match. Returns 'unknown_str', on failure. */ const gchar * val_to_str_const(const guint32 val, const value_string *vs, const char *unknown_str) { const gchar *ret; DISSECTOR_ASSERT(unknown_str != NULL); ret = try_val_to_str(val, vs); if (ret != NULL) return ret; return unknown_str; }
/*--- dissect_isdn_sup_arg ------------------------------------------------------*/ static int dissect_isdn_sup_arg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { int offset = 0; rose_ctx_t *rctx; gint32 opcode = 0; const gchar *p; const isdn_sup_op_t *op_ptr; proto_item *ti; proto_tree *isdn_sup_tree; /* Reject the packet if data is NULL */ if (data == NULL) return 0; rctx = get_rose_ctx(data); DISSECTOR_ASSERT(rctx); if (rctx->d.pdu != 1) /* invoke */ return offset; if (rctx->d.code == 0) { /* local */ opcode = rctx->d.code_local; } else { return offset; } op_ptr = get_op(opcode); if (!op_ptr) return offset; ti = proto_tree_add_item(tree, proto_isdn_sup, tvb, offset, -1, ENC_NA); isdn_sup_tree = proto_item_add_subtree(ti, ett_isdn_sup); proto_tree_add_uint(isdn_sup_tree, hf_isdn_sup_operation, tvb, 0, 0, opcode); p = try_val_to_str(opcode, VALS(isdn_sup_str_operation)); if (p) { proto_item_append_text(ti, ": %s", p); proto_item_append_text(rctx->d.code_item, " - %s", p); if (rctx->apdu_depth >= 0) proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p); } if (op_ptr->arg_pdu) offset = op_ptr->arg_pdu(tvb, pinfo, isdn_sup_tree, NULL); else if (tvb_reported_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(tree, pinfo, &ei_isdn_sup_unsupported_error_type, tvb, offset, -1); offset += tvb_reported_length_remaining(tvb, offset); } return offset; }
/*--- dissect_qsig_err ------------------------------------------------------*/ static int dissect_qsig_err(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { int offset = 0; rose_ctx_t *rctx; gint32 errcode; const qsig_err_t *err_ptr; const gchar *p; proto_item *ti; proto_tree *qsig_tree; /* Reject the packet if data is NULL */ if (data == NULL) return 0; rctx = get_rose_ctx(data); DISSECTOR_ASSERT(rctx); if (rctx->d.pdu != 3) /* returnError */ return offset; if (rctx->d.code != 0) /* local */ return offset; errcode = rctx->d.code_local; err_ptr = get_err(errcode); if (!err_ptr) return offset; ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_captured_length(tvb), ENC_NA); qsig_tree = proto_item_add_subtree(ti, ett_qsig); proto_tree_add_uint(qsig_tree, hf_qsig_error, tvb, 0, 0, errcode); p = try_val_to_str(errcode, VALS(qsig_str_error)); if (p) { proto_item_append_text(ti, ": %s", p); proto_item_append_text(rctx->d.code_item, " - %s", p); if (rctx->apdu_depth >= 0) proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p); } if (err_ptr->err_pdu) offset = err_ptr->err_pdu(tvb, pinfo, qsig_tree, NULL); else if (tvb_reported_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(tree, pinfo, &ei_qsig_unsupported_error_type, tvb, offset, -1); offset += tvb_captured_length_remaining(tvb, offset); } return offset; }
/*--- dissect_h450_err ------------------------------------------------------*/ static int dissect_h450_err(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *hidden_item; int offset = 0; rose_ctx_t *rctx; gint32 errcode; const h450_err_t *err_ptr; const gchar *p; /* Reject the packet if data is NULL */ if (data == NULL) return 0; rctx = get_rose_ctx(data); DISSECTOR_ASSERT(rctx); if (rctx->d.pdu != 3) /* returnError */ return offset; if (rctx->d.code != 0) /* local */ return offset; errcode = rctx->d.code_local; err_ptr = get_err(errcode); if (!err_ptr) return offset; hidden_item = proto_tree_add_uint(tree, hf_h450_error, tvb, 0, 0, errcode); PROTO_ITEM_SET_HIDDEN(hidden_item); p = try_val_to_str(errcode, VALS(h450_str_error)); if (p) { proto_item_append_text(rctx->d.code_item, " - %s", p); if (rctx->apdu_depth >= 0) proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p); } if (err_ptr->err_pdu && (tvb_reported_length_remaining(tvb, offset) > 0)) offset = err_ptr->err_pdu(tvb, pinfo, tree, NULL); else if (tvb_reported_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(tree, pinfo, &ei_h450_unsupported_error_type, tvb, offset, -1); offset += tvb_reported_length_remaining(tvb, offset); } return offset; }
guint dissect_cbs_message_identifier(tvbuff_t *tvb, proto_tree *tree, guint offset) { guint16 msg_id; const char *msg_id_string = NULL; msg_id = tvb_get_ntohs(tvb, offset); msg_id_string = try_val_to_str(msg_id, message_id_values); if (msg_id_string == NULL) { if (msg_id < 1000) { msg_id_string = "Message ID to be allocated by GSMA"; } else if (msg_id < 4096) { msg_id_string = "Message ID intended for standardization in future versions of 3GPP TS 23.041"; } else if (msg_id < 4224) { msg_id_string = "Message ID reserved for Cell Broadcast Data Download (unsecured) to the SIM "; } else if (msg_id < 4352) { msg_id_string = "Message ID reserved for Cell Broadcast Data Download (secured) to the SIM "; } else if (msg_id < 4360) { msg_id_string = "ETWS CBS Message Identifier for future extension"; } else if (msg_id < 4400) { msg_id_string = "CMAS CBS Message Identifier for future extension"; } else if (msg_id < 6400) { msg_id_string = "CBS Message Identifier for future PWS use"; } else if (msg_id < 40960) { msg_id_string = "Intended for standardization in future versions of 3GPP TS 23.041"; } else if (msg_id < 43500) { msg_id_string = "Message ID in PLMN operator specific range"; } else if (msg_id < 43530) { msg_id_string = "Traffic Information Traffic Master UK"; } else if (msg_id < 43585) { msg_id_string = "Traffic information Mannesmann Telecommerce"; } else if (msg_id < 45056) { msg_id_string = "Message ID in PLMN operator specific range"; } else { msg_id_string = "Message ID intended as PLMN operator specific range in future versions of 3GPP TS 23.041"; } } proto_tree_add_uint_format_value(tree, hf_gsm_cbs_message_identifier, tvb, offset, 2, msg_id, "%s (%d)", msg_id_string, msg_id); offset += 2; return offset; }
/* void ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype, packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree, int etype_id, int trailer_id, int fcs_len) */ static int dissect_ethertype(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { const char *description; tvbuff_t *volatile next_tvb; guint length_before; gint captured_length, reported_length; volatile int dissector_found = 0; const char *volatile saved_proto; ethertype_data_t *ethertype_data; /* Reject the packet if data is NULL */ if (data == NULL) return 0; ethertype_data = (ethertype_data_t*)data; /* Add the Ethernet type to the protocol tree */ proto_tree_add_uint(ethertype_data->fh_tree, ethertype_data->etype_id, tvb, ethertype_data->offset_after_ethertype - 2, 2, ethertype_data->etype); /* Get the captured length and reported length of the data after the Ethernet type. */ captured_length = tvb_captured_length_remaining(tvb, ethertype_data->offset_after_ethertype); reported_length = tvb_reported_length_remaining(tvb, ethertype_data->offset_after_ethertype); /* Remember how much data there is after the Ethernet type, including any trailer and FCS. */ length_before = reported_length; /* Construct a tvbuff for the payload after the Ethernet type. If the FCS length is positive, remove the FCS. (If it's zero, there's no FCS; if it's negative, we don't know whether there's an FCS, so we'll guess based on the length of the trailer.) */ if (ethertype_data->fcs_len > 0) { if (captured_length >= 0 && reported_length >= 0) { if (reported_length >= ethertype_data->fcs_len) reported_length -= ethertype_data->fcs_len; if (captured_length > reported_length) captured_length = reported_length; } } next_tvb = tvb_new_subset(tvb, ethertype_data->offset_after_ethertype, captured_length, reported_length); p_add_proto_data(pinfo->pool, pinfo, proto_ethertype, 0, GUINT_TO_POINTER((guint)ethertype_data->etype)); /* Look for sub-dissector, and call it if found. Catch exceptions, so that if the reported length of "next_tvb" was reduced by some dissector before an exception was thrown, we can still put in an item for the trailer. */ saved_proto = pinfo->current_proto; TRY { dissector_found = dissector_try_uint(ethertype_dissector_table, ethertype_data->etype, next_tvb, pinfo, tree); } CATCH_NONFATAL_ERRORS { /* Somebody threw an exception that means that there was a problem dissecting the payload; that means that a dissector was found, so we don't need to dissect the payload as data or update the protocol or info columns. Just show the exception and then drive on to show the trailer, after noting that a dissector was found and restoring the protocol value that was in effect before we called the subdissector. */ show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); dissector_found = 1; pinfo->current_proto = saved_proto; } ENDTRY; if (!dissector_found) { /* No sub-dissector found. Label rest of packet as "Data" */ call_data_dissector(next_tvb, pinfo, tree); /* Label protocol */ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", ethertype_data->etype); description = try_val_to_str(ethertype_data->etype, etype_vals); if (description) { col_add_str(pinfo->cinfo, COL_INFO, description); } } add_dix_trailer(pinfo, tree, ethertype_data->fh_tree, ethertype_data->trailer_id, tvb, next_tvb, ethertype_data->offset_after_ethertype, length_before, ethertype_data->fcs_len); return tvb_captured_length(tvb); }
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); 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, &ei_return_code, "SSS Error: %s", str); 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_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_tcp) { proto_tree *ncp_tree = NULL; proto_item *ti; struct ncp_ip_header ncpiph; struct ncp_ip_rqhdr ncpiphrq; guint16 ncp_burst_seqno, ncp_ack_seqno; guint16 flags = 0; proto_tree *flags_tree = NULL; int hdr_offset = 0; int commhdr = 0; int offset = 0; gint length_remaining; tvbuff_t *next_tvb; guint32 testvar = 0, ncp_burst_command, burst_len, burst_off, burst_file; guint8 subfunction; guint32 nw_connection = 0, data_offset; guint16 data_len = 0; guint16 missing_fraglist_count = 0; mncp_rhash_value *request_value = NULL; conversation_t *conversation; proto_item *expert_item; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NCP"); col_clear(pinfo->cinfo, COL_INFO); ncp_hdr = &header; ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, ENC_NA); ncp_tree = proto_item_add_subtree(ti, ett_ncp); if (is_tcp) { if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY) commhdr += 1; /* Get NCPIP Header data */ ncpiph.signature = tvb_get_ntohl(tvb, commhdr); proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, commhdr, 4, ncpiph.signature); ncpiph.length = (0x7fffffff & tvb_get_ntohl(tvb, commhdr+4)); proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, commhdr+4, 4, ncpiph.length); commhdr += 8; if (ncpiph.signature == NCPIP_RQST) { ncpiphrq.version = tvb_get_ntohl(tvb, commhdr); proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, commhdr, 4, ncpiphrq.version); commhdr += 4; ncpiphrq.rplybufsize = tvb_get_ntohl(tvb, commhdr); proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, commhdr, 4, ncpiphrq.rplybufsize); commhdr += 4; } /* Check to see if this is a valid offset, otherwise increment for packet signature */ if (try_val_to_str(tvb_get_ntohs(tvb, commhdr), ncp_type_vals)==NULL) { /* Check to see if we have a valid type after packet signature length */ if (try_val_to_str(tvb_get_ntohs(tvb, commhdr+8), ncp_type_vals)!=NULL) { proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, commhdr, 8, ENC_NA); commhdr += 8; } } } else { /* Initialize this structure, we use it below */ memset(&ncpiph, 0, sizeof(ncpiph)); } header.type = tvb_get_ntohs(tvb, commhdr); header.sequence = tvb_get_guint8(tvb, commhdr+2); header.conn_low = tvb_get_guint8(tvb, commhdr+3); header.task = tvb_get_guint8(tvb, commhdr+4); header.conn_high = tvb_get_guint8(tvb, commhdr+5); proto_tree_add_uint(ncp_tree, hf_ncp_type, tvb, commhdr, 2, header.type); nw_connection = (header.conn_high*256)+header.conn_low; /* Ok, we need to track the conversation so that we can * determine if a new server session is occuring for this * connection. */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0); if ((ncpiph.length & 0x80000000) || ncpiph.signature == NCPIP_RPLY) { /* First time through we will record the initial connection and task * values */ if (!pinfo->fd->flags.visited) { if (conversation != NULL) { /* find the record telling us the * request made that caused this * reply */ request_value = mncp_hash_lookup(conversation, nw_connection, header.task); /* if for some reason we have no * conversation in our hash, create * one */ if (request_value == NULL) { mncp_hash_insert(conversation, nw_connection, header.task, pinfo); } } else { /* It's not part of any conversation * - create a new one. */ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0); mncp_hash_insert(conversation, nw_connection, header.task, pinfo); } /* If this is a request packet then we * might have a new task */ if (ncpiph.signature == NCPIP_RPLY) { /* Now on reply packets we have to * use the state of the original * request packet, so look up the * request value and check the task number */ /*request_value = mncp_hash_lookup(conversation, nw_connection, header.task);*/ } } else { /* Get request value data */ request_value = mncp_hash_lookup(conversation, nw_connection, header.task); if (request_value) { if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn) { expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task); } } } } else { if (!pinfo->fd->flags.visited) { if (conversation != NULL) { /* find the record telling us the * request made that caused this * reply */ request_value = mncp_hash_lookup(conversation, nw_connection, header.task); /* if for some reason we have no * conversation in our hash, create * one */ if (request_value == NULL) { mncp_hash_insert(conversation, nw_connection, header.task, pinfo); } } else { /* It's not part of any conversation * - create a new one. */ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0); mncp_hash_insert(conversation, nw_connection, header.task, pinfo); } /* find the record telling us the request * made that caused this reply */ } else { request_value = mncp_hash_lookup(conversation, nw_connection, header.task); if (request_value) { if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn) { expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task); } } } } tap_queue_packet(ncp_tap.hdr, pinfo, ncp_hdr); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)")); /* * Process the packet-type-specific header. */ switch (header.type) { case NCP_BROADCAST_SLOT: /* Server Broadcast */ proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence); proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection); proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, tvb_get_guint8(tvb, commhdr+9)); proto_tree_add_item(ncp_tree, hf_ncp_oplock_handle, tvb, commhdr + 10, 4, ENC_BIG_ENDIAN); if ((tvb_get_guint8(tvb, commhdr+9)==0x24) && ncp_echo_file) { expert_add_info_format(pinfo, NULL, &ei_ncp_oplock_handle, "Server requesting station to clear oplock on handle - %08x", tvb_get_ntohl(tvb, commhdr+10)); } break; case NCP_LIP_ECHO: /* Lip Echo Packet */ proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr, 13, ENC_ASCII|ENC_NA); break; case NCP_BURST_MODE_XFER: /* Packet Burst Packet */ /* * XXX - we should keep track of whether there's a burst * outstanding on a connection and, if not, treat the * beginning of the data as a burst header. * * The burst header contains: * * 4 bytes of little-endian function number: * 1 = read, 2 = write; * * 4 bytes of file handle; * * 8 reserved bytes; * * 4 bytes of big-endian file offset; * * 4 bytes of big-endian byte count. * * The data follows for a burst write operation. * * The first packet of a burst read reply contains: * * 4 bytes of little-endian result code: * 0: No error * 1: Initial error * 2: I/O error * 3: No data read; * * 4 bytes of returned byte count (big-endian?). * * The data follows. * * Each burst of a write request is responded to with a * burst packet with a 2-byte little-endian result code: * * 0: Write successful * 4: Write error */ flags = tvb_get_guint8(tvb, commhdr + 2); ti = proto_tree_add_uint(ncp_tree, hf_ncp_system_flags, tvb, commhdr + 2, 1, flags); flags_tree = proto_item_add_subtree(ti, ett_ncp_system_flags); proto_tree_add_item(flags_tree, hf_ncp_system_flags_abt, tvb, commhdr + 2, 1, ENC_BIG_ENDIAN); if (flags & ABT) { proto_item_append_text(ti, " ABT"); } flags&=(~( ABT )); proto_tree_add_item(flags_tree, hf_ncp_system_flags_bsy, tvb, commhdr + 2, 1, ENC_BIG_ENDIAN); if (flags & BSY) { proto_item_append_text(ti, " BSY"); } flags&=(~( BSY )); proto_tree_add_item(flags_tree, hf_ncp_system_flags_eob, tvb, commhdr + 2, 1, ENC_BIG_ENDIAN); if (flags & EOB) { proto_item_append_text(ti, " EOB"); } flags&=(~( EOB )); proto_tree_add_item(flags_tree, hf_ncp_system_flags_lst, tvb, commhdr + 2, 1, ENC_BIG_ENDIAN); if (flags & LST) { proto_item_append_text(ti, " LST"); } flags&=(~( LST )); proto_tree_add_item(flags_tree, hf_ncp_system_flags_sys, tvb, commhdr + 2, 1, ENC_BIG_ENDIAN); if (flags & SYS) { proto_item_append_text(ti, " SYS"); } flags&=(~( SYS )); proto_tree_add_item(ncp_tree, hf_ncp_stream_type, tvb, commhdr + 3, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ncp_tree, hf_ncp_src_connection, tvb, commhdr + 4, 4, ENC_BIG_ENDIAN); proto_tree_add_item(ncp_tree, hf_ncp_dst_connection, tvb, commhdr + 8, 4, ENC_BIG_ENDIAN); proto_tree_add_item(ncp_tree, hf_ncp_packet_seqno, tvb, commhdr + 12, 4, ENC_BIG_ENDIAN); proto_tree_add_item(ncp_tree, hf_ncp_delay_time, tvb, commhdr + 16, 4, ENC_BIG_ENDIAN); ncp_burst_seqno = tvb_get_ntohs(tvb, commhdr+20); proto_tree_add_item(ncp_tree, hf_ncp_burst_seqno, tvb, commhdr + 20, 2, ENC_BIG_ENDIAN); ncp_ack_seqno = tvb_get_ntohs(tvb, commhdr+22); proto_tree_add_item(ncp_tree, hf_ncp_ack_seqno, tvb, commhdr + 22, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ncp_tree, hf_ncp_burst_len, tvb, commhdr + 24, 4, ENC_BIG_ENDIAN); data_offset = tvb_get_ntohl(tvb, commhdr + 28); proto_tree_add_uint(ncp_tree, hf_ncp_data_offset, tvb, commhdr + 28, 4, data_offset); data_len = tvb_get_ntohs(tvb, commhdr + 32); proto_tree_add_uint(ncp_tree, hf_ncp_data_bytes, tvb, commhdr + 32, 2, data_len); missing_fraglist_count = tvb_get_ntohs(tvb, commhdr + 34); proto_tree_add_item(ncp_tree, hf_ncp_missing_fraglist_count, tvb, commhdr + 34, 2, ENC_BIG_ENDIAN); offset = commhdr + 36; if (!(flags & SYS) && ncp_burst_seqno == ncp_ack_seqno && data_offset == 0) { /* * This is either a Burst Read or Burst Write * command. The data length includes the burst * mode header, plus any data in the command * (there shouldn't be any in a read, but there * might be some in a write). */ if (data_len < 4) return; ncp_burst_command = tvb_get_ntohl(tvb, offset); proto_tree_add_item(ncp_tree, hf_ncp_burst_command, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; data_len -= 4; if (data_len < 4) return; burst_file = tvb_get_ntohl(tvb, offset); proto_tree_add_item(ncp_tree, hf_ncp_burst_file_handle, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; data_len -= 4; if (data_len < 8) return; proto_tree_add_item(ncp_tree, hf_ncp_burst_reserved, tvb, offset, 8, ENC_NA); offset += 8; data_len -= 8; if (data_len < 4) return; burst_off = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(ncp_tree, hf_ncp_burst_offset, tvb, offset, 4, burst_off); offset += 4; data_len -= 4; if (data_len < 4) return; burst_len = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(ncp_tree, hf_ncp_burst_len, tvb, offset, 4, burst_len); offset += 4; data_len -= 4; col_add_fstr(pinfo->cinfo, COL_INFO, "%s %d bytes starting at offset %d in file 0x%08x", val_to_str(ncp_burst_command, burst_command, "Unknown (0x%08x)"), burst_len, burst_off, burst_file); break; } else { if (tvb_get_guint8(tvb, commhdr + 2) & 0x10) { col_set_str(pinfo->cinfo, COL_INFO, "End of Burst"); } } break; case NCP_ALLOCATE_SLOT: /* Allocate Slot Request */ length_remaining = tvb_length_remaining(tvb, commhdr + 4); if (length_remaining > 4) { testvar = tvb_get_ntohl(tvb, commhdr+4); if (testvar == 0x4c495020) { proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr+4, 13, ENC_ASCII|ENC_NA); break; } } /* otherwise fall through */ case NCP_POSITIVE_ACK: /* Positive Acknowledgement */ case NCP_SERVICE_REQUEST: /* Server NCP Request */ case NCP_SERVICE_REPLY: /* Server NCP Reply */ case NCP_WATCHDOG: /* Watchdog Packet */ case NCP_DEALLOCATE_SLOT: /* Deallocate Slot Request */ default: proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence); proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection); proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN); break; } /* * Process the packet body. */ switch (header.type) { case NCP_ALLOCATE_SLOT: /* Allocate Slot Request */ length_remaining = tvb_length_remaining(tvb, commhdr + 4); if (length_remaining > 4) { testvar = tvb_get_ntohl(tvb, commhdr+4); if (testvar == 0x4c495020) { proto_tree_add_text(ncp_tree, tvb, commhdr, -1, "Lip Echo Packet"); /*break;*/ } } next_tvb = tvb_new_subset_remaining(tvb, commhdr); dissect_ncp_request(next_tvb, pinfo, nw_connection, header.sequence, header.type, ncp_tree); break; case NCP_DEALLOCATE_SLOT: /* Deallocate Slot Request */ next_tvb = tvb_new_subset_remaining(tvb, commhdr); dissect_ncp_request(next_tvb, pinfo, nw_connection, header.sequence, header.type, ncp_tree); break; case NCP_SERVICE_REQUEST: /* Server NCP Request */ case NCP_BROADCAST_SLOT: /* Server Broadcast Packet */ next_tvb = tvb_new_subset_remaining(tvb, commhdr); if (tvb_get_guint8(tvb, commhdr+6) == 0x68) { subfunction = tvb_get_guint8(tvb, commhdr+7); switch (subfunction) { case 0x02: /* NDS Frag Packet to decode */ dissect_nds_request(next_tvb, pinfo, nw_connection, header.sequence, header.type, ncp_tree); break; case 0x01: /* NDS Ping */ dissect_ping_req(next_tvb, pinfo, nw_connection, header.sequence, header.type, ncp_tree); break; default: dissect_ncp_request(next_tvb, pinfo, nw_connection, header.sequence, header.type, ncp_tree); break; } } else { dissect_ncp_request(next_tvb, pinfo, nw_connection, header.sequence, header.type, ncp_tree); } break; case NCP_SERVICE_REPLY: /* Server NCP Reply */ next_tvb = tvb_new_subset_remaining(tvb, commhdr); nds_defrag(next_tvb, pinfo, nw_connection, header.sequence, header.type, ncp_tree, &ncp_tap); break; case NCP_POSITIVE_ACK: /* Positive Acknowledgement */ /* * XXX - this used to call "nds_defrag()", which would * clear out "frags". Was that the right thing to * do? */ next_tvb = tvb_new_subset_remaining(tvb, commhdr); dissect_ncp_reply(next_tvb, pinfo, nw_connection, header.sequence, header.type, ncp_tree, &ncp_tap); break; case NCP_WATCHDOG: /* Watchdog Packet */ /* * XXX - should the completion code be interpreted as * it is in "packet-ncp2222.inc"? If so, this * packet should be handled by "dissect_ncp_reply()". */ proto_tree_add_item(ncp_tree, hf_ncp_completion_code, tvb, commhdr + 6, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(ncp_tree, hf_ncp_connection_status, tvb, commhdr + 7, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(ncp_tree, hf_ncp_slot, tvb, commhdr + 8, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(ncp_tree, hf_ncp_control_code, tvb, commhdr + 9, 1, ENC_LITTLE_ENDIAN); /* * Display the rest of the packet as data. */ if (tvb_offset_exists(tvb, commhdr + 10)) { call_dissector(data_handle, tvb_new_subset_remaining(tvb, commhdr + 10), pinfo, ncp_tree); } break; case NCP_BURST_MODE_XFER: /* Packet Burst Packet */ if (flags & SYS) { /* * System packet; show missing fragments if there * are any. */ while (missing_fraglist_count != 0) { proto_tree_add_item(ncp_tree, hf_ncp_missing_data_offset, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(ncp_tree, hf_ncp_missing_data_count, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; missing_fraglist_count--; } } else { /* * XXX - do this by using -1 and -1 as the length * arguments to "tvb_new_subset()" and then calling * "tvb_set_reported_length()"? That'll throw an * exception if "data_len" goes past the reported * length of the packet, but that's arguably a * feature in this case. */ length_remaining = tvb_length_remaining(tvb, offset); if (length_remaining > data_len) length_remaining = data_len; if (data_len != 0) { call_dissector(data_handle, tvb_new_subset(tvb, offset, length_remaining, data_len), pinfo, ncp_tree); } } break; case NCP_LIP_ECHO: /* LIP Echo Packet */ proto_tree_add_text(ncp_tree, tvb, commhdr, -1, "Lip Echo Packet"); break; default: expert_item = proto_tree_add_text(ncp_tree, tvb, commhdr + 6, -1, "%s packets not supported yet", val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)")); if (ncp_echo_err) { expert_add_info_format(pinfo, expert_item, &ei_ncp_type, "%s packets not supported yet", val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)")); } break; } }
static void dissect_pw_cesopsn( tvbuff_t * tvb_original ,packet_info * pinfo ,proto_tree * tree ,pwc_demux_type_t demux) { const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/ gint packet_size; gint payload_size; gint padding_size; int properties; packet_size = tvb_reported_length_remaining(tvb_original, 0); /* * FIXME * "4" below should be replaced by something like "min_packet_size_this_dissector" * Also call to dissect_try_cw_first_nibble() should be moved before this block */ if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */ { proto_item *item; item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA); expert_add_info_format(pinfo, item, &ei_packet_size_too_small, "PW packet size (%d) is too small to carry sensible information" ,(int)packet_size); col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname); col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small"); return; } switch (demux) { case PWC_DEMUX_MPLS: if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree)) { return; } break; case PWC_DEMUX_UDP: break; default: DISSECTOR_ASSERT_NOT_REACHED(); return; } /* check how "good" is this packet */ /* also decide payload length from packet size and CW */ properties = PWC_PACKET_PROPERTIES_T_INITIALIZER; if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/)) { properties |= PWC_CW_BAD_BITS03; } if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/)) { properties |= PWC_CW_BAD_FRAG; } { /* RFC5086: * [LEN (bits (10 to 15) MAY be used to carry the length of the CESoPSN * packet (defined as the size of the CESoPSN header + the payload size) * if it is less than 64 bytes, and MUST be set to zero otherwise. * Note: If fixed RTP header is used in the encapsulation, it is * considered part of the CESoPSN header.] * * Note that this differs from RFC4385's definition of length: * [ If the MPLS payload is less than 64 bytes, the length field * MUST be set to the length of the PW payload...] * * We will use RFC5086's definition here. */ int cw_len; gint payload_size_from_packet; cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f; payload_size_from_packet = packet_size - encaps_size; if (cw_len != 0) { gint payload_size_from_cw; payload_size_from_cw = cw_len - encaps_size; /* * Assumptions for error case, * will be overwritten if no errors found: */ payload_size = payload_size_from_packet; padding_size = 0; if (payload_size_from_cw < 0) { properties |= PWC_CW_BAD_PAYLEN_LT_0; } else if (payload_size_from_cw > payload_size_from_packet) { properties |= PWC_CW_BAD_PAYLEN_GT_PACKET; } else if (payload_size_from_packet >= 64) { properties |= PWC_CW_BAD_LEN_MUST_BE_0; } else /* ok */ { payload_size = payload_size_from_cw; padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */ } } else { payload_size = payload_size_from_packet; padding_size = 0; } } { guint8 cw_lm; cw_lm = tvb_get_guint8(tvb_original, 0) & 0x0b /*l+mod*/; if (NULL == try_val_to_str(cw_lm, vals_cw_lm)) { properties |= PWC_CW_SUSPECT_LM; } { guint8 l_bit, m_bits; l_bit = (cw_lm & 0x08) >> 3; m_bits = (cw_lm & 0x03) >> 0; if ((l_bit == 0 && m_bits == 0x0) /*CESoPSN data packet - normal situation*/ ||(l_bit == 0 && m_bits == 0x2) /*CESoPSN data packet - RDI on the AC*/ ) { if ((payload_size == 0) || ((payload_size % 8) != 0)) { properties |= PWC_PAY_SIZE_BAD; } } else if (l_bit == 1 && m_bits == 0x0) /*TDM data is invalid; payload MAY be omitted*/ { /*allow any size of payload*/ } else /*reserved combinations*/ { /*allow any size of payload*/ } } } /* fill up columns*/ col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname); col_clear(pinfo->cinfo, COL_INFO); if (properties & PWC_ANYOF_CW_BAD) { col_set_str(pinfo->cinfo, COL_INFO, "CW:Bad, "); } else if (properties & PWC_ANYOF_CW_SUSPECT) { col_append_str(pinfo->cinfo, COL_INFO, "CW:Suspect, "); } if (properties & PWC_PAY_SIZE_BAD) { col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, "); } col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size); if (padding_size != 0) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Padding:%d", (int)padding_size); } { proto_item* item; item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA); pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE); pwc_item_append_text_n_items(item,(int)payload_size,"octet"); { proto_tree* tree2; tree2 = proto_item_add_subtree(item, ett); { tvbuff_t* tvb; proto_item* item2; tvb = tvb_new_subset(tvb_original, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW); item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA); pwc_item_append_cw(item2,tvb_get_ntohl(tvb, 0),FALSE); { proto_tree* tree3; tree3 = proto_item_add_subtree(item, ett); { proto_item* item3; if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/ { item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN); expert_add_info(pinfo, item3, &ei_cw_bits03); } item3 = proto_tree_add_item(tree3, hf_cw_lm, tvb, 0, 1, ENC_BIG_ENDIAN); if (properties & PWC_CW_SUSPECT_LM) { expert_add_info(pinfo, item3, &ei_cw_lm); } proto_tree_add_item(tree3, hf_cw_r, tvb, 0, 1, ENC_BIG_ENDIAN); item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN); if (properties & PWC_CW_BAD_FRAG) { expert_add_info(pinfo, item3, &ei_cw_frg); } item3 = proto_tree_add_item(tree3, hf_cw_len, tvb, 1, 1, ENC_BIG_ENDIAN); if (properties & PWC_CW_BAD_PAYLEN_LT_0) { expert_add_info_format(pinfo, item3, &ei_pref_cw_len, "Bad Length: too small, must be > %d", (int)encaps_size); } if (properties & PWC_CW_BAD_PAYLEN_GT_PACKET) { expert_add_info_format(pinfo, item3, &ei_pref_cw_len, "Bad Length: must be <= than PSN packet size (%d)", (int)packet_size); } if (properties & PWC_CW_BAD_LEN_MUST_BE_0) { expert_add_info_format(pinfo, item3, &ei_pref_cw_len, "Bad Length: must be 0 if CESoPSN packet size (%d) is > 64", (int)packet_size); } proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN); } } } } /* payload */ if (payload_size == 0) { if (properties & PWC_PAY_SIZE_BAD) { expert_add_info_format(pinfo, item, &ei_payload_size_invalid_error, "CESoPSN payload: none found. Size of payload must be <> 0"); } else { expert_add_info_format(pinfo, item, &ei_payload_size_invalid_undecoded, "CESoPSN payload: omitted to conserve bandwidth"); } } else { proto_tree* tree2; tree2 = proto_item_add_subtree(item, ett); { proto_item* item2; tvbuff_t* tvb; tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW, payload_size, payload_size); item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA); pwc_item_append_text_n_items(item2,(int)payload_size,"octet"); if (properties & PWC_PAY_SIZE_BAD) { expert_add_info_format(pinfo, item2, &ei_payload_size_invalid_error, "CESoPSN packet payload size must be multiple of 8"); } tree2 = proto_item_add_subtree(item2, ett); call_dissector(data_handle, tvb, pinfo, tree2); item2 = proto_tree_add_int(tree2, hf_payload_l, tvb, 0, 0 ,(int)payload_size); /* allow filtering */ PROTO_ITEM_SET_HIDDEN(item2); } } /* padding */ if (padding_size > 0) { proto_tree* tree2; tree2 = proto_item_add_subtree(item, ett); { tvbuff_t* tvb; tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1); call_dissector(pw_padding_handle, tvb, pinfo, tree2); } } } return; }
/* Code to actually dissect the packets */ static gboolean dissect_ipa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp) { gint remaining; gint header_length = 3; int offset = 0; guint16 len, msg_type; if (tvb_reported_length(tvb) < 4) return FALSE; //sanity check the message type msg_type = tvb_get_guint8(tvb, 2); if ((try_val_to_str(msg_type, ipa_protocol_vals) == NULL) && (msg_type >= ABISIP_RSL_MAX)) return FALSE; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPA"); col_clear(pinfo->cinfo, COL_INFO); while ((remaining = tvb_reported_length_remaining(tvb, offset)) > 0) { proto_item *ti; proto_tree *ipa_tree = NULL; tvbuff_t *next_tvb; len = tvb_get_ntohs(tvb, offset); msg_type = tvb_get_guint8(tvb, offset+2); col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(msg_type, ipa_protocol_vals, "unknown 0x%02x")); /* * The IPA header is different depending on the transport protocol. * With UDP there seems to be a fourth byte for the IPA header. * We attempt to detect this by checking if the length from the * header + four bytes of the IPA header equals the remaining size. */ if (is_udp && (len + 4 == remaining)) { header_length++; } ti = proto_tree_add_protocol_format(tree, proto_ipa, tvb, offset, len+header_length, "IPA protocol ip.access, type: %s", val_to_str(msg_type, ipa_protocol_vals, "unknown 0x%02x")); ipa_tree = proto_item_add_subtree(ti, ett_ipa); proto_tree_add_item(ipa_tree, hf_ipa_data_len, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ipa_tree, hf_ipa_protocol, tvb, offset+2, 1, ENC_BIG_ENDIAN); next_tvb = tvb_new_subset_length(tvb, offset+header_length, len); switch (msg_type) { case ABISIP_OML: /* hand this off to the standard A-bis OML dissector */ if (sub_handles[SUB_OML]) call_dissector(sub_handles[SUB_OML], next_tvb, pinfo, tree); break; case ABISIP_IPACCESS: dissect_ipaccess(next_tvb, pinfo, tree); break; case AIP_SCCP: /* hand this off to the standard SCCP dissector */ call_dissector(sub_handles[SUB_SCCP], next_tvb, pinfo, tree); break; case IPA_MGCP: /* hand this off to the standard MGCP dissector */ call_dissector(sub_handles[SUB_MGCP], next_tvb, pinfo, tree); break; case OSMO_EXT: dissect_osmo(next_tvb, pinfo, ipa_tree, tree, ti); break; case HSL_DEBUG: proto_tree_add_item(ipa_tree, hf_ipa_hsl_debug, next_tvb, 0, len, ENC_ASCII|ENC_NA); if (global_ipa_in_root == TRUE) proto_tree_add_item(tree, hf_ipa_hsl_debug, next_tvb, 0, len, ENC_ASCII|ENC_NA); if (global_ipa_in_info == TRUE) col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", tvb_get_stringz_enc(wmem_packet_scope(), next_tvb, 0, NULL, ENC_ASCII)); break; default: if (msg_type < ABISIP_RSL_MAX) { /* hand this off to the standard A-bis RSL dissector */ call_dissector(sub_handles[SUB_RSL], next_tvb, pinfo, tree); } break; } offset += len + header_length; } return TRUE; }
void dissect_nmas_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, guint8 func _U_, guint8 subfunc, ncp_req_hash_value *request_value) { guint32 foffset=0, roffset=0; guint32 subverb=0; guint8 msgverb=0; guint32 msg_length=0; guint32 return_code=0, encrypt_error=0; proto_tree *atree; proto_item *expert_item; const gchar *str; foffset = 8; if (request_value) { subverb = request_value->req_nds_flags; msgverb = request_value->nds_request_verb; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMAS"); if (tvb_reported_length_remaining(tvb, foffset)<4) { return; } atree = proto_tree_add_subtree_format(ncp_tree, tvb, foffset, -1, ett_nmas, NULL, "Packet Type: %s", val_to_str(subfunc, nmas_func_enum, "Unknown (0x%02x)")); switch (subfunc) { case 1: proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN); /*foffset += 4;*/ break; case 2: proto_tree_add_uint(atree, hf_verb, tvb, foffset, -1, subverb); proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_LITTLE_ENDIAN); msg_length = tvb_get_letohl(tvb, foffset); foffset +=4; proto_tree_add_item(atree, hf_frag_handle, tvb, foffset, 4, ENC_LITTLE_ENDIAN); /* Check for a fragment packet */ if (tvb_get_letohl(tvb, foffset)!=0xffffffff) { break; } foffset += 4; return_code = tvb_get_letohl(tvb, foffset); roffset = foffset; foffset += 4; msg_length -= 8; if (return_code == 0 && msg_length > 0) { switch (subverb) { case 0: /* Fragmented Ping */ proto_tree_add_item(atree, hf_session_ident, tvb, foffset, 4, ENC_BIG_ENDIAN); /*foffset += 4;*/ /*proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4;*/ break; case 2: /* Client Put Data */ proto_tree_add_item(atree, hf_squeue_bytes, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; proto_tree_add_item(atree, hf_cqueue_bytes, tvb, foffset, 4, ENC_LITTLE_ENDIAN); /*foffset += 4;*/ break; case 4: /* Client Get Data */ proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, ENC_NA); /*foffset += msg_length;*/ break; case 6: /* Client Get User NDS Credentials */ proto_tree_add_item(atree, hf_num_creds, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; proto_tree_add_item(atree, hf_cred_type, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; proto_tree_add_item(atree, hf_login_state, tvb, foffset, 4, ENC_LITTLE_ENDIAN); foffset += 4; msg_length -= 12; proto_tree_add_item(atree, hf_enc_cred, tvb, foffset, msg_length, ENC_NA); /*foffset += msg_length;*/ break; case 8: /* Login Store Management */ proto_tree_add_uint_format(atree, hf_lsm_verb, tvb, foffset, -1, msgverb, "Subverb: %s", val_to_str(msgverb, nmas_lsmverb_enum, "Unknown (%u)")); switch(msgverb) { /* The data within these structures is all encrypted. */ case 1: case 3: case 5: case 7: case 9: proto_tree_add_item(atree, hf_enc_data, tvb, foffset, msg_length, ENC_NA); /*foffset += msg_length;*/ break; default: break; } break; case 10: /* Writable Object Check */ proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN); /*foffset += 4;*/ break; case 1242: /* Message Handler */ proto_tree_add_uint_format(atree, hf_msg_verb, tvb, foffset, 1, msgverb, "Subverb: %s", val_to_str(msgverb, nmas_msgverb_enum, "Unknown (%u)")); switch(msgverb) { case 1: msg_length = tvb_get_ntohl(tvb, foffset); proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_BIG_ENDIAN); foffset += 4; proto_tree_add_item(atree, hf_data, tvb, foffset, msg_length, ENC_NA); /*foffset += msg_length;*/ break; case 3: proto_tree_add_item(atree, hf_session_ident, tvb, foffset, 4, ENC_BIG_ENDIAN); /*foffset += 4;*/ break; case 5: /* No Op */ break; case 7: encrypt_error = tvb_get_ntohl(tvb, foffset); str = try_val_to_str(encrypt_error, nmas_errors_enum); if (str) { col_add_fstr(pinfo->cinfo, COL_INFO, "R Payload Error - %s", str); expert_item = proto_tree_add_item(atree, hf_encrypt_error, tvb, foffset, 4, ENC_BIG_ENDIAN); expert_add_info_format(pinfo, expert_item, &ei_encrypt_error, "NMAS Payload Error: %s", str); } else { proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, ENC_NA); } /*foffset += msg_length;*/ break; case 9: /* No Op */ break; default: break; } break; default: break; } } str = try_val_to_str(return_code, nmas_errors_enum); if (str) { expert_item = proto_tree_add_item(atree, hf_return_code, tvb, roffset, 4, ENC_LITTLE_ENDIAN); expert_add_info_format(pinfo, expert_item, &ei_return_error, "NMAS Error: 0x%08x %s", return_code, str); col_add_fstr(pinfo->cinfo, COL_INFO, "R Error - %s", str); } else { if (return_code!=0) { expert_item = proto_tree_add_item(atree, hf_return_code, tvb, roffset, 4, ENC_LITTLE_ENDIAN); expert_add_info_format(pinfo, expert_item, &ei_return_error, "NMAS Error: 0x%08x is unknown", return_code); col_add_fstr(pinfo->cinfo, COL_INFO, "R Unknown NMAS Error - 0x%08x", return_code); } } if (return_code == 0) { proto_tree_add_uint_format_value(atree, hf_return_code, tvb, roffset, 4, return_code, "Success (0x00000000)"); } break; case 3: break; default: break; } }
static void display_xip_serval(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *xip_serval_tree; proto_item *ti, *check_ti, *hl_ti; tvbuff_t *next_tvb; vec_t cksum_vec; gint offset; guint16 packet_checksum, actual_checksum; guint8 xsh_len, protocol, bytes_remaining; /* Get XIP Serval header length, stored as number of 32-bit words. */ xsh_len = tvb_get_guint8(tvb, XSRVL_LEN) << 2; /* Create XIP Serval header tree. */ ti = proto_tree_add_item(tree, proto_xip_serval, tvb, 0, xsh_len, ENC_NA); xip_serval_tree = proto_item_add_subtree(ti, ett_xip_serval_tree); /* Add XIP Serval header length. */ hl_ti = proto_tree_add_item(xip_serval_tree, hf_xip_serval_hl, tvb, XSRVL_LEN, 1, ENC_BIG_ENDIAN); proto_item_append_text(hl_ti, " bytes"); if (tvb_captured_length(tvb) < xsh_len) expert_add_info_format(pinfo, hl_ti, &ei_xip_serval_bad_len, "Header Length field (%d bytes) cannot be greater than actual number of bytes left in packet (%d bytes)", xsh_len, tvb_captured_length(tvb)); /* Add XIP Serval protocol. If it's not data, TCP, or UDP, the * packet is malformed. */ proto_tree_add_item(xip_serval_tree, hf_xip_serval_proto, tvb, XSRVL_PRO, 1, ENC_BIG_ENDIAN); protocol = tvb_get_guint8(tvb, XSRVL_PRO); if (!try_val_to_str(protocol, xip_serval_proto_vals)) expert_add_info_format(pinfo, ti, &ei_xip_serval_bad_proto, "Unrecognized protocol type: %d", protocol); /* Compute checksum. */ SET_CKSUM_VEC_TVB(cksum_vec, tvb, 0, xsh_len); actual_checksum = in_cksum(&cksum_vec, 1); /* Get XIP Serval checksum. */ packet_checksum = tvb_get_ntohs(tvb, XSRVL_CHK); if (actual_checksum == 0) { /* Add XIP Serval checksum as correct. */ proto_tree_add_uint_format(xip_serval_tree, hf_xip_serval_check, tvb, XSRVL_CHK, 2, packet_checksum, "Header checksum: 0x%04x [correct]", packet_checksum); } else { /* Add XIP Serval checksum as incorrect. */ check_ti = proto_tree_add_uint_format(xip_serval_tree, hf_xip_serval_check, tvb, XSRVL_CHK, 2, packet_checksum, "Header checksum: 0x%04x [incorrect, should be 0x%04x]", packet_checksum, in_cksum_shouldbe(packet_checksum, actual_checksum)); expert_add_info_format(pinfo, check_ti, &ei_xip_serval_bad_checksum, "Bad checksum"); } offset = XSRVL_EXT; /* If there's still more room, check for extension headers. */ bytes_remaining = xsh_len - offset; while (bytes_remaining >= XIP_SERVAL_EXT_MIN_LEN) { gint8 bytes_displayed = display_xip_serval_ext(tvb, pinfo, ti, xip_serval_tree, offset); /* Extension headers are malformed, so we can't say * what the rest of the packet holds. Stop dissecting. */ if (bytes_displayed <= 0) return; offset += bytes_displayed; bytes_remaining -= bytes_displayed; } switch (protocol) { case XIP_SERVAL_PROTO_DATA: next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, tree); break; case IP_PROTO_TCP: { /* Get the Data Offset field of the TCP header, which is * the high nibble of the 12th octet and represents the * size of the TCP header of 32-bit words. */ guint8 tcp_len = hi_nibble(tvb_get_guint8(tvb, offset + 12))*4; next_tvb = tvb_new_subset(tvb, offset, tcp_len, tcp_len); call_dissector(tcp_handle, next_tvb, pinfo, tree); break; } case IP_PROTO_UDP: /* The UDP header is always 8 bytes. */ next_tvb = tvb_new_subset(tvb, offset, 8, 8); call_dissector(udp_handle, next_tvb, pinfo, tree); break; default: break; } }
/* Code to actually dissect BFCP packets */ static void dissect_bfcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; guint8 primitive; const gchar *str; gint bfcp_payload_length; proto_tree *bfcp_tree = NULL; primitive = tvb_get_guint8(tvb, 1); str = try_val_to_str(primitive, map_bfcp_primitive); /* Make entries in Protocol column and Info column on summary display*/ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BFCP"); col_add_str(pinfo->cinfo, COL_INFO, str); if (tree) { proto_item *ti; ti = proto_tree_add_item(tree, proto_bfcp, tvb, 0, -1, ENC_NA); bfcp_tree = proto_item_add_subtree(ti, ett_bfcp); /* The following is the format of the common header. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Ver |R|F| Res | Primitive | Payload Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Conference ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Transaction ID | User ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Fragment Offset (if F is set) | Fragment Length (if F is set) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Add items to BFCP tree */ proto_tree_add_item(bfcp_tree, hf_bfcp_version, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(bfcp_tree, hf_bfcp_hdr_r_bit, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(bfcp_tree, hf_bfcp_hdr_f_bit, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(bfcp_tree, hf_bfcp_primitive, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(bfcp_tree, hf_bfcp_payload_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; proto_tree_add_item(bfcp_tree, hf_bfcp_conference_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; proto_tree_add_item(bfcp_tree, hf_bfcp_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; proto_tree_add_item(bfcp_tree, hf_bfcp_user_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; bfcp_payload_length = tvb_get_ntohs(tvb, BFCP_OFFSET_PAYLOAD_LENGTH) * 4; /*offset = */dissect_bfcp_attributes(tvb, pinfo, bfcp_tree, offset, bfcp_payload_length); } /* if(tree) */ }
static void dissect_usb_i1d3_command( tvbuff_t *tvb, packet_info *pinfo, usb_i1d3_conversation_t *conversation, proto_tree *tree) { // Parsing the command code is a bit tricky: if the most significant // byte is non-zero, the command code is the most significant byte, // *and* the next byte is the first byte of the payload. guint32 command_code = tvb_get_ntohs(tvb, 0); guint32 command_code_msb = command_code & 0xff00; gint command_code_length = 2; if (command_code_msb) { command_code = command_code_msb; command_code_length = 1; } proto_item *command_code_item = proto_tree_add_uint( tree, hf_usb_i1d3_command_code, tvb, 0, command_code_length, command_code); usb_i1d3_transaction_t *transaction; if (!PINFO_FD_VISITED(pinfo)) { transaction = usb_i1d3_create_transaction(conversation, pinfo->num); transaction->command_code = command_code; } else { transaction = (usb_i1d3_transaction_t *)wmem_map_lookup( conversation->request_to_transaction, GUINT_TO_POINTER(pinfo->num)); } DISSECTOR_ASSERT(transaction); if (transaction->response != 0) { proto_item *response_item = proto_tree_add_uint( tree, hf_usb_i1d3_response_in, tvb, 0, 0, transaction->response); PROTO_ITEM_SET_GENERATED(response_item); } const gchar *command_code_string = try_val_to_str( command_code, usb_i1d3_command_code_strings); if (command_code_string) { col_set_str(pinfo->cinfo, COL_INFO, command_code_string); } else { expert_add_info(pinfo, command_code_item, &ei_usb_i1d3_unknown_command); col_set_str(pinfo->cinfo, COL_INFO, "Unknown command"); } switch (command_code) { case USB_I1D3_LOCKRESP: { // TODO: verify that the challenge response is correct proto_tree_add_item( tree, hf_usb_i1d3_challenge_response, tvb, 24, 16, ENC_NA); break; } case USB_I1D3_READINTEE: { guint32 offset, length; proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_readintee_offset, tvb, 1, 1, ENC_NA, &offset); proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_readintee_length, tvb, 2, 1, ENC_NA, &length); col_add_fstr(pinfo->cinfo, COL_INFO, "%s (offset: %u, length: %u)", command_code_string, offset, length); if (!PINFO_FD_VISITED(pinfo)) { transaction->offset = offset; transaction->length = length; } break; } case USB_I1D3_READEXTEE: { guint32 offset, length; proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_readextee_offset, tvb, 1, 2, ENC_BIG_ENDIAN, &offset); proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_readextee_length, tvb, 3, 1, ENC_NA, &length); col_add_fstr(pinfo->cinfo, COL_INFO, "%s (offset: %u, length: %u)", command_code_string, offset, length); if (!PINFO_FD_VISITED(pinfo)) { transaction->offset = offset; transaction->length = length; } break; } case USB_I1D3_MEASURE1: { guint32 integration_time; proto_item *integration_time_item = proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_requested_integration_time, tvb, 1, 4, ENC_LITTLE_ENDIAN, &integration_time); double integration_time_seconds = integration_time / USB_I1D3_CLOCK_FREQUENCY; proto_item_append_text( integration_time_item, " [%.6f seconds]", integration_time_seconds); col_add_fstr(pinfo->cinfo, COL_INFO, "Measure for %.6fs", integration_time_seconds); break; } case USB_I1D3_MEASURE2: { proto_item *edge_count_item = proto_tree_add_item( tree, hf_usb_i1d3_requested_edge_count, tvb, 1, 6, ENC_NA); proto_tree *edge_count_tree = proto_item_add_subtree( edge_count_item, ett_usb_i1d3_requested_edge_count); guint32 edge_count_red, edge_count_green, edge_count_blue; proto_tree_add_item_ret_uint( edge_count_tree, hf_usb_i1d3_requested_edge_count_red, tvb, 1, 2, ENC_LITTLE_ENDIAN, &edge_count_red); proto_tree_add_item_ret_uint( edge_count_tree, hf_usb_i1d3_requested_edge_count_green, tvb, 3, 2, ENC_LITTLE_ENDIAN, &edge_count_green); proto_tree_add_item_ret_uint( edge_count_tree, hf_usb_i1d3_requested_edge_count_blue, tvb, 5, 2, ENC_LITTLE_ENDIAN, &edge_count_blue); proto_item_append_text( edge_count_item, ": R%u G%u B%u", edge_count_red, edge_count_green, edge_count_blue); col_add_fstr(pinfo->cinfo, COL_INFO, "Measure R%u G%u B%u edges", edge_count_red, edge_count_green, edge_count_blue); break; } case USB_I1D3_SETLED: { guint32 led_mode, led_offtime, led_ontime, pulse_count; proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_led_mode, tvb, 1, 1, ENC_NA, &led_mode); proto_item *led_offtime_item = proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_led_offtime, tvb, 2, 1, ENC_NA, &led_offtime); double led_offtime_seconds = led_offtime / USB_I1D3_LED_OFFTIME_FACTOR; proto_item_append_text( led_offtime_item, " [%.6f seconds]", led_offtime_seconds); proto_item *led_ontime_item = proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_led_ontime, tvb, 3, 1, ENC_NA, &led_ontime); double led_ontime_seconds = led_ontime / ((led_mode == USB_I1D3_LED_BLINK) ? USB_I1D3_LED_ONTIME_FACTOR : USB_I1D3_LED_ONTIME_FADE_FACTOR); proto_item_append_text( led_ontime_item, " [%.6f seconds]", led_ontime_seconds); proto_item *pulse_count_item = proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_led_pulse_count, tvb, 4, 1, ENC_NA, &pulse_count); if (pulse_count == 0x80) { proto_item_append_text(pulse_count_item, " [infinity]"); col_add_fstr(pinfo->cinfo, COL_INFO, "Pulse LED off (%.6fs) and on (%.6fs%s) " "indefinitely", led_offtime_seconds, led_ontime_seconds, (led_mode == USB_I1D3_LED_BLINK_FADE_ON) ? " fading" : ""); } else { col_add_fstr(pinfo->cinfo, COL_INFO, "Pulse LED off (%.6fs) and on (%.6fs%s) " "%u times", led_offtime_seconds, led_ontime_seconds, (led_mode == USB_I1D3_LED_BLINK_FADE_ON) ? " fading" : "", pulse_count); } } } }
static void dissect_usb_i1d3_response( tvbuff_t *tvb, packet_info *pinfo, usb_i1d3_conversation_t *conversation, proto_tree *tree) { // The response packet does not contain any information about the command // it is a response to, so we need to reconstruct this information using the // previous packet that we saw. // // Note: currently, for simplicity's sake, this assumes that there is only // one inflight request at any given time - in other words, that there is no // pipelining going on. It is not clear if the device would even be able to // service more than one request at the same time in the first place. usb_i1d3_transaction_t *transaction; if (!PINFO_FD_VISITED(pinfo)) { transaction = (usb_i1d3_transaction_t *)wmem_map_lookup( conversation->request_to_transaction, GUINT_TO_POINTER(conversation->previous_packet)); if (transaction) { DISSECTOR_ASSERT(transaction->response == 0); transaction->response = pinfo->num; wmem_map_insert( conversation->response_to_transaction, GUINT_TO_POINTER(transaction->response), (void *)transaction); } } else { // After the first pass, we can't use previous_packet anymore since // there is no guarantee the dissector is called in order, so we use // the reverse mapping that we populated above. transaction = (usb_i1d3_transaction_t *)wmem_map_lookup( conversation->response_to_transaction, GUINT_TO_POINTER(pinfo->num)); } if (transaction) { DISSECTOR_ASSERT(transaction->response == pinfo->num); DISSECTOR_ASSERT(transaction->request != 0); } proto_item *request_item = proto_tree_add_uint( tree, hf_usb_i1d3_request_in, tvb, 0, 0, transaction ? transaction->request : 0); PROTO_ITEM_SET_GENERATED(request_item); if (!transaction) { expert_add_info(pinfo, request_item, &ei_usb_i1d3_unexpected_response); } else { proto_item *command_code_item = proto_tree_add_uint( tree, hf_usb_i1d3_command_code, tvb, 0, 0, transaction->command_code); PROTO_ITEM_SET_GENERATED(command_code_item); } const gchar *command_string = transaction ? try_val_to_str( transaction->command_code, usb_i1d3_command_code_strings) : NULL; if (!command_string) command_string = "unknown"; guint32 response_code; proto_item *response_code_item = proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_response_code, tvb, 0, 1, ENC_NA, &response_code); proto_item_append_text( response_code_item, " (%s)", (response_code == 0) ? "OK" : "error"); if (response_code != 0) { col_add_fstr( pinfo->cinfo, COL_INFO, "Error code %u (%s)", response_code, command_string); expert_add_info(pinfo, response_code_item, &ei_usb_i1d3_error); return; } col_add_fstr(pinfo->cinfo, COL_INFO, "OK (%s)", command_string); if (!transaction) return; // As mentioned in ArgyllCMS spectro/i1d3.c, the second byte is usually the // first byte of the command code, except for GET_DIFF. if (transaction->command_code != USB_I1D3_GET_DIFF) { guint32 echoed_command_code; proto_item *echoed_command_code_item = proto_tree_add_item_ret_uint( tree, hf_usb_i1d3_echoed_command_code, tvb, 1, 1, ENC_NA, &echoed_command_code); guint8 expected_command_code = transaction->command_code >> 8; proto_item_append_text( echoed_command_code_item, " [expected 0x%02x]", expected_command_code); if (echoed_command_code != expected_command_code) { expert_add_info( pinfo, echoed_command_code_item, &ei_usb_i1d3_echoed_command_code_mismatch); } }
static void dissect_aarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 ar_hrd; guint16 ar_pro; guint8 ar_hln; guint8 ar_pln; guint16 ar_op; proto_tree *aarp_tree; proto_item *ti; const gchar *op_str; int sha_offset, spa_offset, tha_offset, tpa_offset; const gchar *sha_str, *spa_str, /* *tha_str, */ *tpa_str; col_set_str(pinfo->cinfo, COL_PROTOCOL, "AARP"); col_clear(pinfo->cinfo, COL_INFO); ar_hrd = tvb_get_ntohs(tvb, AR_HRD); ar_pro = tvb_get_ntohs(tvb, AR_PRO); ar_hln = tvb_get_guint8(tvb, AR_HLN); ar_pln = tvb_get_guint8(tvb, AR_PLN); ar_op = tvb_get_ntohs(tvb, AR_OP); /* Get the offsets of the addresses. */ sha_offset = MIN_AARP_HEADER_SIZE; spa_offset = sha_offset + ar_hln; tha_offset = spa_offset + ar_pln; tpa_offset = tha_offset + ar_hln; /* Extract the addresses. */ sha_str = tvb_aarphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd); spa_str = tvb_aarpproaddr_to_str(tvb, spa_offset, ar_pln, ar_pro); #if 0 /* TODO: tha_str is currently not shown nor parsed */ tha_str = tvb_aarphrdaddr_to_str(tvb, tha_offset, ar_hln, ar_hrd); #endif tpa_str = tvb_aarpproaddr_to_str(tvb, tpa_offset, ar_pln, ar_pro); switch (ar_op) { case AARP_REQUEST: case AARP_REQUEST_SWAPPED: col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str); break; case AARP_REPLY: case AARP_REPLY_SWAPPED: col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", spa_str, sha_str); break; case AARP_PROBE: case AARP_PROBE_SWAPPED: col_add_fstr(pinfo->cinfo, COL_INFO, "Is there a %s", tpa_str); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown AARP opcode 0x%04x", ar_op); break; } if (tree) { if ((op_str = try_val_to_str(ar_op, op_vals))) ti = proto_tree_add_protocol_format(tree, proto_aarp, tvb, 0, MIN_AARP_HEADER_SIZE + 2*ar_hln + 2*ar_pln, "AppleTalk Address Resolution Protocol (%s)", op_str); else ti = proto_tree_add_protocol_format(tree, proto_aarp, tvb, 0, MIN_AARP_HEADER_SIZE + 2*ar_hln + 2*ar_pln, "AppleTalk Address Resolution Protocol (opcode 0x%04x)", ar_op); aarp_tree = proto_item_add_subtree(ti, ett_aarp); proto_tree_add_uint(aarp_tree, hf_aarp_hard_type, tvb, AR_HRD, 2, ar_hrd); proto_tree_add_uint(aarp_tree, hf_aarp_proto_type, tvb, AR_PRO, 2, ar_pro); proto_tree_add_uint(aarp_tree, hf_aarp_hard_size, tvb, AR_HLN, 1, ar_hln); proto_tree_add_uint(aarp_tree, hf_aarp_proto_size, tvb, AR_PLN, 1, ar_pln); proto_tree_add_uint(aarp_tree, hf_aarp_opcode, tvb, AR_OP, 2, ar_op); if (ar_hln != 0) { proto_tree_add_item(aarp_tree, AARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_aarp_src_hw_mac : hf_aarp_src_hw, tvb, sha_offset, ar_hln, ENC_NA); } if (ar_pln != 0) { if (AARP_PRO_IS_ATALK(ar_pro, ar_pln)) { proto_tree_add_bytes_format_value(aarp_tree, hf_aarp_src_proto_id, tvb, spa_offset, ar_pln, NULL, "%s", spa_str); } else { proto_tree_add_bytes_format_value(aarp_tree, hf_aarp_src_proto, tvb, spa_offset, ar_pln, NULL, "%s", spa_str); } } if (ar_hln != 0) { proto_tree_add_item(aarp_tree, AARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_aarp_dst_hw_mac : hf_aarp_dst_hw, tvb, tha_offset, ar_hln, ENC_NA); } if (ar_pln != 0) { if (AARP_PRO_IS_ATALK(ar_pro, ar_pln)) { proto_tree_add_bytes_format_value(aarp_tree, hf_aarp_dst_proto_id, tvb, tpa_offset, ar_pln, NULL, "%s", tpa_str); } else { proto_tree_add_bytes_format_value(aarp_tree, hf_aarp_dst_proto, tvb, tpa_offset, ar_pln, NULL, "%s", tpa_str); } } } }
void ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype, packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree, int etype_id, int trailer_id, int fcs_len) { const char *description; tvbuff_t *volatile next_tvb; guint length_before; gint captured_length, reported_length; volatile gboolean dissector_found = FALSE; const char *volatile saved_proto; void *pd_save; /* Add the Ethernet type to the protocol tree */ if (tree) { proto_tree_add_uint(fh_tree, etype_id, tvb, offset_after_etype - 2, 2, etype); } /* Get the captured length and reported length of the data after the Ethernet type. */ captured_length = tvb_length_remaining(tvb, offset_after_etype); reported_length = tvb_reported_length_remaining(tvb, offset_after_etype); /* Remember how much data there is after the Ethernet type, including any trailer and FCS. */ length_before = reported_length; /* Construct a tvbuff for the payload after the Ethernet type. If the FCS length is positive, remove the FCS. (If it's zero, there's no FCS; if it's negative, we don't know whether there's an FCS, so we'll guess based on the length of the trailer.) */ if (fcs_len > 0) { if (captured_length >= 0 && reported_length >= 0) { if (reported_length >= fcs_len) reported_length -= fcs_len; if (captured_length > reported_length) captured_length = reported_length; } } next_tvb = tvb_new_subset(tvb, offset_after_etype, captured_length, reported_length); pinfo->ethertype = etype; /* Look for sub-dissector, and call it if found. Catch exceptions, so that if the reported length of "next_tvb" was reduced by some dissector before an exception was thrown, we can still put in an item for the trailer. */ saved_proto = pinfo->current_proto; pd_save = pinfo->private_data; TRY { dissector_found = dissector_try_uint(ethertype_dissector_table, etype, next_tvb, pinfo, tree); } CATCH_NONFATAL_ERRORS { /* Somebody threw an exception that means that there was a problem dissecting the payload; that means that a dissector was found, so we don't need to dissect the payload as data or update the protocol or info columns. Just show the exception and then drive on to show the trailer, after noting that a dissector was found and restoring the protocol value that was in effect before we called the subdissector. */ show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); /* Restore the private_data structure in case one of the * called dissectors modified it (and, due to the exception, * was unable to restore it). */ pinfo->private_data = pd_save; dissector_found = TRUE; pinfo->current_proto = saved_proto; } ENDTRY; if (!dissector_found) { /* No sub-dissector found. Label rest of packet as "Data" */ call_dissector(data_handle,next_tvb, pinfo, tree); /* Label protocol */ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", etype); description = try_val_to_str(etype, etype_vals); if (description) { col_add_str(pinfo->cinfo, COL_INFO, description); } } add_dix_trailer(pinfo, tree, fh_tree, trailer_id, tvb, next_tvb, offset_after_etype, length_before, fcs_len); }