static void dissect_acap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request; proto_tree *acap_tree, *reqresp_tree; proto_item *ti, *hidden_item; gint offset = 0; const guchar *line; gint next_offset; int linelen; int tokenlen; const guchar *next_token; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACAP"); /* * Find the end of the first line. * * 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); if (pinfo->match_uint == pinfo->destport) is_request = TRUE; else is_request = FALSE; /* * Put the first line from the buffer into the summary * (but leave out the line terminator). */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); if (tree) { ti = proto_tree_add_item(tree, hfi_acap, tvb, offset, -1, ENC_NA); acap_tree = proto_item_add_subtree(ti, ett_acap); if (is_request) { hidden_item = proto_tree_add_boolean(acap_tree, &hfi_acap_request, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } else { hidden_item = proto_tree_add_boolean(acap_tree, &hfi_acap_response, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } /* * Put the line into the protocol tree. */ ti = proto_tree_add_format_text(acap_tree, tvb, offset, next_offset - offset); reqresp_tree = proto_item_add_subtree(ti, ett_acap_reqresp); /* * Show the first line as tags + requests or replies. */ /* * Extract the first token, and, if there is a first * token, add it as the request or reply tag. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { if (is_request) { proto_tree_add_text(reqresp_tree, tvb, offset, tokenlen, "Request Tag: %s", format_text(line, tokenlen)); } else { proto_tree_add_text(reqresp_tree, tvb, offset, tokenlen, "Response Tag: %s", format_text(line, tokenlen)); } offset += (int)(next_token - line); linelen -= (int)(next_token - line); line = next_token; } /* * Add the rest of the line as request or reply data. */ if (linelen != 0) { if (is_request) { proto_tree_add_text(reqresp_tree, tvb, offset, linelen, "Request: %s", format_text(line, linelen)); } else { proto_tree_add_text(reqresp_tree, tvb, offset, linelen, "Response: %s", format_text(line, linelen)); } } /* * XXX - show the rest of the frame; this requires that * we handle literals, quoted strings, continuation * responses, etc.. * * This involves a state machine, and attaching * state information to the packets. */ } }
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; 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 to be part of a token; that * means it must be ASCII. */ if (!isascii(c)) { is_icap = FALSE; break; /* not ASCII, thus not a CHAR */ } /* * This mustn't be a CTL to be part of a token. * * XXX - what about leading LWS on continuation * lines of a header? */ if (iscntrl(c)) { is_icap = FALSE; break; /* CTL, not part of a header */ } 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: if (tree) { proto_tree_add_text(icap_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(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_length_remaining(tvb, offset); if (datalen > 0) { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, icap_tree); } }
static void dissect_fddi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean bitswapped) { proto_tree *fh_tree = NULL; proto_item *ti, *hidden_item; const gchar *fc_str; proto_tree *fc_tree; static guchar src[6], dst[6]; guchar src_swapped[6], dst_swapped[6]; tvbuff_t *next_tvb; static fddi_hdr fddihdrs[4]; static int fddihdr_num=0; fddi_hdr *fddihdr; fddihdr_num++; if(fddihdr_num>=4){ fddihdr_num=0; } fddihdr=&fddihdrs[fddihdr_num]; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FDDI"); fddihdr->fc = tvb_get_guint8(tvb, FDDI_P_FC + FDDI_PADDING); fc_str = fddifc_to_str(fddihdr->fc); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, fc_str); if (tree) { ti = proto_tree_add_protocol_format(tree, proto_fddi, tvb, 0, FDDI_HEADER_SIZE+FDDI_PADDING, "Fiber Distributed Data Interface, %s", fc_str); fh_tree = proto_item_add_subtree(ti, ett_fddi); ti = proto_tree_add_uint_format(fh_tree, hf_fddi_fc, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc, "Frame Control: 0x%02x (%s)", fddihdr->fc, fc_str); fc_tree = proto_item_add_subtree(ti, ett_fddi_fc); proto_tree_add_uint(fc_tree, hf_fddi_fc_clf, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc); switch ((fddihdr->fc) & FDDI_FC_CLFF) { case FDDI_FC_SMT: proto_tree_add_uint(fc_tree, hf_fddi_fc_smt_subtype, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc); break; case FDDI_FC_MAC: if (fddihdr->fc != FDDI_FC_RT) proto_tree_add_uint(fc_tree, hf_fddi_fc_mac_subtype, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc); break; case FDDI_FC_LLC_ASYNC: if (!((fddihdr->fc) & FDDI_FC_ASYNC_R)) proto_tree_add_uint(fc_tree, hf_fddi_fc_prio, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc); break; } } /* Extract the destination address, possibly bit-swapping it. */ if (bitswapped) swap_mac_addr(dst, tvb_get_ptr(tvb, FDDI_P_DHOST + FDDI_PADDING, 6)); else memcpy(dst, tvb_get_ptr(tvb, FDDI_P_DHOST + FDDI_PADDING, 6), sizeof dst); swap_mac_addr(dst_swapped, tvb_get_ptr(tvb, FDDI_P_DHOST + FDDI_PADDING, 6)); /* XXX - copy them to some buffer associated with "pi", rather than just making "dst" static? */ SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, &dst[0]); SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, &dst[0]); SET_ADDRESS(&fddihdr->dst, AT_ETHER, 6, &dst[0]); if (fh_tree) { proto_tree_add_ether(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst); hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst); PROTO_ITEM_SET_HIDDEN(hidden_item); /* hide some bit-swapped mac address fields in the proto_tree, just in case */ hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst_swapped); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst_swapped); PROTO_ITEM_SET_HIDDEN(hidden_item); } /* Extract the source address, possibly bit-swapping it. */ if (bitswapped) swap_mac_addr(src, tvb_get_ptr(tvb, FDDI_P_SHOST + FDDI_PADDING, 6)); else memcpy(src, tvb_get_ptr(tvb, FDDI_P_SHOST + FDDI_PADDING, 6), sizeof src); swap_mac_addr(src_swapped, tvb_get_ptr(tvb, FDDI_P_SHOST + FDDI_PADDING, 6)); /* XXX - copy them to some buffer associated with "pi", rather than just making "src" static? */ SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, &src[0]); SET_ADDRESS(&pinfo->src, AT_ETHER, 6, &src[0]); SET_ADDRESS(&fddihdr->src, AT_ETHER, 6, &src[0]); if (fh_tree) { proto_tree_add_ether(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src); hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src); PROTO_ITEM_SET_HIDDEN(hidden_item); /* hide some bit-swapped mac address fields in the proto_tree, just in case */ hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src_swapped); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src_swapped); PROTO_ITEM_SET_HIDDEN(hidden_item); } next_tvb = tvb_new_subset_remaining(tvb, FDDI_HEADER_SIZE + FDDI_PADDING); tap_queue_packet(fddi_tap, pinfo, fddihdr); switch (fddihdr->fc) { /* From now, only 802.2 SNAP (Async. LCC frame) is supported */ case FDDI_FC_LLC_ASYNC + 0 : case FDDI_FC_LLC_ASYNC + 1 : case FDDI_FC_LLC_ASYNC + 2 : case FDDI_FC_LLC_ASYNC + 3 : case FDDI_FC_LLC_ASYNC + 4 : case FDDI_FC_LLC_ASYNC + 5 : case FDDI_FC_LLC_ASYNC + 6 : case FDDI_FC_LLC_ASYNC + 7 : case FDDI_FC_LLC_ASYNC + 8 : case FDDI_FC_LLC_ASYNC + 9 : case FDDI_FC_LLC_ASYNC + 10 : case FDDI_FC_LLC_ASYNC + 11 : case FDDI_FC_LLC_ASYNC + 12 : case FDDI_FC_LLC_ASYNC + 13 : case FDDI_FC_LLC_ASYNC + 14 : case FDDI_FC_LLC_ASYNC + 15 : call_dissector(llc_handle, next_tvb, pinfo, tree); return; default : call_dissector(data_handle,next_tvb, pinfo, tree); return; } /* fc */ } /* dissect_fddi */
static void dissect_nstrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *ns_tree = NULL, *flagtree = NULL; proto_item *ti = NULL, *flagitem = NULL; struct nstr_phdr *pnstr = &(pinfo->pseudo_header->nstr); tvbuff_t *next_tvb_eth_client; guint8 offset; guint i, bpos; wmem_strbuf_t *flags_strbuf = wmem_strbuf_new_label(wmem_packet_scope()); static const gchar *flags[] = {"FP", "FR", "DFD", "SRSS", "RSSH"}; gboolean first_flag = TRUE; guint8 flagoffset, flagval; guint8 src_vmname_len = 0, dst_vmname_len = 0; guint8 variable_ns_len = 0; guint flagval32; wmem_strbuf_append(flags_strbuf, "None"); if (pnstr->rec_type == NSPR_HEADER_VERSION205) { src_vmname_len = tvb_get_guint8(tvb,pnstr->src_vmname_len_offset); dst_vmname_len = tvb_get_guint8(tvb,pnstr->dst_vmname_len_offset); variable_ns_len = src_vmname_len + dst_vmname_len; pnstr->eth_offset += variable_ns_len; } ti = proto_tree_add_protocol_format(tree, proto_nstrace, tvb, 0, pnstr->eth_offset, "NetScaler Packet Trace"); ns_tree = proto_item_add_subtree(ti, ett_ns); proto_tree_add_item(ns_tree, hf_ns_dir, tvb, pnstr->dir_offset, pnstr->dir_len, ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_nicno, tvb, pnstr->nicno_offset, pnstr->nicno_len, ENC_LITTLE_ENDIAN); switch (pnstr->rec_type) { case NSPR_HEADER_VERSION206: flagoffset = pnstr->ns_activity_offset; flagval32 = tvb_get_letohl(tvb, flagoffset); flagitem = proto_tree_add_uint_format(ns_tree, hf_ns_activity, tvb, flagoffset, 4, flagval32, "Activity Flags: 0x%04x", flagval32); flagtree = proto_item_add_subtree(flagitem, ett_ns_activity_flags); proto_tree_add_item(flagtree, hf_ns_activity_perf_collection, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_pcb_zombie, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_natpcb_zombie, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_lbstats_sync, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(flagtree, hf_ns_activity_stats_req, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN); case NSPR_HEADER_VERSION205: if(src_vmname_len){ proto_tree_add_item(ns_tree,hf_ns_src_vm,tvb,pnstr->data_offset,src_vmname_len,ENC_LITTLE_ENDIAN); } if(dst_vmname_len){ proto_tree_add_item(ns_tree,hf_ns_dst_vm,tvb,pnstr->data_offset+src_vmname_len,dst_vmname_len,ENC_LITTLE_ENDIAN); } case NSPR_HEADER_VERSION204: flagoffset = pnstr->clflags_offset; flagval = tvb_get_guint8(tvb, flagoffset); for (i = 0; i < 5; i++) { bpos = 1 << i; if (flagval & bpos) { if (first_flag) { wmem_strbuf_truncate(flags_strbuf, 0); } wmem_strbuf_append_printf(flags_strbuf, "%s%s", first_flag ? "" : ", ", flags[i]); first_flag = FALSE; } } proto_tree_add_item(ns_tree, hf_ns_snode, tvb, pnstr->srcnodeid_offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(ns_tree, hf_ns_dnode, tvb, pnstr->destnodeid_offset, 2, ENC_LITTLE_ENDIAN); flagitem = proto_tree_add_uint_format_value(ns_tree, hf_ns_clflags, tvb, flagoffset, 1, flagval, "0x%02x (%s)", flagval, wmem_strbuf_get_str(flags_strbuf)); flagtree = proto_item_add_subtree(flagitem, ett_ns_flags); proto_tree_add_boolean(flagtree, hf_ns_clflags_res, tvb, flagoffset, 1, flagval); proto_tree_add_boolean(flagtree, hf_ns_clflags_rssh, tvb, flagoffset, 1, flagval); proto_tree_add_boolean(flagtree, hf_ns_clflags_rss, tvb, flagoffset, 1, flagval); proto_tree_add_boolean(flagtree, hf_ns_clflags_dfd, tvb, flagoffset, 1, flagval); proto_tree_add_boolean(flagtree, hf_ns_clflags_fr, tvb, flagoffset, 1, flagval); proto_tree_add_boolean(flagtree, hf_ns_clflags_fp, tvb, flagoffset, 1, flagval); case NSPR_HEADER_VERSION203: proto_tree_add_item(ns_tree, hf_ns_coreid, tvb, pnstr->coreid_offset, 2, ENC_LITTLE_ENDIAN); /* fall through to next case */ case NSPR_HEADER_VERSION202: col_add_fstr(pinfo->cinfo, COL_8021Q_VLAN_ID, "%d", tvb_get_letohs(tvb, pnstr->vlantag_offset)); proto_tree_add_item(ns_tree, hf_ns_vlantag, tvb, pnstr->vlantag_offset, 2, ENC_LITTLE_ENDIAN); /* fall through to next case */ case NSPR_HEADER_VERSION201: proto_tree_add_item(ns_tree, hf_ns_pcbdevno, tvb, pnstr->pcb_offset, 4, ENC_LITTLE_ENDIAN); ti = proto_tree_add_item(ns_tree, hf_ns_devno, tvb, pnstr->pcb_offset, 4, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(ti); proto_tree_add_item(ns_tree, hf_ns_l_pcbdevno, tvb, pnstr->l_pcb_offset, 4, ENC_LITTLE_ENDIAN); ti = proto_tree_add_item(ns_tree, hf_ns_devno, tvb, pnstr->l_pcb_offset, 4, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(ti); break; default: break; } /* Dissect as Ethernet */ offset = pnstr->eth_offset; next_tvb_eth_client = tvb_new_subset_remaining(tvb, offset); call_dissector(eth_withoutfcs_handle, next_tvb_eth_client, pinfo, tree); }
static void dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int linelen) { proto_tree *response_tree, *command_tree = NULL; proto_item *response_item, *command_item, *hidden_item; int start_offset = offset; int end_offset = start_offset+linelen; gint eop_offset = -1, eoc_offset = -1, eocp_offset, tag_start_offset, tag_end_offset; guint8* str_command; guint16 num_command; guchar found_needle = 0, found_tag_needle = 0; gboolean first_command_param = TRUE; response_item = proto_tree_add_item(tree, hf_irc_response, tvb, offset, linelen, ENC_ASCII|ENC_NA); if (linelen <= 0) return; response_tree = proto_item_add_subtree(response_item, ett_irc_response ); /* Check if message has a prefix */ if (tvb_get_guint8(tvb, offset) == ':') { /* find the end of the prefix */ eop_offset = tvb_pbrk_guint8(tvb, offset+1, linelen-1, " ", &found_needle); if (eop_offset == -1) { expert_add_info_format(pinfo, response_item, PI_MALFORMED, PI_ERROR, "Prefix missing ending <space>"); return; } proto_tree_add_item(response_tree, hf_irc_response_prefix, tvb, offset+1, eop_offset-offset-1, ENC_ASCII|ENC_NA); found_needle = 0; offset = eop_offset+1; } /* clear out any whitespace before command */ while(offset < end_offset && tvb_get_guint8(tvb, offset) == ' ') { offset++; } if (offset == end_offset) { expert_add_info_format(pinfo, response_item, PI_MALFORMED, PI_ERROR, "Response has no command"); return; } eoc_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle); if (eoc_offset == -1) { proto_tree_add_item(response_tree, hf_irc_response_command, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA); col_append_fstr( pinfo->cinfo, COL_INFO, " (%s)", tvb_get_ephemeral_string(tvb, offset, end_offset-offset)); /* if response command is numeric, allow it to be filtered as an integer */ if ((end_offset-offset == 3) && (isdigit(tvb_get_guint8(tvb, offset))) && (isdigit(tvb_get_guint8(tvb, offset+1))) && (isdigit(tvb_get_guint8(tvb, offset+2)))) { num_command = ((tvb_get_guint8(tvb, offset)-0x30)*100) + ((tvb_get_guint8(tvb, offset+1)-0x30)*10) + (tvb_get_guint8(tvb, offset+2)-0x30); hidden_item = proto_tree_add_uint(response_tree, hf_irc_response_num_command, tvb, offset, end_offset-offset, num_command); PROTO_ITEM_SET_HIDDEN(hidden_item); } return; } proto_tree_add_item(response_tree, hf_irc_response_command, tvb, offset, eoc_offset-offset, ENC_ASCII|ENC_NA); str_command = tvb_get_ephemeral_string(tvb, offset, eoc_offset-offset); col_append_fstr( pinfo->cinfo, COL_INFO, " (%s)", str_command); /* if response command is numeric, allow it to be filtered as an integer */ if ((eoc_offset-offset == 3) && (isdigit(tvb_get_guint8(tvb, offset))) && (isdigit(tvb_get_guint8(tvb, offset+1))) && (isdigit(tvb_get_guint8(tvb, offset+2)))) { num_command = ((tvb_get_guint8(tvb, offset)-0x30)*100) + ((tvb_get_guint8(tvb, offset+1)-0x30)*10) + (tvb_get_guint8(tvb, offset+2)-0x30); hidden_item = proto_tree_add_uint(response_tree, hf_irc_response_num_command, tvb, offset, eoc_offset-offset, num_command); PROTO_ITEM_SET_HIDDEN(hidden_item); } found_needle = 0; offset = eoc_offset+1; /* clear out any whitespace before command parameter */ while(offset < end_offset && tvb_get_guint8(tvb, offset) == ' ') { offset++; } if (offset == end_offset) { /* No command parameters */ return; } /* Check if message has a trailer */ if (tvb_get_guint8(tvb, offset) == ':') { proto_tree_add_item(response_tree, hf_irc_response_trailer, tvb, offset+1, end_offset-offset-1, ENC_ASCII|ENC_NA); dissect_irc_tag_data(response_tree, response_item, tvb, offset+1, end_offset-offset-1, pinfo, str_command); return; } while(offset < end_offset) { eocp_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle); tag_start_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, TAG_DELIMITER, &found_tag_needle); /* Create subtree when the first parameter is found */ if (first_command_param) { command_item = proto_tree_add_text(response_tree, tvb, offset, end_offset-offset, "Command parameters"); command_tree = proto_item_add_subtree(command_item, ett_irc_response_command ); first_command_param = FALSE; } if ((tag_start_offset == -1) || (eocp_offset < tag_start_offset)) { /* regular message should be dissected */ found_needle = 0; if (eocp_offset == -1) { proto_tree_add_item(command_tree, hf_irc_response_command_param, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA); return; } proto_tree_add_item(command_tree, hf_irc_response_command_param, tvb, offset, eocp_offset-offset, ENC_ASCII|ENC_NA); offset = eocp_offset+1; /* clear out any whitespace before next command parameter */ while(offset < end_offset && tvb_get_guint8(tvb, offset) == ' ') { offset++; } if (offset == end_offset) { break; } /* Check if message has a trailer */ if (tvb_get_guint8(tvb, offset) == ':') { proto_tree_add_item(response_tree, hf_irc_response_trailer, tvb, offset+1, end_offset-offset-1, ENC_ASCII|ENC_NA); dissect_irc_tag_data(response_tree, response_item, tvb, offset+1, end_offset-offset-1, pinfo, str_command); return; } } else if ((eocp_offset == -1) || (eocp_offset > tag_start_offset)) { /* tag data dissected */ found_tag_needle = 0; tag_end_offset = tvb_pbrk_guint8(tvb, tag_start_offset+1, end_offset-tag_start_offset-1, TAG_DELIMITER, &found_tag_needle); if (tag_end_offset == -1) { expert_add_info_format(pinfo, response_item, PI_MALFORMED, PI_ERROR, "Missing ending tag delimited (0x01)"); return; } dissect_irc_tag_data(response_tree, response_item, tvb, tag_start_offset, tag_end_offset-tag_start_offset, pinfo, str_command); offset = tag_end_offset+1; } } }
static void dissect_smtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { struct smtp_proto_data *spd_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 or create the conversation for this. */ conversation = find_or_create_conversation(pinfo); /* * 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 = 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; guint32 save_last_nontls_frame; /* This is TLS, not raw SMTP. TLS can desegment */ save_can_desegment = pinfo->can_desegment; pinfo->can_desegment = pinfo->saved_can_desegment; /* Make sure the SSL dissector will not be called again after decryption */ save_last_nontls_frame = session_state->last_nontls_frame; session_state->last_nontls_frame = 0; call_dissector(ssl_handle, tvb, pinfo, tree); pinfo->can_desegment = save_can_desegment; session_state->last_nontls_frame = save_last_nontls_frame; return; } /* Is this a request or a response? */ request = pinfo->destport == pinfo->match_uint; /* * Is there any data attached to this frame? */ spd_frame_data = p_get_proto_data(pinfo->fd, proto_smtp); if (!spd_frame_data) { /* * No frame data. */ if(request) { /* * Create a frame data structure and attach it to the packet. */ spd_frame_data = se_alloc0(sizeof(struct smtp_proto_data)); spd_frame_data->conversation_id = conversation->index; spd_frame_data->more_frags = TRUE; p_add_proto_data(pinfo->fd, proto_smtp, spd_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 == 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 == SMTP_STATE_READING_DATA) { /* * This is message data. */ if (eom_seen) { /* Seen the EOM */ /* * EOM. * Everything that comes after it is commands. */ spd_frame_data->pdu_type = SMTP_PDU_EOM; session_state->smtp_state = SMTP_STATE_READING_CMDS; break; } else { /* * Message data with no EOM. */ spd_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 = SMTP_STATE_READING_CMDS; if (session_state->msg_last) { /* * We have found the LAST data chunk. * The message can now be reassembled. */ spd_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. */ spd_frame_data->pdu_type = SMTP_PDU_CMD; session_state->smtp_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); spd_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 = SMTP_STATE_READING_CMDS; } else { session_state->smtp_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. */ spd_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 = SMTP_STATE_AWAITING_STARTTLS_RESPONSE; spd_frame_data->pdu_type = SMTP_PDU_CMD; } else { /* * Regular command. */ spd_frame_data->pdu_type = SMTP_PDU_CMD; } } else { /* * Assume it's message data. */ spd_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 (spd_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 (spd_frame_data->pdu_type) { case SMTP_PDU_MESSAGE: if (smtp_data_desegment) { frag_msg = fragment_add_seq_next(tvb, 0, pinfo, spd_frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table, tvb_length(tvb), spd_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, spd_frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table, loffset, spd_frame_data->more_frags); /* terminate the desegmentation */ frag_msg = fragment_end_seq_next (pinfo, spd_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 && !spd_frame_data->more_frags) { /* terminate the desegmentation */ frag_msg = fragment_end_seq_next (pinfo, spd_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 == 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 = 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_tacplus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tvbuff_t *new_tvb=NULL; proto_tree *tacplus_tree; proto_item *ti, *hidden_item; guint8 version,flags; proto_tree *flags_tree; proto_item *tf; proto_item *tmp_pi; guint32 len; gboolean request=( pinfo->destport == TCP_PORT_TACACS ); const char *key=NULL; len = tvb_get_ntohl(tvb, 8); if(len > (guint)tvb_length_remaining(tvb, 12) && pinfo->can_desegment && tacplus_preference_desegment) { pinfo->desegment_offset = 0; pinfo->desegment_len = len; return; } if( request ) { key=find_key( &pinfo->dst, &pinfo->src ); } else { key=find_key( &pinfo->src, &pinfo->dst ); } col_set_str(pinfo->cinfo, COL_PROTOCOL, "TACACS+"); col_add_fstr( pinfo->cinfo, COL_INFO, "%s: %s", request ? "Q" : "R", val_to_str(tvb_get_guint8(tvb,1), tacplus_type_vals, "Unknown (0x%02x)")); if (tree) { ti = proto_tree_add_item(tree, proto_tacplus, tvb, 0, -1, ENC_NA); tacplus_tree = proto_item_add_subtree(ti, ett_tacplus); if (pinfo->match_uint == pinfo->destport) { hidden_item = proto_tree_add_boolean(tacplus_tree, hf_tacplus_request, tvb, 0, 0, TRUE); } else { hidden_item = proto_tree_add_boolean(tacplus_tree, hf_tacplus_response, tvb, 0, 0, TRUE); } PROTO_ITEM_SET_HIDDEN(hidden_item); version = tvb_get_guint8(tvb,0); proto_tree_add_uint_format_value(tacplus_tree, hf_tacplus_majvers, tvb, 0, 1, version, "%s", (version&0xf0)==0xc0?"TACACS+":"Unknown Version"); proto_tree_add_uint(tacplus_tree, hf_tacplus_minvers, tvb, 0, 1, version&0xf); proto_tree_add_item(tacplus_tree, hf_tacplus_type, tvb, 1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tacplus_tree, hf_tacplus_seqno, tvb, 2, 1, ENC_BIG_ENDIAN); flags = tvb_get_guint8(tvb,3); tf = proto_tree_add_uint_format_value(tacplus_tree, hf_tacplus_flags, tvb, 3, 1, flags, "0x%02x (%s payload, %s)", flags, (flags&FLAGS_UNENCRYPTED) ? "Unencrypted" : "Encrypted", (flags&FLAGS_SINGLE) ? "Single connection" : "Multiple Connections" ); flags_tree = proto_item_add_subtree(tf, ett_tacplus_flags); proto_tree_add_boolean(flags_tree, hf_tacplus_flags_payload_type, tvb, 3, 1, flags); proto_tree_add_boolean(flags_tree, hf_tacplus_flags_connection_type, tvb, 3, 1, flags); proto_tree_add_item(tacplus_tree, hf_tacplus_session_id, tvb, 4, 4, ENC_BIG_ENDIAN); tmp_pi = proto_tree_add_uint(tacplus_tree, hf_tacplus_packet_len, tvb, 8, 4, len); if ((gint)len < 1) { expert_add_info_format(pinfo, tmp_pi, &ei_tacplus_packet_len_invalid, "Invalid length: %u", len); } tmp_pi = proto_tree_add_text(tacplus_tree, tvb, TAC_PLUS_HDR_SIZE, len, "%s%s", ((flags&FLAGS_UNENCRYPTED)?"":"Encrypted "), request?"Request":"Reply" ); if( flags&FLAGS_UNENCRYPTED ) { new_tvb = tvb_new_subset( tvb, TAC_PLUS_HDR_SIZE, len, len ); } else { new_tvb=NULL; if( key && *key ){ tacplus_decrypted_tvb_setup( tvb, &new_tvb, pinfo, len, version, key ); } } if( new_tvb ) { /* Check to see if I've a decrypted tacacs packet */ if( !(flags&FLAGS_UNENCRYPTED) ){ tmp_pi = proto_tree_add_text(tacplus_tree, new_tvb, 0, len, "Decrypted %s", request?"Request":"Reply" ); } dissect_tacplus_body( tvb, new_tvb, proto_item_add_subtree( tmp_pi, ett_tacplus_body )); } } }
static void dissect_ftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request; proto_tree *ftp_tree = NULL; proto_tree *reqresp_tree = NULL; proto_item *ti, *hidden_item; gint offset; const guchar *line; guint32 code; gchar code_str[4]; gboolean is_port_request = FALSE; gboolean is_eprt_request = FALSE; gboolean is_pasv_response = FALSE; gboolean is_epasv_response = FALSE; gint next_offset; int linelen; int tokenlen = 0; const guchar *next_token; guint32 pasv_ip; guint32 pasv_offset; guint32 ftp_ip; guint32 ftp_ip_len; guint32 eprt_offset; guint32 eprt_af = 0; guint32 eprt_ip; guint16 eprt_ipv6[8]; guint32 eprt_ip_len = 0; guint16 ftp_port; guint32 ftp_port_len; address ftp_ip_address; gboolean ftp_nat; conversation_t *conversation; ftp_ip_address = pinfo->src; if (pinfo->match_uint == pinfo->destport) is_request = TRUE; else is_request = FALSE; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FTP"); /* * Find the end of the first line. * * 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, 0, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, 0, linelen); /* * Put the first line from the buffer into the summary * (but leave out the line terminator). */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); ti = proto_tree_add_item(tree, proto_ftp, tvb, 0, -1, ENC_NA); ftp_tree = proto_item_add_subtree(ti, ett_ftp); if (is_request) { hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_request, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_response, tvb, 0, 0, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); } else { hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_request, tvb, 0, 0, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_boolean(ftp_tree, hf_ftp_response, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } /* Put the line into the protocol tree. */ ti = proto_tree_add_text(ftp_tree, tvb, 0, next_offset, "%s", tvb_format_text(tvb, 0, next_offset)); reqresp_tree = proto_item_add_subtree(ti, ett_ftp_reqresp); if (is_request) { /* * Extract the first token, and, if there is a first * token, add it as the request. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { proto_tree_add_item(reqresp_tree, hf_ftp_request_command, tvb, 0, tokenlen, ENC_ASCII|ENC_NA); if (strncmp(line, "PORT", tokenlen) == 0) is_port_request = TRUE; /* * EPRT request command, as per RFC 2428 */ else if (strncmp(line, "EPRT", tokenlen) == 0) is_eprt_request = TRUE; } } else { /* * This is a response; the response code is 3 digits, * followed by a space or hyphen, possibly followed by * text. * * If the line doesn't start with 3 digits, it's part of * a continuation. * * XXX - keep track of state in the first pass, and * treat non-continuation lines not beginning with digits * as errors? */ if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1]) && isdigit(line[2])) { /* * One-line reply, or first or last line * of a multi-line reply. */ tvb_get_nstringz0(tvb, 0, sizeof(code_str), code_str); code = (guint32)strtoul(code_str, NULL, 10); proto_tree_add_uint(reqresp_tree, hf_ftp_response_code, tvb, 0, 3, code); /* * See if it's a passive-mode response. * * XXX - does anybody do FOOBAR, as per RFC * 1639, or has that been supplanted by RFC 2428? */ if (code == 227) is_pasv_response = TRUE; /* * Responses to EPSV command, as per RFC 2428 */ if (code == 229) is_epasv_response = TRUE; /* * Skip the 3 digits and, if present, the * space or hyphen. */ if (linelen >= 4) next_token = line + 4; else next_token = line + linelen; } else { /* * Line doesn't start with 3 digits; assume it's * a line in the middle of a multi-line reply. */ next_token = line; } } offset = (gint) (next_token - line); linelen -= (int) (next_token - line); line = next_token; /* * Add the rest of the first line as request or * reply data. */ if (linelen != 0) { if (is_request) { proto_tree_add_item(reqresp_tree, hf_ftp_request_arg, tvb, offset, linelen, ENC_ASCII|ENC_NA); } else { proto_tree_add_item(reqresp_tree, hf_ftp_response_arg, tvb, offset, linelen, ENC_ASCII|ENC_NA); } } offset = next_offset; /* * If this is a PORT request or a PASV response, handle it. */ if (is_port_request) { if (parse_port_pasv(line, linelen, &ftp_ip, &ftp_port, &pasv_offset, &ftp_ip_len, &ftp_port_len)) { proto_tree_add_ipv4(reqresp_tree, hf_ftp_active_ip, tvb, pasv_offset + (tokenlen+1) , ftp_ip_len, ftp_ip); proto_tree_add_uint(reqresp_tree, hf_ftp_active_port, tvb, pasv_offset + 1 + (tokenlen+1) + ftp_ip_len, ftp_port_len, ftp_port); SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4, (const guint8 *)&ftp_ip); ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address); if (ftp_nat) { proto_tree_add_boolean(reqresp_tree, hf_ftp_active_nat, tvb, 0, 0, ftp_nat); } } } if (is_pasv_response) { if (linelen != 0) { /* * This frame contains a PASV response; set up a * conversation for the data. */ if (parse_port_pasv(line, linelen, &pasv_ip, &ftp_port, &pasv_offset, &ftp_ip_len, &ftp_port_len)) { proto_tree_add_ipv4(reqresp_tree, hf_ftp_pasv_ip, tvb, pasv_offset + 4, ftp_ip_len, pasv_ip); proto_tree_add_uint(reqresp_tree, hf_ftp_pasv_port, tvb, pasv_offset + 4 + 1 + ftp_ip_len, ftp_port_len, ftp_port); SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4, (const guint8 *)&pasv_ip); ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address); if (ftp_nat) { proto_tree_add_boolean(reqresp_tree, hf_ftp_pasv_nat, tvb, 0, 0, ftp_nat); } /* * We use "ftp_ip_address", so that if * we're NAT'd we look for the un-NAT'd * connection. * * XXX - should this call to * "find_conversation()" just use * "ftp_ip_address" and "server_port", and * wildcard everything else? */ conversation = find_conversation(pinfo->fd->num, &ftp_ip_address, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT_B); if (conversation == NULL) { /* * XXX - should this call to "conversation_new()" * just use "ftp_ip_address" and "server_port", * and wildcard everything else? * * XXX - what if we did find a conversation? As * we create it only on the first pass through the * packets, if we find one, it's presumably an * unrelated conversation. Should we remove the * old one from the hash table and put this one in * its place? Can the conversation code handle * conversations not in the hash table? Or should * we make conversations support start and end * frames, as circuits do, and treat this as an * indication that one conversation was closed and * a new one was opened? */ conversation = conversation_new( pinfo->fd->num, &ftp_ip_address, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT2); conversation_set_dissector(conversation, ftpdata_handle); } } } } if (is_eprt_request) { /* * RFC2428 - sect. 2 * This frame contains a EPRT request; let's dissect it and set up a * conversation for the data connection. */ if (parse_eprt_request(line, linelen, &eprt_af, &eprt_ip, eprt_ipv6, &ftp_port, &eprt_ip_len, &ftp_port_len)) { /* since parse_eprt_request() returned TRUE, we know that we have a valid address family */ eprt_offset = tokenlen + 1 + 1; /* token, space, 1st delimiter */ proto_tree_add_uint(reqresp_tree, hf_ftp_eprt_af, tvb, eprt_offset, 1, eprt_af); eprt_offset += 1 + 1; /* addr family, 2nd delimiter */ if (eprt_af == EPRT_AF_IPv4) { proto_tree_add_ipv4(reqresp_tree, hf_ftp_eprt_ip, tvb, eprt_offset, eprt_ip_len, eprt_ip); SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4, (const guint8 *)&eprt_ip); } else if (eprt_af == EPRT_AF_IPv6) { proto_tree_add_ipv6(reqresp_tree, hf_ftp_eprt_ipv6, tvb, eprt_offset, eprt_ip_len, (const guint8 *)eprt_ipv6); SET_ADDRESS(&ftp_ip_address, AT_IPv6, 16, (const guint8 *)&eprt_ipv6); } eprt_offset += eprt_ip_len + 1; /* addr, 3rd delimiter */ proto_tree_add_uint(reqresp_tree, hf_ftp_eprt_port, tvb, eprt_offset, ftp_port_len, ftp_port); /* Find/create conversation for data */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &ftp_ip_address, PT_TCP, ftp_port, 0, NO_PORT_B); if (conversation == NULL) { conversation = conversation_new( pinfo->fd->num, &pinfo->src, &ftp_ip_address, PT_TCP, ftp_port, 0, NO_PORT2); conversation_set_dissector(conversation, ftpdata_handle); } } else { proto_item *item; item = proto_tree_add_text(reqresp_tree, tvb, offset - linelen - 1, linelen, "Invalid EPRT arguments"); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "EPRT arguments must have the form: |<family>|<addr>|<port>|"); } } if (is_epasv_response) { if (linelen != 0) { proto_item *addr_it; /* * RFC2428 - sect. 3 * This frame contains an EPSV response; set up a * conversation for the data. */ if (parse_extended_pasv_response(line, linelen, &ftp_port, &pasv_offset, &ftp_port_len)) { /* Add IP address and port number to tree */ if (ftp_ip_address.type == AT_IPv4) { guint32 addr; memcpy(&addr, ftp_ip_address.data, 4); addr_it = proto_tree_add_ipv4(reqresp_tree, hf_ftp_epsv_ip, tvb, 0, 0, addr); PROTO_ITEM_SET_GENERATED(addr_it); } else if (ftp_ip_address.type == AT_IPv6) { addr_it = proto_tree_add_ipv6(reqresp_tree, hf_ftp_epsv_ipv6, tvb, 0, 0, (guint8*)ftp_ip_address.data); PROTO_ITEM_SET_GENERATED(addr_it); } proto_tree_add_uint(reqresp_tree, hf_ftp_epsv_port, tvb, pasv_offset + 4, ftp_port_len, ftp_port); /* Find/create conversation for data */ conversation = find_conversation(pinfo->fd->num, &ftp_ip_address, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT_B); if (conversation == NULL) { conversation = conversation_new( pinfo->fd->num, &ftp_ip_address, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT2); conversation_set_dissector(conversation, ftpdata_handle); } } else { proto_item *item; item = proto_tree_add_text(reqresp_tree, tvb, offset - linelen - 1, linelen, "Invalid EPSV arguments"); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "EPSV arguments must have the form (|||<port>|)"); } } } /* * Show the rest of the request or response as text, * a line at a time. * XXX - only if there's a continuation indicator? */ 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(ftp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; } }
static void display_socks_v4(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, socks_hash_entry_t *hash_info) { /* Display the protocol tree for the V4 version. This routine uses the */ /* stored conversation information to decide what to do with the row. */ /* Per packet information would have been better to do this, but we */ /* didn't have that when I wrote this. And I didn't expect this to get */ /* so messy. */ proto_item *hidden_item; guint command; unsigned char ipaddr[4]; guint username_len, domainname_len; /* Display command from client */ if (compare_packet( hash_info->connect_row)){ proto_tree_add_text( tree, tvb, offset, 1, "Version: %u", hash_info->version); ++offset; command = tvb_get_guint8(tvb, offset); proto_tree_add_text( tree, tvb, offset, 1, "Command: %u (%s)", command, get_command_name( command)); ++offset; /* Do remote port */ proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2, FALSE); offset += 2; /* Do destination address */ tvb_memcpy(tvb, ipaddr, offset, 4); proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset, 4, FALSE); offset += 4; /*XXX check this, needs to do length checking */ /* Should perhaps do TCP reassembly as well */ if ( tvb_offset_exists(tvb, offset)) { /* display user name */ username_len = tvb_strsize(tvb, offset); proto_tree_add_item( tree, hf_user_name, tvb, offset, username_len, FALSE); offset += username_len; if ( ipaddr[0] == 0 && ipaddr[1] == 0 && ipaddr[2] == 0 && ipaddr[3] != 0) { /* 0.0.0.x , where x!=0 means v4a support */ domainname_len = tvb_strsize(tvb, offset); proto_tree_add_item( tree, hf_v4a_dns_name, tvb, offset, domainname_len, FALSE); } } } /*Display command response from server*/ else if ( compare_packet( hash_info->cmd_reply_row)){ proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, FALSE); ++offset; /* Do results code */ proto_tree_add_item( tree, hf_socks_results_4, tvb, offset, 1, FALSE); hidden_item = proto_tree_add_item(tree, hf_socks_results, tvb, offset, 1, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); ++offset; /* Do remote port */ proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2, FALSE); offset += 2; /* Do remote address */ proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset, 4, FALSE); } else if ( compare_packet( hash_info->v4_user_name_row)){ /*XXX check this, needs to do length checking */ /* Should perhaps do TCP reassembly as well */ if ( tvb_offset_exists(tvb, offset)) { proto_tree_add_text( tree, tvb, offset, tvb_strsize(tvb, offset), "User Name: %s", tvb_get_ptr(tvb, offset, -1)); } } }
static void dissect_tns_accept(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_tree *tns_tree) { proto_tree *accept_tree = NULL, *ti; proto_item *hidden_item; int accept_offset; int accept_len; int tns_offset = offset-8; if ( tree ) { ti = proto_tree_add_text(tns_tree, tvb, offset, -1, "Accept"); accept_tree = proto_item_add_subtree(ti, ett_tns_accept); hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_accept, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } col_append_str(pinfo->cinfo, COL_INFO, ", Accept"); if ( accept_tree ) { proto_tree_add_item(accept_tree, hf_tns_version, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( accept_tree ) { proto_tree *sopt_tree = NULL; ti = proto_tree_add_item(accept_tree, hf_tns_service_options, tvb, offset, 2, ENC_BIG_ENDIAN); sopt_tree = proto_item_add_subtree(ti, ett_tns_sopt_flag); dissect_tns_service_options(tvb, offset, sopt_tree); } offset += 2; if ( accept_tree ) { proto_tree_add_item(accept_tree, hf_tns_sdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( accept_tree ) { proto_tree_add_item(accept_tree, hf_tns_max_tdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( accept_tree ) { proto_tree_add_item(accept_tree, hf_tns_value_of_one, tvb, offset, 2, ENC_NA); } offset += 2; accept_len = tvb_get_ntohs(tvb, offset); if ( accept_tree ) { proto_tree_add_uint(accept_tree, hf_tns_accept_data_length, tvb, offset, 2, accept_len); } offset += 2; accept_offset = tvb_get_ntohs(tvb, offset); if ( accept_tree ) { proto_tree_add_uint(accept_tree, hf_tns_accept_data_offset, tvb, offset, 2, accept_offset); } offset += 2; if ( accept_tree ) { proto_tree *cflag_tree = NULL; ti = proto_tree_add_item(accept_tree, hf_tns_connect_flags0, tvb, offset, 1, ENC_BIG_ENDIAN); cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag); dissect_tns_connect_flag(tvb, offset, cflag_tree); } offset += 1; if ( accept_tree ) { proto_tree *cflag_tree = NULL; ti = proto_tree_add_item(accept_tree, hf_tns_connect_flags1, tvb, offset, 1, ENC_BIG_ENDIAN); cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag); dissect_tns_connect_flag(tvb, offset, cflag_tree); } /* offset += 1; */ if ( accept_tree && accept_len > 0) { proto_tree_add_item(accept_tree, hf_tns_accept_data, tvb, tns_offset+accept_offset, -1, ENC_ASCII|ENC_NA); } return; }
int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree) { int consumed_bytes = tvb->length; lua_pinfo = pinfo; lua_tvb = tvb; lua_tree = g_malloc(sizeof(struct _wslua_treeitem)); lua_tree->tree = tree; lua_tree->item = proto_tree_add_text(tree,tvb,0,0,"lua fake item"); lua_tree->expired = FALSE; PROTO_ITEM_SET_HIDDEN(lua_tree->item); /* * almost equivalent to Lua: * dissectors[current_proto](tvb,pinfo,tree) */ lua_settop(L,0); lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref); lua_pushstring(L, pinfo->current_proto); lua_gettable(L, -2); lua_remove(L,1); if (lua_isfunction(L,1)) { push_Tvb(L,tvb); push_Pinfo(L,pinfo); push_TreeItem(L,lua_tree); if ( lua_pcall(L,3,1,0) ) { const gchar* error = lua_tostring(L,-1); proto_item* pi = proto_tree_add_text(tree,tvb,0,0,"Lua Error: %s",error); expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_ERROR ,"Lua Error"); } else { /* if the Lua dissector reported the consumed bytes, pass it to our caller */ if (lua_isnumber(L, -1)) { /* we got the consumed bytes or the missing bytes as a negative number */ consumed_bytes = (int) lua_tonumber(L, -1); lua_pop(L, 1); } } } else { proto_item* pi = proto_tree_add_text(tree,tvb,0,0,"Lua Error: did not find the %s dissector" " in the dissectors table",pinfo->current_proto); expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_ERROR ,"Lua Error"); } register_frame_end_routine(lua_frame_end); lua_pinfo = NULL; lua_tree = NULL; lua_tvb = NULL; return consumed_bytes; }
static void dissect_lpd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *lpd_tree; proto_item *ti, *hidden_item; enum lpr_type lpr_packet_type; guint8 code; gint printer_len; /* This information comes from the LPRng HOWTO, which also describes RFC 1179. http://www.astart.com/lprng/LPRng-HOWTO.html */ static const value_string lpd_client_code[] = { { 1, "LPC: start print / jobcmd: abort" }, { 2, "LPR: transfer a printer job / jobcmd: receive control file" }, { 3, "LPQ: print short form of queue status / jobcmd: receive data file" }, { 4, "LPQ: print long form of queue status" }, { 5, "LPRM: remove jobs" }, { 6, "LPRng lpc: do control operation" }, { 7, "LPRng lpr: transfer a block format print job" }, { 8, "LPRng lpc: secure command transfer" }, { 9, "LPRng lpq: verbose status information" }, { 0, NULL } }; static const value_string lpd_server_code[] = { { 0, "Success: accepted, proceed" }, { 1, "Queue not accepting jobs" }, { 2, "Queue temporarily full, retry later" }, { 3, "Bad job format, do not retry" }, { 0, NULL } }; col_set_str(pinfo->cinfo, COL_PROTOCOL, "LPD"); col_clear(pinfo->cinfo, COL_INFO); /* rfc1179 states that all responses are 1 byte long */ code = tvb_get_guint8(tvb, 0); if (tvb_reported_length(tvb) == 1) { lpr_packet_type = response; } else if (code <= 9) { lpr_packet_type = request; } else { lpr_packet_type = unknown; } if (lpr_packet_type == request && code !=0) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(code, lpd_client_code, "Unknown client code: %u")); } else if (lpr_packet_type == response) { col_set_str(pinfo->cinfo, COL_INFO, "LPD response"); } else { col_set_str(pinfo->cinfo, COL_INFO, "LPD continuation"); } if (tree) { ti = proto_tree_add_item(tree, proto_lpd, tvb, 0, -1, ENC_NA); lpd_tree = proto_item_add_subtree(ti, ett_lpd); if (lpr_packet_type == response) { hidden_item = proto_tree_add_boolean(lpd_tree, hf_lpd_response, tvb, 0, 0, TRUE); } else { hidden_item = proto_tree_add_boolean(lpd_tree, hf_lpd_request, tvb, 0, 0, TRUE); } PROTO_ITEM_SET_HIDDEN(hidden_item); if (lpr_packet_type == request) { printer_len = find_printer_string(tvb, 1); if (code <= 9 && printer_len != -1) { proto_tree_add_text(lpd_tree, tvb, 0, 1, "%s", val_to_str(code, lpd_client_code, "Unknown client code: %u")); proto_tree_add_text(lpd_tree, tvb, 1, printer_len, "Printer/options: %s", tvb_format_text(tvb, 1, printer_len)); } else { call_dissector(data_handle,tvb, pinfo, lpd_tree); } } else if (lpr_packet_type == response) { if (code <= 3) { proto_tree_add_text(lpd_tree, tvb, 0, 1, "Response: %s", val_to_str(code, lpd_server_code, "Unknown server code: %u")); } else { call_dissector(data_handle,tvb, pinfo, lpd_tree); } } else { call_dissector(data_handle,tvb, pinfo, lpd_tree); } } }
static int dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ws_tree, guint8 opcode, guint64 payload_length, guint8 mask, const guint8* masking_key) { int offset = 0; int payload_length_32bit; proto_item *ti_unmask, *ti; proto_tree *pl_tree, *mask_tree = NULL; tvbuff_t *unmask_tvb = NULL; /* Wireshark does not handle packets larger than 2^31-1 bytes. */ payload_length_32bit = (int)payload_length; if (payload_length != (guint64)payload_length_32bit) { proto_tree_add_text(ws_tree, tvb, offset, -1, "Payload length %" G_GINT64_MODIFIER "u is too large to dissect", payload_length); return tvb_length(tvb); } /* Payload */ ti = proto_tree_add_item(ws_tree, hf_ws_payload, tvb, offset, payload_length_32bit, ENC_NA); pl_tree = proto_item_add_subtree(ti, ett_ws_pl); if(mask){ unmask_tvb = tvb_unmasked(tvb, offset, payload_length_32bit, masking_key); tvb_set_child_real_data_tvbuff(tvb, unmask_tvb); add_new_data_source(pinfo, unmask_tvb, payload_length_32bit > (int) tvb_length(unmask_tvb) ? "Unmasked Data (truncated)" : "Unmasked Data"); ti = proto_tree_add_item(ws_tree, hf_ws_payload_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA); mask_tree = proto_item_add_subtree(ti, ett_ws_mask); } /* Extension Data */ /* TODO: Add dissector of Extension (not extension available for the moment...) */ /* Application Data */ switch(opcode){ case WS_CONTINUE: /* Continue */ proto_tree_add_item(pl_tree, hf_ws_payload_continue, tvb, offset, payload_length_32bit, ENC_NA); /* TODO: Add Fragmentation support... */ break; case WS_TEXT: /* Text */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_text_mask, tvb, offset, payload_length_32bit, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text_unmask, unmask_tvb, offset, payload_length_32bit, ENC_UTF_8|ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text, unmask_tvb, offset, payload_length_32bit, ENC_UTF_8|ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); }else{ proto_tree_add_item(pl_tree, hf_ws_payload_text, tvb, offset, payload_length_32bit, ENC_UTF_8|ENC_NA); } offset += payload_length_32bit; break; case WS_BINARY: /* Binary */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_binary_mask, tvb, offset, payload_length_32bit, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary, unmask_tvb, offset, payload_length_32bit, ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); }else{ proto_tree_add_item(pl_tree, hf_ws_payload_binary, tvb, offset, payload_length_32bit, ENC_NA); } offset += payload_length_32bit; break; case WS_CLOSE: /* Close */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_close_mask, tvb, offset, payload_length_32bit, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close, unmask_tvb, offset, payload_length_32bit, ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_status_code, unmask_tvb, offset, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_GENERATED(ti_unmask); if(payload_length_32bit > 2){ ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_reason, unmask_tvb, offset+2, payload_length_32bit-2, ENC_ASCII|ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); } }else{ proto_tree_add_item(pl_tree, hf_ws_payload_close, tvb, offset, payload_length_32bit, ENC_NA); proto_tree_add_item(pl_tree, hf_ws_payload_close_status_code, tvb, offset, 2, ENC_BIG_ENDIAN); if(payload_length_32bit > 2){ proto_tree_add_item(pl_tree, hf_ws_payload_close_reason, tvb, offset+2, payload_length_32bit-2, ENC_ASCII|ENC_NA); } } offset += payload_length_32bit; break; case WS_PING: /* Ping */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_ping_mask, tvb, offset, payload_length_32bit, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping, unmask_tvb, offset, payload_length_32bit, ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); }else{ proto_tree_add_item(pl_tree, hf_ws_payload_ping, tvb, offset, payload_length_32bit, ENC_NA); } offset += payload_length_32bit; break; case WS_PONG: /* Pong */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_pong_mask, tvb, offset, payload_length_32bit, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong, unmask_tvb, offset, payload_length_32bit, ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); }else{ proto_tree_add_item(pl_tree, hf_ws_payload_pong, tvb, offset, payload_length_32bit, ENC_NA); } offset += payload_length_32bit; break; default: /* Unknown */ ti = proto_tree_add_item(pl_tree, hf_ws_payload_unknown, tvb, offset, payload_length_32bit, ENC_NA); expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_NOTE, "Dissector for Websocket Opcode (%d)" " code not implemented, Contact Wireshark developers" " if you want this supported", opcode); break; } return offset; }
static int dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { const char *opcode_str; proto_tree *slimp3_tree = NULL; proto_item *ti = NULL, *hidden_item; gint i1; gint offset = 0; guint16 opcode; guchar lcd_char; char lcd_str[MAX_LCD_STR_LEN + 1]; int to_server = FALSE; int old_protocol = FALSE; address tmp_addr; gboolean in_str; int lcd_strlen; /* * If it doesn't begin with a known opcode, reject it, so that * traffic that happens to be do or from one of our ports * doesn't get misidentified as SliMP3 traffic. */ if (!tvb_bytes_exist(tvb, offset, 1)) return 0; /* not even an opcode */ opcode = tvb_get_guint8(tvb, offset); opcode_str = match_strval(opcode, slimp3_opcode_vals); if (opcode_str == NULL) return 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SliMP3"); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, opcode_str); } if (tree) { ti = proto_tree_add_item(tree, proto_slimp3, tvb, offset, -1, ENC_NA); slimp3_tree = proto_item_add_subtree(ti, ett_slimp3); proto_tree_add_uint(slimp3_tree, hf_slimp3_opcode, tvb, offset, 1, opcode); } /* The new protocol (v1.3 and later) uses an IANA-assigned port number. * It usually uses the same number for both sizes of the conversation, so * the port numbers can't always be used to determine client and server. * The new protocol places the clients MAC address in the packet, so that * is used to identify packets originating at the client. */ if ((pinfo->destport == UDP_PORT_SLIMP3_V2) && (pinfo->srcport == UDP_PORT_SLIMP3_V2)) { SET_ADDRESS(&tmp_addr, AT_ETHER, 6, tvb_get_ptr(tvb, offset+12, 6)); to_server = ADDRESSES_EQUAL(&tmp_addr, &pinfo->dl_src); } else if (pinfo->destport == UDP_PORT_SLIMP3_V2) { to_server = TRUE; } else if (pinfo->srcport == UDP_PORT_SLIMP3_V2) { to_server = FALSE; } if (pinfo->destport == UDP_PORT_SLIMP3_V1) { to_server = TRUE; old_protocol = TRUE; } else if (pinfo->srcport == UDP_PORT_SLIMP3_V1) { to_server = FALSE; old_protocol = TRUE; } switch (opcode) { case SLIMP3_IR: /* IR code * * [0] 'i' as in "IR" * [1] 0x00 * [2..5] player's time since startup in ticks @625 KHz * [6] IR code id, ff=JVC, 02=SLIMP3 * [7] number of meaningful bits - 16 for JVC, 32 for SLIMP3 * [8..11] the 32-bit IR code * [12..17] reserved */ if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_ir, tvb, offset+8, 4, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); i1 = tvb_get_ntohl(tvb, offset+2); proto_tree_add_text(slimp3_tree, tvb, offset+2, 4, "Uptime: %u sec (%u ticks)", i1/625000, i1); i1 = tvb_get_guint8(tvb, offset+6); proto_tree_add_text(slimp3_tree, tvb, offset+6, 1, "Code identifier: 0x%0x: %s", i1, val_to_str(i1, slimp3_ir_types, "Unknown")); proto_tree_add_text(slimp3_tree, tvb, offset+7, 1, "Code bits: %d", tvb_get_guint8(tvb, offset+7)); i1 = tvb_get_ntohl(tvb, offset+8); /* Check the code to figure out which remote is being used. */ if (tvb_get_guint8(tvb, offset+6) == 0x02 && tvb_get_guint8(tvb, offset+7) == 32) { /* This is the custom SLIMP3 remote. */ proto_tree_add_text(slimp3_tree, tvb, offset+8, 4, "Infrared Code: %s: 0x%0x", val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown"), i1); } else if (tvb_get_guint8(tvb, offset+6) == 0xff && tvb_get_guint8(tvb, offset+7) == 16) { /* This is a JVC DVD player remote */ proto_tree_add_text(slimp3_tree, tvb, offset+8, 4, "Infrared Code: %s: 0x%0x", val_to_str(i1, slimp3_ir_codes_jvc, "Unknown"), i1); } else { /* Unknown code; just write it */ proto_tree_add_text(slimp3_tree, tvb, offset+8, 4, "Infrared Code: 0x%0x", i1); } } if (check_col(pinfo->cinfo, COL_INFO)) { i1 = tvb_get_ntohl(tvb, offset+8); if (tvb_get_guint8(tvb, offset+6) == 0x02 && tvb_get_guint8(tvb, offset+7) == 32) { col_append_fstr(pinfo->cinfo, COL_INFO, ", SLIMP3: %s", val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown (0x%0x)")); } else if (tvb_get_guint8(tvb, offset+6) == 0xff && tvb_get_guint8(tvb, offset+7) == 16) { col_append_fstr(pinfo->cinfo, COL_INFO, ", JVC: %s", val_to_str(i1, slimp3_ir_codes_jvc, "Unknown (0x%0x)")); } else { /* Unknown code; just write it */ col_append_fstr(pinfo->cinfo, COL_INFO, ", 0x%0x", i1); } } break; case SLIMP3_DISPLAY: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_display, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); /* Loop through the commands */ i1 = 18; in_str = FALSE; lcd_strlen = 0; while (i1 < tvb_reported_length_remaining(tvb, offset)) { switch(tvb_get_guint8(tvb, offset + i1)) { case 0: in_str = FALSE; lcd_strlen = 0; proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2, "Delay (%d ms)", tvb_get_guint8(tvb, offset + i1 + 1)); i1 += 2; break; case 3: lcd_char = tvb_get_guint8(tvb, offset + i1 + 1); if (!isprint(lcd_char)) lcd_char = '.'; if (ti && in_str) { lcd_strlen += 2; proto_item_append_text(ti, "%c", lcd_char); proto_item_set_len(ti, lcd_strlen); } else { ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2, "String: %c", lcd_char); in_str = TRUE; lcd_strlen = 2; } i1 += 2; break; case 2: in_str = FALSE; lcd_strlen = 0; ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2, "Command: %s", val_to_str(tvb_get_guint8(tvb, offset + i1 + 1), slimp3_display_commands, "Unknown (0x%0x)")); if ((tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30) { proto_item_append_text(ti, ": %s", val_to_str(tvb_get_guint8(tvb, offset + i1 + 2), slimp3_display_fset8, "Unknown (0x%0x)")); i1 += 2; } i1 += 2; break; default: proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2, "Unknown 0x%0x, 0x%0x", tvb_get_guint8(tvb, offset + i1), tvb_get_guint8(tvb, offset + i1 + 1)); i1 += 2; break; } } } if (check_col(pinfo->cinfo, COL_INFO)) { i1 = 18; lcd_strlen = 0; while (tvb_offset_exists(tvb, offset + i1) && lcd_strlen < MAX_LCD_STR_LEN) { switch (tvb_get_guint8(tvb, offset + i1)) { case 0: lcd_str[lcd_strlen++] = '.'; break; case 2: lcd_str[lcd_strlen++] = '|'; if (tvb_offset_exists(tvb, offset + i1 + 1) && (tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30) i1 += 2; break; case 3: if (tvb_offset_exists(tvb, offset + i1 + 1)) { if (lcd_strlen < 1 || lcd_str[lcd_strlen-1] != ' ' || tvb_get_guint8(tvb, offset + i1 + 1) != ' ') { lcd_char = tvb_get_guint8(tvb, offset + i1 + 1); lcd_str[lcd_strlen++] = isprint(lcd_char) ? lcd_char : '.'; } } } i1 += 2; } lcd_str[lcd_strlen] = '\0'; if (lcd_strlen > 0) col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", lcd_str); } break; case SLIMP3_CONTROL: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_control, tvb, offset+1, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s", val_to_str(tvb_get_guint8(tvb, offset+1), slimp3_stream_control, "Unknown (0x%0x)")); } if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str(tvb_get_guint8(tvb, offset+1), slimp3_stream_control, "Unknown (0x%0x)")); } break; case SLIMP3_HELLO: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_hello, tvb, offset+1, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (to_server) { guint8 fw_ver = 0; /* Hello response; client->server */ proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Response (Client --> Server)"); proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Device ID: %d", tvb_get_guint8(tvb, offset+1)); fw_ver = tvb_get_guint8(tvb, offset+2); proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)", fw_ver>>4, fw_ver & 0xf, fw_ver); } else { /* Hello request; server->client */ proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Request (Server --> Client)"); } } break; case SLIMP3_I2C: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_i2c, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (to_server) { /* Hello response; client->server */ proto_tree_add_text(slimp3_tree, tvb, offset, -1, "I2C Response (Client --> Server)"); } else { /* Hello request; server->client */ proto_tree_add_text(slimp3_tree, tvb, offset, -1, "I2C Request (Server --> Client)"); } } if (check_col(pinfo->cinfo, COL_INFO)) { if (to_server) { col_append_str(pinfo->cinfo, COL_INFO, ", Response"); } else { col_append_str(pinfo->cinfo, COL_INFO, ", Request"); } } break; case SLIMP3_DATA_REQ: if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data_request, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_text(slimp3_tree, tvb, offset+2, 2, "Requested offset: %d bytes.", tvb_get_ntohs(tvb, offset+2)*2); } if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Offset: %d bytes", tvb_get_ntohs(tvb, offset+2)*2); } break; case SLIMP3_DATA: /* MPEG data (v1.3 and later) * * [0] 'm' * [1..5] reserved * [6..7] Write pointer (in words) * [8..9] reserved * [10..11] Sequence number * [12..17] reserved * [18..] MPEG data */ if (tree) { hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (old_protocol) { proto_tree_add_text(slimp3_tree, tvb, offset, -1, "Length: %d bytes", tvb_reported_length_remaining(tvb, offset+18)); proto_tree_add_text(slimp3_tree, tvb, offset+2, 2, "Buffer offset: %d bytes.", tvb_get_ntohs(tvb, offset+2) * 2); } else { proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s", val_to_str(tvb_get_guint8(tvb, offset+1), slimp3_mpg_control, "Unknown (0x%0x)")); proto_tree_add_text(slimp3_tree, tvb, offset, -1, "Length: %d bytes", tvb_reported_length_remaining(tvb, offset+18)); proto_tree_add_text(slimp3_tree, tvb, offset+6, 2, "Write Pointer: %d", tvb_get_ntohs(tvb, offset+6) * 2); proto_tree_add_text(slimp3_tree, tvb, offset+10, 2, "Sequence: %d", tvb_get_ntohs(tvb, offset+10)); } } if (check_col(pinfo->cinfo, COL_INFO)) { if (old_protocol) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Length: %d bytes, Offset: %d bytes.", tvb_reported_length_remaining(tvb, offset+18), tvb_get_ntohs(tvb, offset+2) * 2); } else { col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, %d bytes at %d, Sequence: %d", val_to_str(tvb_get_guint8(tvb, offset+1), slimp3_mpg_control, "Unknown (0x%0x)"), tvb_reported_length_remaining(tvb, offset+18), tvb_get_ntohs(tvb, offset+6) * 2, tvb_get_ntohs(tvb, offset+10)); } } break; case SLIMP3_DISC_REQ: if (tree) { guint8 fw_ver; hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_discover_request, tvb, offset, 1, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Device ID: %d.", tvb_get_guint8(tvb, offset+1)); fw_ver = tvb_get_guint8(tvb, offset+2); proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)", fw_ver>>4, fw_ver & 0xf, fw_ver); } if (check_col(pinfo->cinfo, COL_INFO)) { guint8 fw_ver = tvb_get_guint8(tvb, offset+2); col_append_fstr(pinfo->cinfo, COL_INFO, ", Device ID: %d. Firmware: %d.%d", tvb_get_guint8(tvb, offset+1), fw_ver>>4, fw_ver & 0xf); }
static void dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree) { guint32 label, dpc, opc; proto_item *label_item, *label_dpc_item, *label_opc_item; proto_item *hidden_item; proto_tree *label_tree; proto_tree *pc_subtree; int hf_dpc_string; int hf_opc_string; switch (mtp3_standard) { case ITU_STANDARD: label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); label = tvb_get_letohl(tvb, ROUTING_LABEL_OFFSET); opc = (label & ITU_OPC_MASK) >> 14; dpc = label & ITU_DPC_MASK; hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); PROTO_ITEM_SET_HIDDEN(hidden_item); label_dpc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); if (mtp3_pc_structured()) proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc)); if(mtp3_addr_dpc->ni == MTP3_NI_INT0) { pc_subtree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc); analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); } label_opc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); if (mtp3_pc_structured()) proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc)); if(mtp3_addr_opc->ni == MTP3_NI_INT0) { pc_subtree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc); analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); } proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); break; case ANSI_STANDARD: case CHINESE_ITU_STANDARD: if (mtp3_standard == ANSI_STANDARD) { hf_dpc_string = hf_mtp3_ansi_dpc; hf_opc_string = hf_mtp3_ansi_opc; } else /* CHINESE_ITU_STANDARD */ { hf_dpc_string = hf_mtp3_chinese_dpc; hf_opc_string = hf_mtp3_chinese_opc; } /* Create the Routing Label Tree */ label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ANSI_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); /* create and fill the DPC tree */ dissect_mtp3_3byte_pc(tvb, ANSI_DPC_OFFSET, label_tree, ett_mtp3_label_dpc, hf_dpc_string, hf_mtp3_dpc_network, hf_mtp3_dpc_cluster, hf_mtp3_dpc_member, hf_mtp3_24bit_dpc, hf_mtp3_24bit_pc); /* Store dpc for mtp3_addr below */ dpc = tvb_get_letoh24(tvb, ANSI_DPC_OFFSET); /* create and fill the OPC tree */ dissect_mtp3_3byte_pc(tvb, ANSI_OPC_OFFSET, label_tree, ett_mtp3_label_opc, hf_opc_string, hf_mtp3_opc_network, hf_mtp3_opc_cluster, hf_mtp3_opc_member, hf_mtp3_24bit_opc, hf_mtp3_24bit_pc); /* Store opc for mtp3_addr below */ opc = tvb_get_letoh24(tvb, ANSI_OPC_OFFSET); /* SLS */ if (mtp3_standard == ANSI_STANDARD) { if (mtp3_use_ansi_5_bit_sls) proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); else proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } else /* CHINESE_ITU_STANDARD */ { proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } break; case JAPAN_STANDARD: label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, JAPAN_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); label_dpc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_dpc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); dpc = tvb_get_letohs(tvb, ROUTING_LABEL_OFFSET); if (mtp3_pc_structured()) { proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc)); } label_opc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_opc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); opc = tvb_get_letohs(tvb, JAPAN_OPC_OFFSET); if (mtp3_pc_structured()) { proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc)); } hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (mtp3_use_japan_5_bit_sls) { proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); } else { proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); } break; default: DISSECTOR_ASSERT_NOT_REACHED(); } mtp3_addr_opc->type = (Standard_Type)mtp3_standard; mtp3_addr_opc->pc = opc; SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc); mtp3_addr_dpc->type = (Standard_Type)mtp3_standard; mtp3_addr_dpc->pc = dpc; SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc); }
static void display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, socks_hash_entry_t *hash_info) { /* Display the protocol tree for the version. This routine uses the */ /* stored conversation information to decide what to do with the row. */ /* Per packet information would have been better to do this, but we */ /* didn't have that when I wrote this. And I didn't expect this to get */ /* so messy. */ unsigned int i, command; guint temp; const char *AuthMethodStr; guint8 auth_status; proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, FALSE); ++offset; if (compare_packet( hash_info->connect_row)){ proto_tree *AuthTree; proto_item *ti; temp = tvb_get_guint8(tvb, offset); /* Get Auth method count */ /* build auth tree */ ti = proto_tree_add_text( tree, tvb, offset, -1, "Client Authentication Methods"); AuthTree = proto_item_add_subtree(ti, ett_socks_auth); proto_tree_add_text( AuthTree, tvb, offset, 1, "Count: %u", temp); ++offset; for( i = 0; i < temp; ++i) { AuthMethodStr = get_auth_method_name( tvb_get_guint8( tvb, offset)); proto_tree_add_text( AuthTree, tvb, offset, 1, "Method[%u]: %u (%s)", i, tvb_get_guint8( tvb, offset), AuthMethodStr); ++offset; } proto_item_set_end( ti, tvb, offset); return; } /* Get accepted auth method */ else if (compare_packet( hash_info->auth_method_row)) { proto_tree_add_text( tree, tvb, offset, 1, "Accepted Auth Method: 0x%0x (%s)", tvb_get_guint8( tvb, offset), get_auth_method_name( tvb_get_guint8( tvb, offset))); return; } /* handle user/password auth */ else if (compare_packet( hash_info->user_name_auth_row)) { /* process user name */ offset += display_string( tvb, offset, tree, "User name"); /* process password */ offset += display_string( tvb, offset, tree, "Password"); } /* command to the server */ /* command response from server */ else if (compare_packet( hash_info->auth_version)) { auth_status = tvb_get_guint8(tvb, offset); if(auth_status != 0) proto_tree_add_text( tree, tvb, offset, 1, "Status: %u (failure)", auth_status); else proto_tree_add_text( tree, tvb, offset, 1, "Status: success"); offset ++; } else if (compare_packet( hash_info->gssapi_auth_row)) { guint16 len; proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, FALSE); proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, FALSE); len = tvb_get_ntohs(tvb, offset+1); if (len > 0) proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, FALSE); } else if (compare_packet( hash_info->gssapi_auth_failure_row)) { proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, FALSE); } else if (compare_packet( hash_info->gssapi_auth_reply_row)) { guint16 len; proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, FALSE); proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, FALSE); len = tvb_get_ntohs(tvb, offset+1); if (len > 0) proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, FALSE); } else if ((compare_packet( hash_info->command_row)) || (compare_packet( hash_info->cmd_reply_row)) || (compare_packet( hash_info->bind_reply_row))){ command = tvb_get_guint8(tvb, offset); if (compare_packet( hash_info->command_row)) proto_tree_add_uint( tree, hf_socks_cmd, tvb, offset, 1, command); else { proto_item *hidden_item; proto_tree_add_item( tree, hf_socks_results_5, tvb, offset, 1, FALSE); hidden_item = proto_tree_add_item(tree, hf_socks_results, tvb, offset, 1, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); } ++offset; proto_tree_add_text( tree, tvb, offset, 1, "Reserved: 0x%0x (should = 0x00)", tvb_get_guint8(tvb, offset)); ++offset; offset = display_address(tvb, offset, tree); /*XXX Add remote port for search somehow */ /* Do remote port */ proto_tree_add_text( tree, tvb, offset, 2, "%sPort: %u", (compare_packet( hash_info->bind_reply_row) ? "Remote Host " : ""), tvb_get_ntohs(tvb, offset)); } }
static void dissect_xmpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { xml_frame_t *xml_frame; gboolean out_packet; conversation_t *conversation; xmpp_conv_info_t *xmpp_info; proto_tree *xmpp_tree = NULL; proto_item *xmpp_item = NULL; xmpp_element_t *packet = NULL; /*check if desegment * now it checks that last char is '>', * TODO checks that first element in packet is closed*/ int indx; gchar last_char; if (xmpp_desegment) { indx = tvb_reported_length(tvb) - 1; if (indx >= 0) { last_char = tvb_get_guint8(tvb, indx); while ((last_char <= ' ') && (indx - 1 >= 0)) { indx--; last_char = tvb_get_guint8(tvb, indx); } if ((indx >= 0) && (last_char != '>')) { pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return; } } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "XMPP"); col_clear(pinfo->cinfo, COL_INFO); conversation = find_or_create_conversation(pinfo); xmpp_info = (xmpp_conv_info_t *)conversation_get_proto_data(conversation, proto_xmpp); if (xmpp_info && xmpp_info->ssl_proceed && xmpp_info->ssl_proceed < pinfo->fd->num) { call_dissector(ssl_handle, tvb, pinfo, tree); return; } /*if tree == NULL then xmpp_item and xmpp_tree will also NULL*/ xmpp_item = proto_tree_add_item(tree, proto_xmpp, tvb, 0, -1, ENC_NA); xmpp_tree = proto_item_add_subtree(xmpp_item, ett_xmpp); call_dissector(xml_handle, tvb, pinfo, xmpp_tree); /* If XML dissector is disabled, we can't do much */ if (!proto_is_protocol_enabled(find_protocol_by_id(dissector_handle_get_protocol_index(xml_handle)))) { col_append_str(pinfo->cinfo, COL_INFO, "(XML dissector disabled, can't dissect XMPP)"); expert_add_info_format(pinfo, xmpp_item, PI_UNDECODED, PI_WARN, "XML dissector disabled, can't dissect XMPP"); return; } /*if stream end occurs then return*/ if(xmpp_stream_close(xmpp_tree,tvb, pinfo)) { if(xmpp_tree) xmpp_proto_tree_hide_first_child(xmpp_tree); return; } if(!pinfo->private_data) return; /*data from XML dissector*/ xml_frame = ((xml_frame_t*)pinfo->private_data)->first_child; if(!xml_frame) return; if (!xmpp_info) { xmpp_info = se_new(xmpp_conv_info_t); xmpp_info->req_resp = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_req_resp"); xmpp_info->jingle_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_jingle_sessions"); xmpp_info->ibb_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_ibb_sessions"); xmpp_info->gtalk_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_gtalk_sessions"); xmpp_info->ssl_start = 0; xmpp_info->ssl_proceed = 0; conversation_add_proto_data(conversation, proto_xmpp, (void *) xmpp_info); } if (pinfo->match_uint == pinfo->destport) out_packet = TRUE; else out_packet = FALSE; while(xml_frame) { packet = xmpp_xml_frame_to_element_t(xml_frame, NULL, tvb); DISSECTOR_ASSERT(packet); if (strcmp(packet->name, "iq") == 0) { xmpp_iq_reqresp_track(pinfo, packet, xmpp_info); xmpp_jingle_session_track(pinfo, packet, xmpp_info); xmpp_gtalk_session_track(pinfo, packet, xmpp_info); } if (strcmp(packet->name, "iq") == 0 || strcmp(packet->name, "message") == 0) { xmpp_ibb_session_track(pinfo, packet, xmpp_info); } if (tree) { /* we are being asked for details */ proto_item *outin_item; if (out_packet) outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_out, tvb, 0, 0, TRUE); else outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_in, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(outin_item); /*it hides tree generated by XML dissector*/ xmpp_proto_tree_hide_first_child(xmpp_tree); if (strcmp(packet->name, "iq") == 0) { xmpp_iq(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "presence") == 0) { xmpp_presence(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "message") == 0) { xmpp_message(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "auth") == 0) { xmpp_auth(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "challenge") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_challenge, ett_xmpp_challenge, "CHALLENGE"); } else if (strcmp(packet->name, "response") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_response, ett_xmpp_response, "RESPONSE"); } else if (strcmp(packet->name, "success") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_success, ett_xmpp_success, "SUCCESS"); } else if (strcmp(packet->name, "failure") == 0) { xmpp_failure(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "xml") == 0) { xmpp_xml_header(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "stream") == 0) { xmpp_stream(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "features") == 0) { xmpp_features(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "starttls") == 0) { xmpp_starttls(xmpp_tree, tvb, pinfo, packet, xmpp_info); }else if (strcmp(packet->name, "proceed") == 0) { xmpp_proceed(xmpp_tree, tvb, pinfo, packet, xmpp_info); }else { xmpp_proto_tree_show_first_child(xmpp_tree); expert_add_info_format(pinfo, xmpp_tree, PI_UNDECODED, PI_NOTE, "Unknown packet: %s", packet->name); col_clear(pinfo->cinfo, COL_INFO); col_append_fstr(pinfo->cinfo, COL_INFO, "UNKNOWN PACKET "); } /*appends to COL_INFO information about src or dst*/ if (pinfo->match_uint == pinfo->destport) { xmpp_attr_t *to = xmpp_get_attr(packet, "to"); if (to) col_append_fstr(pinfo->cinfo, COL_INFO, "> %s ", to->value); } else { xmpp_attr_t *from = xmpp_get_attr(packet, "from"); if (from) col_append_fstr(pinfo->cinfo, COL_INFO, "< %s ", from->value); } } xmpp_element_t_tree_free(packet); xml_frame = xml_frame->next_sibling; } }
static void dissect_gift(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti, *hidden_item; proto_tree *gift_tree, *cmd_tree; gboolean is_request; gint offset = 0; const guchar *line; gint next_offset; int linelen; int tokenlen; const guchar *next_token; /* set "Protocol" column text */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "giFT"); /* determine whether it is a request to or response from the server */ if (pinfo->match_uint == pinfo->destport) is_request = TRUE; else is_request = FALSE; linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); /* set "Info" column text */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); /* if tree != NULL, build protocol tree */ if (tree) { ti = proto_tree_add_item(tree, proto_gift, tvb, 0, -1, ENC_NA); gift_tree = proto_item_add_subtree(ti, ett_gift); if (is_request) { hidden_item = proto_tree_add_boolean(gift_tree, hf_gift_request, tvb, 0, 0, TRUE); } else { hidden_item = proto_tree_add_boolean(gift_tree, hf_gift_response, tvb, 0, 0, TRUE); } PROTO_ITEM_SET_HIDDEN(hidden_item); ti = proto_tree_add_format_text(gift_tree, tvb, offset, next_offset - offset); cmd_tree = proto_item_add_subtree(ti, ett_gift_cmd); tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { if (is_request) { proto_tree_add_string(cmd_tree, hf_gift_request_cmd, tvb, offset, tokenlen, format_text(line, tokenlen)); } else { proto_tree_add_string(cmd_tree, hf_gift_response_cmd, tvb, offset, tokenlen, format_text(line, tokenlen)); } offset += (gint) (next_token - line); linelen -= (int) (next_token - line); line = next_token; } if (linelen != 0) { if (is_request) { proto_tree_add_string(cmd_tree, hf_gift_request_arg, tvb, offset, linelen, format_text(line, linelen)); } else { proto_tree_add_string(cmd_tree, hf_gift_response_arg, tvb, offset, linelen, format_text(line, linelen)); } } } }
/* XXX: Are all the tests against tvb_length() really the right way to handle invalid fields ? * It seems to me that invalid fields should just add an expert item * or cause a "Malformed" exception. */ static void dissect_elcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request, length_ok; proto_tree *elcom_tree; proto_item *ti, *hidden_item; gint offset = 0; guint elcom_len; guint8 elcom_msg_type; guint8 *suffix; /* Check that there's enough data */ if (tvb_length(tvb) < 3) return; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ELCOM"); col_clear(pinfo->cinfo, COL_INFO); is_request = (pinfo->match_uint == pinfo->destport); elcom_len = tvb_get_ntohs(tvb, 0); length_ok = (tvb_reported_length(tvb) == (elcom_len+2)); col_add_fstr(pinfo->cinfo, COL_INFO, "%s Len=%d%s", is_request ? "Request" : "Response", elcom_len, length_ok ? "" : " (incorrect)"); elcom_msg_type = tvb_get_guint8(tvb, 2); switch (elcom_msg_type) { case P_CONRQ: case P_CONRS: /* starting after elcom_len and elcom_msg_type, initiator + responder + userdata fields must be there */ if (tvb_length_remaining(tvb, 3+TOTAL_LEN+TOTAL_LEN+3) < 0) return; /* check also that those field lengths are valid */ if (tvb_get_guint8(tvb, 3) != LOWADR_LEN) return; if (tvb_get_guint8(tvb, 3+1+LOWADR_LEN) != SUFFIX_LEN) return; if (tvb_get_guint8(tvb, 3+TOTAL_LEN) != LOWADR_LEN) return; if (tvb_get_guint8(tvb, 3+1+TOTAL_LEN+LOWADR_LEN) != SUFFIX_LEN) return; /* finally believe that there is valid suffix */ suffix = tvb_get_string_enc(wmem_packet_scope(), tvb, 3+2+LOWADR_LEN, 2, ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, " %s Connect", suffix); break; case P_RELRQ: case P_RELRS: col_append_str(pinfo->cinfo, COL_INFO, " Release"); break; case P_DATRQ: col_append_str(pinfo->cinfo, COL_INFO, " Data"); break; } switch (elcom_msg_type) { case P_CONRQ: case P_RELRQ: col_append_str(pinfo->cinfo, COL_INFO, " Request"); break; case P_CONRS: case P_RELRS: col_append_str(pinfo->cinfo, COL_INFO, " Response"); break; } if (!tree) return; ti = proto_tree_add_item(tree, proto_elcom, tvb, offset, -1, ENC_NA); elcom_tree = proto_item_add_subtree(ti, ett_elcom); hidden_item = proto_tree_add_boolean(elcom_tree, is_request ? hf_elcom_request : hf_elcom_response, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); /* 2 first bytes are the frame length */ offset = 0; ti = proto_tree_add_item(elcom_tree, hf_elcom_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset = +2; if (! length_ok) { proto_item_append_text(ti, " (incorrect)"); } elcom_msg_type = tvb_get_guint8(tvb, offset); ti = proto_tree_add_item(elcom_tree, hf_elcom_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(elcom_tree, " ( %s)", val_to_str(elcom_msg_type, type_vals, "Unknown %d")); offset++; if (tvb_length_remaining(tvb, offset) <= 0) return; switch (elcom_msg_type) { case P_CONRQ: case P_CONRS: /* * Connection request/release assiciated PDU's, * /ELCOM-90 P Protocol spec/ p. 85... */ /* We need the length here, hardcode the LOWADR_LEN = 21 */ ti = proto_tree_add_item(elcom_tree, hf_elcom_initiator, tvb, offset, TOTAL_LEN, ENC_NA); offset = dissect_lower_address(ti, ett_elcom_initiator, tvb, offset, hf_elcom_initiator_endian, hf_elcom_initiator_ip, hf_elcom_initiator_port, hf_elcom_initiator_suff); if (tvb_length_remaining(tvb, offset) <= 0) return; ti = proto_tree_add_item(elcom_tree, hf_elcom_responder, tvb, offset, TOTAL_LEN, ENC_NA); offset = dissect_lower_address(ti, ett_elcom_responder, tvb, offset, hf_elcom_responder_endian, hf_elcom_responder_ip, hf_elcom_responder_port, hf_elcom_responder_suff); if (tvb_length_remaining(tvb, offset) <= 0) return; /* Rest of the payload is USER-DATA, 0..82 bytes */ ti = proto_tree_add_item(elcom_tree, hf_elcom_userdata, tvb, offset, -1, ENC_NA); offset = dissect_userdata(ti, ett_elcom_userdata, tvb, offset); break; case P_RELRQ: proto_tree_add_item(elcom_tree, hf_elcom_release_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case P_RELRS: proto_tree_add_item(elcom_tree, hf_elcom_release_result, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case P_DATRQ: ti = proto_tree_add_item(elcom_tree, hf_elcom_datarequest, tvb, offset, -1, ENC_NA); offset = dissect_datarequest(ti, ett_elcom_datarequest, tvb, offset); break; default: proto_item_append_text(ti, " <<--- meaning WHAT??"); break; } if (tvb_length_remaining(tvb, offset) > 0) { /* We should not get here, but if we do, show what is left over: */ proto_tree_add_item(elcom_tree, hf_elcom_strangeleftover, tvb, offset, -1, ENC_NA); } }
/* * dissect_pgm - The dissector for Pragmatic General Multicast */ static void dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 pgmhdr_sport; guint16 pgmhdr_dport; guint8 pgmhdr_type; guint8 pgmhdr_opts; guint16 pgmhdr_cksum; guint16 pgmhdr_tsdulen; guint32 sqn; guint16 afi; guint plen = 0; proto_item *ti; const char *pktname; const char *pollstname; char *gsi; gboolean isdata = FALSE; guint pgmlen, reportedlen; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGM"); if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); if (tvb_reported_length_remaining(tvb, 0) < 18) { col_set_str(pinfo->cinfo, COL_INFO, "Packet too small"); return; } } pinfo->srcport = pgmhdr_sport = tvb_get_ntohs(tvb, 0); pinfo->destport = pgmhdr_dport = tvb_get_ntohs(tvb, 2); pgmhdr_type = tvb_get_guint8(tvb, 4); pktname = val_to_str(pgmhdr_type, type_vals, "Unknown (0x%02x)"); pgmhdr_opts = tvb_get_guint8(tvb, 5); pgmhdr_cksum = tvb_get_ntohs(tvb, 6); gsi = tvb_bytes_to_str(tvb, 8, 6); pgmhdr_tsdulen = tvb_get_ntohs(tvb, 14); sqn = tvb_get_ntohl(tvb, 16); switch(pgmhdr_type) { case PGM_SPM_PCKT: case PGM_NAK_PCKT: case PGM_NNAK_PCKT: case PGM_NCF_PCKT: case PGM_POLR_PCKT: case PGM_ACK_PCKT: if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s", pktname, sqn, gsi); } break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, sqn, gsi, pgmhdr_tsdulen); } isdata = TRUE; break; case PGM_POLL_PCKT: { guint16 poll_stype = tvb_get_ntohs(tvb, 22); pollstname = val_to_str(poll_stype, poll_subtype_vals, "Unknown (0x%02x)"); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s subtype %s", pktname, sqn, gsi, pollstname); } } break; default: return; } { proto_tree *pgm_tree = NULL; proto_tree *opt_tree = NULL; proto_tree *type_tree = NULL; proto_item *tf, *hidden_item; ptvcursor_t* cursor; ti = proto_tree_add_protocol_format(tree, proto_pgm, tvb, 0, -1, "Pragmatic General Multicast: Type %s" " Src Port %u, Dst Port %u, GSI %s", pktname, pgmhdr_sport, pgmhdr_dport, gsi); pgm_tree = proto_item_add_subtree(ti, ett_pgm); cursor = ptvcursor_new(pgm_tree, tvb, 0); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 0, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 2, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); ptvcursor_add(cursor, hf_pgm_main_sport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_dport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_type, 1, ENC_BIG_ENDIAN); tf = proto_tree_add_uint_format(pgm_tree, hf_pgm_main_opts, tvb, ptvcursor_current_offset(cursor), 1, pgmhdr_opts, "Options: %s (0x%x)", optsstr(pgmhdr_opts), pgmhdr_opts); opt_tree = proto_item_add_subtree(tf, ett_pgm_optbits); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_opt, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_netsig, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_varlen, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_opts_parity, 1, ENC_BIG_ENDIAN); ptvcursor_set_tree(cursor, pgm_tree); /* Checksum may be 0 (not available), but not for DATA packets */ if ((pgmhdr_type != PGM_RDATA_PCKT) && (pgmhdr_type != PGM_ODATA_PCKT) && (pgmhdr_cksum == 0)) { proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: not available"); } else { reportedlen = tvb_reported_length(tvb); pgmlen = tvb_length(tvb); if (pgm_check_checksum && pgmlen >= reportedlen) { vec_t cksum_vec[1]; guint16 computed_cksum; cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pgmlen); cksum_vec[0].len = pgmlen; computed_cksum = in_cksum(&cksum_vec[0], 1); if (computed_cksum == 0) { proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 0x%04x [correct]", pgmhdr_cksum); } else { hidden_item = proto_tree_add_boolean(pgm_tree, hf_pgm_main_cksum_bad, tvb, ptvcursor_current_offset(cursor), 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 0x%04x [incorrect, should be 0x%04x]", pgmhdr_cksum, in_cksum_shouldbe(pgmhdr_cksum, computed_cksum)); } } else { ptvcursor_add_no_advance(cursor, hf_pgm_main_cksum, 2, ENC_BIG_ENDIAN); } } ptvcursor_advance(cursor, 2); ptvcursor_add(cursor, hf_pgm_main_gsi, 6, ENC_NA); ptvcursor_add(cursor, hf_pgm_main_tsdulen, 2, ENC_BIG_ENDIAN); tf = proto_tree_add_text(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, "%s Packet", pktname); switch(pgmhdr_type) { case PGM_SPM_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_spm); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_lead, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_spm_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_spm_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_spm_path6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); return; } break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_data); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); break; case PGM_NAK_PCKT: case PGM_NNAK_PCKT: case PGM_NCF_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_nak); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_nak_sqn, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_nak_srcafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_srcres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_src, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_src6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_nak_grpafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_grpres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_grp, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_grp6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); return; } break; case PGM_POLL_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_poll); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_poll_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_subtype, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_poll_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_poll_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_poll_path6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } ptvcursor_add(cursor, hf_pgm_poll_backoff_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_rand_str, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_matching_bmask, 4, ENC_BIG_ENDIAN); break; case PGM_POLR_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_polr); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_polr_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_res, 2, ENC_BIG_ENDIAN); break; case PGM_ACK_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_ack); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_ack_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_ack_bitmap, 4, ENC_BIG_ENDIAN); break; } if (pgmhdr_opts & PGM_OPT) dissect_pgmopts(cursor, pktname); if (isdata) decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport); } }
static void dissect_pw_satop(tvbuff_t * tvb_original ,packet_info * pinfo ,proto_tree * tree ,pwc_demux_type_t demux) { const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/ gint packet_size; gint payload_size; gint padding_size; int properties; enum { PAY_NO_IDEA = 0 ,PAY_LIKE_E1 ,PAY_LIKE_T1 ,PAY_LIKE_E3_T3 ,PAY_LIKE_OCTET_ALIGNED_T1 } payload_properties; packet_size = tvb_reported_length_remaining(tvb_original, 0); /* * FIXME * "4" below should be replaced by something like "min_packet_size_this_dissector" * Also call to dissect_try_cw_first_nibble() should be moved before this block */ if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */ { proto_item *item; item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA); expert_add_info_format(pinfo, item, &ei_cw_packet_size_too_small, "PW packet size (%d) is too small to carry sensible information" ,(int)packet_size); col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname); col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small"); return; } switch (demux) { case PWC_DEMUX_MPLS: if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree)) { return; } break; case PWC_DEMUX_UDP: break; default: DISSECTOR_ASSERT_NOT_REACHED(); return; } /* check how "good" is this packet */ /* also decide payload length from packet size and CW */ properties = 0; if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/)) { properties |= PWC_CW_BAD_BITS03; } if (0 != (tvb_get_guint8(tvb_original, 0) & 0x03 /*rsv*/)) { properties |= PWC_CW_BAD_RSV; } if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/)) { properties |= PWC_CW_BAD_FRAG; } { /* RFC4553: * [...MAY be used to carry the length of the SAToP * packet (defined as the size of the SAToP header + the payload * size) if it is less than 64 bytes, and MUST be set to zero * otherwise... ] * * Note that this differs from RFC4385's definition of length: * [ If the MPLS payload is less than 64 bytes, the length field * MUST be set to the length of the PW payload...] * * We will use RFC4553's definition here. */ int cw_len; gint payload_size_from_packet; cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f; payload_size_from_packet = packet_size - encaps_size; if (cw_len != 0) { gint payload_size_from_cw; payload_size_from_cw = cw_len - encaps_size; /* * Assumptions for error case, * will be overwritten if no errors found: */ payload_size = payload_size_from_packet; padding_size = 0; if (payload_size_from_cw < 0) { properties |= PWC_CW_BAD_PAYLEN_LT_0; } else if (payload_size_from_cw > payload_size_from_packet) { properties |= PWC_CW_BAD_PAYLEN_GT_PACKET; } else if (payload_size_from_packet >= 64) { properties |= PWC_CW_BAD_LEN_MUST_BE_0; } else /* ok */ { payload_size = payload_size_from_cw; padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */ } } else { payload_size = payload_size_from_packet; padding_size = 0; } } if (payload_size == 0) { /* * As CW.L it indicates that PW payload is invalid, dissector should * not blame packets with bad payload (including "bad" or "strange" SIZE of * payload) when L bit is set. */ if (0 == (tvb_get_guint8(tvb_original, 0) & 0x08 /*L bit*/)) { properties |= PWC_PAY_SIZE_BAD; } } /* guess about payload type */ if (payload_size == 256) { payload_properties = PAY_LIKE_E1; } else if (payload_size == 192) { payload_properties = PAY_LIKE_T1; } else if (payload_size == 1024) { payload_properties = PAY_LIKE_E3_T3; } else if ((payload_size != 0) && (payload_size % 25 == 0)) { payload_properties = PAY_LIKE_OCTET_ALIGNED_T1; } else { payload_properties = PAY_NO_IDEA; /*we do not have any ideas about payload type*/ } /* fill up columns*/ col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname); col_clear(pinfo->cinfo, COL_INFO); if (properties & PWC_ANYOF_CW_BAD) { col_set_str(pinfo->cinfo, COL_INFO, "CW:Bad, "); } if (properties & PWC_PAY_SIZE_BAD) { col_append_str(pinfo->cinfo, COL_INFO, "Payload size:0 (Bad)"); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size); } if (padding_size != 0) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Padding:%d", (int)padding_size); } { proto_item* item; item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA); pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE); pwc_item_append_text_n_items(item,(int)payload_size,"octet"); { proto_tree* tree2; tree2 = proto_item_add_subtree(item, ett); { tvbuff_t* tvb; proto_item* item2; tvb = tvb_new_subset_length(tvb_original, 0, PWC_SIZEOF_CW); item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA); pwc_item_append_cw(item2, tvb_get_ntohl(tvb, 0),FALSE); { proto_tree* tree3; tree3 = proto_item_add_subtree(item2, ett); { proto_item* item3; if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/ { item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN); expert_add_info(pinfo, item3, &ei_cw_bits03); } proto_tree_add_item(tree3, hf_cw_l , tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree3, hf_cw_r , tvb, 0, 1, ENC_BIG_ENDIAN); item3 = proto_tree_add_item(tree3, hf_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN); if (properties & PWC_CW_BAD_RSV) { expert_add_info(pinfo, item3, &ei_cw_rsv); } item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN); if (properties & PWC_CW_BAD_FRAG) { expert_add_info(pinfo, item3, &ei_cw_frg); } item3 = proto_tree_add_item(tree3, hf_cw_len, tvb, 1, 1, ENC_BIG_ENDIAN); if (properties & PWC_CW_BAD_PAYLEN_LT_0) { expert_add_info_format(pinfo, item3, &ei_payload_size_invalid, "Bad Length: too small, must be > %d", (int)encaps_size); } if (properties & PWC_CW_BAD_PAYLEN_GT_PACKET) { expert_add_info_format(pinfo, item3, &ei_payload_size_invalid, "Bad Length: must be <= than PSN packet size (%d)", (int)packet_size); } if (properties & PWC_CW_BAD_LEN_MUST_BE_0) { expert_add_info_format(pinfo, item3, &ei_payload_size_invalid, "Bad Length: must be 0 if SAToP packet size (%d) is > 64", (int)packet_size); } proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN); } } } } /* payload */ if (properties & PWC_PAY_SIZE_BAD) { expert_add_info_format(pinfo, item, &ei_payload_size_invalid, "SAToP payload: none found. Size of payload must be <> 0"); } else if (payload_size == 0) { expert_add_info(pinfo, item, &ei_payload_size_invalid_undecoded); } else { proto_tree* tree2; tree2 = proto_item_add_subtree(item, ett); { proto_item* item2; tvbuff_t* tvb; tvb = tvb_new_subset_length(tvb_original, PWC_SIZEOF_CW, payload_size); item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA); pwc_item_append_text_n_items(item2,(int)payload_size,"octet"); { proto_tree* tree3; const char* s; switch(payload_properties) { case PAY_LIKE_E1: s = " (looks like E1)"; break; case PAY_LIKE_T1: s = " (looks like T1)"; break; case PAY_LIKE_E3_T3: s = " (looks like E3/T3)"; break; case PAY_LIKE_OCTET_ALIGNED_T1: s = " (looks like octet-aligned T1)"; break; case PAY_NO_IDEA: default: s = ""; break; } proto_item_append_text(item2, "%s", s); tree3 = proto_item_add_subtree(item2, ett); call_dissector(data_handle, tvb, pinfo, tree3); item2 = proto_tree_add_int(tree3, hf_payload_l, tvb, 0, 0 ,(int)payload_size); /* allow filtering */ PROTO_ITEM_SET_HIDDEN(item2); } } } /* padding */ if (padding_size > 0) { proto_tree* tree2; tree2 = proto_item_add_subtree(item, ett); { tvbuff_t* tvb; tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1); call_dissector(pw_padding_handle, tvb, pinfo, tree2); } } } return; }
/* Header */ static void dissect_cpfi_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint32 tda; guint32 src; guint8 src_instance = 0; guint8 src_board = 0; guint8 src_port = 0; guint32 dst; guint8 dst_instance = 0; guint8 dst_board = 0; guint8 dst_port = 0; proto_item *extra_item = NULL; proto_tree *extra_tree = NULL; proto_item *hidden_item; /* add a tree for the header */ if ( tree != NULL) { extra_item = proto_tree_add_protocol_format(tree, proto_cpfi, tvb, 0, -1, "Header"); extra_tree = proto_item_add_subtree(extra_item, ett_cpfi_header); } /* Extract the common header, and get the bits we need */ word1 = tvb_get_ntohl (tvb, 0); word2 = tvb_get_ntohl (tvb, sizeof(word1)); /* Figure out where the frame came from. dstTDA is source of frame! */ tda = (word1 & CPFI_DEST_MASK) >> CPFI_DEST_SHIFT; if ( tda >= FIRST_TIO_CARD_ADDRESS ) { g_strlcpy(src_str, " CPFI", sizeof(src_str)); src = 0; /* Make it smallest */ } else { const guint8 *srcmac; /* Make sure this is an Ethernet address. */ DISSECTOR_ASSERT(pinfo->src.type == AT_ETHER); srcmac = (const guint8 *)pinfo->src.data; src_instance = srcmac[2]-1; src_board = tda >> 4; src_port = tda & 0x0f; src = (1 << 24) + (src_instance << 16) + (src_board << 8) + src_port; g_snprintf(src_str, sizeof(src_str), "%u.%u.%u", src_instance, src_board, src_port); } /* Figure out where the frame is going. srcTDA is destination of frame! */ tda = (word1 & CPFI_SOURCE_MASK) >> CPFI_SOURCE_SHIFT; if ( tda >= FIRST_TIO_CARD_ADDRESS ) { g_strlcpy(dst_str, " CPFI", sizeof(dst_str)); dst = 0; /* Make it smallest */ } else { const guint8 *dstmac; /* Make sure this is an Ethernet address. */ DISSECTOR_ASSERT(pinfo->dst.type == AT_ETHER); dstmac = (const guint8 *)pinfo->dst.data; dst_instance = dstmac[2]-1; dst_board = tda >> 4; dst_port = tda & 0x0f; dst = (1 << 24) + (dst_instance << 16) + (dst_board << 8) + dst_port; g_snprintf(dst_str, sizeof(dst_str), "%u.%u.%u", dst_instance, dst_board, dst_port); } /* Set up the source and destination and arrow per user configuration. */ if ( cpfi_arrow_moves && (dst < src) ) { left = dst_str; arrow = r_to_l_arrow; right = src_str; } else { left = src_str; arrow = l_to_r_arrow; right = dst_str; } if (extra_tree) { /* For "real" TDAs (i.e. not for microTDAs), add hidden addresses to allow filtering */ if ( src != 0 ) { hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_instance, tvb, 0, 1, &src_instance); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_src_instance, tvb, 0, 1, &src_instance); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_board, tvb, 0, 1, &src_board); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_src_board, tvb, 0, 1, &src_board); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_port, tvb, 0, 1, &src_port); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_src_port, tvb, 0, 1, &src_port); PROTO_ITEM_SET_HIDDEN(hidden_item); } if ( dst != 0 ) { hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_instance, tvb, 0, 1, &dst_instance); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_dst_instance, tvb, 0, 1, &dst_instance); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_board, tvb, 0, 1, &dst_board); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_dst_board, tvb, 0, 1, &dst_board); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_port, tvb, 0, 1, &dst_port); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_dst_port, tvb, 0, 1, &dst_port); PROTO_ITEM_SET_HIDDEN(hidden_item); } /* add word 1 components to the protocol tree */ proto_tree_add_item(extra_tree, hf_cpfi_word_one , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_frame_type, tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_source , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_dest , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_SOF_type , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_speed , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_OPM_error , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_from_LCM , tvb, 0, 4, ENC_BIG_ENDIAN); /* add word 2 components to the protocol tree */ proto_tree_add_item(extra_tree, hf_cpfi_word_two , tvb, 4, 4, ENC_BIG_ENDIAN); }; }
static void dissect_fcp_cmnd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, proto_tree *tree, conversation_t *conversation, fc_hdr *fchdr, fcp_conv_data_t *fcp_conv_data) { int offset = 0; int add_len = 0; guint8 flags, rwflags, lun0; guint16 lun = 0xffff; tvbuff_t *cdb_tvb; int tvb_len, tvb_rlen; fcp_request_data_t *request_data = NULL; proto_item *hidden_item; fcp_proto_data_t *proto_data; /* Determine the length of the FCP part of the packet */ flags = tvb_get_guint8(tvb, offset+10); if (flags) { add_len = tvb_get_guint8(tvb, offset+11) & 0x7C; add_len = add_len >> 2; } hidden_item = proto_tree_add_uint(tree, hf_fcp_type, tvb, offset, 0, 0); PROTO_ITEM_SET_HIDDEN(hidden_item); lun0 = tvb_get_guint8(tvb, offset); /* Display single-level LUNs in decimal for clarity */ /* I'm taking a shortcut here by assuming that if the first byte of the * LUN field is 0, it is a single-level LUN. This is not true. For a * real single-level LUN, all 8 bytes except byte 1 must be 0. */ if (lun0) { proto_tree_add_item(tree, hf_fcp_multilun, tvb, offset, 8, ENC_NA); lun = tvb_get_guint8(tvb, offset) & 0x3f; lun <<= 8; lun |= tvb_get_guint8(tvb, offset+1); } else { proto_tree_add_item(tree, hf_fcp_singlelun, tvb, offset+1, 1, ENC_BIG_ENDIAN); lun = tvb_get_guint8(tvb, offset+1); } if (fchdr->itlq) fchdr->itlq->lun = lun; if (!pinfo->fd->flags.visited) { proto_data = wmem_new(wmem_file_scope(), fcp_proto_data_t); proto_data->lun = lun; p_add_proto_data(wmem_file_scope(), pinfo, proto_fcp, 0, proto_data); } request_data = (fcp_request_data_t*)wmem_tree_lookup32(fcp_conv_data->luns, lun); if (!request_data) { request_data = wmem_new(wmem_file_scope(), fcp_request_data_t); request_data->request_frame = pinfo->fd->num; request_data->response_frame = 0; request_data->request_time = pinfo->fd->abs_ts; request_data->itl = wmem_new(wmem_file_scope(), itl_nexus_t); request_data->itl->cmdset = 0xff; request_data->itl->conversation = conversation; wmem_tree_insert32(fcp_conv_data->luns, lun, request_data); } proto_tree_add_item(tree, hf_fcp_crn, tvb, offset+8, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fcp_taskattr, tvb, offset+9, 1, ENC_BIG_ENDIAN); dissect_task_mgmt_flags(pinfo, tree, tvb, offset+10); proto_tree_add_item(tree, hf_fcp_addlcdblen, tvb, offset+11, 1, ENC_BIG_ENDIAN); rwflags = tvb_get_guint8(tvb, offset+11); if (fchdr->itlq) { if (rwflags & 0x02) { fchdr->itlq->task_flags |= SCSI_DATA_READ; } if (rwflags & 0x01) { fchdr->itlq->task_flags |= SCSI_DATA_WRITE; } } proto_tree_add_item(tree, hf_fcp_rddata, tvb, offset+11, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fcp_wrdata, tvb, offset+11, 1, ENC_BIG_ENDIAN); tvb_len = tvb_length_remaining(tvb, offset+12); if (tvb_len > (16 + add_len)) tvb_len = 16 + add_len; tvb_rlen = tvb_reported_length_remaining(tvb, offset+12); if (tvb_rlen > (16 + add_len)) tvb_rlen = 16 + add_len; cdb_tvb = tvb_new_subset(tvb, offset+12, tvb_len, tvb_rlen); dissect_scsi_cdb(cdb_tvb, pinfo, parent_tree, SCSI_DEV_UNKNOWN, fchdr->itlq, request_data->itl); proto_tree_add_item(tree, hf_fcp_dl, tvb, offset+12+16+add_len, 4, ENC_BIG_ENDIAN); if (fchdr->itlq) { fchdr->itlq->data_length = tvb_get_ntohl(tvb, offset+12+16+add_len); } if ( ((rwflags & 0x03) == 0x03) && tvb_length_remaining(tvb, offset+12+16+add_len+4) >= 4) { proto_tree_add_item(tree, hf_fcp_bidir_dl, tvb, offset+12+16+add_len+4, 4, ENC_BIG_ENDIAN); if (fchdr->itlq) { fchdr->itlq->bidir_data_length = tvb_get_ntohl(tvb, offset+12+16+add_len+4); } } }
static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_tree *tns_tree) { proto_tree *data_tree = NULL, *ti; proto_item *hidden_item; int is_sns = 0; if ( tvb_bytes_exist(tvb, offset+2, 4) ) { if ( tvb_get_guint8(tvb, offset+2) == 0xDE && tvb_get_guint8(tvb, offset+3) == 0xAD && tvb_get_guint8(tvb, offset+4) == 0xBE && tvb_get_guint8(tvb, offset+5) == 0xEF ) { is_sns = 1; } } if ( tree ) { if ( is_sns ) { data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL, "Secure Network Services"); } else { data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL, "Data"); } hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_data, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } if ( tree ) { proto_tree *df_tree = NULL; ti = proto_tree_add_item(data_tree, hf_tns_data_flag, tvb, offset, 2, ENC_BIG_ENDIAN); df_tree = proto_item_add_subtree(ti, ett_tns_data_flag); proto_tree_add_item(df_tree, hf_tns_data_flag_send, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_rc, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_c, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_more, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_eof, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_dic, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_rts, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(df_tree, hf_tns_data_flag_sntt, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( is_sns ) { col_append_str(pinfo->cinfo, COL_INFO, ", SNS"); } else { col_append_str(pinfo->cinfo, COL_INFO, ", Data"); } call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, data_tree); return; }
static void dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto) { proto_tree *udp_tree = NULL; proto_item *ti, *hidden_item, *port_item; guint len; guint reported_len; vec_t cksum_vec[4]; guint32 phdr[2]; guint16 computed_cksum; int offset = 0; e_udphdr *udph; proto_tree *checksum_tree; proto_item *item; conversation_t *conv = NULL; struct udp_analysis *udpd = NULL; proto_tree *process_tree; udph=ep_new(e_udphdr); SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data); SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data); col_set_str(pinfo->cinfo, COL_PROTOCOL, (ip_proto == IP_PROTO_UDP) ? "UDP" : "UDPlite"); col_clear(pinfo->cinfo, COL_INFO); udph->uh_sport=tvb_get_ntohs(tvb, offset); udph->uh_dport=tvb_get_ntohs(tvb, offset+2); col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s Destination port: %s", get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport)); if (tree) { if (udp_summary_in_tree) { if (ip_proto == IP_PROTO_UDP) { ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8, "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport); } else { ti = proto_tree_add_protocol_format(tree, proto_udplite, tvb, offset, 8, "Lightweight User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport); } } else { ti = proto_tree_add_item(tree, (ip_proto == IP_PROTO_UDP) ? proto_udp : proto_udplite, tvb, offset, 8, ENC_NA); } udp_tree = proto_item_add_subtree(ti, ett_udp); port_item = proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport, "Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport); /* The beginning port number, 32768 + 666 (33434), is from LBL's traceroute.c source code and this code * further assumes that 3 attempts are made per hop */ if(udph->uh_sport > 32768 + 666 && udph->uh_sport <= 32768 + 666 + 30) expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u", ((udph->uh_sport - 32768 - 666 - 1) / 3) + 1, ((udph->uh_sport - 32768 - 666 - 1) % 3) + 1 ); port_item = proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport, "Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport); if(udph->uh_dport > 32768 + 666 && udph->uh_dport <= 32768 + 666 + 30) expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u", ((udph->uh_dport - 32768 - 666 - 1) / 3) + 1, ((udph->uh_dport - 32768 - 666 - 1) % 3) + 1 ); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport); PROTO_ITEM_SET_HIDDEN(hidden_item); } if (ip_proto == IP_PROTO_UDP) { udph->uh_ulen = udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4); if (udph->uh_ulen < 8) { /* Bogus length - it includes the header, so it must be >= 8. */ /* XXX - should handle IPv6 UDP jumbograms (RFC 2675), where the length is zero */ item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen, "Length: %u (bogus, must be >= 8)", udph->uh_ulen); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u < 8", udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u < 8]", udph->uh_ulen); return; } if ((udph->uh_ulen > tvb_reported_length(tvb)) && ! pinfo->fragmented && ! pinfo->flags.in_error_pkt) { /* Bogus length - it goes past the end of the IP payload */ item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen, "Length: %u (bogus, payload length %u)", udph->uh_ulen, tvb_reported_length(tvb)); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u > IP payload length", udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u > IP PAYLOAD LENGTH]", udph->uh_ulen); } else { if (tree) { proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen); /* XXX - why is this here, given that this is UDP, not Lightweight UDP? */ hidden_item = proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 0, udph->uh_sum_cov); PROTO_ITEM_SET_HIDDEN(hidden_item); } } } else { udph->uh_ulen = pinfo->iplen - pinfo->iphdrlen; udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4); if (((udph->uh_sum_cov > 0) && (udph->uh_sum_cov < 8)) || (udph->uh_sum_cov > udph->uh_ulen)) { /* Bogus length - it includes the header, so it must be >= 8, and no larger then the IP payload size. */ if (tree) { hidden_item = proto_tree_add_boolean(udp_tree, hf_udplite_checksum_coverage_bad, tvb, offset + 4, 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen); PROTO_ITEM_SET_HIDDEN(hidden_item); } item = proto_tree_add_uint_format(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov, "Checksum coverage: %u (bogus, must be >= 8 and <= %u (ip.len-ip.hdr_len))", udph->uh_sum_cov, udph->uh_ulen); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad checksum coverage length value %u < 8 or > %u", udph->uh_sum_cov, udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD LIGHTWEIGHT UDP CHECKSUM COVERAGE LENGTH %u < 8 or > %u]", udph->uh_sum_cov, udph->uh_ulen); if (!udplite_ignore_checksum_coverage) return; } else { if (tree) { hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov); } } } udph->uh_sum_cov = (udph->uh_sum_cov) ? udph->uh_sum_cov : udph->uh_ulen; udph->uh_sum = tvb_get_ntohs(tvb, offset+6); reported_len = tvb_reported_length(tvb); len = tvb_length(tvb); if (udph->uh_sum == 0) { /* No checksum supplied in the packet. */ if ((ip_proto == IP_PROTO_UDP) && (pinfo->src.type == AT_IPv4)) { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0, "Checksum: 0x%04x (none)", 0); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0, "Checksum: 0x%04x (Illegal)", 0); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Illegal Checksum value (0)"); col_append_fstr(pinfo->cinfo, COL_INFO, " [ILLEGAL CHECKSUM (0)]"); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); } } else if (!pinfo->fragmented && len >= reported_len && len >= udph->uh_sum_cov && reported_len >= udph->uh_sum_cov && udph->uh_sum_cov >=8) { /* The packet isn't part of a fragmented datagram and isn't truncated, so we can checksum it. XXX - make a bigger scatter-gather list once we do fragment reassembly? */ if (((ip_proto == IP_PROTO_UDP) && (udp_check_checksum)) || ((ip_proto == IP_PROTO_UDPLITE) && (udplite_check_checksum))) { /* Set up the fields of the pseudo-header. */ cksum_vec[0].ptr = (const guint8 *)pinfo->src.data; cksum_vec[0].len = pinfo->src.len; cksum_vec[1].ptr = (const guint8 *)pinfo->dst.data; cksum_vec[1].len = pinfo->dst.len; cksum_vec[2].ptr = (const guint8 *)&phdr; switch (pinfo->src.type) { case AT_IPv4: if (ip_proto == IP_PROTO_UDP) phdr[0] = g_htonl((ip_proto<<16) | udph->uh_ulen); else phdr[0] = g_htonl((ip_proto<<16) | reported_len); cksum_vec[2].len = 4; break; case AT_IPv6: if (ip_proto == IP_PROTO_UDP) phdr[0] = g_htonl(udph->uh_ulen); else phdr[0] = g_htonl(reported_len); phdr[1] = g_htonl(ip_proto); cksum_vec[2].len = 8; break; default: /* UDP runs only atop IPv4 and IPv6.... */ DISSECTOR_ASSERT_NOT_REACHED(); break; } cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, udph->uh_sum_cov); cksum_vec[3].len = udph->uh_sum_cov; computed_cksum = in_cksum(&cksum_vec[0], 4); if (computed_cksum == 0) { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [correct]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"UDP checksum offload\"?)]", udph->uh_sum, in_cksum_shouldbe(udph->uh_sum, computed_cksum)); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); col_append_fstr(pinfo->cinfo, COL_INFO, " [UDP CHECKSUM INCORRECT]"); } } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [validation disabled]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [unchecked, not all data available]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } /* Skip over header */ offset += 8; pinfo->ptype = PT_UDP; pinfo->srcport = udph->uh_sport; pinfo->destport = udph->uh_dport; tap_queue_packet(udp_tap, pinfo, udph); /* find(or create if needed) the conversation for this udp session */ if (udp_process_info) { conv=find_or_create_conversation(pinfo); udpd=get_udp_conversation_data(conv,pinfo); } if (udpd && ((udpd->fwd && udpd->fwd->command) || (udpd->rev && udpd->rev->command))) { ti = proto_tree_add_text(udp_tree, tvb, offset, 0, "Process Information"); PROTO_ITEM_SET_GENERATED(ti); process_tree = proto_item_add_subtree(ti, ett_udp_process_info); if (udpd->fwd && udpd->fwd->command) { proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_uid, tvb, 0, 0, udpd->fwd->process_uid, "%u", udpd->fwd->process_uid); proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_pid, tvb, 0, 0, udpd->fwd->process_pid, "%u", udpd->fwd->process_pid); proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_uname, tvb, 0, 0, udpd->fwd->username, "%s", udpd->fwd->username); proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_cmd, tvb, 0, 0, udpd->fwd->command, "%s", udpd->fwd->command); } if (udpd->rev->command) { proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_uid, tvb, 0, 0, udpd->rev->process_uid, "%u", udpd->rev->process_uid); proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_pid, tvb, 0, 0, udpd->rev->process_pid, "%u", udpd->rev->process_pid); proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_uname, tvb, 0, 0, udpd->rev->username, "%s", udpd->rev->username); proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_cmd, tvb, 0, 0, udpd->rev->command, "%s", udpd->rev->command); } } /* * Call sub-dissectors. * * XXX - should we do this if this is included in an error packet? * It might be nice to see the details of the packet that caused the * ICMP error, but it might not be nice to have the dissector update * state based on it. * Also, we probably don't want to run UDP taps on those packets. * * We definitely don't want to do it for an error packet if there's * nothing left in the packet. */ if (!pinfo->flags.in_error_pkt || tvb_length_remaining(tvb, offset) > 0) decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport, udph->uh_ulen); }
static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_tree *tns_tree) { proto_tree *connect_tree = NULL, *ti; proto_item *hidden_item; int cd_offset; int cd_len; int tns_offset = offset-8; if ( tree ) { connect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_connect, NULL, "Connect"); hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_connect, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } col_append_str(pinfo->cinfo, COL_INFO, ", Connect"); if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_version, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_compat_version, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree *sopt_tree = NULL; ti = proto_tree_add_item(connect_tree, hf_tns_service_options, tvb, offset, 2, ENC_BIG_ENDIAN); sopt_tree = proto_item_add_subtree(ti, ett_tns_sopt_flag); dissect_tns_service_options(tvb, offset, sopt_tree); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_sdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_max_tdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree *ntp_tree = NULL; ti = proto_tree_add_item(connect_tree, hf_tns_nt_proto_characteristics, tvb, offset, 2, ENC_BIG_ENDIAN); ntp_tree = proto_item_add_subtree(ti, ett_tns_ntp_flag); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_hangon, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_crel, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_tduio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_srun, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_dtest, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_cbio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_asio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_pio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_grant, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_handoff, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigpipe, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigurg, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_urgentio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_fdio, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_testop, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_line_turnaround, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_value_of_one, tvb, offset, 2, ENC_NA); } offset += 2; cd_len = tvb_get_ntohs(tvb, offset); if ( connect_tree ) { proto_tree_add_uint(connect_tree, hf_tns_connect_data_length, tvb, offset, 2, cd_len); } offset += 2; cd_offset = tvb_get_ntohs(tvb, offset); if ( connect_tree ) { proto_tree_add_uint(connect_tree, hf_tns_connect_data_offset, tvb, offset, 2, cd_offset); } offset += 2; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_connect_data_max, tvb, offset, 4, ENC_BIG_ENDIAN); } offset += 4; if ( connect_tree ) { proto_tree *cflag_tree = NULL; ti = proto_tree_add_item(connect_tree, hf_tns_connect_flags0, tvb, offset, 1, ENC_BIG_ENDIAN); cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag); dissect_tns_connect_flag(tvb, offset, cflag_tree); } offset += 1; if ( connect_tree ) { proto_tree *cflag_tree = NULL; ti = proto_tree_add_item(connect_tree, hf_tns_connect_flags1, tvb, offset, 1, ENC_BIG_ENDIAN); cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag); dissect_tns_connect_flag(tvb, offset, cflag_tree); } offset += 1; /* * XXX - sometimes it appears that this stuff isn't present * in the packet. */ if (offset + 16 <= tns_offset+cd_offset) { if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_trace_cf1, tvb, offset, 4, ENC_BIG_ENDIAN); } offset += 4; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_trace_cf2, tvb, offset, 4, ENC_BIG_ENDIAN); } offset += 4; if ( connect_tree ) { proto_tree_add_item(connect_tree, hf_tns_trace_cid, tvb, offset, 8, ENC_BIG_ENDIAN); } /* offset += 8;*/ } if ( connect_tree && cd_len > 0) { proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb, tns_offset+cd_offset, -1, ENC_ASCII|ENC_NA); } return; }
static void dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request; proto_tree *imap_tree, *reqresp_tree; proto_item *ti, *hidden_item; gint offset = 0; gint uid_offset = 0; gint folder_offset = 0; const guchar *line; const guchar *uid_line; const guchar *folder_line; gint next_offset; int linelen; int tokenlen; int uid_tokenlen; int folder_tokenlen; const guchar *next_token; const guchar *uid_next_token; const guchar *folder_next_token; guchar *tokenbuf; guchar *command_token; int iter; int commandlen; tokenbuf = (guchar *)wmem_alloc(wmem_packet_scope(), MAX_BUFFER); command_token = (guchar *)wmem_alloc(wmem_packet_scope(), MAX_BUFFER); memset(tokenbuf, '\0', MAX_BUFFER); memset(command_token, '\0', MAX_BUFFER); commandlen = 0; folder_offset = 0; folder_tokenlen = 0; folder_line = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IMAP"); if (pinfo->match_uint == pinfo->destport) is_request = TRUE; else is_request = FALSE; /* * Put the first line from the buffer into the summary * (but leave out the line terminator). */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); if (tree) { ti = proto_tree_add_item(tree, proto_imap, tvb, offset, -1, ENC_NA); imap_tree = proto_item_add_subtree(ti, ett_imap); hidden_item = proto_tree_add_boolean(imap_tree, hf_imap_isrequest, tvb, 0, 0, is_request); PROTO_ITEM_SET_HIDDEN(hidden_item); while(tvb_length_remaining(tvb, offset) > 0) { /* * Find the end of each line * * 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); /* * Put the line into the protocol tree. */ ti = proto_tree_add_item(imap_tree, hf_imap_line, tvb, offset, next_offset - offset, ENC_ASCII|ENC_NA); reqresp_tree = proto_item_add_subtree(ti, ett_imap_reqresp); /* * Check that the line doesn't begin with '*', because that's a continuation line. * Otherwise if a tag is present then extract tokens. */ if ( (line) && ((line[0] != '*') || (TRUE == is_request)) ) { /* * Show each line as tags + requests or replies. */ /* * Extract the first token, and, if there is a first * token, add it as the request or reply tag. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_tag : hf_imap_response_tag, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); offset += (gint) (next_token - line); linelen -= (int) (next_token - line); line = next_token; } /* * Extract second token, and, if there is a second * token, and it's not uid, add it as the request or reply command. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { for (iter = 0; iter < tokenlen && iter < MAX_BUFFER-1; iter++) { tokenbuf[iter] = g_ascii_tolower(line[iter]); } if ( TRUE == is_request && strncmp(tokenbuf,"uid",tokenlen) == 0) { proto_tree_add_item(reqresp_tree, hf_imap_request_uid, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); /* * UID is a precursor to a command, if following the tag, * so move to next token to grab the actual command. */ uid_offset = offset; uid_offset += (gint) (next_token - line); uid_line = next_token; uid_tokenlen = get_token_len(uid_line, uid_line + (linelen - tokenlen), &uid_next_token); if (tokenlen != 0) { proto_tree_add_item(reqresp_tree, hf_imap_request_command, tvb, uid_offset, uid_tokenlen, ENC_ASCII|ENC_NA); /* * Save command string to do specialized processing. */ for (iter = 0; iter < uid_tokenlen && iter < MAX_BUFFER-1; iter++) { command_token[iter] = g_ascii_tolower(uid_line[iter]); } commandlen = uid_tokenlen; folder_offset = uid_offset; folder_offset += (gint) (uid_next_token - uid_line); folder_line = uid_next_token; folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - uid_tokenlen), &folder_next_token); } } else { /* * Not a UID request so perform normal parsing. */ proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_command : hf_imap_response_status, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); if (is_request) { /* * Save command string to do specialized processing. */ for (iter = 0; iter < tokenlen && iter < 256; iter++) { command_token[iter] = g_ascii_tolower(line[iter]); } commandlen = tokenlen; folder_offset = offset; folder_offset += (gint) (next_token - line); folder_line = next_token; folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - 1), &folder_next_token); } } if (commandlen > 0 && ( strncmp(command_token, "select", commandlen) == 0 || strncmp(command_token, "examine", commandlen) == 0 || strncmp(command_token, "create", commandlen) == 0 || strncmp(command_token, "delete", commandlen) == 0 || strncmp(command_token, "rename", commandlen) == 0 || strncmp(command_token, "subscribe", commandlen) == 0 || strncmp(command_token, "unsubscribe", commandlen) == 0 || strncmp(command_token, "status", commandlen) == 0 || strncmp(command_token, "append", commandlen) == 0 || strncmp(command_token, "search", commandlen) == 0)) { /* * These commands support folder as an argument, * so parse out the folder name. */ if (folder_tokenlen != 0) proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA); } if ( is_request && (NULL != folder_line) && strncmp(command_token, "copy", commandlen) == 0) { /* * Handle the copy command separately since folder * is the second argument for this command. */ folder_offset += (gint) (folder_next_token - folder_line); folder_line = folder_next_token; folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen), &folder_next_token); if (folder_tokenlen != 0) proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA); } } /* * Add the rest of the line as request or reply data. */ if (linelen != 0) { proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request : hf_imap_response, tvb, offset, linelen, ENC_ASCII|ENC_NA); } } offset = next_offset; /* Skip over last line and \r\n at the end of it */ } } }
static void expert_set_info_vformat(packet_info *pinfo, proto_item *pi, int group, int severity, int hf_index, gboolean use_vaformat, const char *format, va_list ap) { char formatted[ITEM_LABEL_LENGTH]; int tap; expert_info_t *ei; proto_tree *tree; proto_item *ti; if (pinfo == NULL && pi && pi->tree_data) { pinfo = PTREE_DATA(pi)->pinfo; } /* if this packet isn't loaded because of a read filter, don't output anything */ if (pinfo == NULL || pinfo->num == 0) { return; } if (severity > highest_severity) { highest_severity = severity; } /* XXX: can we get rid of these checks and make them programming errors instead now? */ if (pi != NULL && PITEM_FINFO(pi) != NULL) { expert_set_item_flags(pi, group, severity); } if ((pi == NULL) || (PITEM_FINFO(pi) == NULL) || ((guint)severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK))) { col_add_str(pinfo->cinfo, COL_EXPERT, val_to_str(severity, expert_severity_vals, "Unknown (%u)")); } if (use_vaformat) { g_vsnprintf(formatted, ITEM_LABEL_LENGTH, format, ap); } else { g_strlcpy(formatted, format, ITEM_LABEL_LENGTH); } tree = expert_create_tree(pi, group, severity, formatted); if (hf_index == -1) { /* If no filterable expert info, just add the message */ ti = proto_tree_add_string(tree, hf_expert_msg, NULL, 0, 0, formatted); PROTO_ITEM_SET_GENERATED(ti); } else { /* If filterable expert info, hide the "generic" form of the message, and generate the formatted filterable expert info */ ti = proto_tree_add_none_format(tree, hf_index, NULL, 0, 0, "%s", formatted); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_string(tree, hf_expert_msg, NULL, 0, 0, formatted); PROTO_ITEM_SET_HIDDEN(ti); } ti = proto_tree_add_uint_format_value(tree, hf_expert_severity, NULL, 0, 0, severity, "%s", val_to_str_const(severity, expert_severity_vals, "Unknown")); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint_format_value(tree, hf_expert_group, NULL, 0, 0, group, "%s", val_to_str_const(group, expert_group_vals, "Unknown")); PROTO_ITEM_SET_GENERATED(ti); tap = have_tap_listener(expert_tap); if (!tap) return; ei = wmem_new(wmem_packet_scope(), expert_info_t); ei->packet_num = pinfo->num; ei->group = group; ei->severity = severity; ei->hf_index = hf_index; ei->protocol = pinfo->current_proto; ei->summary = wmem_strdup(wmem_packet_scope(), formatted); /* if we have a proto_item (not a faked item), set expert attributes to it */ if (pi != NULL && PITEM_FINFO(pi) != NULL) { ei->pitem = pi; } /* XXX: remove this because we don't have an internal-only function now? */ else { ei->pitem = NULL; } tap_queue_packet(expert_tap, pinfo, ei); }
static void dissect_ascend(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *fh_tree; proto_item *ti, *hidden_item; union wtap_pseudo_header *pseudo_header = pinfo->pseudo_header; /* load the top pane info. This should be overwritten by the next protocol in the stack */ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A"); col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "N/A"); col_set_str(pinfo->cinfo, COL_INFO, "Lucent/Ascend packet trace"); /* If this is a transmitted or received PPP frame, set the PPP direction. */ switch (pseudo_header->ascend.type) { case ASCEND_PFX_WDS_X: pinfo->p2p_dir = P2P_DIR_SENT; break; case ASCEND_PFX_WDS_R: pinfo->p2p_dir = P2P_DIR_RECV; break; } /* populate a tree in the second pane with the status of the link layer (ie none) */ if(tree) { ti = proto_tree_add_protocol_format(tree, proto_ascend, tvb, 0, 0, "Lucent/Ascend packet trace"); fh_tree = proto_item_add_subtree(ti, ett_raw); proto_tree_add_uint(fh_tree, hf_link_type, tvb, 0, 0, pseudo_header->ascend.type); if (pseudo_header->ascend.type == ASCEND_PFX_WDD) { proto_tree_add_string(fh_tree, hf_called_number, tvb, 0, 0, pseudo_header->ascend.call_num); proto_tree_add_uint(fh_tree, hf_chunk, tvb, 0, 0, pseudo_header->ascend.chunk); hidden_item = proto_tree_add_uint(fh_tree, hf_session_id, tvb, 0, 0, 0); PROTO_ITEM_SET_HIDDEN(hidden_item); } else { /* It's wandsession data */ proto_tree_add_string(fh_tree, hf_user_name, tvb, 0, 0, pseudo_header->ascend.user); proto_tree_add_uint(fh_tree, hf_session_id, tvb, 0, 0, pseudo_header->ascend.sess); hidden_item = proto_tree_add_uint(fh_tree, hf_chunk, tvb, 0, 0, 0); PROTO_ITEM_SET_HIDDEN(hidden_item); } proto_tree_add_uint(fh_tree, hf_task, tvb, 0, 0, pseudo_header->ascend.task); } switch (pseudo_header->ascend.type) { case ASCEND_PFX_WDS_X: case ASCEND_PFX_WDS_R: call_dissector(ppp_hdlc_handle, tvb, pinfo, tree); break; case ASCEND_PFX_WDD: call_dissector(eth_withoutfcs_handle, tvb, pinfo, tree); break; default: break; } }
static int dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *ws_tree, guint8 opcode, guint payload_length, guint8 mask, const guint8* masking_key) { guint offset = 0; proto_item *ti_unmask, *ti; dissector_handle_t handle; proto_tree *pl_tree, *mask_tree = NULL; tvbuff_t *payload_tvb = NULL; /* Payload */ ti = proto_tree_add_item(ws_tree, hf_ws_payload, tvb, offset, payload_length, ENC_NA); pl_tree = proto_item_add_subtree(ti, ett_ws_pl); if(mask){ payload_tvb = tvb_unmasked(tvb, offset, payload_length, masking_key); tvb_set_child_real_data_tvbuff(tvb, payload_tvb); add_new_data_source(pinfo, payload_tvb, payload_length > tvb_length(payload_tvb) ? "Unmasked Data (truncated)" : "Unmasked Data"); ti = proto_tree_add_item(ws_tree, hf_ws_payload_unmask, payload_tvb, offset, payload_length, ENC_NA); mask_tree = proto_item_add_subtree(ti, ett_ws_mask); }else{ payload_tvb = tvb_new_subset(tvb, offset, payload_length, -1); } handle = dissector_get_uint_handle(port_subdissector_table, pinfo->match_uint); if(handle != NULL){ call_dissector_only(handle, payload_tvb, pinfo, tree, NULL); }else{ dissector_try_heuristic(heur_subdissector_list, payload_tvb, pinfo, tree, NULL); } /* Extension Data */ /* TODO: Add dissector of Extension (not extension available for the moment...) */ /* Application Data */ switch(opcode){ case WS_CONTINUE: /* Continue */ proto_tree_add_item(pl_tree, hf_ws_payload_continue, tvb, offset, payload_length, ENC_NA); /* TODO: Add Fragmentation support... */ break; case WS_TEXT: /* Text */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_text_mask, tvb, offset, payload_length, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text_unmask, payload_tvb, offset, payload_length, ENC_UTF_8|ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text, payload_tvb, offset, payload_length, ENC_UTF_8|ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); }else{ const gchar *saved_match_string = pinfo->match_string; void *save_private_data = pinfo->private_data; pinfo->match_string = NULL; pinfo->private_data = NULL; switch(pref_text_type){ case WEBSOCKET_TEXT: call_dissector(text_lines_handle, payload_tvb, pinfo, pl_tree); break; case WEBSOCKET_JSON: call_dissector(json_handle, payload_tvb, pinfo, pl_tree); break; case WEBSOCKET_NONE: /* falltrough */ default: proto_tree_add_item(pl_tree, hf_ws_payload_text, tvb, offset, payload_length, ENC_UTF_8|ENC_NA); break; } pinfo->match_string = saved_match_string; pinfo->private_data = save_private_data; } offset += payload_length; break; case WS_BINARY: /* Binary */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_binary_mask, tvb, offset, payload_length, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary_unmask, payload_tvb, offset, payload_length, ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary, payload_tvb, offset, payload_length, ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); }else{ proto_tree_add_item(pl_tree, hf_ws_payload_binary, tvb, offset, payload_length, ENC_NA); } offset += payload_length; break; case WS_CLOSE: /* Close */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_close_mask, tvb, offset, payload_length, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_unmask, payload_tvb, offset, payload_length, ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close, payload_tvb, offset, payload_length, ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_status_code, payload_tvb, offset, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_GENERATED(ti_unmask); if(payload_length > 2){ ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_reason, payload_tvb, offset+2, payload_length-2, ENC_ASCII|ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); } }else{ proto_tree_add_item(pl_tree, hf_ws_payload_close, tvb, offset, payload_length, ENC_NA); proto_tree_add_item(pl_tree, hf_ws_payload_close_status_code, tvb, offset, 2, ENC_BIG_ENDIAN); if(payload_length > 2){ proto_tree_add_item(pl_tree, hf_ws_payload_close_reason, tvb, offset+2, payload_length-2, ENC_ASCII|ENC_NA); } } offset += payload_length; break; case WS_PING: /* Ping */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_ping_mask, tvb, offset, payload_length, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping_unmask, payload_tvb, offset, payload_length, ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping, payload_tvb, offset, payload_length, ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); }else{ proto_tree_add_item(pl_tree, hf_ws_payload_ping, tvb, offset, payload_length, ENC_NA); } offset += payload_length; break; case WS_PONG: /* Pong */ if(mask){ proto_tree_add_item(pl_tree, hf_ws_payload_pong_mask, tvb, offset, payload_length, ENC_NA); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong_unmask, payload_tvb, offset, payload_length, ENC_NA); PROTO_ITEM_SET_GENERATED(ti_unmask); ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong, payload_tvb, offset, payload_length, ENC_NA); PROTO_ITEM_SET_HIDDEN(ti_unmask); }else{ proto_tree_add_item(pl_tree, hf_ws_payload_pong, tvb, offset, payload_length, ENC_NA); } offset += payload_length; break; default: /* Unknown */ ti = proto_tree_add_item(pl_tree, hf_ws_payload_unknown, tvb, offset, payload_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; } return offset; }