/* Calculates a CRC32 checksum from the tvb zeroing out four bytes at the offset and checks it with the given crc32 and adds the result to the tree * Returns true if the calculated CRC32 matches the passed CRC32. * */ static gboolean ts2_add_checked_crc32(proto_tree *tree, int hf_item, tvbuff_t *tvb, guint16 offset, guint32 icrc32 ) { guint8 *zero; gint len; guint32 ocrc32; zero = (guint8 *)wmem_alloc0(wmem_packet_scope(), 4); ocrc32 = crc32_ccitt_tvb(tvb, offset); ocrc32 = crc32_ccitt_seed(zero, 4, 0xffffffff-ocrc32); len = tvb_reported_length_remaining(tvb, offset+4); if (len<0) return FALSE; ocrc32 = crc32_ccitt_tvb_offset_seed(tvb, offset+4, (guint)len, 0xffffffff-ocrc32); if(icrc32==ocrc32) { proto_tree_add_uint_format(tree, hf_item, tvb, offset, 4, tvb_get_letohl(tvb, 16), "crc32: 0x%04x [correct]", tvb_get_letohl(tvb, offset)); return TRUE; } else { proto_tree_add_uint_format(tree, hf_item, tvb, offset, 4, tvb_get_letohl(tvb,16), "crc32: 0x%04x [incorrect, should be 0x%04x]", tvb_get_letohl(tvb, offset),ocrc32); return FALSE; } }
static void dissect_tacplus_args_list( tvbuff_t *tvb, proto_tree *tree, int data_off, int len_off, int arg_cnt ) { int i; guint8 buff[257]; for(i=0;i<arg_cnt;i++){ int len=tvb_get_guint8(tvb,len_off+i); proto_tree_add_uint_format(tree, hf_tacplus_arg_length, tvb, len_off+i, 1, len, "Arg[%d] length: %d", i, len); tvb_get_nstringz0(tvb, data_off, len+1, buff); proto_tree_add_string_format(tree, hf_tacplus_arg_value, tvb, data_off, len, buff, "Arg[%d] value: %s", i, buff); data_off+=len; } }
static void dissect_status_type_identification_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { guint16 status_type, status_id; status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET); status_id = tvb_get_ntohs(parameter_tvb, STATUS_IDENT_OFFSET); proto_tree_add_item(parameter_tree, hf_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, NETWORK_BYTE_ORDER); proto_tree_add_uint_format(parameter_tree, hf_status_id, parameter_tvb, STATUS_IDENT_OFFSET, STATUS_IDENT_LENGTH, status_id, "Status identification: %u (%s)", status_id, val_to_str(status_type * 256 * 256 + status_id, status_type_id_values, "unknown")); proto_item_append_text(parameter_item, " (%s)", val_to_str(status_type * 256 * 256 + status_id, status_type_id_values, "unknown status information")); }
static void dissect_tacplus_args_list( tvbuff_t *tvb, proto_tree *tree, int data_off, int len_off, int arg_cnt ) { int i; int len; guint8 *value; for(i=0;i<arg_cnt;i++){ len=tvb_get_guint8(tvb,len_off+i); proto_tree_add_uint_format(tree, hf_tacplus_arg_length, tvb, len_off+i, 1, len, "Arg[%d] length: %d", i, len); value=tvb_get_string_enc(wmem_packet_scope(), tvb, data_off, len, ENC_ASCII|ENC_NA); proto_tree_add_string_format(tree, hf_tacplus_arg_value, tvb, data_off, len, value, "Arg[%d] value: %s", i, value); data_off+=len; } }
static void decode_iei_ns_vci(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { guint16 ns_vci; if (bi->nsip_tree) { ns_vci = tvb_get_ntohs(bi->tvb, bi->offset); proto_tree_add_uint_format(bi->nsip_tree, hf_nsip_ns_vci, bi->tvb, ie_start_offset, ie->total_length, ns_vci, "NS VCI: %#04x", ns_vci); col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "NS VCI: %#04x", ns_vci); proto_item_append_text(bi->ti, ", NS VCI: %#04x", ns_vci); } bi->offset += ie->value_length; }
static int dissect_mip6_bu(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo) { proto_tree *data_tree = NULL; proto_item *ti; int lifetime; col_set_str(pinfo->cinfo, COL_INFO, "Binding Update"); if (mip6_tree) { ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, MIP6_BU_LEN, "Binding Update"); data_tree = proto_item_add_subtree(ti, ett_mip6); proto_tree_add_item(data_tree, hf_mip6_bu_seqnr, tvb, MIP6_BU_SEQNR_OFF, MIP6_BU_SEQNR_LEN, FALSE); proto_tree_add_item(data_tree, hf_mip6_bu_a_flag, tvb, MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE); proto_tree_add_item(data_tree, hf_mip6_bu_h_flag, tvb, MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE); proto_tree_add_item(data_tree, hf_mip6_bu_l_flag, tvb, MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE); proto_tree_add_item(data_tree, hf_mip6_bu_k_flag, tvb, MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE); proto_tree_add_item(data_tree, hf_mip6_bu_m_flag, tvb, MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE); proto_tree_add_item(data_tree, hf_nemo_bu_r_flag, tvb, MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE); proto_tree_add_item(data_tree, hf_proxy_bu_p_flag, tvb, MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE); if ((tvb_get_guint8(tvb, MIP6_BU_FLAGS_OFF) & 0x0004 ) == 0x0004) proto_nemo = 1; lifetime = tvb_get_ntohs(tvb, MIP6_BU_LIFETIME_OFF); proto_tree_add_uint_format(data_tree, hf_mip6_bu_lifetime, tvb, MIP6_BU_LIFETIME_OFF, MIP6_BU_LIFETIME_LEN, lifetime, "Lifetime: %d (%ld seconds)", lifetime, (long)lifetime * 4); } return MIP6_DATA_OFF + MIP6_BU_LEN; }
static void dissect_gdb_token(void *tvbparse_data, const void *wanted_data, tvbparse_elem_t *tok) { proto_tree *tree; guint token; guint8 ack; if (!tok) /* XXX - is this check necessary? */ return; tree = (proto_tree *)tvbparse_data; token = GPOINTER_TO_UINT(wanted_data); /* XXX - check that tok->len is what we expect? */ switch (token) { case GDB_TOK_ACK: ack = tvb_get_guint8(tok->tvb, tok->offset); proto_tree_add_uint_format(tree, hf_gdb_ack, tok->tvb, tok->offset, tok->len, ack, "Acknowledgement: %s (%c)", val_to_str_const(ack, gdb_ack, "unknown"), ack); break; case GDB_TOK_START: proto_tree_add_item(tree, hf_gdb_start, tok->tvb, tok->offset, tok->len, ENC_ASCII|ENC_NA); break; case GDB_TOK_PAYLOAD: proto_tree_add_item(tree, hf_gdb_payload, tok->tvb, tok->offset, tok->len, ENC_NA); break; case GDB_TOK_END: proto_tree_add_item(tree, hf_gdb_end, tok->tvb, tok->offset, tok->len, ENC_ASCII|ENC_NA); break; case GDB_TOK_CHKSUM: /* the spec is not really explicit but it seems that the checksum is big endian */ proto_tree_add_item(tree, hf_gdb_chksum, tok->tvb, tok->offset, tok->len, ENC_BIG_ENDIAN); break; default: break; } }
static void dissect_whoent(tvbuff_t *tvb, int offset, proto_tree *tree) { proto_tree *whoent_tree = NULL; proto_item *whoent_ti = NULL; int line_offset = offset; guint8 *out_line; guint8 *out_name; nstime_t ts; int whoent_num = 0; guint32 idle_secs; /* say that out loud... */ ts.nsecs = 0; while (tvb_reported_length_remaining(tvb, line_offset) > 0 && whoent_num < MAX_NUM_WHOENTS) { whoent_ti = proto_tree_add_item(tree, hf_who_whoent, tvb, line_offset, SIZE_OF_WHOENT, ENC_NA); whoent_tree = proto_item_add_subtree(whoent_ti, ett_whoent); out_line = tvb_get_stringzpad(wmem_packet_scope(), tvb, line_offset, 8, ENC_ASCII|ENC_NA); proto_tree_add_string(whoent_tree, hf_who_tty, tvb, line_offset, 8, out_line); line_offset += 8; out_name = tvb_get_stringzpad(wmem_packet_scope(), tvb, line_offset, 8, ENC_ASCII|ENC_NA); proto_tree_add_string(whoent_tree, hf_who_uid, tvb, line_offset, 8, out_name); line_offset += 8; ts.secs = tvb_get_ntohl(tvb, line_offset); proto_tree_add_time(whoent_tree, hf_who_timeon, tvb, line_offset, 4, &ts); line_offset += 4; idle_secs = tvb_get_ntohl(tvb, line_offset); proto_tree_add_uint_format(whoent_tree, hf_who_idle, tvb, line_offset, 4, idle_secs, "Idle: %s", time_secs_to_str(wmem_packet_scope(), idle_secs)); line_offset += 4; whoent_num++; } }
static void dissect_whoent(tvbuff_t *tvb, int offset, proto_tree *tree) { proto_tree *whoent_tree = NULL; proto_item *whoent_ti = NULL; int line_offset = offset; gchar out_line[9]; gchar out_name[9]; nstime_t ts; int whoent_num = 0; guint32 idle_secs; /* say that out loud... */ ts.nsecs = 0; while (tvb_reported_length_remaining(tvb, line_offset) > 0 && whoent_num < MAX_NUM_WHOENTS) { whoent_ti = proto_tree_add_item(tree, hf_who_whoent, tvb, line_offset, SIZE_OF_WHOENT, FALSE); whoent_tree = proto_item_add_subtree(whoent_ti, ett_whoent); tvb_get_nstringz0(tvb, line_offset, sizeof(out_line), (guint8*)out_line); proto_tree_add_string(whoent_tree, hf_who_tty, tvb, line_offset, 8, out_line); line_offset += 8; tvb_get_nstringz0(tvb, line_offset, sizeof(out_name), (guint8*)out_name); proto_tree_add_string(whoent_tree, hf_who_uid, tvb, line_offset, 8, out_name); line_offset += 8; ts.secs = tvb_get_ntohl(tvb, line_offset); proto_tree_add_time(whoent_tree, hf_who_timeon, tvb, line_offset, 4, &ts); line_offset += 4; idle_secs = tvb_get_ntohl(tvb, line_offset); proto_tree_add_uint_format(whoent_tree, hf_who_idle, tvb, line_offset, 4, idle_secs, "Idle: %s", time_secs_to_str(idle_secs)); line_offset += 4; whoent_num++; } }
static gint dissect_tss_mo_state(tvbuff_t *tvb, gint offset, proto_tree *tree) { guint8 tmp; guint i = 0; for (i = 0; i < 8; i+= 2) { tmp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format(tree, hf_om2k_tsn_state, tvb, offset, 1, tmp & 0xf, "Timslot %u MO State: %s", i, val_to_str(tmp & 0xf, om2k_mo_state_vals, "unknown (%02d)")); proto_tree_add_uint_format(tree, hf_om2k_tsn_state, tvb, offset, 1, tmp >> 4, "Timslot %u MO State: %s", i+1, val_to_str(tmp >> 4, om2k_mo_state_vals, "unknown (%02d)")); offset++; } return 4; }
static void dissect_trmac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *mac_tree = NULL; proto_item *ti; int mv_length, sv_offset, sv_additional; guint8 mv_val; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TR MAC"); col_clear(pinfo->cinfo, COL_INFO); mv_val = tvb_get_guint8(tvb, 3); /* Interpret the major vector */ if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(mv_val, major_vector_vs, "Unknown Major Vector: %u")); if (tree) { mv_length = tvb_get_ntohs(tvb, 0); ti = proto_tree_add_item(tree, proto_trmac, tvb, 0, mv_length, FALSE); mac_tree = proto_item_add_subtree(ti, ett_tr_mac); proto_tree_add_uint(mac_tree, hf_trmac_mv, tvb, 3, 1, mv_val); proto_tree_add_uint_format(mac_tree, hf_trmac_length, tvb, 0, 2, mv_length, "Total Length: %d bytes", mv_length); proto_tree_add_uint(mac_tree, hf_trmac_srcclass, tvb, 2, 1, tvb_get_guint8(tvb, 2) & 0x0f); proto_tree_add_uint(mac_tree, hf_trmac_dstclass, tvb, 2, 1, tvb_get_guint8(tvb, 2) >> 4 ); /* interpret the subvectors */ sv_offset = 4; while (sv_offset < mv_length) { sv_additional = sv_text(tvb, sv_offset, mac_tree); /* if this is a bad packet, we could get a 0-length added here, * looping forever */ if (sv_additional > 0) sv_offset += sv_additional; else break; } } }
/* add the list of fragments for this sdu to 'tree' */ static void tree_add_fragment_list_incomplete(struct rlc_sdu *sdu, tvbuff_t *tvb, proto_tree *tree) { proto_item *ti; proto_tree *frag_tree; guint16 offset; struct rlc_frag *sdufrag; ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, 0, FALSE); frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments); proto_item_append_text(ti, " (%u bytes, %u fragments): ", sdu->len, sdu->fragcnt); sdufrag = sdu->frags; offset = 0; while (sdufrag) { proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, 0, 0, sdufrag->frame_num, "Frame: %u, payload %u-%u (%u bytes) (Seq: %u)", sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq); offset += sdufrag->len; sdufrag = sdufrag->next; } }
static void dissect_response_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, guint8 flags) { proto_tree* subtree; guint encoding = (flags & NETWORK_BYTE_ORDER) ? ENC_BIG_ENDIAN : ENC_LITTLE_ENDIAN; guint32 r_uptime; subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_response, NULL, "Response-PDU"); NORLEL(flags, r_uptime, tvb, offset); proto_tree_add_uint_format(subtree, hf_resp_uptime, tvb, offset, 4, r_uptime, "sysUptime: %s", time_msecs_to_str(wmem_packet_scope(), r_uptime)); proto_tree_add_item(subtree, hf_resp_error, tvb, offset + 4, 2, encoding); proto_tree_add_item(subtree, hf_resp_index, tvb, offset + 6, 2, encoding); offset += 8; len += PDU_HDR_LEN; while(len > offset) { offset += dissect_varbind(tvb, subtree, offset, len, flags); } }
static void decode_iei_cause(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { guint8 cause; if (bi->nsip_tree) { cause = tvb_get_guint8(bi->tvb, bi->offset); proto_tree_add_uint_format(bi->nsip_tree, hf_nsip_cause, bi->tvb, ie_start_offset, ie->total_length, cause, "Cause: %s (%#02x)", val_to_str_const(cause, tab_nsip_cause_values, "Unknown"), cause); col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Cause: %s", val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)")); proto_item_append_text(bi->ti, ", Cause: %s", val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)")); } bi->offset += ie->value_length; }
/* * Dissect 802.11 with a variable-length link-layer header and a pseudo- * header containing radio information. */ static void dissect_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) { proto_item *ti = NULL; proto_tree *radio_tree = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "Radio"); col_clear(pinfo->cinfo, COL_INFO); /* Add the radio information to the column information */ col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u", pinfo->pseudo_header->ieee_802_11.data_rate / 2, pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0); /* XX - this is a percentage, not a dBm or normalized or raw RSSI */ col_add_fstr(pinfo->cinfo, COL_RSSI, "%u", pinfo->pseudo_header->ieee_802_11.signal_level); if (tree) { ti = proto_tree_add_item(tree, proto_radio, tvb, 0, 0, ENC_NA); radio_tree = proto_item_add_subtree (ti, ett_radio); proto_tree_add_uint64_format(radio_tree, hf_data_rate, tvb, 0, 0, (guint64)pinfo->pseudo_header->ieee_802_11.data_rate * 500000, "Data Rate: %u.%u Mb/s", pinfo->pseudo_header->ieee_802_11.data_rate / 2, pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0); proto_tree_add_uint(radio_tree, hf_channel, tvb, 0, 0, pinfo->pseudo_header->ieee_802_11.channel); proto_tree_add_uint_format(radio_tree, hf_signal_strength, tvb, 0, 0, pinfo->pseudo_header->ieee_802_11.signal_level, "Signal Strength: %u%%", pinfo->pseudo_header->ieee_802_11.signal_level); } /* dissect the 802.11 header next */ pinfo->current_proto = "IEEE 802.11"; call_dissector(ieee80211_handle, tvb, pinfo, tree); }
static void dissect_netrom_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_netrom_type_param, gint ett_netrom_type_param, const netrom_tf_items *type_items ) { proto_tree *tc; proto_tree *type_tree; char *info_buffer; guint8 type; guint8 op_code; type = tvb_get_guint8( tvb, offset ); op_code = type &0x0f; info_buffer = ep_strdup_printf( "%s%s%s%s (0x%02x)", val_to_str_const( op_code, op_code_vals_text, "Unknown" ), ( type & NETROM_MORE_FLAG ) ? ", More" : "", ( type & NETROM_NAK_FLAG ) ? ", NAK" : "", ( type & NETROM_CHOKE_FLAG ) ? ", Choke" : "", type ); col_add_str( pinfo->cinfo, COL_INFO, info_buffer ); if ( tree ) { tc = proto_tree_add_uint_format( tree, hf_netrom_type_param, tvb, offset, 1, type, "Type field: %s", info_buffer ); type_tree = proto_item_add_subtree( tc, ett_netrom_type_param ); proto_tree_add_item( type_tree, *type_items->hf_tf_op, tvb, offset, 1, ENC_BIG_ENDIAN ); proto_tree_add_item( type_tree, *type_items->hf_tf_choke, tvb, offset, 1, ENC_BIG_ENDIAN ); proto_tree_add_item( type_tree, *type_items->hf_tf_nak, tvb, offset, 1, ENC_BIG_ENDIAN ); proto_tree_add_item( type_tree, *type_items->hf_tf_more, tvb, offset, 1, ENC_BIG_ENDIAN ); } }
static guint parse_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int hf_item, const char* msg, gboolean have_position) { proto_item *fitem; proto_tree *ftree; guint32 arr_len, i, val, j; arr_len = tvb_get_ntohl(tvb, offset); fitem = proto_tree_add_uint_format(tree, hf_item, tvb, offset, 4, arr_len, "%s (count: %u)", msg, arr_len); offset += 4; ftree = proto_item_add_subtree(fitem, ett_rpcordma_chunk); for (i = 0; i < arr_len; ++i) { val = tvb_get_ntohl(tvb, offset); offset += 4; for (j = 0; j < val; ++j) { if (have_position) { proto_tree_add_item(ftree, hf_rpcordma_position, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } /* xdr_rdma_segment */ proto_tree_add_item(ftree, hf_rpcordma_rdma_handle, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(ftree, hf_rpcordma_rdma_length, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(ftree, hf_rpcordma_rdma_offset, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; } } return offset; }
static void rs09(tvbuff_t *tvb, proto_tree *tree) { static const int *byte1[] = { &hf_ipmi_chs_09_rs_param_version, NULL }; proto_item *ti; proto_tree *s_tree; tvbuff_t *sub; guint8 pno; const char *desc; pno = tvb_get_guint8(tvb, 1) & 0x7f; if (pno < array_length(boot_options)) { desc = boot_options[pno].name; } else if (pno >= 96 && pno <= 127) { desc = "OEM"; } else { desc = "Reserved"; } proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL, ett_ipmi_chs_09_rs_byte1, byte1, TRUE, 0); ti = proto_tree_add_text(tree, tvb, 1, 1, "Boot option parameter selector: %s (0x%02x)", desc, pno); s_tree = proto_item_add_subtree(ti, ett_ipmi_chs_09_rs_byte2); proto_tree_add_item(s_tree, hf_ipmi_chs_09_rs_valid, tvb, 1, 1, TRUE); proto_tree_add_uint_format(s_tree, hf_ipmi_chs_09_rs_param_select, tvb, 1, 1, pno, "%sBoot option parameter selector: %s (0x%02x)", ipmi_dcd8(pno, 0x7f), desc, pno); if (pno < array_length(boot_options)) { sub = tvb_new_subset(tvb, 2, tvb_length(tvb) - 2, tvb_length(tvb) - 2); boot_options[pno].intrp(sub, tree); } else { proto_tree_add_item(tree, hf_ipmi_chs_09_rs_param_data, tvb, 2, tvb_length(tvb) - 2, TRUE); } }
/* Set System Boot Options */ static void rq08(tvbuff_t *tvb, proto_tree *tree) { proto_item *ti; proto_tree *s_tree; tvbuff_t *sub; guint8 pno; const char *desc; pno = tvb_get_guint8(tvb, 0) & 0x7f; if (pno < array_length(boot_options)) { desc = boot_options[pno].name; } else if (pno >= 96 && pno <= 127) { desc = "OEM"; } else { desc = "Reserved"; } ti = proto_tree_add_text(tree, tvb, 0, 1, "Boot option parameter selector: %s (0x%02x)", desc, pno); s_tree = proto_item_add_subtree(ti, ett_ipmi_chs_08_byte1); proto_tree_add_item(s_tree, hf_ipmi_chs_08_valid, tvb, 0, 1, TRUE); proto_tree_add_uint_format(s_tree, hf_ipmi_chs_08_selector, tvb, 0, 1, pno, "%sBoot option parameter selector: %s (0x%02x)", ipmi_dcd8(pno, 0x7f), desc, pno); /* Data is optional; no data means 'just set validity' */ if (tvb_length(tvb) > 1) { if (pno < array_length(boot_options)) { sub = tvb_new_subset(tvb, 1, tvb_length(tvb) - 1, tvb_length(tvb) - 1); boot_options[pno].intrp(sub, tree); } else { proto_tree_add_none_format(tree, hf_ipmi_chs_08_data, tvb, 1, tvb_length(tvb) - 1, "Parameter data: %s", desc); } } }
static void dissect_response_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags) { proto_item* item; proto_tree* subtree; gboolean little_endian = !(flags & NETWORK_BYTE_ORDER); guint32 r_uptime; item = proto_tree_add_text(tree, tvb, offset, len, "Response-PDU"); subtree = proto_item_add_subtree(item, ett_response); r_uptime = little_endian ? \ tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset); proto_tree_add_uint_format(subtree, hf_resp_uptime, tvb, offset, 4, r_uptime, "sysUptime: %s", time_msecs_to_str(r_uptime)); proto_tree_add_item(subtree, hf_resp_error, tvb, offset + 4, 2, little_endian); proto_tree_add_item(subtree, hf_resp_index, tvb, offset + 6, 2, little_endian); offset += 8; while(len > offset) { offset += dissect_varbind(tvb, subtree, offset, len, flags); } }
void netbios_add_name(const char* label, tvbuff_t *tvb, int offset, proto_tree *tree) {/* add a name field display tree. Display the name and station type in sub-tree */ proto_tree *field_tree; proto_item *tf; char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1]; int name_type; const char *name_type_str; /* decode the name field */ name_type = get_netbios_name( tvb, offset, name_str, (NETBIOS_NAME_LEN - 1)*4 + 1); name_type_str = netbios_name_type_descr(name_type); tf = proto_tree_add_text( tree, tvb, offset, NETBIOS_NAME_LEN, "%s: %s<%02x> (%s)", label, name_str, name_type, name_type_str); field_tree = proto_item_add_subtree( tf, ett_netb_name); proto_tree_add_string_format( field_tree, hf_netb_nb_name, tvb, offset, 15, name_str, "%s", name_str); proto_tree_add_uint_format( field_tree, hf_netb_nb_name_type, tvb, offset + 15, 1, name_type, "0x%02x (%s)", name_type, name_type_str); }
static void dissect_nsip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 pdu_type; build_info_t bi = { NULL, 0, NULL, NULL, NULL, NULL }; proto_tree *nsip_tree; bi.tvb = tvb; bi.pinfo = pinfo; bi.parent_tree = tree; pinfo->current_proto = "GPRS-NS"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-NS"); col_clear(pinfo->cinfo, COL_INFO); pdu_type = tvb_get_guint8(tvb, 0); bi.offset++; if (tree) { bi.ti = proto_tree_add_item(tree, proto_nsip, tvb, 0, -1, ENC_NA); nsip_tree = proto_item_add_subtree(bi.ti, ett_nsip); proto_tree_add_uint_format(nsip_tree, hf_nsip_pdu_type, tvb, 0, 1, pdu_type, "PDU type: %s (%#02x)", val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown"), pdu_type); proto_item_append_text(bi.ti, ", PDU type: %s", val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown")); bi.nsip_tree = nsip_tree; } col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown PDU type")); decode_pdu(pdu_type, &bi); }
static int display_LMNT_token(tvbuff_t *tvb, int offset, proto_tree *tree) { guint16 Token; Token = tvb_get_letohs(tvb, offset); if (Token == 0xffff) { proto_tree_add_uint_format_value(tree, hf_lmnt_token, tvb, offset, 2, Token, "0x%04x (Windows NT Networking)", Token); } else { /* * XXX - what is it if it's not 0xffff? */ proto_tree_add_uint_format(tree, hf_lm_token, tvb, offset, 2, Token, "LMNT Token: 0x%04x (Unknown)", Token); } offset += 2; return offset; }
static void dissect_time(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *time_tree; proto_item *ti; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TIME"); col_add_fstr(pinfo->cinfo, COL_INFO, "TIME %s", pinfo->srcport == pinfo->match_uint ? "Response":"Request"); ti = proto_tree_add_item(tree, proto_time, tvb, 0, -1, ENC_NA); time_tree = proto_item_add_subtree(ti, ett_time); proto_tree_add_text(time_tree, tvb, 0, 0, pinfo->srcport==pinfo->match_uint ? "Type: Response":"Type: Request"); if (pinfo->srcport == pinfo->match_uint) { /* seconds since 1900-01-01 00:00:00 GMT, *not* 1970 */ guint32 delta_seconds = tvb_get_ntohl(tvb, 0); proto_tree_add_uint_format(time_tree, hf_time_time, tvb, 0, 4, delta_seconds, "%s", abs_time_secs_to_ep_str(delta_seconds-2208988800U, time_display_type, TRUE)); } }
static void dissect_DataStatus(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 u8DataStatus) { proto_item *sub_item; proto_tree *sub_tree; sub_item = proto_tree_add_uint_format(tree, hf_pn_rt_data_status, tvb, offset, 1, u8DataStatus, "DataStatus: 0x%02x (Frame: %s and %s, Provider: %s and %s)", u8DataStatus, (u8DataStatus & 0x04) ? "Valid" : "Invalid", (u8DataStatus & 0x01) ? "Primary" : "Backup", (u8DataStatus & 0x20) ? "Ok" : "Problem", (u8DataStatus & 0x10) ? "Run" : "Stop"); sub_tree = proto_item_add_subtree(sub_item, ett_pn_rt_data_status); proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_ignore, tvb, offset, 1, u8DataStatus); proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_subframe_sender_mode, tvb, offset, 1, u8DataStatus); proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_ok, tvb, offset, 1, u8DataStatus); proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_operate, tvb, offset, 1, u8DataStatus); proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_res3, tvb, offset, 1, u8DataStatus); proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_valid, tvb, offset, 1, u8DataStatus); proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_res1, tvb, offset, 1, u8DataStatus); proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_primary, tvb, offset, 1, u8DataStatus); }
static void dissect_cimd_dcs(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset) { /* Set up structures needed to add the param subtree and manage it */ proto_item *param_item; proto_tree *param_tree; gint offset; guint dcs; guint dcs_cg; /* coding group */ guint dcs_cf; /* compressed flag */ guint dcs_mcm; /* message class meaning flag */ guint dcs_chs; /* character set */ guint dcs_mc; /* message class */ guint dcs_is; /* indication sense */ guint dcs_it; /* indication type */ gchar* bigbuf = (gchar*)ep_alloc(1024); param_item = proto_tree_add_text(tree, tvb, startOffset + 1, endOffset - (startOffset + 1), "%s", cimd_vals_PC[pindex].strptr ); param_tree = proto_item_add_subtree(param_item, (*vals_hdr_PC[pindex].ett_p)); proto_tree_add_string(param_tree, hf_cimd_pcode_indicator, tvb, startOffset + 1, CIMD_PC_LENGTH, tvb_format_text(tvb, startOffset + 1, CIMD_PC_LENGTH) ); offset = startOffset + 1 + CIMD_PC_LENGTH + 1; dcs = decimal_int_value(tvb, offset, endOffset - offset); proto_tree_add_uint(param_tree, (*vals_hdr_PC[pindex].hf_p), tvb, offset, endOffset - offset, dcs); dcs_cg = (dcs & 0xF0) >> 4; other_decode_bitfield_value(bigbuf, dcs, (dcs_cg <= 0x07 ? 0xC0 : 0xF0), 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_coding_group_indicator, tvb, offset, 1, dcs_cg, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_coding_group_indicator)->name, val_to_str(dcs_cg, cimd_dcs_coding_groups, "Unknown (%d)"), dcs_cg ); if (dcs_cg <= 0x07) { dcs_cf = (dcs & 0x20) >> 5; other_decode_bitfield_value(bigbuf, dcs, 0x20, 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_compressed_indicator, tvb, offset, 1, dcs_cf, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_compressed_indicator)->name, val_to_str(dcs_cf, cimd_dcs_compressed, "Unknown (%d)"), dcs_cf ); dcs_mcm = (dcs & 0x10) >> 4; other_decode_bitfield_value(bigbuf, dcs, 0x10, 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_meaning_indicator, tvb, offset, 1, dcs_mcm, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_meaning_indicator)->name, val_to_str(dcs_mcm, cimd_dcs_message_class_meaning, "Unknown (%d)"), dcs_mcm ); dcs_chs = (dcs & 0x0C) >> 2; other_decode_bitfield_value(bigbuf, dcs, 0x0C, 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_character_set_indicator, tvb, offset, 1, dcs_chs, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_character_set_indicator)->name, val_to_str(dcs_chs, cimd_dcs_character_set, "Unknown (%d)"), dcs_chs ); if (dcs_mcm) { dcs_mc = (dcs & 0x03); other_decode_bitfield_value(bigbuf, dcs, 0x03, 8); proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_indicator, tvb, offset, 1, dcs_mc, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_indicator)->name, val_to_str(dcs_mc, cimd_dcs_message_class, "Unknown (%d)"), dcs_mc ); } }
static void dissect_msdp_notification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, guint16 tlv_len) { guint8 error, error_sub; const value_string *vals; proto_tree_add_item(tree, hf_msdp_not_o, tvb, *offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_msdp_not_error, tvb, *offset, 1, ENC_BIG_ENDIAN); error = tvb_get_guint8(tvb, *offset); error &= 0x7F; /* Error is 7-bit field. O-bit is bit 8 */ *offset += 1; /* Depending on the Error Code, we collect the correct * value_strings for the Error subcode */ switch (error) { case MESSAGE_HEADER_ERROR: vals = hdr_error_vals; break; case SA_REQUEST_ERROR: vals = sa_req_error_vals; break; case SA_MESSAGE_SA_RESPONSE_ERROR: vals = sa_msg_error_vals; break; case FSM_ERROR: vals = fsm_error_vals; break; case HOLD_TIMER_EXPIRED: case NOTIFICATION: case CEASE: vals = sa_unspec_error_vals; break; default: vals = sa_unspec_error_vals; break; } error_sub = tvb_get_guint8(tvb, *offset); proto_tree_add_uint_format(tree, hf_msdp_not_error_sub, tvb, *offset, 1, error_sub, "Error subcode: %s (%u)", val_to_str(error_sub, vals, "<Unknown Error subcode>"), error_sub); *offset += 1; /* Do switch again, this time to dissect the data portion * correctly. Ugly. */ switch (error) { tvbuff_t *next_tvb; case SA_REQUEST_ERROR: add_notification_data_ipv4addr(tvb, tree, offset, "Group address"); break; case SA_MESSAGE_SA_RESPONSE_ERROR: if (error_sub == 0) { break; } else if (error_sub == 1) { proto_tree_add_item(tree, hf_msdp_not_entry_count, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; break; } else if (error_sub == 2) { add_notification_data_ipv4addr(tvb, tree, offset, "RP address"); break; } else if (error_sub == 3 || error_sub == 8) { add_notification_data_ipv4addr(tvb, tree, offset, "Group address"); break; } else if (error_sub == 4) { add_notification_data_ipv4addr(tvb, tree, offset, "Source address"); break; } else if (error_sub == 5) { proto_tree_add_item(tree, hf_msdp_not_sprefix_len, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; break; } else if (error_sub == 6) { /* No break, causes fall through to next label */ } else if (error_sub == 7) { proto_tree_add_text(tree, tvb, *offset, tlv_len - 5, "Packet with unknown encapsulation: %u bytes", tlv_len - 5); *offset += tlv_len - 5; break; } else { proto_tree_add_text(tree, tvb, *offset, tlv_len - 5, "<Unknown data>: %u bytes", tlv_len -5); *offset += tlv_len - 5; break; } /* Fall through */ case MESSAGE_HEADER_ERROR: case NOTIFICATION: /* Data contains the message that had an error. Even a * broken Notification message causes a Notification * message with Error Code set to Notification to be * sent back. */ next_tvb = tvb_new_subset_remaining(tvb, *offset); dissect_msdp(next_tvb, pinfo, tree); break; case FSM_ERROR: case HOLD_TIMER_EXPIRED: case CEASE: /* Do nothing. These contain no data */ break; default: if (tlv_len - 5 > 0) proto_tree_add_text(tree, tvb, *offset, tlv_len - 5, "<Unknown data>: %u bytes", tlv_len -5); *offset += tlv_len - 5; break; } return; }
/* * dissect_pgm - The dissector for Pragmatic General Multicast */ static void dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 pgmhdr_sport; guint16 pgmhdr_dport; guint8 pgmhdr_type; guint8 pgmhdr_opts; guint16 pgmhdr_cksum; guint16 pgmhdr_tsdulen; guint32 sqn; guint16 afi; guint plen = 0; proto_item *ti; const char *pktname; const char *pollstname; char *gsi; gboolean isdata = FALSE; guint pgmlen, reportedlen; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGM"); if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); if (tvb_reported_length_remaining(tvb, 0) < 18) { col_set_str(pinfo->cinfo, COL_INFO, "Packet too small"); return; } } pinfo->srcport = pgmhdr_sport = tvb_get_ntohs(tvb, 0); pinfo->destport = pgmhdr_dport = tvb_get_ntohs(tvb, 2); pgmhdr_type = tvb_get_guint8(tvb, 4); pktname = val_to_str(pgmhdr_type, type_vals, "Unknown (0x%02x)"); pgmhdr_opts = tvb_get_guint8(tvb, 5); pgmhdr_cksum = tvb_get_ntohs(tvb, 6); gsi = tvb_bytes_to_str(tvb, 8, 6); pgmhdr_tsdulen = tvb_get_ntohs(tvb, 14); sqn = tvb_get_ntohl(tvb, 16); switch(pgmhdr_type) { case PGM_SPM_PCKT: case PGM_NAK_PCKT: case PGM_NNAK_PCKT: case PGM_NCF_PCKT: case PGM_POLR_PCKT: case PGM_ACK_PCKT: if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s", pktname, sqn, gsi); } break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, sqn, gsi, pgmhdr_tsdulen); } isdata = TRUE; break; case PGM_POLL_PCKT: { guint16 poll_stype = tvb_get_ntohs(tvb, 22); pollstname = val_to_str(poll_stype, poll_subtype_vals, "Unknown (0x%02x)"); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s subtype %s", pktname, sqn, gsi, pollstname); } } break; default: return; } { proto_tree *pgm_tree = NULL; proto_tree *opt_tree = NULL; proto_tree *type_tree = NULL; proto_item *tf, *hidden_item; ptvcursor_t* cursor; ti = proto_tree_add_protocol_format(tree, proto_pgm, tvb, 0, -1, "Pragmatic General Multicast: Type %s" " Src Port %u, Dst Port %u, GSI %s", pktname, pgmhdr_sport, pgmhdr_dport, gsi); pgm_tree = proto_item_add_subtree(ti, ett_pgm); cursor = ptvcursor_new(pgm_tree, tvb, 0); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 0, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 2, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); ptvcursor_add(cursor, hf_pgm_main_sport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_dport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_type, 1, ENC_BIG_ENDIAN); tf = proto_tree_add_uint_format(pgm_tree, hf_pgm_main_opts, tvb, ptvcursor_current_offset(cursor), 1, pgmhdr_opts, "Options: %s (0x%x)", optsstr(pgmhdr_opts), pgmhdr_opts); opt_tree = proto_item_add_subtree(tf, ett_pgm_optbits); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_opt, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_netsig, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_varlen, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_opts_parity, 1, ENC_BIG_ENDIAN); ptvcursor_set_tree(cursor, pgm_tree); /* Checksum may be 0 (not available), but not for DATA packets */ if ((pgmhdr_type != PGM_RDATA_PCKT) && (pgmhdr_type != PGM_ODATA_PCKT) && (pgmhdr_cksum == 0)) { proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: not available"); } else { reportedlen = tvb_reported_length(tvb); pgmlen = tvb_length(tvb); if (pgm_check_checksum && pgmlen >= reportedlen) { vec_t cksum_vec[1]; guint16 computed_cksum; cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pgmlen); cksum_vec[0].len = pgmlen; computed_cksum = in_cksum(&cksum_vec[0], 1); if (computed_cksum == 0) { proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 0x%04x [correct]", pgmhdr_cksum); } else { hidden_item = proto_tree_add_boolean(pgm_tree, hf_pgm_main_cksum_bad, tvb, ptvcursor_current_offset(cursor), 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 0x%04x [incorrect, should be 0x%04x]", pgmhdr_cksum, in_cksum_shouldbe(pgmhdr_cksum, computed_cksum)); } } else { ptvcursor_add_no_advance(cursor, hf_pgm_main_cksum, 2, ENC_BIG_ENDIAN); } } ptvcursor_advance(cursor, 2); ptvcursor_add(cursor, hf_pgm_main_gsi, 6, ENC_NA); ptvcursor_add(cursor, hf_pgm_main_tsdulen, 2, ENC_BIG_ENDIAN); tf = proto_tree_add_text(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, "%s Packet", pktname); switch(pgmhdr_type) { case PGM_SPM_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_spm); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_lead, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_spm_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_spm_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_spm_path6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); return; } break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_data); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); break; case PGM_NAK_PCKT: case PGM_NNAK_PCKT: case PGM_NCF_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_nak); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_nak_sqn, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_nak_srcafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_srcres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_src, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_src6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_nak_grpafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_grpres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_grp, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_grp6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); return; } break; case PGM_POLL_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_poll); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_poll_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_subtype, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_poll_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_poll_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_poll_path6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } ptvcursor_add(cursor, hf_pgm_poll_backoff_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_rand_str, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_matching_bmask, 4, ENC_BIG_ENDIAN); break; case PGM_POLR_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_polr); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_polr_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_res, 2, ENC_BIG_ENDIAN); break; case PGM_ACK_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_ack); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_ack_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_ack_bitmap, 4, ENC_BIG_ENDIAN); break; } if (pgmhdr_opts & PGM_OPT) dissect_pgmopts(cursor, pktname); if (isdata) decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport); } }
static void dissect_pgmopts(ptvcursor_t* cursor, const char *pktname) { proto_item *tf; proto_tree *opts_tree = NULL; proto_tree *opt_tree = NULL; tvbuff_t *tvb = ptvcursor_tvbuff(cursor); gboolean theend = FALSE; guint16 opts_total_len; guint8 genopts_type; guint8 genopts_len; guint8 opts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); if (opts_type != PGM_OPT_LENGTH) { proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), 1, "%s Options - initial option is %s, should be %s", pktname, val_to_str(opts_type, opt_vals, "Unknown (0x%02x)"), val_to_str(PGM_OPT_LENGTH, opt_vals, "Unknown (0x%02x)")); return; } opts_total_len = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)+2); if (opts_total_len < 4) { proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor)+2, 2, "%s Options (Total Length %u - invalid, must be >= 4)", pktname, opts_total_len); return; } tf = proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), opts_total_len, "%s Options (Total Length %d)", pktname, opts_total_len); opts_tree = proto_item_add_subtree(tf, ett_pgm_opts); ptvcursor_set_tree(cursor, opts_tree); ptvcursor_add(cursor, hf_pgm_opt_type, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_tlen, 2, ENC_BIG_ENDIAN); for (opts_total_len -= 4; !theend && opts_total_len != 0;){ if (opts_total_len < 4) { proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), opts_total_len, "Remaining total options length doesn't have enough for an options header"); break; } genopts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); genopts_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)+1); if (genopts_type & PGM_OPT_END) { genopts_type &= ~PGM_OPT_END; theend = TRUE; } if (genopts_len < 4) { proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len, "Option: %s, Length: %u (invalid, must be >= 4)", val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"), genopts_len); break; } if (opts_total_len < genopts_len) { proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len, "Option: %s, Length: %u (> remaining total options length)", val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"), genopts_len); break; } tf = proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len, "Option: %s, Length: %u", val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"), genopts_len); switch(genopts_type) { case PGM_OPT_JOIN:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_join); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_JOIN_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_JOIN_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_join_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_join_minjoin, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_PARITY_PRM:{ guint8 optdata_po; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_parityprm); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PARITY_PRM_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_PARITY_PRM_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); optdata_po = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); proto_tree_add_uint_format(opt_tree, hf_pgm_opt_parity_prm_po, tvb, ptvcursor_current_offset(cursor), 1, optdata_po, "Parity Parameters: %s (0x%x)", paritystr(optdata_po), optdata_po); ptvcursor_advance(cursor, 1); ptvcursor_add(cursor, hf_pgm_opt_parity_prm_prmtgsz, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_PARITY_GRP:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_paritygrp); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PARITY_GRP_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_PARITY_GRP_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_parity_grp_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_parity_grp_prmgrp, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_NAK_LIST:{ guint8 optdata_len; guint32 naklist[PGM_MAX_NAK_LIST_SZ+1]; unsigned char *nakbuf; gboolean firsttime; int i, j, naks, soffset; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_naklist); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); optdata_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_res, 1, ENC_BIG_ENDIAN); optdata_len -= PGM_OPT_NAK_LIST_SIZE; tvb_memcpy(tvb, (guint8 *)naklist, ptvcursor_current_offset(cursor), optdata_len); firsttime = TRUE; soffset = 0; naks = (optdata_len/sizeof(guint32)); nakbuf = ep_alloc(8192); j = 0; /* * Print out 8 per line */ for (i=0; i < naks; i++) { soffset += MIN(8192-soffset, g_snprintf(nakbuf+soffset, 8192-soffset, "0x%lx ", (unsigned long)g_ntohl(naklist[i]))); if ((++j % 8) == 0) { if (firsttime) { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List(%d): %s", naks, nakbuf); soffset = 0; firsttime = FALSE; } else { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List: %s", nakbuf); soffset = 0; } ptvcursor_advance(cursor, j*4); j = 0; } } if (j) { if (firsttime) { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List(%d): %s", naks, nakbuf); } else { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List: %s", nakbuf); } ptvcursor_advance(cursor, j*4); } break; } case PGM_OPT_PGMCC_DATA:{ guint16 optdata_afi; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PGMCC_DATA_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_PGMCC_DATA_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccdata_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccdata_tsp, 4, ENC_BIG_ENDIAN); optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_opt_ccdata_afi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccdata_res2, 2, ENC_BIG_ENDIAN); switch (optdata_afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker6, 16, ENC_NA); break; default: proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } break; } case PGM_OPT_PGMCC_FEEDBACK:{ guint16 optdata_afi; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PGMCC_FEEDBACK_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_PGMCC_FEEDBACK_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_tsp, 4, ENC_BIG_ENDIAN); optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_afi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_lossrate, 2, ENC_BIG_ENDIAN); switch (optdata_afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker6, 16, ENC_NA); break; default: proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } break; } case PGM_OPT_NAK_BO_IVL:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_ivl); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_NAK_BO_IVL_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_NAK_BO_IVL_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_NAK_BO_RNG:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_rng); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_NAK_BO_RNG_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_NAK_BO_RNG_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_min_bo_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_max_bo_ivl, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_REDIRECT:{ guint16 optdata_afi; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_redirect); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_REDIRECT_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_REDIRECT_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_redirect_res, 1, ENC_BIG_ENDIAN); optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_opt_redirect_afi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_redirect_res2, 2, ENC_BIG_ENDIAN); switch (optdata_afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr6, 16, ENC_NA); break; default: proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } break; } case PGM_OPT_FRAGMENT:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_fragment); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_FRAGMENT_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_FRAGMENT_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_first_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_offset, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_total_length, 4, ENC_BIG_ENDIAN); break; } default:{ ptvcursor_advance(cursor, genopts_len); break; } } opts_total_len -= genopts_len; } return; }
static void dissect_wlancap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *wlan_tree = NULL; proto_item *ti; tvbuff_t *next_tvb; int offset; guint32 version; guint32 length; guint32 channel; guint32 datarate; guint32 ssi_type; guint32 antnoise; col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN"); col_clear(pinfo->cinfo, COL_INFO); offset = 0; version = tvb_get_ntohl(tvb, offset) - WLANCAP_MAGIC_COOKIE_BASE; length = tvb_get_ntohl(tvb, offset+4); col_add_fstr(pinfo->cinfo, COL_INFO, "AVS WLAN Capture v%x, Length %d",version, length); if (version > 2) { goto skip; } /* Dissect the AVS header */ if (tree) { ti = proto_tree_add_item(tree, proto_wlancap, tvb, 0, length, ENC_NA); wlan_tree = proto_item_add_subtree(ti, ett_radio); proto_tree_add_item(wlan_tree, hf_wlan_magic, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(wlan_tree, hf_wlan_version, tvb, offset, 4, ENC_BIG_ENDIAN); } offset+=4; if (tree) proto_tree_add_item(wlan_tree, hf_wlan_length, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; if (tree) proto_tree_add_item(wlan_tree, hf_mactime, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; if (tree) proto_tree_add_item(wlan_tree, hf_hosttime, tvb, offset, 8, ENC_BIG_ENDIAN); offset+=8; if (tree) proto_tree_add_item(wlan_tree, hf_wlan_phytype, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; /* XXX cook channel (fh uses different numbers) */ channel = tvb_get_ntohl(tvb, offset); if (channel < 256) { col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", channel); if (tree) proto_tree_add_uint(wlan_tree, hf_channel, tvb, offset, 4, channel); } else if (channel < 10000) { col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u MHz", channel); if (tree) proto_tree_add_uint_format(wlan_tree, hf_channel_frequency, tvb, offset, 4, channel, "Frequency: %u MHz", channel); } else { col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u KHz", channel); if (tree) proto_tree_add_uint_format(wlan_tree, hf_channel_frequency, tvb, offset, 4, channel, "Frequency: %u KHz", channel); } offset+=4; datarate = tvb_get_ntohl(tvb, offset); if (datarate < 100000) { /* In units of 100 Kb/s; convert to b/s */ datarate *= 100000; } col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u", datarate / 1000000, ((datarate % 1000000) > 500000) ? 5 : 0); if (tree) { proto_tree_add_uint64_format(wlan_tree, hf_data_rate, tvb, offset, 4, datarate, "Data Rate: %u.%u Mb/s", datarate/1000000, ((datarate % 1000000) > 500000) ? 5 : 0); } offset+=4; if (tree) proto_tree_add_item(wlan_tree, hf_wlan_antenna, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; if (tree) proto_tree_add_item(wlan_tree, hf_wlan_priority, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; ssi_type = tvb_get_ntohl(tvb, offset); if (tree) proto_tree_add_uint(wlan_tree, hf_wlan_ssi_type, tvb, offset, 4, ssi_type); offset+=4; switch (ssi_type) { case SSI_NONE: default: /* either there is no SSI information, or we don't know what type it is */ break; case SSI_NORM_RSSI: /* Normalized RSSI */ col_add_fstr(pinfo->cinfo, COL_RSSI, "%u (norm)", tvb_get_ntohl(tvb, offset)); if (tree) proto_tree_add_item(wlan_tree, hf_normrssi_antsignal, tvb, offset, 4, ENC_BIG_ENDIAN); break; case SSI_DBM: /* dBm */ col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", tvb_get_ntohl(tvb, offset)); if (tree) proto_tree_add_item(wlan_tree, hf_dbm_antsignal, tvb, offset, 4, ENC_BIG_ENDIAN); break; case SSI_RAW_RSSI: /* Raw RSSI */ col_add_fstr(pinfo->cinfo, COL_RSSI, "%u (raw)", tvb_get_ntohl(tvb, offset)); if (tree) proto_tree_add_item(wlan_tree, hf_rawrssi_antsignal, tvb, offset, 4, ENC_BIG_ENDIAN); break; } offset+=4; antnoise = tvb_get_ntohl(tvb, offset); /* 0xffffffff means "hardware does not provide noise data" */ if (antnoise != 0xffffffff) { switch (ssi_type) { case SSI_NONE: default: /* either there is no SSI information, or we don't know what type it is */ break; case SSI_NORM_RSSI: /* Normalized RSSI */ if (tree) proto_tree_add_uint(wlan_tree, hf_normrssi_antnoise, tvb, offset, 4, antnoise); break; case SSI_DBM: /* dBm */ if (tree) proto_tree_add_int(wlan_tree, hf_dbm_antnoise, tvb, offset, 4, antnoise); break; case SSI_RAW_RSSI: /* Raw RSSI */ if (tree) proto_tree_add_uint(wlan_tree, hf_rawrssi_antnoise, tvb, offset, 4, antnoise); break; } } offset+=4; if (tree) proto_tree_add_item(wlan_tree, hf_wlan_preamble, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; if (tree) proto_tree_add_item(wlan_tree, hf_wlan_encoding, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; if (version > 1) { if (tree) proto_tree_add_item(wlan_tree, hf_wlan_sequence, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; if (tree) proto_tree_add_item(wlan_tree, hf_wlan_drops, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; if (tree) proto_tree_add_item(wlan_tree, hf_wlan_receiver_addr, tvb, offset, 6, ENC_NA); offset+=6; if (tree) proto_tree_add_item(wlan_tree, hf_wlan_padding, tvb, offset, 2, ENC_NA); offset+=2; } skip: offset = length; /* dissect the 802.11 header next */ next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(ieee80211_handle, next_tvb, pinfo, tree); }