2 * Routines for building lists of packets that are part of a "conversation"
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "conversation.h"
31 /* define DEBUG_CONVERSATION for pretty debug printing */
32 /* #define DEBUG_CONVERSATION */
33 #include "conversation_debug.h"
35 #ifdef DEBUG_CONVERSATION
36 int _debug_conversation_indent = 0;
39 struct conversation_key {
40 struct conversation_key *next;
49 * Hash table for conversations with no wildcards.
51 static wmem_map_t *conversation_hashtable_exact = NULL;
54 * Hash table for conversations with one wildcard address.
56 static wmem_map_t *conversation_hashtable_no_addr2 = NULL;
59 * Hash table for conversations with one wildcard port.
61 static wmem_map_t *conversation_hashtable_no_port2 = NULL;
64 * Hash table for conversations with one wildcard address and port.
66 static wmem_map_t *conversation_hashtable_no_addr2_or_port2 = NULL;
69 static guint32 new_index;
72 * Creates a new conversation with known endpoints based on a conversation
73 * created with the CONVERSATION_TEMPLATE option while keeping the
74 * conversation created with the CONVERSATION_TEMPLATE option so it can still
75 * match future connections.
77 * Passing a pointer to a conversation whose options mask does not include
78 * CONVERSATION_TEMPLATE or where the conversation's protocol type (ptype)
79 * indicates a non-connnection oriented protocol will return the conversation
82 * addr2 and port2 are used in the function if their respective conversation
83 * options bits are set (NO_ADDR2 and NO_PORT2).
85 static conversation_t *
86 conversation_create_from_template(conversation_t *conversation, const address *addr2, const guint32 port2)
89 * Add a new conversation and keep the conversation template only if the
90 * CONVERSATION_TEMPLATE bit is set for a connection oriented protocol.
92 if(conversation->options & CONVERSATION_TEMPLATE &&
93 conversation->key_ptr->etype != ENDPOINT_UDP)
96 * Set up a new options mask where the conversation template bit and the
97 * bits for absence of a second address and port pair have been removed.
99 conversation_t *new_conversation_from_template;
100 guint options = conversation->options & ~(CONVERSATION_TEMPLATE | NO_ADDR2 | NO_PORT2);
103 * Are both the NO_ADDR2 and NO_PORT2 wildcards set in the options mask?
105 if(conversation->options & NO_ADDR2 &&
106 conversation->options & NO_PORT2)
109 * The conversation template was created without knowledge of both
110 * the second address as well as the second port. Create a new
111 * conversation with new 2nd address and 2nd port.
113 new_conversation_from_template =
114 conversation_new(conversation->setup_frame,
115 &conversation->key_ptr->addr1, addr2,
116 conversation->key_ptr->etype, conversation->key_ptr->port1,
119 else if(conversation->options & NO_PORT2)
122 * The conversation template was created without knowledge of port 2
123 * only. Create a new conversation with new 2nd port.
125 new_conversation_from_template =
126 conversation_new(conversation->setup_frame,
127 &conversation->key_ptr->addr1, &conversation->key_ptr->addr2,
128 conversation->key_ptr->etype, conversation->key_ptr->port1,
131 else if(conversation->options & NO_ADDR2)
134 * The conversation template was created without knowledge of address
135 * 2. Create a new conversation with new 2nd address.
137 new_conversation_from_template =
138 conversation_new(conversation->setup_frame,
139 &conversation->key_ptr->addr1, addr2,
140 conversation->key_ptr->etype, conversation->key_ptr->port1,
141 conversation->key_ptr->port2, options);
146 * The CONVERSATION_TEMPLATE bit was set, but no other bit that the
147 * CONVERSATION_TEMPLATE bit controls is active. Just return the old
154 * Set the protocol dissector used for the template conversation as
155 * the handler of the new conversation as well.
157 new_conversation_from_template->dissector_tree = conversation->dissector_tree;
159 return new_conversation_from_template;
168 * Compute the hash value for two given address/port pairs if the match
171 /* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
175 conversation_hash_exact(gconstpointer v)
177 const conversation_key_t key = (const conversation_key_t)v;
184 hash_val = add_address_to_hash(hash_val, &key->addr1);
186 tmp_addr.data = &key->port1;
187 hash_val = add_address_to_hash(hash_val, &tmp_addr);
189 hash_val = add_address_to_hash(hash_val, &key->addr2);
191 tmp_addr.data = &key->port2;
192 hash_val = add_address_to_hash(hash_val, &tmp_addr);
194 hash_val += ( hash_val << 3 );
195 hash_val ^= ( hash_val >> 11 );
196 hash_val += ( hash_val << 15 );
202 * Compare two conversation keys for an exact match.
205 conversation_match_exact(gconstpointer v, gconstpointer w)
207 const conversation_key_t v1 = (const conversation_key_t)v;
208 const conversation_key_t v2 = (const conversation_key_t)w;
210 if (v1->etype != v2->etype)
211 return 0; /* different types of port */
214 * Are the first and second port 1 values the same, the first and
215 * second port 2 values the same, the first and second address
216 * 1 values the same, and the first and second address 2 values
219 if (v1->port1 == v2->port1 &&
220 v1->port2 == v2->port2 &&
221 addresses_equal(&v1->addr1, &v2->addr1) &&
222 addresses_equal(&v1->addr2, &v2->addr2)) {
224 * Yes. It's the same conversation, and the two
225 * address/port pairs are going in the same direction.
231 * Is the first port 2 the same as the second port 1, the first
232 * port 1 the same as the second port 2, the first address 2
233 * the same as the second address 1, and the first address 1
234 * the same as the second address 2?
236 if (v1->port2 == v2->port1 &&
237 v1->port1 == v2->port2 &&
238 addresses_equal(&v1->addr2, &v2->addr1) &&
239 addresses_equal(&v1->addr1, &v2->addr2)) {
241 * Yes. It's the same conversation, and the two
242 * address/port pairs are going in opposite directions.
248 * The addresses or the ports don't match.
254 * Compute the hash value for two given address/port pairs if the match
255 * has a wildcard address 2.
258 conversation_hash_no_addr2(gconstpointer v)
260 const conversation_key_t key = (const conversation_key_t)v;
267 hash_val = add_address_to_hash(hash_val, &key->addr1);
269 tmp_addr.data = &key->port1;
270 hash_val = add_address_to_hash(hash_val, &tmp_addr);
272 tmp_addr.data = &key->port2;
273 hash_val = add_address_to_hash(hash_val, &tmp_addr);
275 hash_val += ( hash_val << 3 );
276 hash_val ^= ( hash_val >> 11 );
277 hash_val += ( hash_val << 15 );
283 * Compare two conversation keys, except for the address 2 value.
284 * We don't check both directions of the conversation - the routine
285 * doing the hash lookup has to do two searches, as the hash key
286 * will be different for the two directions.
289 conversation_match_no_addr2(gconstpointer v, gconstpointer w)
291 const conversation_key_t v1 = (const conversation_key_t)v;
292 const conversation_key_t v2 = (const conversation_key_t)w;
294 if (v1->etype != v2->etype)
295 return 0; /* different types of port */
298 * Are the first and second port 1 values the same, the first and
299 * second port 2 valuess the same, and the first and second
300 * address 1 values the same?
302 if (v1->port1 == v2->port1 &&
303 v1->port2 == v2->port2 &&
304 addresses_equal(&v1->addr1, &v2->addr1)) {
306 * Yes. It's the same conversation, and the two
307 * address/port pairs are going in the same direction.
313 * The addresses or the ports don't match.
319 * Compute the hash value for two given address/port pairs if the match
320 * has a wildcard port 2.
323 conversation_hash_no_port2(gconstpointer v)
325 const conversation_key_t key = (const conversation_key_t)v;
332 hash_val = add_address_to_hash(hash_val, &key->addr1);
334 tmp_addr.data = &key->port1;
335 hash_val = add_address_to_hash(hash_val, &tmp_addr);
337 hash_val = add_address_to_hash(hash_val, &key->addr2);
339 hash_val += ( hash_val << 3 );
340 hash_val ^= ( hash_val >> 11 );
341 hash_val += ( hash_val << 15 );
347 * Compare two conversation keys, except for the port 2 value.
348 * We don't check both directions of the conversation - the routine
349 * doing the hash lookup has to do two searches, as the hash key
350 * will be different for the two directions.
353 conversation_match_no_port2(gconstpointer v, gconstpointer w)
355 const conversation_key_t v1 = (const conversation_key_t)v;
356 const conversation_key_t v2 = (const conversation_key_t)w;
358 if (v1->etype != v2->etype)
359 return 0; /* different types of port */
362 * Are the first and second port 1 values the same, the first and
363 * second address 1 values the same, and the first and second
364 * address 2 values the same?
366 if (v1->port1 == v2->port1 &&
367 addresses_equal(&v1->addr1, &v2->addr1) &&
368 addresses_equal(&v1->addr2, &v2->addr2)) {
370 * Yes. It's the same conversation, and the two
371 * address/port pairs are going in the same direction.
377 * The addresses or the ports don't match.
383 * Compute the hash value for two given address/port pairs if the match
384 * has a wildcard address 2 and port 2.
387 conversation_hash_no_addr2_or_port2(gconstpointer v)
389 const conversation_key_t key = (const conversation_key_t)v;
396 hash_val = add_address_to_hash(hash_val, &key->addr1);
398 tmp_addr.data = &key->port1;
399 hash_val = add_address_to_hash(hash_val, &tmp_addr);
401 hash_val += ( hash_val << 3 );
402 hash_val ^= ( hash_val >> 11 );
403 hash_val += ( hash_val << 15 );
409 * Compare the address 1 and port 1 in the two conversation keys.
410 * We don't check both directions of the conversation - the routine
411 * doing the hash lookup has to do two searches, as the hash key
412 * will be different for the two directions.
415 conversation_match_no_addr2_or_port2(gconstpointer v, gconstpointer w)
417 const conversation_key_t v1 = (const conversation_key_t)v;
418 const conversation_key_t v2 = (const conversation_key_t)w;
420 if (v1->etype != v2->etype)
421 return 0; /* different types of port */
424 * Are the first and second port 1 values the same and the first
425 * and second address 1 values the same?
427 if (v1->port1 == v2->port1 &&
428 addresses_equal(&v1->addr1, &v2->addr1)) {
430 * Yes. It's the same conversation, and the two
431 * address/port pairs are going in the same direction.
437 * The addresses or the ports don't match.
443 * Create a new hash tables for conversations.
446 conversation_init(void)
449 * Free up any space allocated for conversation protocol data
452 * We can free the space, as the structures it contains are
453 * pointed to by conversation data structures that were freed
456 conversation_hashtable_exact =
457 wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_exact,
458 conversation_match_exact);
459 conversation_hashtable_no_addr2 =
460 wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_no_addr2,
461 conversation_match_no_addr2);
462 conversation_hashtable_no_port2 =
463 wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_no_port2,
464 conversation_match_no_port2);
465 conversation_hashtable_no_addr2_or_port2 =
466 wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_no_addr2_or_port2,
467 conversation_match_no_addr2_or_port2);
472 * Initialize some variables every time a file is loaded or re-loaded.
474 void conversation_epan_reset(void)
477 * Start the conversation indices over at 0.
483 * Does the right thing when inserting into one of the conversation hash tables,
484 * taking into account ordering and hash chains and all that good stuff.
486 * Mostly adapted from the old conversation_new().
489 conversation_insert_into_hashtable(wmem_map_t *hashtable, conversation_t *conv)
491 conversation_t *chain_head, *chain_tail, *cur, *prev;
493 chain_head = (conversation_t *)wmem_map_lookup(hashtable, conv->key_ptr);
495 if (NULL==chain_head) {
499 wmem_map_insert(hashtable, conv->key_ptr, conv);
500 DPRINT(("created a new conversation chain"));
503 /* There's an existing chain for this key */
504 DPRINT(("there's an existing conversation chain"));
506 chain_tail = chain_head->last;
508 if(conv->setup_frame >= chain_tail->setup_frame) {
509 /* This convo belongs at the end of the chain */
512 chain_tail->next = conv;
513 chain_head->last = conv;
516 /* Loop through the chain to find the right spot */
520 for (; (conv->setup_frame > cur->setup_frame) && cur->next; prev=cur, cur=cur->next)
524 /* Changing the head of the chain */
525 conv->next = chain_head;
526 conv->last = chain_tail;
527 chain_head->last = NULL;
528 wmem_map_insert(hashtable, conv->key_ptr, conv);
531 /* Inserting into the middle of the chain */
541 * Does the right thing when removing from one of the conversation hash tables,
542 * taking into account ordering and hash chains and all that good stuff.
545 conversation_remove_from_hashtable(wmem_map_t *hashtable, conversation_t *conv)
547 conversation_t *chain_head, *cur, *prev;
549 chain_head = (conversation_t *)wmem_map_lookup(hashtable, conv->key_ptr);
551 if (conv == chain_head) {
552 /* We are currently the front of the chain */
553 if (NULL == conv->next) {
554 /* We are the only conversation in the chain, no need to
555 * update next pointer, but do not call
556 * wmem_map_remove() either because the conv data
557 * will be re-inserted. */
558 wmem_map_steal(hashtable, conv->key_ptr);
561 /* Update the head of the chain */
562 chain_head = conv->next;
563 chain_head->last = conv->last;
565 if (conv->latest_found == conv)
566 chain_head->latest_found = NULL;
568 chain_head->latest_found = conv->latest_found;
570 wmem_map_insert(hashtable, chain_head->key_ptr, chain_head);
574 /* We are not the front of the chain. Loop through to find us.
575 * Start loop at chain_head->next rather than chain_head because
576 * we already know we're not at the head. */
577 cur = chain_head->next;
580 for (; (cur != conv) && cur->next; prev=cur, cur=cur->next)
584 /* XXX: Conversation not found. Wrong hashtable? */
588 prev->next = conv->next;
590 if (NULL == conv->next) {
591 /* We're at the very end of the list. */
592 chain_head->last = prev;
595 if (chain_head->latest_found == conv)
596 chain_head->latest_found = prev;
601 * Given two address/port pairs for a packet, create a new conversation
602 * to contain packets between those address/port pairs.
604 * The options field is used to specify whether the address 2 value
605 * and/or port 2 value are not given and any value is acceptable
606 * when searching for this conversation.
609 conversation_new(const guint32 setup_frame, const address *addr1, const address *addr2,
610 const endpoint_type etype, const guint32 port1, const guint32 port2, const guint options)
613 DISSECTOR_ASSERT(!(options | CONVERSATION_TEMPLATE) || ((options | (NO_ADDR2 | NO_PORT2 | NO_PORT2_FORCE))) &&
614 "A conversation template may not be constructed without wildcard options");
616 wmem_map_t* hashtable;
617 conversation_t *conversation=NULL;
618 conversation_key_t new_key;
620 DPRINT(("creating conversation for frame #%d: %s:%d -> %s:%d (ptype=%d)",
621 setup_frame, address_to_str(wmem_packet_scope(), addr1), port1,
622 address_to_str(wmem_packet_scope(), addr2), port2, ptype));
624 if (options & NO_ADDR2) {
625 if (options & (NO_PORT2|NO_PORT2_FORCE)) {
626 hashtable = conversation_hashtable_no_addr2_or_port2;
628 hashtable = conversation_hashtable_no_addr2;
631 if (options & (NO_PORT2|NO_PORT2_FORCE)) {
632 hashtable = conversation_hashtable_no_port2;
634 hashtable = conversation_hashtable_exact;
638 new_key = wmem_new(wmem_file_scope(), struct conversation_key);
639 copy_address_wmem(wmem_file_scope(), &new_key->addr1, addr1);
640 copy_address_wmem(wmem_file_scope(), &new_key->addr2, addr2);
641 new_key->etype = etype;
642 new_key->port1 = port1;
643 new_key->port2 = port2;
645 conversation = wmem_new(wmem_file_scope(), conversation_t);
646 memset(conversation, 0, sizeof(conversation_t));
648 conversation->conv_index = new_index;
649 conversation->setup_frame = conversation->last_frame = setup_frame;
650 conversation->data_list = NULL;
652 conversation->dissector_tree = wmem_tree_new(wmem_file_scope());
654 /* set the options and key pointer */
655 conversation->options = options;
656 conversation->key_ptr = new_key;
661 conversation_insert_into_hashtable(hashtable, conversation);
668 * Set the port 2 value in a key. Remove the original from table,
669 * update the options and port values, insert the updated key.
672 conversation_set_port2(conversation_t *conv, const guint32 port)
674 DISSECTOR_ASSERT_HINT(!(conv->options & CONVERSATION_TEMPLATE),
675 "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask");
677 DPRINT(("called for port=%d", port));
680 * If the port 2 value is not wildcarded, don't set it.
682 if ((!(conv->options & NO_PORT2)) || (conv->options & NO_PORT2_FORCE))
686 if (conv->options & NO_ADDR2) {
687 conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
689 conversation_remove_from_hashtable(conversation_hashtable_no_port2, conv);
691 conv->options &= ~NO_PORT2;
692 conv->key_ptr->port2 = port;
693 if (conv->options & NO_ADDR2) {
694 conversation_insert_into_hashtable(conversation_hashtable_no_addr2, conv);
696 conversation_insert_into_hashtable(conversation_hashtable_exact, conv);
702 * Set the address 2 value in a key. Remove the original from
703 * table, update the options and port values, insert the updated key.
706 conversation_set_addr2(conversation_t *conv, const address *addr)
709 DISSECTOR_ASSERT_HINT(!(conv->options & CONVERSATION_TEMPLATE),
710 "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask");
712 addr_str = address_to_str(NULL, addr);
713 DPRINT(("called for addr=%s", addr_str));
714 wmem_free(NULL, addr_str);
717 * If the address 2 value is not wildcarded, don't set it.
719 if (!(conv->options & NO_ADDR2))
723 if (conv->options & NO_PORT2) {
724 conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
726 conversation_remove_from_hashtable(conversation_hashtable_no_port2, conv);
728 conv->options &= ~NO_ADDR2;
729 copy_address_wmem(wmem_file_scope(), &conv->key_ptr->addr2, addr);
730 if (conv->options & NO_PORT2) {
731 conversation_insert_into_hashtable(conversation_hashtable_no_port2, conv);
733 conversation_insert_into_hashtable(conversation_hashtable_exact, conv);
739 * Search a particular hash table for a conversation with the specified
740 * {addr1, port1, addr2, port2} and set up before frame_num.
742 static conversation_t *
743 conversation_lookup_hashtable(wmem_map_t *hashtable, const guint32 frame_num, const address *addr1, const address *addr2,
744 const endpoint_type etype, const guint32 port1, const guint32 port2)
746 conversation_t* convo=NULL;
747 conversation_t* match=NULL;
748 conversation_t* chain_head=NULL;
749 struct conversation_key key;
752 * We don't make a copy of the address data, we just copy the
753 * pointer to it, as "key" disappears when we return.
761 chain_head = (conversation_t *)wmem_map_lookup(hashtable, &key);
763 if (chain_head && (chain_head->setup_frame <= frame_num)) {
766 if((chain_head->last)&&(chain_head->last->setup_frame<=frame_num))
767 return chain_head->last;
769 if((chain_head->latest_found)&&(chain_head->latest_found->setup_frame<=frame_num))
770 match = chain_head->latest_found;
772 for (convo = match; convo && convo->setup_frame <= frame_num; convo = convo->next) {
773 if (convo->setup_frame > match->setup_frame) {
780 chain_head->latest_found = match;
787 * Given two address/port pairs for a packet, search for a conversation
788 * containing packets between those address/port pairs. Returns NULL if
791 * We try to find the most exact match that we can, and then proceed to
792 * try wildcard matches on the "addr_b" and/or "port_b" argument if a more
793 * exact match failed.
795 * Either or both of the "addr_b" and "port_b" arguments may be specified as
796 * a wildcard by setting the NO_ADDR_B or NO_PORT_B flags in the "options"
797 * argument. We do only wildcard matches on addresses and ports specified
802 * if neither "addr_b" nor "port_b" were specified as wildcards, we
803 * do an exact match (addr_a/port_a and addr_b/port_b) and, if that
804 * succeeds, we return a pointer to the matched conversation;
806 * otherwise, if "port_b" wasn't specified as a wildcard, we try to
807 * match any address 2 with the specified port 2 (addr_a/port_a and
808 * {any}/port_b) and, if that succeeds, we return a pointer to the
809 * matched conversation;
811 * otherwise, if "addr_b" wasn't specified as a wildcard, we try to
812 * match any port 2 with the specified address 2 (addr_a/port_a and
813 * addr_b/{any}) and, if that succeeds, we return a pointer to the
814 * matched conversation;
816 * otherwise, we try to match any address 2 and any port 2
817 * (addr_a/port_a and {any}/{any}) and, if that succeeds, we return
818 * a pointer to the matched conversation;
820 * otherwise, we found no matching conversation, and return NULL.
823 find_conversation(const guint32 frame_num, const address *addr_a, const address *addr_b, const endpoint_type etype,
824 const guint32 port_a, const guint32 port_b, const guint options)
826 conversation_t *conversation;
829 * First try an exact match, if we have two addresses and ports.
831 if (!(options & (NO_ADDR_B|NO_PORT_B))) {
833 * Neither search address B nor search port B are wildcarded,
834 * start out with an exact match.
836 DPRINT(("trying exact match"));
838 conversation_lookup_hashtable(conversation_hashtable_exact,
839 frame_num, addr_a, addr_b, etype,
841 /* Didn't work, try the other direction */
842 if (conversation == NULL) {
843 DPRINT(("trying opposite direction"));
845 conversation_lookup_hashtable(conversation_hashtable_exact,
846 frame_num, addr_b, addr_a, etype,
849 if ((conversation == NULL) && (addr_a->type == AT_FC)) {
850 /* In Fibre channel, OXID & RXID are never swapped as
851 * TCP/UDP ports are in TCP/IP.
854 conversation_lookup_hashtable(conversation_hashtable_exact,
855 frame_num, addr_b, addr_a, etype,
858 DPRINT(("exact match %sfound",conversation?"":"not "));
859 if (conversation != NULL)
864 * Well, that didn't find anything. Try matches that wildcard
865 * one of the addresses, if we have two ports.
867 if (!(options & NO_PORT_B)) {
869 * Search port B isn't wildcarded.
871 * First try looking for a conversation with the specified
872 * address A and port A as the first address and port, and
873 * with any address and the specified port B as the second
875 * ("addr_b" doesn't take part in this lookup.)
877 DPRINT(("trying wildcarded dest address"));
879 conversation_lookup_hashtable(conversation_hashtable_no_addr2,
880 frame_num, addr_a, addr_b, etype, port_a, port_b);
881 if ((conversation == NULL) && (addr_a->type == AT_FC)) {
882 /* In Fibre channel, OXID & RXID are never swapped as
883 * TCP/UDP ports are in TCP/IP.
886 conversation_lookup_hashtable(conversation_hashtable_no_addr2,
887 frame_num, addr_b, addr_a, etype,
890 if (conversation != NULL) {
892 * If search address B isn't wildcarded, and this is for a
893 * connection-oriented protocol, set the second address for this
894 * conversation to address B, as that's the address that matched the
895 * wildcarded second address for this conversation.
897 * (This assumes that, for all connection oriented protocols, the
898 * endpoints of a connection have only one address each, i.e. you
899 * don't get packets in a given direction coming from more than one
900 * address, unless the CONVERSATION_TEMPLATE option is set.)
902 DPRINT(("wildcarded dest address match found"));
903 if (!(conversation->options & NO_ADDR_B) && etype != ENDPOINT_UDP)
905 if(!(conversation->options & CONVERSATION_TEMPLATE))
907 conversation_set_addr2(conversation, addr_b);
912 conversation_create_from_template(conversation, addr_b, 0);
919 * Well, that didn't find anything.
920 * If search address B was specified, try looking for a
921 * conversation with the specified address B and port B as
922 * the first address and port, and with any address and the
923 * specified port A as the second address and port (this
924 * packet may be going in the opposite direction from the
925 * first packet in the conversation).
926 * ("addr_a" doesn't take part in this lookup.)
928 if (!(options & NO_ADDR_B)) {
929 DPRINT(("trying dest addr:port as source addr:port with wildcarded dest addr"));
931 conversation_lookup_hashtable(conversation_hashtable_no_addr2,
932 frame_num, addr_b, addr_a, etype, port_b, port_a);
933 if (conversation != NULL) {
935 * If this is for a connection-oriented
936 * protocol, set the second address for
937 * this conversation to address A, as
938 * that's the address that matched the
939 * wildcarded second address for this
942 DPRINT(("match found"));
943 if (etype != ENDPOINT_UDP) {
944 if(!(conversation->options & CONVERSATION_TEMPLATE))
946 conversation_set_addr2(conversation, addr_a);
951 conversation_create_from_template(conversation, addr_a, 0);
960 * Well, that didn't find anything. Try matches that wildcard
961 * one of the ports, if we have two addresses.
963 if (!(options & NO_ADDR_B)) {
965 * Search address B isn't wildcarded.
967 * First try looking for a conversation with the specified
968 * address A and port A as the first address and port, and
969 * with the specified address B and any port as the second
971 * ("port_b" doesn't take part in this lookup.)
973 DPRINT(("trying wildcarded dest port"));
975 conversation_lookup_hashtable(conversation_hashtable_no_port2,
976 frame_num, addr_a, addr_b, etype, port_a, port_b);
977 if ((conversation == NULL) && (addr_a->type == AT_FC)) {
978 /* In Fibre channel, OXID & RXID are never swapped as
979 * TCP/UDP ports are in TCP/IP
982 conversation_lookup_hashtable(conversation_hashtable_no_port2,
983 frame_num, addr_b, addr_a, etype, port_a, port_b);
985 if (conversation != NULL) {
987 * If search port B isn't wildcarded, and this is for a connection-
988 * oriented protocol, set the second port for this conversation to
989 * port B, as that's the port that matched the wildcarded second port
990 * for this conversation.
992 * (This assumes that, for all connection oriented protocols, the
993 * endpoints of a connection have only one port each, i.e. you don't
994 * get packets in a given direction coming from more than one port,
995 * unless the CONVERSATION_TEMPLATE option is set.)
997 DPRINT(("match found"));
998 if (!(conversation->options & NO_PORT_B) && etype != ENDPOINT_UDP)
1000 if(!(conversation->options & CONVERSATION_TEMPLATE))
1002 conversation_set_port2(conversation, port_b);
1007 conversation_create_from_template(conversation, 0, port_b);
1010 return conversation;
1014 * Well, that didn't find anything.
1015 * If search port B was specified, try looking for a
1016 * conversation with the specified address B and port B
1017 * as the first address and port, and with the specified
1018 * address A and any port as the second address and port
1019 * (this packet may be going in the opposite direction
1020 * from the first packet in the conversation).
1021 * ("port_a" doesn't take part in this lookup.)
1023 if (!(options & NO_PORT_B)) {
1024 DPRINT(("trying dest addr:port as source addr:port and wildcarded dest port"));
1026 conversation_lookup_hashtable(conversation_hashtable_no_port2,
1027 frame_num, addr_b, addr_a, etype, port_b, port_a);
1028 if (conversation != NULL) {
1030 * If this is for a connection-oriented
1031 * protocol, set the second port for
1032 * this conversation to port A, as
1033 * that's the address that matched the
1034 * wildcarded second address for this
1037 DPRINT(("match found"));
1038 if (etype != ENDPOINT_UDP)
1040 if(!(conversation->options & CONVERSATION_TEMPLATE))
1042 conversation_set_port2(conversation, port_a);
1047 conversation_create_from_template(conversation, 0, port_a);
1050 return conversation;
1056 * Well, that didn't find anything. Try matches that wildcard
1057 * one address/port pair.
1059 * First try looking for a conversation with the specified address A
1060 * and port A as the first address and port.
1061 * (Neither "addr_b" nor "port_b" take part in this lookup.)
1063 DPRINT(("trying wildcarding dest addr:port"));
1065 conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
1066 frame_num, addr_a, addr_b, etype, port_a, port_b);
1067 if (conversation != NULL) {
1069 * If this is for a connection-oriented protocol:
1071 * if search address B isn't wildcarded, set the
1072 * second address for this conversation to address
1073 * B, as that's the address that matched the
1074 * wildcarded second address for this conversation;
1076 * if search port B isn't wildcarded, set the
1077 * second port for this conversation to port B,
1078 * as that's the port that matched the wildcarded
1079 * second port for this conversation.
1081 DPRINT(("match found"));
1082 if (etype != ENDPOINT_UDP)
1084 if(!(conversation->options & CONVERSATION_TEMPLATE))
1086 if (!(conversation->options & NO_ADDR_B))
1087 conversation_set_addr2(conversation, addr_b);
1088 if (!(conversation->options & NO_PORT_B))
1089 conversation_set_port2(conversation, port_b);
1094 conversation_create_from_template(conversation, addr_b, port_b);
1097 return conversation;
1099 /* for Infiniband, don't try to look in addresses of reverse
1100 * direction, because it could be another different
1101 * valid conversation than what is being searched using
1104 if (etype != ENDPOINT_IBQP)
1108 * Well, that didn't find anything.
1109 * If search address and port B were specified, try looking for a
1110 * conversation with the specified address B and port B as the
1111 * first address and port, and with any second address and port
1112 * (this packet may be going in the opposite direction from the
1113 * first packet in the conversation).
1114 * (Neither "addr_a" nor "port_a" take part in this lookup.)
1116 DPRINT(("trying dest addr:port as source addr:port and wildcarding dest addr:port"));
1117 if (addr_a->type == AT_FC)
1119 conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
1120 frame_num, addr_b, addr_a, etype, port_a, port_b);
1123 conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
1124 frame_num, addr_b, addr_a, etype, port_b, port_a);
1125 if (conversation != NULL) {
1127 * If this is for a connection-oriented protocol, set the
1128 * second address for this conversation to address A, as
1129 * that's the address that matched the wildcarded second
1130 * address for this conversation, and set the second port
1131 * for this conversation to port A, as that's the port
1132 * that matched the wildcarded second port for this
1135 DPRINT(("match found"));
1136 if (etype != ENDPOINT_UDP)
1138 if(!(conversation->options & CONVERSATION_TEMPLATE))
1140 conversation_set_addr2(conversation, addr_a);
1141 conversation_set_port2(conversation, port_a);
1145 conversation = conversation_create_from_template(conversation, addr_a, port_a);
1148 return conversation;
1151 DPRINT(("no matches found"));
1154 * We found no conversation.
1160 conversation_add_proto_data(conversation_t *conv, const int proto, void *proto_data)
1162 /* Add it to the list of items for this conversation. */
1163 if (conv->data_list == NULL)
1164 conv->data_list = wmem_tree_new(wmem_file_scope());
1166 wmem_tree_insert32(conv->data_list, proto, proto_data);
1170 conversation_get_proto_data(const conversation_t *conv, const int proto)
1172 /* No tree created yet */
1173 if (conv->data_list == NULL)
1176 return wmem_tree_lookup32(conv->data_list, proto);
1180 conversation_delete_proto_data(conversation_t *conv, const int proto)
1182 if (conv->data_list != NULL)
1183 wmem_tree_remove32(conv->data_list, proto);
1187 conversation_set_dissector_from_frame_number(conversation_t *conversation,
1188 const guint32 starting_frame_num, const dissector_handle_t handle)
1190 wmem_tree_insert32(conversation->dissector_tree, starting_frame_num, (void *)handle);
1194 conversation_set_dissector(conversation_t *conversation, const dissector_handle_t handle)
1196 conversation_set_dissector_from_frame_number(conversation, 0, handle);
1200 conversation_get_dissector(conversation_t *conversation, const guint32 frame_num)
1202 return (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, frame_num);
1206 * Given two address/port pairs for a packet, search for a matching
1207 * conversation and, if found and it has a conversation dissector,
1208 * call that dissector and return TRUE, otherwise return FALSE.
1210 * This helper uses call_dissector_only which will NOT call the default
1211 * "data" dissector if the packet was rejected.
1212 * Our caller is responsible to call the data dissector explicitly in case
1213 * this function returns FALSE.
1216 try_conversation_dissector(const address *addr_a, const address *addr_b, const endpoint_type etype,
1217 const guint32 port_a, const guint32 port_b, tvbuff_t *tvb, packet_info *pinfo,
1218 proto_tree *tree, void* data)
1220 conversation_t *conversation;
1222 conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a,
1225 if (conversation != NULL) {
1227 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num);
1230 ret=call_dissector_only(handle, tvb, pinfo, tree, data);
1232 /* this packet was rejected by the dissector
1233 * so return FALSE in case our caller wants
1234 * to do some cleaning up.
1243 /** A helper function that calls find_conversation() using data from pinfo
1244 * The frame number and addresses are taken from pinfo.
1247 find_conversation_pinfo(packet_info *pinfo, const guint options)
1249 conversation_t *conv=NULL;
1251 DPRINT(("called for frame #%d: %s:%d -> %s:%d (ptype=%d)",
1252 pinfo->num, address_to_str(wmem_packet_scope(), &pinfo->src), pinfo->srcport,
1253 address_to_str(wmem_packet_scope(), &pinfo->dst), pinfo->destport, pinfo->ptype));
1256 /* Have we seen this conversation before? */
1257 if((conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
1258 conversation_pt_to_endpoint_type(pinfo->ptype), pinfo->srcport,
1259 pinfo->destport, options)) != NULL) {
1260 DPRINT(("found previous conversation for frame #%d (last_frame=%d)",
1261 pinfo->num, conv->last_frame));
1262 if (pinfo->num > conv->last_frame) {
1263 conv->last_frame = pinfo->num;
1270 /* A helper function that calls find_conversation() and, if a conversation is
1271 * not found, calls conversation_new().
1272 * The frame number and addresses are taken from pinfo.
1273 * No options are used, though we could extend this API to include an options
1277 find_or_create_conversation(packet_info *pinfo)
1279 conversation_t *conv=NULL;
1281 /* Have we seen this conversation before? */
1282 if((conv = find_conversation_pinfo(pinfo, 0)) == NULL) {
1283 /* No, this is a new conversation. */
1284 DPRINT(("did not find previous conversation for frame #%d",
1287 conv = conversation_new(pinfo->num, &pinfo->src,
1288 &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
1289 pinfo->srcport, pinfo->destport, 0);
1299 get_conversation_hashtable_exact(void)
1301 return conversation_hashtable_exact;
1305 get_conversation_hashtable_no_addr2(void)
1307 return conversation_hashtable_no_addr2;
1311 get_conversation_hashtable_no_port2(void)
1313 return conversation_hashtable_no_port2;
1317 get_conversation_hashtable_no_addr2_or_port2(void)
1319 return conversation_hashtable_no_addr2_or_port2;
1323 conversation_key_addr1(const conversation_key_t key)
1329 conversation_key_addr2(const conversation_key_t key)
1335 conversation_key_port1(const conversation_key_t key)
1341 conversation_key_port2(const conversation_key_t key)
1347 endpoint_type conversation_pt_to_endpoint_type(port_type pt)
1352 return ENDPOINT_NONE;
1354 return ENDPOINT_SCTP;
1356 return ENDPOINT_TCP;
1358 return ENDPOINT_UDP;
1360 return ENDPOINT_DCCP;
1362 return ENDPOINT_IPX;
1364 return ENDPOINT_EXCHG;
1366 return ENDPOINT_DDP;
1368 return ENDPOINT_IDP;
1370 return ENDPOINT_TIPC;
1372 return ENDPOINT_USB;
1374 return ENDPOINT_I2C;
1376 return ENDPOINT_IBQP;
1378 return ENDPOINT_BLUETOOTH;
1380 return ENDPOINT_TDMOP;
1383 DISSECTOR_ASSERT(FALSE);
1384 return ENDPOINT_NONE;
1388 conversation_get_html_hash(const conversation_key_t key)
1390 gchar *hash, *addr1, *addr2;
1392 addr1 = address_to_str(NULL, &key->addr1);
1393 addr2 = address_to_str(NULL, &key->addr2);
1394 hash = wmem_strdup_printf(NULL, "<tr><td>%s</td><td>%d</td><td>%s</td><td>%d</td></tr>\n",
1395 addr1, key->port1, addr2, key->port2);
1396 wmem_free(NULL, addr1);
1397 wmem_free(NULL, addr2);
1403 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1408 * indent-tabs-mode: t
1411 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1412 * :indentSize=8:tabSize=8:noTabs=false: