static void dissect_mtp3_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 sio; guint8 service_indicator; tvbuff_t *payload_tvb = NULL; sio = tvb_get_guint8(tvb, SIO_OFFSET); service_indicator = sio & SERVICE_INDICATOR_MASK; switch (mtp3_standard) { case ITU_STANDARD: payload_tvb = tvb_new_subset_remaining(tvb, ITU_MTP_PAYLOAD_OFFSET); break; case ANSI_STANDARD: case CHINESE_ITU_STANDARD: payload_tvb = tvb_new_subset_remaining(tvb, ANSI_MTP_PAYLOAD_OFFSET); break; case JAPAN_STANDARD: payload_tvb = tvb_new_subset_remaining(tvb, JAPAN_MTP_PAYLOAD_OFFSET); break; default: DISSECTOR_ASSERT_NOT_REACHED(); } col_set_str(pinfo->cinfo, COL_INFO, "DATA "); if (!dissector_try_uint(mtp3_sio_dissector_table, service_indicator, payload_tvb, pinfo, tree)) call_dissector(data_handle, payload_tvb, pinfo, tree); }
static void mtp3_pc_to_str_buf(const guint32 pc, gchar *buf, int buf_len) { switch (mtp3_standard) { case ITU_STANDARD: switch (itu_pc_structure) { case ITU_PC_STRUCTURE_NONE: g_snprintf(buf, buf_len, "%u", pc); break; case ITU_PC_STRUCTURE_3_8_3: /* this format is used in international ITU networks */ g_snprintf(buf, buf_len, "%u-%u-%u", (pc & 0x3800)>>11, (pc & 0x7f8) >> 3, (pc & 0x07) >> 0); break; case ITU_PC_STRUCTURE_4_3_4_3: /* this format is used in some national ITU networks, the German one for example. */ g_snprintf(buf, buf_len, "%u-%u-%u-%u", (pc & 0x3c00) >>10, (pc & 0x0380) >> 7, (pc & 0x0078) >> 3, (pc & 0x0007) >> 0); break; default: DISSECTOR_ASSERT_NOT_REACHED(); } break; case ANSI_STANDARD: case CHINESE_ITU_STANDARD: g_snprintf(buf, buf_len, "%u-%u-%u", (pc & ANSI_NETWORK_MASK) >> 16, (pc & ANSI_CLUSTER_MASK) >> 8, (pc & ANSI_MEMBER_MASK)); break; case JAPAN_STANDARD: switch (japan_pc_structure) { case JAPAN_PC_STRUCTURE_NONE: g_snprintf(buf, buf_len, "%u", pc); break; case JAPAN_PC_STRUCTURE_7_4_5: /* This format is specified by NTT */ g_snprintf(buf, buf_len, "%u-%u-%u", (pc & 0xfe00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f)); break; case JAPAN_PC_STRUCTURE_3_4_4_5: /* Where does this format come from? */ g_snprintf(buf, buf_len, "%u-%u-%u-%u", (pc & 0xe000)>>13, (pc & 0x1e00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f)); break; default: DISSECTOR_ASSERT_NOT_REACHED(); } break; default: DISSECTOR_ASSERT_NOT_REACHED(); } }
static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { tvbparse_elem_t* new_elem = NULL; int len = 0; int target_offset = offset; #ifdef TVBPARSE_DEBUG if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: START"); #endif if ( offset + wanted->control.until.subelem->len > tt->end_offset ) return -1; do { len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem, &new_elem); } while(len < 0 && target_offset+1 < tt->end_offset); if (len >= 0) { new_elem->id = wanted->id; new_elem->next = NULL; new_elem->last = NULL; new_elem->wanted = wanted; new_elem->offset = offset; (*tok) = new_elem; switch (wanted->control.until.mode) { case TP_UNTIL_INCLUDE: new_elem->len = target_offset - offset - 1 + len; #ifdef TVBPARSE_DEBUG if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len); #endif return target_offset - offset -1 + len; case TP_UNTIL_SPEND: new_elem->len = target_offset - offset - 1; #ifdef TVBPARSE_DEBUG if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len); #endif return target_offset - offset - 1 + len; case TP_UNTIL_LEAVE: new_elem->len = target_offset - offset - 1; #ifdef TVBPARSE_DEBUG if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1); #endif return target_offset - offset -1; default: DISSECTOR_ASSERT_NOT_REACHED(); return -1; } } else { return -1; } }
static void dissect_stt_checksum(tvbuff_t *tvb, packet_info *pinfo, proto_tree *stt_tree) { gboolean can_checksum = !pinfo->fragmented && tvb_bytes_exist(tvb, 0, tvb_reported_length(tvb)); if (can_checksum && pref_check_checksum) { vec_t cksum_vec[4]; guint32 phdr[2]; /* Set up the fields of the pseudo-header. */ SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data, pinfo->src.len); SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data, pinfo->dst.len); switch (pinfo->src.type) { case AT_IPv4: phdr[0] = g_htonl((IP_PROTO_TCP<<16) + tvb_reported_length(tvb)); SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 4); break; case AT_IPv6: phdr[0] = g_htonl(tvb_reported_length(tvb)); phdr[1] = g_htonl(IP_PROTO_TCP); SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 8); break; default: /* STT runs only atop IPv4 and IPv6.... */ DISSECTOR_ASSERT_NOT_REACHED(); break; } SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, tvb_reported_length(tvb)); proto_tree_add_checksum(stt_tree, tvb, 16, hf_stt_checksum, hf_stt_checksum_status, &ei_stt_checksum_bad, pinfo, in_cksum(cksum_vec, 4), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); } else { proto_tree_add_checksum(stt_tree, tvb, 16, hf_stt_checksum, hf_stt_checksum_status, &ei_stt_checksum_bad, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); } }
static void dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree) { guint32 label, dpc, opc; proto_item *label_item, *label_dpc_item, *label_opc_item; proto_item *hidden_item; proto_tree *label_tree; proto_tree *pc_subtree; int hf_dpc_string; int hf_opc_string; switch (mtp3_standard) { case ITU_STANDARD: label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); label = tvb_get_letohl(tvb, ROUTING_LABEL_OFFSET); opc = (label & ITU_OPC_MASK) >> 14; dpc = label & ITU_DPC_MASK; hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); PROTO_ITEM_SET_HIDDEN(hidden_item); label_dpc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); if (mtp3_pc_structured()) proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc)); if(mtp3_addr_dpc->ni == 0) { pc_subtree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc); analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); } label_opc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); if (mtp3_pc_structured()) proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc)); if(mtp3_addr_opc->ni == 0) { pc_subtree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc); analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); } proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); break; case ANSI_STANDARD: case CHINESE_ITU_STANDARD: if (mtp3_standard == ANSI_STANDARD) { hf_dpc_string = hf_mtp3_ansi_dpc; hf_opc_string = hf_mtp3_ansi_opc; } else /* CHINESE_ITU_STANDARD */ { hf_dpc_string = hf_mtp3_chinese_dpc; hf_opc_string = hf_mtp3_chinese_opc; } /* Create the Routing Label Tree */ label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ANSI_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); /* create and fill the DPC tree */ dissect_mtp3_3byte_pc(tvb, ANSI_DPC_OFFSET, label_tree, ett_mtp3_label_dpc, hf_dpc_string, hf_mtp3_dpc_network, hf_mtp3_dpc_cluster, hf_mtp3_dpc_member, hf_mtp3_24bit_dpc, hf_mtp3_24bit_pc); /* Store dpc for mtp3_addr below */ dpc = tvb_get_letoh24(tvb, ANSI_DPC_OFFSET); /* create and fill the OPC tree */ dissect_mtp3_3byte_pc(tvb, ANSI_OPC_OFFSET, label_tree, ett_mtp3_label_opc, hf_opc_string, hf_mtp3_opc_network, hf_mtp3_opc_cluster, hf_mtp3_opc_member, hf_mtp3_24bit_opc, hf_mtp3_24bit_pc); /* Store opc for mtp3_addr below */ opc = tvb_get_letoh24(tvb, ANSI_OPC_OFFSET); /* SLS */ if (mtp3_standard == ANSI_STANDARD) { if (mtp3_use_ansi_5_bit_sls) proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); else proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } else /* CHINESE_ITU_STANDARD */ { proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } break; case JAPAN_STANDARD: label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, JAPAN_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); label_dpc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_dpc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); dpc = tvb_get_letohs(tvb, ROUTING_LABEL_OFFSET); if (mtp3_pc_structured()) { proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc)); } label_opc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_opc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); opc = tvb_get_letohs(tvb, JAPAN_OPC_OFFSET); if (mtp3_pc_structured()) { proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc)); } hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (mtp3_use_japan_5_bit_sls) { proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); } else { proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); } break; default: DISSECTOR_ASSERT_NOT_REACHED(); } mtp3_addr_opc->type = mtp3_standard; mtp3_addr_opc->pc = opc; SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc); mtp3_addr_dpc->type = mtp3_standard; mtp3_addr_dpc->pc = dpc; SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc); }
/** Only tested for BER */ double asn1_get_real(const guint8 *real_ptr, gint len) { guint8 octet; const guint8 *p; guint8 *buf; double val = 0; /* 8.5.2 If the real value is the value zero, * there shall be no contents octets in the encoding. */ if (len < 1) return val; octet = real_ptr[0]; p = real_ptr + 1; len -= 1; if (octet & 0x80) { /* binary encoding */ int i; gboolean Eneg; gint8 S; /* Sign */ guint8 B; /* Base */ guint8 F; /* scaling Factor */ gint32 E = 0; /* Exponent (supported max 3 octets/24 bit) */ guint64 N = 0; /* N (supported max 8 octets/64 bit) */ guint8 lenE, lenN; if(octet & 0x40) S = -1; else S = 1; switch(octet & 0x30) { case 0x00: B = 2; break; case 0x10: B = 8; break; case 0x20: B = 16; break; case 0x30: /* Reserved */ default: /* TODO Add some warning in tree about reserved value for Base */ return 0; } F = (octet & 0x0c) >> 2; /* 8.5.6.4 Exponent length */ lenE = (octet & 0x3) + 1; if(lenE == 4) { /* we can't handle exponents > 24 bits */ /* TODO Next octet(s) define length of exponent */ DISSECTOR_ASSERT_NOT_REACHED(); } Eneg = (*p) & 0x80 ? TRUE : FALSE; for (i = 0; i < lenE; i++) { if(Eneg) { /* 2's complement: inverse bits */ E = (E<<8) | ((guint8) ~(*p)); } else { E = (E<<8) | *p; } p++; } if(Eneg) { /* 2's complement: ... and add 1 (and make negative of course) */ E = -(E + 1); } lenN = len - lenE; if(lenN > 8) { /* we can't handle integers > 64 bits */ DISSECTOR_ASSERT_NOT_REACHED(); } for (i=0; i<lenN; i++) { N = (N<<8) | *p; p++; } val = (double) S * N * pow(2, F) * pow(B, E); #ifdef DEBUG printf("S = %d, N = %lu, F = %u, B = %u, E = %d -> %f\n", S, N, F, B, E, Eneg, val); #endif } else if (octet & 0x40) { /* SpecialRealValue */
/* * Name: dissect_esis() * * Description: * Main entry area for esis de-mangling. This will build the * main esis tree data and call the sub-protocols as needed. * * Input: * tvbuff * : tvbuff referring to packet data * packet_info * : info for current packet * proto_tree * : tree of display data. May be NULL. * * Output: * void, but we will add to the proto_tree if it is not NULL. */ static void dissect_esis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { const char *pdu_type_string = NULL; const char *pdu_type_format_string = "PDU Type : %s (R:%s%s%s)"; esis_hdr_t ehdr; proto_item *ti; proto_tree *esis_tree = NULL; guint8 variable_len; guint tmp_uint = 0; const char *cksum_status; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESIS"); col_clear(pinfo->cinfo, COL_INFO); tvb_memcpy(tvb, (guint8 *)&ehdr, 0, sizeof ehdr); if (tree) { ti = proto_tree_add_item(tree, proto_esis, tvb, 0, -1, ENC_NA); esis_tree = proto_item_add_subtree(ti, ett_esis); if (ehdr.esis_version != ESIS_REQUIRED_VERSION){ esis_dissect_unknown(tvb, esis_tree, "Unknown ESIS version (%u vs %u)", ehdr.esis_version, ESIS_REQUIRED_VERSION ); return; } if (ehdr.esis_length < ESIS_HDR_FIXED_LENGTH) { esis_dissect_unknown(tvb, esis_tree, "Bogus ESIS length (%u, must be >= %u)", ehdr.esis_length, ESIS_HDR_FIXED_LENGTH ); return; } proto_tree_add_uint( esis_tree, hf_esis_nlpi, tvb, 0, 1, ehdr.esis_nlpi ); proto_tree_add_uint( esis_tree, hf_esis_length, tvb, 1, 1, ehdr.esis_length ); proto_tree_add_uint( esis_tree, hf_esis_version, tvb, 2, 1, ehdr.esis_version ); proto_tree_add_uint( esis_tree, hf_esis_reserved, tvb, 3, 1, ehdr.esis_reserved ); pdu_type_string = val_to_str(ehdr.esis_type&OSI_PDU_TYPE_MASK, esis_vals, "Unknown (0x%x)"); proto_tree_add_uint_format( esis_tree, hf_esis_type, tvb, 4, 1, ehdr.esis_type, pdu_type_format_string, pdu_type_string, (ehdr.esis_type&BIT_8) ? "1" : "0", (ehdr.esis_type&BIT_7) ? "1" : "0", (ehdr.esis_type&BIT_6) ? "1" : "0"); tmp_uint = pntohs( ehdr.esis_holdtime ); proto_tree_add_uint_format(esis_tree, hf_esis_holdtime, tvb, 5, 2, tmp_uint, "Holding Time : %u seconds", tmp_uint ); tmp_uint = pntohs( ehdr.esis_checksum ); switch (calc_checksum( tvb, 0, ehdr.esis_length, tmp_uint )) { case NO_CKSUM: cksum_status = "Not Used"; break; case DATA_MISSING: cksum_status = "Not checkable - not all of packet was captured"; break; case CKSUM_OK: cksum_status = "Is good"; break; case CKSUM_NOT_OK: cksum_status = "Is wrong"; break; default: cksum_status = NULL; DISSECTOR_ASSERT_NOT_REACHED(); } proto_tree_add_uint_format( esis_tree, hf_esis_checksum, tvb, 7, 2, tmp_uint, "Checksum : 0x%x ( %s )", tmp_uint, cksum_status ); } /* * Let us make sure we use the same names for all our decodes * here. First, dump the name into info column, and THEN * dispatch the sub-type. */ if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str( ehdr.esis_type&OSI_PDU_TYPE_MASK, esis_vals, "Unknown (0x%x)" ) ); } variable_len = ehdr.esis_length - ESIS_HDR_FIXED_LENGTH; switch (ehdr.esis_type & OSI_PDU_TYPE_MASK) { case ESIS_ESH_PDU: esis_dissect_esh_pdu( variable_len, tvb, esis_tree); break; case ESIS_ISH_PDU: esis_dissect_ish_pdu( variable_len, tvb, esis_tree); break; case ESIS_RD_PDU: esis_dissect_redirect_pdu( variable_len, tvb, esis_tree); break; default: esis_dissect_unknown(tvb, esis_tree, "Unknown ESIS packet type 0x%x", ehdr.esis_type & OSI_PDU_TYPE_MASK ); } } /* dissect_esis */
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) { gcp_trx_t* t = NULL; gcp_trx_msg_t* trxmsg; if ( !m ) return NULL; if (keep_persistent_data) { if (m->commited) { for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) { if (trxmsg->trx && trxmsg->trx->id == t_id) { return trxmsg->trx; } } DISSECTOR_ASSERT_NOT_REACHED(); } else { emem_tree_key_t key[] = { {1,&(m->hi_addr)}, {1,&(m->lo_addr)}, {1,&(t_id)}, {0,NULL} }; trxmsg = se_alloc(sizeof(gcp_trx_msg_t)); t = se_tree_lookup32_array(trxs,key); if (!t) { t = se_alloc(sizeof(gcp_trx_t)); t->initial = m; t->id = t_id; t->type = type; t->pendings = 0; t->error = 0; t->cmds = NULL; se_tree_insert32_array(trxs,key,t); } /* XXX: request, reply and ack + point to frames where they are */ switch ( type ) { case GCP_TRX_PENDING: t->pendings++; break; default: break; } } } else { t = ep_new(gcp_trx_t); trxmsg = ep_new(gcp_trx_msg_t); t->initial = NULL; t->id = t_id; t->type = type; t->pendings = 0; t->error = 0; t->cmds = NULL; } DISSECTOR_ASSERT(trxmsg); trxmsg->trx = t; trxmsg->next = NULL; trxmsg->last = trxmsg; if (m->trxs) { m->trxs->last = m->trxs->last->next = trxmsg; } else { m->trxs = trxmsg; } return t; }
/* * For PIM v2, see RFC 4601, RFC 3973 and draft-ietf-pim-sm-v2-new-03 * (when PIM is run over IPv6, the rules for computing the PIM checksum * from the draft in question, not from RFC 2362, should be used). */ static void dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; guint8 pim_typever; guint length, pim_length; guint16 pim_cksum, computed_cksum; vec_t cksum_vec[4]; guint32 phdr[2]; const char *typestr; proto_tree *pim_tree = NULL; proto_item *ti; proto_tree *pimopt_tree = NULL; proto_item *tiopt; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIM"); col_clear(pinfo->cinfo, COL_INFO); pim_typever = tvb_get_guint8(tvb, 0); switch (PIM_VER(pim_typever)) { case 2: typestr = val_to_str(PIM_TYPE(pim_typever), type2vals, "Unknown (%u)"); break; case 1: /* PIMv1 - we should never see this */ default: typestr = "Unknown"; break; } if (check_col(pinfo->cinfo, COL_PROTOCOL)) { col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "PIMv%d", PIM_VER(pim_typever)); } if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, typestr); ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, ENC_NA); pim_tree = proto_item_add_subtree(ti, ett_pim); proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(pim_tree, hf_pim_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset + 1, 1, ENC_NA); pim_cksum = tvb_get_ntohs(tvb, offset + 2); length = tvb_length(tvb); if (PIM_VER(pim_typever) == 2) { /* * Well, it's PIM v2, so we can check whether this is a Register * message, and thus can figure out how much to checksum and * whether to make the columns read-only. */ if (PIM_TYPE(pim_typever) == 1) { /* * Register message - the PIM header is 8 bytes long. * Also set the columns non-writable. Otherwise the IPv4 or * IPv6 dissector for the encapsulated packet that caused * this register will overwrite the PIM info in the columns. */ pim_length = 8; col_set_writable(pinfo->cinfo, FALSE); } else { /* * Other message - checksum the entire packet. */ pim_length = tvb_reported_length(tvb); } } else { /* * We don't know what type of message this is, so say that * the length is 0, to force it not to be checksummed. */ pim_length = 0; } if (!pinfo->fragmented && length >= pim_length) { /* * The packet isn't part of a fragmented datagram and isn't * truncated, so we can checksum it. */ switch (pinfo->src.type) { case AT_IPv4: cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length); cksum_vec[0].len = pim_length; computed_cksum = in_cksum(&cksum_vec[0], 1); break; case AT_IPv6: /* Set up the fields of the pseudo-header. */ cksum_vec[0].ptr = pinfo->src.data; cksum_vec[0].len = pinfo->src.len; cksum_vec[1].ptr = pinfo->dst.data; cksum_vec[1].len = pinfo->dst.len; cksum_vec[2].ptr = (const guint8 *)&phdr; phdr[0] = g_htonl(pim_length); phdr[1] = g_htonl(IP_PROTO_PIM); cksum_vec[2].len = 8; cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, pim_length); cksum_vec[3].len = pim_length; computed_cksum = in_cksum(&cksum_vec[0], 4); break; default: /* PIM is available for IPv4 and IPv6 right now */ computed_cksum = 0; /* squelch GCC complaints */ DISSECTOR_ASSERT_NOT_REACHED(); break; } if (computed_cksum == 0) { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset + 2, 2, pim_cksum, "Checksum: 0x%04x [correct]", pim_cksum); } else { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset + 2, 2, pim_cksum, "Checksum: 0x%04x [incorrect, should be 0x%04x]", pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum)); } } else { proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb, offset + 2, 2, pim_cksum); } offset += 4; if (tvb_reported_length_remaining(tvb, offset) > 0) { tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1, "PIM options"); pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts); } else goto done; if (PIM_VER(pim_typever) != 2) goto done; /* version 2 decoder */ switch (PIM_TYPE(pim_typever)) { case 0: /*hello*/ { int opt_count = 0; while (tvb_reported_length_remaining(tvb, offset) >= 2) { guint16 hello_opt, opt_len; guint16 opt_value; proto_item *opt_item; proto_tree *opt_tree; opt_count++; hello_opt = tvb_get_ntohs(tvb, offset); opt_len = tvb_get_ntohs(tvb, offset + 2); opt_item = proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len, "Option %u: %s", hello_opt, val_to_str(hello_opt, pim_opt_vals, "Unknown: %u")); opt_tree = proto_item_add_subtree(opt_item, ett_pim_opt); proto_tree_add_item(opt_tree, hf_pim_optiontype, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_optionlength, tvb, offset + 2, 2, ENC_BIG_ENDIAN); switch(hello_opt) { case 1: /* Hello Hold Time Option */ opt_value = tvb_get_ntohs(tvb, offset + 4); proto_tree_add_uint_format(opt_tree, hf_pim_holdtime, tvb, offset + 4, opt_len, opt_value, "Holdtime: %us %s", opt_value, opt_value == 0 ? "(goodbye)" : opt_value == 0xffff ? "(infinity)": ""); proto_item_append_text(opt_item, ": %us %s", opt_value, opt_value == 0 ? "(goodbye)" : opt_value == 0xffff ? "(infinity)": ""); break; case 2: /* LAN Prune Delay Option */ proto_tree_add_item(opt_tree, hf_pim_t, tvb, offset + 4, 1, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_propagation_delay, tvb, offset + 4, 2, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_override_interval, tvb, offset + 6, 2, ENC_BIG_ENDIAN); proto_item_append_text(opt_item, ": T = %u, Propagation Delay = %ums, Override Interval = %ums", tvb_get_guint8(tvb, offset + 4) & 0x80 ? 1 : 0, tvb_get_ntohs(tvb, offset + 4) & 0x7fff, tvb_get_ntohs(tvb, offset + 6)); break; case 19: /* DR priority */ proto_tree_add_item(opt_tree, hf_pim_dr_priority, tvb, offset + 4, 4, ENC_BIG_ENDIAN); proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4)); break; case 20: /* Generation ID */ proto_tree_add_item(opt_tree, hf_pim_generation_id, tvb, offset + 4, 4, ENC_BIG_ENDIAN); proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4)); break; case 21: /* State Refresh Capable Option */ proto_tree_add_item(opt_tree, hf_pim_state_refresh_version, tvb, offset + 4, 1, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_state_refresh_interval, tvb, offset + 5, 1, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_state_refresh_reserved, tvb, offset + 6, 2, ENC_BIG_ENDIAN); proto_item_append_text(opt_item, ": Version = %u, Interval = %us", tvb_get_guint8(tvb, offset + 4), tvb_get_guint8(tvb, offset + 5)); break; case 24: /* address list */ case 65001: /* address list (old implementations) */ { int i; proto_tree *sub_tree = NULL; proto_item *addrlist_option; addrlist_option = proto_tree_add_text(opt_tree, tvb, offset, 4 + opt_len, "%sAddress List (%u)", hello_opt == 65001 ? "old " : "", hello_opt); sub_tree = proto_item_add_subtree(addrlist_option, ett_pim_opt); for (i = offset + 4; i < offset + 4 + opt_len; ) { int advance; const char *s; s = dissect_pim_addr(tvb, i, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(sub_tree, tvb, offset, advance, "Address: %s", s); i += advance; } break; } default: if (opt_len) proto_tree_add_item(opt_tree, hf_pim_optionvalue, tvb, offset + 4, opt_len, ENC_NA); break; } offset += 4 + opt_len; } proto_item_append_text(tiopt, ": %u", opt_count); break; } case 1: /* register */ { guint32 flags; guint8 v_hl; tvbuff_t *next_tvb; proto_tree *flag_tree = NULL; proto_item *tiflag; flags = tvb_get_ntohl(tvb, offset); tiflag = proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Flags: 0x%08x", flags); flag_tree = proto_item_add_subtree(tiflag, ett_pim); proto_tree_add_text(flag_tree, tvb, offset, 1, "%s", decode_boolean_bitfield(flags, 0x80000000, 32, "Border", "Not border")); proto_tree_add_text(flag_tree, tvb, offset, 1, "%s", decode_boolean_bitfield(flags, 0x40000000, 32, "Null-Register", "Not Null-Register")); offset += 4; /* * The rest of the packet is a multicast data packet. */ next_tvb = tvb_new_subset_remaining(tvb, offset); /* * It's an IP packet - determine whether it's IPv4 or IPv6. */ v_hl = tvb_get_guint8(tvb, offset); switch((v_hl & 0xf0) >> 4) { case 0: /* Null-Register dummy header. * Has the same address family as the encapsulating PIM packet, * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet. */ if (pinfo->src.type == AT_IPv4) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv4 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4, "Source: %s", tvb_ip_to_str(tvb, offset + 12)); proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4, "Group: %s", tvb_ip_to_str(tvb, offset + 16)); } else if (pinfo->src.type == AT_IPv6) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv6 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 8, 16, "Source: %s", tvb_ip6_to_str(tvb, offset + 8)); proto_tree_add_text(pimopt_tree, tvb, offset + 8 + 16, 16, "Group: %s", tvb_ip6_to_str(tvb, offset + 8 + 16)); } else proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Dummy header for an unknown protocol"); break; case 4: /* IPv4 */ #if 0 call_dissector(ip_handle, next_tvb, pinfo, tree); #else call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree); #endif break; case 6: /* IPv6 */ #if 0 call_dissector(ipv6_handle, next_tvb, pinfo, tree); #else call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree); #endif break; default: proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Unknown IP version %d", (v_hl & 0xf0) >> 4); break; } break; } case 2: /* register-stop */ { int advance; const char *s; s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s); break; } case 3: /* join/prune */ case 6: /* graft */ case 7: /* graft-ack */ { int advance; int off; const char *s; int ngroup, i, njoin, nprune, j; guint16 holdtime; proto_tree *grouptree = NULL; proto_item *tigroup; proto_tree *subtree = NULL; proto_item *tisub; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Upstream-neighbor: %s", s); offset += advance; proto_tree_add_item(pimopt_tree, hf_pim_res_bytes, tvb, offset, 1, ENC_NA); offset += 1; /* skip reserved field */ ngroup = tvb_get_guint8(tvb, offset); proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; for (i = 0; i < ngroup; i++) { s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) goto breakbreak3; tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group %d: %s", i, s); grouptree = proto_item_add_subtree(tigroup, ett_pim); offset += advance; njoin = tvb_get_ntohs(tvb, offset); nprune = tvb_get_ntohs(tvb, offset + 2); tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb, offset, 2, ENC_BIG_ENDIAN); subtree = proto_item_add_subtree(tisub, ett_pim); off = offset + 4; for (j = 0; j < njoin; j++) { s = dissect_pim_addr(tvb, off, pimv2_source, &advance); if (s == NULL) goto breakbreak3; proto_tree_add_text(subtree, tvb, off, advance, "IP address: %s", s); off += advance; } tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb, offset + 2, 2, ENC_BIG_ENDIAN); subtree = proto_item_add_subtree(tisub, ett_pim); for (j = 0; j < nprune; j++) { s = dissect_pim_addr(tvb, off, pimv2_source, &advance); if (s == NULL) goto breakbreak3; proto_tree_add_text(subtree, tvb, off, advance, "IP address: %s", s); off += advance; } offset = off; } breakbreak3: break; } case 4: /* bootstrap */ { const char *s; int advance; int i, j; int frpcnt; guint16 holdtime; proto_tree *grouptree = NULL; proto_item *tigroup; proto_tree_add_text(pimopt_tree, tvb, offset, 2, "Fragment tag: 0x%04x", tvb_get_ntohs(tvb, offset)); offset += 2; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Hash mask len: %u", tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "BSR priority: %u", tvb_get_guint8(tvb, offset)); offset += 1; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "BSR: %s", s); offset += advance; for (i = 0; tvb_reported_length_remaining(tvb, offset) > 0; i++) { s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) goto breakbreak4; tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group %d: %s", i, s); grouptree = proto_item_add_subtree(tigroup, ett_pim); offset += advance; proto_tree_add_text(grouptree, tvb, offset, 1, "RP count: %u", tvb_get_guint8(tvb, offset)); offset += 1; frpcnt = tvb_get_guint8(tvb, offset); proto_tree_add_text(grouptree, tvb, offset, 1, "FRP count: %u", frpcnt); offset += 3; for (j = 0; j < frpcnt; j++) { s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) goto breakbreak4; proto_tree_add_text(grouptree, tvb, offset, advance, "RP %d: %s", j, s); offset += advance; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(grouptree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; proto_tree_add_text(grouptree, tvb, offset, 1, "Priority: %u", tvb_get_guint8(tvb, offset)); offset += 2; /* also skips reserved field */ } } breakbreak4: break; } case 5: /* assert */ { const char *s; int advance; guint32 pref; s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s); offset += advance; proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN); pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff; proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb, offset, 4, pref, "Metric Preference: %u", pref); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; } case 8: /* Candidate-RP-Advertisement */ { const char *s; int advance; int pfxcnt; guint16 holdtime; int i; pfxcnt = tvb_get_guint8(tvb, offset); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prefix-count: %u", pfxcnt); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Priority: %u", tvb_get_guint8(tvb, offset)); offset += 1; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "RP: %s", s); offset += advance; for (i = 0; i < pfxcnt; i++) { s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) goto breakbreak8; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group %d: %s", i, s); offset += advance; } breakbreak8: break; } case 9: /* State-Refresh */ { const char *s; int advance; guint32 pref; s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Originator: %s", s); offset += advance; proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN); pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff; proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb, offset, 4, pref, "Metric Preference: %u", pref); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Masklen: %u", tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "TTL: %u", tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune indicator %s", decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x80, 8, "set", "clear")); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune now %s", decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x40, 8, "set", "clear")); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Assert override %s", decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x20, 8, "set", "clear")); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Interval: %u", tvb_get_guint8(tvb, offset)); offset += 1; break; } default: break; } done:; }
static void process_rtsp_request(tvbuff_t *tvb, int offset, const guchar *data, size_t linelen, size_t next_line_offset, proto_tree *tree) { proto_tree *sub_tree = NULL; proto_item *ti = NULL; const guchar *lineend = data + linelen; unsigned ii; const guchar *url; const guchar *url_start; guchar *tmp_url; /* Request Methods */ for (ii = 0; ii < RTSP_NMETHODS; ii++) { size_t len = strlen(rtsp_methods[ii]); if (linelen >= len && g_ascii_strncasecmp(rtsp_methods[ii], data, len) == 0 && (len == linelen || isspace(data[len]))) break; } if (ii == RTSP_NMETHODS) { /* * We got here because "is_rtsp_request_or_reply()" returned * RTSP_REQUEST, so we know one of the request methods * matched, so we "can't get here". */ DISSECTOR_ASSERT_NOT_REACHED(); } /* Add a tree for this request */ ti = proto_tree_add_string(tree, hf_rtsp_request, tvb, offset, (gint) (next_line_offset - offset), tvb_format_text(tvb, offset, (gint) (next_line_offset - offset))); sub_tree = proto_item_add_subtree(ti, ett_rtsp_method); /* Add method name to tree */ proto_tree_add_string(sub_tree, hf_rtsp_method, tvb, offset, (gint) strlen(rtsp_methods[ii]), rtsp_methods[ii]); /* URL */ url = data; /* Skip method name again */ while (url < lineend && !isspace(*url)) url++; /* Skip spaces */ while (url < lineend && isspace(*url)) url++; /* URL starts here */ url_start = url; /* Scan to end of URL */ while (url < lineend && !isspace(*url)) url++; /* Create a URL-sized buffer and copy contents */ tmp_url = ep_alloc(url - url_start + 1); memcpy(tmp_url, url_start, url - url_start); tmp_url[url - url_start] = '\0'; /* Add URL to tree */ proto_tree_add_string(sub_tree, hf_rtsp_url, tvb, offset + (gint) (url_start - data), (gint) (url - url_start), tmp_url); }
static void dissect_1722a (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti = NULL; proto_tree *ieee1722a_tree = NULL; proto_tree *audio_tree = NULL; proto_tree *sample_tree = NULL; proto_tree *timestamp_tree = NULL; gint offset = 0; guint16 datalen = 0; guint16 channels_per_frame = 0; guint8 subtype = 0; gint sample_width = 0; int i, j; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE1722a"); col_set_str(pinfo->cinfo, COL_INFO, "AVB Transportation Protocol"); if (tree) { ti = proto_tree_add_item(tree, proto_1722a, tvb, 0, -1, ENC_NA); ieee1722a_tree = proto_item_add_subtree(ti, ett_1722a); } /* Version field ends the common AVTPDU. Now parse the specfic packet type */ subtype = tvb_get_guint8(tvb, IEEE_1722A_CD_OFFSET); subtype &= IEEE_1722A_SUBTYPE_MASK; switch (subtype) { case IEEE_1722A_SUBTYPE_AVTP_AUDIO: if (tree) { proto_tree_add_item(ieee1722a_tree, hf_1722a_mrfield, tvb, IEEE_1722A_VERSION_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_tvfield, tvb, IEEE_1722A_VERSION_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_seqnum, tvb, IEEE_1722A_SEQ_NUM_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_tufield, tvb, IEEE_1722A_TU_FIELD_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_stream_id, tvb, IEEE_1722A_STREAM_ID_OFFSET, 8, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_avbtp_timestamp, tvb, IEEE_1722A_TIMESTAMP_OFFSET, 4, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_format_info, tvb, IEEE_1722A_FORMAT_INFO_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_nominal_sample_rate, tvb, IEEE_1722A_NOM_SAMPLE_RATE_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_channels_per_frame, tvb, IEEE_1722A_CHANNELS_PER_FRAME_OFFSET, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_bit_depth, tvb, IEEE_1722A_BIT_DEPTH_OFFSET, 1, ENC_BIG_ENDIAN); ti = proto_tree_add_item(ieee1722a_tree, hf_1722a_stream_data_length, tvb, IEEE_1722A_STREAM_DATA_LENGTH_OFFSET, 2, ENC_BIG_ENDIAN); proto_item_append_text(ti, " bytes"); proto_tree_add_item(ieee1722a_tree, hf_1722a_sparse_timestamp, tvb, IEEE_1722A_SPARSE_TIMESTAMP_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_evtfield, tvb, IEEE_1722A_EVT_OFFSET, 1, ENC_BIG_ENDIAN); } /* Make the Audio sample tree. */ datalen = tvb_get_ntohs(tvb, IEEE_1722A_STREAM_DATA_LENGTH_OFFSET); /* Length of audio data in bytes */ ti = proto_tree_add_item(ieee1722a_tree, hf_1722a_data, tvb, IEEE_1722A_DATA_OFFSET, datalen, ENC_NA); audio_tree = proto_item_add_subtree(ti, ett_1722a_audio); /* Need to get the offset of where the audio data starts */ offset = IEEE_1722A_DATA_OFFSET; channels_per_frame = tvb_get_ntohs(tvb, IEEE_1722A_CHANNELS_PER_FRAME_OFFSET); channels_per_frame &= IEEE_1722A_CHANNEL_PER_FRAME_MASK; switch (tvb_get_guint8(tvb, IEEE_1722A_FORMAT_INFO_OFFSET)) { case 0: break; case 1: sample_width = 32; break; case 2: sample_width = 32; break; case 3: sample_width = 24; break; case 4: sample_width = 16; break; default: expert_add_info(pinfo, ti, &ei_format_info); break; } if (sample_width == 0) { expert_add_info(pinfo, ti, &ei_sample_width); } else { if (channels_per_frame == 0) { expert_add_info(pinfo, ti, &ei_channels_per_frame); } else { if (tree) { /* Loop through all samples and add them to the audio tree. */ for (j = 0; j < ((datalen * 8) / (channels_per_frame * sample_width)); j++) { sample_tree = proto_tree_add_subtree_format(audio_tree, tvb, offset, 1, ett_1722a_sample, &ti, "Sample Chunk %d", j); for (i = 0; i < channels_per_frame; i++) { ti = proto_tree_add_item(sample_tree, hf_1722a_sample, tvb, offset, sample_width / 8, ENC_NA); proto_item_prepend_text(ti, "Channel: %d ", i); offset += (sample_width / 8); } } } } } break; case IEEE_1722A_SUBTYPE_CRF: proto_tree_add_item(ieee1722a_tree, hf_1722a_mrfield, tvb, IEEE_1722A_VERSION_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_tvfield, tvb, IEEE_1722A_VERSION_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_seqnum, tvb, IEEE_1722A_SEQ_NUM_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_tufield, tvb, IEEE_1722A_TU_FIELD_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_stream_id, tvb, IEEE_1722A_STREAM_ID_OFFSET, 8, ENC_BIG_ENDIAN); ti = proto_tree_add_item(ieee1722a_tree, hf_1722a_stream_data_length, tvb, IEEE_1722A_STREAM_DATA_LENGTH_OFFSET, 2, ENC_BIG_ENDIAN); proto_item_append_text(ti, " bytes"); proto_tree_add_item(ieee1722a_tree, hf_1722a_crf_type, tvb, IEEE_1722A_CRF_TYPE_OFFSET, 2, ENC_BIG_ENDIAN); switch (tvb_get_ntohs(tvb, IEEE_1722A_CRF_TYPE_OFFSET)) { /* Audio Timestamp Case */ case IEEE_1722A_CRF_AUDIO_SAMPLE_TIMESTAMP: if (tree) { proto_tree_add_item(ieee1722a_tree, hf_1722a_clock_frequency, tvb, IEEE_1722A_CRF_CLOCK_FREQUENCY_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_clock_multiplier, tvb, IEEE_1722A_CRF_CLOCK_MULTIPLIER_OFFSET, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ieee1722a_tree, hf_1722a_timestamp_interval, tvb, IEEE_1722A_CRF_TIMESTAMP_INTERVAL_OFFSET, 2, ENC_BIG_ENDIAN); /* Make the Timestamp tree. */ datalen = tvb_get_ntohs(tvb, IEEE_1722A_STREAM_DATA_LENGTH_OFFSET); datalen = datalen - 6; /* remove type field and type header */ ti = proto_tree_add_item(ieee1722a_tree, hf_1722a_crf_timestamp, tvb, IEEE_1722A_CRF_AUDIO_TIMESTAMP_OFFSET, datalen, ENC_NA); timestamp_tree = proto_item_add_subtree(ti, ett_1722a_crf_timestamp); offset = IEEE_1722A_CRF_AUDIO_TIMESTAMP_OFFSET; /* Loop through all timestamps and add them to the timestamp tree. */ for (j = 0; j < (datalen / IEEE_1722A_CRF_TIMESTAMP_SIZE); j++) { proto_tree_add_item(timestamp_tree, hf_1722a_crf_timestamp_data, tvb, offset, IEEE_1722A_CRF_TIMESTAMP_SIZE, ENC_NA); offset += IEEE_1722A_CRF_TIMESTAMP_SIZE; } } break; default: expert_add_info(pinfo, ti, &ei_clock_reference_type); break; } break; default: /* This dissector only registers for subtype 0x02 (AVTP Audio Format) and 0x05 (Clock Reference Format) which will be handled above. So we won`t enter the default path. */ DISSECTOR_ASSERT_NOT_REACHED(); break; } }
/* AU Header dissection */ static offset_struct* dissect_auheader( tvbuff_t *tvb, offset_struct *poffset, packet_info *pinfo, proto_tree *ismacryp_tree, guint set_version ) { proto_item *ismacryp_item; proto_tree *ismacryp_header_tree; proto_tree *ismacryp_header_byte_tree; guint16 header_len_bytes = 0; /* total length of non-first AU header in bytes (rounded up) */ gint header_len = 0; /* length of AU headers in bits */ gint cts_flag =0; gint dts_flag =0; gboolean first_au_flag=FALSE; gint bit_offset = 0; /*first determine total AU header length */ /* calculate each AU header length in bits first */ switch (set_version) { case V11: if (selective_encryption) header_len+=8; /* add one byte to header length */ break; case V20: if (selective_encryption || slice_indication || padding_indication) header_len+=8; /* add one byte to header length */ break; default: DISSECTOR_ASSERT_NOT_REACHED(); break; } /* end switch */ header_len+=au_size_length; /* add au size length */ if (poffset->offset_bytes==AU_HEADERS_LENGTH_SIZE){ /*first AU */ header_len+=8*(iv_length); /* add IV length */ header_len+=8*key_indicator_length; /* add key indicator length */ header_len+=au_index_length; /* add AU index length */ first_au_flag = TRUE; } else { /* not the first AU */ if (key_indicator_per_au_flag == TRUE) header_len+=8*key_indicator_length; /* add key indicator length */ header_len+=8*(delta_iv_length); /* add delta IV length */ header_len+=au_index_delta_length; /* add AU delta index length */ } /* CTS flag is present? */ if (cts_delta_length != 0){ /* need to test whether cts_delta_flag is TRUE or FALSE */ cts_flag=tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8+header_len, 1); /*fetch 1 bit CTS flag */ header_len+=1; /* add CTS flag bit */ if (cts_flag==1) header_len+=cts_delta_length; /* add CTS delta length bits if CTS flag SET */ } /* DTS flag is present? */ if (dts_delta_length != 0){ /* need to test whether dts_delta_flag is TRUE or FALSE */ dts_flag=tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8+header_len, 1); /*fetch 1 bit DTS flag */ header_len+=1; /* add DTS flag bit */ if (dts_flag==1) header_len+=dts_delta_length; /* add DTS delta length bits if DTS flag SET */ } /* RAP flag present? */ if (random_access_indication != FALSE) header_len+=1; /* add 1 bit RAP flag */ /* stream state indication present */ if (stream_state_indication !=0) header_len+=stream_state_indication; /* add stream state indication bits */ /* convert header_len to bytes (rounded up) */ if (header_len% 8!=0) { header_len_bytes=((header_len)/8)+1; /*add 1 */ } else header_len_bytes=((header_len)/8); /* add AU header tree */ ismacryp_item = proto_tree_add_item(ismacryp_tree, hf_ismacryp_header, tvb, poffset->offset_bytes, header_len_bytes, ENC_NA ); proto_item_append_text(ismacryp_item, ": Length=%d bits", header_len); /* add text to Header tree indicating length */ /* sanity check if actual AU header length is zero bits, which indicates an error */ if ( header_len == 0) /* something wrong */ { proto_item_append_text(ismacryp_item, " Error - zero bit AU header size - check parameters!"); } ismacryp_header_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header); /* ismacryp header analysis */ /* we are being asked for details */ /* Extra 1 Byte Header? */ if ((set_version==V20 && (selective_encryption || slice_indication || padding_indication)) || (set_version==V11 && selective_encryption)){ /* add header byte tree */ ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_header_byte, tvb, poffset->offset_bytes, 1, ENC_NA ); proto_item_append_text(ismacryp_item, ": Length=8 bits"); /* add text to Header byte tree indicating length */ ismacryp_header_byte_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header_byte); /*ismacryp_header_byte_tree */ /* we are being asked for details */ /* tvb is network order, so get MSB bits first, so shift 8 bits and work "backwards" */ add_bits(poffset,7); /*shift 7 bits to get correct bit */ /* AU_is_encrypted bit */ bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ if (selective_encryption){ /* bit used */ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_au_is_encrypted, tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit AU_is_encrypted */ } else { /* bit unused */ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits, tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit unused */ } switch (set_version){ /* ISMACryp version? */ case V11: /* Reserved bits */ add_bits(poffset, -7); /* move back 7 bits for reserved bits */ bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits, tvb, bit_offset, 7, ENC_BIG_ENDIAN); /*fetch 7 bits reserved */ add_bits(poffset,8); /* offset to next byte */ break; case V20: /* Slice_start bit */ add_bits(poffset, -1); /* move back 1 bit for slice_start */ bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ if (slice_indication){ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_start, tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit slice_start */ } else { /* bit unused */ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits, tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit unused */ } add_bits(poffset, -1); /* move back 1 bit for slice_end */ /* Slice_end bit */ bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ if (slice_indication){ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_end, tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit Slice_end */ } else { /* bit unused */ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits, tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit unused */ } add_bits(poffset, -3); /* move back 3 bits for padding_bitcount */ /* Padding_bitcount bits */ bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ if (padding_indication){ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_padding_bitcount, tvb, bit_offset, 3, ENC_BIG_ENDIAN); /*fetch 3 bits padding_bitcount */ } else { /* bits unused */ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits, tvb, bit_offset, 3, ENC_BIG_ENDIAN); /*fetch 3 bits unused */ } add_bits(poffset, -2); /* move back 2 bits for reserved bits */ /* Reserved bits */ bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits, tvb, bit_offset, 2, ENC_BIG_ENDIAN); /*fetch 2 bits reserved */ add_bits(poffset,8); /* offset to next byte */ break; default: DISSECTOR_ASSERT_NOT_REACHED(); break; } /* end switch set_version */ } /* end selective encryption */ /* IV */ if (first_au_flag == TRUE && iv_length != 0) { ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_iv, tvb, poffset->offset_bytes, iv_length, ENC_NA); proto_item_append_text(ismacryp_item, ": Length=%d bytes",iv_length); /* add IV info */ col_append_fstr( pinfo->cinfo, COL_INFO, ", IV=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, iv_length,' ')); poffset->offset_bytes+=iv_length; /* add IV length to offset_bytes */ } /*Delta IV */ if (first_au_flag == FALSE && delta_iv_length != 0) { ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_delta_iv, tvb, poffset->offset_bytes, delta_iv_length, ENC_NA); proto_item_append_text(ismacryp_item, ": Length=%d bytes",delta_iv_length); /* add delta IV info */ col_append_fstr( pinfo->cinfo, COL_INFO, ", Delta IV=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, delta_iv_length,' ')); poffset->offset_bytes+=iv_length; /* add IV length to offset_bytes */ } /* Key Indicator */ if ( key_indicator_length != 0 && ( first_au_flag == TRUE || key_indicator_per_au_flag == TRUE) ) { /* (first AU or KI for each AU) and non-zero KeyIndicator size */ ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_key_indicator, tvb, poffset->offset_bytes, key_indicator_length, ENC_NA); proto_item_append_text(ismacryp_item,": Length=%d bytes",key_indicator_length); /* add KI info */ col_append_fstr( pinfo->cinfo, COL_INFO, ", KI=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, key_indicator_length,' ')); poffset->offset_bytes+=key_indicator_length; /* add KI length to offset_bytes */ } /* AU size */ if (au_size_length != 0) /* in bits */ { bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_size, tvb, bit_offset, au_size_length, ENC_BIG_ENDIAN); proto_item_append_text(ismacryp_item, " bytes: Length=%d bits",au_size_length); /* add AU size info */ /*bit_offset+=au_size_length;*/ add_bits(poffset, au_size_length); } /* AU Index */ if (first_au_flag == TRUE && au_index_length != 0) /* first AU and non-zero AU size */ { bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_index, tvb, bit_offset, au_index_length, ENC_BIG_ENDIAN); proto_item_append_text(ismacryp_item, " bits: Length=%d bits",au_index_length); /* add AU index info */ /*bit_offset+=au_index_length;*/ add_bits(poffset, au_index_length); } /* AU index delta */ if (first_au_flag == FALSE && au_index_delta_length != 0) /* not first AU and non-zero AU delta size */ { bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_index_delta, tvb, bit_offset, au_index_delta_length, ENC_BIG_ENDIAN); proto_item_append_text(ismacryp_item, ": Length=%d bits", au_index_delta_length); /* add AU index info */ /*bit_offset+=au_index_delta_length;*/ add_bits(poffset, au_index_delta_length); } /* CTS delta value */ if (cts_delta_length != 0) { bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN); /* read CTS flag */ add_bits(poffset, 1); if (cts_flag==1) { /* now fetch CTS delta value (remember offset 1 bit due to CTS flag) */ bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_delta, tvb, bit_offset, cts_delta_length, ENC_BIG_ENDIAN); /* read CTS delta value */ proto_item_append_text(ismacryp_item, ": Length=%d bits",cts_delta_length); /* add CTS delta info */ add_bits(poffset, cts_delta_length); } } /* DTS delta value */ if (dts_delta_length != 0) { bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN); /* read DTS flag */ add_bits(poffset, 1); /* now fetch DTS delta value (remember offset x bits due to DTS flag) */ if (dts_flag ==1) { bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_delta, tvb, bit_offset, dts_delta_length, ENC_BIG_ENDIAN); /* read DTS delta value */ proto_item_append_text(ismacryp_item, ": Length=%d bits",dts_delta_length); /* add DTS delta info */ add_bits(poffset, dts_delta_length); } } /* RAP */ if (random_access_indication != FALSE) { bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_rap_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN); /* read RAP flag */ add_bits(poffset, 1); } /*STREAM STATE */ if (stream_state_indication != 0) { bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_stream_state, tvb, bit_offset, stream_state_indication, ENC_BIG_ENDIAN); /* read stream state */ add_bits(poffset, stream_state_indication); } /* end header details */ return poffset; }
static void dissect_ismacryp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint ismacryp_version) { guint set_version; /* ISMACryp version used during dissection */ proto_item *ismacryp_item; proto_tree *ismacryp_tree; proto_tree *ismacryp_message_tree; /* select and display ISMACryp version */ if ((ismacryp_version!=version_type) && override_flag){ /* override -> use manual preference setting */ col_append_str(pinfo->cinfo, COL_INFO, " Manual version"); set_version = version_type; /* set to preference value */ } else { set_version = ismacryp_version; } if (set_version == V11){ col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_11); /* display mode */ if (pref_user_mode == FALSE){ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",val_to_str_const(mode, modetypenames, "user mode")); } else { col_append_str(pinfo->cinfo, COL_INFO, ", user mode"); } user_mode = pref_user_mode; } if (set_version == V20){ col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_20); user_mode = TRUE; /* display mode */ col_append_str(pinfo->cinfo, COL_INFO, ", user mode"); } /* select correct AU values depending on version & selected mode in preferences menu if not in user_mode */ if (user_mode == TRUE){ /* use values set in preference menu */ au_size_length = pref_au_size_length; au_index_length = pref_au_index_length; au_index_delta_length = pref_au_index_delta_length; cts_delta_length = pref_cts_delta_length; dts_delta_length = pref_dts_delta_length; random_access_indication = pref_random_access_indication; stream_state_indication = pref_stream_state_indication; } /* end if user_mode == TRUE */ if (user_mode == FALSE){ switch (mode){ case AAC_HBR_MODE: au_size_length = 13; au_index_length = 3; au_index_delta_length = 3; cts_delta_length = 0; dts_delta_length = 0; random_access_indication = FALSE; stream_state_indication = 0; break; case MPEG4_VIDEO_MODE: au_size_length = 0; au_index_length = 0; au_index_delta_length = 0; cts_delta_length = 0; dts_delta_length = 22; random_access_indication = TRUE; stream_state_indication = 0; break; case AVC_VIDEO_MODE: au_size_length = 0; au_index_length = 0; au_index_delta_length = 0; cts_delta_length = 0; dts_delta_length = 22; random_access_indication = TRUE; stream_state_indication = 0; break; default: DISSECTOR_ASSERT_NOT_REACHED(); break; } /* end switch */ } /* end if user_mode == FALSE */ /* navigate through buffer */ if (tree) { /* we are being asked for details */ guint16 au_headers_length = 0; /* total length of AU headers */ guint16 totalbits =0; /* keeps track of total number of AU header bits treated (used to determine end of AU headers) */ int deltabits = -1; /* keeps track of extra bits per AU header treated (used to determine end of AU heafers ) */ guint16 totalbit_offset = 0; /* total offset in bits*/ int nbpadding_bits = 0; /* number of padding bits*/ offset_struct s_offset; offset_struct* poffset; guint16 nbmessage_bytes = 0; /*nb of message data bytes */ s_offset.offset_bytes = 0; /* initialise byte offset */ s_offset.offset_bits = 0; /* initialise bit offset */ poffset = &s_offset; ismacryp_item = proto_tree_add_item(tree, proto_ismacryp, tvb, 0, -1, ENC_NA); ismacryp_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp); proto_item_append_text(tree, ", %s", "ismacryp packet"); /* add text to tree */ /* ismacryp_tree analysis */ /* we are being asked for details */ /* get total length of AU headers (first 2 bytes) */ ismacryp_item = proto_tree_add_item(ismacryp_tree, hf_ismacryp_au_headers_length, tvb, poffset->offset_bytes, AU_HEADERS_LENGTH_SIZE, ENC_BIG_ENDIAN ); proto_item_append_text(ismacryp_item, " (bits)"); /* add text to AU Header tree indicating length */ au_headers_length=tvb_get_ntohs(tvb,poffset->offset_bytes); /* 2 byte au headers length */ poffset->offset_bytes+=AU_HEADERS_LENGTH_SIZE; /* ADD HEADER(S) BRANCH */ /* AU Header loop */ totalbits=(poffset->offset_bytes*8)+poffset->offset_bits; while( ((totalbits-8*AU_HEADERS_LENGTH_SIZE)<au_headers_length) && deltabits!=0 ) /* subtract AU headers length bits*/ { poffset=dissect_auheader( tvb, poffset, pinfo, ismacryp_tree, set_version); deltabits=(poffset->offset_bytes*8)+poffset->offset_bits - totalbits; /* if zero this means no actual AU header so exit while loop */ totalbits+=deltabits; } /* reached end of AU Header(s) */ /* sanity check if actual total AU headers length in bits i.e. totalbits is */ /* the same as expected AU headers length from 2 bytes at start of buffer */ if ( (totalbits-8*AU_HEADERS_LENGTH_SIZE) != au_headers_length) /* something wrong */ { proto_item_append_text(ismacryp_item, " Error - expected total AU headers size (%d bits) " "does not match calculated size (%d bits) - check parameters!", au_headers_length,(totalbits-8*AU_HEADERS_LENGTH_SIZE)); } /* add padding if need to byte align */ if (poffset->offset_bits!=0) { totalbit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ nbpadding_bits = (8-poffset->offset_bits); /* number of padding bits for byte alignment */ ismacryp_item = proto_tree_add_bits_item(ismacryp_tree, hf_ismacryp_padding, tvb, totalbit_offset, nbpadding_bits , ENC_BIG_ENDIAN); /* padding bits */ proto_item_append_text(ismacryp_item, ": Length=%d bits",nbpadding_bits); /* add padding info */ add_bits(poffset, nbpadding_bits); } /* ADD MESSAGE BRANCH */ ismacryp_item = proto_tree_add_item( ismacryp_tree, hf_ismacryp_message, tvb, poffset->offset_bytes, -1, ENC_NA ); ismacryp_message_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_message); proto_item_append_text(ismacryp_item, ", %s", "Encrypted data"); /* add text to Message tree */ nbmessage_bytes = tvb_reported_length_remaining(tvb, poffset->offset_bytes); proto_item_append_text(ismacryp_item, ", Length= %d bytes", nbmessage_bytes ); /* add length of message */ /* ismacryp message tree analysis (encrypted AUs) */ if (ismacryp_message_tree) { /* we are being asked for details */ poffset->offset_bytes+= nbmessage_bytes; /* */ } /* end message details */ /* end ismacryp tree details */ } /* end if tree */ }
static void dissect_llrp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 type, guint offset) { guint8 requested_data; guint16 antenna_id, gpi_port, gpo_port; guint32 spec_id; proto_item *ti; switch (type) { /* Simple cases just have normal TLV or TV parameters */ case LLRP_TYPE_CLOSE_CONNECTION_RESPONSE: case LLRP_TYPE_GET_READER_CAPABILITES_RESPONSE: case LLRP_TYPE_ADD_ROSPEC: case LLRP_TYPE_ADD_ROSPEC_RESPONSE: case LLRP_TYPE_DELETE_ROSPEC_RESPONSE: case LLRP_TYPE_START_ROSPEC_RESPONSE: case LLRP_TYPE_STOP_ROSPEC_RESPONSE: case LLRP_TYPE_ENABLE_ROSPEC_RESPONSE: case LLRP_TYPE_DISABLE_ROSPEC_RESPONSE: case LLRP_TYPE_GET_ROSPECS_RESPONSE: case LLRP_TYPE_ADD_ACCESSSPEC: case LLRP_TYPE_ADD_ACCESSSPEC_RESPONSE: case LLRP_TYPE_DELETE_ACCESSSPEC_RESPONSE: case LLRP_TYPE_ENABLE_ACCESSSPEC_RESPONSE: case LLRP_TYPE_DISABLE_ACCESSSPEC_RESPONSE: case LLRP_TYPE_GET_ACCESSSPECS: case LLRP_TYPE_CLIENT_REQUEST_OP: case LLRP_TYPE_CLIENT_RESQUEST_OP_RESPONSE: case LLRP_TYPE_RO_ACCESS_REPORT: case LLRP_TYPE_READER_EVENT_NOTIFICATION: case LLRP_TYPE_ERROR_MESSAGE: case LLRP_TYPE_GET_READER_CONFIG_RESPONSE: case LLRP_TYPE_SET_READER_CONFIG_RESPONSE: case LLRP_TYPE_SET_PROTOCOL_VERSION_RESPONSE: case LLRP_TYPE_GET_ACCESSSPECS_RESPONSE: case LLRP_TYPE_GET_REPORT: case LLRP_TYPE_ENABLE_EVENTS_AND_REPORTS: dissect_llrp_parameters(tvb, pinfo, tree, offset); break; /* Some just have an ROSpec ID */ case LLRP_TYPE_START_ROSPEC: case LLRP_TYPE_STOP_ROSPEC: case LLRP_TYPE_ENABLE_ROSPEC: case LLRP_TYPE_DISABLE_ROSPEC: case LLRP_TYPE_DELETE_ROSPEC: spec_id = tvb_get_ntohl(tvb, offset); if (spec_id == LLRP_ROSPEC_ALL) proto_tree_add_uint_format(tree, hf_llrp_rospec, tvb, offset, 4, spec_id, "All ROSpecs (%u)", spec_id); else proto_tree_add_item(tree, hf_llrp_rospec, tvb, offset, 4, ENC_BIG_ENDIAN); break; /* Some just have an AccessSpec ID */ case LLRP_TYPE_ENABLE_ACCESSSPEC: case LLRP_TYPE_DELETE_ACCESSSPEC: case LLRP_TYPE_DISABLE_ACCESSSPEC: spec_id = tvb_get_ntohl(tvb, offset); if (spec_id == LLRP_ACCESSSPEC_ALL) proto_tree_add_uint_format(tree, hf_llrp_accessspec, tvb, offset, 4, spec_id, "All Access Specs (%u)", spec_id); else proto_tree_add_item(tree, hf_llrp_accessspec, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_llrp_accessspec, tvb, offset, 4, ENC_BIG_ENDIAN); break; case LLRP_TYPE_GET_READER_CAPABILITES: proto_tree_add_item(tree, hf_llrp_req_cap, tvb, offset, 1, ENC_NA); offset++; dissect_llrp_parameters(tvb, pinfo, tree, offset); break; /* GET_READER_CONFIG is complicated */ case LLRP_TYPE_GET_READER_CONFIG: requested_data = tvb_get_guint8(tvb, offset + 2); switch (requested_data) { case LLRP_CONF_ALL: antenna_id = tvb_get_ntohs(tvb, offset); if (antenna_id == LLRP_ANTENNA_ALL) proto_tree_add_uint_format(tree, hf_llrp_antenna_id, tvb, offset, 2, antenna_id, "All Antennas (%u)", antenna_id); else proto_tree_add_item(tree, hf_llrp_antenna_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_llrp_req_conf, tvb, offset, 1, ENC_NA); offset++; gpi_port = tvb_get_ntohs(tvb, offset); if (gpi_port == LLRP_GPI_PORT_ALL) proto_tree_add_uint_format(tree, hf_llrp_gpi_port, tvb, offset, 2, gpi_port, "All GPI Ports (%u)", gpi_port); else proto_tree_add_item(tree, hf_llrp_gpi_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; gpo_port = tvb_get_ntohs(tvb, offset); if (gpo_port == LLRP_GPO_PORT_ALL) proto_tree_add_uint_format(tree, hf_llrp_gpo_port, tvb, offset, 2, gpo_port, "All GPO Ports (%u)", gpo_port); else proto_tree_add_item(tree, hf_llrp_gpo_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; case LLRP_CONF_ANTENNA_PROPERTIES: case LLRP_CONF_ANTENNA_CONFIGURATION: antenna_id = tvb_get_ntohs(tvb, offset); if (antenna_id == LLRP_ANTENNA_ALL) proto_tree_add_uint_format(tree, hf_llrp_antenna_id, tvb, offset, 2, antenna_id, "All Antennas (%u)", antenna_id); else proto_tree_add_item(tree, hf_llrp_antenna_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_llrp_req_conf, tvb, offset, 1, ENC_NA); offset++; offset += 4; /* Skip both GPI and GPO ports */ break; case LLRP_CONF_IDENTIFICATION: case LLRP_CONF_RO_REPORT_SPEC: case LLRP_CONF_READER_EVENT_NOTIFICATION_SPEC: case LLRP_CONF_ACCESS_REPORT_SPEC: case LLRP_CONF_LLRP_CONFIGURATION_STATE: case LLRP_CONF_KEEPALIVE_SPEC: case LLRP_CONF_EVENTS_AND_REPORTS: offset += 2; /* Skip antenna ID */ proto_tree_add_item(tree, hf_llrp_req_conf, tvb, offset, 1, ENC_NA); offset++; offset += 4; /* Skip both GPI and GPO ports */ break; case LLRP_CONF_GPI_PORT_CURRENT_STATE: offset += 2; /* Skip antenna ID */ proto_tree_add_item(tree, hf_llrp_req_conf, tvb, offset, 1, ENC_NA); offset++; gpi_port = tvb_get_ntohs(tvb, offset); if (gpi_port == LLRP_GPI_PORT_ALL) proto_tree_add_uint_format(tree, hf_llrp_gpi_port, tvb, offset, 2, gpi_port, "All GPI Ports (%u)", gpi_port); else proto_tree_add_item(tree, hf_llrp_gpi_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; offset += 2; /* Skip GPO Port */ break; case LLRP_CONF_GPO_WRITE_DATA: offset += 2; /* Skip antenna ID */ proto_tree_add_item(tree, hf_llrp_req_conf, tvb, offset, 1, ENC_NA); offset++; offset += 2; /* Skip GPI Port */ gpo_port = tvb_get_ntohs(tvb, offset); if (gpo_port == LLRP_GPO_PORT_ALL) proto_tree_add_uint_format(tree, hf_llrp_gpo_port, tvb, offset, 2, gpo_port, "All GPO Ports (%u)", gpo_port); else proto_tree_add_item(tree, hf_llrp_gpo_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; default: offset += 2; /* Skip antenna ID */ ti = proto_tree_add_item(tree, hf_llrp_req_conf, tvb, offset, 1, ENC_NA); expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Unrecognized configuration request: %u", requested_data); offset++; offset += 4; /* Skip both GPI and GPO ports */ break; }; dissect_llrp_parameters(tvb, pinfo, tree, offset); break; /* END GET_READER_CONFIG */ /* Misc */ case LLRP_TYPE_SET_READER_CONFIG: proto_tree_add_item(tree, hf_llrp_rest_fact, tvb, offset, 1, ENC_NA); offset++; dissect_llrp_parameters(tvb, pinfo, tree, offset); break; case LLRP_TYPE_SET_PROTOCOL_VERSION: proto_tree_add_item(tree, hf_llrp_version, tvb, offset, 1, ENC_NA); break; case LLRP_TYPE_GET_SUPPORTED_VERSION_RESPONSE: proto_tree_add_item(tree, hf_llrp_cur_ver, tvb, offset, 1, ENC_NA); offset++; proto_tree_add_item(tree, hf_llrp_sup_ver, tvb, offset, 1, ENC_NA); offset++; dissect_llrp_parameters(tvb, pinfo, tree, offset); break; case LLRP_TYPE_CUSTOM_MESSAGE: proto_tree_add_item(tree, hf_llrp_vendor, tvb, offset, 4, ENC_BIG_ENDIAN); break; /* Some have no extra data expected */ case LLRP_TYPE_KEEPALIVE: case LLRP_TYPE_KEEPALIVE_ACK: case LLRP_TYPE_CLOSE_CONNECTION: case LLRP_TYPE_GET_ROSPECS: case LLRP_TYPE_GET_SUPPORTED_VERSION: break; default: /* We shouldn't be called if we don't already recognize the value */ DISSECTOR_ASSERT_NOT_REACHED(); }; }
/* Dissect OSC message */ static int dissect_osc_message(tvbuff_t *tvb, proto_item *ti, proto_tree *osc_tree, gint offset, gint len) { proto_tree *message_tree = NULL; proto_tree *header_tree = NULL; gint slen; gint rem; gint end = offset + len; const gchar *path = NULL; gint path_len; gint path_offset; const gchar *format = NULL; gint format_offset; gint format_len; const gchar *ptr = NULL; /* peek/read path */ path_offset = offset; path = tvb_get_const_stringz(tvb, path_offset, &path_len); if( (rem = path_len%4) ) path_len += 4-rem; if(!is_valid_path(path)) return -1; /* peek/read fmt */ format_offset = path_offset + path_len; format = tvb_get_const_stringz(tvb, format_offset, &format_len); if( (rem = format_len%4) ) format_len += 4-rem; if(!is_valid_format(format)) return -1; /* create message */ ti = proto_tree_add_none_format(osc_tree, hf_osc_message_type, tvb, offset, len, "Message: %s %s", path, format); message_tree = proto_item_add_subtree(ti, ett_osc_message); /* append header */ ti = proto_tree_add_item(message_tree, hf_osc_message_header_type, tvb, offset, path_len+format_len, ENC_NA); header_tree = proto_item_add_subtree(ti, ett_osc_message_header); /* append path */ proto_tree_add_item(header_tree, hf_osc_message_path_type, tvb, path_offset, path_len, ENC_ASCII | ENC_NA); /* append format */ proto_tree_add_item(header_tree, hf_osc_message_format_type, tvb, format_offset, format_len, ENC_ASCII | ENC_NA); offset += path_len + format_len; /* ::parse argument:: */ ptr = format + 1; /* skip ',' */ while( (*ptr != '\0') && (offset < end) ) { switch(*ptr) { case OSC_INT32: proto_tree_add_item(message_tree, hf_osc_message_int32_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case OSC_FLOAT: proto_tree_add_item(message_tree, hf_osc_message_float_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case OSC_STRING: slen = tvb_strsize(tvb, offset); if( (rem = slen%4) ) slen += 4-rem; proto_tree_add_item(message_tree, hf_osc_message_string_type, tvb, offset, slen, ENC_ASCII | ENC_NA); offset += slen; break; case OSC_BLOB: { proto_item *bi = NULL; proto_tree *blob_tree = NULL; gint32 blen = tvb_get_ntohl(tvb, offset); slen = blen; if( (rem = slen%4) ) slen += 4-rem; bi = proto_tree_add_none_format(message_tree, hf_osc_message_blob_type, tvb, offset, 4+slen, "Blob: %i bytes", blen); blob_tree = proto_item_add_subtree(bi, ett_osc_blob); proto_tree_add_int_format_value(blob_tree, hf_osc_message_blob_size_type, tvb, offset, 4, blen, "%i bytes", blen); offset += 4; /* check for zero length blob */ if(blen == 0) break; proto_tree_add_item(blob_tree, hf_osc_message_blob_data_type, tvb, offset, slen, ENC_NA); offset += slen; break; } case OSC_TRUE: proto_tree_add_item(message_tree, hf_osc_message_true_type, tvb, offset, 0, ENC_NA); break; case OSC_FALSE: proto_tree_add_item(message_tree, hf_osc_message_false_type, tvb, offset, 0, ENC_NA); break; case OSC_NIL: proto_tree_add_item(message_tree, hf_osc_message_nil_type, tvb, offset, 0, ENC_NA); break; case OSC_BANG: proto_tree_add_item(message_tree, hf_osc_message_bang_type, tvb, offset, 0, ENC_NA); break; case OSC_INT64: proto_tree_add_item(message_tree, hf_osc_message_int64_type, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; break; case OSC_DOUBLE: proto_tree_add_item(message_tree, hf_osc_message_double_type, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; break; case OSC_TIMETAG: { guint32 sec = tvb_get_ntohl(tvb, offset); guint32 frac = tvb_get_ntohl(tvb, offset+4); nstime_t ns; if( (sec == 0UL) && (frac == 1UL) ) proto_tree_add_time_format_value(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, &ns, immediate_fmt, immediate_str); else proto_tree_add_item(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN); offset += 8; } break; case OSC_SYMBOL: slen = tvb_strsize(tvb, offset); if( (rem = slen%4) ) slen += 4-rem; proto_tree_add_item(message_tree, hf_osc_message_symbol_type, tvb, offset, slen, ENC_ASCII | ENC_NA); offset += slen; break; case OSC_CHAR: offset += 3; proto_tree_add_item(message_tree, hf_osc_message_char_type, tvb, offset, 1, ENC_ASCII | ENC_NA); offset += 1; break; case OSC_RGBA: { proto_item *ri = NULL; proto_tree *rgba_tree = NULL; ri = proto_tree_add_item(message_tree, hf_osc_message_rgba_type, tvb, offset, 4, ENC_BIG_ENDIAN); rgba_tree = proto_item_add_subtree(ri, ett_osc_rgba); proto_tree_add_item(rgba_tree, hf_osc_message_rgba_red_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_green_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_blue_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_alpha_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case OSC_MIDI: { const gchar *status_str = NULL; const gchar *control_str = NULL; proto_item *mi = NULL; proto_tree *midi_tree = NULL; guint8 channel; guint8 status; guint8 data1; guint8 data2; channel = tvb_get_guint8(tvb, offset); status = tvb_get_guint8(tvb, offset+1); data1 = tvb_get_guint8(tvb, offset+2); data2 = tvb_get_guint8(tvb, offset+3); status_str = val_to_str_const(status, MIDI_status, "Unknown"); if(status == MIDI_STATUS_CONTROLLER) /* MIDI Controller */ { control_str = val_to_str_const(data1, MIDI_control, "Unknown"); mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Channel %2i, %s (0x%02x), %s (0x%02x), 0x%02x", channel, status_str, status, control_str, data1, data2); } else mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Channel %2i, %s (0x%02x), 0x%02x, 0x%02x", channel, status_str, status, data1, data2); midi_tree = proto_item_add_subtree(mi, ett_osc_midi); proto_tree_add_item(midi_tree, hf_osc_message_midi_channel_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_status_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if(status == MIDI_STATUS_CONTROLLER) { proto_tree_add_item(midi_tree, hf_osc_message_midi_controller_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_value_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } else { proto_tree_add_item(midi_tree, hf_osc_message_midi_data1_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } break; } default: /* if we get here, there must be a bug in the dissector */ DISSECTOR_ASSERT_NOT_REACHED(); break; } ptr++; } if(offset != end) return -1; else return 0; }
/* Dissect OSC message */ static int dissect_osc_message(tvbuff_t *tvb, proto_item *ti, proto_tree *osc_tree, gint offset, gint len) { proto_tree *message_tree; proto_tree *header_tree; gint slen; gint rem; gint end = offset + len; const gchar *path; gint path_len; gint path_offset; const gchar *format; gint format_offset; gint format_len; const gchar *ptr; /* peek/read path */ path_offset = offset; path = tvb_get_const_stringz(tvb, path_offset, &path_len); if( (rem = path_len%4) ) path_len += 4-rem; if(!is_valid_path(path)) return -1; /* peek/read fmt */ format_offset = path_offset + path_len; format = tvb_get_const_stringz(tvb, format_offset, &format_len); if( (rem = format_len%4) ) format_len += 4-rem; if(!is_valid_format(format)) return -1; /* create message */ ti = proto_tree_add_none_format(osc_tree, hf_osc_message_type, tvb, offset, len, "Message: %s %s", path, format); message_tree = proto_item_add_subtree(ti, ett_osc_message); /* append header */ ti = proto_tree_add_item(message_tree, hf_osc_message_header_type, tvb, offset, path_len+format_len, ENC_NA); header_tree = proto_item_add_subtree(ti, ett_osc_message_header); /* append path */ proto_tree_add_item(header_tree, hf_osc_message_path_type, tvb, path_offset, path_len, ENC_ASCII | ENC_NA); /* append format */ proto_tree_add_item(header_tree, hf_osc_message_format_type, tvb, format_offset, format_len, ENC_ASCII | ENC_NA); offset += path_len + format_len; /* ::parse argument:: */ ptr = format + 1; /* skip ',' */ while( (*ptr != '\0') && (offset < end) ) { switch(*ptr) { case OSC_INT32: proto_tree_add_item(message_tree, hf_osc_message_int32_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case OSC_FLOAT: proto_tree_add_item(message_tree, hf_osc_message_float_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case OSC_STRING: slen = tvb_strsize(tvb, offset); if( (rem = slen%4) ) slen += 4-rem; proto_tree_add_item(message_tree, hf_osc_message_string_type, tvb, offset, slen, ENC_ASCII | ENC_NA); offset += slen; break; case OSC_BLOB: { proto_item *bi; proto_tree *blob_tree; gint32 blen = tvb_get_ntohl(tvb, offset); slen = blen; if( (rem = slen%4) ) slen += 4-rem; bi = proto_tree_add_none_format(message_tree, hf_osc_message_blob_type, tvb, offset, 4+slen, "Blob: %i bytes", blen); blob_tree = proto_item_add_subtree(bi, ett_osc_blob); proto_tree_add_int_format_value(blob_tree, hf_osc_message_blob_size_type, tvb, offset, 4, blen, "%i bytes", blen); offset += 4; /* check for zero length blob */ if(blen == 0) break; proto_tree_add_item(blob_tree, hf_osc_message_blob_data_type, tvb, offset, slen, ENC_NA); offset += slen; break; } case OSC_TRUE: proto_tree_add_item(message_tree, hf_osc_message_true_type, tvb, offset, 0, ENC_NA); break; case OSC_FALSE: proto_tree_add_item(message_tree, hf_osc_message_false_type, tvb, offset, 0, ENC_NA); break; case OSC_NIL: proto_tree_add_item(message_tree, hf_osc_message_nil_type, tvb, offset, 0, ENC_NA); break; case OSC_BANG: proto_tree_add_item(message_tree, hf_osc_message_bang_type, tvb, offset, 0, ENC_NA); break; case OSC_INT64: proto_tree_add_item(message_tree, hf_osc_message_int64_type, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; break; case OSC_DOUBLE: proto_tree_add_item(message_tree, hf_osc_message_double_type, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; break; case OSC_TIMETAG: { guint32 sec = tvb_get_ntohl(tvb, offset); guint32 frac = tvb_get_ntohl(tvb, offset+4); nstime_t ns; if( (sec == 0) && (frac == 1) ) proto_tree_add_time_format_value(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, &ns, immediate_fmt, immediate_str); else proto_tree_add_item(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN); offset += 8; } break; case OSC_SYMBOL: slen = tvb_strsize(tvb, offset); if( (rem = slen%4) ) slen += 4-rem; proto_tree_add_item(message_tree, hf_osc_message_symbol_type, tvb, offset, slen, ENC_ASCII | ENC_NA); offset += slen; break; case OSC_CHAR: offset += 3; proto_tree_add_item(message_tree, hf_osc_message_char_type, tvb, offset, 1, ENC_ASCII | ENC_NA); offset += 1; break; case OSC_RGBA: { proto_item *ri; proto_tree *rgba_tree; ri = proto_tree_add_item(message_tree, hf_osc_message_rgba_type, tvb, offset, 4, ENC_BIG_ENDIAN); rgba_tree = proto_item_add_subtree(ri, ett_osc_rgba); proto_tree_add_item(rgba_tree, hf_osc_message_rgba_red_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_green_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_blue_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_alpha_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case OSC_MIDI: { const gchar *status_str; proto_item *mi = NULL; proto_tree *midi_tree; guint8 port; guint8 command; guint8 data1; guint8 data2; guint8 status; guint8 channel; gboolean system_msg; guint8 status_shifted; port = tvb_get_guint8(tvb, offset); command = tvb_get_guint8(tvb, offset+1); data1 = tvb_get_guint8(tvb, offset+2); data2 = tvb_get_guint8(tvb, offset+3); status = command & 0xF0; channel = command & 0x0F; system_msg = status == 0xF0; /* is system message */ status_shifted = status >> 4; if(system_msg) status_str = val_to_str_ext_const(command, &MIDI_system_ext, "Unknown"); else status_str = val_to_str_ext_const(status_shifted, &MIDI_status_ext, "Unknown"); if(system_msg) { mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, %s, %i, %i", port, status_str, data1, data2); } else { switch(status_shifted) { case MIDI_STATUS_NOTE_ON: case MIDI_STATUS_NOTE_OFF: case MIDI_STATUS_NOTE_PRESSURE: { const gchar *note_str; note_str = val_to_str_ext_const(data1, &MIDI_note_ext, "Unknown"); mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, Channel %i, %s, %s, %i", port, channel, status_str, note_str, data2); break; } case MIDI_STATUS_CONTROLLER: { const gchar *control_str; control_str = val_to_str_ext_const(data1, &MIDI_control_ext, "Unknown"); mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, Channel %i, %s, %s, %i", port, channel, status_str, control_str, data2); break; } case MIDI_STATUS_PITCH_BENDER: { const gint bender = (((gint)data2 << 7) | (gint)data1) - 0x2000; mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, Channel %i, %s, %i", port, channel, status_str, bender); break; } default: { mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, Channel %i, %s, %i, %i", port, channel, status_str, data1, data2); break; } } } midi_tree = proto_item_add_subtree(mi, ett_osc_midi); proto_tree_add_item(midi_tree, hf_osc_message_midi_port_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if(system_msg) { proto_tree_add_item(midi_tree, hf_osc_message_midi_system_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data1_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } else { proto_tree_add_item(midi_tree, hf_osc_message_midi_status_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(midi_tree, hf_osc_message_midi_channel_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; switch(status_shifted) { case MIDI_STATUS_NOTE_ON: case MIDI_STATUS_NOTE_OFF: { proto_tree_add_item(midi_tree, hf_osc_message_midi_note_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_velocity_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case MIDI_STATUS_NOTE_PRESSURE: { proto_tree_add_item(midi_tree, hf_osc_message_midi_note_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_pressure_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case MIDI_STATUS_CONTROLLER: { proto_tree_add_item(midi_tree, hf_osc_message_midi_controller_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case MIDI_STATUS_CHANNEL_PRESSURE: { proto_tree_add_item(midi_tree, hf_osc_message_midi_pressure_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case MIDI_STATUS_PITCH_BENDER: { const gint bender = (((gint)data2 << 7) | (gint)data1) - 0x2000; proto_tree_add_int(midi_tree, hf_osc_message_midi_bender_type, tvb, offset, 2, bender); offset += 2; break; } default: { proto_tree_add_item(midi_tree, hf_osc_message_midi_data1_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } } } break; } default: /* if we get here, there must be a bug in the dissector */ DISSECTOR_ASSERT_NOT_REACHED(); break; } ptr++; } if(offset != end) return -1; else return 0; }
static void dissect_omapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *omapi_tree; ptvcursor_t* cursor; guint32 authlength; guint32 msglength; guint32 objlength; col_set_str(pinfo->cinfo, COL_PROTOCOL, "OMAPI"); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(tree, proto_omapi, tvb, 0, -1, ENC_NA); omapi_tree = proto_item_add_subtree(ti, ett_omapi); cursor = ptvcursor_new(omapi_tree, tvb, 0); if (tvb_reported_length_remaining(tvb, 0) < 8) { /* Payload too small for OMAPI */ DISSECTOR_ASSERT_NOT_REACHED(); } else if (tvb_reported_length_remaining(tvb, 0) < 24) { /* This is a startup message */ ptvcursor_add(cursor, hf_omapi_version, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_hlength, 4, ENC_BIG_ENDIAN); col_set_str(pinfo->cinfo, COL_INFO, "Status message"); proto_item_append_text(ti, ", Status message"); return; } else if ( !(tvb_get_ntohl(tvb, 8) || tvb_get_ntohl(tvb, 12)) ) { /* This is a startup message, and more */ ptvcursor_add(cursor, hf_omapi_version, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_hlength, 4, ENC_BIG_ENDIAN); col_append_str(pinfo->cinfo, COL_INFO, "Status message"); proto_item_append_text(ti, ", Status message"); } ptvcursor_add(cursor, hf_omapi_auth_id, 4, ENC_BIG_ENDIAN); authlength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_omapi_auth_len, 4, ENC_BIG_ENDIAN); col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)), omapi_opcode_vals, "Unknown opcode (0x%04x)")); proto_item_append_text(ti, ", Opcode: %s", val_to_str(tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)), omapi_opcode_vals, "Unknown opcode (0x%04x)")); ptvcursor_add(cursor, hf_omapi_opcode, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_handle, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_id, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_rid, 4, ENC_BIG_ENDIAN); msglength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); while (msglength) { ptvcursor_add(cursor, hf_omapi_msg_name_len, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_msg_name, msglength, ENC_ASCII|ENC_NA); msglength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_omapi_msg_value_len, 4, ENC_BIG_ENDIAN); if (msglength == 0) { proto_tree_add_text(omapi_tree, tvb, 0, 0, "Empty string"); } else if (msglength == (guint32)~0) { proto_tree_add_text(omapi_tree, tvb, 0, 0, "No value"); } else { ptvcursor_add(cursor, hf_omapi_msg_value, msglength, ENC_ASCII|ENC_NA); } msglength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); } proto_tree_add_text(omapi_tree, tvb, ptvcursor_current_offset(cursor), 2, "Message end tag"); ptvcursor_advance(cursor, 2); objlength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); while (objlength) { ptvcursor_add(cursor, hf_omapi_obj_name_len, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_obj_name, objlength, ENC_ASCII|ENC_NA); objlength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_omapi_obj_value_len, 4, ENC_BIG_ENDIAN); if (objlength == 0) { proto_tree_add_text(omapi_tree, tvb, 0, 0, "Empty string"); } else if (objlength == (guint32)~0) { proto_tree_add_text(omapi_tree, tvb, 0, 0, "No value"); } else { ptvcursor_add(cursor, hf_omapi_obj_value, objlength, ENC_NA); } objlength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); } proto_tree_add_text(omapi_tree, tvb, ptvcursor_current_offset(cursor), 2, "Object end tag"); ptvcursor_advance(cursor, 2); if (authlength > 0) { ptvcursor_add(cursor, hf_omapi_signature, authlength, ENC_NA); } }
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) { gcp_trx_t* t = NULL; gcp_trx_msg_t* trxmsg; if ( !m ) return NULL; if (keep_persistent_data) { if (m->committed) { for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) { if (trxmsg->trx && trxmsg->trx->id == t_id) { return trxmsg->trx; } } DISSECTOR_ASSERT_NOT_REACHED(); } else { wmem_tree_key_t key[4]; key[0].length = 1; key[0].key = &(m->hi_addr); key[1].length = 1; key[1].key = &(m->lo_addr); key[2].length = 1; key[2].key = &(t_id); key[3].length = 0; key[3].key = NULL; trxmsg = wmem_new(wmem_file_scope(), gcp_trx_msg_t); t = (gcp_trx_t *)wmem_tree_lookup32_array(trxs,key); if (!t) { t = wmem_new(wmem_file_scope(), gcp_trx_t); t->initial = m; t->id = t_id; t->type = type; t->pendings = 0; t->error = 0; t->cmds = NULL; wmem_tree_insert32_array(trxs,key,t); } /* XXX: request, reply and ack + point to frames where they are */ switch ( type ) { case GCP_TRX_PENDING: t->pendings++; break; default: break; } } } else { t = wmem_new(wmem_packet_scope(), gcp_trx_t); trxmsg = wmem_new(wmem_packet_scope(), gcp_trx_msg_t); t->initial = NULL; t->id = t_id; t->type = type; t->pendings = 0; t->error = 0; t->cmds = NULL; } DISSECTOR_ASSERT(trxmsg); trxmsg->trx = t; trxmsg->next = NULL; trxmsg->last = trxmsg; if (m->trxs) { m->trxs->last = m->trxs->last->next = trxmsg; } else { m->trxs = trxmsg; } return t; }
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; }
static int dissect_mint_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint32 packet_length, guint received_via) { proto_item *ti; proto_tree *mint_tree = NULL; proto_tree *mint_header_tree = NULL; proto_tree *mint_data_tree = NULL; proto_tree *mint_ctrl_tree = NULL; guint16 bytes_remaining; guint16 packet_type; guint8 type, length, header_length; guint32 message_type; guint8 element_length; static header_field_info *display_hfi_tlv_vals; packet_type = tvb_get_ntohs(tvb, offset + 12); col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type, mint_packettype_vals, "Type 0x%02x")); ti = proto_tree_add_item(tree, hfi_mint, tvb, offset, packet_length, ENC_NA); mint_tree = proto_item_add_subtree(ti, ett_mint); ti = proto_tree_add_item(mint_tree, &hfi_mint_header, tvb, offset, 16, ENC_NA); mint_header_tree = proto_item_add_subtree(ti, ett_mint_header); /* MiNT header */ proto_tree_add_item(mint_header_tree, &hfi_mint_header_unknown1, tvb, offset, 4, ENC_NA); offset += 4; proto_tree_add_item(mint_header_tree, &hfi_mint_header_dstid, tvb, offset, 4, ENC_NA); offset += 4; proto_tree_add_item(mint_header_tree, &hfi_mint_header_srcid, tvb, offset, 4, ENC_NA); offset += 4; proto_tree_add_item(mint_header_tree, &hfi_mint_header_dstdatatype, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(mint_header_tree, &hfi_mint_header_srcdatatype, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* FIXME: This is probably not the right way to determine the packet type. * It's more likely something in mint_header_unknown1 but I haven't * found out what. */ switch(packet_type) { case MINT_TYPE_DATA_UC: ti = proto_tree_add_item(mint_tree, &hfi_mint_data, tvb, offset, packet_length - 16, ENC_NA); mint_data_tree = proto_item_add_subtree(ti, ett_mint_data); proto_tree_add_item(mint_data_tree, &hfi_mint_data_unknown1, tvb, offset, 2, ENC_NA); offset += 2; /* Transported user frame */ if (offset < packet_length) offset += dissect_eth_frame(tvb, pinfo, tree, offset, packet_length - offset); break; case MINT_TYPE_DATA_BCMC: ti = proto_tree_add_item(mint_tree, &hfi_mint_data, tvb, offset, packet_length - 16, ENC_NA); mint_data_tree = proto_item_add_subtree(ti, ett_mint_data); /* Decode as vlan only for now. To be verified against a capture * with CoS != 0 */ proto_tree_add_item(mint_data_tree, &hfi_mint_data_vlan, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(mint_data_tree, &hfi_mint_data_seqno, tvb, offset, 4, ENC_NA); offset += 4; proto_tree_add_item(mint_data_tree, &hfi_mint_data_unknown1, tvb, offset, 4, ENC_NA); offset += 4; /* Transported user frame */ if (offset < packet_length) offset += dissect_eth_frame(tvb, pinfo, tree, offset, packet_length - offset); break; case MINT_TYPE_CTRL_0x0c: ti = proto_tree_add_item(mint_tree, &hfi_mint_control, tvb, offset, packet_length - 16, ENC_NA); mint_ctrl_tree = proto_item_add_subtree(ti, ett_mint_ctrl); proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_32zerobytes, tvb, offset, 32, ENC_NA); offset += 32; proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_unknown1, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_unknown2, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_unknown3, tvb, offset, 1, ENC_NA); offset += 1; header_length = tvb_get_guint8(tvb, offset); proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_header_length, tvb, offset, 1, ENC_NA); offset += 1; message_type = tvb_get_ntohl(tvb, offset); proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_message_type, tvb, offset, 4, ENC_NA); offset += 4; proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_header_sender, tvb, offset, 4, ENC_NA); offset += 4; switch (message_type) { case 0x43534E50: /* CSNP */ element_length = 12; display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_csnp; break; case 0x48454C4F: /* HELO */ element_length = 0; display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_helo; break; case 0x4C535000: /* LSP */ element_length = 8; display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_lsp; break; case 0x50534E50: /* PSNP */ element_length = 4; display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_psnp; break; default: element_length = 0; display_hfi_tlv_vals = &hfi_mint_control_0x0c_type_unknown; } /* FIXME: This should go into the per message_type switch above */ if (header_length > 12) { proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_header_unknown, tvb, offset, header_length - 12, ENC_NA); offset += header_length - 12; } while (offset < packet_length - 2) { type = tvb_get_guint8(tvb, offset); proto_tree_add_item(mint_ctrl_tree, display_hfi_tlv_vals, tvb, offset, 1, ENC_NA); offset += 1; length = tvb_get_guint8(tvb, offset); /* FIXME: This is a hack - reliable array detection missing */ if (type == 1 && length == 128) { proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_array, tvb, offset, 1, ENC_NA); offset += 1; length = tvb_get_guint8(tvb, offset); } proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_length, tvb, offset, 1, ENC_NA); offset += 1; if (offset + length > packet_length) { /* FIXME: print expert information */ break; } if (type == 1 && element_length) { guint32 end_offset = offset + length; for (; offset < end_offset; offset += element_length) { proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_element, tvb, offset, element_length, ENC_NA); } } else { proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x0c_value, tvb, offset, length, ENC_NA); offset += length; } } break; case MINT_TYPE_CTRL_0x1e: ti = proto_tree_add_item(mint_tree, &hfi_mint_control, tvb, offset, packet_length - 16, ENC_NA); mint_ctrl_tree = proto_item_add_subtree(ti, ett_mint_ctrl); proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_32zerobytes, tvb, offset, 32, ENC_NA); offset += 32; bytes_remaining = packet_length - offset; proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x1e_unknown, tvb, offset, bytes_remaining, ENC_NA); offset += bytes_remaining; break; case MINT_TYPE_ETH_0x22: ti = proto_tree_add_item(mint_tree, &hfi_mint_control, tvb, offset, packet_length - 16, ENC_NA); mint_ctrl_tree = proto_item_add_subtree(ti, ett_mint_ctrl); proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_32zerobytes, tvb, offset, 32, ENC_NA); offset += 32; proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x22_message, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; while (offset < packet_length - 2) { proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x22_type, tvb, offset, 1, ENC_NA); offset += 1; length = tvb_get_guint8(tvb, offset); proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x22_length, tvb, offset, 1, ENC_NA); offset += 1; if (offset + length > packet_length) { /* print expert information */ break; } proto_tree_add_item(mint_ctrl_tree, &hfi_mint_control_0x22_value, tvb, offset, length, ENC_NA); offset += length; } break; default: bytes_remaining = packet_length - offset; switch(received_via) { case PORT_MINT_CONTROL_TUNNEL: case ETHERTYPE_MINT: proto_tree_add_item(mint_tree, &hfi_mint_control_unknown1, tvb, offset, bytes_remaining, ENC_NA); break; case PORT_MINT_DATA_TUNNEL: proto_tree_add_item(mint_tree, &hfi_mint_data_unknown1, tvb, offset, bytes_remaining, ENC_NA); break; default: DISSECTOR_ASSERT_NOT_REACHED(); } offset += bytes_remaining; break; } #if defined MINT_DEVELOPMENT tree_expanded_set(ett_mint, TRUE); tree_expanded_set(ett_mint_ethshim, TRUE); tree_expanded_set(ett_mint_header, TRUE); tree_expanded_set(ett_mint_ctrl, TRUE); tree_expanded_set(ett_mint_data, TRUE); #endif return offset; }
gcp_term_t* gcp_cmd_add_term(gcp_msg_t* m, gcp_trx_t* tr, gcp_cmd_t* c, gcp_term_t* t, gcp_wildcard_t wildcard, gboolean persistent) { gcp_terms_t* ct; gcp_terms_t* ct2; static gcp_term_t all_terms = {"$",(guint8*)"",1,GCP_TERM_TYPE_UNKNOWN,NULL,NULL,NULL}; if ( !c ) return NULL; if ( wildcard == GCP_WILDCARD_CHOOSE) { return &all_terms; } if (persistent) { if ( c->msg->commited ) { if (wildcard == GCP_WILDCARD_ALL) { for (ct = c->ctx->terms.next; ct; ct = ct->next) { /* XXX not handling more wilcards in one msg */ if ( ct->term->start == m ) { return ct->term; } } return NULL; } else { for (ct = c->ctx->terms.next; ct; ct = ct->next) { if ( g_str_equal(ct->term->str,t->str) ) { return ct->term; } } return NULL; } } else { for (ct = c->ctx->terms.next; ct; ct = ct->next) { if ( g_str_equal(ct->term->str,t->str) || ct->term->start == m) { break; } } if ( ! ct ) { if (wildcard == GCP_WILDCARD_ALL) { ct = se_alloc(sizeof(gcp_terms_t)); ct->next = NULL; ct->term = se_alloc0(sizeof(gcp_term_t)); ct->term->start = m; ct->term->str = "*"; ct->term->buffer = NULL; ct->term->len = 0; c->terms.last = c->terms.last->next = ct; ct2 = se_alloc0(sizeof(gcp_terms_t)); ct2->term = ct->term; c->ctx->terms.last->next = ct2; c->ctx->terms.last = ct2; return ct->term; } else { for (ct = c->ctx->terms.next; ct; ct = ct->next) { /* XXX not handling more wilcards in one msg */ if ( ct->term->buffer == NULL && tr->cmds->cmd->msg == ct->term->start ) { ct->term->str = se_strdup(t->str); ct->term->buffer = se_memdup(t->buffer,t->len); ct->term->len = t->len; ct2 = se_alloc0(sizeof(gcp_terms_t)); ct2->term = ct->term; c->terms.last = c->terms.last->next = ct2; return ct->term; } if ( g_str_equal(ct->term->str,t->str) ) { ct2 = se_alloc0(sizeof(gcp_terms_t)); ct2->term = ct->term; c->terms.last = c->terms.last->next = ct2; return ct->term; } } ct = se_alloc(sizeof(gcp_terms_t)); ct->next = NULL; ct->term = se_alloc0(sizeof(gcp_term_t)); ct->term->start = m; ct->term->str = se_strdup(t->str); ct->term->buffer = se_memdup(t->buffer,t->len); ct->term->len = t->len; ct2 = se_alloc0(sizeof(gcp_terms_t)); ct2->term = ct->term; c->terms.last = c->terms.last->next = ct2; ct2 = se_alloc0(sizeof(gcp_terms_t)); ct2->term = ct->term; c->ctx->terms.last = c->ctx->terms.last->next = ct2; return ct->term; } } else { ct2 = se_alloc0(sizeof(gcp_terms_t)); ct2->term = ct->term; c->terms.last = c->terms.last->next = ct2; return ct->term; } DISSECTOR_ASSERT_NOT_REACHED(); return NULL; } } else { ct = ep_new(gcp_terms_t); ct->term = t; ct->next = NULL; c->terms.last = c->terms.last->next = ct; return t; } }
static void dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto) { proto_tree *udp_tree = NULL; proto_item *ti, *hidden_item, *port_item; guint len; guint reported_len; vec_t cksum_vec[4]; guint32 phdr[2]; guint16 computed_cksum; int offset = 0; e_udphdr *udph; proto_tree *checksum_tree; proto_item *item; conversation_t *conv = NULL; struct udp_analysis *udpd = NULL; proto_tree *process_tree; udph=ep_new(e_udphdr); SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data); SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data); col_set_str(pinfo->cinfo, COL_PROTOCOL, (ip_proto == IP_PROTO_UDP) ? "UDP" : "UDPlite"); col_clear(pinfo->cinfo, COL_INFO); udph->uh_sport=tvb_get_ntohs(tvb, offset); udph->uh_dport=tvb_get_ntohs(tvb, offset+2); col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s Destination port: %s", get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport)); if (tree) { if (udp_summary_in_tree) { if (ip_proto == IP_PROTO_UDP) { ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8, "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport); } else { ti = proto_tree_add_protocol_format(tree, proto_udplite, tvb, offset, 8, "Lightweight User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport); } } else { ti = proto_tree_add_item(tree, (ip_proto == IP_PROTO_UDP) ? proto_udp : proto_udplite, tvb, offset, 8, ENC_NA); } udp_tree = proto_item_add_subtree(ti, ett_udp); port_item = proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport, "Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport); /* The beginning port number, 32768 + 666 (33434), is from LBL's traceroute.c source code and this code * further assumes that 3 attempts are made per hop */ if(udph->uh_sport > 32768 + 666 && udph->uh_sport <= 32768 + 666 + 30) expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u", ((udph->uh_sport - 32768 - 666 - 1) / 3) + 1, ((udph->uh_sport - 32768 - 666 - 1) % 3) + 1 ); port_item = proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport, "Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport); if(udph->uh_dport > 32768 + 666 && udph->uh_dport <= 32768 + 666 + 30) expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u", ((udph->uh_dport - 32768 - 666 - 1) / 3) + 1, ((udph->uh_dport - 32768 - 666 - 1) % 3) + 1 ); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport); PROTO_ITEM_SET_HIDDEN(hidden_item); } if (ip_proto == IP_PROTO_UDP) { udph->uh_ulen = udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4); if (udph->uh_ulen < 8) { /* Bogus length - it includes the header, so it must be >= 8. */ /* XXX - should handle IPv6 UDP jumbograms (RFC 2675), where the length is zero */ item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen, "Length: %u (bogus, must be >= 8)", udph->uh_ulen); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u < 8", udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u < 8]", udph->uh_ulen); return; } if ((udph->uh_ulen > tvb_reported_length(tvb)) && ! pinfo->fragmented && ! pinfo->flags.in_error_pkt) { /* Bogus length - it goes past the end of the IP payload */ item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen, "Length: %u (bogus, payload length %u)", udph->uh_ulen, tvb_reported_length(tvb)); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u > IP payload length", udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u > IP PAYLOAD LENGTH]", udph->uh_ulen); } else { if (tree) { proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen); /* XXX - why is this here, given that this is UDP, not Lightweight UDP? */ hidden_item = proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 0, udph->uh_sum_cov); PROTO_ITEM_SET_HIDDEN(hidden_item); } } } else { udph->uh_ulen = pinfo->iplen - pinfo->iphdrlen; udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4); if (((udph->uh_sum_cov > 0) && (udph->uh_sum_cov < 8)) || (udph->uh_sum_cov > udph->uh_ulen)) { /* Bogus length - it includes the header, so it must be >= 8, and no larger then the IP payload size. */ if (tree) { hidden_item = proto_tree_add_boolean(udp_tree, hf_udplite_checksum_coverage_bad, tvb, offset + 4, 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen); PROTO_ITEM_SET_HIDDEN(hidden_item); } item = proto_tree_add_uint_format(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov, "Checksum coverage: %u (bogus, must be >= 8 and <= %u (ip.len-ip.hdr_len))", udph->uh_sum_cov, udph->uh_ulen); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad checksum coverage length value %u < 8 or > %u", udph->uh_sum_cov, udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD LIGHTWEIGHT UDP CHECKSUM COVERAGE LENGTH %u < 8 or > %u]", udph->uh_sum_cov, udph->uh_ulen); if (!udplite_ignore_checksum_coverage) return; } else { if (tree) { hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov); } } } udph->uh_sum_cov = (udph->uh_sum_cov) ? udph->uh_sum_cov : udph->uh_ulen; udph->uh_sum = tvb_get_ntohs(tvb, offset+6); reported_len = tvb_reported_length(tvb); len = tvb_length(tvb); if (udph->uh_sum == 0) { /* No checksum supplied in the packet. */ if ((ip_proto == IP_PROTO_UDP) && (pinfo->src.type == AT_IPv4)) { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0, "Checksum: 0x%04x (none)", 0); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0, "Checksum: 0x%04x (Illegal)", 0); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Illegal Checksum value (0)"); col_append_fstr(pinfo->cinfo, COL_INFO, " [ILLEGAL CHECKSUM (0)]"); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); } } else if (!pinfo->fragmented && len >= reported_len && len >= udph->uh_sum_cov && reported_len >= udph->uh_sum_cov && udph->uh_sum_cov >=8) { /* The packet isn't part of a fragmented datagram and isn't truncated, so we can checksum it. XXX - make a bigger scatter-gather list once we do fragment reassembly? */ if (((ip_proto == IP_PROTO_UDP) && (udp_check_checksum)) || ((ip_proto == IP_PROTO_UDPLITE) && (udplite_check_checksum))) { /* Set up the fields of the pseudo-header. */ cksum_vec[0].ptr = (const guint8 *)pinfo->src.data; cksum_vec[0].len = pinfo->src.len; cksum_vec[1].ptr = (const guint8 *)pinfo->dst.data; cksum_vec[1].len = pinfo->dst.len; cksum_vec[2].ptr = (const guint8 *)&phdr; switch (pinfo->src.type) { case AT_IPv4: if (ip_proto == IP_PROTO_UDP) phdr[0] = g_htonl((ip_proto<<16) | udph->uh_ulen); else phdr[0] = g_htonl((ip_proto<<16) | reported_len); cksum_vec[2].len = 4; break; case AT_IPv6: if (ip_proto == IP_PROTO_UDP) phdr[0] = g_htonl(udph->uh_ulen); else phdr[0] = g_htonl(reported_len); phdr[1] = g_htonl(ip_proto); cksum_vec[2].len = 8; break; default: /* UDP runs only atop IPv4 and IPv6.... */ DISSECTOR_ASSERT_NOT_REACHED(); break; } cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, udph->uh_sum_cov); cksum_vec[3].len = udph->uh_sum_cov; computed_cksum = in_cksum(&cksum_vec[0], 4); if (computed_cksum == 0) { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [correct]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"UDP checksum offload\"?)]", udph->uh_sum, in_cksum_shouldbe(udph->uh_sum, computed_cksum)); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); col_append_fstr(pinfo->cinfo, COL_INFO, " [UDP CHECKSUM INCORRECT]"); } } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [validation disabled]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [unchecked, not all data available]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } /* Skip over header */ offset += 8; pinfo->ptype = PT_UDP; pinfo->srcport = udph->uh_sport; pinfo->destport = udph->uh_dport; tap_queue_packet(udp_tap, pinfo, udph); /* find(or create if needed) the conversation for this udp session */ if (udp_process_info) { conv=find_or_create_conversation(pinfo); udpd=get_udp_conversation_data(conv,pinfo); } if (udpd && ((udpd->fwd && udpd->fwd->command) || (udpd->rev && udpd->rev->command))) { ti = proto_tree_add_text(udp_tree, tvb, offset, 0, "Process Information"); PROTO_ITEM_SET_GENERATED(ti); process_tree = proto_item_add_subtree(ti, ett_udp_process_info); if (udpd->fwd && udpd->fwd->command) { proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_uid, tvb, 0, 0, udpd->fwd->process_uid, "%u", udpd->fwd->process_uid); proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_pid, tvb, 0, 0, udpd->fwd->process_pid, "%u", udpd->fwd->process_pid); proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_uname, tvb, 0, 0, udpd->fwd->username, "%s", udpd->fwd->username); proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_cmd, tvb, 0, 0, udpd->fwd->command, "%s", udpd->fwd->command); } if (udpd->rev->command) { proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_uid, tvb, 0, 0, udpd->rev->process_uid, "%u", udpd->rev->process_uid); proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_pid, tvb, 0, 0, udpd->rev->process_pid, "%u", udpd->rev->process_pid); proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_uname, tvb, 0, 0, udpd->rev->username, "%s", udpd->rev->username); proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_cmd, tvb, 0, 0, udpd->rev->command, "%s", udpd->rev->command); } } /* * Call sub-dissectors. * * XXX - should we do this if this is included in an error packet? * It might be nice to see the details of the packet that caused the * ICMP error, but it might not be nice to have the dissector update * state based on it. * Also, we probably don't want to run UDP taps on those packets. * * We definitely don't want to do it for an error packet if there's * nothing left in the packet. */ if (!pinfo->flags.in_error_pkt || tvb_length_remaining(tvb, offset) > 0) decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport, udph->uh_ulen); }
static void dissect_pw_satop(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; enum { PAY_NO_IDEA = 0 ,PAY_LIKE_E1 ,PAY_LIKE_T1 ,PAY_LIKE_E3_T3 ,PAY_LIKE_OCTET_ALIGNED_T1 } payload_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_cw_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 = 0; if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/)) { properties |= PWC_CW_BAD_BITS03; } if (0 != (tvb_get_guint8(tvb_original, 0) & 0x03 /*rsv*/)) { properties |= PWC_CW_BAD_RSV; } if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/)) { properties |= PWC_CW_BAD_FRAG; } { /* RFC4553: * [...MAY be used to carry the length of the SAToP * packet (defined as the size of the SAToP header + the payload * size) if it is less than 64 bytes, and MUST be set to zero * otherwise... ] * * 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 RFC4553'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; } } if (payload_size == 0) { /* * As CW.L it indicates that PW payload is invalid, dissector should * not blame packets with bad payload (including "bad" or "strange" SIZE of * payload) when L bit is set. */ if (0 == (tvb_get_guint8(tvb_original, 0) & 0x08 /*L bit*/)) { properties |= PWC_PAY_SIZE_BAD; } } /* guess about payload type */ if (payload_size == 256) { payload_properties = PAY_LIKE_E1; } else if (payload_size == 192) { payload_properties = PAY_LIKE_T1; } else if (payload_size == 1024) { payload_properties = PAY_LIKE_E3_T3; } else if ((payload_size != 0) && (payload_size % 25 == 0)) { payload_properties = PAY_LIKE_OCTET_ALIGNED_T1; } else { payload_properties = PAY_NO_IDEA; /*we do not have any ideas about payload type*/ } /* 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, "); } if (properties & PWC_PAY_SIZE_BAD) { col_append_str(pinfo->cinfo, COL_INFO, "Payload size:0 (Bad)"); } else { 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_length(tvb_original, 0, 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(item2, 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); } proto_tree_add_item(tree3, hf_cw_l , tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree3, hf_cw_r , tvb, 0, 1, ENC_BIG_ENDIAN); item3 = proto_tree_add_item(tree3, hf_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN); if (properties & PWC_CW_BAD_RSV) { expert_add_info(pinfo, item3, &ei_cw_rsv); } 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_payload_size_invalid, "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_payload_size_invalid, "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_payload_size_invalid, "Bad Length: must be 0 if SAToP packet size (%d) is > 64", (int)packet_size); } proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN); } } } } /* payload */ if (properties & PWC_PAY_SIZE_BAD) { expert_add_info_format(pinfo, item, &ei_payload_size_invalid, "SAToP payload: none found. Size of payload must be <> 0"); } else if (payload_size == 0) { expert_add_info(pinfo, item, &ei_payload_size_invalid_undecoded); } else { proto_tree* tree2; tree2 = proto_item_add_subtree(item, ett); { proto_item* item2; tvbuff_t* tvb; tvb = tvb_new_subset_length(tvb_original, PWC_SIZEOF_CW, 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"); { proto_tree* tree3; const char* s; switch(payload_properties) { case PAY_LIKE_E1: s = " (looks like E1)"; break; case PAY_LIKE_T1: s = " (looks like T1)"; break; case PAY_LIKE_E3_T3: s = " (looks like E3/T3)"; break; case PAY_LIKE_OCTET_ALIGNED_T1: s = " (looks like octet-aligned T1)"; break; case PAY_NO_IDEA: default: s = ""; break; } proto_item_append_text(item2, "%s", s); tree3 = proto_item_add_subtree(item2, ett); call_data_dissector(tvb, pinfo, tree3); item2 = proto_tree_add_int(tree3, 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; }
static void dissect_stt_checksum(tvbuff_t *tvb, packet_info *pinfo, proto_tree *stt_tree) { proto_tree *checksum_tree; proto_item *item; guint16 checksum = tvb_get_ntohs(tvb, 16); gboolean can_checksum; guint16 computed_cksum; gboolean checksum_good = FALSE, checksum_bad = FALSE; item = proto_tree_add_uint_format_value(stt_tree, hf_stt_checksum, tvb, 16, 2, checksum, "0x%04x", checksum); can_checksum = !pinfo->fragmented && tvb_bytes_exist(tvb, 0, tvb_reported_length(tvb)); if (can_checksum && pref_check_checksum) { vec_t cksum_vec[4]; guint32 phdr[2]; /* Set up the fields of the pseudo-header. */ SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data, pinfo->src.len); SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data, pinfo->dst.len); switch (pinfo->src.type) { case AT_IPv4: phdr[0] = g_htonl((IP_PROTO_TCP<<16) + tvb_reported_length(tvb)); SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 4); break; case AT_IPv6: phdr[0] = g_htonl(tvb_reported_length(tvb)); phdr[1] = g_htonl(IP_PROTO_TCP); SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 8); break; default: /* STT runs only atop IPv4 and IPv6.... */ DISSECTOR_ASSERT_NOT_REACHED(); break; } SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, tvb_reported_length(tvb)); computed_cksum = in_cksum(cksum_vec, 4); checksum_good = (computed_cksum == 0); checksum_bad = !checksum_good; if (checksum_good) { proto_item_append_text(item, " [correct]"); } else if (checksum_bad) { guint16 expected_cksum = in_cksum_shouldbe(checksum, computed_cksum); proto_item_append_text(item, " [incorrect, should be 0x%04x (maybe caused by \"TCP checksum offload\"?)]", expected_cksum); expert_add_info(pinfo, item, &ei_stt_checksum_bad); checksum = expected_cksum; } } else if (pref_check_checksum) { proto_item_append_text(item, " [unchecked, not all data available]"); } else { proto_item_append_text(item, " [validation disabled]"); } checksum_tree = proto_item_add_subtree(item, ett_stt_checksum); if (checksum_good || checksum_bad) { item = proto_tree_add_uint(checksum_tree, hf_stt_checksum_calculated, tvb, 16, 2, checksum); PROTO_ITEM_SET_GENERATED(item); } item = proto_tree_add_boolean(checksum_tree, hf_stt_checksum_good, tvb, 16, 2, checksum_good); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_stt_checksum_bad, tvb, 16, 2, checksum_bad); PROTO_ITEM_SET_GENERATED(item); }