static int dissect_btsmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { int offset = 0; proto_item *ti; proto_tree *st; guint8 opcode; guint32 interface_id; guint32 adapter_id; gint previous_proto; interface_id = HCI_INTERFACE_DEFAULT; adapter_id = HCI_ADAPTER_DEFAULT; previous_proto = (GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers))))); if (data && previous_proto == proto_btl2cap) { btl2cap_data_t *l2cap_data; l2cap_data = (btl2cap_data_t *) data; if (l2cap_data) { interface_id = l2cap_data->interface_id; adapter_id = l2cap_data->adapter_id; } } ti = proto_tree_add_item(tree, proto_btsmp, tvb, 0, tvb_captured_length(tvb), ENC_NA); st = proto_item_add_subtree(ti, ett_btsmp); col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMP"); switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_set_str(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_set_str(pinfo->cinfo, COL_INFO, "Rcvd "); break; default: col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection "); break; } if (tvb_reported_length(tvb) < 1) return FALSE; proto_tree_add_item(st, hf_btsmp_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN); opcode = tvb_get_guint8(tvb, 0); offset++; col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, opcode_vals, "<unknown>")); switch (opcode) { case 0x01: /* Pairing Request */ case 0x02: /* Pairing Response */ { col_append_str(pinfo->cinfo, COL_INFO, ": "); proto_tree_add_item(st, hf_btsmp_io_capabilities, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; proto_tree_add_item(st, hf_btsmp_oob_data_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); proto_tree_add_item(st, hf_btsmp_max_enc_key_size, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, TRUE); offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, FALSE); break; } case 0x03: /* Pairing Confirm */ proto_tree_add_item(st, hf_btsmp_cfm_value, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x04: /* Pairing Random */ proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x05: /* Pairing Failed */ proto_tree_add_item(st, hf_btsmp_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(tvb_get_guint8(tvb, offset), reason_vals, "<unknown>")); offset++; break; case 0x06: /* Encryption Information */ proto_tree_add_item(st, hf_btsmp_long_term_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x07: /* Master Identification */ proto_tree_add_item(st, hf_btsmp_ediv, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 8, ENC_NA); offset += 8; break; case 0x08: /* Identity Information */ proto_tree_add_item(st, hf_btsmp_id_resolving_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x09: /* Identity Address Information */ proto_tree_add_item(st, hf_address_type, tvb, offset, 1, ENC_NA); offset += 1; offset = dissect_bd_addr(hf_bd_addr, pinfo, st, tvb, offset, FALSE, interface_id, adapter_id, NULL); break; case 0x0A: /* Signing Information */ proto_tree_add_item(st, hf_btsmp_signature_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x0B: /* Security Request */ col_append_str(pinfo->cinfo, COL_INFO, ": "); offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); break; case 0x0C: /* Pairing Public Key */ { proto_item *sub_item; sub_item = proto_tree_add_item(st, hf_btsmp_public_key_x, tvb, offset, 32, ENC_NA); if (tvb_memeql(tvb, offset, debug_public_key_x, 32) == 0) proto_item_append_text(sub_item, " (Debug Key)"); offset += 32; sub_item = proto_tree_add_item(st, hf_btsmp_public_key_y, tvb, offset, 32, ENC_NA); if (tvb_memeql(tvb, offset, debug_public_key_y, 32) == 0) proto_item_append_text(sub_item, " (Debug Key)"); offset += 32; break;} case 0x0D: /* Pairing DHKey Check" */ proto_tree_add_item(st, hf_btsmp_dhkey_check, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x0E: /* Pairing Keypress Notification */ proto_tree_add_item(st, hf_btsmp_notification_type, tvb, offset, 1, ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(tvb_get_guint8(tvb, offset), notification_type_vals, "<unknown>")); offset += 1; break; default: break; } return offset; }
static void dissect_ipsictl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *ipsictl_tree = NULL; proto_tree *pdu_tree = NULL; proto_item *ti; int offset = 0; int loffset = 0; int llength = 0; int remaining_length; guint16 magic; guint16 length; guint16 type=0; guint16 sequence=0; int first_sequence=-1; int last_sequence=-1; guint16 field1=0; guint16 pdu=0; int haspdus=0; remaining_length=tvb_reported_length_remaining(tvb, offset); if (tree) { ti = proto_tree_add_item(tree, proto_ipsictl, tvb, offset, remaining_length, ENC_NA); ipsictl_tree = proto_item_add_subtree(ti, ett_ipsictl); } magic = tvb_get_ntohs(tvb, offset); if (magic == IPSICTL_PDU_MAGIC) { haspdus=1; } while (haspdus && ((remaining_length=tvb_reported_length_remaining(tvb, offset)) > 6)) { loffset = offset; magic = tvb_get_ntohs(tvb, loffset); loffset+=2; length = tvb_get_ntohs(tvb, loffset); loffset+=2; llength=length; remaining_length-=4; if (remaining_length>=2) { type = tvb_get_ntohs(tvb, loffset); loffset+=2; remaining_length-=2; llength-=2; } if (remaining_length>=2) { sequence = tvb_get_ntohs(tvb, loffset); loffset+=2; remaining_length-=2; llength-=2; if (first_sequence==-1) { first_sequence=sequence; }else{ last_sequence=sequence; } } if (remaining_length>=2) { field1 = tvb_get_ntohs(tvb, loffset); llength-=2; } if (tree) { ti = proto_tree_add_uint_format(ipsictl_tree, hf_ipsictl_pdu, tvb, offset, (length+4), pdu, "PDU: %d", pdu); pdu_tree = proto_item_add_subtree(ti, ett_ipsictl_pdu); } loffset=offset; remaining_length=tvb_reported_length_remaining(tvb, offset); if (tree) { proto_tree_add_uint(pdu_tree, hf_ipsictl_magic, tvb, loffset, 2, magic); } loffset+=2; remaining_length-=2; if (tree) { proto_tree_add_uint(pdu_tree, hf_ipsictl_length, tvb, loffset, 2, length); } loffset+=2; remaining_length-=2; if (remaining_length>=2) { if (tree) { proto_tree_add_uint(pdu_tree, hf_ipsictl_type, tvb, loffset, 2, type); } loffset+=2; remaining_length-=2; } if (remaining_length>=2) { if (tree) { proto_tree_add_uint(pdu_tree, hf_ipsictl_sequence, tvb, loffset, 2, sequence); } loffset+=2; remaining_length-=2; } if (remaining_length>=2) { if (tree) { proto_tree_add_uint(pdu_tree, hf_ipsictl_field1, tvb, loffset, 2, field1); } loffset+=2; remaining_length-=2; } if (remaining_length>=2) { if (tree) { proto_tree_add_item(pdu_tree, hf_ipsictl_data, tvb, loffset, llength, ENC_NA); } loffset+=llength; } offset=loffset; pdu++; } if (!haspdus) { if (tree) { proto_tree_add_item(ipsictl_tree, hf_ipsictl_data, tvb, offset, -1, ENC_NA); } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPSICTL"); if (haspdus) { if (last_sequence==-1) { col_add_fstr(pinfo->cinfo, COL_INFO, "PDUS=%d, Seq=0x%04x", pdu,first_sequence); }else{ col_add_fstr(pinfo->cinfo, COL_INFO, "PDUS=%d, Seq=0x%04x-0x%04x", pdu,first_sequence,last_sequence); } }else{ col_set_str(pinfo->cinfo, COL_INFO, "Initialization"); } } /* dissect_ipsictl */
static void dissect_rmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *rmi_tree; tvbuff_t *next_tvb; gint offset; gint next_offset; int datalen; guint16 version, len, port; guint8 message, proto; rmi_type rmitype; const char *epid_hostname; guint epid_len; offset = 0; rmitype = 0; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RMI"); datalen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); rmitype = get_rmi_type(tvb, offset, datalen); if (check_col(pinfo->cinfo, COL_INFO)) { switch(rmitype) { case RMI_OUTPUTSTREAM: version = tvb_get_ntohs(tvb,4); col_add_fstr(pinfo->cinfo, COL_INFO, "JRMI, Version: %d, ", version); proto = tvb_get_guint8(tvb, 6); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(proto, rmi_protocol_str, "Unknown protocol")); break; case RMI_OUTPUTMESSAGE: message = tvb_get_guint8(tvb,0); col_set_str(pinfo->cinfo, COL_INFO, "JRMI, "); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(message, rmi_output_message_str, "Unknown message")); break; case RMI_INPUTSTREAM: message = tvb_get_guint8(tvb,0); col_set_str(pinfo->cinfo, COL_INFO, "JRMI, "); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(message, rmi_input_message_str, "Unknown message")); break; case SERIALIZATION_DATA: version = tvb_get_ntohs(tvb,2); col_add_fstr(pinfo->cinfo, COL_INFO, "Serialization data, Version: %d", version); break; default: col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); break; } } if (tree) { ti = proto_tree_add_item(tree, proto_rmi, tvb, 0, -1, ENC_NA); rmi_tree = proto_item_add_subtree(ti, ett_rmi); switch(rmitype) { case RMI_OUTPUTSTREAM: /* XXX - uint, or string? */ proto_tree_add_uint(rmi_tree, hf_rmi_magic, tvb, offset, 4, tvb_get_ntohl(tvb,0)); proto_tree_add_item(rmi_tree, hf_rmi_version, tvb, offset + 4, 2, ENC_BIG_ENDIAN); proto_tree_add_item(rmi_tree, hf_rmi_protocol, tvb, offset + 6, 1, ENC_BIG_ENDIAN); break; case RMI_INPUTSTREAM: message = tvb_get_guint8(tvb, 0); proto_tree_add_uint(rmi_tree, hf_rmi_inputmessage, tvb, offset, 1, message); if(message == RMI_INPUTSTREAM_MESSAGE_ACK) { proto_tree_add_text(rmi_tree, tvb, offset + 1, -1, "EndPointIdentifier"); /* MESSAGE_ACK should include EndpointIdentifier */ len = tvb_get_ntohs(tvb, 1); proto_tree_add_uint(rmi_tree, hf_rmi_epid_length, tvb, offset + 1, 2, len); epid_len = len < ITEM_LABEL_LENGTH ? len : ITEM_LABEL_LENGTH; if (epid_len > 0) { epid_hostname = tvb_format_text(tvb, offset + 3, epid_len); } else { epid_hostname = "[Empty]"; } proto_tree_add_string(rmi_tree, hf_rmi_epid_hostname, tvb, offset + 3, len, epid_hostname); port = tvb_get_ntohs(tvb, offset + len + 5); proto_tree_add_uint(rmi_tree, hf_rmi_epid_port, tvb, offset + len + 5, 2, port); } if(message == RMI_INPUTSTREAM_MESSAGE_RETURNDATA) { proto_tree_add_text(rmi_tree, tvb, offset + 1, -1, "Serialization Data"); next_tvb = tvb_new_subset_remaining(tvb, offset + 1); dissect_ser(next_tvb, tree); } break; case RMI_OUTPUTMESSAGE: message = tvb_get_guint8(tvb, 0); proto_tree_add_uint(rmi_tree, hf_rmi_outputmessage, tvb, offset, 1, message); if(message == RMI_OUTPUTSTREAM_MESSAGE_CALL) { proto_tree_add_text(rmi_tree, tvb, offset + 1, -1, "Serialization Data"); /* XXX */ next_tvb = tvb_new_subset_remaining(tvb, offset + 1); dissect_ser(next_tvb, tree); } if(message == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) { proto_tree_add_text(rmi_tree, tvb, offset + 1, -1, "UniqueIdentifier"); } break; case SERIALIZATION_DATA: dissect_ser(tvb, tree); break; default: break; } } }
static void dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { proto_item *volatile ti = NULL, *comment_item; guint cap_len = 0, frame_len = 0; proto_tree *volatile tree; proto_tree *comments_tree; proto_item *item; const gchar *cap_plurality, *frame_plurality; tree=parent_tree; pinfo->current_proto = "Frame"; if (pinfo->pseudo_header != NULL) { switch (pinfo->fd->lnk_t) { case WTAP_ENCAP_WFLEET_HDLC: case WTAP_ENCAP_CHDLC_WITH_PHDR: case WTAP_ENCAP_PPP_WITH_PHDR: case WTAP_ENCAP_SDLC: case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ? P2P_DIR_SENT : P2P_DIR_RECV; break; case WTAP_ENCAP_BLUETOOTH_HCI: pinfo->p2p_dir = pinfo->pseudo_header->bthci.sent; break; case WTAP_ENCAP_LAPB: case WTAP_ENCAP_FRELAY_WITH_PHDR: pinfo->p2p_dir = (pinfo->pseudo_header->x25.flags & FROM_DCE) ? P2P_DIR_RECV : P2P_DIR_SENT; break; case WTAP_ENCAP_ISDN: case WTAP_ENCAP_V5_EF: case WTAP_ENCAP_DPNSS: case WTAP_ENCAP_BACNET_MS_TP_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ? P2P_DIR_SENT : P2P_DIR_RECV; break; case WTAP_ENCAP_LINUX_LAPD: pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 || pinfo->pseudo_header->lapd.pkttype == 4) ? P2P_DIR_SENT : P2P_DIR_RECV; break; case WTAP_ENCAP_MTP2_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ? P2P_DIR_SENT : P2P_DIR_RECV; pinfo->link_number = pinfo->pseudo_header->mtp2.link_number; pinfo->annex_a_used = pinfo->pseudo_header->mtp2.annex_a_used; break; case WTAP_ENCAP_GSM_UM: pinfo->p2p_dir = pinfo->pseudo_header->gsm_um.uplink ? P2P_DIR_SENT : P2P_DIR_RECV; break; } } if(pinfo->pkt_comment){ item = proto_tree_add_item(tree, proto_pkt_comment, tvb, 0, -1, ENC_NA); comments_tree = proto_item_add_subtree(item, ett_comments); comment_item = proto_tree_add_string_format(comments_tree, hf_comments_text, tvb, 0, -1, pinfo->pkt_comment, "%s", pinfo->pkt_comment); expert_add_info_format(pinfo, comment_item, &ei_comments_text, "%s", pinfo->pkt_comment); } /* if FRAME is not referenced from any filters we dont need to worry about generating any tree items. */ if(!proto_field_is_referenced(tree, proto_frame)) { tree=NULL; if(pinfo->fd->flags.has_ts) { if(pinfo->fd->abs_ts.nsecs < 0 || pinfo->fd->abs_ts.nsecs >= 1000000000) expert_add_info(pinfo, NULL, &ei_arrive_time_out_of_range); } } else { proto_tree *fh_tree; gboolean old_visible; /* Put in frame header information. */ cap_len = tvb_length(tvb); frame_len = tvb_reported_length(tvb); cap_plurality = plurality(cap_len, "", "s"); frame_plurality = plurality(frame_len, "", "s"); ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, -1, "Frame %u: %u byte%s on wire", pinfo->fd->num, frame_len, frame_plurality); if (generate_bits_field) proto_item_append_text(ti, " (%u bits)", frame_len * 8); proto_item_append_text(ti, ", %u byte%s captured", cap_len, cap_plurality); if (generate_bits_field) { proto_item_append_text(ti, " (%u bits)", cap_len * 8); } if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) { proto_item_append_text(ti, " on interface %u", pinfo->phdr->interface_id); } if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) { if (pinfo->phdr->pack_flags & 0x00000001) { proto_item_append_text(ti, " (inbound)"); pinfo->p2p_dir = P2P_DIR_RECV; } if (pinfo->phdr->pack_flags & 0x00000002) { proto_item_append_text(ti, " (outbound)"); pinfo->p2p_dir = P2P_DIR_SENT; } } fh_tree = proto_item_add_subtree(ti, ett_frame); if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID && proto_field_is_referenced(tree, hf_frame_interface_id)) { const char *interface_name = epan_get_interface_name(pinfo->epan, pinfo->phdr->interface_id); if (interface_name) proto_tree_add_uint_format_value(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id, "%u (%s)", pinfo->phdr->interface_id, interface_name); else proto_tree_add_uint(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id); } if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) { proto_tree *flags_tree; proto_item *flags_item; flags_item = proto_tree_add_uint(fh_tree, hf_frame_pack_flags, tvb, 0, 0, pinfo->phdr->pack_flags); flags_tree = proto_item_add_subtree(flags_item, ett_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_direction, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_reception_type, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_fcs_length, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_reserved, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_crc_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_long_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_short_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_inter_frame_gap_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_unaligned_frame_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_start_frame_delimiter_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_preamble_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_symbol_error, tvb, 0, 0, pinfo->phdr->pack_flags); } proto_tree_add_int(fh_tree, hf_frame_wtap_encap, tvb, 0, 0, pinfo->fd->lnk_t); if (pinfo->fd->flags.has_ts) { proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb, 0, 0, &(pinfo->fd->abs_ts)); if(pinfo->fd->abs_ts.nsecs < 0 || pinfo->fd->abs_ts.nsecs >= 1000000000) { expert_add_info_format(pinfo, ti, &ei_arrive_time_out_of_range, "Arrival Time: Fractional second %09ld is invalid," " the valid range is 0-1000000000", (long) pinfo->fd->abs_ts.nsecs); } item = proto_tree_add_time(fh_tree, hf_frame_shift_offset, tvb, 0, 0, &(pinfo->fd->shift_offset)); PROTO_ITEM_SET_GENERATED(item); if(generate_epoch_time) { proto_tree_add_time(fh_tree, hf_frame_arrival_time_epoch, tvb, 0, 0, &(pinfo->fd->abs_ts)); } if (proto_field_is_referenced(tree, hf_frame_time_delta)) { nstime_t del_cap_ts; frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->fd->num - 1, &del_cap_ts); item = proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb, 0, 0, &(del_cap_ts)); PROTO_ITEM_SET_GENERATED(item); } if (proto_field_is_referenced(tree, hf_frame_time_delta_displayed)) { nstime_t del_dis_ts; frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->fd->prev_dis_num, &del_dis_ts); item = proto_tree_add_time(fh_tree, hf_frame_time_delta_displayed, tvb, 0, 0, &(del_dis_ts)); PROTO_ITEM_SET_GENERATED(item); } item = proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb, 0, 0, &(pinfo->rel_ts)); PROTO_ITEM_SET_GENERATED(item); if(pinfo->fd->flags.ref_time){ ti = proto_tree_add_item(fh_tree, hf_frame_time_reference, tvb, 0, 0, ENC_NA); PROTO_ITEM_SET_GENERATED(ti); } } proto_tree_add_uint(fh_tree, hf_frame_number, tvb, 0, 0, pinfo->fd->num); proto_tree_add_uint_format(fh_tree, hf_frame_len, tvb, 0, 0, frame_len, "Frame Length: %u byte%s (%u bits)", frame_len, frame_plurality, frame_len * 8); proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb, 0, 0, cap_len, "Capture Length: %u byte%s (%u bits)", cap_len, cap_plurality, cap_len * 8); if (generate_md5_hash) { const guint8 *cp; md5_state_t md_ctx; md5_byte_t digest[16]; const gchar *digest_string; cp = tvb_get_ptr(tvb, 0, cap_len); md5_init(&md_ctx); md5_append(&md_ctx, cp, cap_len); md5_finish(&md_ctx, digest); digest_string = bytestring_to_str(digest, 16, '\0'); ti = proto_tree_add_string(fh_tree, hf_frame_md5_hash, tvb, 0, 0, digest_string); PROTO_ITEM_SET_GENERATED(ti); } ti = proto_tree_add_boolean(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_boolean(fh_tree, hf_frame_ignored, tvb, 0, 0,pinfo->fd->flags.ignored); PROTO_ITEM_SET_GENERATED(ti); if(proto_field_is_referenced(tree, hf_frame_protocols)) { /* we are going to be using proto_item_append_string() on * hf_frame_protocols, and we must therefore disable the * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by * setting it as visible. * * See proto.h for details. */ old_visible = proto_tree_set_visible(fh_tree, TRUE); ti = proto_tree_add_string(fh_tree, hf_frame_protocols, tvb, 0, 0, ""); PROTO_ITEM_SET_GENERATED(ti); proto_tree_set_visible(fh_tree, old_visible); } if(pinfo->fd->pfd != 0){ proto_item *ppd_item; guint num_entries = g_slist_length(pinfo->fd->pfd); guint i; ppd_item = proto_tree_add_uint(fh_tree, hf_frame_num_p_prot_data, tvb, 0, 0, num_entries); PROTO_ITEM_SET_GENERATED(ppd_item); for(i=0; i<num_entries; i++){ proto_tree_add_text (fh_tree, tvb, 0, 0, "%s",p_get_proto_name_and_key(pinfo->fd, i)); } } /* Check for existences of P2P pseudo header */ if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) { proto_tree_add_int(fh_tree, hf_frame_p2p_dir, tvb, 0, 0, pinfo->p2p_dir); } /* Check for existences of MTP2 link number */ if ((pinfo->pseudo_header != NULL ) && (pinfo->fd->lnk_t == WTAP_ENCAP_MTP2_WITH_PHDR)) { proto_tree_add_uint(fh_tree, hf_link_number, tvb, 0, 0, pinfo->link_number); } if (show_file_off) { proto_tree_add_int64_format_value(fh_tree, hf_frame_file_off, tvb, 0, 0, pinfo->fd->file_off, "%" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)", pinfo->fd->file_off, pinfo->fd->file_off); } if(pinfo->fd->color_filter != NULL) { const color_filter_t *color_filter = (const color_filter_t *)pinfo->fd->color_filter; item = proto_tree_add_string(fh_tree, hf_frame_color_filter_name, tvb, 0, 0, color_filter->filter_name); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_string(fh_tree, hf_frame_color_filter_text, tvb, 0, 0, color_filter->filter_text); PROTO_ITEM_SET_GENERATED(item); } } if (pinfo->fd->flags.ignored) { /* Ignored package, stop handling here */ col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>"); proto_tree_add_text (tree, tvb, 0, -1, "This frame is marked as ignored"); return; } /* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */ TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations. (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif if ((force_docsis_encap) && (docsis_handle)) { call_dissector(docsis_handle, tvb, pinfo, parent_tree); } else { if (!dissector_try_uint(wtap_encap_dissector_table, pinfo->fd->lnk_t, tvb, pinfo, parent_tree)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN"); col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %d", pinfo->fd->lnk_t); call_dissector(data_handle,tvb, pinfo, parent_tree); } } #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch(GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; if(proto_field_is_referenced(tree, hf_frame_protocols)) { wmem_strbuf_t *val = wmem_strbuf_new(wmem_packet_scope(), ""); wmem_list_frame_t *frame; /* skip the first entry, it's always the "frame" protocol */ frame = wmem_list_frame_next(wmem_list_head(pinfo->layers)); if (frame) { wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } while (frame) { wmem_strbuf_append_c(val, ':'); wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } proto_item_append_string(ti, wmem_strbuf_get_str(val)); } /* Call postdissectors if we have any (while trying to avoid another * TRY/CATCH) */ if (have_postdissector()) { TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations */ /* (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif call_all_postdissectors(tvb, pinfo, parent_tree); #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch(GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; } tap_queue_packet(frame_tap, pinfo, NULL); if (pinfo->frame_end_routines) { g_slist_foreach(pinfo->frame_end_routines, &call_frame_end_routine, NULL); g_slist_free(pinfo->frame_end_routines); pinfo->frame_end_routines = NULL; } }
static int dissect_l1_events(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { proto_tree *subtree; proto_item *ti; gint offset = 0, next_offset; gint len; const char *data_name; data_name = pinfo->match_string; if (! (data_name && data_name[0])) { /* * No information from "match_string" */ data_name = (char *)data; if (! (data_name && data_name[0])) { /* * No information from dissector data */ data_name = (char *)(pinfo->private_data); if (! (data_name && data_name[0])) { /* * No information from "private_data" */ data_name = NULL; } } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "Layer1"); col_set_str(pinfo->cinfo, COL_DEF_SRC, pinfo->pseudo_header->l1event.uton? "TE" : "NT"); len = tvb_find_line_end(tvb, 0, tvb_ensure_length_remaining(tvb, 0), &next_offset, FALSE); if(len>0) col_add_str(pinfo->cinfo, COL_INFO, tvb_format_text(tvb, 0, len)); if (tree) { ti = proto_tree_add_item(tree, proto_l1_events, tvb, 0, -1, ENC_NA); if (data_name) proto_item_append_text(ti, ": %s", data_name); subtree = proto_item_add_subtree(ti, ett_l1_events); /* Read the media line by line */ while (tvb_offset_exists(tvb, offset)) { /* * XXX - we need to be passed the parameters * of the content type via "pinfo->private_data", * so that we know the character set. We'd * have to handle that character set, which * might be a multibyte character set such * as "iso-10646-ucs-2", or might require other * special processing. */ len = tvb_find_line_end(tvb, offset, tvb_ensure_length_remaining(tvb, offset), &next_offset, FALSE); if (len == -1) break; /* We use next_offset - offset instead of len in the * call to proto_tree_add_format_text() so it will include the * line terminator(s) (\r and/or \n) in the display. */ proto_tree_add_format_text(subtree, tvb, offset, next_offset - offset); offset = next_offset; } } return tvb_length(tvb); }
/* Code to actually dissect the packets */ static void dissect_mip( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures we will need to add the protocol subtree and manage it */ proto_item *ti; proto_tree *mip_tree=NULL; proto_item *tf; proto_tree *flags_tree; guint8 type; guint16 flags; gint offset=0; const guint8 *reftime; tvbuff_t *next_tvb; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MobileIP"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, offset); switch (type) { case MIP_REGISTRATION_REQUEST: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Request: HoA=%s HA=%s CoA=%s", ip_to_str(tvb_get_ptr(tvb,4,4)), ip_to_str(tvb_get_ptr(tvb,8,4)), ip_to_str(tvb_get_ptr(tvb,12,4))); if (tree) { ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* flags */ flags = tvb_get_guint8(tvb, offset); tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 1, flags); flags_tree = proto_item_add_subtree(tf, ett_mip_flags); proto_tree_add_boolean(flags_tree, hf_mip_s, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_b, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_d, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_m, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_g, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_v, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_t, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_x, tvb, offset, 1, flags); offset++; /* lifetime */ proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE); offset += 2; /* home address */ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE); offset += 4; /* home agent address */ proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE); offset += 4; /* Care of Address */ proto_tree_add_item(mip_tree, hf_mip_coa, tvb, offset, 4, FALSE); offset += 4; /* Identifier - assumed to be an NTP time here */ reftime = tvb_get_ptr(tvb, offset, 8); proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8, reftime, "Identification: %s", ntp_fmt_ts(reftime)); offset += 8; } /* if tree */ break; case MIP_REGISTRATION_REPLY: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Reply: HoA=%s HA=%s, Code=%u", ip_to_str(tvb_get_ptr(tvb,4,4)), ip_to_str(tvb_get_ptr(tvb,8,4)), tvb_get_guint8(tvb,1)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* Type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* Reply Code */ proto_tree_add_item(mip_tree, hf_mip_code, tvb, offset, 1, FALSE); offset++; /* Registration Lifetime */ proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE); offset += 2; /* Home address */ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE); offset += 4; /* Home Agent Address */ proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE); offset += 4; /* Identifier - assumed to be an NTP time here */ reftime = tvb_get_ptr(tvb, offset, 8); proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8, reftime, "Identification: %s", ntp_fmt_ts(reftime)); offset += 8; } /* if tree */ break; case MIP_NATT_TUNNEL_DATA: col_add_fstr(pinfo->cinfo, COL_INFO, "Tunnel Data: Next Header=%u", tvb_get_guint8(tvb,1)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* Type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* Next Header */ proto_tree_add_item(mip_tree, hf_mip_nattt_nexthdr, tvb, offset, 1, FALSE); offset++; /* reserved */ proto_tree_add_item(mip_tree, hf_mip_nattt_reserved, tvb, offset, 2, FALSE); offset += 2; } /* if tree */ else { offset += 4; } /* encapsulated payload */ next_tvb = tvb_new_subset_remaining(tvb, 4); call_dissector(ip_handle, next_tvb, pinfo, mip_tree); offset += tvb_reported_length_remaining(tvb, offset); break; case MIP_REGISTRATION_REVOCATION: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Revocation: HoA=%s HDA=%s FDA=%s", ip_to_str(tvb_get_ptr(tvb,4,4)), ip_to_str(tvb_get_ptr(tvb,8,4)), ip_to_str(tvb_get_ptr(tvb,12,4))); if (tree) { ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* reserved */ proto_tree_add_item(mip_tree, hf_mip_rev_reserved, tvb, offset, 1, FALSE); offset++; /* flags */ flags = tvb_get_ntohs(tvb, offset); tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags); flags_tree = proto_item_add_subtree(tf, ett_mip_flags); proto_tree_add_boolean(flags_tree, hf_mip_rev_a, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_mip_rev_i, tvb, offset, 2, flags); /* reserved */ proto_tree_add_uint(flags_tree, hf_mip_rev_reserved, tvb, offset, 2, flags); offset += 2; /* home address */ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE); offset += 4; /* home domain address */ proto_tree_add_item(mip_tree, hf_mip_hda, tvb, offset, 4, FALSE); offset += 4; /* foreign domain address */ proto_tree_add_item(mip_tree, hf_mip_fda, tvb, offset, 4, FALSE); offset += 4; /* revocation identifier */ proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE); offset += 4; } /* if tree */ break; case MIP_REGISTRATION_REVOCATION_ACK: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Revocation Ack: HoA=%s", ip_to_str(tvb_get_ptr(tvb,4,4))); if (tree) { ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* reserved */ proto_tree_add_item(mip_tree, hf_mip_ack_reserved, tvb, offset, 1, FALSE); offset++; /* flags */ flags = tvb_get_ntohs(tvb, offset); tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags); flags_tree = proto_item_add_subtree(tf, ett_mip_flags); proto_tree_add_boolean(flags_tree, hf_mip_ack_i, tvb, offset, 2, flags); /* reserved */ proto_tree_add_uint(flags_tree, hf_mip_ack_reserved, tvb, offset, 2, flags); offset += 2; /* home address */ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE); offset += 4; /* revocation identifier */ proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE); offset += 4; } /* if tree */ break; } /* End switch */ if (tree) { if (tvb_reported_length_remaining(tvb, offset) > 0) dissect_mip_extensions(tvb, offset, mip_tree); } } /* dissect_mip */
static void dissect_bacnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_item *ct; proto_tree *bacnet_tree; proto_tree *control_tree; gint offset; guint8 bacnet_version; guint8 bacnet_control; guint8 bacnet_dlen; guint8 bacnet_slen; guint8 bacnet_mesgtyp; guint8 bacnet_rejectreason; guint8 bacnet_rportnum; guint8 bacnet_pinfolen; guint8 i; tvbuff_t *next_tvb; guint32 vendor_id; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-NPDU"); col_set_str(pinfo->cinfo, COL_INFO, "Building Automation and Control Network NPDU"); offset = 0; bacnet_version = tvb_get_guint8(tvb, offset); bacnet_control = tvb_get_guint8(tvb, offset+1); /* I don't know the length of the NPDU yet; Setting the length after dissection */ ti = proto_tree_add_item(tree, proto_bacnet, tvb, 0, -1, ENC_NA); bacnet_tree = proto_item_add_subtree(ti, ett_bacnet); proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_version, tvb, offset, 1, bacnet_version,"0x%02x (%s)",bacnet_version, (bacnet_version == 0x01)?"ASHRAE 135-1995":"unknown"); offset ++; ct = proto_tree_add_uint(bacnet_tree, hf_bacnet_control, tvb, offset, 1, bacnet_control); control_tree = proto_item_add_subtree(ct, ett_bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_net, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_res1, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_dest, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_res2, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_src, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_expect, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_high, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_low, tvb, offset, 1, bacnet_control); offset ++; if (bacnet_control & BAC_CONTROL_DEST) { /* DNET, DLEN, DADR */ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; bacnet_dlen = tvb_get_guint8(tvb, offset); /* DLEN = 0 is broadcast on dest.network */ if( bacnet_dlen == 0) { /* append to hf_bacnet_dlen: broadcast */ proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen, "%d indicates Broadcast on Destination Network", bacnet_dlen); offset ++; /* going to SNET */ } else if (bacnet_dlen==6) { proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen); offset ++; /* Ethernet MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_dadr_eth, tvb, offset, bacnet_dlen, ENC_NA); offset += bacnet_dlen; } else if (bacnet_dlen==1) { proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen); offset ++; /* MS/TP or ARCNET MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_dadr_mstp, tvb, offset, bacnet_dlen, ENC_BIG_ENDIAN); offset += bacnet_dlen; } else if (bacnet_dlen<7) { proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen); offset ++; /* Other MAC formats should be included here */ proto_tree_add_item(bacnet_tree, hf_bacnet_dadr_tmp, tvb, offset, bacnet_dlen, ENC_NA); offset += bacnet_dlen; } else { proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen, "%d invalid!", bacnet_dlen); } } if (bacnet_control & BAC_CONTROL_SRC) { /* SNET, SLEN, SADR */ /* SNET */ proto_tree_add_uint(bacnet_tree, hf_bacnet_snet, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset += 2; bacnet_slen = tvb_get_guint8(tvb, offset); if( bacnet_slen == 0) { /* SLEN = 0 invalid */ proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen, "%d invalid!", bacnet_slen); offset ++; } else if (bacnet_slen==6) { /* SLEN */ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen); offset ++; /* Ethernet MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_sadr_eth, tvb, offset, bacnet_slen, ENC_NA); offset += bacnet_slen; } else if (bacnet_slen==1) { /* SLEN */ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen); offset ++; /* MS/TP or ARCNET MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_sadr_mstp, tvb, offset, bacnet_slen, ENC_BIG_ENDIAN); offset += bacnet_slen; } else if (bacnet_slen<6) { /* LON MAC */ /* SLEN */ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen); offset ++; /* Other MAC formats should be included here */ proto_tree_add_item(bacnet_tree, hf_bacnet_sadr_tmp, tvb, offset, bacnet_slen, ENC_NA); offset += bacnet_slen; } else { proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen, "%d invalid!", bacnet_slen); offset ++; } } if (bacnet_control & BAC_CONTROL_DEST) { /* Hopcount */ proto_tree_add_item(bacnet_tree, hf_bacnet_hopc, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; } /* Network Layer Message Type */ if (bacnet_control & BAC_CONTROL_NET) { bacnet_mesgtyp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_mesgtyp, tvb, offset, 1, bacnet_mesgtyp, "%02x (%s)", bacnet_mesgtyp, bacnet_mesgtyp_name(bacnet_mesgtyp)); /* Put the NPDU Type in the info column */ col_add_str(pinfo->cinfo, COL_INFO, bacnet_mesgtyp_name(bacnet_mesgtyp)); offset ++; /* Vendor ID * The standard says: "If Bit 7 of the control octet is 1 and * the Message Type field contains a value in the range * X'80' - X'FF', then a Vendor ID field shall be present (...)." * We should not go any further in dissecting the packet if it's * not present, but we don't know about that: No length field... */ if (bacnet_mesgtyp > 0x7f) { /* Note: our next_tvb includes message type and vendor id! */ next_tvb = tvb_new_subset_remaining(tvb, offset-1); vendor_id = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(bacnet_tree, hf_bacnet_vendor, tvb, offset, 2, vendor_id); offset += 2; /* vendor_id */ if (dissector_try_uint(bacnet_dissector_table, vendor_id, next_tvb, pinfo, bacnet_tree)) { /* we parsed it so skip over length and we are done */ /* Note: offset has now been bumped for message type and vendor id so we take that out of our next_tvb size */ offset += tvb_length(next_tvb) -3; } } /* Performance Index (in I-Could-Be-Router-To-Network) */ if (bacnet_mesgtyp == BAC_NET_ICB_R) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(bacnet_tree, hf_bacnet_perf, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; } /* Reason, DNET (in Reject-Message-To-Network) */ if (bacnet_mesgtyp == BAC_NET_REJ) { bacnet_rejectreason = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_rejectreason, tvb, offset, 1, bacnet_rejectreason, "%d (%s)", bacnet_rejectreason, bacnet_rejectreason_name(bacnet_rejectreason)); offset ++; proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } /* N*DNET (in Router-Busy-To-Network,Router-Available-To-Network) */ if ((bacnet_mesgtyp == BAC_NET_R_BUSY) || (bacnet_mesgtyp == BAC_NET_WHO_R) || (bacnet_mesgtyp == BAC_NET_R_AVA) || (bacnet_mesgtyp == BAC_NET_IAM_R) ) { while(tvb_reported_length_remaining(tvb, offset) > 1 ) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } } /* Initialize-Routing-Table */ if ( (bacnet_mesgtyp == BAC_NET_INIT_RTAB) || (bacnet_mesgtyp == BAC_NET_INIT_RTAB_ACK) ) { bacnet_rportnum = tvb_get_guint8(tvb, offset); /* number of ports */ proto_tree_add_uint(bacnet_tree, hf_bacnet_rportnum, tvb, offset, 1, bacnet_rportnum); offset ++; for(i=0; i<bacnet_rportnum; i++) { /* Connected DNET */ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Port ID */ proto_tree_add_item(bacnet_tree, hf_bacnet_portid, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; /* Port Info Length */ bacnet_pinfolen = tvb_get_guint8(tvb, offset); proto_tree_add_uint(bacnet_tree, hf_bacnet_pinfolen, tvb, offset, 1, bacnet_pinfolen); offset ++; proto_tree_add_item(bacnet_tree, hf_bacnet_pinfo, tvb, offset, bacnet_pinfolen, ENC_NA); offset += bacnet_pinfolen; } } /* Establish-Connection-To-Network */ if (bacnet_mesgtyp == BAC_NET_EST_CON) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(bacnet_tree, hf_bacnet_term_time_value, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; } /* Disconnect-Connection-To-Network */ if (bacnet_mesgtyp == BAC_NET_DISC_CON) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } } /* Now set NPDU length */ proto_item_set_len(ti, offset); /* dissect BACnet APDU */ next_tvb = tvb_new_subset_remaining(tvb,offset); if (bacnet_control & BAC_CONTROL_NET) { /* Unknown function - dissect the payload as data */ call_dissector(data_handle, next_tvb, pinfo, tree); } else { /* APDU - call the APDU dissector */ call_dissector(bacapp_handle, next_tvb, pinfo, tree); } }
static void dissect_nmpi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *nmpi_tree = NULL; proto_item *ti; int offset = 0; guint8 opcode; guint8 nmpi_name_type; char name[(NETBIOS_NAME_LEN - 1)*4 + 1]; int name_type; char node_name[(NETBIOS_NAME_LEN - 1)*4 + 1]; /*int node_name_type = 0;*/ tvbuff_t *next_tvb; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMPI"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { ti = proto_tree_add_item(tree, proto_nmpi, tvb, offset, 68, ENC_NA); nmpi_tree = proto_item_add_subtree(ti, ett_nmpi); add_routers(nmpi_tree, tvb, offset); } offset += 32; /* * XXX - we don't use "node_name" or "node_name_type". */ opcode = tvb_get_guint8(tvb, offset); nmpi_name_type = tvb_get_guint8(tvb, offset+1); name_type = get_netbios_name(tvb, offset+4, name, (NETBIOS_NAME_LEN - 1)*4 + 1); /*node_name_type = */get_netbios_name(tvb, offset+20, node_name, (NETBIOS_NAME_LEN - 1)*4 + 1); switch (opcode) { case INAME_CLAIM: col_add_fstr(pinfo->cinfo, COL_INFO, "Claim name %s<%02x>", name, name_type); break; case INAME_DELETE: col_add_fstr(pinfo->cinfo, COL_INFO, "Delete name %s<%02x>", name, name_type); break; case INAME_QUERY: col_add_fstr(pinfo->cinfo, COL_INFO, "Query name %s<%02x>", name, name_type); break; case INAME_FOUND: col_add_fstr(pinfo->cinfo, COL_INFO, "Name %s<%02x> found", name, name_type); break; case IMSG_HANGUP: col_add_fstr(pinfo->cinfo, COL_INFO, "Messenger hangup on %s<%02x>", name, name_type); break; case IMSLOT_SEND: col_add_fstr(pinfo->cinfo, COL_INFO, "Mailslot write to %s<%02x>", name, name_type); break; case IMSLOT_FIND: col_add_fstr(pinfo->cinfo, COL_INFO, "Find mailslot name %s<%02x>", name, name_type); break; case IMSLOT_NAME: col_add_fstr(pinfo->cinfo, COL_INFO, "Mailslot name %s<%02x> found", name, name_type); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown NMPI op 0x%02x: name %s<%02x>", opcode, name, name_type); break; } if (tree) { proto_tree_add_text(nmpi_tree, tvb, offset, 1, "Opcode: %s (0x%02x)", val_to_str_const(opcode, nmpi_opcode_vals, "Unknown"), opcode); proto_tree_add_text(nmpi_tree, tvb, offset+1, 1, "Name Type: %s (0x%02x)", val_to_str_const(nmpi_name_type, nmpi_name_type_vals, "Unknown"), nmpi_name_type); proto_tree_add_text(nmpi_tree, tvb, offset+2, 2, "Message ID: 0x%04x", tvb_get_letohs(tvb, offset+2)); netbios_add_name("Requested name", tvb, offset+4, nmpi_tree); netbios_add_name("Source name", tvb, offset+20, nmpi_tree); } offset += 1 + 1 + 2 + NETBIOS_NAME_LEN + NETBIOS_NAME_LEN; if (opcode == IMSLOT_SEND && tvb_offset_exists(tvb, offset)) { next_tvb = tvb_new_subset_remaining(tvb, offset); dissect_netbios_payload(next_tvb, pinfo, tree); } }
static void dissect_icap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *icap_tree = NULL; proto_item *ti = NULL; proto_item *hidden_item; tvbuff_t *new_tvb; gint offset = 0; const guchar *line; gint next_offset; const guchar *linep, *lineend; int linelen; guchar c; icap_type_t icap_type; int datalen; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICAP"); /* * Put the first line from the buffer into the summary * if it's an ICAP header (but leave out the * line terminator). * Otherwise, just call it a continuation. * * Note that "tvb_find_line_end()" will return a value that * is not longer than what's in the buffer, so the * "tvb_get_ptr()" call won't throw an exception. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); icap_type = ICAP_OTHER; /* type not known yet */ if (is_icap_message(line, linelen, &icap_type)) col_add_str(pinfo->cinfo, COL_INFO, format_text(line, linelen)); else col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); if (tree) { ti = proto_tree_add_item(tree, proto_icap, tvb, offset, -1, ENC_NA); icap_tree = proto_item_add_subtree(ti, ett_icap); } /* * Process the packet data, a line at a time. */ icap_type = ICAP_OTHER; /* type not known yet */ while (tvb_offset_exists(tvb, offset)) { gboolean is_icap = FALSE; gboolean loop_done = FALSE; /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); /* * Get a buffer that refers to the line. */ line = tvb_get_ptr(tvb, offset, linelen); lineend = line + linelen; /* * find header format */ if (is_icap_message(line, linelen, &icap_type)) { goto is_icap_header; } /* * if it looks like a blank line, end of header perhaps? */ if (linelen == 0) { goto is_icap_header; } /* * No. Does it look like a header? */ linep = line; loop_done = FALSE; while (linep < lineend && (!loop_done)) { c = *linep++; /* * This must be a CHAR, and must not be a CTL, to be part * of a token; that means it must be printable ASCII. * * XXX - what about leading LWS on continuation * lines of a header? */ if (!g_ascii_isprint(c)) { is_icap = FALSE; break; } switch (c) { case '(': case ')': case '<': case '>': case '@': case ',': case ';': case '\\': case '"': case '/': case '[': case ']': case '?': case '=': case '{': case '}': /* * It's a separator, so it's not part of a * token, so it's not a field name for the * beginning of a header. * * (We don't have to check for HT; that's * already been ruled out by "iscntrl()".) * * XXX - what about ' '? HTTP's checks * check for that. */ is_icap = FALSE; loop_done = TRUE; break; case ':': /* * This ends the token; we consider this * to be a header. */ goto is_icap_header; } } /* * We don't consider this part of an ICAP message, * so we don't display it. * (Yeah, that means we don't display, say, a text/icap * page, but you can get that from the data pane.) */ if (!is_icap) break; is_icap_header: proto_tree_add_format_text(icap_tree, tvb, offset, next_offset - offset); offset = next_offset; } if (tree) { switch (icap_type) { case ICAP_OPTIONS: hidden_item = proto_tree_add_boolean(icap_tree, hf_icap_options, tvb, 0, 0, 1); PROTO_ITEM_SET_HIDDEN(hidden_item); break; case ICAP_REQMOD: hidden_item = proto_tree_add_boolean(icap_tree, hf_icap_reqmod, tvb, 0, 0, 1); PROTO_ITEM_SET_HIDDEN(hidden_item); break; case ICAP_RESPMOD: hidden_item = proto_tree_add_boolean(icap_tree, hf_icap_respmod, tvb, 0, 0, 1); PROTO_ITEM_SET_HIDDEN(hidden_item); break; case ICAP_RESPONSE: hidden_item = proto_tree_add_boolean(icap_tree, hf_icap_response, tvb, 0, 0, 1); PROTO_ITEM_SET_HIDDEN(hidden_item); break; case ICAP_OTHER: default: break; } } datalen = tvb_reported_length_remaining(tvb, offset); if (datalen > 0) { if(http_handle){ new_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(http_handle, new_tvb, pinfo, icap_tree); } } }
/* Code to actually dissect the PAGP packets */ static void dissect_pagp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint32 raw_word; guint16 raw_half_word; guint16 num_tlvs; guint16 tlv; guint16 len; guint16 ii; guint16 offset = PAGP_FIRST_TLV; guint8 raw_octet; guint8 flags; guchar *ch; proto_tree *pagp_tree = NULL; proto_item *pagp_item; proto_tree *flags_tree; proto_item *flags_item; proto_tree *tlv_tree; proto_item *tlv_item; const char *sep; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PAGP"); /* PAGP Protocol */ col_clear(pinfo->cinfo, COL_INFO); pinfo->current_proto = "PAGP"; raw_octet = tvb_get_guint8(tvb, PAGP_VERSION_NUMBER); if (tree) { pagp_item = proto_tree_add_protocol_format(tree, proto_pagp, tvb, 0, -1, "Port Aggregation Protocol"); pagp_tree = proto_item_add_subtree(pagp_item, ett_pagp); proto_tree_add_uint(pagp_tree, hf_pagp_version_number, tvb, PAGP_VERSION_NUMBER, 1, raw_octet); } col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(raw_octet, pdu_vers, "Unknown PDU version")); if (raw_octet == PAGP_FLUSH_PDU) { col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s", tvb_ether_to_str(tvb, PAGP_FLUSH_LOCAL_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_flush_local_device_id, tvb, PAGP_FLUSH_LOCAL_DEVICE_ID, 6, ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s", tvb_ether_to_str(tvb, PAGP_FLUSH_PARTNER_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_flush_partner_device_id, tvb, PAGP_FLUSH_PARTNER_DEVICE_ID, 6, ENC_NA); raw_word = tvb_get_ntohl(tvb, PAGP_FLUSH_TRANSACTION_ID); col_append_fstr(pinfo->cinfo, COL_INFO, "; Transaction ID: 0x%x ", raw_word); proto_tree_add_uint(pagp_tree, hf_pagp_flush_transaction_id, tvb, PAGP_FLUSH_TRANSACTION_ID, 4, raw_word); return; } /* Info PDU */ flags = tvb_get_guint8(tvb, PAGP_FLAGS); col_append_fstr(pinfo->cinfo, COL_INFO, "; Flags 0x%x", flags); if (tree) { flags_item = proto_tree_add_uint(pagp_tree, hf_pagp_flags, tvb, PAGP_FLAGS, 1, flags); flags_tree = proto_item_add_subtree(flags_item, ett_pagp_flags); sep = initial_sep; APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_SLOW_HELLO, flags_item, "%sSlow Hello"); proto_tree_add_boolean(flags_tree, hf_pagp_flags_slow_hello, tvb, PAGP_FLAGS, 1, flags); APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_AUTO_MODE, flags_item, "%sAuto Mode"); proto_tree_add_boolean(flags_tree, hf_pagp_flags_auto_mode, tvb, PAGP_FLAGS, 1, flags); APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_CONSISTENT_STATE, flags_item, "%sConsistent State"); proto_tree_add_boolean(flags_tree, hf_pagp_flags_consistent_state, tvb, PAGP_FLAGS, 1, flags); sep = cont_sep; if (sep != initial_sep) { /* We put something in; put in the terminating ")" */ proto_item_append_text(flags_item, ")"); } } col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s", tvb_ether_to_str(tvb, PAGP_LOCAL_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_local_device_id, tvb, PAGP_LOCAL_DEVICE_ID, 6, ENC_NA); if (tree) { raw_octet = tvb_get_guint8(tvb, PAGP_LOCAL_LEARN_CAP); proto_tree_add_uint(pagp_tree, hf_pagp_local_learn_cap, tvb, PAGP_LOCAL_LEARN_CAP, 1, raw_octet); raw_octet = tvb_get_guint8(tvb, PAGP_LOCAL_PORT_PRIORITY); proto_tree_add_uint(pagp_tree, hf_pagp_local_port_priority, tvb, PAGP_LOCAL_PORT_PRIORITY, 1, raw_octet); raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_SENT_PORT_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_local_sent_port_ifindex, tvb, PAGP_LOCAL_SENT_PORT_IFINDEX, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_GROUP_CAPABILITY); proto_tree_add_uint(pagp_tree, hf_pagp_local_group_capability, tvb, PAGP_LOCAL_GROUP_CAPABILITY, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_GROUP_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_local_group_ifindex, tvb, PAGP_LOCAL_GROUP_IFINDEX, 4, raw_word); } col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s", tvb_ether_to_str(tvb, PAGP_PARTNER_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_partner_device_id, tvb, PAGP_PARTNER_DEVICE_ID, 6, ENC_NA); if (tree) { raw_octet = tvb_get_guint8(tvb, PAGP_PARTNER_LEARN_CAP); proto_tree_add_uint(pagp_tree, hf_pagp_partner_learn_cap, tvb, PAGP_PARTNER_LEARN_CAP, 1, raw_octet); raw_octet = tvb_get_guint8(tvb, PAGP_PARTNER_PORT_PRIORITY); proto_tree_add_uint(pagp_tree, hf_pagp_partner_port_priority, tvb, PAGP_PARTNER_PORT_PRIORITY, 1, raw_octet); raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_SENT_PORT_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_partner_sent_port_ifindex, tvb, PAGP_PARTNER_SENT_PORT_IFINDEX, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_GROUP_CAPABILITY); proto_tree_add_uint(pagp_tree, hf_pagp_partner_group_capability, tvb, PAGP_PARTNER_GROUP_CAPABILITY, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_GROUP_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_partner_group_ifindex, tvb, PAGP_PARTNER_GROUP_IFINDEX, 4, raw_word); raw_half_word = tvb_get_ntohs(tvb, PAGP_PARTNER_COUNT); proto_tree_add_uint(pagp_tree, hf_pagp_partner_count, tvb, PAGP_PARTNER_COUNT, 2, raw_half_word); num_tlvs = tvb_get_ntohs(tvb, PAGP_NUM_TLVS); proto_tree_add_uint(pagp_tree, hf_pagp_num_tlvs, tvb, PAGP_NUM_TLVS, 2, num_tlvs); /* dump TLV entries */ for ( ii = 0; ii < num_tlvs; ii++ ) { tlv = tvb_get_ntohs(tvb, offset); len = tvb_get_ntohs(tvb, offset + 2); if ( len == 0 ) { proto_tree_add_text(pagp_tree, tvb, offset, -1, "Unknown data - TLV len=0"); return; } tlv_item = proto_tree_add_text (pagp_tree, tvb, offset, len, "TLV Entry #%d", ii+1); tlv_tree = proto_item_add_subtree (tlv_item, ett_pagp_tlvs); proto_tree_add_uint_format (tlv_tree, hf_pagp_tlv, tvb, offset,2,tlv,"Type = %d (%s)", tlv, val_to_str_const(tlv,tlv_types, "Unknown")) ; proto_tree_add_text (tlv_tree, tvb, offset+2, 2, "Length = %u bytes (includes Type and Length)", len) ; if ( tvb_reported_length_remaining(tvb, offset) < len ) { proto_tree_add_text(tlv_tree, tvb, offset, -1, "TLV length too large"); return; } switch (tlv) { case PAGP_TLV_DEVICE_NAME: ch = tvb_get_string(wmem_packet_scope(), tvb, offset+4, len-4); proto_tree_add_string(tlv_tree, hf_pagp_tlv_device_name, tvb, offset+4, len-4, ch); break; case PAGP_TLV_PORT_NAME: ch = tvb_get_string(wmem_packet_scope(), tvb, offset+4, len-4); proto_tree_add_string(tlv_tree, hf_pagp_tlv_port_name, tvb, offset+4, len-4, ch); break; case PAGP_TLV_AGPORT_MAC: proto_tree_add_item(tlv_tree, hf_pagp_tlv_agport_mac, tvb, offset+4, 6, ENC_NA); break; case PAGP_TLV_RESERVED: break; } offset += len; } } }
static int dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { gboolean has_routes; proto_tree *nbipx_tree = NULL; proto_item *ti = NULL; int offset = 0; guint8 packet_type; proto_tree *name_type_flag_tree; proto_item *tf; char name[(NETBIOS_NAME_LEN - 1)*4 + 1]; int name_type; gboolean has_payload; tvbuff_t *next_tvb; ipxhdr_t *ipxh; /* Reject the packet if data is NULL */ if (data == NULL) return 0; ipxh = (ipxhdr_t*)data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBIPX"); col_clear(pinfo->cinfo, COL_INFO); if (ipxh->ipx_type == IPX_PACKET_TYPE_WANBCAST) { /* * This is a WAN Broadcast packet; we assume it will have * 8 IPX addresses at the beginning. */ has_routes = TRUE; } else { /* * This isn't a WAN Broadcast packet, but it still might * have the 8 addresses. * * If it's the right length for a name operation, * and, if we assume it has routes, the packet type * is a name operation, assume it has routes. * * NOTE: this will throw an exception if the byte that * would be the packet type byte if this has the 8 * addresses isn't present; if that's the case, we don't * know how to interpret this packet, so we can't dissect * it anyway. */ has_routes = FALSE; /* start out assuming it doesn't */ if (tvb_reported_length(tvb) == 50) { packet_type = tvb_get_guint8(tvb, offset + 32 + 1); switch (packet_type) { case NBIPX_FIND_NAME: case NBIPX_NAME_RECOGNIZED: case NBIPX_CHECK_NAME: case NBIPX_NAME_IN_USE: case NBIPX_DEREGISTER_NAME: has_routes = TRUE; break; } } } if (tree) { ti = proto_tree_add_item(tree, proto_nbipx, tvb, 0, -1, ENC_NA); nbipx_tree = proto_item_add_subtree(ti, ett_nbipx); } if (has_routes) { if (tree) add_routers(nbipx_tree, tvb, 0); offset += 32; } packet_type = tvb_get_guint8(tvb, offset + 1); switch (packet_type) { case NBIPX_FIND_NAME: case NBIPX_NAME_RECOGNIZED: case NBIPX_CHECK_NAME: case NBIPX_NAME_IN_USE: case NBIPX_DEREGISTER_NAME: name_type = get_netbios_name(tvb, offset+2, name, (NETBIOS_NAME_LEN - 1)*4 + 1); col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s<%02x>", val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"), name, name_type); if (nbipx_tree) { tf = proto_tree_add_item(nbipx_tree, hf_nbipx_name_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); name_type_flag_tree = proto_item_add_subtree(tf, ett_nbipx_name_type_flags); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_group, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_in_use, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_registered, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_duplicated, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_deregistered, tvb, offset, 1, ENC_LITTLE_ENDIAN); } offset += 1; proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type); offset += 1; if (nbipx_tree) netbios_add_name("Name", tvb, offset, nbipx_tree); offset += NETBIOS_NAME_LEN; /* * No payload to be interpreted by another protocol. */ has_payload = FALSE; break; case NBIPX_SESSION_DATA: case NBIPX_SESSION_END: case NBIPX_SESSION_END_ACK: col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown")); dissect_conn_control(tvb, offset, nbipx_tree); offset += 1; proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type); offset += 1; proto_tree_add_item(nbipx_tree, hf_nbipx_session_src_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_dest_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_send_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_total_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_recv_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_bytes_received, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* * We may have payload to dissect. */ has_payload = TRUE; break; case NBIPX_DIRECTED_DATAGRAM: col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown")); dissect_conn_control(tvb, offset, nbipx_tree); offset += 1; proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type); offset += 1; if (nbipx_tree) netbios_add_name("Receiver's Name", tvb, offset, nbipx_tree); offset += NETBIOS_NAME_LEN; if (nbipx_tree) netbios_add_name("Sender's Name", tvb, offset, nbipx_tree); offset += NETBIOS_NAME_LEN; /* * We may have payload to dissect. */ has_payload = TRUE; break; default: col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown")); /* * We don't know what the first byte is. */ offset += 1; /* * The second byte is a data stream type byte. */ proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type); offset += 1; /* * We don't know what the rest of the packet is. */ has_payload = FALSE; } /* * Set the length of the NBIPX tree item. */ if (ti != NULL) proto_item_set_len(ti, offset); if (has_payload && tvb_offset_exists(tvb, offset)) { next_tvb = tvb_new_subset_remaining(tvb, offset); dissect_netbios_payload(next_tvb, pinfo, tree); } return tvb_length(tvb); }
/* Code to actually dissect the packets */ static void dissect_nsrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *nsrp_tree = NULL; gint offset = 0; guint8 msgtype = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSRP"); if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); col_set_str(pinfo->cinfo, COL_INFO, "NSRP Protocol"); } if (tree) { ti = proto_tree_add_item(tree, proto_nsrp, tvb, 0, -1, FALSE); nsrp_tree = proto_item_add_subtree(ti, ett_nsrp); proto_tree_add_item(nsrp_tree, hf_nsrp_version, tvb, offset, 1, FALSE); offset += 1; msgtype = tvb_get_guint8(tvb, offset); proto_tree_add_item(nsrp_tree, hf_nsrp_msg_type, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_clust_id, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_msg_flag, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_len, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nsrp_tree, hf_nsrp_ha_port, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_not_used, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_dst_unit, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(nsrp_tree, hf_nsrp_src_unit, tvb, offset, 4, FALSE); offset += 4; } /* * * * NSRP HA Packet is defined as follow: * * 1 2 3 4 5 6 7 8 * +--------+--------+--------+--------+--------+--------+--------+--------+ * | Type |WstGroup|HstGroup|MSG Flag| Length |Enc Flag|Not Used| * +--------+--------+--------+--------+--------+--------+--------+--------+ * | Total Size | NS | NR | * +--------+--------+--------+--------+--------+--------+--------+--------+ * | No Used | Checksum | Data | * +--------+--------+--------+--------+-----------------------------------+ * * */ if ( msgtype == 0x00 ) { proto_tree_add_item(nsrp_tree, hf_nsrp_msgtype, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_wst_group, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_hst_group, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_msgflag, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_msglen, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nsrp_tree, hf_nsrp_encflag, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_not_used, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_total_size, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(nsrp_tree, hf_nsrp_ns, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nsrp_tree, hf_nsrp_nr, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nsrp_tree, hf_nsrp_no_used, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nsrp_tree, hf_nsrp_checksum, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nsrp_tree, hf_nsrp_data, tvb, offset, -1, FALSE); } /* * * NSRP MNG Packet is defined as follow: * * 1 2 3 4 5 6 7 8 * +--------+--------+--------+--------+--------+--------+--------+--------+ * | Type |WstGroup|HstGroup|MSG Flag| Length |AuthFlag|Not Used| * +--------+--------+--------+--------+--------+--------+--------+--------+ * |Priority+ Dummy + Auth CheckSum + Data | * +--------+--------+--------+--------+-----------------------------------+ * * */ if ( msgtype == 0x02 ) { proto_tree_add_item(nsrp_tree, hf_nsrp_msgtype, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_wst_group, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_hst_group, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_msgflag, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_msglen, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nsrp_tree, hf_nsrp_authflag, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_not_used, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_priority, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_dummy, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_authchecksum, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nsrp_tree, hf_nsrp_data, tvb, offset, -1, FALSE); } /* * NSRP DATA Packet is defined as follow: * * 1 2 3 4 5 6 7 8 * +--------+--------+--------+--------+--------+--------+--------+--------+ * | Type |WstGroup|HstGroup|MSG Flag| Length | Ifnum |Not Used| * +--------+--------+--------+--------+--------+--------+--------+--------+ * | Total Size | Data | * +--------+--------+--------+--------+-----------------------------------+ * * */ if ( msgtype == 0x03 ) { proto_tree_add_item(nsrp_tree, hf_nsrp_msgtype, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_wst_group, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_hst_group, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_msgflag, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_msglen, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nsrp_tree, hf_nsrp_ifnum, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_not_used, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nsrp_tree, hf_nsrp_total_size, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(nsrp_tree, hf_nsrp_data, tvb, offset, -1, FALSE); } }
static int dissect_packetlogger(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_tree *packetlogger_tree = NULL; tvbuff_t *next_tvb; proto_item *ti = NULL; guint8 pl_type; gint len; bluetooth_data_t *bluetooth_data; struct bthci_phdr bthci; bluetooth_data = (bluetooth_data_t *) data; col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME); col_clear (pinfo->cinfo, COL_INFO); ti = proto_tree_add_item (tree, proto_packetlogger, tvb, 0, -1, ENC_NA); packetlogger_tree = proto_item_add_subtree (ti, ett_packetlogger); pl_type = tvb_get_guint8 (tvb, 0); proto_tree_add_item (packetlogger_tree, hf_type, tvb, 0, 1, ENC_BIG_ENDIAN); proto_item_append_text (ti, " %s", val_to_str (pl_type, type_vals, "Unknown 0x%02x")); len = tvb_reported_length_remaining (tvb, 1); next_tvb = tvb_new_subset_remaining (tvb, 1); if (pl_type <= PKT_RECV_ACL_DATA) { /* HCI H1 packages */ switch (pl_type) { case PKT_HCI_COMMAND: bthci.channel = BTHCI_CHANNEL_COMMAND; bthci.sent = P2P_DIR_SENT; pinfo->p2p_dir = P2P_DIR_SENT; break; case PKT_HCI_EVENT: bthci.channel = BTHCI_CHANNEL_EVENT; bthci.sent = P2P_DIR_RECV; pinfo->p2p_dir = P2P_DIR_RECV; break; case PKT_SENT_ACL_DATA: bthci.channel = BTHCI_CHANNEL_ACL; bthci.sent = P2P_DIR_SENT; pinfo->p2p_dir = P2P_DIR_SENT; break; case PKT_RECV_ACL_DATA: bthci.channel = BTHCI_CHANNEL_ACL; bthci.sent = P2P_DIR_RECV; pinfo->p2p_dir = P2P_DIR_RECV; break; default: bthci.channel = pl_type; bthci.sent = P2P_DIR_UNKNOWN; pinfo->p2p_dir = P2P_DIR_UNKNOWN; break; } bluetooth_data->previous_protocol_data.bthci = &bthci; proto_item_set_len (ti, 1); col_add_fstr (pinfo->cinfo, COL_INFO, "%s", val_to_str(pl_type, type_vals, "Unknown 0x%02x")); if (!dissector_try_uint_new(hci_h1_table, bthci.channel, next_tvb, pinfo, tree, TRUE, bluetooth_data)) { call_dissector (data_handle, next_tvb, pinfo, tree); } } else { /* PacketLogger data */ switch (pl_type) { case PKT_POWER: case PKT_NOTE: case PKT_NEW_CONTROLLER: proto_tree_add_item (packetlogger_tree, hf_info, next_tvb, 0, len, ENC_ASCII|ENC_NA); col_add_fstr (pinfo->cinfo, COL_INFO, "%s", tvb_format_stringzpad_wsp (next_tvb, 0, len)); break; default: call_dissector (data_handle, next_tvb, pinfo, tree); col_add_fstr (pinfo->cinfo, COL_INFO, "Unknown 0x%02x", pl_type); break; } } return tvb_captured_length(tvb); }
static void dissect_applemidi_common( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 command ) { guint16 seq_num; guint8 count; guint8 *name; gint offset = 0; gint len; gint string_size; proto_tree *applemidi_tree; proto_tree *applemidi_tree_seq_num; col_set_str( pinfo->cinfo, COL_PROTOCOL, APPLEMIDI_DISSECTOR_SHORTNAME ); /* Clear out stuff in the info column */ col_clear( pinfo->cinfo, COL_INFO ); col_add_fstr( pinfo->cinfo, COL_INFO, "%s", val_to_str( command, applemidi_commands, applemidi_unknown_command ) ); if ( tree ) { proto_item *ti; ti = proto_tree_add_item( tree, proto_applemidi, tvb, 0, -1, ENC_NA ); applemidi_tree = proto_item_add_subtree( ti, ett_applemidi ); proto_tree_add_item( applemidi_tree, hf_applemidi_signature, tvb, offset, 2, ENC_BIG_ENDIAN ); offset += 2; proto_tree_add_item( applemidi_tree, hf_applemidi_command, tvb, offset, 2, ENC_BIG_ENDIAN ); offset += 2; /* the format of packets for "IN", "NO", "OK" and "BY" is identical and contains * the protocol version, a random number generated by the initiator of the session, * the SSRC that is used by the respective sides RTP-entity and optionally the * name of the participant */ if ( ( APPLEMIDI_COMMAND_INVITATION == command ) || ( APPLEMIDI_COMMAND_INVITATION_REJECTED == command ) || ( APLLEMIDI_COMMAND_INVITATION_ACCEPTED == command ) || ( APPLEMIDI_COMMAND_ENDSESSION == command ) ) { proto_tree_add_item( applemidi_tree, hf_applemidi_protocol_version, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; proto_tree_add_item( applemidi_tree, hf_applemidi_token, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; len = tvb_reported_length(tvb) - offset; /* Name is optional */ if ( len > 0 ) { name = tvb_get_string( wmem_packet_scope(), tvb, offset, len ); string_size = (gint)( strlen( name ) + 1 ); proto_tree_add_item( applemidi_tree, hf_applemidi_name, tvb, offset, string_size, ENC_UTF_8|ENC_NA ); col_append_fstr( pinfo->cinfo, COL_INFO, ": peer = \"%s\"", name ); offset += string_size; } /* the synchronization packet contains three 64bit timestamps, and a value to define how * many of the timestamps transmitted are valid */ } else if ( APPLEMIDI_COMMAND_SYNCHRONIZATION == command ) { proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; count = tvb_get_guint8( tvb, offset ); proto_tree_add_item( applemidi_tree, hf_applemidi_count, tvb, offset, 1, ENC_BIG_ENDIAN ); col_append_fstr( pinfo->cinfo, COL_INFO, ": count = %u", count ); offset += 1; proto_tree_add_item( applemidi_tree, hf_applemidi_padding, tvb, offset, 3, ENC_BIG_ENDIAN ); offset += 3; proto_tree_add_item( applemidi_tree, hf_applemidi_timestamp1, tvb, offset, 8, ENC_BIG_ENDIAN ); offset += 8; proto_tree_add_item( applemidi_tree, hf_applemidi_timestamp2, tvb, offset, 8, ENC_BIG_ENDIAN ); offset += 8; proto_tree_add_item( applemidi_tree, hf_applemidi_timestamp3, tvb, offset, 8, ENC_BIG_ENDIAN ); offset += 8; /* With the receiver feedback packet, the recipient can tell the sender up to what sequence * number in the RTP-stream the packets have been received; this can be used to shorten the * recovery-journal-section in the RTP-session */ } else if ( APPLEMIDI_COMMAND_RECEIVER_FEEDBACK == command ) { proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; ti = proto_tree_add_item( applemidi_tree, hf_applemidi_sequence_num, tvb, offset, 4, ENC_BIG_ENDIAN ); /* Apple includes a 32bit sequence-number, but the RTP-packet only specifies 16bit. * this subtree and subitem are added to be able to associate the sequence-number * here easier with the one specified in the corresponding RTP-packet */ applemidi_tree_seq_num = proto_item_add_subtree( ti, ett_applemidi_seq_num ); seq_num = tvb_get_ntohs( tvb, offset ); proto_tree_add_uint( applemidi_tree_seq_num, hf_applemidi_rtp_sequence_num, tvb, offset, 2, seq_num ); offset += 4; col_append_fstr( pinfo->cinfo, COL_INFO, ": seq = %u", seq_num ); /* With the bitrate receive limit packet, the recipient can tell the sender to limit the transmission to a certain bitrate. This is important if the peer is a gateway to a hardware-device that only supports a certain speed. Like the MIDI 1.0 DIN-cable MIDI-implementation which is limited to 31250. */ } else if ( APPLEMIDI_COMMAND_BITRATE_RECEIVE_LIMIT == command ) { proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; proto_tree_add_item( applemidi_tree, hf_applemidi_rtp_bitrate_limit, tvb, offset, 4, ENC_BIG_ENDIAN ); offset += 4; } /* If there is any remaining data (possibly because an unknown command was encountered), * we just dump it here */ len = tvb_length_remaining( tvb, offset ); if ( len > 0 ) { proto_tree_add_item( applemidi_tree, hf_applemidi_unknown_data, tvb, offset, len, ENC_NA ); } } }
/* Code to actually dissect the PAGP packets */ static void dissect_pagp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint32 raw_word; guint16 num_tlvs; guint16 tlv; guint16 len; guint16 ii; guint16 offset = PAGP_FIRST_TLV; guint8 raw_octet; guint8 flags; proto_tree *pagp_tree = NULL; proto_item *pagp_item, *len_item; proto_tree *tlv_tree; static const int * pagp_flags[] = { &hf_pagp_flags_slow_hello, &hf_pagp_flags_auto_mode, &hf_pagp_flags_consistent_state, NULL, }; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PAGP"); /* PAGP Protocol */ col_clear(pinfo->cinfo, COL_INFO); pinfo->current_proto = "PAGP"; raw_octet = tvb_get_guint8(tvb, PAGP_VERSION_NUMBER); if (tree) { pagp_item = proto_tree_add_protocol_format(tree, proto_pagp, tvb, 0, -1, "Port Aggregation Protocol"); pagp_tree = proto_item_add_subtree(pagp_item, ett_pagp); proto_tree_add_uint(pagp_tree, hf_pagp_version_number, tvb, PAGP_VERSION_NUMBER, 1, raw_octet); } col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(raw_octet, pdu_vers, "Unknown PDU version")); if (raw_octet == PAGP_FLUSH_PDU) { col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s", tvb_ether_to_str(tvb, PAGP_FLUSH_LOCAL_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_flush_local_device_id, tvb, PAGP_FLUSH_LOCAL_DEVICE_ID, 6, ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s", tvb_ether_to_str(tvb, PAGP_FLUSH_PARTNER_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_flush_partner_device_id, tvb, PAGP_FLUSH_PARTNER_DEVICE_ID, 6, ENC_NA); raw_word = tvb_get_ntohl(tvb, PAGP_FLUSH_TRANSACTION_ID); col_append_fstr(pinfo->cinfo, COL_INFO, "; Transaction ID: 0x%x ", raw_word); proto_tree_add_uint(pagp_tree, hf_pagp_flush_transaction_id, tvb, PAGP_FLUSH_TRANSACTION_ID, 4, raw_word); return; } /* Info PDU */ flags = tvb_get_guint8(tvb, PAGP_FLAGS); col_append_fstr(pinfo->cinfo, COL_INFO, "; Flags 0x%x", flags); proto_tree_add_bitmask(pagp_tree, tvb, PAGP_FLAGS, hf_pagp_flags, ett_pagp_flags, pagp_flags, ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s", tvb_ether_to_str(tvb, PAGP_LOCAL_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_local_device_id, tvb, PAGP_LOCAL_DEVICE_ID, 6, ENC_NA); if (tree) { proto_tree_add_item(pagp_tree, hf_pagp_local_learn_cap, tvb, PAGP_LOCAL_LEARN_CAP, 1, ENC_NA); proto_tree_add_item(pagp_tree, hf_pagp_local_port_priority, tvb, PAGP_LOCAL_PORT_PRIORITY, 1, ENC_NA); proto_tree_add_item(pagp_tree, hf_pagp_local_sent_port_ifindex, tvb, PAGP_LOCAL_SENT_PORT_IFINDEX, 4, ENC_BIG_ENDIAN); proto_tree_add_item(pagp_tree, hf_pagp_local_group_capability, tvb, PAGP_LOCAL_GROUP_CAPABILITY, 4, ENC_BIG_ENDIAN); proto_tree_add_item(pagp_tree, hf_pagp_local_group_ifindex, tvb, PAGP_LOCAL_GROUP_IFINDEX, 4, ENC_BIG_ENDIAN); } col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s", tvb_ether_to_str(tvb, PAGP_PARTNER_DEVICE_ID)); proto_tree_add_item(pagp_tree, hf_pagp_partner_device_id, tvb, PAGP_PARTNER_DEVICE_ID, 6, ENC_NA); proto_tree_add_item(pagp_tree, hf_pagp_partner_learn_cap, tvb, PAGP_PARTNER_LEARN_CAP, 1, ENC_NA); proto_tree_add_item(pagp_tree, hf_pagp_partner_port_priority, tvb, PAGP_PARTNER_PORT_PRIORITY, 1, ENC_NA); proto_tree_add_item(pagp_tree, hf_pagp_partner_sent_port_ifindex, tvb, PAGP_PARTNER_SENT_PORT_IFINDEX, 4, ENC_BIG_ENDIAN); proto_tree_add_item(pagp_tree, hf_pagp_partner_group_capability, tvb, PAGP_PARTNER_GROUP_CAPABILITY, 4, ENC_BIG_ENDIAN); proto_tree_add_item(pagp_tree, hf_pagp_partner_group_ifindex, tvb, PAGP_PARTNER_GROUP_IFINDEX, 4, ENC_BIG_ENDIAN); proto_tree_add_item(pagp_tree, hf_pagp_partner_count, tvb, PAGP_PARTNER_COUNT, 2, ENC_BIG_ENDIAN); num_tlvs = tvb_get_ntohs(tvb, PAGP_NUM_TLVS); proto_tree_add_uint(pagp_tree, hf_pagp_num_tlvs, tvb, PAGP_NUM_TLVS, 2, num_tlvs); /* dump TLV entries */ for ( ii = 0; ii < num_tlvs; ii++ ) { tlv = tvb_get_ntohs(tvb, offset); len = tvb_get_ntohs(tvb, offset + 2); tlv_tree = proto_tree_add_subtree_format(pagp_tree, tvb, offset, len, ett_pagp_tlvs, NULL, "TLV Entry #%d", ii+1); proto_tree_add_uint(tlv_tree, hf_pagp_tlv, tvb, offset, 2, tlv); len_item = proto_tree_add_uint(tlv_tree, hf_pagp_tlv_length, tvb, offset+2, 2, len); if ( len == 0 ) { expert_add_info_format(pinfo, len_item, &ei_pagp_tlv_length, "Unknown data - TLV len=0"); return; } if ( tvb_reported_length_remaining(tvb, offset) < len ) { expert_add_info_format(pinfo, len_item, &ei_pagp_tlv_length, "TLV length too large"); return; } switch (tlv) { case PAGP_TLV_DEVICE_NAME: proto_tree_add_item(tlv_tree, hf_pagp_tlv_device_name, tvb, offset+4, len-4, ENC_NA|ENC_ASCII); break; case PAGP_TLV_PORT_NAME: proto_tree_add_item(tlv_tree, hf_pagp_tlv_port_name, tvb, offset+4, len-4, ENC_NA|ENC_ASCII); break; case PAGP_TLV_AGPORT_MAC: proto_tree_add_item(tlv_tree, hf_pagp_tlv_agport_mac, tvb, offset+4, 6, ENC_NA); break; case PAGP_TLV_RESERVED: break; } offset += len; } }
static void dissect_smtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { struct smtp_proto_data *frame_data; proto_tree *smtp_tree = NULL; proto_tree *cmdresp_tree; proto_item *ti, *hidden_item; int offset = 0; int request = 0; conversation_t *conversation; struct smtp_session_state *session_state; const guchar *line, *linep, *lineend; guchar c; guint32 code; int linelen = 0; gint length_remaining; gboolean eom_seen = FALSE; gint next_offset; gint loffset = 0; gboolean is_continuation_line; int cmdlen; fragment_data *frag_msg = NULL; tvbuff_t *next_tvb; /* As there is no guarantee that we will only see frames in the * the SMTP conversation once, and that we will see them in * order - in Wireshark, the user could randomly click on frames * in the conversation in any order in which they choose - we * have to store information with each frame indicating whether * it contains commands or data or an EOM indication. * * XXX - what about frames that contain *both*? TCP is a * byte-stream protocol, and there are no guarantees that * TCP segment boundaries will correspond to SMTP commands * or EOM indications. * * We only need that for the client->server stream; responses * are easy to manage. * * If we have per frame data, use that, else, we must be on the first * pass, so we figure it out on the first pass. */ /* * Find the conversation for this. */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (conversation == NULL) { /* No conversation, create one */ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } /* * Is there a request structure attached to this conversation? */ session_state = conversation_get_proto_data(conversation, proto_smtp); if (!session_state) { /* * No - create one and attach it. */ session_state = se_alloc(sizeof(struct smtp_session_state)); session_state->smtp_state = READING_CMDS; session_state->crlf_seen = FALSE; session_state->data_seen = FALSE; session_state->msg_read_len = 0; session_state->msg_tot_len = 0; session_state->msg_last = TRUE; session_state->last_nontls_frame = 0; conversation_add_proto_data(conversation, proto_smtp, session_state); } /* Are we doing TLS? * FIXME In my understanding of RFC 2487 client and server can send SMTP cmds * after a rejected TLS negotiation */ if (session_state->last_nontls_frame != 0 && pinfo->fd->num > session_state->last_nontls_frame) { guint16 save_can_desegment; /* This is TLS, not raw SMTP. TLS can desegment */ save_can_desegment = pinfo->can_desegment; pinfo->can_desegment = pinfo->saved_can_desegment; call_dissector(ssl_handle, tvb, pinfo, tree); pinfo->can_desegment = save_can_desegment; return; } /* Is this a request or a response? */ request = pinfo->destport == pinfo->match_port; /* * Is there any data attached to this frame? */ frame_data = p_get_proto_data(pinfo->fd, proto_smtp); if (!frame_data) { /* * No frame data. */ if(request) { /* * Create a frame data structure and attach it to the packet. */ frame_data = se_alloc0(sizeof(struct smtp_proto_data)); frame_data->conversation_id = conversation->index; frame_data->more_frags = TRUE; p_add_proto_data(pinfo->fd, proto_smtp, frame_data); } /* * Get the first line from the buffer. * * Note that "tvb_find_line_end()" will, if it doesn't return * -1, return a value that is not longer than what's in the buffer, * and "tvb_find_line_end()" will always return a value that is not * longer than what's in the buffer, so the "tvb_get_ptr()" call * won't throw an exception. */ loffset = offset; while (tvb_offset_exists(tvb, loffset)) { linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, smtp_desegment && pinfo->can_desegment); if (linelen == -1) { if (offset == loffset) { /* * We didn't find a line ending, and we're doing desegmentation; * tell the TCP dissector where the data for this message starts * in the data it handed us, and tell it we need more bytes */ pinfo->desegment_offset = loffset; pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return; } else { linelen = tvb_length_remaining(tvb, loffset); next_offset = loffset + linelen; } } line = tvb_get_ptr(tvb, loffset, linelen); /* * Check whether or not this packet is an end of message packet * We should look for CRLF.CRLF and they may be split. * We have to keep in mind that we may see what we want on * two passes through here ... */ if (session_state->smtp_state == READING_DATA) { /* * The order of these is important ... We want to avoid * cases where there is a CRLF at the end of a packet and a * .CRLF at the begining of the same packet. */ if ((session_state->crlf_seen && tvb_strneql(tvb, loffset, ".\r\n", 3) == 0) || tvb_strneql(tvb, loffset, "\r\n.\r\n", 5) == 0) eom_seen = TRUE; length_remaining = tvb_length_remaining(tvb, loffset); if (length_remaining == tvb_reported_length_remaining(tvb, loffset) && tvb_strneql(tvb, loffset + length_remaining - 2, "\r\n", 2) == 0) session_state->crlf_seen = TRUE; else session_state->crlf_seen = FALSE; } /* * OK, Check if we have seen a DATA request. We do it here for * simplicity, but we have to be careful below. */ if (request) { if (session_state->smtp_state == READING_DATA) { /* * This is message data. */ if (eom_seen) { /* Seen the EOM */ /* * EOM. * Everything that comes after it is commands. */ frame_data->pdu_type = SMTP_PDU_EOM; session_state->smtp_state = READING_CMDS; break; } else { /* * Message data with no EOM. */ frame_data->pdu_type = SMTP_PDU_MESSAGE; if (session_state->msg_tot_len > 0) { /* * We are handling a BDAT message. * Check if we have reached end of the data chunk. */ session_state->msg_read_len += tvb_length_remaining(tvb, loffset); if (session_state->msg_read_len == session_state->msg_tot_len) { /* * We have reached end of BDAT data chunk. * Everything that comes after this is commands. */ session_state->smtp_state = READING_CMDS; if (session_state->msg_last) { /* * We have found the LAST data chunk. * The message can now be reassembled. */ frame_data->more_frags = FALSE; } break; /* no need to go through the remaining lines */ } } } } else { /* * This is commands - unless the capture started in the * middle of a session, and we're in the middle of data. * * Commands are not necessarily 4 characters; look * for a space or the end of the line to see where * the putative command ends. */ linep = line; lineend = line + linelen; while (linep < lineend && (c = *linep) != ' ') linep++; cmdlen = (int)(linep - line); if (line_is_smtp_command(line, cmdlen)) { if (g_ascii_strncasecmp(line, "DATA", 4) == 0) { /* * DATA command. * This is a command, but everything that comes after it, * until an EOM, is data. */ frame_data->pdu_type = SMTP_PDU_CMD; session_state->smtp_state = READING_DATA; session_state->data_seen = TRUE; } else if (g_ascii_strncasecmp(line, "BDAT", 4) == 0) { /* * BDAT command. * This is a command, but everything that comes after it, * until given length is received, is data. */ guint32 msg_len; msg_len = strtoul (line+5, NULL, 10); frame_data->pdu_type = SMTP_PDU_CMD; session_state->data_seen = TRUE; session_state->msg_tot_len += msg_len; if (msg_len == 0) { /* No data to read, next will be a command */ session_state->smtp_state = READING_CMDS; } else { session_state->smtp_state = READING_DATA; } if (g_ascii_strncasecmp(line+linelen-4, "LAST", 4) == 0) { /* * This is the last data chunk. */ session_state->msg_last = TRUE; if (msg_len == 0) { /* * No more data to expect. * The message can now be reassembled. */ frame_data->more_frags = FALSE; } } else { session_state->msg_last = FALSE; } } else if (g_ascii_strncasecmp(line, "STARTTLS", 8) == 0) { /* * STARTTLS command. * This is a command, but if the response is 220, * everything after the response is TLS. */ session_state->smtp_state = AWAITING_STARTTLS_RESPONSE; frame_data->pdu_type = SMTP_PDU_CMD; } else { /* * Regular command. */ frame_data->pdu_type = SMTP_PDU_CMD; } } else { /* * Assume it's message data. */ frame_data->pdu_type = session_state->data_seen ? SMTP_PDU_MESSAGE : SMTP_PDU_CMD; } } } /* * Step past this line. */ loffset = next_offset; } } /* * From here, we simply add items to the tree and info to the info * fields ... */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMTP"); if (check_col(pinfo->cinfo, COL_INFO)) { /* Add the appropriate type here */ col_clear(pinfo->cinfo, COL_INFO); /* * If it is a request, we have to look things up, otherwise, just * display the right things */ if (request) { /* We must have frame_data here ... */ switch (frame_data->pdu_type) { case SMTP_PDU_MESSAGE: length_remaining = tvb_length_remaining(tvb, offset); col_set_str(pinfo->cinfo, COL_INFO, smtp_data_desegment ? "C: DATA fragment" : "C: Message Body"); col_append_fstr(pinfo->cinfo, COL_INFO, ", %d byte%s", length_remaining, plurality (length_remaining, "", "s")); break; case SMTP_PDU_EOM: col_set_str(pinfo->cinfo, COL_INFO, "C: ."); break; case SMTP_PDU_CMD: loffset = offset; while (tvb_offset_exists(tvb, loffset)) { /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, loffset, linelen); if(loffset == offset) col_append_fstr(pinfo->cinfo, COL_INFO, "C: %s", format_text(line, linelen)); else { col_append_fstr(pinfo->cinfo, COL_INFO, " | %s", format_text(line, linelen)); } loffset = next_offset; } break; } } else { loffset = offset; while (tvb_offset_exists(tvb, loffset)) { /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, loffset, linelen); if (loffset == offset) col_append_fstr(pinfo->cinfo, COL_INFO, "S: %s", format_text(line, linelen)); else { col_append_fstr(pinfo->cinfo, COL_INFO, " | %s", format_text(line, linelen)); } loffset = next_offset; } } } if (tree) { /* Build the tree info ... */ ti = proto_tree_add_item(tree, proto_smtp, tvb, offset, -1, FALSE); smtp_tree = proto_item_add_subtree(ti, ett_smtp); } if (request) { /* * Check out whether or not we can see a command in there ... * What we are looking for is not data_seen and the word DATA * and not eom_seen. * * We will see DATA and session_state->data_seen when we process the * tree view after we have seen a DATA packet when processing * the packet list pane. * * On the first pass, we will not have any info on the packets * On second and subsequent passes, we will. */ switch (frame_data->pdu_type) { case SMTP_PDU_MESSAGE: if (smtp_data_desegment) { frag_msg = fragment_add_seq_next(tvb, 0, pinfo, frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table, tvb_length(tvb), frame_data->more_frags); } else { /* * Message body. * Put its lines into the protocol tree, a line at a time. */ dissect_smtp_data(tvb, offset, smtp_tree); } break; case SMTP_PDU_EOM: /* * End-of-message-body indicator. * * XXX - what about stuff after the first line? * Unlikely, as the client should wait for a response to the * DATA command this terminates before sending another * request, but we should probably handle it. */ proto_tree_add_text(smtp_tree, tvb, offset, linelen, "C: ."); if (smtp_data_desegment) { /* add final data segment */ if (loffset) fragment_add_seq_next(tvb, 0, pinfo, frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table, loffset, frame_data->more_frags); /* terminate the desegmentation */ frag_msg = fragment_end_seq_next (pinfo, frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table); } break; case SMTP_PDU_CMD: /* * Command. * * XXX - what about stuff after the first line? * Unlikely, as the client should wait for a response to the * previous command before sending another request, but we * should probably handle it. */ loffset = offset; while (tvb_offset_exists(tvb, loffset)) { /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE); if (linelen >= 4) cmdlen = 4; else cmdlen = linelen; hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_req, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); /* * Put the command line into the protocol tree. */ ti = proto_tree_add_text(smtp_tree, tvb, loffset, next_offset - loffset, "Command: %s", tvb_format_text(tvb, loffset, next_offset - loffset)); cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp); proto_tree_add_item(cmdresp_tree, hf_smtp_req_command, tvb, loffset, cmdlen, FALSE); if (linelen > 5) { proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb, loffset + 5, linelen - 5, FALSE); } if (smtp_data_desegment && !frame_data->more_frags) { /* terminate the desegmentation */ frag_msg = fragment_end_seq_next (pinfo, frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table); } /* * Step past this line. */ loffset = next_offset; } } if (smtp_data_desegment) { next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled DATA", frag_msg, &smtp_data_frag_items, NULL, smtp_tree); if (next_tvb) { /* XXX: this is presumptious - we may have negotiated something else */ if (imf_handle) { call_dissector(imf_handle, next_tvb, pinfo, tree); } else { /* * Message body. * Put its lines into the protocol tree, a line at a time. */ dissect_smtp_data(tvb, offset, smtp_tree); } pinfo->fragmented = FALSE; } else { pinfo->fragmented = TRUE; } } } else { /* * Process the response, a line at a time, until we hit a line * that doesn't have a continuation indication on it. */ if (tree) { hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_rsp, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } while (tvb_offset_exists(tvb, offset)) { /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); if (tree) { /* * Put it into the protocol tree. */ ti = proto_tree_add_text(smtp_tree, tvb, offset, next_offset - offset, "Response: %s", tvb_format_text(tvb, offset, next_offset - offset)); cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp); } else cmdresp_tree = NULL; /* * Is it a continuation line? */ is_continuation_line = (linelen >= 4 && tvb_get_guint8(tvb, offset + 3) == '-'); line = tvb_get_ptr(tvb, offset, linelen); if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1]) && isdigit(line[2])) { /* * We have a 3-digit response code. */ code = (line[0] - '0')*100 + (line[1] - '0')*10 + (line[2] - '0'); /* * If we're awaiting the response to a STARTTLS code, this * is it - if it's 220, all subsequent traffic will * be TLS, otherwise we're back to boring old SMTP. */ if (session_state->smtp_state == AWAITING_STARTTLS_RESPONSE) { if (code == 220) { /* This is the last non-TLS frame. */ session_state->last_nontls_frame = pinfo->fd->num; session_state->smtp_state = READING_DATA; } else session_state->smtp_state = READING_CMDS; } if (tree) { /* * Put the response code and parameters into the protocol tree. */ proto_tree_add_uint(cmdresp_tree, hf_smtp_rsp_code, tvb, offset, 3, code); if (linelen >= 4) { proto_tree_add_item(cmdresp_tree, hf_smtp_rsp_parameter, tvb, offset + 4, linelen - 4, FALSE); } } } /* * Step past this line. */ offset = next_offset; /* * If it's not a continuation line, quit. */ /* if (!is_continuation_line) break; */ } } }
static void dissect_packetlogger (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *packetlogger_tree = NULL; tvbuff_t *next_tvb; proto_item *ti = NULL; guint8 pl_type; gint len; col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME); col_clear (pinfo->cinfo, COL_INFO); ti = proto_tree_add_item (tree, proto_packetlogger, tvb, 0, -1, FALSE); packetlogger_tree = proto_item_add_subtree (ti, ett_packetlogger); pl_type = tvb_get_guint8 (tvb, 0); proto_tree_add_item (packetlogger_tree, hf_type, tvb, 0, 1, FALSE); proto_item_append_text (ti, " %s", val_to_str (pl_type, type_vals, "Unknown 0x%02x")); len = tvb_length_remaining (tvb, 1); next_tvb = tvb_new_subset (tvb, 1, len, len); if (pl_type <= PKT_RECV_ACL_DATA) { /* HCI H1 packages */ switch (pl_type) { case PKT_HCI_COMMAND: pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_COMMAND; pinfo->pseudo_header->bthci.sent = P2P_DIR_SENT; pinfo->p2p_dir = P2P_DIR_SENT; break; case PKT_HCI_EVENT: pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_EVENT; pinfo->pseudo_header->bthci.sent = P2P_DIR_RECV; pinfo->p2p_dir = P2P_DIR_RECV; break; case PKT_SENT_ACL_DATA: pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_ACL; pinfo->pseudo_header->bthci.sent = P2P_DIR_SENT; pinfo->p2p_dir = P2P_DIR_SENT; break; case PKT_RECV_ACL_DATA: pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_ACL; pinfo->pseudo_header->bthci.sent = P2P_DIR_RECV; pinfo->p2p_dir = P2P_DIR_RECV; break; default: pinfo->pseudo_header->bthci.channel = pl_type; pinfo->pseudo_header->bthci.sent = P2P_DIR_UNKNOWN; pinfo->p2p_dir = P2P_DIR_UNKNOWN; break; } proto_item_set_len (ti, 1); col_add_fstr (pinfo->cinfo, COL_INFO, "%s", val_to_str(pl_type, type_vals, "Unknown 0x%02x")); if (!dissector_try_port (hci_h1_table, pinfo->pseudo_header->bthci.channel, next_tvb, pinfo, tree)) { call_dissector (data_handle, next_tvb, pinfo, tree); } } else { /* PacketLogger data */ switch (pl_type) { case PKT_INFO: case PKT_NEW_CONTROLLER: proto_tree_add_item (packetlogger_tree, hf_info, next_tvb, 0, len, FALSE); col_set_str (pinfo->cinfo, COL_INFO, tvb_format_stringzpad_wsp (next_tvb, 0, len)); break; default: call_dissector (data_handle, next_tvb, pinfo, tree); col_add_fstr (pinfo->cinfo, COL_INFO, "Unknown 0x%02x", pl_type); break; } } }
// content format static void dissect_radiohead_router(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { // your variable definitions go here int offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "rhrouter"); col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%d", tvb_length(tvb) ); // Clear out stuff in the info column col_clear(pinfo->cinfo, COL_INFO); if (tree) { // in case that someone wants to know some details of our protocol // spawn a subtree and cut the sequence in readable parts proto_item *ti = NULL; proto_item *pi = NULL; proto_tree *radiohead_tree = NULL; guint8 dest, source, hops, id, flags; guint length; gchar* info; ti = proto_tree_add_item(tree, proto_radiohead_router, tvb, 0 /*start*/, -1 /*end*/, encoding); radiohead_tree = proto_item_add_subtree(ti, ett_radiohead_router); length = tvb_length(tvb); proto_tree_add_item(radiohead_tree, hf_radiohead_router_dest, tvb, offset, 1, encoding); dest = tvb_get_guint8(tvb, offset); offset++; proto_tree_add_item(radiohead_tree, hf_radiohead_router_source, tvb, offset, 1, encoding); source = tvb_get_guint8(tvb, offset); offset++; proto_tree_add_item(radiohead_tree, hf_radiohead_router_hops, tvb, offset, 1, encoding); hops = tvb_get_guint8(tvb, offset); offset++; proto_tree_add_item(radiohead_tree, hf_radiohead_router_id, tvb, offset, 1, encoding); id = tvb_get_guint8(tvb, offset); offset++; proto_tree_add_item(radiohead_tree, hf_radiohead_router_flags, tvb, offset, 1, encoding); flags = tvb_get_guint8(tvb, offset); offset++; info = radiohead_router_buildColInfo( pinfo, hops, id, flags); col_add_str(pinfo->cinfo, COL_INFO, info); proto_item_append_text(ti, " - %s", info); col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "%d", source); col_add_fstr(pinfo->cinfo, COL_DEF_DST, "%d", dest); if (tvb_length_remaining(tvb, offset /*TODO: bits or bytes?*/) > 0) { tvbuff_t* tvb_next; tvb_next = tvb_new_subset(tvb, offset/*start*/, -1 /*to end*/, -1/*reported length*/ ); add_new_data_source(pinfo, tvb_next, "RadioHead Router Payload Data"); // The radiohead header contains no indication of the payload type. Therefore we // pass it on to a list of heuristic dissectors for radiohead payloads, or display // it as data when none found. if (!dissector_try_heuristic(heur_subdissector_list, tvb_next, pinfo, tree, NULL)) { call_dissector(data_handle, tvb_next, pinfo, tree); } } } }
static void dissect_jpeg( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) { proto_item *ti = NULL; proto_tree *jpeg_tree = NULL; proto_tree *main_hdr_tree = NULL; proto_tree *restart_hdr_tree = NULL; proto_tree *qtable_hdr_tree = NULL; guint32 fragment_offset = 0; guint16 len = 0; guint8 type = 0; guint8 q = 0; gint h = 0; gint w = 0; unsigned int offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "JPEG"); col_set_str(pinfo->cinfo, COL_INFO, "JPEG message"); if ( tree ) { ti = proto_tree_add_item( tree, proto_jpeg, tvb, offset, -1, FALSE ); jpeg_tree = proto_item_add_subtree( ti, ett_jpeg ); ti = proto_tree_add_item(jpeg_tree, hf_rtp_jpeg_main_hdr, tvb, offset, 8, FALSE); main_hdr_tree = proto_item_add_subtree(ti, ett_jpeg); proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_ts, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_offs, tvb, offset, 3, FALSE); fragment_offset = tvb_get_ntoh24(tvb, offset); offset += 3; proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_type, tvb, offset, 1, FALSE); type = tvb_get_guint8(tvb, offset); offset += 1; proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_q, tvb, offset, 1, FALSE); q = tvb_get_guint8(tvb, offset); offset += 1; w = tvb_get_guint8(tvb, offset) * 8; proto_tree_add_uint(main_hdr_tree, hf_rtp_jpeg_main_hdr_width, tvb, offset, 1, w); offset += 1; h = tvb_get_guint8(tvb, offset) * 8; proto_tree_add_uint(main_hdr_tree, hf_rtp_jpeg_main_hdr_height, tvb, offset, 1, h); offset += 1; if (type >= 64 && type <= 127) { ti = proto_tree_add_item(jpeg_tree, hf_rtp_jpeg_restart_hdr, tvb, offset, 4, FALSE); restart_hdr_tree = proto_item_add_subtree(ti, ett_jpeg); proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_interval, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_f, tvb, offset, 2, FALSE); proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_l, tvb, offset, 2, FALSE); proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_count, tvb, offset, 2, FALSE); offset += 2; } if (q >= 128 && fragment_offset == 0) { ti = proto_tree_add_item(jpeg_tree, hf_rtp_jpeg_qtable_hdr, tvb, offset, -1, FALSE); qtable_hdr_tree = proto_item_add_subtree(ti, ett_jpeg); proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_mbz, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_prec, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_length, tvb, offset, 2, FALSE); len = tvb_get_ntohs(tvb, offset); offset += 2; if (len > 0) { proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_data, tvb, offset, len, FALSE); offset += len; } proto_item_set_len(ti, len + 4); } /* The rest of the packet is the JPEG data */ proto_tree_add_item( jpeg_tree, hf_rtp_jpeg_payload, tvb, offset, -1, FALSE ); } }
static void dissect_nntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { const gchar *type; proto_tree *nntp_tree; proto_item *ti; gint offset = 0; gint next_offset; int linelen; if (pinfo->match_uint == pinfo->destport) type = "Request"; else type = "Response"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NNTP"); if (check_col(pinfo->cinfo, COL_INFO)) { /* * Put the first line from the buffer into the summary * (but leave out the line terminator). * * Note that "tvb_find_line_end()" will return a value that * is not longer than what's in the buffer, so the * "tvb_get_ptr()" call won't throw an exception. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", type, tvb_format_text(tvb, offset, linelen)); } if (tree) { ti = proto_tree_add_item(tree, proto_nntp, tvb, offset, -1, ENC_NA); nntp_tree = proto_item_add_subtree(ti, ett_nntp); if (pinfo->match_uint == pinfo->destport) { ti = proto_tree_add_boolean(nntp_tree, hf_nntp_request, tvb, 0, 0, TRUE); } else { ti = proto_tree_add_boolean(nntp_tree, hf_nntp_response, tvb, 0, 0, TRUE); } PROTO_ITEM_SET_HIDDEN(ti); /* * Show the request or response as text, a line at a time. * XXX - for requests, we could display the stuff after the * first line, if any, based on what the request was, and * for responses, we could display it based on what the * matching request was, although the latter requires us to * know what the matching request was.... */ while (tvb_offset_exists(tvb, offset)) { /* * Find the end of the line. */ tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); /* * Put this line. */ proto_tree_add_text(nntp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; } } }
static void dissect_swift(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "swift"); /* Clear out stuff in the info column */ col_clear(pinfo->cinfo,COL_INFO); if (tree) { /* we are being asked for details */ proto_item *ti; ti = proto_tree_add_item(tree, proto_swift, tvb, 0, -1, FALSE); proto_tree *swift_tree; swift_tree = proto_item_add_subtree(ti, ett_swift); /* All messages start with the receiving channel, so we can pull it out here */ proto_tree_add_item(swift_tree, hf_swift_receiving_channel, tvb, offset, 4, FALSE); offset += 4; /* Loop until there is nothing left to read in the packet */ while(tvb_bytes_exist(tvb, offset, 1)) { guint8 message_type; guint dat_len; message_type = tvb_get_guint8(tvb, offset); proto_tree_add_item(swift_tree, hf_swift_message_type, tvb, offset, 1, FALSE); offset += 1; /* Add message type to the info column */ if(offset > 5) { col_append_fstr(pinfo->cinfo, COL_INFO, ", "); } col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(message_type, message_type_names, "Unknown (0x%02x)")); /* Add it to the dissection window as well */ proto_item_append_text(ti, ", %s", val_to_str(message_type, message_type_names, "Unknown (0x%02x)")); switch(message_type) { case 0: /* Handshake */ proto_tree_add_item(swift_tree, hf_swift_handshake_channel, tvb, offset, 4, FALSE); offset += 4; break; case 1: /* Data */ proto_tree_add_item(swift_tree, hf_swift_data_bin_id, tvb, offset, 4, FALSE); offset += 4; /* We assume that the data field comprises the rest of this packet */ dat_len = tvb_length(tvb) - offset; proto_tree_add_item(swift_tree, hf_swift_data_payload, tvb, offset, dat_len, FALSE); offset += dat_len; break; case 2: /* Ack */ proto_tree_add_item(swift_tree, hf_swift_ack_bin_id, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(swift_tree, hf_swift_ack_timestamp, tvb, offset, 8, FALSE); offset += 8; break; case 3: /* Have */ proto_tree_add_item(swift_tree, hf_swift_have_bin_id, tvb, offset, 4, FALSE); offset += 4; break; case 4: /* Hash */ proto_tree_add_item(swift_tree, hf_swift_hash_bin_id, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(swift_tree, hf_swift_hash_value, tvb, offset, 20, FALSE); offset += 20; break; case 5: /* PEX+ */ proto_tree_add_item(swift_tree, hf_swift_pexplus_ip, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(swift_tree, hf_swift_pexplus_port, tvb, offset, 2, FALSE); offset += 2; break; case 6: /* PEX- */ proto_tree_add_item(swift_tree, hf_swift_pexminus_ip, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(swift_tree, hf_swift_pexminus_port, tvb, offset, 2, FALSE); offset += 2; break; case 7: /* Signed Hash */ proto_tree_add_item(swift_tree, hf_swift_signed_hash_bin_id, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(swift_tree, hf_swift_signed_hash_value, tvb, offset, 20, FALSE); offset += 20; /* It is not entirely clear what size the public key will be, so we allow any size For this to work, we must assume there aren't any more messages in the packet */ dat_len = tvb_length(tvb) - offset; proto_tree_add_item(swift_tree, hf_swift_signed_hash_signature, tvb, offset, dat_len, FALSE); offset += dat_len; break; case 8: /* Hint */ proto_tree_add_item(swift_tree, hf_swift_hint_bin_id, tvb, offset, 4, FALSE); offset += 4; break; case 9: /* SWIFT_MSGTYPE_RCVD */ break; case 10: /* SWIFT_MESSAGE_COUNT */ break; default: break; } } /* If the offset is still 4 here, the message is a keep-alive */ if(offset == 4) { col_append_fstr(pinfo->cinfo, COL_INFO, "Keep-Alive"); proto_item_append_text(ti, ", Keep-Alive"); } } }
static int dissect_cmp_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { tvbuff_t *next_tvb; guint32 pdu_len; guint8 pdu_type; nstime_t ts; proto_item *item=NULL; proto_item *ti=NULL; proto_tree *tree=NULL; proto_tree *tcptrans_tree=NULL; asn1_ctx_t asn1_ctx; int offset=0; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); col_set_str(pinfo->cinfo, COL_PROTOCOL, "CMP"); col_set_str(pinfo->cinfo, COL_INFO, "PKIXCMP"); if(parent_tree){ item=proto_tree_add_item(parent_tree, proto_cmp, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_cmp); } pdu_len=tvb_get_ntohl(tvb, 0); pdu_type=tvb_get_guint8(tvb, 4); if (pdu_type < 10) { /* RFC2510 TCP transport */ ti = proto_tree_add_item(tree, proto_cmp, tvb, offset, 5, ENC_NA); tcptrans_tree = proto_item_add_subtree(ti, ett_cmp); proto_tree_add_item(tree, hf_cmp_tcptrans_len, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_cmp_tcptrans_type, tvb, offset++, 1, ENC_BIG_ENDIAN); } else { /* post RFC2510 TCP transport - the former "type" field is now "version" */ ti = proto_tree_add_text(tree, tvb, offset, 7, "TCP transport"); tcptrans_tree = proto_item_add_subtree(ti, ett_cmp); pdu_type=tvb_get_guint8(tvb, 6); proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_len, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans10_version, tvb, offset++, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans10_flags, tvb, offset++, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_type, tvb, offset++, 1, ENC_BIG_ENDIAN); } col_add_str (pinfo->cinfo, COL_INFO, val_to_str (pdu_type, cmp_pdu_types, "0x%x")); switch(pdu_type){ case CMP_TYPE_PKIMSG: next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), pdu_len); dissect_cmp_pdu(next_tvb, tree, &asn1_ctx); offset += tvb_length_remaining(tvb, offset); break; case CMP_TYPE_POLLREP: proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_poll_ref, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; ts.secs = tvb_get_ntohl(tvb, 4); ts.nsecs = 0; proto_tree_add_time(tcptrans_tree, hf_cmp_tcptrans_ttcb, tvb, offset, 4, &ts); offset += 4; break; case CMP_TYPE_POLLREQ: proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_poll_ref, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case CMP_TYPE_NEGPOLLREP: break; case CMP_TYPE_PARTIALMSGREP: proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_next_poll_ref, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; ts.secs = tvb_get_ntohl(tvb, 4); ts.nsecs = 0; proto_tree_add_time(tcptrans_tree, hf_cmp_tcptrans_ttcb, tvb, offset, 4, &ts); offset += 4; next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), pdu_len); dissect_cmp_pdu(next_tvb, tree, &asn1_ctx); offset += tvb_length_remaining(tvb, offset); break; case CMP_TYPE_FINALMSGREP: next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), pdu_len); dissect_cmp_pdu(next_tvb, tree, &asn1_ctx); offset += tvb_length_remaining(tvb, offset); break; case CMP_TYPE_ERRORMSGREP: /*XXX to be added*/ break; } return offset; }
static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *clnp_tree = NULL; proto_item *ti, *ti_len = NULL, *ti_pdu_len = NULL, *ti_tot_len = NULL; guint8 cnf_proto_id; guint8 cnf_hdr_len; guint8 cnf_vers; guint8 cnf_ttl; guint8 cnf_type; char flag_string[6+1]; const char *pdu_type_string; proto_tree *type_tree; guint16 segment_length; guint16 du_id = 0; guint16 segment_offset = 0; guint16 total_length; guint16 cnf_cksum; cksum_status_t cksum_status; int offset; guchar src_len, dst_len, nsel, opt_len = 0; const guint8 *dst_addr, *src_addr; guint next_length; proto_tree *discpdu_tree; gboolean save_in_error_pkt; fragment_data *fd_head; tvbuff_t *next_tvb; gboolean update_col_info = TRUE; gboolean save_fragmented; col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP"); col_clear(pinfo->cinfo, COL_INFO); cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID); if (cnf_proto_id == NLPID_NULL) { col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset"); if (tree) { ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA); clnp_tree = proto_item_add_subtree(ti, ett_clnp); proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1, cnf_proto_id, "Inactive subset"); } next_tvb = tvb_new_subset_remaining(tvb, 1); if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0) call_dissector(data_handle,tvb, pinfo, tree); return; } /* return if version not known */ cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS); if (cnf_vers != ISO8473_V1) { call_dissector(data_handle,tvb, pinfo, tree); return; } /* fixed part decoding */ cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN); if (tree) { ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA); clnp_tree = proto_item_add_subtree(ti, ett_clnp); proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1, cnf_proto_id); ti_len = proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1, cnf_hdr_len); } if (cnf_hdr_len < FIXED_PART_LEN) { /* Header length is less than the length of the fixed part of the header. */ expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Header length value < minimum length %u", FIXED_PART_LEN); return; } if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1, cnf_vers); cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL); proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1, cnf_ttl, "Holding Time : %u (%u.%u secs)", cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5); } cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE); pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals, "Unknown (0x%02x)"); flag_string[0] = '\0'; if (cnf_type & CNF_SEG_OK) g_strlcat(flag_string, "S ", 7); if (cnf_type & CNF_MORE_SEGS) g_strlcat(flag_string, "M ", 7); if (cnf_type & CNF_ERR_OK) g_strlcat(flag_string, "E ", 7); if (tree) { ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1, cnf_type, "PDU Type : 0x%02x (%s%s)", cnf_type, flag_string, pdu_type_string); type_tree = proto_item_add_subtree(ti, ett_clnp_type); proto_tree_add_item(type_tree, hf_clnp_cnf_segmentation, tvb, P_CLNP_TYPE, 1, ENC_NA); proto_tree_add_item(type_tree, hf_clnp_cnf_more_segments, tvb, P_CLNP_TYPE, 1, ENC_NA); proto_tree_add_item(type_tree, hf_clnp_cnf_report_error, tvb, P_CLNP_TYPE, 1, ENC_NA); proto_tree_add_item(type_tree, hf_clnp_cnf_type, tvb, P_CLNP_TYPE, 1, ENC_NA); } /* If we don't have the full header - i.e., not enough to see the segmentation part and determine whether this datagram is segmented or not - set the Info column now; we'll get an exception before we set it otherwise. */ if (tvb_length(tvb) < cnf_hdr_len) { col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); } segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN); if (tree) { ti_pdu_len = proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2, segment_length); } if (segment_length < cnf_hdr_len) { /* Segment length is less than the header length. */ expert_add_info_format(pinfo, ti_pdu_len, PI_MALFORMED, PI_ERROR, "PDU length < header length %u", cnf_hdr_len); return; } cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM); cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum); if (tree) { switch (cksum_status) { default: /* * No checksum present, or not enough of the header present to * checksum it. */ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "Checksum : 0x%04x", cnf_cksum); break; case CKSUM_OK: /* * Checksum is correct. */ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "Checksum : 0x%04x (correct)", cnf_cksum); break; case CKSUM_NOT_OK: /* * Checksum is not correct. */ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "Checksum : 0x%04x (incorrect)", cnf_cksum); break; } } /* tree */ opt_len = cnf_hdr_len; opt_len -= FIXED_PART_LEN; /* Fixed part of Header */ /* address part */ offset = P_CLNP_ADDRESS_PART; if (opt_len < 1) { /* Header length is less than the minimum value in CLNP, including the destination address length. */ expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Header length value < %u", FIXED_PART_LEN + 1); return; } dst_len = tvb_get_guint8(tvb, offset); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1, dst_len); } offset += 1; opt_len -= 1; if (opt_len < dst_len) { /* Header length is less than the minimum value, including the destination address length and the destination address. */ expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len); return; } dst_addr = tvb_get_ptr(tvb, offset, dst_len); nsel = tvb_get_guint8(tvb, offset + dst_len - 1); SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr); SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr); if (tree) { proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset, dst_len, dst_addr, " DA : %s", print_nsap_net(dst_addr, dst_len)); } offset += dst_len; opt_len -= dst_len; if (opt_len < 1) { /* Header length is less than the minimum value, including the destination address length, the destination address, and the source address length. */ expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1); return; } src_len = tvb_get_guint8(tvb, offset); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb, offset, 1, src_len); } offset += 1; opt_len -= 1; if (opt_len < src_len) { /* Header length is less than the minimum value, including the destination address length, the destination address, the source address length, and the source address. */ expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1 + src_len); return; } src_addr = tvb_get_ptr(tvb, offset, src_len); SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr); SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr); if (tree) { proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb, offset, src_len, src_addr, " SA : %s", print_nsap_net(src_addr, src_len)); } offset += src_len; opt_len -= src_len; /* Segmentation Part */ if (cnf_type & CNF_SEG_OK) { if (opt_len < SEGMENTATION_PART_LEN) { /* Header length is less than the minimum value, including the destination address length, the destination address, the source address length, the source address, and the segmentation part. */ expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN); return; } du_id = tvb_get_ntohs(tvb, offset); if (tree) { proto_tree_add_text(clnp_tree, tvb, offset, 2, "Data unit identifier: %06u", du_id); } segment_offset = tvb_get_ntohs(tvb, offset + 2); if (tree) { proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2, "Segment offset : %6u", segment_offset); } total_length = tvb_get_ntohs(tvb, offset + 4); if (tree) { ti_tot_len = proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2, "Total length : %6u", total_length); } if (total_length < segment_length) { /* Reassembled length is less than the length of this segment. */ expert_add_info_format(pinfo, ti_tot_len, PI_MALFORMED, PI_ERROR, "Total length < segment length %u", segment_length); return; } offset += SEGMENTATION_PART_LEN; opt_len -= SEGMENTATION_PART_LEN; } if (tree) { dissect_osi_options(opt_len, tvb, offset, clnp_tree); } offset += opt_len; /* If clnp_reassemble is on, this is a segment, we have all the * data in the segment, and the checksum is valid, then just add the * segment to the hashtable. */ save_fragmented = pinfo->fragmented; if (clnp_reassemble && (cnf_type & CNF_SEG_OK) && ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) && tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) && segment_length > cnf_hdr_len && cksum_status != CKSUM_NOT_OK) { fd_head = fragment_add_check(&clnp_reassembly_table, tvb, offset, pinfo, du_id, NULL, segment_offset, segment_length - cnf_hdr_len, cnf_type & CNF_MORE_SEGS); next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP", fd_head, &clnp_frag_items, &update_col_info, clnp_tree); } else { /* If this is the first segment, dissect its contents, otherwise just show it as a segment. XXX - if we eventually don't save the reassembled contents of all segmented datagrams, we may want to always reassemble. */ if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) { /* Not the first segment - don't dissect it. */ next_tvb = NULL; } else { /* First segment, or not segmented. Dissect what we have here. */ /* Get a tvbuff for the payload. Set its length to the segment length, and flag it as a fragment, so going past the end reports FragmentBoundsError, i.e. "there's data missing because this isn't reassembled", not ReportedBoundsError, i.e. "the dissector ran past the end of the packet, so the packet must not have been constructed properly". */ next_tvb = tvb_new_subset_length(tvb, offset, segment_length - cnf_hdr_len); tvb_set_fragment(next_tvb); /* * If this is the first segment, but not the only segment, * tell the next protocol that. */ if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS)) pinfo->fragmented = TRUE; else pinfo->fragmented = FALSE; } } if (next_tvb == NULL) { /* Just show this as a segment. */ col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)", pdu_type_string, flag_string, segment_offset); /* As we haven't reassembled anything, we haven't changed "pi", so we don't have to restore it. */ call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); pinfo->fragmented = save_fragmented; return; } if (tvb_offset_exists(tvb, offset)) { switch (cnf_type & CNF_TYPE) { case DT_NPDU: case MD_NPDU: /* Continue with COTP if any data. XXX - if this isn't the first Derived PDU of a segmented Initial PDU, skip that? */ if (nsel == (guchar)tp_nsap_selector || always_decode_transport) { if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) { pinfo->fragmented = save_fragmented; return; /* yes, it appears to be COTP or CLTP */ } } if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb, pinfo, tree, NULL)) { pinfo->fragmented = save_fragmented; return; /* yes, it appears to be one of the protocols in the heuristic list */ } break; case ER_NPDU: /* The payload is the header and "none, some, or all of the data part of the discarded PDU", i.e. it's like an ICMP error; dissect it as a CLNP PDU. */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); next_length = tvb_length_remaining(tvb, offset); if (next_length != 0) { /* We have payload; dissect it. */ ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length, "Discarded PDU"); discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu); /* Save the current value of the "we're inside an error packet" flag, and set that flag; subdissectors may treat packets that are the payload of error packets differently from "real" packets. */ save_in_error_pkt = pinfo->flags.in_error_pkt; pinfo->flags.in_error_pkt = TRUE; call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree); /* Restore the "we're inside an error packet" flag. */ pinfo->flags.in_error_pkt = save_in_error_pkt; } pinfo->fragmented = save_fragmented; return; /* we're done with this PDU */ case ERQ_NPDU: case ERP_NPDU: /* XXX - dissect this */ break; } } col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); call_dissector(data_handle,next_tvb, pinfo, tree); pinfo->fragmented = save_fragmented; } /* dissect_clnp */
static void dissect_nflog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { const int start_tlv_offset = 4; proto_tree *nflog_tree = NULL; proto_item *ti; int offset = 0; tvbuff_t *next_tvb = NULL; int aftype; int enc; guint16 (*val16_get)(tvbuff_t *, int); col_set_str(pinfo->cinfo, COL_PROTOCOL, "NFLOG"); col_clear(pinfo->cinfo, COL_INFO); aftype = tvb_get_guint8(tvb, 0); enc = nflog_tvb_byte_order(tvb, start_tlv_offset); switch (enc) { case ENC_LITTLE_ENDIAN: val16_get = tvb_get_letohs; break; case ENC_BIG_ENDIAN: default: val16_get = tvb_get_ntohs; break; } /* Header */ if (proto_field_is_referenced(tree, proto_nflog)) { ti = proto_tree_add_item(tree, proto_nflog, tvb, 0, -1, ENC_NA); nflog_tree = proto_item_add_subtree(ti, ett_nflog); proto_tree_add_item(nflog_tree, hf_nflog_family, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(nflog_tree, hf_nflog_version, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(nflog_tree, hf_nflog_resid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ti = proto_tree_add_uint(nflog_tree, hf_nflog_encoding, tvb, offset, tvb_length_remaining(tvb, offset), enc); PROTO_ITEM_SET_GENERATED(ti); } offset = start_tlv_offset; /* TLVs */ while (tvb_length_remaining(tvb, offset) >= 4) { guint16 tlv_len = val16_get(tvb, offset + 0); guint16 tlv_type; guint16 value_len; proto_tree *tlv_tree; /* malformed */ if (tlv_len < 4) return; value_len = tlv_len - 4; tlv_type = (val16_get(tvb, offset + 2) & 0x7fff); if (nflog_tree) { gboolean handled = FALSE; ti = proto_tree_add_bytes_format(nflog_tree, hf_nflog_tlv, tvb, offset, tlv_len, NULL, "TLV Type: %s (%u), Length: %u", val_to_str_const(tlv_type, nflog_tlv_vals, "Unknown"), tlv_type, tlv_len); tlv_tree = proto_item_add_subtree(ti, ett_nflog_tlv); proto_tree_add_item(tlv_tree, hf_nflog_tlv_length, tvb, offset + 0, 2, enc); proto_tree_add_item(tlv_tree, hf_nflog_tlv_type, tvb, offset + 2, 2, enc); switch (tlv_type) { case WS_NFULA_PAYLOAD: handled = TRUE; break; case WS_NFULA_PREFIX: if (value_len >= 1) { proto_tree_add_item(tlv_tree, hf_nflog_tlv_prefix, tvb, offset + 4, value_len, ENC_NA); handled = TRUE; } break; case WS_NFULA_UID: if (value_len == 4) { proto_tree_add_item(tlv_tree, hf_nflog_tlv_uid, tvb, offset + 4, value_len, ENC_BIG_ENDIAN); handled = TRUE; } break; case WS_NFULA_GID: if (value_len == 4) { proto_tree_add_item(tlv_tree, hf_nflog_tlv_gid, tvb, offset + 4, value_len, ENC_BIG_ENDIAN); handled = TRUE; } break; case WS_NFULA_TIMESTAMP: if (value_len == 16) { nstime_t ts; ts.secs = tvb_get_ntoh64(tvb, offset + 4); /* XXX - add an "expert info" warning if this is >= 10^9? */ ts.nsecs = (int)tvb_get_ntoh64(tvb, offset + 12); proto_tree_add_time(tlv_tree, hf_nflog_tlv_timestamp, tvb, offset + 4, value_len, &ts); handled = TRUE; } break; } if (!handled) proto_tree_add_item(tlv_tree, hf_nflog_tlv_unknown, tvb, offset + 4, value_len, ENC_NA); } if (tlv_type == WS_NFULA_PAYLOAD) next_tvb = tvb_new_subset(tvb, offset + 4, value_len, value_len); offset += ((tlv_len + 3) & ~3); /* next TLV aligned to 4B */ } if (next_tvb) { switch (aftype) { case LINUX_AF_INET: call_dissector(ip_handle, next_tvb, pinfo, tree); break; case LINUX_AF_INET6: call_dissector(ip6_handle, next_tvb, pinfo, tree); break; default: call_dissector(data_handle, next_tvb, pinfo, tree); break; } } }
static void dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *prism_tree = NULL, *prism_did_tree = NULL; proto_item *ti = NULL, *ti_did = NULL; tvbuff_t *next_tvb; int offset; guint32 msgcode, msglen, did; guint16 status; guint8 *devname_p; offset = 0; did = 0; /* handle the AVS header */ msgcode = tvb_get_ntohl(tvb, offset); if ((msgcode == WLANCAP_MAGIC_COOKIE_V1) || (msgcode == WLANCAP_MAGIC_COOKIE_V2)) { call_dissector(wlancap_handle, tvb, pinfo, tree); return; } /* * If we don't see a valid message type, assume the Prism or AVS * header was omitted and just hand off to the 802.11 dissector; * at least one capture has AVS headers on some packets and no * radio headers on others (incoming vs. outgoing?). * * XXX - check for both byte orders and use that to determine * the byte order of the fields in the Prism header? */ msgcode = tvb_get_letohl(tvb, offset); if ((msgcode != PRISM_TYPE1_MSGCODE) && (msgcode != PRISM_TYPE2_MSGCODE)) { call_dissector(ieee80211_handle, tvb, pinfo, tree); return; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism"); col_clear(pinfo->cinfo, COL_INFO); if(tree) { ti = proto_tree_add_item(tree, proto_prism, tvb, 0, 144, ENC_NA); prism_tree = proto_item_add_subtree(ti, ett_prism); } /* Message Code */ if(tree) { proto_tree_add_item(prism_tree, hf_ieee80211_prism_msgcode, tvb, offset, 4, ENC_LITTLE_ENDIAN); } msgcode = tvb_get_letohl(tvb, offset); offset += 4; /* Message Length */ if(tree) { proto_tree_add_item(prism_tree, hf_ieee80211_prism_msglen, tvb, offset, 4, ENC_LITTLE_ENDIAN); } msglen = tvb_get_letohl(tvb, offset); offset += 4; /* Device Name */ if(tree) { proto_tree_add_item(prism_tree, hf_ieee80211_prism_devname, tvb, offset, 16, ENC_ASCII|ENC_NA); } devname_p = tvb_get_ephemeral_string(tvb, offset, 16); offset += 16; col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %s, Message 0x%x, Length %d", devname_p, msgcode, msglen); while(offset < PRISM_HEADER_LENGTH) { /* DID */ if(tree) { ti_did = proto_tree_add_item(prism_tree, hf_ieee80211_prism_did, tvb, offset, 12, ENC_NA); prism_did_tree = proto_item_add_subtree(ti_did, ett_prism_did); proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_type, tvb, offset, 4, ENC_LITTLE_ENDIAN); did = tvb_get_letohl(tvb, offset); proto_item_append_text(ti_did, " %s", val_to_str(did, prism_did_vals, "Unknown %x") ); } offset += 4; /* Status */ status = tvb_get_letohs(tvb, offset); if(tree) { proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_status, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; /* Length */ if(tree) { proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; /* Data, if present... */ if (status == 0) { switch(did){ case PRISM_TYPE1_HOSTTIME: case PRISM_TYPE2_HOSTTIME: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_hosttime, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_MACTIME: case PRISM_TYPE2_MACTIME: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_mactime, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_CHANNEL: case PRISM_TYPE2_CHANNEL: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_channel, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) ); } col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", tvb_get_letohl(tvb, offset)); break; case PRISM_TYPE1_RSSI: case PRISM_TYPE2_RSSI: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rssi, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", tvb_get_letohl(tvb, offset)); break; case PRISM_TYPE1_SQ: case PRISM_TYPE2_SQ: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sq, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_SIGNAL: case PRISM_TYPE2_SIGNAL: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_signal, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_NOISE: case PRISM_TYPE2_NOISE: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_noise, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_RATE: case PRISM_TYPE2_RATE: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rate, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %s Mb/s", prism_rate_return(tvb_get_letohl(tvb, offset)) ); } col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%s", prism_rate_return(tvb_get_letohl(tvb, offset)) ); break; case PRISM_TYPE1_ISTX: case PRISM_TYPE2_ISTX: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_istx, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_FRMLEN: case PRISM_TYPE2_FRMLEN: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_frmlen, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) ); } break; default: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_unknown, tvb, offset, 4, ENC_LITTLE_ENDIAN); } break; } } offset += 4; } /* dissect the 802.11 header next */ next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(ieee80211_handle, next_tvb, pinfo, tree); }
/* Code to actually dissect the packets */ static void dissect_brdwlk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti, *hidden_item; proto_tree *brdwlk_tree = NULL; tvbuff_t *next_tvb; guint8 error, eof, sof; int hdrlen = 2, offset = 0; gint len, reported_len, plen; guint16 pkt_cnt; gboolean dropped_packets; fc_data_t fc_data; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Boardwalk"); col_clear(pinfo->cinfo, COL_INFO); sof = (tvb_get_guint8(tvb, offset) & 0xF0) >> 4; fc_data.sof_eof = 0; if ((sof == FCM_DELIM_SOFI3) || (sof == FCM_DELIM_SOFI2) || (sof == FCM_DELIM_SOFI1) || (sof == FCM_DELIM_SOFI4)) { fc_data.sof_eof = FC_DATA_SOF_FIRST_FRAME; } else if (sof == FCM_DELIM_SOFF) { fc_data.sof_eof = FC_DATA_SOF_SOFF; } if (tree) { ti = proto_tree_add_protocol_format(tree, proto_brdwlk, tvb, 0, hdrlen, "Boardwalk"); brdwlk_tree = proto_item_add_subtree(ti, ett_brdwlk); proto_tree_add_item(brdwlk_tree, hf_brdwlk_sof, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(brdwlk_tree, hf_brdwlk_vsan, tvb, offset, 2, ENC_BIG_ENDIAN); } /* Locate EOF which is the last 4 bytes of the frame */ len = tvb_length_remaining(tvb, hdrlen); reported_len = tvb_reported_length_remaining(tvb, hdrlen); if (reported_len < 4) { /* * This packet is claimed not to even have enough data for * a 4-byte EOF. * Don't try to process the EOF. */ ; } else if (len < reported_len) { /* * This packet is claimed to have enough data for a 4-byte EOF, * but we didn't capture all of the packet. * Slice off the 4-byte EOF from the reported length, and trim * the captured length so it's no more than the reported length; * that will slice off what of the EOF, if any, is in the * captured length. */ reported_len -= 4; if (len > reported_len) len = reported_len; } else { /* * We have the entire packet, and it includes a 4-byte EOF. * Slice it off, and put it into the tree if we're building * a tree. */ len -= 4; reported_len -= 4; offset = tvb_reported_length(tvb) - 4; pkt_cnt = tvb_get_ntohs(tvb, offset); if (tree) { proto_tree_add_uint(brdwlk_tree, hf_brdwlk_pktcnt, tvb, offset, 2, pkt_cnt); } dropped_packets = FALSE; if (pinfo->fd->flags.visited) { /* * This isn't the first pass, so we can't use the global * "packet_count" variable to determine whether there were * any dropped frames or not. * We therefore attach a non-null pointer as frame data to * any frame preceded by dropped packets. */ if (p_get_proto_data(wmem_file_scope(), pinfo, proto_brdwlk, 0) != NULL) dropped_packets = TRUE; } else { /* * This is the first pass, so we have to use the global * "packet_count" variable to determine whether there were * any dropped frames or not. * * XXX - can there be more than one stream of packets, so that * we can't just use a global variable? */ if (pkt_cnt != packet_count + 1) { if (!first_pkt && (pkt_cnt != 0 || (packet_count != BRDWLK_MAX_PACKET_CNT))) { dropped_packets = TRUE; /* * Mark this frame as having been preceded by dropped * packets. (The data we use as the frame data doesn't * matter - it just matters that it's non-null.) */ p_add_proto_data(wmem_file_scope(), pinfo, proto_brdwlk, 0, &packet_count); } } } if (tree) { hidden_item = proto_tree_add_boolean(brdwlk_tree, hf_brdwlk_drop, tvb, offset, 0, dropped_packets); PROTO_ITEM_SET_HIDDEN(hidden_item); } packet_count = pkt_cnt; error=tvb_get_guint8(tvb, offset+2); dissect_brdwlk_err(brdwlk_tree, tvb, offset+2); eof = tvb_get_guint8(tvb, offset+3); if (eof != FCM_DELIM_EOFN) { fc_data.sof_eof |= FC_DATA_EOF_LAST_FRAME; } else if (eof != FCM_DELIM_EOFT) { fc_data.sof_eof |= FC_DATA_EOF_INVALID; } if (tree) { proto_tree_add_item(brdwlk_tree, hf_brdwlk_eof, tvb, offset+3, 1, ENC_BIG_ENDIAN); } if ((error & BRDWLK_HAS_PLEN) && tree) { /* In newer Boardwalks, if this bit is set, the actual frame length * is also provided. This length is the size between SOF & EOF * including FC CRC. */ plen = tvb_get_ntohl(tvb, offset-4); plen *= 4; proto_tree_add_uint(brdwlk_tree, hf_brdwlk_plen, tvb, offset-4, 4, plen); #if 0 /* XXX - this would throw an exception if it would increase * the reported length. */ if (error & BRDWLK_TRUNCATED_BIT) { tvb_set_reported_length(tvb, plen); } #endif } } fc_data.ethertype = ETHERTYPE_BRDWALK; next_tvb = tvb_new_subset(tvb, 2, len, reported_len); call_dissector_with_data(fc_dissector_handle, next_tvb, pinfo, tree, &fc_data); }
static void dissect_ax25_nol3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree ) { proto_item *ti; proto_tree *ax25_nol3_tree; char *info_buffer; int offset; tvbuff_t *next_tvb = NULL; guint8 dti = 0; gboolean dissected; info_buffer = (char *)wmem_alloc( wmem_packet_scope(), STRLEN ); info_buffer[0] = '\0'; col_set_str( pinfo->cinfo, COL_PROTOCOL, "AX.25-NoL3"); col_clear( pinfo->cinfo, COL_INFO); offset = 0; g_snprintf( info_buffer, STRLEN, "Text" ); if ( gPREF_APRS ) { dti = tvb_get_guint8( tvb, offset ); if ( isaprs( dti ) ) g_snprintf( info_buffer, STRLEN, "APRS" ); } if ( gPREF_DX ) { if ( tvb_get_guint8( tvb, offset ) == 'D' && tvb_get_guint8( tvb, offset + 1 ) == 'X' ) g_snprintf( info_buffer, STRLEN, "DX cluster" ); } col_add_str( pinfo->cinfo, COL_INFO, info_buffer ); /* Call sub-dissectors here */ if ( parent_tree ) { /* create display subtree for the protocol */ ti = proto_tree_add_protocol_format( parent_tree, proto_ax25_nol3, tvb, 0, -1, "AX.25 No Layer 3 - (%s)", info_buffer ); ax25_nol3_tree = proto_item_add_subtree( ti, ett_ax25_nol3 ); next_tvb = tvb_new_subset_remaining(tvb, offset); dissected = FALSE; if ( gPREF_APRS ) { if ( isaprs( dti ) ) { dissected = TRUE; call_dissector( aprs_handle , next_tvb, pinfo, ax25_nol3_tree ); } } if ( gPREF_DX ) { if ( tvb_get_guint8( tvb, offset ) == 'D' && tvb_get_guint8( tvb, offset + 1 ) == 'X' ) { dissected = TRUE; dissect_dx( next_tvb, pinfo, ax25_nol3_tree ); } } if ( ! dissected ) call_dissector( default_handle , next_tvb, pinfo, ax25_nol3_tree ); } }
/* dissect_main * * main dissect function that calls the other functions listed above as necessary */ static void dissect_mvrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtrees and manage them */ proto_item *ti, *msg_ti, *attr_list_ti, *vect_attr_ti, *first_value_ti; proto_tree *mvrp_tree, *msg_tree, *attr_list_tree, *vect_attr_tree, *first_value_tree; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MRP-MVRP"); col_set_str(pinfo->cinfo, COL_INFO, "Multiple VLAN Registration Protocol"); if (tree) { guint8 attribute_type; guint8 attribute_length; guint16 number_of_values; guint offset = 0; int vect_attr_len; int msg_offset; /* Use when handling multiple messages. This points to current msg being decoded. */ int vect_offset; /* Use when handling multiple vector attributes. This points to the current vector attribute being decoded. */ ti = proto_tree_add_item(tree, proto_mvrp, tvb, 0, -1, ENC_NA); mvrp_tree = proto_item_add_subtree(ti, ett_mvrp); proto_tree_add_item(mvrp_tree, hf_mvrp_proto_id, tvb, MVRP_PROTOCOL_VERSION_OFFSET, 1, ENC_BIG_ENDIAN); /* MVRP supports multiple MRP Messages per frame. Handle those Messages in * the following while() loop. You will know you are at the end of the list * of messages when the EndMark (0x0000) is encountered instead of an * Attribute Type and Attribute Length (guaranteed to not be 0x0000). */ msg_offset = 0; while (tvb_get_ntohs(tvb, MVRP_ATTRIBUTE_TYPE_OFFSET + msg_offset) != MVRP_END_MARK) { attribute_type = tvb_get_guint8(tvb, MVRP_ATTRIBUTE_TYPE_OFFSET + msg_offset); attribute_length = tvb_get_guint8(tvb, MVRP_ATTRIBUTE_LENGTH_OFFSET + msg_offset); /* MVRP Message is a group of fields * * Contains AttributeType (1 byte) * + AttributeLength (1 byte) * + AttributeList (AttributeListLength bytes) * bytes of data */ msg_ti = proto_tree_add_item(mvrp_tree, hf_mvrp_message, tvb, MVRP_MESSAGE_GROUP_OFFSET + msg_offset, -1, ENC_NA); msg_tree = proto_item_add_subtree(msg_ti, ett_msg); /* Append AttributeType description to the end of the "Message" heading */ proto_item_append_text(msg_tree, ": %s (%d)", val_to_str_const(attribute_type, attribute_type_vals, "<Unknown>"), attribute_type); dissect_mvrp_common1(msg_tree, tvb, msg_offset); /* MVRP AttributeList is a group of fields * * Contains AttributeListLength bytes of data NOT */ attr_list_ti = proto_tree_add_item(msg_tree, hf_mvrp_attribute_list, tvb, MVRP_ATTRIBUTE_LIST_GROUP_OFFSET + msg_offset, -1, ENC_NA); attr_list_tree = proto_item_add_subtree(attr_list_ti, ett_attr_list); /* MVRP supports multiple MRP Vector Attributes per Attribute List. Handle those * Vector Attributes in the following while() loop. You will know you are at the * end of the list of Vector Attributes when the EndMark (0x0000) is encountered * instead of a Vector Header (guaranteed to not be 0x0000). */ vect_offset = 0; while (tvb_get_ntohs(tvb, MVRP_VECTOR_HEADER_OFFSET + msg_offset + vect_offset) != MVRP_END_MARK) { /* MVRP VectorAttribute is a group of fields * * Contains VectorHeader (2 bytes) * + FirstValue (AttributeLength bytes) * + VectorThreePacked (NumberOfValues @ 3/vector bytes) * + VectorFourPacked (NumberOfValues @ 4/vector bytes only for Listener attributes) * bytes of data */ number_of_values = tvb_get_ntohs(tvb, MVRP_NUMBER_OF_VALUES_OFFSET + msg_offset + vect_offset) & MVRP_NUMBER_OF_VALUES_MASK; vect_attr_len = 2 + attribute_length + (number_of_values + 2)/3; /* stores 3 values per byte */ vect_attr_ti = proto_tree_add_item(attr_list_tree, hf_mvrp_vector_attribute, tvb, MVRP_VECTOR_ATTRIBUTE_GROUP_OFFSET + msg_offset + vect_offset, vect_attr_len, ENC_NA); vect_attr_tree = proto_item_add_subtree(vect_attr_ti, ett_vect_attr); dissect_mvrp_common2(vect_attr_tree, tvb, msg_offset + vect_offset); if (attribute_type == MVRP_ATTRIBUTE_TYPE_VID) { /* MVRP VLAN ID FirstValue is a group of fields * * Contains VID (2 bytes) * bytes of data */ first_value_ti = proto_tree_add_item(vect_attr_tree, hf_mvrp_first_value, tvb, MVRP_FIRST_VALUE_GROUP_OFFSET + msg_offset + vect_offset, attribute_length, ENC_NA); first_value_tree = proto_item_add_subtree(first_value_ti, ett_first_value); /* Add VLAN components to First Value tree */ proto_tree_add_item(first_value_tree, hf_mvrp_vid, tvb, MVRP_FIRST_VALUE_GROUP_OFFSET + msg_offset + vect_offset, 2, ENC_BIG_ENDIAN); /* Decode three packed events. */ offset = dissect_mvrp_three_packed_event(vect_attr_tree, tvb, MVRP_VID_THREE_PACKED_OFFSET + msg_offset + vect_offset, number_of_values); } vect_offset += vect_attr_len; /* Move to next Vector Attribute, if there is one */ } /* Multiple VectorAttribute while() */ proto_tree_add_item(attr_list_tree, hf_mvrp_end_mark, tvb, offset, 2, ENC_NA); /* VectorAttribute EndMark */ proto_item_set_len(attr_list_ti, vect_offset); /*without an endmark*/ msg_offset += vect_offset + 2; /* + endmark; Move to next Message, if there is one */ proto_item_set_len(msg_ti, vect_offset + 2); /*length of message*/ } /* Multiple Message while() */ proto_tree_add_item(mvrp_tree, hf_mvrp_end_mark, tvb, offset+2, 2, ENC_NA); /* Message EndMark */ } }
/* * Dissect ASCII TPKT-encapsulated data in a TCP stream. */ void dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, dissector_handle_t subdissector_handle) { proto_item *ti = NULL; proto_tree *tpkt_tree = NULL; volatile int offset = 0; int length_remaining; int data_len; volatile int mgcp_packet_len = 0; int mgcp_version = 0; int mgcp_reserved = 0; volatile int length; tvbuff_t *volatile next_tvb; const char *saved_proto; guint8 string[4]; /* * If we're reassembling segmented TPKT PDUs, empty the COL_INFO * column, so subdissectors can append information * without having to worry about emptying the column. * * We use "col_add_str()" because the subdissector * might be appending information to the column, in * which case we'd have to zero the buffer out explicitly * anyway. */ if (tpkt_desegment) col_set_str(pinfo->cinfo, COL_INFO, ""); while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * Is the first byte of this putative TPKT header * a valid TPKT version number, i.e. 3? */ if (tvb_get_guint8(tvb, offset) != 48) { /* * No, so don't assume this is a TPKT header; * we might be in the middle of TPKT data, * so don't get the length and don't try to * do reassembly. */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, -1, ENC_NA); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA); } return; } length_remaining = tvb_length_remaining(tvb, offset); /* * Get the length from the TPKT header. */ tvb_memcpy(tvb, (guint8 *)string, offset, 2); mgcp_version = parseVersionText(string); tvb_memcpy(tvb, (guint8 *)string, offset +2, 2); mgcp_reserved = parseReservedText(string); tvb_memcpy(tvb, (guint8 *)string, offset + 4, 4); mgcp_packet_len = parseLengthText(string); data_len = mgcp_packet_len; /* * Dissect the TPKT header. * Save and restore "pinfo->current_proto". */ saved_proto = pinfo->current_proto; pinfo->current_proto = "TPKT"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); /* * Don't add the TPKT header information if we're * reassembling segmented TPKT PDUs or if this * PDU isn't reassembled. * * XXX - the first is so that subdissectors can append * information without getting TPKT stuff in the middle; * why the second? */ if (!tpkt_desegment && !pinfo->fragmented) { col_add_fstr(pinfo->cinfo, COL_INFO, "TPKT Data length = %u", data_len); } if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, 8, ENC_NA); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_item_set_text(ti, "TPKT"); /* Version */ proto_tree_add_uint(tpkt_tree, hf_tpkt_version, tvb, offset, 2, mgcp_version); /* Reserved octet*/ proto_tree_add_uint(tpkt_tree, hf_tpkt_reserved, tvb, offset + 2, 2, mgcp_reserved); /* Length */ proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb, offset + 4, 4, mgcp_packet_len); } pinfo->current_proto = saved_proto; /* Skip the TPKT header. */ offset += TEXT_LAYER_LENGTH; length = length_remaining - TEXT_LAYER_LENGTH; if (length > data_len) length = data_len; next_tvb = tvb_new_subset(tvb, offset,length, data_len); /* * Call the subdissector. * * If it gets an error that means there's no point in * dissecting any more TPKT messages, rethrow the * exception in question. * * If it gets any other error, report it and continue, as that * means that TPKT message got an error, but that doesn't mean * we should stop dissecting TPKT messages within this frame * or chunk of reassembled data. */ TRY { call_dissector(subdissector_handle, next_tvb, pinfo, tree); } CATCH_NONFATAL_ERRORS { show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; /* * Skip the payload. */ offset += data_len; } }
static void dissect_1722(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti = NULL; proto_tree *ieee1722_tree = NULL; proto_tree *audio_tree = NULL; proto_tree *sample_tree = NULL; gint offset = 0; guint16 datalen = 0; guint8 dbs = 0; guint8 subtype = 0; int i, j; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE1722"); col_set_str(pinfo->cinfo, COL_INFO, "AVB Transportation Protocol"); if (tree) { ti = proto_tree_add_item(tree, proto_1722, tvb, 0, -1, FALSE); ieee1722_tree = proto_item_add_subtree(ti, ett_1722); /* Add the CD and Subtype fields * CD field is 1 bit * Subtype field is 7 bits */ proto_tree_add_item(ieee1722_tree, hf_1722_cdfield, tvb, IEEE_1722_CD_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_subtype, tvb, IEEE_1722_CD_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_svfield, tvb, IEEE_1722_VERSION_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_verfield, tvb, IEEE_1722_VERSION_OFFSET, 1, FALSE); /* Version field ends the common AVTPDU. Now parse the specfic packet type */ subtype = tvb_get_guint8(tvb, IEEE_1722_CD_OFFSET); subtype &= 0x7F; // fprintf(stderr, "subtype: %d\n", subtype); switch (subtype) { case 0x7A: { if (dissector_try_uint(avb_dissector_table, 0x7A, tvb, pinfo, tree)) { return; } } case 0x7B: { if (dissector_try_uint(avb_dissector_table, 0x7B, tvb, pinfo, tree)) { return; } } case 0x7C: { if (dissector_try_uint(avb_dissector_table, 0x7C, tvb, pinfo, tree)) { return; } } default: break; } proto_tree_add_item(ieee1722_tree, hf_1722_mrfield, tvb, IEEE_1722_VERSION_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_gvfield, tvb, IEEE_1722_VERSION_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_tvfield, tvb, IEEE_1722_VERSION_OFFSET, 1, FALSE); /* Add the rest of the packet fields */ proto_tree_add_item(ieee1722_tree, hf_1722_seqnum, tvb, IEEE_1722_SEQ_NUM_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_tufield, tvb, IEEE_1722_TU_FIELD_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_stream_id, tvb, IEEE_1722_STREAM_ID_OFFSET, 8, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_avbtp_timestamp, tvb, IEEE_1722_TIMESTAMP_OFFSET, 4, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_gateway_info, tvb, IEEE_1722_GW_INFO_OFFSET, 4, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_packet_data_length, tvb, IEEE_1722_PKT_DATA_LENGTH_OFFSET, 2, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_tag, tvb, IEEE_1722_TAG_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_channel, tvb, IEEE_1722_TAG_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_tcode, tvb, IEEE_1722_TCODE_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_sy, tvb, IEEE_1722_TCODE_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_sid, tvb, IEEE_1722_SID_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_dbs, tvb, IEEE_1722_DBS_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_fn, tvb, IEEE_1722_FN_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_qpc, tvb, IEEE_1722_FN_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_sph, tvb, IEEE_1722_FN_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_dbc, tvb, IEEE_1722_DBC_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_fmt, tvb, IEEE_1722_FMT_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_fdf, tvb, IEEE_1722_FDF_OFFSET, 1, FALSE); proto_tree_add_item(ieee1722_tree, hf_1722_syt, tvb, IEEE_1722_SYT_OFFSET, 2, FALSE); /* Calculate the remaining size by subtracting the CIP header size from the value in the packet data length field */ datalen = tvb_get_ntohs(tvb, IEEE_1722_PKT_DATA_LENGTH_OFFSET); datalen -= IEEE_1722_CIP_HEADER_SIZE; /* Make the Audio sample tree. */ ti = proto_tree_add_item(ieee1722_tree, hf_1722_data, tvb, IEEE_1722_DATA_OFFSET, datalen, FALSE); audio_tree = proto_item_add_subtree(ti, ett_1722_audio); /* Need to get the offset of where the audio data starts */ offset = IEEE_1722_DATA_OFFSET; dbs = tvb_get_guint8(tvb, IEEE_1722_DBS_OFFSET); /* If the DBS is ever 0 for whatever reason, then just add the rest of packet as unknown */ if(dbs == 0) proto_tree_add_text(ieee1722_tree, tvb, IEEE_1722_DATA_OFFSET, datalen, "Incorrect DBS"); else { /* Loop through all samples and add them to the audio tree. */ for (j = 0; j < (datalen / (dbs*4)); j++) { ti = proto_tree_add_text(audio_tree, tvb, offset, 1, "Sample %d", j+1); sample_tree = proto_item_add_subtree(ti, ett_1722_sample); for (i = 0; i < dbs; i++) { proto_tree_add_item(sample_tree, hf_1722_label, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(sample_tree, hf_1722_sample, tvb, offset, 3, FALSE); offset += 3; } } } } }