/* * Returns the state associated with a MPA connection or NULL otherwise. */ static mpa_state_t * get_mpa_state(conversation_t *conversation) { if (conversation) { return (mpa_state_t*) conversation_get_proto_data(conversation, proto_iwarp_mpa); } else { return NULL; } }
/* 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); }
static int is_pmproxy_exchange_complete(packet_info *pinfo) { conversation_t *conversation; pmproxy_conversation_info_t *pmproxy_conversation; conversation = find_or_create_conversation(pinfo); pmproxy_conversation = (pmproxy_conversation_info_t *)conversation_get_proto_data(conversation, proto_pmproxy); if(pmproxy_conversation == NULL) { return FALSE; } return pinfo->num >= pmproxy_conversation->last_proxy_frame; }
static void mark_pmproxy_exchange_complete(packet_info *pinfo) { conversation_t *conversation; pmproxy_conversation_info_t *pmproxy_conversation; conversation = find_or_create_conversation(pinfo); pmproxy_conversation = (pmproxy_conversation_info_t *)conversation_get_proto_data(conversation, proto_pmproxy); if(pmproxy_conversation == NULL) { pmproxy_conversation = wmem_new(wmem_file_scope(), pmproxy_conversation_info_t); } pmproxy_conversation->last_proxy_frame = pinfo->num; conversation_add_proto_data(conversation, proto_pmproxy, pmproxy_conversation); }
static usbip_conv_info_t * usbip_get_usbip_conv(packet_info *pinfo) { conversation_t *conversation; usbip_conv_info_t *usbip_info; conversation = find_or_create_conversation(pinfo); usbip_info = (usbip_conv_info_t *) conversation_get_proto_data(conversation, proto_usbip); if (!usbip_info) { usbip_info = wmem_new(wmem_file_scope(), usbip_conv_info_t); usbip_info->pdus = wmem_tree_new(wmem_file_scope()); conversation_add_proto_data(conversation, proto_usbip, usbip_info); } return usbip_info; }
static usb_i1d3_conversation_t *usb_i1d3_get_conversation(packet_info *pinfo) { conversation_t *conversation = find_or_create_conversation(pinfo); usb_i1d3_conversation_t* i1d3_conversation = (usb_i1d3_conversation_t *)conversation_get_proto_data( conversation, proto_usb_i1d3); if (!i1d3_conversation) { i1d3_conversation = wmem_new0( wmem_file_scope(), usb_i1d3_conversation_t); i1d3_conversation->request_to_transaction = wmem_map_new( wmem_file_scope(), g_direct_hash, g_direct_equal); i1d3_conversation->response_to_transaction = wmem_map_new( wmem_file_scope(), g_direct_hash, g_direct_equal); conversation_add_proto_data( conversation, proto_usb_i1d3, i1d3_conversation); } return i1d3_conversation; }
lbttcp_transport_t * lbttcp_transport_find(const address * source_address, guint16 source_port, guint32 session_id, guint32 frame) { lbttcp_transport_t * entry = NULL; conversation_t * conv = NULL; lbttcp_transport_conv_data_t * conv_data = NULL; conv = find_conversation(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0); if (conv != NULL) { conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp); if (conv_data != NULL) { entry = (lbttcp_transport_t *) wmem_tree_lookup32(conv_data->session_tree, session_id); } } return (entry); }
struct udp_analysis * get_udp_conversation_data(conversation_t *conv, packet_info *pinfo) { int direction; struct udp_analysis *udpd=NULL; /* Did the caller supply the conversation pointer? */ if (conv == NULL) conv = find_or_create_conversation(pinfo); /* Get the data for this conversation */ udpd=(struct udp_analysis *)conversation_get_proto_data(conv, hfi_udp->id); /* If the conversation was just created or it matched a * conversation with template options, udpd will not * have been initialized. So, initialize * a new udpd structure for the conversation. */ if (!udpd) { udpd = init_udp_conversation_data(); conversation_add_proto_data(conv, hfi_udp->id, udpd); } if (!udpd) { return NULL; } /* check direction and get ua lists */ direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst); /* if the addresses are equal, match the ports instead */ if (direction == 0) { direction= (pinfo->srcport > pinfo->destport) ? 1 : -1; } if (direction >= 0) { udpd->fwd=&(udpd->flow1); udpd->rev=&(udpd->flow2); } else { udpd->fwd=&(udpd->flow2); udpd->rev=&(udpd->flow1); } return udpd; }
static lbttcp_client_transport_t * lbttcp_client_transport_add(lbttcp_transport_t * transport, const address * receiver_address, guint16 receiver_port, guint32 frame) { lbttcp_client_transport_t * entry; conversation_t * client_conv = NULL; wmem_tree_t * session_tree = NULL; if (transport == NULL) { return (NULL); } entry = lbttcp_client_transport_find(transport, receiver_address, receiver_port, frame); if (entry != NULL) { return (entry); } entry = wmem_new(wmem_file_scope(), lbttcp_client_transport_t); copy_address_wmem(wmem_file_scope(), &(entry->receiver_address), receiver_address); entry->receiver_port = receiver_port; entry->id = transport->next_client_id++; /* See if a conversation for this address/port pair exists. */ client_conv = find_conversation(frame, &(transport->source_address), receiver_address, PT_TCP, transport->source_port, receiver_port, 0); if (client_conv == NULL) { client_conv = conversation_new(frame, &(transport->source_address), receiver_address, PT_TCP, transport->source_port, receiver_port, 0); session_tree = wmem_tree_new(wmem_file_scope()); conversation_add_proto_data(client_conv, proto_lbttcp, (void *) session_tree); } session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbttcp); if (session_tree == NULL) { session_tree = wmem_tree_new(wmem_file_scope()); conversation_add_proto_data(client_conv, proto_lbttcp, (void *) session_tree); } wmem_tree_insert32(session_tree, transport->session_id, (void *) entry); /* Add this client to the transport. */ wmem_list_append(transport->client_list, (void *) entry); return (entry); }
static lbttcp_client_transport_t * lbttcp_client_transport_find(lbttcp_transport_t * transport, const address * receiver_address, guint16 receiver_port, guint32 frame) { lbttcp_client_transport_t * entry = NULL; conversation_t * client_conv = NULL; if (transport == NULL) { return (NULL); } client_conv = find_conversation(frame, &(transport->source_address), receiver_address, PT_TCP, transport->source_port, receiver_port, 0); if (client_conv != NULL) { wmem_tree_t * session_tree = NULL; session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbttcp); if (session_tree != NULL) { entry = (lbttcp_client_transport_t *) wmem_tree_lookup32(session_tree, transport->session_id); } } return (entry); }
/* Find the current conversation or make a new one if required */ static ts2_conversation* ts2_get_conversation(packet_info *pinfo) { conversation_t *conversation; ts2_conversation *conversation_data; conversation = find_or_create_conversation(pinfo); conversation_data = (ts2_conversation*)conversation_get_proto_data(conversation, proto_ts2); if (conversation_data == NULL) { conversation_data = wmem_new(wmem_file_scope(), ts2_conversation); conversation_data->last_inorder_server_frame=0; /* sequence number should never be zero so we can use this as an initial number */ conversation_data->last_inorder_client_frame=0; conversation_data->server_port=pinfo->srcport; conversation_data->server_frag_size=0; conversation_data->server_frag_num=0; conversation_data->client_frag_size=0; conversation_data->client_frag_num=0; conversation_add_proto_data(conversation, proto_ts2, (void *)conversation_data); } return conversation_data; }
void xmpp_message(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet) { proto_item *message_item; proto_tree *message_tree; static const gchar *type_enums[] = {"chat", "error", "groupchat", "headline", "normal"}; xmpp_array_t *type_array = xmpp_ep_init_array_t(type_enums, array_length(type_enums)); xmpp_attr_info attrs_info[] = { {"from", &hf_xmpp_from, FALSE, FALSE, NULL, NULL}, {"id", &hf_xmpp_id, FALSE, TRUE, NULL, NULL}, {"to", &hf_xmpp_to, FALSE, FALSE, NULL, NULL}, {"type", &hf_xmpp_type, FALSE, TRUE, xmpp_val_enum_list, type_array}, {"xml:lang", NULL, FALSE, FALSE, NULL,NULL}, {"chatstate", &hf_xmpp_message_chatstate, FALSE, TRUE, NULL, NULL} }; xmpp_elem_info elems_info [] = { {NAME_AND_ATTR, xmpp_name_attr_struct("data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data, ONE}, {NAME, "thread", xmpp_message_thread, ONE}, {NAME, "body", xmpp_message_body, MANY}, {NAME, "subject", xmpp_message_subject, MANY}, {NAME, "delay", xmpp_delay, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("x","xmlns","jabber:x:event"), xmpp_x_event, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("x","xmlns","http://jabber.org/protocol/muc#user"), xmpp_muc_user_x, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("x","xmlns","google:nosave"), xmpp_gtalk_nosave_x, ONE}, {NAME, "error", xmpp_error, ONE} }; xmpp_element_t *chatstate; xmpp_attr_t *id; conversation_t *conversation; xmpp_conv_info_t *xmpp_info; col_set_str(pinfo->cinfo, COL_INFO, "MESSAGE "); id = xmpp_get_attr(packet, "id"); conversation = find_or_create_conversation(pinfo); xmpp_info = (xmpp_conv_info_t *)conversation_get_proto_data(conversation, proto_xmpp); message_item = proto_tree_add_item(tree, hf_xmpp_message, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN); message_tree = proto_item_add_subtree(message_item, ett_xmpp_message); if((chatstate = xmpp_steal_element_by_attr(packet, "xmlns", "http://jabber.org/protocol/chatstates"))!=NULL) { xmpp_attr_t *fake_chatstate_attr = xmpp_ep_init_attr_t(chatstate->name, chatstate->offset, chatstate->length); g_hash_table_insert(packet->attrs, (gpointer)"chatstate", fake_chatstate_attr); } xmpp_display_attrs(message_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); xmpp_display_elems(message_tree, packet, pinfo, tvb, elems_info, array_length(elems_info)); /*Displays data about IBB session*/ if(xmpp_info && id) { gchar *ibb_sid; ibb_sid = (gchar *)wmem_tree_lookup_string(xmpp_info->ibb_sessions, id->value, WMEM_TREE_STRING_NOCASE); if (ibb_sid) { proto_item *it = proto_tree_add_string(tree, hf_xmpp_ibb, tvb, 0, 0, ibb_sid); PROTO_ITEM_SET_GENERATED(it); } } }
static int dissect_ajp13_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { guint16 mag; /* guint16 len; */ conversation_t *conv = NULL; ajp13_conv_data *cd = NULL; proto_tree *ajp13_tree = NULL; ajp13_frame_data* fd = NULL; /* conversational state really only does us good during the first * in-order traversal */ conv = find_or_create_conversation(pinfo); cd = (ajp13_conv_data*)conversation_get_proto_data(conv, proto_ajp13); if (!cd) { cd = wmem_new(wmem_file_scope(), ajp13_conv_data); cd->content_length = 0; cd->was_get_body_chunk = FALSE; conversation_add_proto_data(conv, proto_ajp13, cd); } /* we use the per segment user data to record the conversational * state for use later on when we're called out of order (see * comments at top of this file) */ fd = (ajp13_frame_data*)p_get_proto_data(wmem_file_scope(), pinfo, proto_ajp13, 0); if (!fd) { /*printf("ajp13:dissect_ajp13_common():no frame data, adding");*/ /* since there's no per-packet user data, this must be the first
static void dissect_exec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *exec_tree=NULL; /* Variables for extracting and displaying data from the packet */ guchar *field_stringz; /* Temporary storage for each field we extract */ gint length; guint offset = 0; conversation_t *conversation; exec_hash_entry_t *hash_info; conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if(!conversation){ /* Conversation does not exist yet - create it */ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } /* Retrieve information from conversation * or add it if it isn't there yet */ hash_info = conversation_get_proto_data(conversation, proto_exec); if(!hash_info){ hash_info = se_alloc(sizeof(exec_hash_entry_t)); hash_info->first_packet_number = pinfo->fd->num; hash_info->second_packet_number = 0; hash_info->third_packet_number = 0; hash_info->fourth_packet_number = 0; hash_info->state = WAIT_FOR_STDERR_PORT; /* The first field we'll see */ /* Start with empty username and command strings */ hash_info->username=NULL; hash_info->command=NULL; /* These will be set on the first pass by the first * four packets of the conversation */ hash_info->first_packet_state = NONE; hash_info->second_packet_state = NONE; hash_info->third_packet_state = NONE; hash_info->fourth_packet_state = NONE; conversation_add_proto_data(conversation, proto_exec, hash_info); } /* Store the number of the first three packets of this conversation * as we reach them the first time */ if(!hash_info->second_packet_number && pinfo->fd->num > hash_info->first_packet_number){ /* We're on the second packet of the conversation */ hash_info->second_packet_number = pinfo->fd->num; } else if(hash_info->second_packet_number && !hash_info->third_packet_number && pinfo->fd->num > hash_info->second_packet_number) { /* We're on the third packet of the conversation */ hash_info->third_packet_number = pinfo->fd->num; } else if(hash_info->third_packet_number && !hash_info->fourth_packet_number && pinfo->fd->num > hash_info->third_packet_number) { /* We're on the fourth packet of the conversation */ hash_info->fourth_packet_number = pinfo->fd->num; } /* Save this packet's state so we can retrieve it if this packet * is selected again later. If the packet's state was already stored, * then retrieve it */ if(pinfo->fd->num == hash_info->first_packet_number){ if(hash_info->first_packet_state == NONE){ hash_info->first_packet_state = hash_info->state; } else { hash_info->state = hash_info->first_packet_state; } } if(pinfo->fd->num == hash_info->second_packet_number){ if(hash_info->second_packet_state == NONE){ hash_info->second_packet_state = hash_info->state; } else { hash_info->state = hash_info->second_packet_state; } } if(pinfo->fd->num == hash_info->third_packet_number){ if(hash_info->third_packet_state == NONE){ hash_info->third_packet_state = hash_info->state; } else { hash_info->state = hash_info->third_packet_state; } } if(pinfo->fd->num == hash_info->fourth_packet_number){ if(hash_info->fourth_packet_state == NONE){ hash_info->fourth_packet_state = hash_info->state; } else { hash_info->state = hash_info->fourth_packet_state; } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "EXEC"); if(check_col(pinfo->cinfo, COL_INFO)){ /* First, clear the info column */ col_clear(pinfo->cinfo, COL_INFO); /*username */ if(hash_info->username && preference_info_show_username == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Username:%s ", hash_info->username); } /* Command */ if(hash_info->command && preference_info_show_command == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Command:%s ", hash_info->command); } } /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_exec, tvb, 0, -1, FALSE); exec_tree = proto_item_add_subtree(ti, ett_exec); /* If this packet doesn't end with a null terminated string, * then it must be session data only and we can skip looking * for the other fields. */ if(tvb_find_guint8(tvb, tvb_length(tvb)-1, 1, '\0') == -1){ hash_info->state = WAIT_FOR_DATA; } if(hash_info->state == WAIT_FOR_STDERR_PORT && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the stderr_port field. * It is optional, so it may only be 1 character long * (the NULL) */ if(length == 1 || (exec_isdigit_string(field_stringz) && length <= EXEC_STDERR_PORT_LEN)){ proto_tree_add_string(exec_tree, hf_exec_stderr_port, tvb, offset, length, (gchar*)field_stringz); /* Next field we need */ hash_info->state = WAIT_FOR_USERNAME; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; } if(hash_info->state == WAIT_FOR_USERNAME && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the username field */ if(length != 1 && length <= EXEC_USERNAME_LEN && exec_isprint_string(field_stringz)){ proto_tree_add_string(exec_tree, hf_exec_username, tvb, offset, length, (gchar*)field_stringz); /* Store the username so we can display it in the * info column of the entire conversation */ if(!hash_info->username){ hash_info->username=se_strdup((gchar*)field_stringz); } /* Next field we need */ hash_info->state = WAIT_FOR_PASSWORD; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; } if(hash_info->state == WAIT_FOR_PASSWORD && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the password field */ if(length != 1 && length <= EXEC_PASSWORD_LEN && exec_isprint_string(field_stringz)){ proto_tree_add_string(exec_tree, hf_exec_password, tvb, offset, length, (gchar*)field_stringz); /* Next field we need */ hash_info->state = WAIT_FOR_COMMAND; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; /* Next field we are looking for */ hash_info->state = WAIT_FOR_COMMAND; } if(hash_info->state == WAIT_FOR_COMMAND && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the command field */ if(length != 1 && length <= EXEC_COMMAND_LEN && exec_isprint_string(field_stringz)){ proto_tree_add_string(exec_tree, hf_exec_command, tvb, offset, length, (gchar*)field_stringz); /* Store the username so we can display it in the * info column of the entire conversation */ if(!hash_info->command){ hash_info->command=se_strdup((gchar*)field_stringz); } } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } } if(hash_info->state == WAIT_FOR_DATA && tvb_length_remaining(tvb, offset)){ if(pinfo->destport == EXEC_PORT){ /* Packet going to the server */ /* offset = 0 since the whole packet is data */ proto_tree_add_text(exec_tree, tvb, 0, -1, "Client -> Server Data"); if(check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, "Client -> Server data"); } else { /* This packet must be going back to the client */ /* offset = 0 since the whole packet is data */ proto_tree_add_text(exec_tree, tvb, 0, -1, "Server -> Client Data"); if(check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, "Server -> Client Data"); } } /* We haven't seen all of the fields yet */ if(hash_info->state < WAIT_FOR_DATA){ col_set_str(pinfo->cinfo, COL_INFO, "Session Establishment"); } }
/**************************************************************** * Main dissection function ****************************************************************/ static int dissect_rlogin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { struct tcpinfo *tcpinfo = (struct tcpinfo *)data; conversation_t *conversation; rlogin_hash_entry_t *hash_info; guint length; gint ti_offset; /* Get or create conversation */ conversation = find_or_create_conversation(pinfo); /* Get or create data associated with this conversation */ hash_info = (rlogin_hash_entry_t *)conversation_get_proto_data(conversation, proto_rlogin); if (!hash_info) { /* Populate new data struct... */ hash_info = wmem_new(wmem_file_scope(), rlogin_hash_entry_t); hash_info->state = NONE; hash_info->info_framenum = 0; /* no frame has the number 0 */ hash_info->user_name[0] = '\0'; /* ... and store in conversation */ conversation_add_proto_data(conversation, proto_rlogin, hash_info); } /* Set protocol column text */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Rlogin"); /* Set info column */ /* Show user-name if available */ if (hash_info->user_name[0]) { col_add_fstr(pinfo->cinfo, COL_INFO, "User name: %s, ", hash_info->user_name); } else { col_clear(pinfo->cinfo, COL_INFO); } /* Work out packet content summary for display */ length = tvb_reported_length(tvb); if (length != 0) { /* Initial NULL byte represents part of connection handshake */ if (tvb_get_guint8(tvb, 0) == '\0') { col_append_str(pinfo->cinfo, COL_INFO, (pinfo->destport == RLOGIN_PORT) ? "Start Handshake" : "Startup info received"); } else if (tcpinfo && IS_TH_URG(tcpinfo->flags) && length >= tcpinfo->urgent_pointer) { /* Urgent pointer inside current data represents a control message */ col_append_str(pinfo->cinfo, COL_INFO, "Control Message"); } else { /* Search for 2 consecutive ff bytes (signifies window change control message) */ ti_offset = tvb_find_guint8(tvb, 0, -1, 0xff); if (ti_offset != -1 && tvb_bytes_exist(tvb, ti_offset + 1, 1) && tvb_get_guint8(tvb, ti_offset + 1) == 0xff) { col_append_str(pinfo->cinfo, COL_INFO, "Terminal Info"); } else { /* Show any text data in the frame */ int bytes_to_copy = tvb_captured_length(tvb); if (bytes_to_copy > 128) { /* Truncate to 128 bytes for display */ bytes_to_copy = 128; } /* Add data into info column */ col_append_fstr(pinfo->cinfo, COL_INFO, "Data: %s", tvb_format_text(tvb, 0, bytes_to_copy)); } } } /* See if conversation state needs to be updated */ rlogin_state_machine(hash_info, tvb, pinfo); /* Dissect in detail */ rlogin_display(hash_info, tvb, pinfo, tree, tcpinfo); return tvb_captured_length(tvb); }
/* 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; }
/* This function will try to determine the complete size of a PDU * based on the information in the header. */ static guint get_nbd_tcp_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset) { guint32 magic, type, packet; conversation_t *conversation; nbd_conv_info_t *nbd_info; nbd_transaction_t *nbd_trans=NULL; wmem_tree_key_t hkey[3]; guint32 handle[2]; magic=tvb_get_ntohl(tvb, offset); switch(magic){ case NBD_REQUEST_MAGIC: type=tvb_get_ntohl(tvb, offset+4); switch(type){ case NBD_CMD_WRITE: return tvb_get_ntohl(tvb, offset+24)+28; default: return 28; } case NBD_RESPONSE_MAGIC: /* * Do we have a conversation for this connection? */ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (conversation == NULL) { /* No, so just return the rest of the current packet */ return tvb_length(tvb); } /* * Do we have a state structure for this conv */ nbd_info = (nbd_conv_info_t *)conversation_get_proto_data(conversation, proto_nbd); if (!nbd_info) { /* No, so just return the rest of the current packet */ return tvb_length(tvb); } if(!pinfo->fd->flags.visited){ /* * Do we have a state structure for this transaction */ handle[0]=tvb_get_ntohl(tvb, offset+8); handle[1]=tvb_get_ntohl(tvb, offset+12); hkey[0].length=2; hkey[0].key=handle; hkey[1].length=0; nbd_trans=(nbd_transaction_t *)wmem_tree_lookup32_array(nbd_info->unacked_pdus, hkey); if(!nbd_trans){ /* No, so just return the rest of the current packet */ return tvb_length(tvb); } } else { /* * Do we have a state structure for this transaction */ handle[0]=tvb_get_ntohl(tvb, offset+8); handle[1]=tvb_get_ntohl(tvb, offset+12); packet=pinfo->fd->num; hkey[0].length=1; hkey[0].key=&packet; hkey[1].length=2; hkey[1].key=handle; hkey[2].length=0; nbd_trans=(nbd_transaction_t *)wmem_tree_lookup32_array(nbd_info->acked_pdus, hkey); if(!nbd_trans){ /* No, so just return the rest of the current packet */ return tvb_length(tvb); } } /* If this is a read response we must add the datalen to * the pdu size */ if(nbd_trans->type==NBD_CMD_READ){ return 16+nbd_trans->datalen; } else { return 16; } default: break; } /* Did not really look like a NBD packet after all */ return 0; }
static void dissect_pop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { struct pop_proto_data *frame_data_p; gboolean is_request; gboolean is_continuation; proto_tree *pop_tree, *reqresp_tree; proto_item *ti; gint offset = 0; const guchar *line; gint next_offset; int linelen; int tokenlen; const guchar *next_token; fragment_data *frag_msg = NULL; tvbuff_t *next_tvb = NULL; conversation_t *conversation = NULL; struct pop_data_val *data_val = NULL; gint length_remaining; col_set_str(pinfo->cinfo, COL_PROTOCOL, "POP"); /* * Find the end of the first line. * * Note that "tvb_find_line_end()" will return a value that is * not longer than what's in the buffer, so the "tvb_get_ptr()" * call won't throw an exception. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); if (pinfo->match_port == pinfo->destport) { is_request = TRUE; is_continuation = FALSE; } else { is_request = FALSE; is_continuation = response_is_continuation(line); } frame_data_p = p_get_proto_data(pinfo->fd, proto_pop); if (!frame_data_p) { conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (conversation == NULL) { /* No conversation, create one */ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } data_val = conversation_get_proto_data(conversation, proto_pop); if (!data_val) { /* * No - create one and attach it. */ data_val = se_alloc0(sizeof(struct pop_data_val)); conversation_add_proto_data(conversation, proto_pop, data_val); } } if (check_col(pinfo->cinfo, COL_INFO)) { /* * Put the first line from the buffer into the summary * if it's a POP request or reply (but leave out the * line terminator). * Otherwise, just call it a continuation. */ if (is_continuation) { length_remaining = tvb_length_remaining(tvb, offset); col_add_fstr(pinfo->cinfo, COL_INFO, "S: DATA fragment, %d byte%s", length_remaining, plurality (length_remaining, "", "s")); } else col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "C" : "S", format_text(line, linelen)); } ti = proto_tree_add_item(tree, proto_pop, tvb, offset, -1, FALSE); pop_tree = proto_item_add_subtree(ti, ett_pop); if (is_continuation) { if (pop_data_desegment) { if (!frame_data_p) { data_val->msg_read_len += tvb_length(tvb); frame_data_p = se_alloc(sizeof(struct pop_proto_data)); frame_data_p->conversation_id = conversation->index; frame_data_p->more_frags = data_val->msg_read_len < data_val->msg_tot_len; p_add_proto_data(pinfo->fd, proto_pop, frame_data_p); } frag_msg = fragment_add_seq_next(tvb, 0, pinfo, frame_data_p->conversation_id, pop_data_segment_table, pop_data_reassembled_table, tvb_length(tvb), frame_data_p->more_frags); next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled DATA", frag_msg, &pop_data_frag_items, NULL, pop_tree); if (next_tvb) { if (imf_handle) call_dissector(imf_handle, next_tvb, pinfo, tree); if (data_val) { /* we have read everything - reset */ data_val->msg_read_len = 0; data_val->msg_tot_len = 0; } pinfo->fragmented = FALSE; } else { pinfo->fragmented = TRUE; } } else { /* * Put the whole packet into the tree as data. */ call_dissector(data_handle,tvb, pinfo, pop_tree); } return; } /* * Put the line into the protocol tree. */ ti = proto_tree_add_string_format(pop_tree, (is_request) ? hf_pop_request : hf_pop_response, tvb, offset, next_offset - offset, "", "%s", tvb_format_text(tvb, offset, next_offset - offset)); reqresp_tree = proto_item_add_subtree(ti, ett_pop_reqresp); /* * Extract the first token, and, if there is a first * token, add it as the request or reply code. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { proto_tree_add_item(reqresp_tree, (is_request) ? hf_pop_request_command : hf_pop_response_indicator, tvb, offset, tokenlen, FALSE); if (data_val) { if (is_request) { /* see if this is RETR or TOP command */ if (g_ascii_strncasecmp(line, "RETR", 4) == 0 || g_ascii_strncasecmp(line, "TOP", 3) == 0) /* the next response will tell us how many bytes */ data_val->msg_request = TRUE; } else { if (data_val->msg_request) { /* this is a response to a RETR or TOP command */ if (g_ascii_strncasecmp(line, "+OK ", 4) == 0) { /* the message will be sent - work out how many bytes */ data_val->msg_read_len = 0; data_val->msg_tot_len = atoi(line + 4); } data_val->msg_request = FALSE; } } } offset += (gint) (next_token - line); linelen -= (int) (next_token - line); } if (tree) { /* * Add the rest of the first line as request or * reply param/description. */ if (linelen != 0) { proto_tree_add_item(reqresp_tree, (is_request) ? hf_pop_request_parameter : hf_pop_response_description, tvb, offset, linelen, FALSE); } offset = next_offset; /* * Show the rest of the request or response as text, * a line at a time. */ 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_string_format(pop_tree, (is_request) ? hf_pop_request_data : hf_pop_response_data, tvb, offset, next_offset - offset, "", "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; } } }
static void dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request; proto_tree *imap_tree, *reqresp_tree; proto_item *ti, *hidden_item; gint offset = 0; gint uid_offset = 0; gint folder_offset = 0; const guchar *line; const guchar *uid_line; const guchar *folder_line; gint next_offset; int linelen; int tokenlen; int uid_tokenlen; int folder_tokenlen; const guchar *next_token; const guchar *uid_next_token; const guchar *folder_next_token; guchar *tokenbuf; guchar *command_token; int iter; int commandlen; conversation_t *conversation; imap_state_t *session_state; conversation = find_or_create_conversation(pinfo); session_state = (imap_state_t *)conversation_get_proto_data(conversation, proto_imap); if (!session_state) { session_state = wmem_new0(wmem_file_scope(), imap_state_t); session_state->ssl_requested = FALSE; conversation_add_proto_data(conversation, proto_imap, session_state); } tokenbuf = (guchar *)wmem_alloc0(wmem_packet_scope(), MAX_BUFFER); command_token = (guchar *)wmem_alloc0(wmem_packet_scope(), MAX_BUFFER); commandlen = 0; folder_offset = 0; folder_tokenlen = 0; folder_line = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IMAP"); if (pinfo->match_uint == pinfo->destport) is_request = TRUE; else is_request = FALSE; /* * Put the first line from the buffer into the summary * (but leave out the line terminator). */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); { ti = proto_tree_add_item(tree, proto_imap, tvb, offset, -1, ENC_NA); imap_tree = proto_item_add_subtree(ti, ett_imap); hidden_item = proto_tree_add_boolean(imap_tree, hf_imap_isrequest, tvb, 0, 0, is_request); PROTO_ITEM_SET_HIDDEN(hidden_item); while(tvb_offset_exists(tvb, offset)) { /* * Find the end of each line * * Note that "tvb_find_line_end()" will return a value that is * not longer than what's in the buffer, so the "tvb_get_ptr()" * call won't throw an exception. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, offset, linelen); /* * Put the line into the protocol tree. */ ti = proto_tree_add_item(imap_tree, hf_imap_line, tvb, offset, next_offset - offset, ENC_ASCII|ENC_NA); reqresp_tree = proto_item_add_subtree(ti, ett_imap_reqresp); /* * Check that the line doesn't begin with '*', because that's a continuation line. * Otherwise if a tag is present then extract tokens. */ if ( (line) && ((line[0] != '*') || (TRUE == is_request)) ) { /* * Show each line as tags + requests or replies. */ /* * Extract the first token, and, if there is a first * token, add it as the request or reply tag. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_tag : hf_imap_response_tag, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); offset += (gint) (next_token - line); linelen -= (int) (next_token - line); line = next_token; } /* * Extract second token, and, if there is a second * token, and it's not uid, add it as the request or reply command. */ tokenlen = get_token_len(line, line + linelen, &next_token); if (tokenlen != 0) { for (iter = 0; iter < tokenlen && iter < MAX_BUFFER-1; iter++) { tokenbuf[iter] = g_ascii_tolower(line[iter]); } if (tree && is_request && strncmp(tokenbuf, "uid", tokenlen) == 0) { proto_tree_add_item(reqresp_tree, hf_imap_request_uid, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); /* * UID is a precursor to a command, if following the tag, * so move to next token to grab the actual command. */ uid_offset = offset; uid_offset += (gint) (next_token - line); uid_line = next_token; uid_tokenlen = get_token_len(uid_line, uid_line + (linelen - tokenlen), &uid_next_token); if (tokenlen != 0) { proto_tree_add_item(reqresp_tree, hf_imap_request_command, tvb, uid_offset, uid_tokenlen, ENC_ASCII|ENC_NA); /* * Save command string to do specialized processing. */ for (iter = 0; iter < uid_tokenlen && iter < MAX_BUFFER-1; iter++) { command_token[iter] = g_ascii_tolower(uid_line[iter]); } commandlen = uid_tokenlen; folder_offset = uid_offset; folder_offset += (gint) (uid_next_token - uid_line); folder_line = uid_next_token; folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - uid_tokenlen), &folder_next_token); } } else { /* * Not a UID request so perform normal parsing. */ proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_command : hf_imap_response_status, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); if (is_request) { /* * Save command string to do specialized processing. */ for (iter = 0; iter < tokenlen && iter < 256; iter++) { command_token[iter] = g_ascii_tolower(line[iter]); } commandlen = tokenlen; folder_offset = offset; folder_offset += (gint) (next_token - line); folder_line = next_token; folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - 1), &folder_next_token); } } if (tree && commandlen > 0 && ( strncmp(command_token, "select", commandlen) == 0 || strncmp(command_token, "examine", commandlen) == 0 || strncmp(command_token, "create", commandlen) == 0 || strncmp(command_token, "delete", commandlen) == 0 || strncmp(command_token, "rename", commandlen) == 0 || strncmp(command_token, "subscribe", commandlen) == 0 || strncmp(command_token, "unsubscribe", commandlen) == 0 || strncmp(command_token, "status", commandlen) == 0 || strncmp(command_token, "append", commandlen) == 0 || strncmp(command_token, "search", commandlen) == 0)) { /* * These commands support folder as an argument, * so parse out the folder name. */ if (folder_tokenlen != 0) proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA); } if (tree && is_request && (NULL != folder_line) && strncmp(command_token, "copy", commandlen) == 0) { /* * Handle the copy command separately since folder * is the second argument for this command. */ folder_offset += (gint) (folder_next_token - folder_line); folder_line = folder_next_token; folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen), &folder_next_token); if (folder_tokenlen != 0) proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA); } /* If not yet switched to TLS, check for STARTTLS. */ if (session_state->ssl_requested) { if (!is_request && session_state->ssl_requested && strncmp(tokenbuf, "ok", tokenlen) == 0) { /* STARTTLS accepted, next reply will be TLS. */ ssl_starttls_ack(ssl_handle, pinfo, imap_handle); } session_state->ssl_requested = FALSE; } if (is_request && commandlen > 0 && strncmp(command_token, "starttls", commandlen) == 0) { /* If next response is OK, then TLS should be commenced. */ session_state->ssl_requested = TRUE; } } /* * Add the rest of the line as request or reply data. */ if (linelen != 0) { proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request : hf_imap_response, tvb, offset, linelen, ENC_ASCII|ENC_NA); } } offset = next_offset; /* Skip over last line and \r\n at the end of it */ } } }
void xmpp_iq(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet) { proto_item *xmpp_iq_item; proto_tree *xmpp_iq_tree; xmpp_attr_t *attr_id, *attr_type; xmpp_attr_info attrs_info[] = { {"xmlns", &hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, {"id", &hf_xmpp_id, TRUE, TRUE, NULL, NULL}, {"type", &hf_xmpp_type, TRUE, TRUE, NULL, NULL}, {"from", &hf_xmpp_from, FALSE, TRUE, NULL, NULL}, {"to", &hf_xmpp_to, FALSE, TRUE, NULL, NULL}, {"xml:lang", NULL, FALSE, FALSE, NULL, NULL} }; conversation_t *conversation; xmpp_conv_info_t *xmpp_info; xmpp_transaction_t *reqresp_trans; xmpp_elem_info elems_info [] = { {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns","http://jabber.org/protocol/disco#items"), xmpp_disco_items_query, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns", "jabber:iq:roster"), xmpp_roster_query, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns", "http://jabber.org/protocol/disco#info"), xmpp_disco_info_query, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns", "http://jabber.org/protocol/bytestreams"), xmpp_bytestreams_query, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns", "http://jabber.org/protocol/muc#owner"), xmpp_muc_owner_query, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns", "http://jabber.org/protocol/muc#admin"), xmpp_muc_admin_query, ONE}, {NAME, "bind", xmpp_iq_bind, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("session", "xmlns", "urn:ietf:params:xml:ns:xmpp-session"), xmpp_session, ONE}, {NAME, "vCard", xmpp_vcard, ONE}, {NAME, "jingle", xmpp_jingle, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("services", "xmlns", "http://jabber.org/protocol/jinglenodes"), xmpp_jinglenodes_services, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("channel", "xmlns", "http://jabber.org/protocol/jinglenodes#channel"), xmpp_jinglenodes_channel, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("open", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_open, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("close", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_close, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data, ONE}, {NAME, "si", xmpp_si, ONE}, {NAME, "error", xmpp_error, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("session", "xmlns", "http://www.google.com/session"), xmpp_gtalk_session, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns","google:jingleinfo"), xmpp_gtalk_jingleinfo_query, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("usersetting", "xmlns","google:setting"), xmpp_gtalk_usersetting, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns","jabber:iq:last"), xmpp_last_query, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns","jabber:iq:version"), xmpp_version_query, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns","google:mail:notify"), xmpp_gtalk_mail_query, ONE}, {NAME, "mailbox", xmpp_gtalk_mail_mailbox, ONE}, {NAME, "new-mail", xmpp_gtalk_mail_new_mail, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("query", "xmlns","google:shared-status"), xmpp_gtalk_status_query, ONE}, {NAME, "conference-info", xmpp_conference_info, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("ping", "xmlns","urn:xmpp:ping"), xmpp_ping, ONE}, {NAME_AND_ATTR, xmpp_name_attr_struct("inputevt", "xmlns","http://jitsi.org/protocol/inputevt"), xmpp_jitsi_inputevt, ONE}, }; attr_id = xmpp_get_attr(packet, "id"); attr_type = xmpp_get_attr(packet, "type"); conversation = find_or_create_conversation(pinfo); xmpp_info = (xmpp_conv_info_t *)conversation_get_proto_data(conversation, proto_xmpp); xmpp_iq_item = proto_tree_add_item(tree, hf_xmpp_iq, tvb, packet->offset, packet->length, ENC_LITTLE_ENDIAN); xmpp_iq_tree = proto_item_add_subtree(xmpp_iq_item,ett_xmpp_iq); xmpp_display_attrs(xmpp_iq_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); col_add_fstr(pinfo->cinfo, COL_INFO, "IQ(%s) ", attr_type?attr_type->value:""); xmpp_display_elems(xmpp_iq_tree, packet, pinfo, tvb, elems_info, array_length(elems_info)); /*displays generated info such as req/resp tracking, jingle sid * in each packet related to specified jingle session and IBB sid in packet related to it*/ if(xmpp_info && attr_id) { gchar *jingle_sid, *ibb_sid, *gtalk_sid; jingle_sid = (gchar *)wmem_tree_lookup_string(xmpp_info->jingle_sessions, attr_id->value, WMEM_TREE_STRING_NOCASE); if (jingle_sid) { proto_item *it = proto_tree_add_string(tree, hf_xmpp_jingle_session, tvb, 0, 0, jingle_sid); PROTO_ITEM_SET_GENERATED(it); } ibb_sid = (gchar *)wmem_tree_lookup_string(xmpp_info->ibb_sessions, attr_id->value, WMEM_TREE_STRING_NOCASE); if (ibb_sid) { proto_item *it = proto_tree_add_string(tree, hf_xmpp_ibb, tvb, 0, 0, ibb_sid); PROTO_ITEM_SET_GENERATED(it); } gtalk_sid = (gchar *)wmem_tree_lookup_string(xmpp_info->gtalk_sessions, attr_id->value, WMEM_TREE_STRING_NOCASE); if (gtalk_sid) { proto_item *it = proto_tree_add_string(tree, hf_xmpp_gtalk, tvb, 0, 0, gtalk_sid); PROTO_ITEM_SET_GENERATED(it); } reqresp_trans = (xmpp_transaction_t *)wmem_tree_lookup_string(xmpp_info->req_resp, attr_id->value, WMEM_TREE_STRING_NOCASE); /*displays request/response field in each iq packet*/ if (reqresp_trans) { if (reqresp_trans->req_frame == pinfo->fd->num) { if (reqresp_trans->resp_frame) { proto_item *it = proto_tree_add_uint(tree, hf_xmpp_response_in, tvb, 0, 0, reqresp_trans->resp_frame); PROTO_ITEM_SET_GENERATED(it); } else { expert_add_info(pinfo, xmpp_iq_item, &ei_xmpp_packet_without_response); } } else { if (reqresp_trans->req_frame) { proto_item *it = proto_tree_add_uint(tree, hf_xmpp_response_to, tvb, 0, 0, reqresp_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); } else { expert_add_info(pinfo, xmpp_iq_item, &ei_xmpp_packet_without_response); } } } } }
/* main dissector function. wireshark calls it for segments in both * directions. */ static void dissect_ajp13_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 mag; /* guint16 len; */ conversation_t *conv = NULL; ajp13_conv_data *cd = NULL; proto_tree *ajp13_tree = NULL; ajp13_frame_data* fd = NULL; /* conversational state really only does us good during the first * in-order traversal */ conv = find_or_create_conversation(pinfo); cd = (ajp13_conv_data*)conversation_get_proto_data(conv, proto_ajp13); if (!cd) { cd = se_new(ajp13_conv_data); cd->content_length = 0; cd->was_get_body_chunk = FALSE; conversation_add_proto_data(conv, proto_ajp13, cd); } /* we use the per segment user data to record the conversational * state for use later on when we're called out of order (see * comments at top of this file) */ fd = (ajp13_frame_data*)p_get_proto_data(pinfo->fd, proto_ajp13); if (!fd) { /*printf("ajp13:dissect_ajp13_common():no frame data, adding");*/ /* since there's no per-packet user data, this must be the first * time we've see the packet, and it must be the first "in order" * pass through the data. */ fd = se_new(ajp13_frame_data); p_add_proto_data(pinfo->fd, proto_ajp13, fd); fd->is_request_body = FALSE; if (cd->content_length) { /* this is screwy, see AJPv13.html. the idea is that if the * request has a body (as determined by the content-length * header), then there's always an immediate follow-up PDU with * no GET_BODY_CHUNK from the container. */ fd->is_request_body = TRUE; } } col_clear(pinfo->cinfo, COL_INFO); mag = tvb_get_ntohs(tvb, 0); /* len = tvb_get_ntohs(tvb, 2); */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AJP13"); if (mag == 0x1234 && !fd->is_request_body) col_append_fstr(pinfo->cinfo, COL_INFO, "%d:REQ:", conv->index); else if (mag == 0x1234 && fd->is_request_body) col_append_fstr(pinfo->cinfo, COL_INFO, "%d:REQ:Body", conv->index); else if (mag == 0x4142) col_append_fstr(pinfo->cinfo, COL_INFO, "%d:RSP:", conv->index); else col_set_str(pinfo->cinfo, COL_INFO, "AJP13 Error?"); if (tree) { proto_item *ti; ti = proto_tree_add_item(tree, proto_ajp13, tvb, 0, -1, ENC_NA); ajp13_tree = proto_item_add_subtree(ti, ett_ajp13); } if (mag == 0x1234) { if (fd->is_request_body) display_req_body(tvb, ajp13_tree, cd); else display_req_forward(tvb, pinfo, ajp13_tree, cd); } else if (mag == 0x4142) { display_rsp(tvb, pinfo, ajp13_tree, cd); } }
/* * Dissect ROS PDUs inside a PPDU. */ static int dissect_ros(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data) { int offset = 0; int old_offset; proto_item *item; proto_tree *tree; proto_tree *next_tree=NULL; conversation_t *conversation; ros_conv_info_t *ros_info = NULL; asn1_ctx_t asn1_ctx; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); /* save parent_tree so subdissectors can create new top nodes */ top_tree=parent_tree; /* do we have application context from the acse dissector? */ if( !data){ if(parent_tree){ proto_tree_add_text(parent_tree, tvb, offset, -1, "Internal error:can't get application context from ACSE dissector."); } return 0; } asn1_ctx.private_data = data; conversation = find_or_create_conversation(pinfo); /* * Do we already have our info */ ros_info = (ros_conv_info_t *)conversation_get_proto_data(conversation, proto_ros); if (ros_info == NULL) { /* No. Attach that information to the conversation. */ ros_info = (ros_conv_info_t *)g_malloc(sizeof(ros_conv_info_t)); ros_info->matched=g_hash_table_new(ros_info_hash_matched, ros_info_equal_matched); ros_info->unmatched=g_hash_table_new(ros_info_hash_unmatched, ros_info_equal_unmatched); conversation_add_proto_data(conversation, proto_ros, ros_info); ros_info->next = ros_info_items; ros_info_items = ros_info; } item = proto_tree_add_item(parent_tree, proto_ros, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_ros); col_set_str(pinfo->cinfo, COL_PROTOCOL, "ROS"); col_clear(pinfo->cinfo, COL_INFO); while (tvb_reported_length_remaining(tvb, offset) > 0){ old_offset=offset; offset=dissect_ros_ROS(FALSE, tvb, offset, &asn1_ctx , tree, -1); if(offset == old_offset){ item = proto_tree_add_text(tree, tvb, offset, -1,"Unknown ROS PDU"); if(item){ expert_add_info(pinfo, item, &ei_ros_unknown_ros_pdu); next_tree=proto_item_add_subtree(item, ett_ros_unknown); dissect_unknown_ber(pinfo, tvb, offset, next_tree); } break; } } return tvb_length(tvb); }
static void socks_udp_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Conversation dissector called from UDP dissector. Decode and display */ /* the socks header, the pass the rest of the data to the udp port */ /* decode routine to handle the payload. */ int offset = 0; guint32 *ptr; socks_hash_entry_t *hash_info; conversation_t *conversation; proto_tree *socks_tree; proto_item *ti; conversation = find_conversation( pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); DISSECTOR_ASSERT( conversation); /* should always find a conversation */ hash_info = (socks_hash_entry_t *)conversation_get_proto_data(conversation, proto_socks); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Socks"); col_set_str(pinfo->cinfo, COL_INFO, "Version: 5, UDP Associated packet"); if ( tree) { ti = proto_tree_add_protocol_format( tree, proto_socks, tvb, offset, -1, "Socks" ); socks_tree = proto_item_add_subtree(ti, ett_socks); proto_tree_add_item(socks_tree, hf_socks_reserved2, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(socks_tree, hf_socks_fragment_number, tvb, offset, 1, ENC_NA); offset += 1; offset = display_address( tvb, offset, socks_tree); hash_info->udp_remote_port = tvb_get_ntohs(tvb, offset); proto_tree_add_uint( socks_tree, hf_socks_dstport, tvb, offset, 2, hash_info->udp_remote_port); offset += 2; } else { /* no tree, skip past the socks header */ offset += 3; offset = get_address_v5( tvb, offset, 0) + 2; } /* set pi src/dst port and call the udp sub-dissector lookup */ if ( pinfo->srcport == hash_info->port) ptr = &pinfo->destport; else ptr = &pinfo->srcport; *ptr = hash_info->udp_remote_port; decode_udp_ports( tvb, offset, pinfo, tree, pinfo->srcport, pinfo->destport, -1); *ptr = hash_info->udp_port; }
static void dissect_smtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { struct smtp_proto_data *spd_frame_data; proto_tree *smtp_tree = NULL; proto_tree *cmdresp_tree; proto_item *ti, *hidden_item; int offset = 0; int request = 0; conversation_t *conversation; struct smtp_session_state *session_state; const guchar *line, *linep, *lineend; guint32 code; int linelen = 0; gint length_remaining; gboolean eom_seen = FALSE; gint next_offset; gint loffset = 0; int cmdlen; fragment_data *frag_msg = NULL; tvbuff_t *next_tvb; /* As there is no guarantee that we will only see frames in the * the SMTP conversation once, and that we will see them in * order - in Wireshark, the user could randomly click on frames * in the conversation in any order in which they choose - we * have to store information with each frame indicating whether * it contains commands or data or an EOM indication. * * XXX - what about frames that contain *both*? TCP is a * byte-stream protocol, and there are no guarantees that * TCP segment boundaries will correspond to SMTP commands * or EOM indications. * * We only need that for the client->server stream; responses * are easy to manage. * * If we have per frame data, use that, else, we must be on the first * pass, so we figure it out on the first pass. */ /* * Find or create the conversation for this. */ conversation = find_or_create_conversation(pinfo); /* * Is there a request structure attached to this conversation? */ session_state = conversation_get_proto_data(conversation, proto_smtp); if (!session_state) { /* * No - create one and attach it. */ session_state = se_alloc(sizeof(struct smtp_session_state)); session_state->smtp_state = SMTP_STATE_READING_CMDS; session_state->crlf_seen = FALSE; session_state->data_seen = FALSE; session_state->msg_read_len = 0; session_state->msg_tot_len = 0; session_state->msg_last = TRUE; session_state->last_nontls_frame = 0; conversation_add_proto_data(conversation, proto_smtp, session_state); } /* Are we doing TLS? * FIXME In my understanding of RFC 2487 client and server can send SMTP cmds * after a rejected TLS negotiation */ if (session_state->last_nontls_frame != 0 && pinfo->fd->num > session_state->last_nontls_frame) { guint16 save_can_desegment; guint32 save_last_nontls_frame; /* This is TLS, not raw SMTP. TLS can desegment */ save_can_desegment = pinfo->can_desegment; pinfo->can_desegment = pinfo->saved_can_desegment; /* Make sure the SSL dissector will not be called again after decryption */ save_last_nontls_frame = session_state->last_nontls_frame; session_state->last_nontls_frame = 0; call_dissector(ssl_handle, tvb, pinfo, tree); pinfo->can_desegment = save_can_desegment; session_state->last_nontls_frame = save_last_nontls_frame; return; } /* Is this a request or a response? */ request = pinfo->destport == pinfo->match_uint; /* * Is there any data attached to this frame? */ spd_frame_data = p_get_proto_data(pinfo->fd, proto_smtp); if (!spd_frame_data) { /* * No frame data. */ if(request) { /* * Create a frame data structure and attach it to the packet. */ spd_frame_data = se_alloc0(sizeof(struct smtp_proto_data)); spd_frame_data->conversation_id = conversation->index; spd_frame_data->more_frags = TRUE; p_add_proto_data(pinfo->fd, proto_smtp, spd_frame_data); } /* * Get the first line from the buffer. * * Note that "tvb_find_line_end()" will, if it doesn't return * -1, return a value that is not longer than what's in the buffer, * and "tvb_find_line_end()" will always return a value that is not * longer than what's in the buffer, so the "tvb_get_ptr()" call * won't throw an exception. */ loffset = offset; while (tvb_offset_exists(tvb, loffset)) { linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, smtp_desegment && pinfo->can_desegment); if (linelen == -1) { if (offset == loffset) { /* * We didn't find a line ending, and we're doing desegmentation; * tell the TCP dissector where the data for this message starts * in the data it handed us, and tell it we need more bytes */ pinfo->desegment_offset = loffset; pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return; } else { linelen = tvb_length_remaining(tvb, loffset); next_offset = loffset + linelen; } } line = tvb_get_ptr(tvb, loffset, linelen); /* * Check whether or not this packet is an end of message packet * We should look for CRLF.CRLF and they may be split. * We have to keep in mind that we may see what we want on * two passes through here ... */ if (session_state->smtp_state == SMTP_STATE_READING_DATA) { /* * The order of these is important ... We want to avoid * cases where there is a CRLF at the end of a packet and a * .CRLF at the begining of the same packet. */ if ((session_state->crlf_seen && tvb_strneql(tvb, loffset, ".\r\n", 3) == 0) || tvb_strneql(tvb, loffset, "\r\n.\r\n", 5) == 0) eom_seen = TRUE; length_remaining = tvb_length_remaining(tvb, loffset); if (length_remaining == tvb_reported_length_remaining(tvb, loffset) && tvb_strneql(tvb, loffset + length_remaining - 2, "\r\n", 2) == 0) session_state->crlf_seen = TRUE; else session_state->crlf_seen = FALSE; } /* * OK, Check if we have seen a DATA request. We do it here for * simplicity, but we have to be careful below. */ if (request) { if (session_state->smtp_state == SMTP_STATE_READING_DATA) { /* * This is message data. */ if (eom_seen) { /* Seen the EOM */ /* * EOM. * Everything that comes after it is commands. */ spd_frame_data->pdu_type = SMTP_PDU_EOM; session_state->smtp_state = SMTP_STATE_READING_CMDS; break; } else { /* * Message data with no EOM. */ spd_frame_data->pdu_type = SMTP_PDU_MESSAGE; if (session_state->msg_tot_len > 0) { /* * We are handling a BDAT message. * Check if we have reached end of the data chunk. */ session_state->msg_read_len += tvb_length_remaining(tvb, loffset); if (session_state->msg_read_len == session_state->msg_tot_len) { /* * We have reached end of BDAT data chunk. * Everything that comes after this is commands. */ session_state->smtp_state = SMTP_STATE_READING_CMDS; if (session_state->msg_last) { /* * We have found the LAST data chunk. * The message can now be reassembled. */ spd_frame_data->more_frags = FALSE; } break; /* no need to go through the remaining lines */ } } } } else { /* * This is commands - unless the capture started in the * middle of a session, and we're in the middle of data. * * Commands are not necessarily 4 characters; look * for a space or the end of the line to see where * the putative command ends. */ linep = line; lineend = line + linelen; while (linep < lineend && *linep != ' ') linep++; cmdlen = (int)(linep - line); if (line_is_smtp_command(line, cmdlen)) { if (g_ascii_strncasecmp(line, "DATA", 4) == 0) { /* * DATA command. * This is a command, but everything that comes after it, * until an EOM, is data. */ spd_frame_data->pdu_type = SMTP_PDU_CMD; session_state->smtp_state = SMTP_STATE_READING_DATA; session_state->data_seen = TRUE; } else if (g_ascii_strncasecmp(line, "BDAT", 4) == 0) { /* * BDAT command. * This is a command, but everything that comes after it, * until given length is received, is data. */ guint32 msg_len; msg_len = strtoul (line+5, NULL, 10); spd_frame_data->pdu_type = SMTP_PDU_CMD; session_state->data_seen = TRUE; session_state->msg_tot_len += msg_len; if (msg_len == 0) { /* No data to read, next will be a command */ session_state->smtp_state = SMTP_STATE_READING_CMDS; } else { session_state->smtp_state = SMTP_STATE_READING_DATA; } if (g_ascii_strncasecmp(line+linelen-4, "LAST", 4) == 0) { /* * This is the last data chunk. */ session_state->msg_last = TRUE; if (msg_len == 0) { /* * No more data to expect. * The message can now be reassembled. */ spd_frame_data->more_frags = FALSE; } } else { session_state->msg_last = FALSE; } } else if (g_ascii_strncasecmp(line, "STARTTLS", 8) == 0) { /* * STARTTLS command. * This is a command, but if the response is 220, * everything after the response is TLS. */ session_state->smtp_state = SMTP_STATE_AWAITING_STARTTLS_RESPONSE; spd_frame_data->pdu_type = SMTP_PDU_CMD; } else { /* * Regular command. */ spd_frame_data->pdu_type = SMTP_PDU_CMD; } } else { /* * Assume it's message data. */ spd_frame_data->pdu_type = session_state->data_seen ? SMTP_PDU_MESSAGE : SMTP_PDU_CMD; } } } /* * Step past this line. */ loffset = next_offset; } } /* * From here, we simply add items to the tree and info to the info * fields ... */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMTP"); if (check_col(pinfo->cinfo, COL_INFO)) { /* Add the appropriate type here */ col_clear(pinfo->cinfo, COL_INFO); /* * If it is a request, we have to look things up, otherwise, just * display the right things */ if (request) { /* We must have frame_data here ... */ switch (spd_frame_data->pdu_type) { case SMTP_PDU_MESSAGE: length_remaining = tvb_length_remaining(tvb, offset); col_set_str(pinfo->cinfo, COL_INFO, smtp_data_desegment ? "C: DATA fragment" : "C: Message Body"); col_append_fstr(pinfo->cinfo, COL_INFO, ", %d byte%s", length_remaining, plurality (length_remaining, "", "s")); break; case SMTP_PDU_EOM: col_set_str(pinfo->cinfo, COL_INFO, "C: ."); break; case SMTP_PDU_CMD: loffset = offset; while (tvb_offset_exists(tvb, loffset)) { /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, loffset, linelen); if(loffset == offset) col_append_fstr(pinfo->cinfo, COL_INFO, "C: %s", format_text(line, linelen)); else { col_append_fstr(pinfo->cinfo, COL_INFO, " | %s", format_text(line, linelen)); } loffset = next_offset; } break; } } else { loffset = offset; while (tvb_offset_exists(tvb, loffset)) { /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE); line = tvb_get_ptr(tvb, loffset, linelen); if (loffset == offset) col_append_fstr(pinfo->cinfo, COL_INFO, "S: %s", format_text(line, linelen)); else { col_append_fstr(pinfo->cinfo, COL_INFO, " | %s", format_text(line, linelen)); } loffset = next_offset; } } } if (tree) { /* Build the tree info ... */ ti = proto_tree_add_item(tree, proto_smtp, tvb, offset, -1, ENC_NA); smtp_tree = proto_item_add_subtree(ti, ett_smtp); } if (request) { /* * Check out whether or not we can see a command in there ... * What we are looking for is not data_seen and the word DATA * and not eom_seen. * * We will see DATA and session_state->data_seen when we process the * tree view after we have seen a DATA packet when processing * the packet list pane. * * On the first pass, we will not have any info on the packets * On second and subsequent passes, we will. */ switch (spd_frame_data->pdu_type) { case SMTP_PDU_MESSAGE: if (smtp_data_desegment) { frag_msg = fragment_add_seq_next(tvb, 0, pinfo, spd_frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table, tvb_length(tvb), spd_frame_data->more_frags); } else { /* * Message body. * Put its lines into the protocol tree, a line at a time. */ dissect_smtp_data(tvb, offset, smtp_tree); } break; case SMTP_PDU_EOM: /* * End-of-message-body indicator. * * XXX - what about stuff after the first line? * Unlikely, as the client should wait for a response to the * DATA command this terminates before sending another * request, but we should probably handle it. */ proto_tree_add_text(smtp_tree, tvb, offset, linelen, "C: ."); if (smtp_data_desegment) { /* add final data segment */ if (loffset) fragment_add_seq_next(tvb, 0, pinfo, spd_frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table, loffset, spd_frame_data->more_frags); /* terminate the desegmentation */ frag_msg = fragment_end_seq_next (pinfo, spd_frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table); } break; case SMTP_PDU_CMD: /* * Command. * * XXX - what about stuff after the first line? * Unlikely, as the client should wait for a response to the * previous command before sending another request, but we * should probably handle it. */ loffset = offset; while (tvb_offset_exists(tvb, loffset)) { /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE); if (linelen >= 4) cmdlen = 4; else cmdlen = linelen; hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_req, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); /* * Put the command line into the protocol tree. */ ti = proto_tree_add_item(smtp_tree, hf_smtp_command_line, tvb, loffset, next_offset - loffset, ENC_ASCII|ENC_NA); cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp); proto_tree_add_item(cmdresp_tree, hf_smtp_req_command, tvb, loffset, cmdlen, ENC_ASCII|ENC_NA); if (linelen > 5) { proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb, loffset + 5, linelen - 5, ENC_ASCII|ENC_NA); } if (smtp_data_desegment && !spd_frame_data->more_frags) { /* terminate the desegmentation */ frag_msg = fragment_end_seq_next (pinfo, spd_frame_data->conversation_id, smtp_data_segment_table, smtp_data_reassembled_table); } /* * Step past this line. */ loffset = next_offset; } } if (smtp_data_desegment) { next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled SMTP", frag_msg, &smtp_data_frag_items, NULL, smtp_tree); if (next_tvb) { /* XXX: this is presumptious - we may have negotiated something else */ if (imf_handle) { call_dissector(imf_handle, next_tvb, pinfo, tree); } else { /* * Message body. * Put its lines into the protocol tree, a line at a time. */ dissect_smtp_data(tvb, offset, smtp_tree); } pinfo->fragmented = FALSE; } else { pinfo->fragmented = TRUE; } } } else { /* * Process the response, a line at a time, until we hit a line * that doesn't have a continuation indication on it. */ if (tree) { hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_rsp, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } while (tvb_offset_exists(tvb, offset)) { /* * Find the end of the line. */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); if (tree) { /* * Put it into the protocol tree. */ ti = proto_tree_add_item(smtp_tree, hf_smtp_response, tvb, offset, next_offset - offset, ENC_ASCII|ENC_NA); cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp); } else cmdresp_tree = NULL; line = tvb_get_ptr(tvb, offset, linelen); if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1]) && isdigit(line[2])) { /* * We have a 3-digit response code. */ code = (line[0] - '0')*100 + (line[1] - '0')*10 + (line[2] - '0'); /* * If we're awaiting the response to a STARTTLS code, this * is it - if it's 220, all subsequent traffic will * be TLS, otherwise we're back to boring old SMTP. */ if (session_state->smtp_state == SMTP_STATE_AWAITING_STARTTLS_RESPONSE) { if (code == 220) { /* This is the last non-TLS frame. */ session_state->last_nontls_frame = pinfo->fd->num; } session_state->smtp_state = SMTP_STATE_READING_CMDS; } if (tree) { /* * Put the response code and parameters into the protocol tree. */ proto_tree_add_uint(cmdresp_tree, hf_smtp_rsp_code, tvb, offset, 3, code); if (linelen >= 4) { proto_tree_add_item(cmdresp_tree, hf_smtp_rsp_parameter, tvb, offset + 4, linelen - 4, ENC_ASCII|ENC_NA); } } } /* * Step past this line. */ offset = next_offset; } } }
/* Conversation dissector called from TCP or UDP dissector. Decode and */ /* display the msproxy header, the pass the rest of the data to the tcp */ /* or udp port decode routine to handle the payload. */ guint32 *ptr; redirect_entry_t *redirect_info; conversation_t *conversation; proto_tree *msp_tree; proto_item *ti; conversation = find_conversation( pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); DISSECTOR_ASSERT( conversation); /* should always find a conversation */ redirect_info = (redirect_entry_t *)conversation_get_proto_data(conversation, proto_msproxy); col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS Proxy"); col_set_str(pinfo->cinfo, COL_INFO, (( redirect_info->proto == PT_TCP) ? "TCP stream" : "UDP packets")); if ( tree) { ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0, 0, ENC_NA ); msp_tree = proto_item_add_subtree(ti, ett_msproxy); proto_tree_add_uint( msp_tree, hf_msproxy_dstport, tvb, 0, 0, redirect_info->remote_port);
/* Transfers happen in response to broadcasts, they are always TCP and are * used to send the file to the port mentioned in the broadcast. There are * 2 types of transfers: Pushes, which are direct responses to searches, * in which the peer that has the file connects to the peer that doesn't and * sends it, then disconnects. The other type of transfer is a pull, where * the peer that doesn't have the file connects to the peer that does and * requests it be sent. * * Pulls have a file request which identifies the desired file, * while pushes simply send the file. In practice this works because every * file the implementation sends searches for is on a different TCP port * on the searcher's machine. */ static int dissect_ldss_transfer (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { conversation_t *transfer_conv; ldss_transfer_info_t *transfer_info; struct tcpinfo *transfer_tcpinfo; proto_tree *ti, *line_tree = NULL, *ldss_tree = NULL; nstime_t broadcast_response_time; /* Reject the packet if data is NULL */ if (data == NULL) return 0; transfer_tcpinfo = (struct tcpinfo *)data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDSS"); /* Look for the transfer conversation; this was created during * earlier broadcast dissection (see prepare_ldss_transfer_conv) */ transfer_conv = find_conversation (pinfo->num, &pinfo->src, &pinfo->dst, PT_TCP, pinfo->srcport, pinfo->destport, 0); transfer_info = (ldss_transfer_info_t *)conversation_get_proto_data(transfer_conv, proto_ldss); /* For a pull, the first packet in the TCP connection is the file request. * First packet is identified by relative seq/ack numbers of 1. * File request only appears on a pull (triggered by an offer - see above * about broadcasts) */ if (transfer_tcpinfo->seq == 1 && transfer_tcpinfo->lastackseq == 1 && transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND) { /* LDSS pull transfers look a lot like HTTP. * Sample request: * md5:01234567890123... * Size: 2550 * Start: 0 * Compression: 0 * (remote end sends the file identified by the digest) */ guint offset = 0; gboolean already_dissected = TRUE; col_set_str(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Requesting file - pull)"); if (highest_num_seen == 0 || highest_num_seen < pinfo->num) { already_dissected = FALSE; transfer_info->req = wmem_new0(wmem_file_scope(), ldss_file_request_t); transfer_info->req->file = wmem_new0(wmem_file_scope(), ldss_file_t); highest_num_seen = pinfo->num; } if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, tvb_reported_length(tvb), ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer); } /* Populate digest data into the file struct in the request */ transfer_info->file = transfer_info->req->file; /* Grab each line from the packet, there should be 4 but lets * not walk off the end looking for more. */ while (tvb_offset_exists(tvb, offset)) { gint next_offset; const guint8 *line; int linelen; gboolean is_digest_line; guint digest_type_len; linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); /* Include new-line in line */ line = (guint8 *)tvb_memdup(NULL, tvb, offset, linelen+1); /* XXX - memory leak? */ line_tree = proto_tree_add_subtree(ldss_tree, tvb, offset, linelen, ett_ldss_transfer_req, NULL, tvb_format_text(tvb, offset, next_offset-offset)); /* Reduce code duplication processing digest lines. * There are too many locals to pass to a function - the signature * looked pretty ugly when I tried! */ is_digest_line = FALSE; if (strncmp(line,"md5:",4)==0) { is_digest_line = TRUE; digest_type_len = 4; transfer_info->file->digest_type = DIGEST_TYPE_MD5; } else if (strncmp(line, "sha1:", 5)==0) { is_digest_line = TRUE; digest_type_len = 5; transfer_info->file->digest_type = DIGEST_TYPE_SHA1; } else if (strncmp(line, "sha256:", 7)==0) { is_digest_line = TRUE; digest_type_len = 7; transfer_info->file->digest_type = DIGEST_TYPE_SHA256; } else if (strncmp(line, "unknown:", 8)==0) { is_digest_line = TRUE; digest_type_len = 8; transfer_info->file->digest_type = DIGEST_TYPE_UNKNOWN; } else if (strncmp(line, "Size: ", 6)==0) { /* Sample size line: * Size: 2550\n */ transfer_info->req->size = g_ascii_strtoull(line+6, NULL, 10); if (tree) { ti = proto_tree_add_uint64(line_tree, hf_ldss_size, tvb, offset+6, linelen-6, transfer_info->req->size); PROTO_ITEM_SET_GENERATED(ti); } } else if (strncmp(line, "Start: ", 7)==0) { /* Sample offset line: * Start: 0\n */ transfer_info->req->offset = g_ascii_strtoull(line+7, NULL, 10); if (tree) { ti = proto_tree_add_uint64(line_tree, hf_ldss_offset, tvb, offset+7, linelen-7, transfer_info->req->offset); PROTO_ITEM_SET_GENERATED(ti); } } else if (strncmp(line, "Compression: ", 13)==0) { /* Sample compression line: * Compression: 0\n */ transfer_info->req->compression = (gint8)strtol(line+13, NULL, 10); /* XXX - bad cast */ if (tree) { ti = proto_tree_add_uint(line_tree, hf_ldss_compression, tvb, offset+13, linelen-13, transfer_info->req->compression); PROTO_ITEM_SET_GENERATED(ti); } } else { proto_tree_add_expert(line_tree, pinfo, &ei_ldss_unrecognized_line, tvb, offset, linelen); } if (is_digest_line) { /* Sample digest-type/digest line: * md5:0123456789ABCDEF\n */ if (!already_dissected) { GByteArray *digest_bytes; digest_bytes = g_byte_array_new(); hex_str_to_bytes( tvb_get_ptr(tvb, offset+digest_type_len, linelen-digest_type_len), digest_bytes, FALSE); if(digest_bytes->len >= DIGEST_LEN) digest_bytes->len = (DIGEST_LEN-1); /* Ensure the digest is zero-padded */ transfer_info->file->digest = (guint8 *)wmem_alloc0(wmem_file_scope(), DIGEST_LEN); memcpy(transfer_info->file->digest, digest_bytes->data, digest_bytes->len); g_byte_array_free(digest_bytes, TRUE); } if (tree) { proto_item *tii = NULL; tii = proto_tree_add_uint(line_tree, hf_ldss_digest_type, tvb, offset, digest_type_len, transfer_info->file->digest_type); PROTO_ITEM_SET_GENERATED(tii); tii = proto_tree_add_bytes(line_tree, hf_ldss_digest, tvb, offset+digest_type_len, MIN(linelen-digest_type_len, DIGEST_LEN), transfer_info->file->digest); PROTO_ITEM_SET_GENERATED(tii); } } offset = next_offset; } /* Link forwards to the response for this pull. */ if (tree && transfer_info->resp_num != 0) { ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_in, tvb, 0, 0, transfer_info->resp_num); PROTO_ITEM_SET_GENERATED(ti); } transfer_info->req->num = pinfo->num; transfer_info->req->ts = pinfo->abs_ts; } /* Remaining packets are the file response */ else { guint64 size; guint64 offset; guint8 compression; /* size, digest, compression come from the file request for a pull but * they come from the broadcast for a push. Pushes don't bother * with a file request - they just send the data. We have to get file * info from the offer broadcast which triggered this transfer. * If we cannot find the file request, default to the broadcast. */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL) { transfer_info->file = transfer_info->req->file; size = transfer_info->req->size; offset = transfer_info->req->offset; compression = transfer_info->req->compression; } else { transfer_info->file = transfer_info->broadcast->file; size = transfer_info->broadcast->size; offset = transfer_info->broadcast->offset; compression = transfer_info->broadcast->compression; } /* Remaining data in this TCP connection is all file data. * Always desegment if the size is 0 (ie. unknown) */ if (pinfo->can_desegment) { if (size == 0 || tvb_captured_length(tvb) < size) { pinfo->desegment_offset = 0; pinfo->desegment_len = DESEGMENT_UNTIL_FIN; return 0; } } /* OK. Now we have the whole file that was transferred. */ transfer_info->resp_num = pinfo->num; transfer_info->resp_ts = pinfo->abs_ts; col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Sending file - %s)", transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND ? "pull" : "push"); if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, tvb_reported_length(tvb), ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer); proto_tree_add_bytes_format(ldss_tree, hf_ldss_file_data, tvb, 0, tvb_captured_length(tvb), NULL, compression == COMPRESSION_GZIP ? "Gzip compressed data: %d bytes" : "File data: %d bytes", tvb_captured_length(tvb)); #ifdef HAVE_ZLIB /* Be nice and uncompress the file data. */ if (compression == COMPRESSION_GZIP) { tvbuff_t *uncomp_tvb; uncomp_tvb = tvb_child_uncompress(tvb, tvb, 0, tvb_captured_length(tvb)); if (uncomp_tvb != NULL) { /* XXX: Maybe not a good idea to add a data_source for what may very well be a large buffer since then the full uncompressed buffer will be shown in a tab in the hex bytes pane ? However, if we don't, bytes in an unrelated tab will be highlighted. */ add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Data"); proto_tree_add_bytes_format_value(ldss_tree, hf_ldss_file_data, uncomp_tvb, 0, tvb_captured_length(uncomp_tvb), NULL, "Uncompressed data: %d bytes", tvb_captured_length(uncomp_tvb)); } } #endif ti = proto_tree_add_uint(ldss_tree, hf_ldss_digest_type, tvb, 0, 0, transfer_info->file->digest_type); PROTO_ITEM_SET_GENERATED(ti); if (transfer_info->file->digest != NULL) { /* This is ugly. You can't add bytes of nonzero length and have * filtering work correctly unless you give a valid location in * the packet. This hack pretends the first 32 bytes of the packet * are the digest, which they aren't: they're actually the first 32 * bytes of the file that was sent. */ ti = proto_tree_add_bytes(ldss_tree, hf_ldss_digest, tvb, 0, DIGEST_LEN, transfer_info->file->digest); } PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint64(ldss_tree, hf_ldss_size, tvb, 0, 0, size); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint64(ldss_tree, hf_ldss_offset, tvb, 0, 0, offset); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint(ldss_tree, hf_ldss_compression, tvb, 0, 0, compression); PROTO_ITEM_SET_GENERATED(ti); /* Link to the request for a pull. */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL && transfer_info->req->num != 0) { ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_to, tvb, 0, 0, transfer_info->req->num); PROTO_ITEM_SET_GENERATED(ti); } } } /* Print the pull response time */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL && transfer_info->resp_num != 0) { nstime_t pull_response_time; nstime_delta(&pull_response_time, &transfer_info->resp_ts, &transfer_info->req->ts); ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_response_time, tvb, 0, 0, &pull_response_time); PROTO_ITEM_SET_GENERATED(ti); } /* Link the transfer back to the initiating broadcast. Response time is * calculated as the time from broadcast to completed transfer. */ ti = proto_tree_add_uint(ldss_tree, hf_ldss_initiated_by, tvb, 0, 0, transfer_info->broadcast->num); PROTO_ITEM_SET_GENERATED(ti); if (transfer_info->resp_num != 0) { nstime_delta(&broadcast_response_time, &transfer_info->resp_ts, &transfer_info->broadcast->ts); ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_completed_in, tvb, 0, 0, &broadcast_response_time); PROTO_ITEM_SET_GENERATED(ti); } /* This conv got its addr2/port2 set by the TCP dissector because a TCP * connection was established. Make a new one to handle future connections * to the addr/port mentioned in the broadcast, because that socket is * still open. */ if (transfer_tcpinfo->seq == 1 && transfer_tcpinfo->lastackseq == 1) { prepare_ldss_transfer_conv(transfer_info->broadcast); } return tvb_captured_length(tvb); }
static int dissect_skype_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *skype_tree = NULL; guint32 offset = 0; guint32 packet_length; guint8 packet_type, packet_unk; conversation_t *conversation = NULL; skype_udp_conv_info_t *skype_udp_info; /* look up the conversation */ conversation = find_or_create_conversation(pinfo); /* if conversation found get the data pointer that you stored */ skype_udp_info = (skype_udp_conv_info_t *)conversation_get_proto_data(conversation, proto_skype); if (!skype_udp_info) { /* new conversation create local data structure */ skype_udp_info = wmem_new(wmem_file_scope(), skype_udp_conv_info_t); skype_udp_info->global_src_ip = 0; skype_udp_info->global_dst_ip = 0; conversation_add_proto_data(conversation, proto_skype, skype_udp_info); } /* at this point the conversation data is ready */ packet_type = tvb_get_guint8(tvb, 2) & SKYPE_SOM_TYPE_MASK; packet_unk = (tvb_get_guint8(tvb, 2) & SKYPE_SOM_UNK_MASK) >> 4; packet_length = tvb_length(tvb); col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type, skype_type_vals, "Type 0x%1x")); if (packet_unk) { col_append_fstr(pinfo->cinfo, COL_INFO, " Unk: %1x", packet_unk); } if (tree) { /* Start of message dissection */ ti = proto_tree_add_item(tree, proto_skype, tvb, offset, -1, ENC_NA); skype_tree = proto_item_add_subtree(ti, ett_skype); proto_tree_add_item(skype_tree, hf_skype_som_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(skype_tree, hf_skype_som_unk, tvb, offset, 1, ENC_NA); proto_tree_add_item(skype_tree, hf_skype_som_type, tvb, offset, 1, ENC_NA); offset += 1; /* Body dissection */ switch (packet_type) { case SKYPE_TYPE_UNKNOWN_0: proto_tree_add_item(skype_tree, hf_skype_unknown_0_unk1, tvb, offset, -1, ENC_NA); offset = packet_length; break; case SKYPE_TYPE_PAYLOAD: proto_tree_add_item(skype_tree, hf_skype_payload_iv, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_payload_crc, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_payload_enc_data, tvb, offset, -1, ENC_NA); offset = packet_length; break; case SKYPE_TYPE_FFR: proto_tree_add_item(skype_tree, hf_skype_ffr_num, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(skype_tree, hf_skype_ffr_unk1, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_ffr_iv, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_ffr_crc, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_ffr_enc_data, tvb, offset, -1, ENC_NA); offset = packet_length; break; case SKYPE_TYPE_NAT_INFO: proto_tree_add_item(skype_tree, hf_skype_natinfo_srcip, tvb, offset, 4, ENC_BIG_ENDIAN); skype_udp_info->global_src_ip = tvb_get_ipv4(tvb, offset); offset += 4; proto_tree_add_item(skype_tree, hf_skype_natinfo_dstip, tvb, offset, 4, ENC_BIG_ENDIAN); skype_udp_info->global_dst_ip = tvb_get_ipv4(tvb, offset); offset += 4; break; case SKYPE_TYPE_NAT_REPEAT: proto_tree_add_item(skype_tree, hf_skype_natrequest_srcip, tvb, offset, 4, ENC_BIG_ENDIAN); skype_udp_info->global_src_ip = tvb_get_ipv4(tvb, offset); offset += 4; proto_tree_add_item(skype_tree, hf_skype_natrequest_dstip, tvb, offset, 4, ENC_BIG_ENDIAN); skype_udp_info->global_dst_ip = tvb_get_ipv4(tvb, offset); offset += 4; break; case SKYPE_TYPE_AUDIO: proto_tree_add_item(skype_tree, hf_skype_audio_unk1, tvb, offset, -1, ENC_NA); offset = packet_length; break; case SKYPE_TYPE_UNKNOWN_F: proto_tree_add_item(skype_tree, hf_skype_unknown_f_unk1, tvb, offset, -1, ENC_NA); offset = packet_length; break; default: proto_tree_add_item(skype_tree, hf_skype_unknown_packet, tvb, offset, -1, ENC_NA); offset = packet_length; break; } } return offset; }
static void dissect_xmpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { xml_frame_t *xml_frame; gboolean out_packet; conversation_t *conversation; xmpp_conv_info_t *xmpp_info; proto_tree *xmpp_tree = NULL; proto_item *xmpp_item = NULL; xmpp_element_t *packet = NULL; /*check if desegment * now it checks that last char is '>', * TODO checks that first element in packet is closed*/ int indx; gchar last_char; if (xmpp_desegment) { indx = tvb_reported_length(tvb) - 1; if (indx >= 0) { last_char = tvb_get_guint8(tvb, indx); while ((last_char <= ' ') && (indx - 1 >= 0)) { indx--; last_char = tvb_get_guint8(tvb, indx); } if ((indx >= 0) && (last_char != '>')) { pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return; } } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "XMPP"); col_clear(pinfo->cinfo, COL_INFO); conversation = find_or_create_conversation(pinfo); xmpp_info = (xmpp_conv_info_t *)conversation_get_proto_data(conversation, proto_xmpp); if (xmpp_info && xmpp_info->ssl_proceed && xmpp_info->ssl_proceed < pinfo->fd->num) { call_dissector(ssl_handle, tvb, pinfo, tree); return; } /*if tree == NULL then xmpp_item and xmpp_tree will also NULL*/ xmpp_item = proto_tree_add_item(tree, proto_xmpp, tvb, 0, -1, ENC_NA); xmpp_tree = proto_item_add_subtree(xmpp_item, ett_xmpp); call_dissector(xml_handle, tvb, pinfo, xmpp_tree); /* If XML dissector is disabled, we can't do much */ if (!proto_is_protocol_enabled(find_protocol_by_id(dissector_handle_get_protocol_index(xml_handle)))) { col_append_str(pinfo->cinfo, COL_INFO, "(XML dissector disabled, can't dissect XMPP)"); expert_add_info_format(pinfo, xmpp_item, PI_UNDECODED, PI_WARN, "XML dissector disabled, can't dissect XMPP"); return; } /*if stream end occurs then return*/ if(xmpp_stream_close(xmpp_tree,tvb, pinfo)) { if(xmpp_tree) xmpp_proto_tree_hide_first_child(xmpp_tree); return; } if(!pinfo->private_data) return; /*data from XML dissector*/ xml_frame = ((xml_frame_t*)pinfo->private_data)->first_child; if(!xml_frame) return; if (!xmpp_info) { xmpp_info = se_new(xmpp_conv_info_t); xmpp_info->req_resp = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_req_resp"); xmpp_info->jingle_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_jingle_sessions"); xmpp_info->ibb_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_ibb_sessions"); xmpp_info->gtalk_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_gtalk_sessions"); xmpp_info->ssl_start = 0; xmpp_info->ssl_proceed = 0; conversation_add_proto_data(conversation, proto_xmpp, (void *) xmpp_info); } if (pinfo->match_uint == pinfo->destport) out_packet = TRUE; else out_packet = FALSE; while(xml_frame) { packet = xmpp_xml_frame_to_element_t(xml_frame, NULL, tvb); DISSECTOR_ASSERT(packet); if (strcmp(packet->name, "iq") == 0) { xmpp_iq_reqresp_track(pinfo, packet, xmpp_info); xmpp_jingle_session_track(pinfo, packet, xmpp_info); xmpp_gtalk_session_track(pinfo, packet, xmpp_info); } if (strcmp(packet->name, "iq") == 0 || strcmp(packet->name, "message") == 0) { xmpp_ibb_session_track(pinfo, packet, xmpp_info); } if (tree) { /* we are being asked for details */ proto_item *outin_item; if (out_packet) outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_out, tvb, 0, 0, TRUE); else outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_in, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(outin_item); /*it hides tree generated by XML dissector*/ xmpp_proto_tree_hide_first_child(xmpp_tree); if (strcmp(packet->name, "iq") == 0) { xmpp_iq(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "presence") == 0) { xmpp_presence(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "message") == 0) { xmpp_message(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "auth") == 0) { xmpp_auth(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "challenge") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_challenge, ett_xmpp_challenge, "CHALLENGE"); } else if (strcmp(packet->name, "response") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_response, ett_xmpp_response, "RESPONSE"); } else if (strcmp(packet->name, "success") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_success, ett_xmpp_success, "SUCCESS"); } else if (strcmp(packet->name, "failure") == 0) { xmpp_failure(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "xml") == 0) { xmpp_xml_header(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "stream") == 0) { xmpp_stream(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "features") == 0) { xmpp_features(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "starttls") == 0) { xmpp_starttls(xmpp_tree, tvb, pinfo, packet, xmpp_info); }else if (strcmp(packet->name, "proceed") == 0) { xmpp_proceed(xmpp_tree, tvb, pinfo, packet, xmpp_info); }else { xmpp_proto_tree_show_first_child(xmpp_tree); expert_add_info_format(pinfo, xmpp_tree, PI_UNDECODED, PI_NOTE, "Unknown packet: %s", packet->name); col_clear(pinfo->cinfo, COL_INFO); col_append_fstr(pinfo->cinfo, COL_INFO, "UNKNOWN PACKET "); } /*appends to COL_INFO information about src or dst*/ if (pinfo->match_uint == pinfo->destport) { xmpp_attr_t *to = xmpp_get_attr(packet, "to"); if (to) col_append_fstr(pinfo->cinfo, COL_INFO, "> %s ", to->value); } else { xmpp_attr_t *from = xmpp_get_attr(packet, "from"); if (from) col_append_fstr(pinfo->cinfo, COL_INFO, "< %s ", from->value); } } xmpp_element_t_tree_free(packet); xml_frame = xml_frame->next_sibling; } }
/* 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; }
/* * Function for the PANA PDU dissector. */ static void dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *pana_tree = NULL; guint16 flags; guint16 msg_type; guint32 msg_length; guint32 avp_length; guint32 seq_num; conversation_t *conversation; pana_conv_info_t *pana_info; pana_transaction_t *pana_trans; int offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PANA"); col_clear(pinfo->cinfo, COL_INFO); /* Get message length, type and flags */ msg_length = tvb_get_ntohs(tvb, 2); flags = tvb_get_ntohs(tvb, 4); msg_type = tvb_get_ntohs(tvb, 6); seq_num = tvb_get_ntohl(tvb, 12); avp_length = msg_length - 16; col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s-%s", val_to_str(msg_type, msg_type_names, "Unknown (%d)"), val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)")); /* Make the protocol tree */ if (tree) { proto_item *ti; ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, ENC_NA); pana_tree = proto_item_add_subtree(ti, ett_pana); } /* * We need to track some state for this protocol on a per conversation * basis so we can do neat things like request/response tracking */ conversation = find_or_create_conversation(pinfo); /* * Do we already have a state structure for this conv */ pana_info = (pana_conv_info_t *)conversation_get_proto_data(conversation, proto_pana); if (!pana_info) { /* No. Attach that information to the conversation, and add * it to the list of information structures. */ pana_info = wmem_new(wmem_file_scope(), pana_conv_info_t); pana_info->pdus=wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); conversation_add_proto_data(conversation, proto_pana, pana_info); } if(!pinfo->fd->flags.visited){ if(flags&PANA_FLAG_R){ /* This is a request */ pana_trans=wmem_new(wmem_file_scope(), pana_transaction_t); pana_trans->req_frame=pinfo->num; pana_trans->rep_frame=0; pana_trans->req_time=pinfo->abs_ts; wmem_map_insert(pana_info->pdus, GUINT_TO_POINTER(seq_num), (void *)pana_trans); } else { pana_trans=(pana_transaction_t *)wmem_map_lookup(pana_info->pdus, GUINT_TO_POINTER(seq_num)); if(pana_trans){ pana_trans->rep_frame=pinfo->num; } } } else { pana_trans=(pana_transaction_t *)wmem_map_lookup(pana_info->pdus, GUINT_TO_POINTER(seq_num)); } if(!pana_trans){ /* create a "fake" pana_trans structure */ pana_trans=wmem_new(wmem_packet_scope(), pana_transaction_t); pana_trans->req_frame=0; pana_trans->rep_frame=0; pana_trans->req_time=pinfo->abs_ts; } /* print state tracking in the tree */ if(flags&PANA_FLAG_R){ /* This is a request */ if(pana_trans->rep_frame){ proto_item *it; it=proto_tree_add_uint(pana_tree, hf_pana_response_in, tvb, 0, 0, pana_trans->rep_frame); PROTO_ITEM_SET_GENERATED(it); } } else { /* This is a reply */ if(pana_trans->req_frame){ proto_item *it; nstime_t ns; it=proto_tree_add_uint(pana_tree, hf_pana_response_to, tvb, 0, 0, pana_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); nstime_delta(&ns, &pinfo->abs_ts, &pana_trans->req_time); it=proto_tree_add_time(pana_tree, hf_pana_response_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(it); } } /* Reserved field */ proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 2, ENC_NA); offset += 2; /* Length */ proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Flags */ dissect_pana_flags(pana_tree, tvb, offset, flags); offset += 2; /* Message Type */ proto_tree_add_uint_format_value(pana_tree, hf_pana_msg_type, tvb, offset, 2, msg_type, "%s-%s (%d)", val_to_str(msg_type, msg_type_names, "Unknown (%d)"), val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"), msg_type); offset += 2; /* Session ID */ proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Sequence Number */ proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* AVPs */ if(avp_length != 0){ tvbuff_t *avp_tvb; proto_tree *avp_tree; avp_tvb = tvb_new_subset_length(tvb, offset, avp_length); avp_tree = proto_tree_add_subtree(pana_tree, tvb, offset, avp_length, ett_pana_avp, NULL, "Attribute Value Pairs"); dissect_avps(avp_tvb, pinfo, avp_tree); } }