static gboolean test_njack(tvbuff_t *tvb) { /* We need at least 'NJ200' + 1 Byte packet type */ if ( (tvb_length(tvb) < 6) || (tvb_strncaseeql(tvb, 0, "NJ200", 5) != 0) ) { return FALSE; } return TRUE; }
/* Returns index of headers */ static gint msrp_is_known_msrp_header(tvbuff_t *tvb, int offset, guint header_len) { guint i; for (i = 1; i < array_length(msrp_headers); i++) { if (header_len == strlen(msrp_headers[i].name) && tvb_strncaseeql(tvb, offset, msrp_headers[i].name, header_len) == 0) { return i; } } return -1; }
static int cond_casestring(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { int len = wanted->len; #ifdef TVBPARSE_DEBUG if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: control='%s'",wanted->control.str); #endif if ( offset + len > tt->end_offset ) return -1; if ( tvb_strncaseeql(tt->tvb, offset, wanted->control.str, len) == 0 ) { *tok = new_tok(tt,wanted->id,offset,len,wanted); #ifdef TVBPARSE_DEBUG if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: GOT len=%i",len); #endif return len; } else { *tok = NULL; return -1; } }
static int dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { proto_tree *subtree; proto_item *ti; gint offset = 0, next_offset; gint len; http_message_info_t *message_info; const char *data_name; int length = tvb_captured_length(tvb); /* Check if this is actually xml * If there is less than 38 characters this is not XML * <?xml version="1.0" encoding="UTF-8"?> */ if(length > 38){ if (tvb_strncaseeql(tvb, 0, "<?xml", 5) == 0){ call_dissector(xml_handle, tvb, pinfo, tree); return length; } } data_name = pinfo->match_string; if (! (data_name && data_name[0])) { /* * No information from "match_string" */ message_info = (http_message_info_t *)data; if (message_info == NULL) { /* * No information from dissector data */ data_name = NULL; } else { data_name = message_info->media_str; if (! (data_name && data_name[0])) { /* * No information from dissector data */ data_name = NULL; } } } if (data_name) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name); if (tree) { guint lines_read = 0; ti = proto_tree_add_item(tree, proto_text_lines, tvb, 0, -1, ENC_NA); if (data_name) proto_item_append_text(ti, ": %s", data_name); subtree = proto_item_add_subtree(ti, ett_text_lines); /* Read the media line by line */ while (tvb_offset_exists(tvb, offset)) { /* * XXX - we need to be passed the parameters * of the content type via data parameter, * so that we know the character set. We'd * have to handle that character set, which * might be a multibyte character set such * as "iso-10646-ucs-2", or might require other * special processing. */ len = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); if (len == -1) break; /* We use next_offset - offset instead of len in the * call to proto_tree_add_format_text() so it will include the * line terminator(s) (\r and/or \n) in the display. */ proto_tree_add_format_text(subtree, tvb, offset, next_offset - offset); lines_read++; offset = next_offset; } proto_item_append_text(subtree, " (%u lines)", lines_read); } return length; }
/* Code to actually dissect the packets */ static int dissect_tivoconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* parsing variables */ gchar * string = NULL; gint length = -1; /* value strings */ gchar * proto_name = NULL; gchar * packet_identity = NULL; gchar * packet_machine = NULL; /* validate that we have a tivoconnect packet */ if ( tvb_strncaseeql(tvb, 0, "tivoconnect", 11) != 0) { return 0; } length = tvb_length(tvb); string = (gchar*)tvb_get_ephemeral_string(tvb, 0, length); /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TiVoConnect"); /* make a distinction between UDP and TCP packets */ proto_name = pinfo->ipproto == IP_PROTO_TCP ? "Discovery Connection" : "Discovery Beacon"; col_set_str(pinfo->cinfo, COL_INFO, proto_name); if (tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti = NULL; proto_tree *tivoconnect_tree = NULL; /* parsing variables */ guint offset = 0; gchar * field = NULL; /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_tivoconnect, tvb, 0, -1, ENC_NA); tivoconnect_tree = proto_item_add_subtree(ti, ett_tivoconnect); /* process the packet */ for ( field = strtok(string,"\n"); field; offset+=length, field = strtok(NULL,"\n") ) { gchar * value = NULL; gint fieldlen; length = (int)strlen(field) + 1; if ( !(value=strchr(field, '=')) ) { /* bad packet: missing the field separator */ continue; } *value++='\0'; fieldlen=(int)strlen(field)+1; if ( g_ascii_strcasecmp(field,"tivoconnect") == 0 ) { proto_tree_add_item(tivoconnect_tree, hf_tivoconnect_flavor, tvb, offset+fieldlen, length-fieldlen-1, ENC_ASCII|ENC_NA); } else if ( g_ascii_strcasecmp(field,"method") == 0 ) { proto_tree_add_item(tivoconnect_tree, hf_tivoconnect_method, tvb, offset+fieldlen, length-fieldlen-1, ENC_ASCII|ENC_NA); } else if ( g_ascii_strcasecmp(field,"platform") == 0 ) { proto_tree_add_item(tivoconnect_tree, hf_tivoconnect_platform, tvb, offset+fieldlen, length-fieldlen-1, ENC_ASCII|ENC_NA); } else if ( g_ascii_strcasecmp(field,"machine") == 0 ) { proto_tree_add_item(tivoconnect_tree, hf_tivoconnect_machine, tvb, offset+fieldlen, length-fieldlen-1, ENC_ASCII|ENC_NA); packet_machine = value; } else if ( g_ascii_strcasecmp(field,"identity") == 0 ) { proto_tree_add_item(tivoconnect_tree, hf_tivoconnect_identity, tvb, offset+fieldlen, length-fieldlen-1, ENC_ASCII|ENC_NA); packet_identity = value; } else if ( g_ascii_strcasecmp(field,"services") == 0 ) { proto_tree_add_item(tivoconnect_tree, hf_tivoconnect_services, tvb, offset+fieldlen, length-fieldlen-1, ENC_ASCII|ENC_NA); } else if ( g_ascii_strcasecmp(field,"swversion") == 0 ) { proto_tree_add_item(tivoconnect_tree, hf_tivoconnect_version, tvb, offset+fieldlen, length-fieldlen-1, ENC_ASCII|ENC_NA); } else { /* unknown field! */ } } /* Adjust "Info" column and top of tree into more useful info */ if (packet_machine) { proto_item_append_text(ti, ", %s", packet_machine); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", proto_name, packet_machine); } if (packet_identity) { proto_item_append_text(ti, packet_machine ? " (%s)" : ", ID:%s", packet_identity); if (packet_machine) { if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s (%s)", proto_name, packet_machine, packet_identity); } else { if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "%s ID:%s", proto_name, packet_identity); } } } /* If this protocol has a sub-dissector call it here, see section 1.8 */ return tvb_length(tvb); }
static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo, struct ssh_flow_data *global_data, int offset, proto_tree *tree, int is_response, guint * version, gboolean *need_desegmentation) { guint remain_length; gint linelen, protolen; /* * If the first packet do not contain the banner, * it is dump in the middle of a flow or not a ssh at all */ if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) { offset = ssh_dissect_encrypted_packet(tvb, pinfo, &global_data->peer_data[is_response], offset, tree); return offset; } if (!is_response) { if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) { *(version) = SSH_VERSION_2; } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) { *(version) = SSH_VERSION_2; } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) { *(version) = SSH_VERSION_1; } } /* * We use "tvb_ensure_length_remaining()" to make sure there * actually *is* data remaining. * * This means we're guaranteed that "remain_length" is positive. */ remain_length = tvb_ensure_length_remaining(tvb, offset); /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); */ linelen = tvb_find_guint8(tvb, offset, -1, '\n'); if (ssh_desegment && pinfo->can_desegment) { if (linelen == -1 || remain_length < (guint)linelen-offset) { pinfo->desegment_offset = offset; pinfo->desegment_len = linelen-remain_length; *need_desegmentation = TRUE; return offset; } } if (linelen == -1) { /* XXX - reassemble across segment boundaries? */ linelen = remain_length; protolen = linelen; } else { linelen = linelen - offset + 1; if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r') protolen = linelen - 2; else protolen = linelen - 1; } col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)", tvb_format_text(tvb, offset, protolen)); proto_tree_add_item(tree, hf_ssh_protocol, tvb, offset, linelen, ENC_ASCII|ENC_NA); offset+=linelen; return offset; }
static void dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *ssh_tree = NULL; proto_item *ti; conversation_t *conversation; int last_offset, offset = 0; gboolean is_response = (pinfo->destport != pinfo->match_uint), need_desegmentation; guint version; struct ssh_flow_data *global_data=NULL; struct ssh_peer_data *peer_data; conversation = find_or_create_conversation(pinfo); global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh); if (!global_data) { global_data = (struct ssh_flow_data *)wmem_alloc0(wmem_file_scope(), sizeof(struct ssh_flow_data)); global_data->version=SSH_VERSION_UNKNOWN; global_data->kex_specific_dissector=ssh_dissect_kex_dh; global_data->peer_data[CLIENT_PEER_DATA].mac_length=-1; global_data->peer_data[SERVER_PEER_DATA].mac_length=-1; conversation_add_proto_data(conversation, proto_ssh, global_data); } peer_data = &global_data->peer_data[is_response]; if (tree) { ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA); ssh_tree = proto_item_add_subtree(ti, ett_ssh); } version = global_data->version; switch(version) { case SSH_VERSION_UNKNOWN: col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH"); break; case SSH_VERSION_1: col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1"); break; case SSH_VERSION_2: col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2"); break; } col_clear(pinfo->cinfo, COL_INFO); while(tvb_reported_length_remaining(tvb, offset)> 0) { gboolean after_version_start = (peer_data->frame_version_start == 0 || pinfo->fd->num >= peer_data->frame_version_start); gboolean before_version_end = (peer_data->frame_version_end == 0 || pinfo->fd->num <= peer_data->frame_version_end); need_desegmentation = FALSE; last_offset = offset; peer_data->counter++; if (after_version_start && before_version_end && (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) { if (peer_data->frame_version_start == 0) peer_data->frame_version_start = pinfo->fd->num; offset = ssh_dissect_protocol(tvb, pinfo, global_data, offset, ssh_tree, is_response, &version, &need_desegmentation); if (!need_desegmentation) { peer_data->frame_version_end = pinfo->fd->num; global_data->version = version; } } else { switch(version) { case SSH_VERSION_UNKNOWN: offset = ssh_dissect_encrypted_packet(tvb, pinfo, &global_data->peer_data[is_response], offset, ssh_tree); break; case SSH_VERSION_1: offset = ssh_dissect_ssh1(tvb, pinfo, global_data, offset, ssh_tree, is_response, &need_desegmentation); break; case SSH_VERSION_2: offset = ssh_dissect_ssh2(tvb, pinfo, global_data, offset, ssh_tree, is_response, &need_desegmentation); break; } } if (need_desegmentation) return; if (offset <= last_offset) THROW(ReportedBoundsError); } col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client"); }