Clean up indentation.
[obnox/wireshark/wip.git] / epan / conversation.c
1 /* conversation.c
2  * Routines for building lists of packets that are part of a "conversation"
3  *
4  * $Id: conversation.c,v 1.17 2001/11/29 09:05:25 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  * 
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdio.h>
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #ifdef HAVE_NETINET_IN_H
36 # include <netinet/in.h>
37 #endif
38
39 #include <string.h>
40 #include <glib.h>
41 #include "packet.h"
42 #include "conversation.h"
43
44 /*
45  * Hash table for conversations with no wildcards.
46  */
47 static GHashTable *conversation_hashtable_exact = NULL;
48
49 /*
50  * Hash table for conversations with one wildcard address.
51  */
52 static GHashTable *conversation_hashtable_no_addr2 = NULL;
53
54 /*
55  * Hash table for conversations with one wildcard port.
56  */
57 static GHashTable *conversation_hashtable_no_port2 = NULL;
58
59 /*
60  * Hash table for conversations with one wildcard address and port.
61  */
62 static GHashTable *conversation_hashtable_no_addr2_or_port2 = NULL;
63
64 static GMemChunk *conversation_key_chunk = NULL;
65 static GMemChunk *conversation_chunk = NULL;
66
67 #ifdef __NOT_USED__ 
68 typedef struct conversation_key {
69         struct conversation_key *next;
70         address addr1;
71         address addr2;
72         port_type ptype;
73         guint32 port1;
74         guint32 port2;
75 } conversation_key;
76 #endif
77 /*
78  * Linked list of conversation keys, so we can, before freeing them all,
79  * free the address data allocations associated with them.
80  */
81 static conversation_key *conversation_keys;
82
83 static guint32 new_index;
84
85 static int conversation_init_count = 200;
86
87 /*
88  * Protocol-specific data attached to a conversation_t structure - protocol
89  * index and opaque pointer.
90  */
91 typedef struct _conv_proto_data {
92         int     proto;
93         void    *proto_data;
94 } conv_proto_data;
95
96 static GMemChunk *conv_proto_data_area = NULL;
97
98 /*
99  * Compute the hash value for two given address/port pairs if the match
100  * is to be exact.
101  */
102 static guint 
103 conversation_hash_exact(gconstpointer v)
104 {
105         conversation_key *key = (conversation_key *)v;
106         guint hash_val;
107         int i;
108
109         hash_val = 0;
110         for (i = 0; i < key->addr1.len; i++)
111                 hash_val += key->addr1.data[i];
112
113         hash_val += key->port1;
114
115         for (i = 0; i < key->addr2.len; i++)
116                 hash_val += key->addr2.data[i];
117
118         hash_val += key->port2;
119
120         return hash_val;
121 }
122
123 /*
124  * Compare two conversation keys for an exact match.
125  */
126 static gint
127 conversation_match_exact(gconstpointer v, gconstpointer w)
128 {
129         conversation_key *v1 = (conversation_key *)v;
130         conversation_key *v2 = (conversation_key *)w;
131
132         if (v1->ptype != v2->ptype)
133                 return 0;       /* different types of port */
134
135         /*
136          * Are the first and second port 1 values the same, the first and
137          * second port 2 values the same, the first and second address
138          * 1 values the same, and the first and second address 2 values
139          * the same?
140          */
141         if (v1->port1 == v2->port1 &&
142             v1->port2 == v2->port2 &&
143             ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
144             ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
145                 /*
146                  * Yes.  It's the same conversation, and the two
147                  * address/port pairs are going in the same direction.
148                  */
149                 return 1;
150         }
151
152         /*
153          * Is the first port 2 the same as the second port 1, the first
154          * port 1 the same as the second port 2, the first address 2
155          * the same as the second address 1, and the first address 1
156          * the same as the second address 2?
157          */
158         if (v1->port2 == v2->port1 &&
159             v1->port1 == v2->port2 &&
160             ADDRESSES_EQUAL(&v1->addr2, &v2->addr1) &&
161             ADDRESSES_EQUAL(&v1->addr1, &v2->addr2)) {
162                 /*
163                  * Yes.  It's the same conversation, and the two
164                  * address/port pairs are going in opposite directions.
165                  */
166                 return 1;
167         }
168
169         /*
170          * The addresses or the ports don't match.
171          */     
172         return 0;
173 }
174
175 /*
176  * Compute the hash value for two given address/port pairs if the match
177  * has a wildcard address 2.
178  */
179 static guint 
180 conversation_hash_no_addr2(gconstpointer v)
181 {
182         conversation_key *key = (conversation_key *)v;
183         guint hash_val;
184         int i;
185
186         hash_val = 0;
187         for (i = 0; i < key->addr1.len; i++)
188                 hash_val += key->addr1.data[i];
189
190         hash_val += key->port1;
191
192         hash_val += key->port2;
193
194         return hash_val;
195 }
196
197 /*
198  * Compare two conversation keys, except for the address 2 value.
199  * We don't check both directions of the conversation - the routine
200  * doing the hash lookup has to do two searches, as the hash key
201  * will be different for the two directions.
202  */
203 static gint
204 conversation_match_no_addr2(gconstpointer v, gconstpointer w)
205 {
206         conversation_key *v1 = (conversation_key *)v;
207         conversation_key *v2 = (conversation_key *)w;
208
209         if (v1->ptype != v2->ptype)
210                 return 0;       /* different types of port */
211
212         /*
213          * Are the first and second port 1 values the same, the first and
214          * second port 2 valuess the same, and the first and second
215          * address 1 values the same?
216          */
217         if (v1->port1 == v2->port1 &&
218             v1->port2 == v2->port2 &&
219             ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) {
220                 /*
221                  * Yes.  It's the same conversation, and the two
222                  * address/port pairs are going in the same direction.
223                  */
224                 return 1;
225         }
226
227         /*
228          * The addresses or the ports don't match.
229          */     
230         return 0;
231 }
232
233 /*
234  * Compute the hash value for two given address/port pairs if the match
235  * has a wildcard port 2.
236  */
237 static guint 
238 conversation_hash_no_port2(gconstpointer v)
239 {
240         conversation_key *key = (conversation_key *)v;
241         guint hash_val;
242         int i;
243
244         hash_val = 0;
245         for (i = 0; i < key->addr1.len; i++)
246                 hash_val += key->addr1.data[i];
247
248         hash_val += key->port1;
249
250         for (i = 0; i < key->addr2.len; i++)
251                 hash_val += key->addr2.data[i];
252
253         return hash_val;
254 }
255
256 /*
257  * Compare two conversation keys, except for the port 2 value.
258  * We don't check both directions of the conversation - the routine
259  * doing the hash lookup has to do two searches, as the hash key
260  * will be different for the two directions.
261  */
262 static gint
263 conversation_match_no_port2(gconstpointer v, gconstpointer w)
264 {
265         conversation_key *v1 = (conversation_key *)v;
266         conversation_key *v2 = (conversation_key *)w;
267
268         if (v1->ptype != v2->ptype)
269                 return 0;       /* different types of port */
270
271         /*
272          * Are the first and second port 1 values the same, the first and
273          * second address 1 values the same, and the first and second
274          * address 2 values the same?
275          */
276         if (v1->port1 == v2->port1 &&
277             ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
278             ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
279                 /*
280                  * Yes.  It's the same conversation, and the two
281                  * address/port pairs are going in the same direction.
282                  */
283                 return 1;
284         }
285
286         /*
287          * The addresses or the ports don't match.
288          */     
289         return 0;
290 }
291
292 /*
293  * Compute the hash value for two given address/port pairs if the match
294  * has a wildcard address 2 and port 2.
295  */
296 static guint 
297 conversation_hash_no_addr2_or_port2(gconstpointer v)
298 {
299         conversation_key *key = (conversation_key *)v;
300         guint hash_val;
301         int i;
302
303         hash_val = 0;
304         for (i = 0; i < key->addr1.len; i++)
305                 hash_val += key->addr1.data[i];
306
307         hash_val += key->port1;
308
309         return hash_val;
310 }
311
312 /*
313  * Compare the address 1 and port 1 in the two conversation keys.
314  * We don't check both directions of the conversation - the routine
315  * doing the hash lookup has to do two searches, as the hash key
316  * will be different for the two directions.
317  */
318 static gint
319 conversation_match_no_addr2_or_port2(gconstpointer v, gconstpointer w)
320 {
321         conversation_key *v1 = (conversation_key *)v;
322         conversation_key *v2 = (conversation_key *)w;
323
324         if (v1->ptype != v2->ptype)
325                 return 0;       /* different types of port */
326
327         /*
328          * Are the first and second port 1 values the same and the first
329          * and second address 1 values the same?
330          */
331         if (v1->port1 == v2->port1 &&
332             ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) {
333                 /*
334                  * Yes.  It's the same conversation, and the two
335                  * address/port pairs are going in the same direction.
336                  */
337                 return 1;
338         }
339
340         /*
341          * The addresses or the ports don't match.
342          */     
343         return 0;
344 }
345
346 /*
347  * Initialize some variables every time a file is loaded or re-loaded.
348  * Destroy all existing conversations, and create a new hash table
349  * for the conversations in the new file.
350  */
351 void
352 conversation_init(void)
353 {
354         conversation_key *key;
355
356         /*
357          * Free the addresses associated with the conversation keys.
358          */
359         for (key = conversation_keys; key != NULL; key = key->next) {
360                 /*
361                  * Grr.  I guess the theory here is that freeing
362                  * something sure as heck modifies it, so you
363                  * want to ban attempts to free it, but, alas,
364                  * if we make the "data" field of an "address"
365                  * structure not a "const", the compiler whines if
366                  * we try to make it point into the data for a packet,
367                  * as that's a "const" array (and should be, as dissectors
368                  * shouldn't trash it).
369                  *
370                  * So we cast the complaint into oblivion, and rely on
371                  * the fact that these addresses are known to have had
372                  * their data mallocated, i.e. they don't point into,
373                  * say, the middle of the data for a packet.
374                  */
375                 g_free((gpointer)key->addr1.data);
376                 g_free((gpointer)key->addr2.data);
377         }
378         conversation_keys = NULL;
379         if (conversation_hashtable_exact != NULL)
380                 g_hash_table_destroy(conversation_hashtable_exact);
381         if (conversation_hashtable_no_addr2 != NULL)
382                 g_hash_table_destroy(conversation_hashtable_no_addr2);
383         if (conversation_hashtable_no_port2 != NULL)
384                 g_hash_table_destroy(conversation_hashtable_no_port2);
385         if (conversation_hashtable_no_addr2_or_port2 != NULL)
386                 g_hash_table_destroy(conversation_hashtable_no_addr2_or_port2);
387         if (conversation_key_chunk != NULL)
388                 g_mem_chunk_destroy(conversation_key_chunk);
389         if (conversation_chunk != NULL)
390                 g_mem_chunk_destroy(conversation_chunk);
391
392         /*
393          * Free up any space allocated for conversation protocol data
394          * areas.
395          *
396          * We can free the space, as the structures it contains are
397          * pointed to by conversation data structures that were freed
398          * above.
399          */
400         if (conv_proto_data_area != NULL)
401                 g_mem_chunk_destroy(conv_proto_data_area);
402
403         conversation_hashtable_exact =
404             g_hash_table_new(conversation_hash_exact,
405               conversation_match_exact);
406         conversation_hashtable_no_addr2 =
407             g_hash_table_new(conversation_hash_no_addr2,
408               conversation_match_no_addr2);
409         conversation_hashtable_no_port2 =
410             g_hash_table_new(conversation_hash_no_port2,
411               conversation_match_no_port2);
412         conversation_hashtable_no_addr2_or_port2 =
413             g_hash_table_new(conversation_hash_no_addr2_or_port2,
414               conversation_match_no_addr2_or_port2);
415         conversation_key_chunk = g_mem_chunk_new("conversation_key_chunk",
416             sizeof(conversation_key),
417             conversation_init_count * sizeof(struct conversation_key),
418             G_ALLOC_AND_FREE);
419         conversation_chunk = g_mem_chunk_new("conversation_chunk",
420             sizeof(conversation_t),
421             conversation_init_count * sizeof(conversation_t),
422             G_ALLOC_AND_FREE);
423
424         /*
425          * Allocate a new area for conversation protocol data items.
426          */
427         conv_proto_data_area = g_mem_chunk_new("conv_proto_data_area",
428             sizeof(conv_proto_data), 20 * sizeof(conv_proto_data), /* FIXME*/
429             G_ALLOC_ONLY);
430
431         /*
432          * Start the conversation indices over at 0.
433          */
434         new_index = 0;
435 }
436
437 /*
438  * Given two address/port pairs for a packet, create a new conversation
439  * to contain packets between those address/port pairs.
440  *
441  * The options field is used to specify whether the address 2 value
442  * and/or port 2 value are not given and any value is acceptable
443  * when searching for this conversation.
444  */
445 conversation_t *
446 conversation_new(address *addr1, address *addr2, port_type ptype,
447     guint32 port1, guint32 port2, guint options)
448 {
449         conversation_t *conversation;
450         conversation_key *new_key;
451
452         new_key = g_mem_chunk_alloc(conversation_key_chunk);
453         new_key->next = conversation_keys;
454         conversation_keys = new_key;
455         COPY_ADDRESS(&new_key->addr1, addr1);
456         COPY_ADDRESS(&new_key->addr2, addr2);
457         new_key->ptype = ptype;
458         new_key->port1 = port1;
459         new_key->port2 = port2;
460
461         conversation = g_mem_chunk_alloc(conversation_chunk);
462         conversation->index = new_index;
463         conversation->data_list = NULL;
464
465 /* clear dissector handle */
466         conversation->dissector_handle = NULL;
467
468 /* set the options and key pointer */
469         conversation->options = options;
470         conversation->key_ptr = new_key;
471
472         new_index++;
473
474         if (options & NO_ADDR2) {
475                 if (options & NO_PORT2) {
476                         g_hash_table_insert(conversation_hashtable_no_addr2_or_port2,
477                             new_key, conversation);
478                 } else {
479                         g_hash_table_insert(conversation_hashtable_no_addr2,
480                             new_key, conversation);
481                 }
482         } else {
483                 if (options & NO_PORT2) {
484                         g_hash_table_insert(conversation_hashtable_no_port2,
485                             new_key, conversation);
486                 } else {
487                         g_hash_table_insert(conversation_hashtable_exact,
488                             new_key, conversation);
489                 }
490         }
491         return conversation;
492 }
493
494 /*
495  * Set the port 2 value in a key.  Remove the original from table,
496  * update the options and port values, insert the updated key.
497  */
498 void
499 conversation_set_port2(conversation_t *conv, guint32 port)
500 {
501         /*
502          * If the port 2 value is wildcarded, don't set it.
503          */
504         if (!(conv->options & NO_PORT2))
505                 return;
506
507         if (conv->options & NO_ADDR2) {
508                 g_hash_table_remove(conversation_hashtable_no_addr2_or_port2,
509                     conv->key_ptr);
510         } else {
511                 g_hash_table_remove(conversation_hashtable_no_port2,
512                     conv->key_ptr);
513         }
514         conv->options &= ~NO_PORT2;
515         conv->key_ptr->port2  = port;
516         if (conv->options & NO_ADDR2) {
517                 g_hash_table_insert(conversation_hashtable_no_addr2,
518                     conv->key_ptr, conv);
519         } else {
520                 g_hash_table_insert(conversation_hashtable_exact,
521                     conv->key_ptr, conv);
522         }
523
524
525 /*
526  * Set the address 2 value in a key.  Remove the original from
527  * table, update the options and port values, insert the updated key.
528  */
529 void
530 conversation_set_addr2(conversation_t *conv, address *addr)
531 {
532         /*
533          * If the address 2 value is wildcarded, don't set it.
534          */
535         if (!(conv->options & NO_ADDR2))
536                 return;
537
538         if (conv->options & NO_PORT2) {
539                 g_hash_table_remove(conversation_hashtable_no_addr2_or_port2,
540                     conv->key_ptr);
541         } else {
542                 g_hash_table_remove(conversation_hashtable_no_addr2,
543                     conv->key_ptr);
544         }
545         conv->options &= ~NO_ADDR2;
546         COPY_ADDRESS(&conv->key_ptr->addr2, addr);
547         if (conv->options & NO_PORT2) {
548                 g_hash_table_insert(conversation_hashtable_no_port2,
549                     conv->key_ptr, conv);
550         } else {
551                 g_hash_table_insert(conversation_hashtable_exact,
552                     conv->key_ptr, conv);
553         }
554 }
555
556 /*
557  * Search a particular hash table for a conversaton with the specified
558  * addr1, port1, addr2, and port2.
559  */
560 static conversation_t *
561 conversation_lookup_hashtable(GHashTable *hashtable, address *addr1, address *addr2,
562     port_type ptype, guint32 port1, guint32 port2)
563 {
564         conversation_key key;
565
566         /*
567          * We don't make a copy of the address data, we just copy the
568          * pointer to it, as "key" disappears when we return.
569          */
570         key.addr1 = *addr1;
571         key.addr2 = *addr2;
572         key.ptype = ptype;
573         key.port1 = port1;
574         key.port2 = port2;
575         return g_hash_table_lookup(hashtable, &key);
576 }
577  
578
579 /*
580  * Given two address/port pairs for a packet, search for a conversation
581  * containing packets between those address/port pairs.  Returns NULL if
582  * not found.
583  *
584  * We try to find the most exact match that we can, and then proceed to
585  * try wildcard matches on the "addr_b" and/or "port_b" argument if a more
586  * exact match failed.
587  *
588  * Either or both of the "addr_b" and "port_b" arguments may be specified as
589  * a wildcard by setting the NO_ADDR_B or NO_PORT_B flags in the "options"
590  * argument.  We do only wildcard matches on addresses and ports specified
591  * as wildcards.
592  *
593  * I.e.:
594  *
595  *      if neither "addr_b" nor "port_b" were specified as wildcards, we
596  *      do an exact match (addr_a/port_a and addr_b/port_b) and, if that
597  *      succeeds, we return a pointer to the matched conversation;
598  *
599  *      otherwise, if "port_b" wasn't specified as a wildcard, we try to
600  *      match any address 2 with the specified port 2 (addr_a/port_a and
601  *      {any}/addr_b) and, if that succeeds, we return a pointer to the
602  *      matched conversation;
603  *
604  *      otherwise, if "addr_b" wasn't specified as a wildcard, we try to
605  *      match any port 2 with the specified address 2 (addr_a/port_a and
606  *      addr_b/{any}) and, if that succeeds, we return a pointer to the
607  *      matched conversation;
608  *
609  *      otherwise, we try to match any address 2 and any port 2
610  *      (addr_a/port_a and {any}/{any}) and, if that succeeds, we return
611  *      a pointer to the matched conversation;
612  *
613  *      otherwise, we found no matching conversation, and return NULL.
614  */
615 conversation_t *
616 find_conversation(address *addr_a, address *addr_b, port_type ptype,
617     guint32 port_a, guint32 port_b, guint options)
618 {
619         conversation_t *conversation;
620
621         /*
622          * First try an exact match, if we have two addresses and ports.
623          */
624         if (!(options & (NO_ADDR_B|NO_PORT_B))) {
625                 /*
626                  * Neither search address B nor search port B are wildcarded,
627                  * start out with an exact match.
628                  * Exact matches check both directions.
629                  */
630                 conversation =
631                     conversation_lookup_hashtable(conversation_hashtable_exact,
632                       addr_a, addr_b, ptype, port_a, port_b);
633                 if (conversation != NULL)
634                         return conversation;
635         }
636
637         /*
638          * Well, that didn't find anything.  Try matches that wildcard
639          * one of the addresses, if we have two ports.
640          */
641         if (!(options & NO_PORT_B)) {
642                 /*
643                  * Search port B isn't wildcarded.
644                  *
645                  * First try looking for a conversation with the specified
646                  * address A and port A as the first address and port, and
647                  * with any address and the specified port B as the second
648                  * address and port.
649                  * ("addr_b" doesn't take part in this lookup.)
650                  */
651                 conversation =
652                     conversation_lookup_hashtable(conversation_hashtable_no_addr2,
653                         addr_a, addr_b, ptype, port_a, port_b);
654                 if (conversation != NULL) {
655                         /*
656                          * If search address B isn't wildcarded, and this
657                          * is for a connection-oriented protocol, set the
658                          * second address for this conversation to address
659                          * B, as that's the address that matched the
660                          * wildcarded second address for this conversation.
661                          *
662                          * (XXX - this assumes that, for all connection-
663                          * oriented protocols, the endpoints of a connection
664                          * have only one address each, i.e. you don't get
665                          * packets in a given direction coming from more than
666                          * one address.) 
667                          */
668                         if (!(options & NO_ADDR_B) && ptype != PT_UDP)
669                                 conversation_set_addr2(conversation, addr_b);
670                         return conversation;
671                 }
672
673                 /*
674                  * Well, that didn't find anything.
675                  * If search address B was specified, try looking for a
676                  * conversation with the specified address B and port B as
677                  * the first address and port, and with any address and the
678                  * specified port A as the second address and port (this
679                  * packet may be going in the opposite direction from the
680                  * first packet in the conversation).
681                  * ("addr_a" doesn't take part in this lookup.)
682                  */
683                 if (!(options & NO_ADDR_B)) {
684                         conversation =
685                             conversation_lookup_hashtable(conversation_hashtable_no_addr2,
686                             addr_b, addr_a, ptype, port_b, port_a);
687                         if (conversation != NULL) {
688                                 /*
689                                  * If this is for a connection-oriented
690                                  * protocol, set the second address for
691                                  * this conversation to address A, as
692                                  * that's the address that matched the
693                                  * wildcarded second address for this
694                                  * conversation.
695                                  */
696                                 if (ptype != PT_UDP) {
697                                         conversation_set_addr2(conversation,
698                                             addr_a);
699                                 }
700                                 return conversation;
701                         }
702                 }
703         }
704
705         /*
706          * Well, that didn't find anything.  Try matches that wildcard
707          * one of the ports, if we have two addresses.
708          */
709         if (!(options & NO_ADDR_B)) {
710                 /*
711                  * Search address B isn't wildcarded.
712                  *
713                  * First try looking for a conversation with the specified
714                  * address A and port A as the first address and port, and
715                  * with the specified address B and any port as the second
716                  * address and port.
717                  * ("port_b" doesn't take part in this lookup.)
718                  */
719                 conversation =
720                     conversation_lookup_hashtable(conversation_hashtable_no_port2,
721                       addr_a, addr_b, ptype, port_a, port_b);
722                 if (conversation != NULL) {
723                         /*
724                          * If search port B isn't wildcarded, and this is
725                          * for a connection-oriented protocol, set the
726                          * second port for this conversation to port B,
727                          * as that's the port that matched the wildcarded
728                          * second port for this conversation.
729                          *
730                          * (XXX - this assumes that, for all connection-
731                          * oriented protocols, the endpoints of a connection
732                          * have only one port each, i.e. you don't get
733                          * packets in a given direction coming from more than
734                          * one port.)
735                          */
736                         if (!(options & NO_PORT_B) && ptype != PT_UDP)
737                                 conversation_set_port2(conversation, port_b);
738                         return conversation;
739                 }
740
741                 /*
742                  * Well, that didn't find anything.
743                  * If search port B was specified, try looking for a
744                  * conversation with the specified address B and port B
745                  * as the first address and port, and with the specified
746                  * address A and any port as the second address and port
747                  * (this packet may be going in the opposite direction
748                  * from the first packet in the conversation).
749                  * ("port_a" doesn't take part in this lookup.)
750                  */
751                 if (!(options & NO_PORT_B)) {
752                         conversation =
753                             conversation_lookup_hashtable(conversation_hashtable_no_port2,
754                               addr_b, addr_a, ptype, port_b, port_a);
755                         if (conversation != NULL) {
756                                 /*
757                                  * If this is for a connection-oriented
758                                  * protocol, set the second port for
759                                  * this conversation to port A, as
760                                  * that's the address that matched the
761                                  * wildcarded second address for this
762                                  * conversation.
763                                  */
764                                 if (ptype != PT_UDP) {
765                                         conversation_set_port2(conversation,
766                                             port_a);
767                                 }
768                                 return conversation;
769                         }
770                 }
771         }
772
773         /*
774          * Well, that didn't find anything.  Try matches that wildcard
775          * one address/port pair.
776          *
777          * First try looking for a conversation with the specified address A
778          * and port B as the first address and port.
779          * (Neither "addr_b" nor "port_b" take part in this lookup.)
780          */
781         conversation =
782             conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
783               addr_a, addr_b, ptype, port_a, port_b);
784         if (conversation != NULL) {
785                 /*
786                  * If this is for a connection-oriented protocol:
787                  *
788                  *      if search address B isn't wildcarded, set the
789                  *      second address for this conversation to address
790                  *      B, as that's the address that matched the
791                  *      wildcarded second address for this conversation;
792                  *
793                  *      if search port B isn't wildcarded, set the
794                  *      second port for this conversation to port B,
795                  *      as that's the port that matched the wildcarded
796                  *      second port for this conversation.
797                  */
798                 if (ptype != PT_UDP) {
799                         if (!(options & NO_ADDR_B))
800                                 conversation_set_addr2(conversation, addr_b);
801                         if (!(options & NO_PORT_B))
802                                 conversation_set_port2(conversation, port_b);
803                 }
804                 return conversation;
805         }
806
807         /*
808          * Well, that didn't find anything.
809          * If search address and port B were specified, try looking for a
810          * conversation with the specified address B and port B as the
811          * first address and port, and with any second address and port
812          * (this packet may be going in the opposite direction from the
813          * first packet in the conversation).
814          * (Neither "addr_a" nor "port_a" take part in this lookup.)
815          */
816         conversation =
817             conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
818               addr_b, addr_a, ptype, port_b, port_a);
819         if (conversation != NULL) {
820                 /*
821                  * If this is for a connection-oriented protocol, set the
822                  * second address for this conversation to address A, as
823                  * that's the address that matched the wildcarded second
824                  * address for this conversation, and set the second port
825                  * for this conversation to port A, as that's the port
826                  * that matched the wildcarded second port for this
827                  * conversation.
828                  */
829                 if (ptype != PT_UDP) {
830                         conversation_set_addr2(conversation, addr_a);
831                         conversation_set_port2(conversation, port_a);
832                 }
833                 return conversation;
834         }
835
836         /*
837          * We found no conversation.
838          */
839         return NULL;
840 }
841
842 static gint
843 p_compare(gconstpointer a, gconstpointer b)
844 {
845         if (((conv_proto_data *)a)->proto > ((conv_proto_data *)b)->proto)
846                 return 1;
847         else if (((conv_proto_data *)a)->proto == ((conv_proto_data *)b)->proto)
848                 return 0;
849         else
850                 return -1;
851 }
852
853 void
854 conversation_add_proto_data(conversation_t *conv, int proto, void *proto_data)
855 {
856         conv_proto_data *p1 = g_mem_chunk_alloc(conv_proto_data_area);
857
858         p1->proto = proto;
859         p1->proto_data = proto_data;
860
861         /* Add it to the list of items for this conversation. */
862
863         conv->data_list = g_slist_insert_sorted(conv->data_list, (gpointer *)p1,
864             p_compare);
865 }
866
867 void *
868 conversation_get_proto_data(conversation_t *conv, int proto)
869 {
870         conv_proto_data temp, *p1;
871         GSList *item;
872
873         temp.proto = proto;
874         temp.proto_data = NULL;
875
876         item = g_slist_find_custom(conv->data_list, (gpointer *)&temp,
877             p_compare);
878
879         if (item != NULL) {
880                 p1 = (conv_proto_data *)item->data;
881                 return p1->proto_data;
882         }
883
884         return NULL;
885 }
886
887 void
888 conversation_delete_proto_data(conversation_t *conv, int proto)
889 {
890         conv_proto_data temp;
891         GSList *item;
892
893         temp.proto = proto;
894         temp.proto_data = NULL;
895
896         item = g_slist_find_custom(conv->data_list, (gpointer *)&temp,
897             p_compare);
898
899         if (item != NULL)
900                 conv->data_list = g_slist_remove(conv->data_list, item);
901 }
902
903 void
904 conversation_set_dissector(conversation_t *conversation,
905     dissector_handle_t handle)
906 {
907         conversation->dissector_handle = handle;
908 }
909
910 /*
911  * Given two address/port pairs for a packet, search for a matching
912  * conversation and, if found and it has a conversation dissector,
913  * call that dissector and return TRUE, otherwise return FALSE.
914  */
915 gboolean
916 try_conversation_dissector(address *addr_a, address *addr_b, port_type ptype,
917     guint32 port_a, guint32 port_b, tvbuff_t *tvb, packet_info *pinfo,
918     proto_tree *tree)
919 {
920         conversation_t *conversation;
921         guint16 saved_can_desegment;
922
923         /* can_desegment is set to 2 by anyone which offers this api/service.
924            then everytime a subdissector is called it is decremented by one.
925            thus only the subdissector immediately ontop of whoever offers this
926            service can use it.
927         */
928         saved_can_desegment=pinfo->can_desegment;
929         pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
930
931         conversation = find_conversation(addr_a, addr_b, ptype, port_a,
932             port_b, 0);
933         
934         if (conversation != NULL) {
935                 if (conversation->dissector_handle == NULL){
936                         pinfo->can_desegment=saved_can_desegment;
937                         return FALSE;
938                 }
939                 call_dissector(conversation->dissector_handle, tvb, pinfo,
940                     tree);
941                 pinfo->can_desegment=saved_can_desegment;
942                 return TRUE;
943         }
944         pinfo->can_desegment=saved_can_desegment;
945         return FALSE;
946 }