static void dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int fcs_len) { proto_item *ti = NULL; eth_hdr *ehdr; gboolean is_802_2; proto_tree *fh_tree = NULL; const guint8 *src_addr, *dst_addr; static eth_hdr ehdrs[4]; static int ehdr_num=0; proto_tree *tree; proto_item *addr_item; proto_tree *addr_tree=NULL; ehdr_num++; if(ehdr_num>=4){ ehdr_num=0; } ehdr=&ehdrs[ehdr_num]; tree=parent_tree; col_set_str(pinfo->cinfo, COL_PROTOCOL, "Ethernet"); src_addr=tvb_get_ptr(tvb, 6, 6); SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src_addr); SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src_addr); SET_ADDRESS(&ehdr->src, AT_ETHER, 6, src_addr); dst_addr=tvb_get_ptr(tvb, 0, 6); SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst_addr); SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst_addr); SET_ADDRESS(&ehdr->dst, AT_ETHER, 6, dst_addr); ehdr->type = tvb_get_ntohs(tvb, 12); tap_queue_packet(eth_tap, pinfo, ehdr); /* * In case the packet is a non-Ethernet packet inside * Ethernet framing, allow heuristic dissectors to take * a first look before we assume that it's actually an * Ethernet packet. */ if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, parent_tree, NULL)) return; if (ehdr->type <= IEEE_802_3_MAX_LEN) { /* Oh, yuck. Cisco ISL frames require special interpretation of the destination address field; fortunately, they can be recognized by checking the first 5 octets of the destination address, which are 01-00-0C-00-00 for ISL frames. */ if ((tvb_get_guint8(tvb, 0) == 0x01 || tvb_get_guint8(tvb, 0) == 0x0C) && tvb_get_guint8(tvb, 1) == 0x00 && tvb_get_guint8(tvb, 2) == 0x0C && tvb_get_guint8(tvb, 3) == 0x00 && tvb_get_guint8(tvb, 4) == 0x00) { dissect_isl(tvb, pinfo, parent_tree, fcs_len); return; } } /* * If the type/length field is <= the maximum 802.3 length, * and is not zero, this is an 802.3 frame, and it's a length * field; it might be an Novell "raw 802.3" frame, with no * 802.2 LLC header, or it might be a frame with an 802.2 LLC * header. * * If the type/length field is >= the minimum Ethernet II length, * this is an Ethernet II frame, and it's a type field. * * If the type/length field is > maximum 802.3 length and < minimum * Ethernet II length, then this is an invalid packet. * * If the type/length field is zero (ETHERTYPE_UNK), this is * a frame used internally by the Cisco MDS switch to contain * Fibre Channel ("Vegas"). We treat that as an Ethernet II * frame; the dissector for those frames registers itself with * an ethernet type of ETHERTYPE_UNK. */ if (ehdr->type > IEEE_802_3_MAX_LEN && ehdr->type < ETHERNET_II_MIN_LEN) { tvbuff_t *next_tvb; col_add_fstr(pinfo->cinfo, COL_INFO, "Ethernet Unknown: Invalid length/type: 0x%04x (%d)", ehdr->type, ehdr->type); ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE, "Ethernet Unknown, Src: %s (%s), Dst: %s (%s)", get_ether_name(src_addr), ether_to_str(src_addr), get_ether_name(dst_addr), ether_to_str(dst_addr)); fh_tree = proto_item_add_subtree(ti, ett_ether); addr_item = proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr); if (addr_item) addr_tree = proto_item_add_subtree(addr_item, ett_addr); proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 0, 6, dst_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 0, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 0, 3, ENC_BIG_ENDIAN); addr_item = proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr); if (addr_item) addr_tree = proto_item_add_subtree(addr_item, ett_addr); proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 6, 6, src_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 6, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 6, 3, ENC_BIG_ENDIAN); ti = proto_tree_add_item(fh_tree, hf_eth_invalid_lentype, tvb, 12, 2, ENC_BIG_ENDIAN); expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Invalid length/type: 0x%04x (%d)", ehdr->type, ehdr->type); next_tvb = tvb_new_subset_remaining(tvb, 14); call_dissector(data_handle, next_tvb, pinfo, parent_tree); return; } if (ehdr->type <= IEEE_802_3_MAX_LEN && ehdr->type != ETHERTYPE_UNK) { is_802_2 = check_is_802_2(tvb, fcs_len); col_add_fstr(pinfo->cinfo, COL_INFO, "IEEE 802.3 Ethernet %s", (is_802_2 ? "" : "Raw ")); if (tree) { ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE, "IEEE 802.3 Ethernet %s", (is_802_2 ? "" : "Raw ")); fh_tree = proto_item_add_subtree(ti, ett_ieee8023); } /* if IP is not referenced from any filters we dont need to worry about generating any tree items. We must do this after we created the actual protocol above so that proto hier stat still works though. */ if(!proto_field_is_referenced(parent_tree, proto_eth)){ tree=NULL; fh_tree=NULL; } addr_item=proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr); if(addr_item){ addr_tree = proto_item_add_subtree(addr_item, ett_addr); } proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 0, 6, dst_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 0, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 0, 3, ENC_BIG_ENDIAN); addr_item=proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr); if(addr_item){ addr_tree = proto_item_add_subtree(addr_item, ett_addr); } proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 6, 6, src_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 6, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 6, 3, ENC_BIG_ENDIAN); dissect_802_3(ehdr->type, is_802_2, tvb, ETH_HEADER_SIZE, pinfo, parent_tree, fh_tree, hf_eth_len, hf_eth_trailer, fcs_len); } else { if (eth_interpret_as_fw1_monitor) { if ((dst_addr[0] == 'i') || (dst_addr[0] == 'I') || (dst_addr[0] == 'o') || (dst_addr[0] == 'O')) { call_dissector(fw1_handle, tvb, pinfo, parent_tree); return; } } col_set_str(pinfo->cinfo, COL_INFO, "Ethernet II"); if (parent_tree) { if (PTREE_DATA(parent_tree)->visible) { ti = proto_tree_add_protocol_format(parent_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE, "Ethernet II, Src: %s (%s), Dst: %s (%s)", get_ether_name(src_addr), ether_to_str(src_addr), get_ether_name(dst_addr), ether_to_str(dst_addr)); } else { ti = proto_tree_add_item(parent_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE, ENC_NA); } fh_tree = proto_item_add_subtree(ti, ett_ether2); } addr_item=proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr); if(addr_item){ addr_tree = proto_item_add_subtree(addr_item, ett_addr); } proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 0, 6, dst_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 0, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 0, 3, ENC_BIG_ENDIAN); addr_item=proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr); if(addr_item){ addr_tree = proto_item_add_subtree(addr_item, ett_addr); if (tvb_get_guint8(tvb, 6) & 0x01) { expert_add_info_format(pinfo, addr_item, PI_PROTOCOL, PI_WARN, "Source MAC must not be a group address: IEEE 802.3-2002, Section 3.2.3(b)"); } } proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 6, 6, src_addr); proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 6, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 6, 3, ENC_BIG_ENDIAN); ethertype(ehdr->type, tvb, ETH_HEADER_SIZE, pinfo, parent_tree, fh_tree, hf_eth_type, hf_eth_trailer, fcs_len); } }
static void dissect_websocket_data_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *pl_tree, guint8 opcode) { proto_item *ti; const guint offset = 0, length = tvb_reported_length(tvb); dissector_handle_t handle = NULL; heur_dtbl_entry_t *hdtbl_entry; conversation_t *conv; http_conv_t *http_conv = NULL; /* try to find a dissector which accepts the data. */ conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (conv) { http_conv = (http_conv_t *)conversation_get_proto_data(conv, proto_http); if (http_conv) handle = dissector_get_uint_handle(port_subdissector_table, http_conv->server_port); } if (handle) { call_dissector_only(handle, tvb, pinfo, tree, NULL); return; /* handle found, assume dissector took care of it. */ } else if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &hdtbl_entry, NULL)) { return; /* heuristics dissector handled it. */ } /* no dissector wanted it, try to print something appropriate. */ switch (opcode) { case WS_TEXT: /* Text */ { const gchar *saved_match_string = pinfo->match_string; pinfo->match_string = NULL; switch (pref_text_type) { case WEBSOCKET_TEXT: case WEBSOCKET_NONE: default: /* Assume that most text protocols are line-based. */ call_dissector(text_lines_handle, tvb, pinfo, tree); break; case WEBSOCKET_JSON: call_dissector(json_handle, tvb, pinfo, tree); break; case WEBSOCKET_SIP: call_dissector(sip_handle, tvb, pinfo, tree); break; } pinfo->match_string = saved_match_string; } break; case WS_BINARY: /* Binary */ call_dissector(data_handle, tvb, pinfo, tree); break; default: /* Unknown */ ti = proto_tree_add_item(pl_tree, hf_ws_payload_unknown, tvb, offset, length, ENC_NA); expert_add_info_format(pinfo, ti, &ei_ws_payload_unknown, "Dissector for Websocket Opcode (%d)" " code not implemented, Contact Wireshark developers" " if you want this supported", opcode); break; } }
static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *clnp_tree; 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_head *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"); 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); 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, &ei_clnp_length, "Header length value < minimum length %u", FIXED_PART_LEN); return; } 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); 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); 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, &ei_clnp_length, "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); switch (cksum_status) { default: /* * No checksum present, or not enough of the header present to * checksum it. */ proto_tree_add_uint(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum); break; case CKSUM_OK: /* * Checksum is correct. */ proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "0x%04x (correct)", cnf_cksum); break; case CKSUM_NOT_OK: /* * Checksum is not correct. */ proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "0x%04x (incorrect)", cnf_cksum); break; } 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, &ei_clnp_length, "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, &ei_clnp_length, "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); proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_dest, tvb, offset, dst_len, dst_addr, "%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, &ei_clnp_length, "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, &ei_clnp_length, "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); proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_src, tvb, offset, src_len, src_addr, "%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, &ei_clnp_length, "Header length value < %u", FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN); return; } du_id = tvb_get_ntohs(tvb, offset); proto_tree_add_text(clnp_tree, tvb, offset, 2, "Data unit identifier: %06u", du_id); segment_offset = tvb_get_ntohs(tvb, offset + 2); proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2, "Segment offset : %6u", segment_offset); total_length = tvb_get_ntohs(tvb, offset + 4); 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, &ei_clnp_length, "Total length < segment length %u", segment_length); return; } offset += SEGMENTATION_PART_LEN; opt_len -= SEGMENTATION_PART_LEN; } 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==NSEL_NET && tvb_get_guint8(next_tvb, 0)==NLPID_ISO10747_IDRP) { if(call_dissector(idrp_handle, next_tvb, pinfo, tree) != 0) { pinfo->fragmented = save_fragmented; return; } } 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_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *clnp_tree = NULL; proto_item *ti; 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 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); opt_len = cnf_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); proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1, cnf_hdr_len); 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_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s", decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8, "Segmentation permitted", "Segmentation not permitted")); proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s", decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8, "More segments", "Last segment")); proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s", decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8, "Report error if PDU discarded", "Don't report error if PDU discarded")); proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s", decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8, npdu_type_vals, "%s")); } /* 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); cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM); cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2, segment_length); 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; } opt_len -= 9; /* Fixed part of Hesder */ } /* tree */ /* address part */ offset = P_CLNP_ADDRESS_PART; dst_len = tvb_get_guint8(tvb, offset); dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len); nsel = tvb_get_guint8(tvb, offset + dst_len); src_len = tvb_get_guint8(tvb, offset + dst_len + 1); src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1, dst_len); proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len, dst_addr, " DA : %s", print_nsap_net(dst_addr, dst_len)); proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb, offset + 1 + dst_len, 1, src_len); proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb, offset + dst_len + 2, src_len, src_addr, " SA : %s", print_nsap_net(src_addr, src_len)); opt_len -= dst_len + src_len +2; } SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr); SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr); SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr); SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr); /* Segmentation Part */ offset += dst_len + src_len + 2; if (cnf_type & CNF_SEG_OK) { #if 0 struct clnp_segment seg; /* XXX - not used */ tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg)); /* XXX - not used */ #endif segment_offset = tvb_get_ntohs(tvb, offset + 2); du_id = tvb_get_ntohs(tvb, offset); if (tree) { proto_tree_add_text(clnp_tree, tvb, offset, 2, "Data unit identifier: %06u", du_id); proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2, "Segment offset : %6u", segment_offset); proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2, "Total length : %6u", tvb_get_ntohs(tvb, offset + 4)); } offset += 6; opt_len -= 6; } if (tree) { /* To do : decode options */ #if 0 proto_tree_add_text(clnp_tree, tvb, offset, cnf_hdr_len - offset, "Options/Data: <not shown>"); #endif /* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/ dissect_osi_options( opt_len, tvb, offset, clnp_tree ); } offset = cnf_hdr_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(tvb, offset, pinfo, du_id, clnp_segment_table, clnp_reassembled_table, 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. */ next_tvb = tvb_new_subset_remaining(tvb, offset); /* * 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)) { 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 */
/* * Add an Ethernet trailer - which, for some captures, might be the FCS * rather than a pad-to-60-bytes trailer. * * If fcs_len is 0, we assume the frame has no FCS; if it's 4, we assume * it has an FCS; if it's anything else (such as -1, which means "maybe * it does, maybe it doesn't"), we try to infer whether it has an FCS. */ void add_ethernet_trailer(packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb, tvbuff_t *trailer_tvb, int fcs_len) { /* If there're some bytes left over, it could be a combination of: - padding to meet the minimum 64 byte frame length - an FCS, if present (if fcs_len is 0, we know it's not present; if fcs_len is 4, we know it's present; if fcs_len is -1, we need some heuristics to determine whether it's present) - information inserted by TAPs or other network monitoring equipment. If we don't know whether the FCS is present, then, if we don't have a network monitoring trailer, and if the Ethernet frame was claimed to have had 64 or more bytes - i.e., it was at least an FCS worth of data longer than the minimum payload size - we could assume the last 4 bytes of the trailer are an FCS. */ proto_item *item; proto_tree *checksum_tree; if (trailer_tvb) { guint trailer_length, trailer_reported_length; guint padding_length = 0; gboolean has_fcs = FALSE; tvbuff_t *real_trailer_tvb; trailer_length = tvb_length(trailer_tvb); trailer_reported_length = tvb_reported_length(trailer_tvb); /* There can not have been padding when the length of the frame (including the trailer) is less than 60 bytes. */ if (eth_assume_padding && pinfo->fd->pkt_len>=60) { /* Calculate the amount of padding needed for a minimum sized frame */ if ( (pinfo->fd->pkt_len - trailer_reported_length) < 60 ) padding_length = 60 - (pinfo->fd->pkt_len - trailer_reported_length); /* Add the padding to the tree, unless it should be treated as part of the trailer and therefor be handed over to (one of) the ethernet-trailer dissectors */ if (padding_length > 0) { tvb_ensure_bytes_exist(tvb, 0, padding_length); proto_tree_add_item(fh_tree, hf_eth_padding, trailer_tvb, 0, padding_length, ENC_NA); trailer_length -= padding_length; trailer_reported_length -= padding_length; } } if (fcs_len != 0) { /* If fcs_len is 4, we assume we definitely have an FCS. Otherwise, then, if the frame is big enough that, if we have a trailer, it probably inclues an FCS, and we have enough space in the trailer for the FCS, we assume we have an FCS. "Big enough" means 64 bytes or more; any frame that big needs no trailer, as there's no need to pad an Ethernet packet past 60 bytes. The trailer must be at least 4 bytes long to have enough space for an FCS. */ if (fcs_len == 4 || (tvb_reported_length(tvb) >= 64 && trailer_reported_length >= 4)) { /* Either we know we have an FCS, or we believe we have an FCS. */ if (trailer_length < trailer_reported_length) { /* The packet is claimed to have enough data for a 4-byte FCS, but we didn't capture all of the packet. Slice off the 4-byte FCS 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 FCS, if any, is in the captured packet. */ trailer_reported_length -= 4; if (trailer_length > trailer_reported_length) trailer_length = trailer_reported_length; has_fcs = TRUE; } else { /* We captured all of the packet, including what appears to be a 4-byte FCS. Slice it off. */ trailer_length -= 4; trailer_reported_length -= 4; has_fcs = TRUE; } } } /* Create a new tvb without the padding and/or the (assumed) fcs */ if (fcs_len==4) real_trailer_tvb = tvb_new_subset(trailer_tvb, padding_length, trailer_length, trailer_reported_length); else real_trailer_tvb = tvb_new_subset_remaining(trailer_tvb, padding_length); /* Call all ethernet trailer dissectors to dissect the trailer if we actually have a trailer. */ if (tvb_reported_length(real_trailer_tvb) != 0) { if (dissector_try_heuristic(eth_trailer_subdissector_list, real_trailer_tvb, pinfo, tree, NULL) ) { /* If we're not sure that there is a FCS, all trailer data has been given to the ethernet-trailer dissector, so stop dissecting here */ if (fcs_len!=4) return; } else { /* No luck with the trailer dissectors, so just display the extra bytes as general trailer */ if (trailer_length != 0) { tvb_ensure_bytes_exist(tvb, 0, trailer_length); proto_tree_add_item(fh_tree, trailer_id, real_trailer_tvb, 0, trailer_length, ENC_NA); } } } if (has_fcs) { guint32 sent_fcs = tvb_get_ntohl(trailer_tvb, padding_length+trailer_length); if(eth_check_fcs){ guint32 fcs = crc32_802_tvb(tvb, tvb_length(tvb) - 4); if (fcs == sent_fcs) { item = proto_tree_add_uint_format_value(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "0x%08x [correct]", sent_fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, TRUE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format_value(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "0x%08x [incorrect, should be 0x%08x]", sent_fcs, fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, TRUE); PROTO_ITEM_SET_GENERATED(item); expert_add_info(pinfo, item, &ei_eth_fcs_bad); col_append_str(pinfo->cinfo, COL_INFO, " [ETHERNET FRAME CHECK SEQUENCE INCORRECT]"); } }else{ item = proto_tree_add_uint_format_value(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "0x%08x [validiation disabled]", sent_fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); } trailer_length += 4; } proto_tree_set_appendix(fh_tree, tvb, tvb_length(tvb) - padding_length - trailer_length, padding_length + trailer_length); } }
static void dissect_smb_direct_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 remaining_length) { gboolean save_fragmented = pinfo->fragmented; int save_visited = pinfo->fd->flags.visited; conversation_t *conversation = NULL; fragment_head *fd_head = NULL; tvbuff_t *payload_tvb = NULL; gboolean more_frags = FALSE; gboolean fd_head_not_cached = FALSE; if (!smb_direct_reassemble) { payload_tvb = tvb; goto dissect_payload; } conversation = find_or_create_conversation(pinfo); if (remaining_length > 0) { more_frags = TRUE; } fd_head = (fragment_head *)p_get_proto_data(wmem_file_scope(), pinfo, proto_smb_direct, 0); if (fd_head == NULL) { fd_head_not_cached = TRUE; pinfo->fd->flags.visited = 0; fd_head = fragment_add_seq_next(&smb_direct_reassembly_table, tvb, 0, pinfo, conversation->index, NULL, tvb_captured_length(tvb), more_frags); } if (fd_head == NULL) { /* * We really want the fd_head and pass it to * process_reassembled_data() * * So that individual fragments gets the * reassembled in field. */ fd_head = fragment_get_reassembled_id(&smb_direct_reassembly_table, pinfo, conversation->index); } if (fd_head == NULL) { /* * we need more data... */ goto done; } if (fd_head_not_cached) { p_add_proto_data(wmem_file_scope(), pinfo, proto_smb_direct, 0, fd_head); } payload_tvb = process_reassembled_data(tvb, 0, pinfo, "Reassembled SMB Direct", fd_head, &smb_direct_frag_items, NULL, /* update_col_info*/ tree); if (payload_tvb == NULL) { /* * we need more data... */ goto done; } dissect_payload: pinfo->fragmented = FALSE; if (!dissector_try_heuristic(smb_direct_heur_subdissector_list, payload_tvb, pinfo, tree, NULL)) { call_dissector(data_handle, payload_tvb, pinfo, tree); } done: pinfo->fragmented = save_fragmented; pinfo->fd->flags.visited = save_visited; return; }
static int dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint len; guint16 channel_id; guint16 data_len; proto_item *ti; proto_tree *turnchannel_tree; len = tvb_length(tvb); /* First, make sure we have enough data to do the check. */ if (len < TURNCHANNEL_HDR_LEN) { return 0; } channel_id = tvb_get_ntohs(tvb, 0); data_len = tvb_get_ntohs(tvb, 2); if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) { return 0; } if (len != TURNCHANNEL_HDR_LEN + data_len) { return 0; } /* Seems to be a decent TURN channel message */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TURN CHANNEL"); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "Channel Id 0x%x", channel_id); ti = proto_tree_add_item(tree, proto_turnchannel, tvb, 0, -1, ENC_NA); turnchannel_tree = proto_item_add_subtree(ti, ett_turnchannel); proto_tree_add_uint(turnchannel_tree, hf_turnchannel_id, tvb, 0, 2, channel_id); proto_tree_add_uint(turnchannel_tree, hf_turnchannel_len, tvb, 2, 2, data_len); if (len > TURNCHANNEL_HDR_LEN) { tvbuff_t *next_tvb; guint reported_len, new_len; new_len = tvb_length_remaining(tvb, TURNCHANNEL_HDR_LEN); reported_len = tvb_reported_length_remaining(tvb, TURNCHANNEL_HDR_LEN); if (data_len < reported_len) { reported_len = data_len; } next_tvb = tvb_new_subset(tvb, TURNCHANNEL_HDR_LEN, new_len, reported_len); if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)) { call_dissector(data_handle,next_tvb, pinfo, tree); } } return tvb_length(tvb); }
// 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); } } } }