Add tables of "conversation" dissectors, which are associated with
[obnox/wireshark/wip.git] / epan / packet.c
1 /* packet.c
2  * Routines for packet disassembly
3  *
4  * $Id: packet.c,v 1.12 2001/01/09 05:53:21 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/socket.h>
36 #endif
37
38 #ifdef HAVE_WINSOCK_H
39 #include <winsock.h>
40 #endif
41
42 #include <glib.h>
43
44 #include <stdio.h>
45 #include <stdlib.h>
46
47 #ifdef HAVE_STDARG_H
48 #include <stdarg.h>
49 #endif
50
51 #include <string.h>
52 #include <ctype.h>
53 #include <time.h>
54
55 #ifdef NEED_SNPRINTF_H
56 # include "snprintf.h"
57 #endif
58
59 #ifdef HAVE_NETINET_IN_H
60 # include <netinet/in.h>
61 #endif
62
63 #ifdef HAVE_ARPA_INET_H
64 #include <arpa/inet.h>
65 #endif
66
67 #ifdef NEED_INET_V6DEFS_H
68 # include "inet_v6defs.h"
69 #endif
70
71 #include "packet.h"
72 #include "print.h"
73 #include "timestamp.h"
74 #include "file.h"
75
76 #include "packet-atalk.h"
77 #include "packet-frame.h"
78 #include "packet-ipv6.h"
79 #include "packet-sna.h"
80 #include "packet-vines.h"
81
82 #include "resolv.h"
83 #include "tvbuff.h"
84 #include "plugins.h"
85
86 static void display_signed_time(gchar *, int, gint32, gint32);
87
88
89
90 /* Protocol-specific data attached to a frame_data structure - protocol
91    index and opaque pointer. */
92 typedef struct _frame_proto_data {
93   int proto;
94   void *proto_data;
95 } frame_proto_data;
96
97 static GMemChunk *frame_proto_data_area = NULL;
98
99
100 /* 
101  * Free up any space allocated for frame proto data areas and then 
102  * allocate a new area.
103  *
104  * We can free the area, as the structures it contains are pointed to by
105  * frames, that will be freed as well.
106  */
107 static void
108 packet_init_protocol(void)
109 {
110
111   if (frame_proto_data_area)
112     g_mem_chunk_destroy(frame_proto_data_area);
113
114   frame_proto_data_area = g_mem_chunk_new("frame_proto_data_area",
115                                           sizeof(frame_proto_data),
116                                           20 * sizeof(frame_proto_data), /* FIXME*/
117                                           G_ALLOC_ONLY);
118
119 }
120
121         
122 void
123 packet_init(void)
124 {
125         register_init_routine(&packet_init_protocol);
126 }
127
128 void
129 packet_cleanup(void)
130 {
131         /* nothing */
132 }
133
134 /* Wrapper for the most common case of asking
135  * for a string using a colon as the hex-digit separator.
136  */
137 gchar *
138 ether_to_str(const guint8 *ad)
139 {
140         return ether_to_str_punct(ad, ':');
141 }
142
143 /* Places char punct in the string as the hex-digit separator.
144  * If punct is '\0', no punctuation is applied (and thus
145  * the resulting string is 5 bytes shorter)
146  */
147 gchar *
148 ether_to_str_punct(const guint8 *ad, char punct) {
149   static gchar  str[3][18];
150   static gchar *cur;
151   gchar        *p;
152   int          i;
153   guint32      octet;
154   static const gchar hex_digits[16] = "0123456789abcdef";
155
156   if (cur == &str[0][0]) {
157     cur = &str[1][0];
158   } else if (cur == &str[1][0]) {  
159     cur = &str[2][0];
160   } else {  
161     cur = &str[0][0];
162   }
163   p = &cur[18];
164   *--p = '\0';
165   i = 5;
166   for (;;) {
167     octet = ad[i];
168     *--p = hex_digits[octet&0xF];
169     octet >>= 4;
170     *--p = hex_digits[octet&0xF];
171     if (i == 0)
172       break;
173     if (punct)
174       *--p = punct;
175     i--;
176   }
177   return p;
178 }
179
180 gchar *
181 ip_to_str(const guint8 *ad) {
182   static gchar  str[3][16];
183   static gchar *cur;
184   gchar        *p;
185   int           i;
186   guint32       octet;
187   guint32       digit;
188
189   if (cur == &str[0][0]) {
190     cur = &str[1][0];
191   } else if (cur == &str[1][0]) {  
192     cur = &str[2][0];
193   } else {  
194     cur = &str[0][0];
195   }
196   p = &cur[16];
197   *--p = '\0';
198   i = 3;
199   for (;;) {
200     octet = ad[i];
201     *--p = (octet%10) + '0';
202     octet /= 10;
203     digit = octet%10;
204     octet /= 10;
205     if (digit != 0 || octet != 0)
206       *--p = digit + '0';
207     if (octet != 0)
208       *--p = octet + '0';
209     if (i == 0)
210       break;
211     *--p = '.';
212     i--;
213   }
214   return p;
215 }
216
217 gchar *
218 ip6_to_str(struct e_in6_addr *ad) {
219 #ifndef INET6_ADDRSTRLEN
220 #define INET6_ADDRSTRLEN 46
221 #endif
222   static gchar buf[INET6_ADDRSTRLEN];
223
224   inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
225   return buf;
226 }
227
228
229 #define PLURALIZE(n)    (((n) > 1) ? "s" : "")
230 #define COMMA(do_it)    ((do_it) ? ", " : "")
231
232 gchar *
233 time_secs_to_str(guint32 time)
234 {
235   static gchar  str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
236   static gchar *cur, *p;
237   int hours, mins, secs;
238   int do_comma;
239
240   if (cur == &str[0][0]) {
241     cur = &str[1][0];
242   } else if (cur == &str[1][0]) {  
243     cur = &str[2][0];
244   } else {  
245     cur = &str[0][0];
246   }
247
248   if (time == 0) {
249     sprintf(cur, "0 time");
250     return cur;
251   }
252
253   secs = time % 60;
254   time /= 60;
255   mins = time % 60;
256   time /= 60;
257   hours = time % 24;
258   time /= 24;
259
260   p = cur;
261   if (time != 0) {
262     sprintf(p, "%u day%s", time, PLURALIZE(time));
263     p += strlen(p);
264     do_comma = 1;
265   } else
266     do_comma = 0;
267   if (hours != 0) {
268     sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
269     p += strlen(p);
270     do_comma = 1;
271   } else
272     do_comma = 0;
273   if (mins != 0) {
274     sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
275     p += strlen(p);
276     do_comma = 1;
277   } else
278     do_comma = 0;
279   if (secs != 0)
280     sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
281   return cur;
282 }
283
284 static const char *mon_names[12] = {
285         "Jan",
286         "Feb",
287         "Mar",
288         "Apr",
289         "May",
290         "Jun",
291         "Jul",
292         "Aug",
293         "Sep",
294         "Oct",
295         "Nov",
296         "Dec"
297 };
298
299 gchar *
300 abs_time_to_str(struct timeval *abs_time)
301 {
302         struct tm *tmp;
303         static gchar *cur;
304         static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
305
306         if (cur == &str[0][0]) {
307                 cur = &str[1][0];
308         } else if (cur == &str[1][0]) {
309                 cur = &str[2][0];
310         } else {
311                 cur = &str[0][0];
312         }
313
314         tmp = localtime(&abs_time->tv_sec);
315         sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
316             mon_names[tmp->tm_mon],
317             tmp->tm_mday,
318             tmp->tm_year + 1900,
319             tmp->tm_hour,
320             tmp->tm_min,
321             tmp->tm_sec,
322             (long)abs_time->tv_usec/100);
323
324         return cur;
325 }
326
327 #define REL_TIME_LEN    (1+10+1+6+1)
328
329 gchar *
330 rel_time_to_str(struct timeval *rel_time)
331 {
332         static gchar *cur;
333         static char str[3][REL_TIME_LEN];
334
335         if (cur == &str[0][0]) {
336                 cur = &str[1][0];
337         } else if (cur == &str[1][0]) {
338                 cur = &str[2][0];
339         } else {
340                 cur = &str[0][0];
341         }
342
343         display_signed_time(cur, REL_TIME_LEN, rel_time->tv_sec,
344             rel_time->tv_usec);
345         return cur;
346 }
347
348 static void
349 display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 usec)
350 {
351         char *sign;
352
353         /* If the microseconds part of the time stamp is negative,
354            print its absolute value and, if the seconds part isn't
355            (the seconds part should be zero in that case), stick
356            a "-" in front of the entire time stamp. */
357         sign = "";
358         if (usec < 0) {
359                 usec = -usec;
360                 if (sec >= 0)
361                         sign = "-";
362         }
363         snprintf(buf, buflen, "%s%d.%06d", sign, sec, usec);
364 }
365
366
367 /* Tries to match val against each element in the value_string array vs.
368    Returns the associated string ptr on a match.
369    Formats val with fmt, and returns the resulting string, on failure. */
370 gchar*
371 val_to_str(guint32 val, const value_string *vs, const char *fmt) {
372   gchar *ret;
373   static gchar  str[3][64];
374   static gchar *cur;
375
376   ret = match_strval(val, vs);
377   if (ret != NULL)
378     return ret;
379   if (cur == &str[0][0]) {
380     cur = &str[1][0];
381   } else if (cur == &str[1][0]) {  
382     cur = &str[2][0];
383   } else {  
384     cur = &str[0][0];
385   }
386   snprintf(cur, 64, fmt, val);
387   return cur;
388 }
389
390 /* Tries to match val against each element in the value_string array vs.
391    Returns the associated string ptr on a match, or NULL on failure. */
392 gchar*
393 match_strval(guint32 val, const value_string *vs) {
394   gint i = 0;
395   
396   while (vs[i].strptr) {
397     if (vs[i].value == val)
398       return(vs[i].strptr);
399     i++;
400   }
401
402   return(NULL);
403 }
404
405 /* Generate, into "buf", a string showing the bits of a bitfield.
406    Return a pointer to the character after that string. */
407 char *
408 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
409 {
410   int i;
411   guint32 bit;
412   char *p;
413
414   i = 0;
415   p = buf;
416   bit = 1 << (width - 1);
417   for (;;) {
418     if (mask & bit) {
419       /* This bit is part of the field.  Show its value. */
420       if (val & bit)
421         *p++ = '1';
422       else
423         *p++ = '0';
424     } else {
425       /* This bit is not part of the field. */
426       *p++ = '.';
427     }
428     bit >>= 1;
429     i++;
430     if (i >= width)
431       break;
432     if (i % 4 == 0)
433       *p++ = ' ';
434   }
435   strcpy(p, " = ");
436   p += 3;
437   return p;
438 }
439
440 /* Generate a string describing a Boolean bitfield (a one-bit field that
441    says something is either true of false). */
442 const char *
443 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
444     const char *truedesc, const char *falsedesc)
445 {
446   static char buf[1025];
447   char *p;
448
449   p = decode_bitfield_value(buf, val, mask, width);
450   if (val & mask)
451     strcpy(p, truedesc);
452   else
453     strcpy(p, falsedesc);
454   return buf;
455 }
456
457 /* Generate a string describing an enumerated bitfield (an N-bit field
458    with various specific values having particular names). */
459 const char *
460 decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
461     const value_string *tab, const char *fmt)
462 {
463   static char buf[1025];
464   char *p;
465
466   p = decode_bitfield_value(buf, val, mask, width);
467   sprintf(p, fmt, val_to_str(val & mask, tab, "Unknown"));
468   return buf;
469 }
470
471 /* Generate a string describing a numeric bitfield (an N-bit field whose
472    value is just a number). */
473 const char *
474 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
475     const char *fmt)
476 {
477   static char buf[1025];
478   char *p;
479   int shift = 0;
480
481   /* Compute the number of bits we have to shift the bitfield right
482      to extract its value. */
483   while ((mask & (1<<shift)) == 0)
484     shift++;
485
486   p = decode_bitfield_value(buf, val, mask, width);
487   sprintf(p, fmt, (val & mask) >> shift);
488   return buf;
489 }
490
491 /* Allocate all the data structures for constructing column data, given
492    the number of columns. */
493 void
494 col_init(column_info *col_info, gint num_cols)
495 {
496   col_info->num_cols    = num_cols;
497   col_info->col_fmt     = (gint *) g_malloc(sizeof(gint) * num_cols);
498   col_info->fmt_matx    = (gboolean **) g_malloc(sizeof(gboolean *) * num_cols);
499   col_info->col_width   = (gint *) g_malloc(sizeof(gint) * num_cols);
500   col_info->col_title   = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
501   col_info->col_data    = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
502   col_info->col_buf     = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
503 }
504
505 gboolean
506 col_get_writable(frame_data *fd)
507 {
508   if (fd) {
509
510     return (fd->cinfo ? fd->cinfo->writable : FALSE);
511
512   }
513
514   return FALSE;
515
516 }
517
518 void
519 col_set_writable(frame_data *fd, gboolean writable)
520 {
521         if (fd->cinfo) {
522                 fd->cinfo->writable = writable;
523         }
524 }
525
526 /* Checks to see if a particular packet information element is needed for
527    the packet list */
528 gint
529 check_col(frame_data *fd, gint el) {
530   int i;
531
532   if (fd->cinfo && fd->cinfo->writable) {
533     for (i = 0; i < fd->cinfo->num_cols; i++) {
534       if (fd->cinfo->fmt_matx[i][el])
535         return TRUE;
536     }
537   }
538   return FALSE;
539 }
540
541 /* Use this to clear out a column, especially if you're going to be
542    appending to it later; at least on some platforms, it's more
543    efficient than using "col_add_str()" with a null string, and
544    more efficient than "col_set_str()" with a null string if you
545    later append to it, as the later append will cause a string
546    copy to be done. */
547 void
548 col_clear(frame_data *fd, gint el) {
549   int    i;
550
551   for (i = 0; i < fd->cinfo->num_cols; i++) {
552     if (fd->cinfo->fmt_matx[i][el]) {
553       fd->cinfo->col_buf[i][0] = 0;
554       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
555     }
556   }
557 }
558
559 /* Use this if "str" points to something that will stay around (and thus
560    needn't be copied). */
561 void
562 col_set_str(frame_data *fd, gint el, gchar* str) {
563   int i;
564   
565   for (i = 0; i < fd->cinfo->num_cols; i++) {
566     if (fd->cinfo->fmt_matx[i][el])
567       fd->cinfo->col_data[i] = str;
568   }
569 }
570
571 /* Adds a vararg list to a packet info string. */
572 void
573 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
574   va_list ap;
575   int     i;
576   size_t  max_len;
577
578   if (el == COL_INFO)
579         max_len = COL_MAX_INFO_LEN;
580   else
581         max_len = COL_MAX_LEN;
582   
583   va_start(ap, format);
584   for (i = 0; i < fd->cinfo->num_cols; i++) {
585     if (fd->cinfo->fmt_matx[i][el]) {
586       vsnprintf(fd->cinfo->col_buf[i], max_len, format, ap);
587       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
588     }
589   }
590 }
591
592 /* Use this if "str" points to something that won't stay around (and
593    must thus be copied). */
594 void
595 col_add_str(frame_data *fd, gint el, const gchar* str) {
596   int    i;
597   size_t max_len;
598
599   if (el == COL_INFO)
600         max_len = COL_MAX_INFO_LEN;
601   else
602         max_len = COL_MAX_LEN;
603   
604   for (i = 0; i < fd->cinfo->num_cols; i++) {
605     if (fd->cinfo->fmt_matx[i][el]) {
606       strncpy(fd->cinfo->col_buf[i], str, max_len);
607       fd->cinfo->col_buf[i][max_len - 1] = 0;
608       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
609     }
610   }
611 }
612
613 /* Appends a vararg list to a packet info string. */
614 void
615 col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
616   va_list ap;
617   int     i;
618   size_t  len, max_len;
619   
620   if (el == COL_INFO)
621         max_len = COL_MAX_INFO_LEN;
622   else
623         max_len = COL_MAX_LEN;
624   
625   va_start(ap, format);
626   for (i = 0; i < fd->cinfo->num_cols; i++) {
627     if (fd->cinfo->fmt_matx[i][el]) {
628       if (fd->cinfo->col_data[i] != fd->cinfo->col_buf[i]) {
629         /* This was set with "col_set_str()"; copy the string they
630            set it to into the buffer, so we can append to it. */
631         strncpy(fd->cinfo->col_buf[i], fd->cinfo->col_data[i], max_len);
632         fd->cinfo->col_buf[i][max_len - 1] = '\0';
633       }
634       len = strlen(fd->cinfo->col_buf[i]);
635       vsnprintf(&fd->cinfo->col_buf[i][len], max_len - len, format, ap);
636       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
637     }
638   }
639 }
640
641 void
642 col_append_str(frame_data *fd, gint el, gchar* str) {
643   int    i;
644   size_t len, max_len;
645
646   if (el == COL_INFO)
647         max_len = COL_MAX_INFO_LEN;
648   else
649         max_len = COL_MAX_LEN;
650   
651   for (i = 0; i < fd->cinfo->num_cols; i++) {
652     if (fd->cinfo->fmt_matx[i][el]) {
653       if (fd->cinfo->col_data[i] != fd->cinfo->col_buf[i]) {
654         /* This was set with "col_set_str()"; copy the string they
655            set it to into the buffer, so we can append to it. */
656         strncpy(fd->cinfo->col_buf[i], fd->cinfo->col_data[i], max_len);
657         fd->cinfo->col_buf[i][max_len - 1] = '\0';
658       }
659       len = strlen(fd->cinfo->col_buf[i]);
660       strncat(fd->cinfo->col_buf[i], str, max_len - len);
661       fd->cinfo->col_buf[i][max_len - 1] = 0;
662       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
663     }
664   }
665 }
666
667 /* To do: Add check_col checks to the col_add* routines */
668
669 static void
670 col_set_abs_time(frame_data *fd, int col)
671 {
672   struct tm *tmp;
673   time_t then;
674
675   then = fd->abs_secs;
676   tmp = localtime(&then);
677   snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
678     tmp->tm_hour,
679     tmp->tm_min,
680     tmp->tm_sec,
681     (long)fd->abs_usecs/100);
682   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
683 }
684
685 static void
686 col_set_abs_date_time(frame_data *fd, int col)
687 {
688   struct tm *tmp;
689   time_t then;
690
691   then = fd->abs_secs;
692   tmp = localtime(&then);
693   snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN,
694     "%04d-%02d-%02d %02d:%02d:%02d.%04ld",
695     tmp->tm_year + 1900,
696     tmp->tm_mon + 1,
697     tmp->tm_mday,
698     tmp->tm_hour,
699     tmp->tm_min,
700     tmp->tm_sec,
701     (long)fd->abs_usecs/100);
702   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
703 }
704
705 static void
706 col_set_rel_time(frame_data *fd, int col)
707 {
708   display_signed_time(fd->cinfo->col_buf[col], COL_MAX_LEN,
709         fd->rel_secs, fd->rel_usecs);
710   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
711 }
712
713 static void
714 col_set_delta_time(frame_data *fd, int col)
715 {
716   display_signed_time(fd->cinfo->col_buf[col], COL_MAX_LEN,
717         fd->del_secs, fd->del_usecs);
718   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
719 }
720
721 /* Add "command-line-specified" time.
722    XXX - this is called from "file.c" when the user changes the time
723    format they want for "command-line-specified" time; it's a bit ugly
724    that we have to export it, but if we go to a CList-like widget that
725    invokes callbacks to get the text for the columns rather than
726    requiring us to stuff the text into the widget from outside, we
727    might be able to clean this up. */
728 void
729 col_set_cls_time(frame_data *fd, int col)
730 {
731   switch (timestamp_type) {
732     case ABSOLUTE:
733       col_set_abs_time(fd, col);
734       break;
735
736     case ABSOLUTE_WITH_DATE:
737       col_set_abs_date_time(fd, col);
738       break;
739
740     case RELATIVE:
741       col_set_rel_time(fd, col);
742       break;
743
744     case DELTA:
745       col_set_delta_time(fd, col);
746       break;
747   }
748 }
749
750 static void
751 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
752 {
753   u_int ipv4_addr;
754   struct e_in6_addr ipv6_addr;
755   struct atalk_ddp_addr ddp_addr;
756   struct sna_fid_type_4_addr sna_fid_type_4_addr;
757
758   switch (addr->type) {
759
760   case AT_ETHER:
761     if (is_res)
762       strncpy(fd->cinfo->col_buf[col], get_ether_name(addr->data), COL_MAX_LEN);
763     else
764       strncpy(fd->cinfo->col_buf[col], ether_to_str(addr->data), COL_MAX_LEN);
765     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
766     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
767     break;
768
769   case AT_IPv4:
770     memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
771     if (is_res)
772       strncpy(fd->cinfo->col_buf[col], get_hostname(ipv4_addr), COL_MAX_LEN);
773     else
774       strncpy(fd->cinfo->col_buf[col], ip_to_str(addr->data), COL_MAX_LEN);
775     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
776     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
777     break;
778
779   case AT_IPv6:
780     memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
781     if (is_res)
782       strncpy(fd->cinfo->col_buf[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
783     else
784       strncpy(fd->cinfo->col_buf[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
785     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
786     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
787     break;
788
789   case AT_IPX:
790     strncpy(fd->cinfo->col_buf[col],
791       ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
792     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
793     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
794     break;
795
796   case AT_SNA:
797     switch (addr->len) {
798
799     case 1:
800       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%04X", addr->data[0]);
801       break;
802
803     case 2:
804       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%04X",
805         pntohs(&addr->data[0]));
806       break;
807
808     case SNA_FID_TYPE_4_ADDR_LEN:
809       memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
810       strncpy(fd->cinfo->col_buf[col],
811         sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
812       break;
813     }
814     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
815     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
816     break;
817
818   case AT_ATALK:
819     memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
820     strncpy(fd->cinfo->col_buf[col], atalk_addr_to_str(&ddp_addr),
821       COL_MAX_LEN);
822     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
823     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
824     break;
825
826   case AT_VINES:
827     strncpy(fd->cinfo->col_buf[col], vines_addr_to_str(&addr->data[0]),
828       COL_MAX_LEN);
829     fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
830     fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
831     break;
832
833   default:
834     break;
835   }
836 }
837
838 static void
839 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
840                 gboolean is_res)
841 {
842   switch (ptype) {
843
844   case PT_SCTP:
845     if (is_res)
846       strncpy(fd->cinfo->col_buf[col], get_sctp_port(port), COL_MAX_LEN);
847     else
848       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
849     break;
850     
851   case PT_TCP:
852     if (is_res)
853       strncpy(fd->cinfo->col_buf[col], get_tcp_port(port), COL_MAX_LEN);
854     else
855       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
856     break;
857
858   case PT_UDP:
859     if (is_res)
860       strncpy(fd->cinfo->col_buf[col], get_udp_port(port), COL_MAX_LEN);
861     else
862       snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
863     break;
864
865   default:
866     break;
867   }
868   fd->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
869   fd->cinfo->col_data[col] = fd->cinfo->col_buf[col];
870 }
871
872 void
873 fill_in_columns(frame_data *fd)
874 {
875   int i;
876
877   for (i = 0; i < fd->cinfo->num_cols; i++) {
878     switch (fd->cinfo->col_fmt[i]) {
879
880     case COL_NUMBER:
881       snprintf(fd->cinfo->col_buf[i], COL_MAX_LEN, "%u", fd->num);
882       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
883       break;
884
885     case COL_CLS_TIME:
886       col_set_cls_time(fd, i);
887       break;
888
889     case COL_ABS_TIME:
890       col_set_abs_time(fd, i);
891       break;
892
893     case COL_ABS_DATE_TIME:
894       col_set_abs_date_time(fd, i);
895       break;
896
897     case COL_REL_TIME:
898       col_set_rel_time(fd, i);
899       break;
900
901     case COL_DELTA_TIME:
902       col_set_delta_time(fd, i);
903       break;
904
905     case COL_DEF_SRC:
906     case COL_RES_SRC:   /* COL_DEF_SRC is currently just like COL_RES_SRC */
907       col_set_addr(fd, i, &pi.src, TRUE);
908       break;
909
910     case COL_UNRES_SRC:
911       col_set_addr(fd, i, &pi.src, FALSE);
912       break;
913
914     case COL_DEF_DL_SRC:
915     case COL_RES_DL_SRC:
916       col_set_addr(fd, i, &pi.dl_src, TRUE);
917       break;
918
919     case COL_UNRES_DL_SRC:
920       col_set_addr(fd, i, &pi.dl_src, FALSE);
921       break;
922
923     case COL_DEF_NET_SRC:
924     case COL_RES_NET_SRC:
925       col_set_addr(fd, i, &pi.net_src, TRUE);
926       break;
927
928     case COL_UNRES_NET_SRC:
929       col_set_addr(fd, i, &pi.net_src, FALSE);
930       break;
931
932     case COL_DEF_DST:
933     case COL_RES_DST:   /* COL_DEF_DST is currently just like COL_RES_DST */
934       col_set_addr(fd, i, &pi.dst, TRUE);
935       break;
936
937     case COL_UNRES_DST:
938       col_set_addr(fd, i, &pi.dst, FALSE);
939       break;
940
941     case COL_DEF_DL_DST:
942     case COL_RES_DL_DST:
943       col_set_addr(fd, i, &pi.dl_dst, TRUE);
944       break;
945
946     case COL_UNRES_DL_DST:
947       col_set_addr(fd, i, &pi.dl_dst, FALSE);
948       break;
949
950     case COL_DEF_NET_DST:
951     case COL_RES_NET_DST:
952       col_set_addr(fd, i, &pi.net_dst, TRUE);
953       break;
954
955     case COL_UNRES_NET_DST:
956       col_set_addr(fd, i, &pi.net_dst, FALSE);
957       break;
958
959     case COL_DEF_SRC_PORT:
960     case COL_RES_SRC_PORT:      /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
961       col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
962       break;
963
964     case COL_UNRES_SRC_PORT:
965       col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
966       break;
967
968     case COL_DEF_DST_PORT:
969     case COL_RES_DST_PORT:      /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
970       col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
971       break;
972
973     case COL_UNRES_DST_PORT:
974       col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
975       break;
976
977     case COL_PROTOCOL:  /* currently done by dissectors */
978     case COL_INFO:      /* currently done by dissectors */
979       break;
980
981     case COL_PACKET_LENGTH:
982       snprintf(fd->cinfo->col_buf[i], COL_MAX_LEN, "%d", fd->pkt_len);
983       fd->cinfo->col_data[i] = fd->cinfo->col_buf[i];
984       break;
985
986     case NUM_COL_FMTS:  /* keep compiler happy - shouldn't get here */
987       break;
988     }
989   }
990 }
991         
992 void blank_packetinfo(void)
993 {
994   pi.dl_src.type = AT_NONE;
995   pi.dl_dst.type = AT_NONE;
996   pi.net_src.type = AT_NONE;
997   pi.net_dst.type = AT_NONE;
998   pi.src.type = AT_NONE;
999   pi.dst.type = AT_NONE;
1000   pi.ipproto  = 0;
1001   pi.ptype = PT_NONE;
1002   pi.srcport  = 0;
1003   pi.destport = 0;
1004   pi.current_proto = "<Missing Protocol Name>";
1005   pi.p2p_dir = P2P_DIR_UNKNOWN;
1006 }
1007
1008
1009 /* Allow protocols to register "init" routines, which are called before
1010    we make a pass through a capture file and dissect all its packets
1011    (e.g., when we read in a new capture file, or run a "filter packets"
1012    or "colorize packets" pass over the current capture file). */
1013 static GSList *init_routines;
1014
1015 void
1016 register_init_routine(void (*func)(void))
1017 {
1018         init_routines = g_slist_append(init_routines, func);
1019 }
1020
1021 /* Call all the registered "init" routines. */
1022 static void
1023 call_init_routine(gpointer routine, gpointer dummy)
1024 {
1025         void (*func)(void) = routine;
1026
1027         (*func)();
1028 }
1029
1030 void
1031 init_all_protocols(void)
1032 {
1033         g_slist_foreach(init_routines, &call_init_routine, NULL);
1034 }
1035
1036 /* Creates the top-most tvbuff and calls dissect_frame() */
1037 void
1038 dissect_packet(tvbuff_t **p_tvb, union wtap_pseudo_header *pseudo_header,
1039                 const u_char *pd, frame_data *fd, proto_tree *tree)
1040 {
1041         blank_packetinfo();
1042
1043         /* Set the initial payload to the packet length, and the initial
1044            captured payload to the capture length (other protocols may
1045            reduce them if their headers say they're less). */
1046         pi.len = fd->pkt_len;
1047         pi.captured_len = fd->cap_len;
1048
1049         pi.fd = fd;
1050         pi.pseudo_header = pseudo_header;
1051
1052         col_set_writable(fd, TRUE);
1053
1054         TRY {
1055                 *p_tvb = tvb_new_real_data(pd, fd->cap_len, fd->pkt_len);
1056                 pi.compat_top_tvb = *p_tvb;
1057         }
1058         CATCH(BoundsError) {
1059                 g_assert_not_reached();
1060         }
1061         CATCH(ReportedBoundsError) {
1062                 proto_tree_add_protocol_format(tree, proto_malformed, *p_tvb, 0, 0,
1063                                 "[Malformed Frame: Packet Length]" );
1064         }
1065         ENDTRY;
1066
1067         dissect_frame(*p_tvb, &pi, tree);
1068
1069         fd->flags.visited = 1;
1070 }
1071
1072
1073
1074 gint p_compare(gconstpointer a, gconstpointer b)
1075 {
1076
1077   if (((frame_proto_data *)a) -> proto > ((frame_proto_data *)b) -> proto)
1078     return 1;
1079   else if (((frame_proto_data *)a) -> proto == ((frame_proto_data *)b) -> proto)
1080     return 0;
1081   else
1082     return -1;
1083
1084 }
1085
1086 void
1087 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
1088 {
1089   frame_proto_data *p1 = g_mem_chunk_alloc(frame_proto_data_area);
1090  
1091   g_assert(p1 != NULL);
1092
1093   p1 -> proto = proto;
1094   p1 -> proto_data = proto_data;
1095
1096   /* Add it to the GSLIST */
1097
1098   fd -> pfd = g_slist_insert_sorted(fd -> pfd,
1099                                     (gpointer *)p1,
1100                                     p_compare);
1101
1102 }
1103
1104 void *
1105 p_get_proto_data(frame_data *fd, int proto)
1106 {
1107   frame_proto_data temp, *p1;
1108   GSList *item;
1109
1110   temp.proto = proto;
1111   temp.proto_data = NULL;
1112
1113   item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
1114
1115   if (item) {
1116     p1 = (frame_proto_data *)item->data;
1117     return p1->proto_data;
1118   }
1119
1120   return NULL;
1121
1122 }
1123
1124 void
1125 p_rem_proto_data(frame_data *fd, int proto)
1126 {
1127   frame_proto_data temp;
1128   GSList *item;
1129
1130   temp.proto = proto;
1131   temp.proto_data = NULL;
1132
1133   item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
1134
1135   if (item) {
1136
1137     fd->pfd = g_slist_remove(fd->pfd, item);
1138
1139   }
1140
1141 }
1142
1143
1144 /*********************** code added for sub-dissector lookup *********************/
1145
1146 static GHashTable *dissector_tables = NULL;
1147
1148 /*
1149  * XXX - for now, we support having both "old" dissectors, with packet
1150  * data pointer, packet offset, frame_data pointer, and protocol tree
1151  * pointer arguments, and "new" dissectors, with tvbuff pointer,
1152  * packet_info pointer, and protocol tree pointer arguments.
1153  *
1154  * Nuke this and go back to storing a pointer to the dissector when
1155  * the last old-style dissector is gone.
1156  */
1157 typedef struct {
1158         gboolean is_old_dissector;
1159         union {
1160                 old_dissector_t old;
1161                 dissector_t     new;
1162         } dissector;
1163 } dtbl_entry_t;
1164
1165 /* Finds a dissector table by field name. */
1166 static dissector_table_t
1167 find_dissector_table(const char *name)
1168 {
1169         g_assert(dissector_tables);
1170         return g_hash_table_lookup( dissector_tables, name );
1171 }
1172
1173 /* add an entry, lookup the dissector table for the specified field name,  */
1174 /* if a valid table found, add the subdissector */
1175 void
1176 old_dissector_add(const char *name, guint32 pattern, old_dissector_t dissector)
1177 {
1178         dissector_table_t sub_dissectors = find_dissector_table( name);
1179         dtbl_entry_t *dtbl_entry;
1180
1181 /* sanity check */
1182         g_assert( sub_dissectors);
1183
1184         dtbl_entry = g_malloc(sizeof (dtbl_entry_t));
1185         dtbl_entry->is_old_dissector = TRUE;
1186         dtbl_entry->dissector.old = dissector;
1187
1188 /* do the table insertion */
1189         g_hash_table_insert( sub_dissectors, GUINT_TO_POINTER( pattern),
1190          (gpointer)dtbl_entry);
1191 }
1192
1193 void
1194 dissector_add(const char *name, guint32 pattern, dissector_t dissector)
1195 {
1196         dissector_table_t sub_dissectors = find_dissector_table( name);
1197         dtbl_entry_t *dtbl_entry;
1198
1199 /* sanity check */
1200         g_assert( sub_dissectors);
1201
1202         dtbl_entry = g_malloc(sizeof (dtbl_entry_t));
1203         dtbl_entry->is_old_dissector = FALSE;
1204         dtbl_entry->dissector.new = dissector;
1205
1206 /* do the table insertion */
1207         g_hash_table_insert( sub_dissectors, GUINT_TO_POINTER( pattern),
1208          (gpointer)dtbl_entry);
1209 }
1210
1211 /* delete the entry for this dissector at this pattern */
1212
1213 /* NOTE: this doesn't use the dissector call variable. It is included to */
1214 /*      be consistant with the dissector_add and more importantly to be used */
1215 /*      if the technique of adding a temporary dissector is implemented.  */
1216 /*      If temporary dissectors are deleted, then the original dissector must */
1217 /*      be available. */
1218 void
1219 old_dissector_delete(const char *name, guint32 pattern, old_dissector_t dissector)
1220 {
1221         dissector_table_t sub_dissectors = find_dissector_table( name);
1222         dtbl_entry_t *dtbl_entry;
1223
1224 /* sanity check */
1225         g_assert( sub_dissectors);
1226
1227         /*
1228          * Find the entry.
1229          */
1230         dtbl_entry = g_hash_table_lookup(sub_dissectors,
1231             GUINT_TO_POINTER(pattern));
1232
1233         if (dtbl_entry != NULL) {
1234                 /*
1235                  * Found - remove it.
1236                  */
1237                 g_hash_table_remove(sub_dissectors, GUINT_TO_POINTER(pattern));
1238
1239                 /*
1240                  * Now free up the entry.
1241                  */
1242                 g_free(dtbl_entry);
1243         }
1244 }
1245
1246 void
1247 dissector_delete(const char *name, guint32 pattern, dissector_t dissector)
1248 {
1249         dissector_table_t sub_dissectors = find_dissector_table( name);
1250         dtbl_entry_t *dtbl_entry;
1251
1252 /* sanity check */
1253         g_assert( sub_dissectors);
1254
1255         /*
1256          * Find the entry.
1257          */
1258         dtbl_entry = g_hash_table_lookup(sub_dissectors,
1259             GUINT_TO_POINTER(pattern));
1260
1261         if (dtbl_entry != NULL) {
1262                 /*
1263                  * Found - remove it.
1264                  */
1265                 g_hash_table_remove(sub_dissectors, GUINT_TO_POINTER(pattern));
1266
1267                 /*
1268                  * Now free up the entry.
1269                  */
1270                 g_free(dtbl_entry);
1271         }
1272 }
1273
1274 /* Look for a given port in a given dissector table and, if found, call
1275    the dissector with the arguments supplied, and return TRUE, otherwise
1276    return FALSE.
1277
1278    If the arguments supplied don't match the arguments to the dissector,
1279    do the appropriate translation. */
1280 gboolean
1281 old_dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
1282     const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1283 {
1284         dtbl_entry_t *dtbl_entry;
1285         tvbuff_t *tvb;
1286
1287         dtbl_entry = g_hash_table_lookup(sub_dissectors,
1288             GUINT_TO_POINTER(port));
1289         if (dtbl_entry != NULL) {
1290                 pi.match_port = port;
1291                 if (dtbl_entry->is_old_dissector)
1292                         (*dtbl_entry->dissector.old)(pd, offset, fd, tree);
1293                 else {
1294                         /*
1295                          * Old dissector calling new dissector; use
1296                          * "tvb_create_from_top()" to remap.
1297                          *
1298                          * XXX - what about the "pd" argument?  Do
1299                          * any dissectors not just pass that along and
1300                          * let the "offset" argument handle stepping
1301                          * through the packet?
1302                          */
1303                         tvb = tvb_create_from_top(offset);
1304                         (*dtbl_entry->dissector.new)(tvb, &pi, tree);
1305                 }
1306                 return TRUE;
1307         } else
1308                 return FALSE;
1309 }
1310
1311 gboolean
1312 dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
1313     tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1314 {
1315         dtbl_entry_t *dtbl_entry;
1316         const guint8 *pd;
1317         int offset;
1318
1319         dtbl_entry = g_hash_table_lookup(sub_dissectors,
1320             GUINT_TO_POINTER(port));
1321         if (dtbl_entry != NULL) {
1322                 pi.match_port = port;
1323                 if (dtbl_entry->is_old_dissector) {
1324                         /*
1325                          * New dissector calling old dissector; use
1326                          * "tvb_compat()" to remap.
1327                          */
1328                         tvb_compat(tvb, &pd, &offset);
1329                         (*dtbl_entry->dissector.old)(pd, offset, pinfo->fd,
1330                             tree);
1331                 } else
1332                         (*dtbl_entry->dissector.new)(tvb, pinfo, tree);
1333                 return TRUE;
1334         } else
1335                 return FALSE;
1336 }
1337
1338 dissector_table_t
1339 register_dissector_table(const char *name)
1340 {
1341         dissector_table_t       sub_dissectors;
1342
1343         /* Create our hash-of-hashes if it doesn't already exist */
1344         if (!dissector_tables) {
1345                 dissector_tables = g_hash_table_new( g_str_hash, g_str_equal );
1346                 g_assert(dissector_tables);
1347         }
1348
1349         /* Make sure the registration is unique */
1350         g_assert(!g_hash_table_lookup( dissector_tables, name ));
1351
1352         /* Create and register the dissector table for this name; returns */
1353         /* a pointer to the dissector table. */
1354         sub_dissectors = g_hash_table_new( g_direct_hash, g_direct_equal );
1355         g_hash_table_insert( dissector_tables, (gpointer)name, (gpointer) sub_dissectors );
1356         return sub_dissectors;
1357 }
1358
1359 static GHashTable *heur_dissector_lists = NULL;
1360
1361 /*
1362  * XXX - for now, we support having both "old" dissectors, with packet
1363  * data pointer, packet offset, frame_data pointer, and protocol tree
1364  * pointer arguments, and "new" dissectors, with tvbuff pointer,
1365  * packet_info pointer, and protocol tree pointer arguments.
1366  *
1367  * Nuke this and go back to storing a pointer to the dissector when
1368  * the last old-style dissector is gone.
1369  */
1370 typedef struct {
1371         gboolean is_old_dissector;
1372         union {
1373                 old_heur_dissector_t    old;
1374                 heur_dissector_t        new;
1375         } dissector;
1376 } heur_dtbl_entry_t;
1377
1378 /* Finds a heuristic dissector table by field name. */
1379 static heur_dissector_list_t *
1380 find_heur_dissector_list(const char *name)
1381 {
1382         g_assert(heur_dissector_lists != NULL);
1383         return g_hash_table_lookup(heur_dissector_lists, name);
1384 }
1385
1386 void
1387 old_heur_dissector_add(const char *name, old_heur_dissector_t dissector)
1388 {
1389         heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
1390         heur_dtbl_entry_t *dtbl_entry;
1391
1392         /* sanity check */
1393         g_assert(sub_dissectors != NULL);
1394
1395         dtbl_entry = g_malloc(sizeof (heur_dtbl_entry_t));
1396         dtbl_entry->is_old_dissector = TRUE;
1397         dtbl_entry->dissector.old = dissector;
1398
1399         /* do the table insertion */
1400         *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)dtbl_entry);
1401 }
1402
1403 void
1404 heur_dissector_add(const char *name, heur_dissector_t dissector)
1405 {
1406         heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
1407         heur_dtbl_entry_t *dtbl_entry;
1408
1409         /* sanity check */
1410         g_assert(sub_dissectors != NULL);
1411
1412         dtbl_entry = g_malloc(sizeof (heur_dtbl_entry_t));
1413         dtbl_entry->is_old_dissector = FALSE;
1414         dtbl_entry->dissector.new = dissector;
1415
1416         /* do the table insertion */
1417         *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)dtbl_entry);
1418 }
1419
1420 gboolean
1421 dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
1422     tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1423 {
1424         GSList *entry;
1425         heur_dtbl_entry_t *dtbl_entry;
1426         const guint8 *pd = NULL;
1427         int offset;
1428
1429         for (entry = sub_dissectors; entry != NULL; entry = g_slist_next(entry)) {
1430                 dtbl_entry = (heur_dtbl_entry_t *)entry->data;
1431                 if (dtbl_entry->is_old_dissector) {
1432                         /*
1433                          * New dissector calling old dissector; use
1434                          * "tvb_compat()" to remap.
1435                          */
1436                         if (pd == NULL)
1437                                 tvb_compat(tvb, &pd, &offset);
1438                         if ((*dtbl_entry->dissector.old)(pd, offset, pinfo->fd,
1439                             tree))
1440                                 return TRUE;
1441                 } else {
1442                         if ((*dtbl_entry->dissector.new)(tvb, pinfo, tree))
1443                                 return TRUE;
1444                 }
1445         }
1446         return FALSE;
1447 }
1448
1449 void
1450 register_heur_dissector_list(const char *name, heur_dissector_list_t *sub_dissectors)
1451 {
1452         /* Create our hash-of-lists if it doesn't already exist */
1453         if (heur_dissector_lists == NULL) {
1454                 heur_dissector_lists = g_hash_table_new(g_str_hash, g_str_equal);
1455                 g_assert(heur_dissector_lists != NULL);
1456         }
1457
1458         /* Make sure the registration is unique */
1459         g_assert(g_hash_table_lookup(heur_dissector_lists, name) == NULL);
1460
1461         *sub_dissectors = NULL; /* initially empty */
1462         g_hash_table_insert(heur_dissector_lists, (gpointer)name,
1463             (gpointer) sub_dissectors);
1464 }
1465
1466 static GHashTable *conv_dissector_lists = NULL;
1467
1468 /*
1469  * XXX - for now, we support having both "old" dissectors, with packet
1470  * data pointer, packet offset, frame_data pointer, and protocol tree
1471  * pointer arguments, and "new" dissectors, with tvbuff pointer,
1472  * packet_info pointer, and protocol tree pointer arguments.
1473  *
1474  * Nuke this and go back to storing a pointer to the dissector when
1475  * the last old-style dissector is gone.
1476  */
1477 typedef struct {
1478         gboolean is_old_dissector;
1479         union {
1480                 old_dissector_t old;
1481                 dissector_t     new;
1482         } dissector;
1483 } conv_dtbl_entry_t;
1484
1485 /* Finds a conversation dissector table by table name. */
1486 static conv_dissector_list_t *
1487 find_conv_dissector_list(const char *name)
1488 {
1489         g_assert(conv_dissector_lists != NULL);
1490         return g_hash_table_lookup(conv_dissector_lists, name);
1491 }
1492
1493 void
1494 old_conv_dissector_add(const char *name, old_dissector_t dissector)
1495 {
1496         conv_dissector_list_t *sub_dissectors = find_conv_dissector_list(name);
1497         conv_dtbl_entry_t *dtbl_entry;
1498
1499         /* sanity check */
1500         g_assert(sub_dissectors != NULL);
1501
1502         dtbl_entry = g_malloc(sizeof (conv_dtbl_entry_t));
1503         dtbl_entry->is_old_dissector = TRUE;
1504         dtbl_entry->dissector.old = dissector;
1505
1506         /* do the table insertion */
1507         *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)dtbl_entry);
1508 }
1509
1510 void
1511 conv_dissector_add(const char *name, dissector_t dissector)
1512 {
1513         conv_dissector_list_t *sub_dissectors = find_conv_dissector_list(name);
1514         conv_dtbl_entry_t *dtbl_entry;
1515
1516         /* sanity check */
1517         g_assert(sub_dissectors != NULL);
1518
1519         dtbl_entry = g_malloc(sizeof (conv_dtbl_entry_t));
1520         dtbl_entry->is_old_dissector = FALSE;
1521         dtbl_entry->dissector.new = dissector;
1522
1523         /* do the table insertion */
1524         *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)dtbl_entry);
1525 }
1526
1527 void
1528 register_conv_dissector_list(const char *name, conv_dissector_list_t *sub_dissectors)
1529 {
1530         /* Create our hash-of-lists if it doesn't already exist */
1531         if (conv_dissector_lists == NULL) {
1532                 conv_dissector_lists = g_hash_table_new(g_str_hash, g_str_equal);
1533                 g_assert(conv_dissector_lists != NULL);
1534         }
1535
1536         /* Make sure the registration is unique */
1537         g_assert(g_hash_table_lookup(conv_dissector_lists, name) == NULL);
1538
1539         *sub_dissectors = NULL; /* initially empty */
1540         g_hash_table_insert(conv_dissector_lists, (gpointer)name,
1541             (gpointer) sub_dissectors);
1542 }
1543
1544 /*
1545  * Register dissectors by name; used if one dissector always calls a
1546  * particular dissector, or if it bases the decision of which dissector
1547  * to call on something other than a numerical value or on "try a bunch
1548  * of dissectors until one likes the packet".
1549  */
1550
1551 /*
1552  * List of registered dissectors.
1553  */
1554 static GHashTable *registered_dissectors = NULL;
1555
1556 /*
1557  * An entry in the list of registered dissectors.
1558  */
1559 struct dissector_handle {
1560         const char      *name;          /* dissector name */
1561         dissector_t     dissector;
1562 };
1563
1564 /* Find a registered dissector by name. */
1565 dissector_handle_t
1566 find_dissector(const char *name)
1567 {
1568         g_assert(registered_dissectors != NULL);
1569         return g_hash_table_lookup(registered_dissectors, name);
1570 }
1571
1572 /* Register a dissector by name. */
1573 void
1574 register_dissector(const char *name, dissector_t dissector)
1575 {
1576         struct dissector_handle *handle;
1577
1578         /* Create our hash table if it doesn't already exist */
1579         if (registered_dissectors == NULL) {
1580                 registered_dissectors = g_hash_table_new(g_str_hash, g_str_equal);
1581                 g_assert(registered_dissectors != NULL);
1582         }
1583
1584         /* Make sure the registration is unique */
1585         g_assert(g_hash_table_lookup(registered_dissectors, name) == NULL);
1586
1587         handle = g_malloc(sizeof (struct dissector_handle));
1588         handle->name = name;
1589         handle->dissector = dissector;
1590         
1591         g_hash_table_insert(registered_dissectors, (gpointer)name,
1592             (gpointer) handle);
1593 }
1594
1595 /* Call a dissector through a handle. */
1596 void
1597 old_call_dissector(dissector_handle_t handle, const u_char *pd,
1598     int offset, frame_data *fd, proto_tree *tree)
1599 {
1600         tvbuff_t *tvb;
1601
1602         /*
1603          * Old dissector calling new dissector; use
1604          * "tvb_create_from_top()" to remap.
1605          *
1606          * XXX - what about the "pd" argument?  Do
1607          * any dissectors not just pass that along and
1608          * let the "offset" argument handle stepping
1609          * through the packet?
1610          */
1611         tvb = tvb_create_from_top(offset);
1612         (*handle->dissector)(tvb, &pi, tree);
1613 }
1614
1615 void
1616 call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
1617     packet_info *pinfo, proto_tree *tree)
1618 {
1619         (*handle->dissector)(tvb, pinfo, tree);
1620 }