static gboolean dissect_msrp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint offset = 0; conversation_t* conversation; if ( check_msrp_header(tvb)){ /* * TODO Set up conversation here */ if (pinfo->fd->flags.visited){ /* Look for existing conversation */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); /* Create new one if not found */ if (conversation == NULL){ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); /* Set dissector */ conversation_set_dissector(conversation, msrp_handle); } } offset = dissect_msrp(tvb, pinfo, tree); return TRUE; } return FALSE; }
/* Set up an MSRP conversation using the info given */ void msrp_add_address( packet_info *pinfo, address *addr, int port, const gchar *setup_method, guint32 setup_frame_number) { address null_addr; conversation_t* p_conv; struct _msrp_conversation_info *p_conv_data = NULL; /* * If this isn't the first time this packet has been processed, * we've already done this work, so we don't need to do it * again. */ if (pinfo->fd->flags.visited) { return; } SET_ADDRESS(&null_addr, AT_NONE, 0, NULL); /* * Check if the ip address and port combination is not * already registered as a conversation. */ p_conv = find_conversation( pinfo->fd->num, addr, &null_addr, PT_TCP, port, 0, NO_ADDR_B | NO_PORT_B); /* * If not, create a new conversation. */ if (!p_conv) { p_conv = conversation_new( pinfo->fd->num, addr, &null_addr, PT_TCP, (guint32)port, 0, NO_ADDR2 | NO_PORT2); } /* Set dissector */ conversation_set_dissector(p_conv, msrp_handle); /* * Check if the conversation has data associated with it. */ p_conv_data = conversation_get_proto_data(p_conv, proto_msrp); /* * If not, add a new data item. */ if (!p_conv_data) { /* Create conversation data */ p_conv_data = se_alloc0(sizeof(struct _msrp_conversation_info)); conversation_add_proto_data(p_conv, proto_msrp, p_conv_data); } /* * Update the conversation data. */ p_conv_data->setup_method_set = TRUE; g_strlcpy(p_conv_data->setup_method, setup_method, MAX_MSRP_SETUP_METHOD_SIZE); p_conv_data->setup_frame_number = setup_frame_number; }
static void new_udp_conversation( socks_hash_entry_t *hash_info, packet_info *pinfo){ conversation_t *conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_UDP, hash_info->udp_port, hash_info->port, 0); DISSECTOR_ASSERT( conversation); conversation_add_proto_data(conversation, proto_socks, hash_info); conversation_set_dissector(conversation, socks_udp_handle); }
/* Set up an MSRP conversation using the info given */ void msrp_add_address( packet_info *pinfo, address *addr, int port, const gchar *setup_method, guint32 setup_frame_number) { address null_addr; conversation_t* p_conv; struct _msrp_conversation_info *p_conv_data = NULL; /* * If this isn't the first time this packet has been processed, * we've already done this work, so we don't need to do it * again. */ if (pinfo->fd->flags.visited) { return; } clear_address(&null_addr); /* * Check if the ip address and port combination is not * already registered as a conversation. */ p_conv = find_conversation( pinfo->num, addr, &null_addr, ENDPOINT_TCP, port, 0, NO_ADDR_B | NO_PORT_B); /* * If not, create a new conversation. */ if (!p_conv) { p_conv = conversation_new( pinfo->num, addr, &null_addr, ENDPOINT_TCP, (guint32)port, 0, NO_ADDR2 | NO_PORT2); } /* Set dissector */ conversation_set_dissector(p_conv, msrp_handle); /* * Check if the conversation has data associated with it. */ p_conv_data = (struct _msrp_conversation_info *)conversation_get_proto_data(p_conv, proto_msrp); /* * If not, add a new data item. */ if (!p_conv_data) { /* Create conversation data */ p_conv_data = wmem_new0(wmem_file_scope(), struct _msrp_conversation_info); conversation_add_proto_data(p_conv, proto_msrp, p_conv_data); }
/* WSLUA_ATTRIBUTE Pinfo_conversation WO sets the packet conversation to the given Proto object. */ static int Pinfo_set_conversation(lua_State *L) { Pinfo pinfo = checkPinfo(L,1); Proto proto = checkProto(L,2); conversation_t *conversation; if (!proto->handle) { luaL_error(L,"Proto %s has no registered dissector", proto->name? proto->name:"<UKNOWN>"); return 0; } conversation = find_or_create_conversation(pinfo->ws_pinfo); conversation_set_dissector(conversation,proto->handle); return 0; }
/* When seeing a broadcast talking about an open TCP port on a host, create * a conversation to dissect anything sent/received at that address. Setup * protocol data so the TCP dissection knows what broadcast triggered it. */ static void prepare_ldss_transfer_conv(ldss_broadcast_t *broadcast) { conversation_t *transfer_conv; ldss_transfer_info_t *transfer_info; transfer_info = wmem_new0(wmem_file_scope(), ldss_transfer_info_t); transfer_info->broadcast = broadcast; /* Preparation for later push/pull dissection */ transfer_conv = conversation_new (broadcast->num, &broadcast->broadcaster->addr, &broadcast->broadcaster->addr, PT_TCP, broadcast->broadcaster->port, broadcast->broadcaster->port, NO_ADDR2|NO_PORT2); conversation_add_proto_data(transfer_conv, proto_ldss, transfer_info); conversation_set_dissector(transfer_conv, ldss_tcp_handle); }
static void add_msproxy_conversation( packet_info *pinfo, hash_entry_t *hash_info){ /* check to see if a conversation already exists, if it does assume */ /* it's our conversation and quit. Otherwise create a new conversation. */ /* Load the conversation dissector to our dissector and load the */ /* conversation data structure with the info needed to call the TCP or */ /* UDP port decoder. */ /* NOTE: Currently this assume that the conversation will be created */ /* during a packet from the server. If that changes, pinfo->src */ /* and pinfo->dst will not be correct and this routine will have */ /* to change. */ conversation_t *conversation; redirect_entry_t *new_conv_info; if (pinfo->fd->flags.visited) { /* * We've already processed this frame once, so we * should already have done this. */ return; } conversation = find_conversation( pinfo->fd->num, &pinfo->src, &pinfo->dst, (port_type)hash_info->proto, hash_info->server_int_port, hash_info->clnt_port, 0); if ( !conversation) { conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst, (port_type)hash_info->proto, hash_info->server_int_port, hash_info->clnt_port, 0); } conversation_set_dissector(conversation, msproxy_sub_handle); new_conv_info = se_new(redirect_entry_t); new_conv_info->remote_addr = hash_info->dst_addr; new_conv_info->clnt_port = hash_info->clnt_port; new_conv_info->remote_port = hash_info->dst_port; new_conv_info->server_int_port = hash_info->server_int_port; new_conv_info->proto = hash_info->proto; conversation_add_proto_data(conversation, proto_msproxy, new_conv_info); }
static gboolean dissect_bt_dht_heur (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* try dissecting */ /* XXX: This is a very weak heuristic; so: heuristic dissection is disabled by default */ if( tvb_get_guint8(tvb,0)=='d' ) { conversation_t *conversation; conversation = find_or_create_conversation(pinfo); conversation_set_dissector(conversation, bt_dht_handle); dissect_bt_dht(tvb, pinfo, tree); return TRUE; } return FALSE; }
static gboolean dissect_applemidi_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) { guint16 command; conversation_t *p_conv; /*struct _rtp_conversation_info *p_conv_data = NULL;*/ encoding_name_and_rate_t *encoding_name_and_rate = NULL; GHashTable *rtp_dyn_payload = NULL; gint *key; if ( tvb_length( tvb ) < 4) return FALSE; /* not enough bytes to check */ if ( !test_applemidi( tvb, &command, FALSE ) ) { return FALSE; } /* set dynamic payload-type 97 which is used by Apple for their RTP-MIDI implementation for this address/port-tuple to cause RTP-dissector to call the RTP-MIDI-dissector for payload-decoding */ encoding_name_and_rate = se_alloc( sizeof( encoding_name_and_rate_t ) ); rtp_dyn_payload = g_hash_table_new( g_int_hash, g_int_equal ); encoding_name_and_rate->encoding_name = se_strdup( "rtp-midi" ); encoding_name_and_rate->sample_rate = 10000; key = se_alloc( sizeof( gint ) ); *key = 97; g_hash_table_insert( rtp_dyn_payload, key, encoding_name_and_rate ); rtp_add_address( pinfo, &pinfo->src, pinfo->srcport, 0, APPLEMIDI_DISSECTOR_SHORTNAME, pinfo->fd->num, FALSE, rtp_dyn_payload); /* call dissect_applemidi() from now on for UDP packets on this "connection" it is important to do this step after calling rtp_add_address, otherwise all further packets will go directly to the RTP-dissector! */ p_conv = find_or_create_conversation(pinfo); conversation_set_dissector( p_conv, applemidi_handle ); /* punt to actual decoding */ dissect_applemidi_common( tvb, pinfo, tree, command ); return TRUE; }
static gboolean dissect_tuxedo_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { if (tvb_length(tvb) >= 8) { guint32 magic; magic = tvb_get_ntohl(tvb, 0); if (magic == TUXEDO_MAGIC || magic == TUXEDO_SMAGIC) { /* Register this dissector for this conversation */ conversation_t *conversation = NULL; conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (conversation == NULL) { conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } conversation_set_dissector(conversation, tuxedo_handle); dissect_tuxedo(tvb, pinfo, tree); return TRUE; } } return FALSE; }
/* initialize the tap t38_info and the conversation */ static void init_t38_info_conv(packet_info *pinfo) { /* tap info */ t38_info_current++; if (t38_info_current==MAX_T38_MESSAGES_IN_PACKET) { t38_info_current=0; } t38_info = &t38_info_arr[t38_info_current]; t38_info->seq_num = 0; t38_info->type_msg = 0; t38_info->data_value = 0; t38_info->t30ind_value =0; t38_info->setup_frame_number = 0; t38_info->Data_Field_field_type_value = 0; t38_info->desc[0] = '\0'; t38_info->desc_comment[0] = '\0'; t38_info->time_first_t4_data = 0; t38_info->frame_num_first_t4_data = 0; /* p_t38_packet_conv hold the conversation info in each of the packets. p_t38_conv hold the conversation info used to reassemble the HDLC packets, and also the Setup info (e.g SDP) If we already have p_t38_packet_conv in the packet, it means we already reassembled the HDLC packets, so we don't need to use p_t38_conv */ p_t38_packet_conv = NULL; p_t38_conv = NULL; /* Use existing packet info if available */ p_t38_packet_conv = (t38_conv *)p_get_proto_data(wmem_file_scope(), pinfo, proto_t38, 0); /* find the conversation used for Reassemble and Setup Info */ p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src, pinfo->ptype, pinfo->destport, pinfo->srcport, NO_ADDR_B | NO_PORT_B); /* create a conv if it doen't exist */ if (!p_conv) { p_conv = conversation_new(pinfo->fd->num, &pinfo->net_src, &pinfo->net_dst, pinfo->ptype, pinfo->srcport, pinfo->destport, NO_ADDR_B | NO_PORT_B); /* Set dissector */ conversation_set_dissector(p_conv, t38_udp_handle); } if (!p_t38_packet_conv) { p_t38_conv = (t38_conv *)conversation_get_proto_data(p_conv, proto_t38); /* create the conversation if it doen't exist */ if (!p_t38_conv) { p_t38_conv = wmem_new(wmem_file_scope(), t38_conv); p_t38_conv->setup_method[0] = '\0'; p_t38_conv->setup_frame_number = 0; p_t38_conv->src_t38_info.reass_ID = 0; p_t38_conv->src_t38_info.reass_start_seqnum = -1; p_t38_conv->src_t38_info.reass_data_type = 0; p_t38_conv->src_t38_info.last_seqnum = -1; p_t38_conv->src_t38_info.packet_lost = 0; p_t38_conv->src_t38_info.burst_lost = 0; p_t38_conv->src_t38_info.time_first_t4_data = 0; p_t38_conv->src_t38_info.additional_hdlc_data_field_counter = 0; p_t38_conv->src_t38_info.seqnum_prev_data_field = -1; p_t38_conv->dst_t38_info.reass_ID = 0; p_t38_conv->dst_t38_info.reass_start_seqnum = -1; p_t38_conv->dst_t38_info.reass_data_type = 0; p_t38_conv->dst_t38_info.last_seqnum = -1; p_t38_conv->dst_t38_info.packet_lost = 0; p_t38_conv->dst_t38_info.burst_lost = 0; p_t38_conv->dst_t38_info.time_first_t4_data = 0; p_t38_conv->dst_t38_info.additional_hdlc_data_field_counter = 0; p_t38_conv->dst_t38_info.seqnum_prev_data_field = -1; conversation_add_proto_data(p_conv, proto_t38, p_t38_conv); } /* copy the t38 conversation info to the packet t38 conversation */ p_t38_packet_conv = wmem_new(wmem_file_scope(), t38_conv); g_strlcpy(p_t38_packet_conv->setup_method, p_t38_conv->setup_method, MAX_T38_SETUP_METHOD_SIZE); p_t38_packet_conv->setup_frame_number = p_t38_conv->setup_frame_number; memcpy(&(p_t38_packet_conv->src_t38_info), &(p_t38_conv->src_t38_info), sizeof(t38_conv_info)); memcpy(&(p_t38_packet_conv->dst_t38_info), &(p_t38_conv->dst_t38_info), sizeof(t38_conv_info)); p_add_proto_data(wmem_file_scope(), pinfo, proto_t38, 0, p_t38_packet_conv); } if (ADDRESSES_EQUAL(&p_conv->key_ptr->addr1, &pinfo->net_src)) { p_t38_conv_info = &(p_t38_conv->src_t38_info); p_t38_packet_conv_info = &(p_t38_packet_conv->src_t38_info); } else { p_t38_conv_info = &(p_t38_conv->dst_t38_info); p_t38_packet_conv_info = &(p_t38_packet_conv->dst_t38_info); } /* update t38_info */ t38_info->setup_frame_number = p_t38_packet_conv->setup_frame_number; }
/* Set up an T38 conversation */ void t38_add_address(packet_info *pinfo, address *addr, int port, int other_port, const gchar *setup_method, guint32 setup_frame_number) { address null_addr; conversation_t* p_conversation; t38_conv* p_conversation_data = NULL; /* * If this isn't the first time this packet has been processed, * we've already done this work, so we don't need to do it * again. */ if ((pinfo->fd->flags.visited) || (t38_udp_handle == NULL)) { return; } SET_ADDRESS(&null_addr, AT_NONE, 0, NULL); /* * Check if the ip address and port combination is not * already registered as a conversation. */ p_conversation = find_conversation( setup_frame_number, addr, &null_addr, PT_UDP, port, other_port, NO_ADDR_B | (!other_port ? NO_PORT_B : 0)); /* * If not, create a new conversation. */ if ( !p_conversation || p_conversation->setup_frame != setup_frame_number) { p_conversation = conversation_new( setup_frame_number, addr, &null_addr, PT_UDP, (guint32)port, (guint32)other_port, NO_ADDR2 | (!other_port ? NO_PORT2 : 0)); } /* Set dissector */ conversation_set_dissector(p_conversation, t38_udp_handle); /* * Check if the conversation has data associated with it. */ p_conversation_data = (t38_conv*)conversation_get_proto_data(p_conversation, proto_t38); /* * If not, add a new data item. */ if ( ! p_conversation_data ) { /* Create conversation data */ p_conversation_data = wmem_new(wmem_file_scope(), t38_conv); conversation_add_proto_data(p_conversation, proto_t38, p_conversation_data); } /* * Update the conversation data. */ g_strlcpy(p_conversation_data->setup_method, setup_method, MAX_T38_SETUP_METHOD_SIZE); p_conversation_data->setup_frame_number = setup_frame_number; p_conversation_data->src_t38_info.reass_ID = 0; p_conversation_data->src_t38_info.reass_start_seqnum = -1; p_conversation_data->src_t38_info.reass_data_type = 0; p_conversation_data->src_t38_info.last_seqnum = -1; p_conversation_data->src_t38_info.packet_lost = 0; p_conversation_data->src_t38_info.burst_lost = 0; p_conversation_data->src_t38_info.time_first_t4_data = 0; p_conversation_data->dst_t38_info.reass_ID = 0; p_conversation_data->dst_t38_info.reass_start_seqnum = -1; p_conversation_data->dst_t38_info.reass_data_type = 0; p_conversation_data->dst_t38_info.last_seqnum = -1; p_conversation_data->dst_t38_info.packet_lost = 0; p_conversation_data->dst_t38_info.burst_lost = 0; p_conversation_data->dst_t38_info.time_first_t4_data = 0; }
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 = 0; const guchar *line; guint32 code; gchar code_str[4]; gboolean is_port_request = FALSE; gboolean is_pasv_response = FALSE; gboolean is_epasv_response = FALSE; gint next_offset; int linelen; int tokenlen; const guchar *next_token; guint32 pasv_ip; guint32 ftp_ip; guint16 ftp_port; 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, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, 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)); if (tree) { ti = proto_tree_add_item(tree, proto_ftp, tvb, offset, -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, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - 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) { if (tree) { proto_tree_add_item(reqresp_tree, hf_ftp_request_command, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); } if (strncmp(line, "PORT", tokenlen) == 0) is_port_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, offset, sizeof(code_str), code_str); code = strtoul(code_str, NULL, 10); if (tree) { proto_tree_add_uint(reqresp_tree, hf_ftp_response_code, tvb, offset, 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 * XXX - handle IPv6? */ 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; if (tree) { /* * 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)) { if (tree) { proto_tree_add_ipv4(reqresp_tree, hf_ftp_active_ip, tvb, 0, 0, ftp_ip); proto_tree_add_uint(reqresp_tree, hf_ftp_active_port, tvb, 0, 0, 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) { if (tree) { 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)) { if (tree) { proto_tree_add_ipv4(reqresp_tree, hf_ftp_pasv_ip, tvb, 0, 0, pasv_ip); proto_tree_add_uint(reqresp_tree, hf_ftp_pasv_port, tvb, 0, 0, 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) { if (tree) { 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_epasv_response) { if (linelen != 0) { /* * This frame contains an EPSV response; set up a * conversation for the data. */ if (parse_extended_pasv_response(line, linelen, &ftp_port)) { /* Add port number to tree */ if (tree) { proto_tree_add_uint(reqresp_tree, hf_ftp_pasv_port, tvb, 0, 0, ftp_port); } /* Find/create conversation for data */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT_B); if (conversation == NULL) { conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_TCP, ftp_port, 0, NO_PORT2); conversation_set_dissector(conversation, ftpdata_handle); } } } } if (tree) { /* * 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 int dissect_dtpt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *dtpt_tree = NULL; proto_item *dtpt_item = NULL; guint8 version; guint8 message_type; guint32 flags; guint32 payload_size; version = tvb_get_guint8(tvb, 0); if (version != 1) return 0; message_type = tvb_get_guint8(tvb, 1); switch (message_type) { case LookupBeginRequest: case LookupBeginResponse: case LookupNextRequest: case LookupNextResponse: case LookupEndRequest: if (tvb_reported_length(tvb) != 20) return 0; break; case ConnectRequest: case ConnectResponseOK: case ConnectResponseERR: if (tvb_reported_length(tvb) != 36) return 0; break; default: return 0; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTPT"); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(message_type, names_message_type, "Unknown (%d)")); if (message_type == LookupBeginRequest) { conversation_t *c; c = find_or_create_conversation(pinfo); conversation_set_dissector(c, dtpt_conversation_handle); } if (tree) { dtpt_item = proto_tree_add_item(tree, proto_dtpt, tvb, 0, -1, ENC_NA); if (dtpt_item) dtpt_tree = proto_item_add_subtree(dtpt_item, ett_dtpt); } if (dtpt_tree) { proto_tree_add_uint(dtpt_tree, hf_dtpt_version, tvb, 0, 1, version); proto_tree_add_uint(dtpt_tree, hf_dtpt_message_type, tvb, 1, 1, message_type); switch (message_type) { case LookupBeginRequest: { proto_item* flags_item = NULL; proto_tree* flags_tree = NULL; flags = tvb_get_letohl(tvb, 12); flags_item = proto_tree_add_uint(dtpt_tree, hf_dtpt_flags, tvb, 12, 4, flags); if (flags_item) { flags_tree = proto_item_add_subtree(flags_item, ett_dtpt_flags); } if (flags_tree) { proto_tree_add_boolean(flags_tree, hf_dtpt_flags_res_service, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushprevious, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushcache, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_query_string, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_aliases, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_blob, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_addr, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_comment, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_version, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_type, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_name, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nearest, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nocontainers, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_containers, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_deep, tvb, 12, 4, flags); } payload_size = tvb_get_letohl(tvb, 16); proto_tree_add_uint(dtpt_tree, hf_dtpt_payload_size, tvb, 16, 4, payload_size); } break; case LookupBeginResponse: { proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle, tvb, 4, 8, tvb_get_letoh64(tvb, 4)); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 12, 4, tvb_get_letohl(tvb, 12)); } break; case LookupNextRequest: { proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle, tvb, 4, 8, tvb_get_letoh64(tvb, 4)); proto_tree_add_uint(dtpt_tree, hf_dtpt_buffer_size, tvb, 16, 4, tvb_get_letohl(tvb, 16)); } break; case LookupNextResponse: { proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 12, 4, tvb_get_letohl(tvb, 12)); proto_tree_add_uint(dtpt_tree, hf_dtpt_data_size, tvb, 16, 4, tvb_get_letohl(tvb, 16)); } break; case LookupEndRequest: { proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle, tvb, 4, 8, tvb_get_letoh64(tvb, 4)); } break; case ConnectRequest: { dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 32, 4, tvb_get_letohl(tvb, 32)); } break; case ConnectResponseOK: { dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 32, 4, tvb_get_letohl(tvb, 32)); } break; case ConnectResponseERR: { dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 32, 4, tvb_get_letohl(tvb, 32)); } break; } } return tvb_length(tvb); }
/* Packet dissection routine called by tcp (& udp) when port 873 detected */ static void dissect_rsync_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean desegment _U_) { conversation_t *conversation; struct rsync_conversation_data *conversation_data; struct rsync_frame_data *rsync_frame_data_p; proto_item *ti; proto_tree *rsync_tree; int offset = 0; gchar version[5]; gchar auth_string[10]; guint buff_length; gchar magic_string[14]; gchar *version_out; col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSYNC"); col_clear(pinfo->cinfo, COL_INFO); conversation = find_or_create_conversation(pinfo); conversation_data = conversation_get_proto_data(conversation, proto_rsync); if (conversation_data == NULL) { conversation_data = se_alloc(sizeof(struct rsync_conversation_data)); conversation_data->state = RSYNC_INIT; conversation_add_proto_data(conversation, proto_rsync, conversation_data); } conversation_set_dissector(conversation, rsync_handle); ti = proto_tree_add_item(tree, proto_rsync, tvb, 0, -1, ENC_NA); rsync_tree = proto_item_add_subtree(ti, ett_rsync); rsync_frame_data_p = p_get_proto_data(pinfo->fd, proto_rsync); if (!rsync_frame_data_p) { /* then we haven't seen this frame before */ rsync_frame_data_p = se_alloc(sizeof(struct rsync_frame_data)); rsync_frame_data_p->state = conversation_data->state; p_add_proto_data(pinfo->fd, proto_rsync, rsync_frame_data_p); } switch (rsync_frame_data_p->state) { case RSYNC_INIT: proto_tree_add_item(rsync_tree, hf_rsync_hdr_magic, tvb, offset, 8, ENC_ASCII|ENC_NA); offset += 8; proto_tree_add_item(rsync_tree, hf_rsync_hdr_version, tvb, offset, 4, ENC_ASCII|ENC_NA); tvb_get_nstringz0(tvb, offset, sizeof(version), version); offset += 4; if (check_col(pinfo->cinfo, COL_INFO)) { /* XXX - is this really a string? */ version_out = format_text(version, 4); col_append_fstr(pinfo->cinfo, COL_INFO, "Client Initialisation (Version %s)", version_out); } conversation_data->state = RSYNC_SERV_INIT; break; case RSYNC_SERV_INIT: proto_tree_add_item(rsync_tree, hf_rsync_hdr_magic, tvb, offset, 8, ENC_ASCII|ENC_NA); offset += 8; proto_tree_add_item(rsync_tree, hf_rsync_hdr_version, tvb, offset, 4, ENC_ASCII|ENC_NA); tvb_get_nstringz0(tvb, offset, sizeof(version), version); offset += 4; if (check_col(pinfo->cinfo, COL_INFO)) { /* XXX - is this really a string? */ version_out = format_text(version, 4); col_append_fstr(pinfo->cinfo, COL_INFO, "Server Initialisation (Version %s)", version_out); } conversation_data->state = RSYNC_CLIENT_QUERY; break; case RSYNC_CLIENT_QUERY: proto_tree_add_item(rsync_tree, hf_rsync_query_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Client Query"); conversation_data->state = RSYNC_SERV_MOTD; break; case RSYNC_SERV_MOTD: proto_tree_add_item(rsync_tree, hf_rsync_motd_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Server MOTD"); conversation_data->state = RSYNC_SERV_RESPONSE; break; case RSYNC_SERV_RESPONSE: /* there are two cases - file list, or authentication */ tvb_get_nstringz0(tvb, offset, sizeof(auth_string), auth_string); if (0 == strncmp("@RSYNCD:", auth_string, 8)) { /* matches, so we assume its an authentication message */ /* needs to handle the AUTHREQD case, but doesn't - FIXME */ proto_tree_add_item(rsync_tree, hf_rsync_rsyncdok_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Authentication"); conversation_data->state = RSYNC_COMMAND; } else { /* it didn't match, so it is probably a module list */ proto_tree_add_item(rsync_tree, hf_rsync_response_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Module list"); /* we need to check the end of the buffer for magic string */ buff_length = tvb_length_remaining(tvb, offset); tvb_get_nstringz0(tvb, buff_length-14, sizeof(magic_string), magic_string); if (0 == strncmp("@RSYNCD: EXIT", magic_string, 14)) { /* that's all, folks */ conversation_data->state = RSYNC_COMMAND; } else { /* there must be more data */ conversation_data->state = RSYNC_SERV_RESPONSE; } } break; case RSYNC_COMMAND: if (pinfo->destport == glb_rsync_tcp_port) { /* then we are still sending commands */ proto_tree_add_item(rsync_tree, hf_rsync_command_string, tvb, offset, -1, ENC_ASCII|ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Command"); conversation_data->state = RSYNC_COMMAND; break; } /* else we fall through to the data phase */ case RSYNC_DATA: /* then we are still sending commands */ proto_tree_add_item(rsync_tree, hf_rsync_data, tvb, offset, -1, ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Data"); conversation_data->state = RSYNC_DATA; break; } }
static void dissect_xyplex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *xyplex_tree = NULL; proto_item *ti; conversation_t *conversation; gint offset = 0; guint8 prototype; guint8 padding; guint16 server_port; guint16 return_port; guint16 reserved; guint16 reply; col_set_str(pinfo->cinfo, COL_PROTOCOL, "XYPLEX"); if (tree) { ti = proto_tree_add_item(tree, proto_xyplex, tvb, offset, -1, FALSE); xyplex_tree = proto_item_add_subtree(ti, ett_xyplex); } if (pinfo->destport == UDP_PORT_XYPLEX) { /* This is a registration request from a Unix server * to the Xyplex server. The server_port indicates * which Xyplex serial port is desired. The * return_port tells the Xyplex server what TCP port * to open to the Unix server. */ prototype = tvb_get_guint8(tvb, offset); padding = tvb_get_guint8(tvb, offset+1); server_port = tvb_get_ntohs(tvb, offset+2); return_port = tvb_get_ntohs(tvb, offset+4); reserved = tvb_get_ntohs(tvb, offset+6); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "Registration Request: %d Return: %d", server_port, return_port); } if (tree) { proto_tree_add_uint(xyplex_tree, hf_xyplex_type, tvb, offset, 1, prototype); proto_tree_add_uint(xyplex_tree, hf_xyplex_pad, tvb, offset+1, 1, padding); proto_tree_add_uint(xyplex_tree, hf_xyplex_server_port, tvb, offset+2, 2, server_port); proto_tree_add_uint(xyplex_tree, hf_xyplex_return_port, tvb, offset+4, 2, return_port); proto_tree_add_uint(xyplex_tree, hf_xyplex_reserved, tvb, offset+6, 2, reserved); } offset += 8; /* Look for all future TCP conversations between the * requestiong server and the Xyplex host using the * return_port. */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_TCP, return_port, 0, NO_PORT_B); if (conversation == NULL) { conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_TCP, return_port, 0, NO_PORT2); conversation_set_dissector(conversation, xyplex_handle); } return; } if (pinfo->srcport == UDP_PORT_XYPLEX) { prototype = tvb_get_guint8(tvb, offset); padding = tvb_get_guint8(tvb, offset+1); reply = tvb_get_ntohs(tvb, offset+2); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "Registration Reply: %s", val_to_str(reply, xyplex_reg_vals, "Unknown (0x%02x)")); } if (tree) { proto_tree_add_uint(xyplex_tree, hf_xyplex_type, tvb, offset, 1, prototype); proto_tree_add_uint(xyplex_tree, hf_xyplex_pad, tvb, offset+1, 1, padding); proto_tree_add_uint(xyplex_tree, hf_xyplex_reply, tvb, offset+2, 2, reply); } offset += 4; return; } /* * This must be the TCP data stream. This will just be * the raw data being transfered from the remote server * and the Xyplex serial port. */ if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d Data", pinfo->srcport, pinfo->destport); } if (tree) { proto_tree_add_text(xyplex_tree, tvb, offset, -1, "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset)); } }