/* obtain an (aligned) EGPRS data block with given bit-offset and * bit-length from the parent TVB */ static tvbuff_t *get_egprs_data_block(tvbuff_t *tvb, guint offset_bits, guint length_bits, packet_info *pinfo) { tvbuff_t *aligned_tvb; const guint initial_spare_bits = 6; guint8 *aligned_buf; guint min_src_length_bytes = (offset_bits + length_bits + 7) / 8; guint length_bytes = (initial_spare_bits + length_bits + 7) / 8; tvb_ensure_bytes_exist(tvb, 0, min_src_length_bytes); aligned_buf = (guint8 *) wmem_alloc(pinfo->pool, length_bytes); /* Copy the data out of the tvb to an aligned buffer */ clone_aligned_buffer_lsbf( offset_bits - initial_spare_bits, length_bytes, tvb_get_ptr(tvb, 0, min_src_length_bytes), aligned_buf); /* clear spare bits and move block header bits to the right */ aligned_buf[0] = aligned_buf[0] >> initial_spare_bits; aligned_tvb = tvb_new_child_real_data(tvb, aligned_buf, length_bytes, length_bytes); add_new_data_source(pinfo, aligned_tvb, "Aligned EGPRS data bits"); return aligned_tvb; }
void isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length) { gboolean first; proto_item *ti; if ( !tree ) return; /* nothing to do! */ /* * Throw an exception rather than putting in a * partial address. */ tvb_ensure_bytes_exist ( tvb, offset, length ); if (length <= 0) { proto_tree_add_text (tree, tvb, offset, length, "NLPID(s): --none--"); } else { first = TRUE; ti = proto_tree_add_text (tree, tvb, offset, length, "NLPID(s): "); while (length-- > 0 ) { if (!first) { proto_item_append_text(ti, ", "); } proto_item_append_text(ti, "%s (0x%02x)", val_to_str(tvb_get_guint8(tvb, offset), nlpid_vals, "Unknown"), tvb_get_guint8(tvb, offset)); offset++; first = FALSE; } } }
guint16 crc16_x25_ccitt_tvb(tvbuff_t *tvb, guint len) { const guint8 *buf; tvb_ensure_bytes_exist(tvb, 0, len); /* len == -1 not allowed */ buf = tvb_get_ptr(tvb, 0, len); return crc16_x25_ccitt_seed(buf, len, 0xFFFF); }
guint16 crc16_ccitt_tvb_offset_seed(tvbuff_t *tvb, guint offset, guint len, guint16 seed) { const guint8 *buf; tvb_ensure_bytes_exist(tvb, offset, len); /* len == -1 not allowed */ buf = tvb_get_ptr(tvb, offset, len); return crc16_ccitt_seed(buf, len, seed); }
guint32 crc32_ccitt_tvb_seed(tvbuff_t *tvb, guint len, guint32 seed) { const guint8* buf; tvb_ensure_bytes_exist(tvb, 0, len); /* len == -1 not allowed */ buf = tvb_get_ptr(tvb, 0, len); return ( crc32_ccitt_seed(buf, len, seed) ); }
guint32 crc32_ccitt_tvb_offset(tvbuff_t *tvb, guint offset, guint len) { const guint8* buf; tvb_ensure_bytes_exist(tvb, offset, len); /* len == -1 not allowed */ buf = tvb_get_ptr(tvb, offset, len); return ( crc32_ccitt(buf, len) ); }
guint32 crc32_0x0AA725CF_tvb_offset_seed(tvbuff_t *tvb, guint offset, guint len, guint32 seed) { const guint8 *buf; tvb_ensure_bytes_exist(tvb, offset, len); /* len == -1 not allowed */ buf = tvb_get_ptr(tvb, offset, len); return crc32_0x0AA725CF_seed(buf, len, seed); }
static int dissect_rx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber) { proto_tree *tree; proto_item *item; guint32 version, tl; int old_offset=offset; if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "RESPONSE " "Seq: %lu " "Call: %lu " "Source Port: %s " "Destination Port: %s ", (unsigned long)seq, (unsigned long)callnumber, get_udp_port(pinfo->srcport), get_udp_port(pinfo->destport) ); } item = proto_tree_add_item(parent_tree, hf_rx_response, tvb, offset, -1, FALSE); tree = proto_item_add_subtree(item, ett_rx_response); version = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(tree, hf_rx_version, tvb, offset, 4, version); offset += 4; if (version==2) { /* skip unused */ offset += 4; /* encrypted : struct */ offset = dissect_rx_response_encrypted(tvb, tree, offset); /* kvno */ proto_tree_add_item(tree, hf_rx_kvno, tvb, offset, 4, FALSE); offset += 4; /* ticket_len */ tl = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(tree, hf_rx_ticket_len, tvb, offset, 4, tl); offset += 4; tvb_ensure_bytes_exist(tvb, offset, tl); proto_tree_add_item(tree, hf_rx_ticket, tvb, offset, tl, FALSE); offset += tl; } proto_item_set_len(item, offset-old_offset); return offset; }
guint16 crc16_plain_tvb_offset_seed(tvbuff_t *tvb, guint offset, guint len, guint16 crc) { const guint8 *buf; tvb_ensure_bytes_exist(tvb, offset, len); /* len == -1 not allowed */ buf = tvb_get_ptr(tvb, offset, len); crc = crc16_plain_update(crc, buf, len); return crc16_plain_finalize(crc); }
/* * Name: isis_dissect_area_address_clv() * * Description: * Take an area address CLV and display it pieces. An area address * CLV is n, x byte hex strings. * * Input: * tvbuff_t * : tvbuffer for packet data * proto_tree * : protocol display tree to fill out. May be NULL * int : offset into packet data where we are. * int : length of clv we are decoding * * Output: * void, but we will add to proto tree if !NULL. */ void isis_dissect_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length) { int arealen,area_idx; while ( length > 0 ) { arealen = tvb_get_guint8(tvb, offset); length--; if (length<=0) { isis_dissect_unknown(tvb, tree, offset, "short address (no length for payload)"); return; } if ( arealen > length) { isis_dissect_unknown(tvb, tree, offset, "short address, packet says %d, we have %d left", arealen, length ); return; } if ( tree ) { proto_item *ti; /* * Throw an exception rather than putting in a * partial address. */ tvb_ensure_bytes_exist ( tvb, offset, arealen + 1 ); ti = proto_tree_add_text ( tree, tvb, offset, arealen + 1, "Area address (%d): ", arealen ); /* * Lets turn the area address into "standard" * xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx format string. * this is a private routine as the print_nsap_net in * epan/osi_utils.c is incomplete and we need only * a subset - actually some nice placing of dots .... */ for (area_idx = 0; area_idx < arealen; area_idx++) { proto_item_append_text(ti, "%02x", tvb_get_guint8(tvb, offset+area_idx+1)); if (((area_idx & 1) == 0) && (area_idx + 1 < arealen)) { proto_item_append_text(ti, "."); } } } offset += arealen + 1; length -= arealen; /* length already adjusted for len fld*/ } }
static void dissect_option_rfd( const guchar error, const guchar field, int offset, guchar len, tvbuff_t *tvb, proto_tree *tree ) { guchar error_class = 0; const char *format_string[] = { "Reason for discard {General} : %s, in field %u", "Reason for discard {Address} : %s, in field %u", "Reason for discard {Source Routing}: %s, in field %u", "Reason for discard {Lifetime} : %s, in field %u", "Reason for discard {PDU discarded} : %s, in field %u", "Reason for discard {Reassembly} : %s, in field %u" }; error_class = error & OSI_OPT_RFD_MASK; tvb_ensure_bytes_exist(tvb, offset + field, 1); if ( OSI_OPT_RFD_GENERAL == error_class ) { proto_tree_add_text( tree, tvb, offset + field, 1, format_string[0], val_to_str( error & OSI_OPT_RFD_SUB_MASK, osi_opt_rfd_general, "Unknown (0x%x)"), field ); } else if ( OSI_OPT_RFD_ADDRESS == error_class ) { proto_tree_add_text( tree, tvb, offset + field, 1, format_string[1], val_to_str( error & OSI_OPT_RFD_SUB_MASK, osi_opt_rfd_address, "Unknown (0x%x)"), field ); } else if ( OSI_OPT_RFD_SOURCE_ROUTING == error_class ) { proto_tree_add_text( tree, tvb, offset + field, 1, format_string[2], val_to_str( error & OSI_OPT_RFD_SUB_MASK, osi_opt_rfd_src_route, "Unknown (0x%x)"), field ); } else if ( OSI_OPT_RFD_LIFETIME == error_class ) { proto_tree_add_text( tree, tvb, offset + field, 1, format_string[3], val_to_str( error & OSI_OPT_RFD_SUB_MASK, osi_opt_rfd_lifetime, "Unknown (0x%x)"), field ); } else if ( OSI_OPT_RFD_PDU_DISCARDED == error_class ) { proto_tree_add_text( tree, tvb, offset + field, 1, format_string[4], val_to_str( error & OSI_OPT_RFD_SUB_MASK, osi_opt_rfd_discarded, "Unknown (0x%x)"), field ); } else if ( OSI_OPT_RFD_REASSEMBLY == error_class ) { proto_tree_add_text( tree, tvb, offset + field, 1, format_string[5], val_to_str( error & OSI_OPT_RFD_SUB_MASK, osi_opt_rfd_reassembly, "Unknown (0x%x)"), field ); } else { proto_tree_add_text( tree, tvb, offset, len, "Reason for discard: UNKNOWN Error Class" ); } }
static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree) { guint16 datalen; proto_tree* noop_tree; datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH); if(lwres_tree == NULL) return; noop_tree = proto_tree_add_subtree(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, ett_noop, NULL, "Noop record"); proto_tree_add_uint(noop_tree, hf_length, tvb, LWRES_LWPACKET_LENGTH, sizeof(guint16), datalen); tvb_ensure_bytes_exist(tvb, LWRES_LWPACKET_LENGTH, datalen); }
void isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length) { gboolean first; proto_item *ti; if ( !tree ) return; /* nothing to do! */ /* * Throw an exception rather than putting in a * partial address. */ tvb_ensure_bytes_exist ( tvb, offset, length ); if (length <= 0) { proto_tree_add_text (tree, tvb, offset, length, "NLPID(s): --none--"); } else { first = TRUE; ti = proto_tree_add_text (tree, tvb, offset, length, "NLPID(s): "); while (length-- > 0 ) { if (!first) { proto_item_append_text(ti, ", "); } proto_item_append_text(ti, "%s (0x%02x)", /* NLPID_IEEE_8021AQ conflicts with NLPID_SNDCF. * In this context, we want the former. */ (tvb_get_guint8(tvb, offset) == NLPID_IEEE_8021AQ ? "IEEE 802.1aq (SPB)" : val_to_str_const(tvb_get_guint8(tvb, offset), nlpid_vals, "Unknown")), tvb_get_guint8(tvb, offset)); offset++; first = FALSE; } } }
static int dissect_rtspmessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { proto_tree *rtsp_tree = NULL; proto_tree *sub_tree = NULL; proto_item *ti = NULL; const guchar *line; gint next_offset; const guchar *linep, *lineend; int orig_offset; int first_linelen, linelen; int line_end_offset; int colon_offset; gboolean is_request_or_reply; gboolean body_requires_content_len; gboolean saw_req_resp_or_header; guchar c; rtsp_type_t rtsp_type; gboolean is_header; int datalen; int content_length; int reported_datalen; int value_offset; int value_len; e164_info_t e164_info; gint rdt_feature_level = 0; gchar *media_type_str_lower_case = NULL; int semi_colon_offset; int par_end_offset; /* * Is this a request or response? * * 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. */ first_linelen = tvb_find_line_end(tvb, offset, tvb_ensure_length_remaining(tvb, offset), &next_offset, FALSE); /* * Is the first line a request or response? */ line = tvb_get_ptr(tvb, offset, first_linelen); is_request_or_reply = is_rtsp_request_or_reply(line, first_linelen, &rtsp_type); if (is_request_or_reply) { /* * Yes, it's a request or response. * Do header desegmentation if we've been told to, * and do body desegmentation if we've been told to and * we find a Content-Length header. */ if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo, rtsp_desegment_headers, rtsp_desegment_body)) { /* * More data needed for desegmentation. */ return -1; } } /* * RFC 2326 says that a content length must be specified * in requests that have a body, although section 4.4 speaks * of a server closing the connection indicating the end of * a reply body. * * We assume that an absent content length in a request means * that we don't have a body, and that an absent content length * in a reply means that the reply body runs to the end of * the connection. If the first line is neither, we assume * that whatever follows a blank line should be treated as a * body; there's not much else we can do, as we're jumping * into the message in the middle. * * XXX - if there was no Content-Length entity header, we should * accumulate all data until the end of the connection. * That'd require that the TCP dissector call subdissectors * for all frames with FIN, even if they contain no data, * which would require subdissectors to deal intelligently * with empty segments. */ if (rtsp_type == RTSP_REQUEST) body_requires_content_len = TRUE; else body_requires_content_len = FALSE; col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTSP"); if (check_col(pinfo->cinfo, COL_INFO)) { /* * Put the first line from the buffer into the summary * if it's an RTSP request or reply (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. */ line = tvb_get_ptr(tvb, offset, first_linelen); if (is_request_or_reply) if ( rtsp_type == RTSP_REPLY ) { col_set_str(pinfo->cinfo, COL_INFO, "Reply: "); col_append_str(pinfo->cinfo, COL_INFO, format_text(line, first_linelen)); } else col_add_str(pinfo->cinfo, COL_INFO, format_text(line, first_linelen)); else col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); } orig_offset = offset; if (tree) { ti = proto_tree_add_item(tree, proto_rtsp, tvb, offset, -1, FALSE); rtsp_tree = proto_item_add_subtree(ti, ett_rtsp); } /* * We haven't yet seen a Content-Length header. */ content_length = -1; /* * Process the packet data, a line at a time. */ saw_req_resp_or_header = FALSE; /* haven't seen anything yet */ while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * We haven't yet concluded that this is a header. */ is_header = FALSE; /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, offset, tvb_ensure_length_remaining(tvb, offset), &next_offset, FALSE); if (linelen < 0) return -1; line_end_offset = offset + linelen; /* * colon_offset may be -1 */ colon_offset = tvb_find_guint8(tvb, offset, linelen, ':'); /* * Get a buffer that refers to the line. */ line = tvb_get_ptr(tvb, offset, linelen); lineend = line + linelen; /* * OK, does it look like an RTSP request or response? */ is_request_or_reply = is_rtsp_request_or_reply(line, linelen, &rtsp_type); if (is_request_or_reply) goto is_rtsp; /* * No. Does it look like a blank line (as would appear * at the end of an RTSP request)? */ if (linelen == 0) goto is_rtsp; /* Yes. */ /* * No. Does it look like a header? */ linep = line; while (linep < lineend) { c = *linep++; /* * This must be a CHAR to be part of a token; that * means it must be ASCII. */ if (!isascii(c)) 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)) 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 tspecial, so it's not * part of a token, so it's not * a field name for the beginning * of a header. */ goto not_rtsp; case ':': /* * This ends the token; we consider * this to be a header. */ is_header = TRUE; goto is_rtsp; case ' ': case '\t': /* * LWS (RFC-2616, 4.2); continue the previous * header. */ goto is_rtsp; } } /* * We haven't seen the colon, but everything else looks * OK for a header line. * * If we've already seen an RTSP request or response * line, or a header line, and we're at the end of * the tvbuff, we assume this is an incomplete header * line. (We quit this loop after seeing a blank line, * so if we've seen a request or response line, or a * header line, this is probably more of the request * or response we're presumably seeing. There is some * risk of false positives, but the same applies for * full request or response lines or header lines, * although that's less likely.) * * We throw an exception in that case, by checking for * the existence of the next byte after the last one * in the line. If it exists, "tvb_ensure_bytes_exist()" * throws no exception, and we fall through to the * "not RTSP" case. If it doesn't exist, * "tvb_ensure_bytes_exist()" will throw the appropriate * exception. */ if (saw_req_resp_or_header) tvb_ensure_bytes_exist(tvb, offset, linelen + 1); not_rtsp: /* * We don't consider this part of an RTSP request or * reply, so we don't display it. */ break; is_rtsp: /* * Process this line. */ if (linelen == 0) { /* * This is a blank line, which means that * whatever follows it isn't part of this * request or reply. */ proto_tree_add_text(rtsp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; break; } /* * Not a blank line - either a request, a reply, or a header * line. */ saw_req_resp_or_header = TRUE; if (rtsp_tree) { switch (rtsp_type) { case RTSP_REQUEST: process_rtsp_request(tvb, offset, line, linelen, next_offset, rtsp_tree); break; case RTSP_REPLY: process_rtsp_reply(tvb, offset, line, linelen, next_offset, rtsp_tree); break; case RTSP_NOT_FIRST_LINE: /* Drop through, it may well be a header line */ break; } } if (is_header) { /* We know that colon_offset must be set */ /* Skip whitespace after the colon. */ value_offset = colon_offset + 1; while ((value_offset < line_end_offset) && ((c = tvb_get_guint8(tvb, value_offset)) == ' ' || c == '\t')) { value_offset++; } value_len = line_end_offset - value_offset; /* * Process some headers specially. */ #define HDR_MATCHES(header) \ ( (size_t)linelen > STRLEN_CONST(header) && \ g_ascii_strncasecmp(line, (header), STRLEN_CONST(header)) == 0) if (HDR_MATCHES(rtsp_transport)) { proto_tree_add_string(rtsp_tree, hf_rtsp_transport, tvb, offset, linelen, tvb_format_text(tvb, value_offset, value_len)); /* * Based on the port numbers specified * in the Transport: header, set up * a conversation that will be dissected * with the appropriate dissector. */ rtsp_create_conversation(pinfo, line, linelen, rdt_feature_level); } else if (HDR_MATCHES(rtsp_content_type)) { proto_tree_add_string(rtsp_tree, hf_rtsp_content_type, tvb, offset, linelen, tvb_format_text(tvb, value_offset, value_len)); offset = offset + STRLEN_CONST(rtsp_content_type); /* Skip wsp */ offset = tvb_skip_wsp(tvb, offset, value_len); semi_colon_offset = tvb_find_guint8(tvb, value_offset, value_len, ';'); if ( semi_colon_offset != -1) { /* m-parameter present */ par_end_offset = tvb_skip_wsp_return(tvb, semi_colon_offset-1); value_len = par_end_offset - offset; } media_type_str_lower_case = ascii_strdown_inplace( (gchar *)tvb_get_ephemeral_string(tvb, offset, value_len)); } else if (HDR_MATCHES(rtsp_content_length)) { proto_tree_add_uint(rtsp_tree, hf_rtsp_content_length, tvb, offset, linelen, atoi(tvb_format_text(tvb, value_offset, value_len))); /* * Only the amount specified by the * Content-Length: header should be treated * as payload. */ content_length = rtsp_get_content_length(line, linelen); } else if (HDR_MATCHES(rtsp_Session)) { /* Put the value into the protocol tree */ proto_tree_add_string(rtsp_tree, hf_rtsp_session, tvb, offset, linelen, tvb_format_text(tvb, value_offset, value_len)); } else if (HDR_MATCHES(rtsp_X_Vig_Msisdn)) { /* * Extract the X_Vig_Msisdn string */ if (colon_offset != -1) { /* Put the value into the protocol tree */ ti = proto_tree_add_string(rtsp_tree, hf_rtsp_X_Vig_Msisdn,tvb, offset, linelen , tvb_format_text(tvb, value_offset, value_len)); sub_tree = proto_item_add_subtree(ti, ett_rtsp_method); e164_info.e164_number_type = CALLING_PARTY_NUMBER; e164_info.nature_of_address = 0; e164_info.E164_number_str = tvb_get_ephemeral_string(tvb, value_offset, value_len); e164_info.E164_number_length = value_len; dissect_e164_number(tvb, sub_tree, value_offset, value_len, e164_info); } } else if (HDR_MATCHES(rtsp_rdt_feature_level)) { rdt_feature_level = atoi(tvb_format_text(tvb, value_offset, value_len)); proto_tree_add_uint(rtsp_tree, hf_rtsp_rdtfeaturelevel, tvb, offset, linelen, atoi(tvb_format_text(tvb, value_offset, value_len))); } else { /* Default case for headers. Show line as text */ proto_tree_add_text(rtsp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); } } else if (rtsp_type == RTSP_NOT_FIRST_LINE) { /* Catch-all for all other lines... Show line as text. TODO: should these be shown as errors? */ proto_tree_add_text(rtsp_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); } offset = next_offset; } /* * Have now read all of the lines of this message. * * If a content length was supplied, the amount of data to be * processed as RTSP payload is the minimum of the content * length and the amount of data remaining in the frame. * * If no content length was supplied (or if a bad content length * was supplied), the amount of data to be processed is the amount * of data remaining in the frame. */ datalen = tvb_length_remaining(tvb, offset); reported_datalen = tvb_reported_length_remaining(tvb, offset); if (content_length != -1) { /* * Content length specified; display only that amount * as payload. */ if (datalen > content_length) datalen = content_length; /* * XXX - limit the reported length in the tvbuff we'll * hand to a subdissector to be no greater than the * content length. * * We really need both unreassembled and "how long it'd * be if it were reassembled" lengths for tvbuffs, so * that we throw the appropriate exceptions for * "not enough data captured" (running past the length), * "packet needed reassembly" (within the length but * running past the unreassembled length), and * "packet is malformed" (running past the reassembled * length). */ if (reported_datalen > content_length) reported_datalen = content_length; } else { /* * No content length specified; if this message doesn't * have a body if no content length is specified, process * nothing as payload. */ if (body_requires_content_len) datalen = 0; } if (datalen > 0) { /* * There's stuff left over; process it. */ tvbuff_t *new_tvb; /* * Now create a tvbuff for the Content-type stuff and * dissect it. * * The amount of data to be processed that's * available in the tvbuff is "datalen", which * is the minimum of the amount of data left in * the tvbuff and any specified content length. * * The amount of data to be processed that's in * this frame, regardless of whether it was * captured or not, is "reported_datalen", * which, if no content length was specified, * is -1, i.e. "to the end of the frame. */ new_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen); if (media_type_str_lower_case && dissector_try_string(media_type_dissector_table, media_type_str_lower_case, new_tvb, pinfo, rtsp_tree)){ }else { /* * Fix up the top-level item so that it doesn't * include the SDP stuff. */ if (ti != NULL) proto_item_set_len(ti, offset); if (tvb_get_guint8(tvb, offset) == RTSP_FRAMEHDR) { /* * This is interleaved stuff; don't * treat it as raw data - set "datalen" * to 0, so we won't skip the offset * past it, which will cause our * caller to process that stuff itself. */ datalen = 0; } else { proto_tree_add_text(rtsp_tree, tvb, offset, datalen, "Data (%d bytes)", reported_datalen); } } /* * We've processed "datalen" bytes worth of data * (which may be no data at all); advance the * offset past whatever data we've processed. */ offset += datalen; } return offset - orig_offset; }
/* * Add an Ethernet trailer - which, for some captures, might be the FCS * rather than a pad-to-60-bytes trailer. * * If fcs_len is 0, we assume the frame has no FCS; if it's 4, we assume * it has an FCS; if it's anything else (such as -1, which means "maybe * it does, maybe it doesn't"), we try to infer whether it has an FCS. */ void add_ethernet_trailer(packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb, tvbuff_t *trailer_tvb, int fcs_len) { /* If there're some bytes left over, it could be a combination of: - padding to meet the minimum 64 byte frame length - an FCS, if present (if fcs_len is 0, we know it's not present; if fcs_len is 4, we know it's present; if fcs_len is -1, we need some heuristics to determine whether it's present) - information inserted by TAPs or other network monitoring equipment. If we don't know whether the FCS is present, then, if we don't have a network monitoring trailer, and if the Ethernet frame was claimed to have had 64 or more bytes - i.e., it was at least an FCS worth of data longer than the minimum payload size - we could assume the last 4 bytes of the trailer are an FCS. */ proto_item *item; proto_tree *checksum_tree; if (trailer_tvb) { guint trailer_length, trailer_reported_length; guint padding_length = 0; gboolean has_fcs = FALSE; tvbuff_t *real_trailer_tvb; trailer_length = tvb_length(trailer_tvb); trailer_reported_length = tvb_reported_length(trailer_tvb); /* There can not have been padding when the length of the frame (including the trailer) is less than 60 bytes. */ if (eth_assume_padding && pinfo->fd->pkt_len>=60) { /* Calculate the amount of padding needed for a minimum sized frame */ if ( (pinfo->fd->pkt_len - trailer_reported_length) < 60 ) padding_length = 60 - (pinfo->fd->pkt_len - trailer_reported_length); /* Add the padding to the tree, unless it should be treated as part of the trailer and therefor be handed over to (one of) the ethernet-trailer dissectors */ if (padding_length > 0) { tvb_ensure_bytes_exist(tvb, 0, padding_length); proto_tree_add_item(fh_tree, hf_eth_padding, trailer_tvb, 0, padding_length, ENC_NA); trailer_length -= padding_length; trailer_reported_length -= padding_length; } } if (fcs_len != 0) { /* If fcs_len is 4, we assume we definitely have an FCS. Otherwise, then, if the frame is big enough that, if we have a trailer, it probably inclues an FCS, and we have enough space in the trailer for the FCS, we assume we have an FCS. "Big enough" means 64 bytes or more; any frame that big needs no trailer, as there's no need to pad an Ethernet packet past 60 bytes. The trailer must be at least 4 bytes long to have enough space for an FCS. */ if (fcs_len == 4 || (tvb_reported_length(tvb) >= 64 && trailer_reported_length >= 4)) { /* Either we know we have an FCS, or we believe we have an FCS. */ if (trailer_length < trailer_reported_length) { /* The packet is claimed to have enough data for a 4-byte FCS, but we didn't capture all of the packet. Slice off the 4-byte FCS from the reported length, and trim the captured length so it's no more than the reported length; that will slice off what of the FCS, if any, is in the captured packet. */ trailer_reported_length -= 4; if (trailer_length > trailer_reported_length) trailer_length = trailer_reported_length; has_fcs = TRUE; } else { /* We captured all of the packet, including what appears to be a 4-byte FCS. Slice it off. */ trailer_length -= 4; trailer_reported_length -= 4; has_fcs = TRUE; } } } /* Create a new tvb without the padding and/or the (assumed) fcs */ if (fcs_len==4) real_trailer_tvb = tvb_new_subset(trailer_tvb, padding_length, trailer_length, trailer_reported_length); else real_trailer_tvb = tvb_new_subset_remaining(trailer_tvb, padding_length); /* Call all ethernet trailer dissectors to dissect the trailer if we actually have a trailer. */ if (tvb_reported_length(real_trailer_tvb) != 0) { if (dissector_try_heuristic(eth_trailer_subdissector_list, real_trailer_tvb, pinfo, tree, NULL) ) { /* If we're not sure that there is a FCS, all trailer data has been given to the ethernet-trailer dissector, so stop dissecting here */ if (fcs_len!=4) return; } else { /* No luck with the trailer dissectors, so just display the extra bytes as general trailer */ if (trailer_length != 0) { tvb_ensure_bytes_exist(tvb, 0, trailer_length); proto_tree_add_item(fh_tree, trailer_id, real_trailer_tvb, 0, trailer_length, ENC_NA); } } } if (has_fcs) { guint32 sent_fcs = tvb_get_ntohl(trailer_tvb, padding_length+trailer_length); if(eth_check_fcs){ guint32 fcs = crc32_802_tvb(tvb, tvb_length(tvb) - 4); if (fcs == sent_fcs) { item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "Frame check sequence: 0x%08x [correct]", sent_fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, TRUE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "Frame check sequence: 0x%08x [incorrect, should be 0x%08x]", sent_fcs, fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, TRUE); PROTO_ITEM_SET_GENERATED(item); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); col_append_str(pinfo->cinfo, COL_INFO, " [ETHERNET FRAME CHECK SEQUENCE INCORRECT]"); } }else{ item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "Frame check sequence: 0x%08x [validiation disabled]", sent_fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); } trailer_length += 4; } proto_tree_set_appendix(fh_tree, tvb, tvb_length(tvb) - padding_length - trailer_length, padding_length + trailer_length); } }
/* Function to dissect EDP portion of ISMP message */ static void dissect_ismp_edp(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *ismp_tree) { /* local variables used for EDP dissection */ int neighbors_count = 0; int tuples_count = 0; guint16 device_type = 0; guint32 options = 0; guint16 num_neighbors = 0; guint16 num_tuples = 0; guint16 tuple_type = 0; guint16 tuple_length = 0; const guint8 *neighbors_ptr; const guint8 *tuples_ptr; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *edp_ti; proto_tree *edp_tree; proto_item *edp_options_ti; proto_tree *edp_options_tree; proto_item *edp_neighbors_ti; proto_tree *edp_neighbors_tree; proto_item *edp_neighbors_leaf_ti; proto_tree *edp_neighbors_leaf_tree; proto_item *edp_tuples_ti; proto_tree *edp_tuples_tree; proto_item *edp_tuples_leaf_ti; proto_tree *edp_tuples_leaf_tree; /* add column iformation marking this as EDP (Enterasys Discover Protocol */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISMP.EDP"); col_clear(pinfo->cinfo, COL_INFO); /* create display subtree for EDP */ if (ismp_tree) { edp_ti = proto_tree_add_item(ismp_tree, hf_ismp_edp, tvb, offset, tvb_length_remaining(tvb, offset), FALSE); edp_tree = proto_item_add_subtree(edp_ti, ett_ismp_edp); col_add_fstr(pinfo->cinfo, COL_INFO, "MIP %s, MMAC %s, ifIdx %d", ip_to_str(tvb_get_ptr(tvb, offset+2, 4)), ether_to_str(tvb_get_ptr(tvb, offset+6, 6)), tvb_get_ntohl(tvb, offset+12)); proto_tree_add_item(edp_tree, hf_ismp_edp_version, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(edp_tree, hf_ismp_edp_module_ip, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(edp_tree, hf_ismp_edp_module_mac, tvb, offset, 6, FALSE); offset += 6; proto_tree_add_item(edp_tree, hf_ismp_edp_module_port, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(edp_tree, hf_ismp_edp_chassis_mac, tvb, offset, 6, FALSE); offset += 6; proto_tree_add_item(edp_tree, hf_ismp_edp_chassis_ip, tvb, offset, 4, FALSE); offset += 4; device_type = tvb_get_ntohs(tvb, offset); proto_tree_add_item(edp_tree, hf_ismp_edp_device_type, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_uint_format(edp_tree, hf_ismp_edp_module_rev, tvb, offset, 4, tvb_get_ntohl(tvb, offset), "Module Firmware Revision: %02x.%02x.%02x.%02x", tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3)); offset += 4; /* create display subtree for EDP options */ options = tvb_get_ntohl(tvb, offset); edp_options_ti = proto_tree_add_uint_format(edp_tree, hf_ismp_edp_options, tvb, offset, 4, options,"Options: 0x%08x",options); edp_options_tree = proto_item_add_subtree(edp_options_ti, ett_ismp_edp_options); /* depending on device_type, show the appropriate options */ switch (device_type) { case EDP_DEVICE_TYPE_SFS17: case EDP_DEVICE_TYPE_SFS18: proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_flood, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_port, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_core, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_switch, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_isolated, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_redun, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_conmsg, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_calltap, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_tagflood, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused2, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_resolve, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_flood, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_lsp, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_sfssup, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused1, tvb, offset, 4, FALSE); break; case EDP_DEVICE_TYPE_ROUTER: proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_level1, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_trans, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_route, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp_snoop, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gmrp, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gvrp, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_8021q, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_dvmrp, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ospf, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_bgp, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_rip, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ssr, tvb, offset, 4, FALSE); break; case EDP_DEVICE_TYPE_BRIDGE: proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_level1, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_trans, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_route, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_igmp, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gmrp, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gvrp, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_8021q, tvb, offset, 4, FALSE); break; case EDP_DEVICE_TYPE_VLANMAN: break; case EDP_DEVICE_TYPE_NTSERVER: case EDP_DEVICE_TYPE_NTCLIENT: case EDP_DEVICE_TYPE_WIN95: case EDP_DEVICE_TYPE_WIN98: case EDP_DEVICE_TYPE_UNIXSERVER: case EDP_DEVICE_TYPE_UNIXCLIENT: proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_ad, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dns, tvb, offset, 4, FALSE); proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dhcp, tvb, offset, 4, FALSE); break; case EDP_DEVICE_TYPE_ACCESSPOINT: default: break; } offset += 4; /* determine the number of neighbors and create EDP neighbors subtree */ num_neighbors = tvb_get_ntohs(tvb, offset); proto_tree_add_item(edp_tree, hf_ismp_edp_num_neighbors, tvb, offset, 2, FALSE); offset += 2; if (num_neighbors > 0) { tvb_ensure_bytes_exist(tvb, offset, num_neighbors*10); if (tvb_reported_length_remaining(tvb, offset) >= (num_neighbors *10)) { neighbors_ptr = tvb_get_ptr( tvb, offset, (num_neighbors*10) ); edp_neighbors_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_neighbors, tvb, offset, num_neighbors*10, neighbors_ptr, "Neighbors:"); } else { neighbors_ptr = tvb_get_ptr( tvb, offset, tvb_reported_length_remaining(tvb, offset) ); edp_neighbors_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_neighbors, tvb, offset, num_neighbors *10, neighbors_ptr, "Neighbors:"); } edp_neighbors_tree = proto_item_add_subtree(edp_neighbors_ti, ett_ismp_edp_neighbors); while ( neighbors_count < num_neighbors && tvb_reported_length_remaining(tvb, offset) >= 10) { edp_neighbors_leaf_ti = proto_tree_add_text(edp_neighbors_tree, tvb, offset, 10, "Neighbor%d", (neighbors_count+1)); edp_neighbors_leaf_tree = proto_item_add_subtree(edp_neighbors_leaf_ti, ett_ismp_edp_neighbors_leaf); proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 6, "MAC Address: %s", ether_to_str(tvb_get_ptr(tvb, offset, 6))); proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 4, "Assigned Neighbor State 0x%04x",tvb_get_ntohl(tvb, offset)); offset += 10; neighbors_count++; } if (neighbors_count != num_neighbors) { proto_tree_add_text(edp_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET"); return; } } /* determine data remains, if so, count tuples and create EDP tuples subtree */ if (tvb_reported_length_remaining(tvb, offset) != 0 && tvb_reported_length_remaining(tvb, offset) >= 2) { num_tuples = tvb_get_ntohs(tvb, offset); proto_tree_add_item(edp_tree, hf_ismp_edp_num_tuples, tvb, offset, 2, FALSE); offset += 2; } else if (tvb_reported_length_remaining(tvb, offset) > 0) { proto_tree_add_text(edp_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET"); return; } else { return; } /* start populating tuple information */ if (num_tuples && tvb_reported_length_remaining(tvb, offset) >= 4) { tuples_ptr = tvb_get_ptr(tvb, offset, tvb_reported_length_remaining(tvb, offset)); edp_tuples_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_tuples, tvb, offset, tvb_reported_length_remaining(tvb, offset), tuples_ptr, "Tuples"); edp_tuples_tree = proto_item_add_subtree(edp_tuples_ti, ett_ismp_edp_tuples); while ( (tuples_count < num_tuples) && (tvb_reported_length_remaining(tvb, offset) >= 4) ) { tuple_length = tvb_get_ntohs(tvb, offset+2); edp_tuples_leaf_ti = proto_tree_add_text(edp_tuples_tree, tvb, offset, tuple_length, "Tuple%d", tuples_count+1); edp_tuples_leaf_tree = proto_item_add_subtree(edp_tuples_leaf_ti, ett_ismp_edp_tuples_leaf); tuple_type = tvb_get_ntohs(tvb, offset); proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2, "Tuple Type: %s(%d)", val_to_str( tuple_type, edp_tuple_types, "Unknown"), tuple_type ); offset += 2; proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2, "Tuple Length: %d", tuple_length); tuple_length -= 4; offset += 2; if (tvb_reported_length_remaining(tvb, offset) >= tuple_length) { tvb_ensure_bytes_exist(tvb, offset, tuple_length); switch (tuple_type) { case EDP_TUPLE_HOLD: proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length, "Hold Time = %d", tvb_get_ntohs(tvb, offset)); break; case EDP_TUPLE_INT_NAME: proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length, "Interface Name = %s", tvb_format_text(tvb, offset, tuple_length)); col_append_fstr(pinfo->cinfo, COL_INFO, ", ifName %s", tvb_format_text(tvb, offset, tuple_length)); break; case EDP_TUPLE_SYS_DESCRIPT: proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length, "System Description = %s", tvb_format_text(tvb, offset, tuple_length)); break; case EDP_TUPLE_IPX_ADDR: proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length, "Interface IPX_address = %s", ipx_addr_to_str(tvb_get_ntohl(tvb, offset), tvb_get_ptr(tvb, offset+4, tuple_length-4))); break; case EDP_TUPLE_UNKNOWN: default: proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length, "Unknown Tuple Data %s", tvb_format_text(tvb, offset, tuple_length)); break; } } offset += tuple_length; tuples_count++; tuple_type = 0; tuple_length = 0; } if (tuples_count != num_tuples) { proto_tree_add_text(edp_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET"); return; } else { return; } } } }
static int dissect_daap_one_tag(proto_tree *tree, tvbuff_t *tvb, int offset, int length) { unsigned int tagname; int tagsize; int new_offset; proto_item *ti = NULL; proto_item *ti2 = NULL; proto_tree *new_tree = NULL; do { if (!tvb_offset_exists(tvb, offset)) break; tagname = tvb_get_ntohl(tvb, offset); tagsize = tvb_get_ntohl(tvb, offset+4); tvb_ensure_bytes_exist(tvb, offset, tagsize+8); ti = proto_tree_add_text(tree, tvb, offset, tagsize+8, "Tag: %c%c%c%c, Size: %d", tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3), tagsize); ti2 = proto_tree_add_item(tree, hf_daap_name, tvb, offset, 4, FALSE); PROTO_ITEM_SET_HIDDEN(ti2); ti2 = proto_tree_add_item(tree, hf_daap_size, tvb, offset+4, 4, FALSE); PROTO_ITEM_SET_HIDDEN(ti2); offset += 8; length -= 8; switch (tagname) { case daap_mcon: case daap_msrv: case daap_mccr: case daap_mdcl: case daap_mlog: case daap_mupd: case daap_avdb: case daap_mlcl: case daap_mlit: case daap_mbcl: case daap_adbs: case daap_aply: case daap_apso: case daap_mudl: case daap_abro: case daap_abal: case daap_abcp: case daap_abgn: case daap_prsv: case daap_arif: /* Container tags */ new_tree = proto_item_add_subtree(ti, ett_daap_sub); new_offset = dissect_daap_one_tag(new_tree, tvb, offset, tagsize); break; case daap_minm: case daap_msts: case daap_mcnm: case daap_mcna: case daap_asal: case daap_asar: case daap_ascm: case daap_asfm: case daap_aseq: case daap_asgn: case daap_asdt: case daap_asul: /* Tags contain strings */ proto_item_append_text(ti, ", Data: %s", tvb_format_text(tvb, offset, tagsize)); break; case daap_mper: /* Tags conain uint64 */ proto_item_append_text(ti, ", Persistent Id: %" G_GINT64_MODIFIER "u", tvb_get_ntoh64(tvb, offset)); break; case daap_mstt: proto_item_append_text(ti, ", Status: %d", tvb_get_ntohl(tvb, offset)); break; case daap_musr: case daap_msur: proto_item_append_text(ti, ", Revision: %d", tvb_get_ntohl(tvb, offset)); break; case daap_miid: case daap_mcti: case daap_mpco: case daap_mlid: proto_item_append_text(ti, ", Id: %d", tvb_get_ntohl(tvb, offset)); break; case daap_mrco: case daap_mtco: case daap_mimc: case daap_msdc: proto_item_append_text(ti, ", Count: %d", tvb_get_ntohl(tvb, offset)); break; case daap_mstm: proto_item_append_text(ti, ", Timeout: %d seconds", tvb_get_ntohl(tvb, offset)); break; case daap_asda: case daap_asdm: case daap_assr: case daap_assz: case daap_asst: case daap_assp: case daap_astm: case daap_aeNV: /* Tags conain uint32 */ proto_item_append_text(ti, ", Data: %d", tvb_get_ntohl(tvb, offset)); break; case daap_mcty: case daap_asbt: case daap_asbr: case daap_asdc: case daap_asdn: case daap_astc: case daap_astn: case daap_asyr: /* Tags conain uint16 */ proto_item_append_text(ti, ", Data: %d", tvb_get_ntohs(tvb, offset)); break; case daap_mikd: case daap_msau: case daap_msty: case daap_asrv: case daap_asur: case daap_asdk: /* Tags conain uint8 */ proto_item_append_text(ti, ", Data: %d", tvb_get_guint8(tvb, offset)); break; case daap_mslr: case daap_msal: case daap_msup: case daap_mspi: case daap_msex: case daap_msbr: case daap_msqy: case daap_msix: case daap_msrs: case daap_asco: case daap_asdb: case daap_abpl: case daap_aeSP: /* Tags ARE boolean. Data is (uint8), but it seems * the value is always zero. So, if the tag is present * the "bool" is true. */ proto_item_append_text(ti, ", Data: True"); break; case daap_mpro: case daap_apro: /* Tags conain version (uint32) */ proto_item_append_text(ti, ", Version: %d.%d.%d.%d", tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3)); break; default: break; } offset += tagsize; length -= tagsize; } while (length > 0); return offset; }
void dissect_nhrp_mand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *pOffset, gint mandLen, oui_info_t *oui_info, e_nhrp_hdr *hdr, guint *srcLen, gboolean codeinfo) { gint offset = *pOffset; gint mandEnd = offset + mandLen; guint8 ssl, shl; guint16 flags; guint dstLen; gboolean isReq = 0; gboolean isErr = 0; gboolean isInd = 0; proto_item *nhrp_tree_item = NULL; proto_item *flag_item = NULL; proto_tree *nhrp_tree = NULL; proto_tree *flag_tree = NULL; tvb_ensure_bytes_exist(tvb, offset, mandLen); switch (hdr->ar_op_type) { case NHRP_RESOLUTION_REPLY: case NHRP_REGISTRATION_REPLY: case NHRP_PURGE_REPLY: break; case NHRP_RESOLUTION_REQ: case NHRP_REGISTRATION_REQ: case NHRP_PURGE_REQ: isReq = 1; break; case NHRP_ERROR_INDICATION: /* This needs special treatment */ isErr = 1; isInd = 1; break; case NHRP_TRAFFIC_INDICATION: isInd = 1; break; } nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, mandLen, "NHRP Mandatory Part"); nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_mand); *srcLen = tvb_get_guint8(tvb, offset); proto_tree_add_item(nhrp_tree, hf_nhrp_src_proto_len, tvb, offset, 1, FALSE); offset += 1; dstLen = tvb_get_guint8(tvb, offset); proto_tree_add_item(nhrp_tree, hf_nhrp_dst_proto_len, tvb, offset, 1, FALSE); offset += 1; if (!isInd) { flags = tvb_get_ntohs(tvb, offset); flag_item = proto_tree_add_uint(nhrp_tree, hf_nhrp_flags, tvb, offset, 2, flags); flag_tree = proto_item_add_subtree(flag_item, ett_nhrp_mand_flag); switch (hdr->ar_op_type) { case NHRP_RESOLUTION_REQ: case NHRP_RESOLUTION_REPLY: proto_tree_add_boolean(flag_tree, hf_nhrp_flag_Q, tvb, offset, 2, flags); proto_tree_add_boolean(flag_tree, hf_nhrp_flag_A, tvb, offset, 2, flags); proto_tree_add_boolean(flag_tree, hf_nhrp_flag_D, tvb, offset, 2, flags); proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U1, tvb, offset, 2, flags); proto_tree_add_boolean(flag_tree, hf_nhrp_flag_S, tvb, offset, 2, flags); break; case NHRP_REGISTRATION_REQ: case NHRP_REGISTRATION_REPLY: proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U2, tvb, offset, 2, flags); break; case NHRP_PURGE_REQ: case NHRP_PURGE_REPLY: proto_tree_add_boolean(flag_tree, hf_nhrp_flag_N, tvb, offset, 2, flags); break; } proto_tree_add_boolean(flag_tree, hf_nhrp_flag_NAT, tvb, offset, 2, flags); offset += 2; col_append_fstr(pinfo->cinfo, COL_INFO, ", ID=%u", tvb_get_ntohl(tvb, offset)); proto_tree_add_item(nhrp_tree, hf_nhrp_request_id, tvb, offset, 4, FALSE); offset += 4; } else if (isErr) { offset += 2; col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str(tvb_get_ntohs(tvb, offset), nhrp_error_code_vals, "Unknown Error (%u)")); proto_tree_add_item(nhrp_tree, hf_nhrp_error_code, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nhrp_tree, hf_nhrp_error_offset, tvb, offset, 2, FALSE); offset += 2; } else { offset += 6; } shl = NHRP_SHTL_LEN(hdr->ar_shtl); if (shl) { switch (hdr->ar_afn) { case AFNUM_INET: if (shl == 4) proto_tree_add_item(nhrp_tree, hf_nhrp_src_nbma_addr, tvb, offset, 4, FALSE); else { proto_tree_add_text(nhrp_tree, tvb, offset, shl, "Source NBMA Address: %s", tvb_bytes_to_str(tvb, offset, shl)); } break; default: proto_tree_add_text(nhrp_tree, tvb, offset, shl, "Source NBMA Address: %s", tvb_bytes_to_str(tvb, offset, shl)); break; } offset += shl; } ssl = NHRP_SHTL_LEN(hdr->ar_sstl); if (ssl) { proto_tree_add_text(nhrp_tree, tvb, offset, ssl, "Source NBMA Sub Address: %s", tvb_bytes_to_str(tvb, offset, ssl)); offset += ssl; } if (*srcLen == 4) { proto_tree_add_item(nhrp_tree, hf_nhrp_src_prot_addr, tvb, offset, 4, FALSE); offset += 4; } else if (*srcLen) { proto_tree_add_text(nhrp_tree, tvb, offset, *srcLen, "Source Protocol Address: %s", tvb_bytes_to_str(tvb, offset, *srcLen)); offset += *srcLen; } if (dstLen == 4) { proto_tree_add_item(nhrp_tree, hf_nhrp_dst_prot_addr, tvb, offset, 4, FALSE); offset += 4; } else if (dstLen) { proto_tree_add_text(nhrp_tree, tvb, offset, dstLen, "Destination Protocol Address: %s", tvb_bytes_to_str(tvb, offset, dstLen)); offset += dstLen; } if (isInd) { gboolean save_in_error_pkt; gint pkt_len = mandEnd - offset; proto_item *ind_tree_item = proto_tree_add_text(tree, tvb, offset, pkt_len, "Packet Causing Indication"); proto_tree *ind_tree = proto_item_add_subtree(ind_tree_item, ett_nhrp_indication); gboolean dissected; tvbuff_t *sub_tvb; save_in_error_pkt = pinfo->in_error_pkt; pinfo->in_error_pkt = TRUE; sub_tvb = tvb_new_subset_remaining(tvb, offset); if (isErr) { _dissect_nhrp(sub_tvb, pinfo, ind_tree, TRUE, FALSE); } else { if (hdr->ar_pro_type <= 0xFF) { /* It's an NLPID */ if (hdr->ar_pro_type == NLPID_SNAP) { /* * Dissect based on the SNAP OUI * and PID. */ if (hdr->ar_pro_type_oui == 0x000000) { /* * "Should not happen", as * the protocol type should * be the Ethertype, but.... */ dissected = dissector_try_port( ethertype_subdissector_table, hdr->ar_pro_type_pid, sub_tvb, pinfo, ind_tree); } else { /* * If we have a dissector * table, use it, otherwise * just dissect as data. */ if (oui_info != NULL) { dissected = dissector_try_port( oui_info->table, hdr->ar_pro_type_pid, sub_tvb, pinfo, ind_tree); } else dissected = FALSE; } } else { /* * Dissect based on the NLPID. */ dissected = dissector_try_port( osinl_subdissector_table, hdr->ar_pro_type, sub_tvb, pinfo, ind_tree) || dissector_try_port( osinl_excl_subdissector_table, hdr->ar_pro_type, sub_tvb, pinfo, ind_tree); } } else if (hdr->ar_pro_type <= 0x3FF) { /* Reserved for future use by the IETF */ dissected = FALSE; } else if (hdr->ar_pro_type <= 0x04FF) { /* Allocated for use by the ATM Forum */ dissected = FALSE; } else if (hdr->ar_pro_type <= 0x05FF) { /* Experimental/Local use */ dissected = FALSE; } else { dissected = dissector_try_port( ethertype_subdissector_table, hdr->ar_pro_type, sub_tvb, pinfo, ind_tree); } if (!dissected) { call_dissector(data_handle, sub_tvb, pinfo, ind_tree); } } pinfo->in_error_pkt = save_in_error_pkt; offset = mandEnd; } /* According to RFC 2332, section 5.2.7, there shouldn't be any extensions * in the Error Indication packet. */ if (isErr && tvb_reported_length_remaining(tvb, offset)) { expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "Extensions not allowed per RFC2332 section 5.2.7"); } dissect_cie_list(tvb, pinfo, nhrp_tree, offset, mandEnd, hdr, isReq, codeinfo); *pOffset = mandEnd; }
void dissect_nhrp_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *pOffset, gint extLen, e_nhrp_hdr *hdr, guint srcLen, gboolean nested) { gint offset = *pOffset; gint extEnd = offset + extLen; proto_item *nhrp_tree_item = NULL; proto_tree *nhrp_tree = NULL; proto_item *ti = NULL; tvb_ensure_bytes_exist(tvb, offset, extLen); while ((offset + 4) <= extEnd) { gint extTypeC = tvb_get_ntohs(tvb, offset); gint extType = extTypeC & 0x3FFF; guint len = tvb_get_ntohs(tvb, offset+2); if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) { /* Assume it's not really a Cisco NAT extension, but a device * capabilities extension instead (see RFC 2735). */ nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, len + 4, "Device Capabilities Extension"); } else { nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, len + 4, "%s", val_to_str(extType, ext_type_vals, "Unknown (%u)")); } nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_ext); proto_tree_add_boolean(nhrp_tree, hf_nhrp_ext_C, tvb, offset, 2, extTypeC); proto_tree_add_item(nhrp_tree, hf_nhrp_ext_type, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nhrp_tree, hf_nhrp_ext_len, tvb, offset, 2, FALSE); offset += 2; if (len && (extType != NHRP_EXT_NULL)) { tvb_ensure_bytes_exist(tvb, offset, len); if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) { /* Assume it's not really a Cisco NAT extension, but a device * capabilities extension instead (see RFC 2735). */ proto_item *devcap_item; proto_tree *devcap_tree; proto_item *cap_item; proto_tree *cap_tree; devcap_item = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Extension Data: Src is %sVPN-aware; Dst is %sVPN-aware", tvb_get_ntohl(tvb, offset) & 1 ? "" : "non-", tvb_get_ntohl(tvb, offset + 4) & 1 ? "" : "non-"); devcap_tree = proto_item_add_subtree(devcap_item, ett_nhrp_devcap_ext); cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_srccap, tvb, offset, 4, FALSE); cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_srccap); proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_srccap_V, tvb, offset, 4, FALSE); cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_dstcap, tvb, offset + 4, 4, FALSE); cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_dstcap); proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_dstcap_V, tvb, offset + 4, 4, FALSE); goto skip_switch; } switch (extType) { case NHRP_EXT_RESP_ADDR: case NHRP_EXT_FWD_RECORD: case NHRP_EXT_REV_RECORD: case NHRP_EXT_NAT_ADDRESS: dissect_cie_list(tvb, pinfo, nhrp_tree, offset, offset + len, hdr, 0, FALSE); break; case NHRP_EXT_AUTH: case NHRP_EXT_MOBILE_AUTH: if (len < (4 + srcLen)) { ti = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Malformed Extension: %s", tvb_bytes_to_str(tvb, offset, len)); expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Incomplete Authentication Extension"); } else { proto_item *auth_item; proto_tree *auth_tree; auth_item = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Extension Data: SPI=%u: Data=%s", tvb_get_ntohs(tvb, offset + 2), tvb_bytes_to_str(tvb, offset + 4, len - 4)); auth_tree = proto_item_add_subtree(auth_item, ett_nhrp_auth_ext); proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_reserved, tvb, offset, 2, FALSE); proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_spi, tvb, offset + 2, 2, FALSE); if (srcLen == 4) proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_src_addr, tvb, offset + 4, 4, FALSE); else if (srcLen) { proto_tree_add_text(auth_tree, tvb, offset + 4, srcLen, "Source Address: %s", tvb_bytes_to_str(tvb, offset + 4, srcLen)); } if (len > (4 + srcLen)) { proto_tree_add_text(auth_tree, tvb, offset + 4 + srcLen, len - (4 + srcLen), "Data: %s", tvb_bytes_to_str(tvb, offset + 4 + srcLen, len - (4 + srcLen))); } } break; case NHRP_EXT_VENDOR_PRIV: if (len < 3) { ti = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Malformed Extension: %s", tvb_bytes_to_str(tvb, offset, len)); expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Incomplete Vendor-Private Extension"); } else { proto_item *vendor_item; proto_tree *vendor_tree; gchar manuf[3]; tvb_memcpy(tvb, manuf, offset, 3); vendor_item = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Extension Data: Vendor ID=%s, Data=%s", get_manuf_name(manuf), tvb_bytes_to_str(tvb, offset + 3, len - 3)); vendor_tree = proto_item_add_subtree(vendor_item, ett_nhrp_vendor_ext); proto_tree_add_bytes_format(vendor_tree, hf_nhrp_vendor_ext_id, tvb, offset, 3, manuf, "Vendor ID: %s", get_manuf_name(manuf)); if (len > 3) { proto_tree_add_text(vendor_tree, tvb, offset + 3, len - 3, "Data: %s", tvb_bytes_to_str(tvb, offset + 3, len - 3)); } } break; default: proto_tree_add_text(nhrp_tree, tvb, offset, len, "Extension Value: %s", tvb_bytes_to_str(tvb, offset, len)); break; } skip_switch: offset += len; } if (!nested) { len = tvb_reported_length_remaining(tvb, offset); if ((extType == NHRP_EXT_NULL) && len) { ti = proto_tree_add_text(tree, tvb, offset, len, "Unknown Data (%d bytes)", len); expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Superfluous data follows End Extension"); break; } } } *pOffset = extEnd; }
/* nopad == TRUE : Do not add any padding before this string * exactlen == TRUE : len contains the exact len of the string in bytes. * bc: pointer to variable with amount of data left in the byte parameters * region */ const gchar * get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp, gboolean useunicode, int *len, gboolean nopad, gboolean exactlen, guint16 *bcp) { gchar *cur; const gchar *string; int string_len = 0; int copylen; gboolean overflow = FALSE; if (*bcp == 0) { /* Not enough data in buffer */ return NULL; } if (useunicode) { if ((!nopad) && (*offsetp % 2)) { (*offsetp)++; /* Looks like a pad byte there sometimes */ (*bcp)--; if (*bcp == 0) { /* Not enough data in buffer */ return NULL; } } if(exactlen){ string_len = *len; if (string_len < 0) { /* This probably means it's a very large unsigned number; just set it to the largest signed number, so that we throw the appropriate exception. */ string_len = INT_MAX; } } string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp); } else { if(exactlen){ /* * The string we return must be null-terminated. */ cur=ep_alloc(MAX_UNICODE_STR_LEN+3+1); copylen = *len; if (copylen < 0) { /* This probably means it's a very large unsigned number; just set it to the largest signed number, so that we throw the appropriate exception. */ copylen = INT_MAX; } tvb_ensure_bytes_exist(tvb, *offsetp, copylen); if (copylen > MAX_UNICODE_STR_LEN) { copylen = MAX_UNICODE_STR_LEN; overflow = TRUE; } tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen); cur[copylen] = '\0'; if (overflow) g_strlcat(cur, "...",MAX_UNICODE_STR_LEN+3+1); string_len = *len; string = cur; } else { string = tvb_get_const_stringz(tvb, *offsetp, &string_len); } } *len = string_len; return string; }
/* G.7041 6.1.2 GFP payload area */ static void dissect_gfp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *gfp_tree, guint *offset, guint payload_len) { tvbuff_t *payload_tvb; proto_item *type_ti = NULL; proto_item *fcs_ti; proto_tree *fcs_tree = NULL; guint pti, pfi, exi, upi; guint fcs, fcs_calc; guint fcs_len = 0; /* G.7041 6.1.2.3 Payload area scrambling * Note that payload when sent on the wire is scrambled as per ATM * with a 1 + x^43 multiplicative scrambler. Likely already removed by * the time we get a capture file (as with ATM). Could have a pref, * but if it's present we have to save state over subsequent frames, * always would fail to decode the first 43 payload bytes of a capture. */ /* G.7041 6.1.2.1 Payload Header - at least 4 bytes */ tvb_ensure_bytes_exist(tvb, *offset, 4); payload_len -= 4; /* G.7041 6.1.2.1.1 GFP type field - mandatory 2 bytes */ pti = tvb_get_bits8(tvb, 8*(*offset), 3); pfi = tvb_get_bits8(tvb, 8*(*offset)+3, 1); exi = tvb_get_bits8(tvb, 8*(*offset)+4, 4); upi = tvb_get_guint8(tvb, *offset+1); p_add_proto_data(pinfo->pool, pinfo, proto_gfp, 0, GUINT_TO_POINTER(upi)); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pti, gfp_pti_vals, "Reserved PTI (%d)")); if (pti == GFP_USER_DATA || pti == GFP_MANAGEMENT_COMMUNICATIONS) { /* G.7041 Table 6-3 - GFP_MANAGEMENT_COMMUNICATIONS * uses the same UPI table as USER_DATA, though * "not all of these UPI types are applicable" in that case. */ type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type, ett_gfp_type, gfp_type_data_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS); col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_data_rvals, "Unknown 0x%02x")); } else if (pti == GFP_CLIENT_MANAGEMENT) { /* G.7041 Table 6-4 */ type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type, ett_gfp_type, gfp_type_management_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS); col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_management_rvals, "Unknown 0x%02x")); } /* G.7041 6.1.2.1.2 Type HEC (tHEC) - mandatory 2 bytes */ gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_thec, hf_gfp_thec_status, &ei_gfp_thec_bad); switch (exi) { case GFP_EXT_NULL: /* G.7041 6.1.2.1.3.1 Null extension header */ break; case GFP_EXT_LINEAR: /* G.7041 6.1.2.1.3.2 Extension header for a linear frame */ if (payload_len < 4) { expert_add_info(pinfo, type_ti, &ei_gfp_exi_short); payload_len = 0; } else { payload_len -= 4; } proto_tree_add_item(gfp_tree, hf_gfp_cid, tvb, *offset, 1, ENC_BIG_ENDIAN); /* Next byte spare field, reserved */ /* 6.1.2.1.4 Extension HEC field */ gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_ehec, hf_gfp_ehec_status, &ei_gfp_ehec_bad); break; case GFP_EXT_RING: /* 6.1.2.1.3.3 Extension header for a ring frame */ /* "For further study." Undefined so fall through */ default: /* Reserved */ /* TODO: Mark as error / unhandled? */ break; } proto_item_set_end(gfp_tree, tvb, *offset); if (pfi == 1) { /* 6.1.2.2.1 Payload FCS field present */ if (payload_len < 4) { expert_add_info(pinfo, type_ti, &ei_gfp_pfi_short); fcs_len = payload_len; payload_len = 0; } else { fcs_len = 4; payload_len -= 4; } proto_tree_set_appendix(gfp_tree, tvb, *offset + payload_len, fcs_len); fcs = tvb_get_ntohl(tvb, *offset + payload_len); /* Same CRC32 as ATM */ /* As with ATM, we can either compute the CRC as it would be * calculated and compare (last step involves taking the complement), * or we can include the passed CRC in the input and check to see * if the remainder is a known value. I like the first method * only because it lets us display what we should have received. */ /* Method 1: */ fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len); if (fcs == ~fcs_calc) { fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [correct]", fcs); fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs); fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, TRUE); PROTO_ITEM_SET_GENERATED(fcs_ti); fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, FALSE); PROTO_ITEM_SET_GENERATED(fcs_ti); } else { fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [incorrect, should be 0x%08x]", fcs, fcs_calc); fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs); fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, FALSE); PROTO_ITEM_SET_GENERATED(fcs_ti); fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, TRUE); PROTO_ITEM_SET_GENERATED(fcs_ti); expert_add_info(pinfo, fcs_ti, &ei_gfp_fcs_bad); } /* Method 2: */ /* fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len+4); fcs_ti = proto_tree_add_uint(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs); proto_item_append_text(fcs_ti, (fcs_calc == 0xC704DD7B) ? " [correct]" : " [incorrect]"); */ } /* Some client frames we can do. Others are not implemented yet. * Transparent mode types are much trickier than frame-mapped, * since they requires reassembling streams across multiple GFP packets. */ payload_tvb = tvb_new_subset_length(tvb, *offset, payload_len); switch (pti) { case GFP_USER_DATA: case GFP_MANAGEMENT_COMMUNICATIONS: if (!dissector_try_uint(gfp_dissector_table, upi, payload_tvb, pinfo, tree)) { expert_add_info_format(pinfo, type_ti, &ei_gfp_payload_undecoded, "Payload type 0x%02x (%s) unsupported", upi, rval_to_str_const(upi, gfp_upi_data_rvals, "UNKNOWN")); call_data_dissector(payload_tvb, pinfo, tree); } break; case GFP_CLIENT_MANAGEMENT: call_data_dissector(payload_tvb, pinfo, tree); break; default: break; } *offset += payload_len; *offset += fcs_len; }