First pass at per frame proto data. Keep each proto block as a GSList list.
[obnox/wireshark/wip.git] / packet.c
1 /* packet.c
2  * Routines for packet disassembly
3  *
4  * $Id: packet.c,v 1.67 2000/03/26 06:57:40 sharpe 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 <stdarg.h>
46 #include <string.h>
47 #include <ctype.h>
48 #include <time.h>
49
50 #ifdef NEED_SNPRINTF_H
51 # include "snprintf.h"
52 #endif
53
54 #ifdef HAVE_NETINET_IN_H
55 # include <netinet/in.h>
56 #endif
57
58 #ifdef HAVE_ARPA_INET_H
59 #include <arpa/inet.h>
60 #endif
61
62 #ifdef NEED_INET_V6DEFS_H
63 # include "inet_v6defs.h"
64 #endif
65
66 #include "packet.h"
67 #include "print.h"
68 #include "timestamp.h"
69 #include "file.h"
70
71 #include "packet-ascend.h"
72 #include "packet-atalk.h"
73 #include "packet-atm.h"
74 #include "packet-clip.h"
75 #include "packet-eth.h"
76 #include "packet-fddi.h"
77 #include "packet-ipv6.h"
78 #include "packet-lapb.h"
79 #include "packet-lapd.h"
80 #include "packet-null.h"
81 #include "packet-ppp.h"
82 #include "packet-raw.h"
83 #include "packet-sna.h"
84 #include "packet-tr.h"
85 #include "packet-v120.h"
86 #include "packet-vines.h"
87
88 #ifndef __RESOLV_H__
89 #include "resolv.h"
90 #endif
91
92 extern capture_file  cf;
93
94 static int proto_frame = -1;
95 static int hf_frame_arrival_time = -1;
96 static int hf_frame_time_delta = -1;
97 static int hf_frame_number = -1;
98 static int hf_frame_packet_len = -1;
99 static int hf_frame_capture_len = -1;
100
101 static gint ett_frame = -1;
102
103 /* Wrapper for the most common case of asking
104  * for a string using a colon as the hex-digit separator.
105  */
106 gchar *
107 ether_to_str(const guint8 *ad)
108 {
109         return ether_to_str_punct(ad, ':');
110 }
111
112 /* Places char punct in the string as the hex-digit separator.
113  * If punct is '\0', no punctuation is applied (and thus
114  * the resulting string is 5 bytes shorter)
115  */
116 gchar *
117 ether_to_str_punct(const guint8 *ad, char punct) {
118   static gchar  str[3][18];
119   static gchar *cur;
120   gchar        *p;
121   int          i;
122   guint32      octet;
123   static const gchar hex_digits[16] = "0123456789abcdef";
124
125   if (cur == &str[0][0]) {
126     cur = &str[1][0];
127   } else if (cur == &str[1][0]) {  
128     cur = &str[2][0];
129   } else {  
130     cur = &str[0][0];
131   }
132   p = &cur[18];
133   *--p = '\0';
134   i = 5;
135   for (;;) {
136     octet = ad[i];
137     *--p = hex_digits[octet&0xF];
138     octet >>= 4;
139     *--p = hex_digits[octet&0xF];
140     if (i == 0)
141       break;
142     if (punct)
143       *--p = punct;
144     i--;
145   }
146   return p;
147 }
148
149 gchar *
150 ip_to_str(const guint8 *ad) {
151   static gchar  str[3][16];
152   static gchar *cur;
153   gchar        *p;
154   int           i;
155   guint32       octet;
156   guint32       digit;
157
158   if (cur == &str[0][0]) {
159     cur = &str[1][0];
160   } else if (cur == &str[1][0]) {  
161     cur = &str[2][0];
162   } else {  
163     cur = &str[0][0];
164   }
165   p = &cur[16];
166   *--p = '\0';
167   i = 3;
168   for (;;) {
169     octet = ad[i];
170     *--p = (octet%10) + '0';
171     octet /= 10;
172     digit = octet%10;
173     octet /= 10;
174     if (digit != 0 || octet != 0)
175       *--p = digit + '0';
176     if (octet != 0)
177       *--p = octet + '0';
178     if (i == 0)
179       break;
180     *--p = '.';
181     i--;
182   }
183   return p;
184 }
185
186 gchar *
187 ip6_to_str(struct e_in6_addr *ad) {
188 #ifndef INET6_ADDRSTRLEN
189 #define INET6_ADDRSTRLEN 46
190 #endif
191   static gchar buf[INET6_ADDRSTRLEN];
192
193   inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
194   return buf;
195 }
196
197
198 #define PLURALIZE(n)    (((n) > 1) ? "s" : "")
199 #define COMMA(do_it)    ((do_it) ? ", " : "")
200
201 gchar *
202 time_secs_to_str(guint32 time)
203 {
204   static gchar  str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
205   static gchar *cur, *p;
206   int hours, mins, secs;
207   int do_comma;
208
209   if (cur == &str[0][0]) {
210     cur = &str[1][0];
211   } else if (cur == &str[1][0]) {  
212     cur = &str[2][0];
213   } else {  
214     cur = &str[0][0];
215   }
216
217   if (time == 0) {
218     sprintf(cur, "0 time");
219     return cur;
220   }
221
222   secs = time % 60;
223   time /= 60;
224   mins = time % 60;
225   time /= 60;
226   hours = time % 24;
227   time /= 24;
228
229   p = cur;
230   if (time != 0) {
231     sprintf(p, "%u day%s", time, PLURALIZE(time));
232     p += strlen(p);
233     do_comma = 1;
234   } else
235     do_comma = 0;
236   if (hours != 0) {
237     sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
238     p += strlen(p);
239     do_comma = 1;
240   } else
241     do_comma = 0;
242   if (mins != 0) {
243     sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
244     p += strlen(p);
245     do_comma = 1;
246   } else
247     do_comma = 0;
248   if (secs != 0)
249     sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
250   return cur;
251 }
252
253 /* Max string length for displaying byte string.  */
254 #define MAX_BYTE_STR_LEN        32
255
256 /* Turn an array of bytes into a string showing the bytes in hex. */
257 #define N_BYTES_TO_STR_STRINGS  6
258 gchar *
259 bytes_to_str(const guint8 *bd, int bd_len) {
260   static gchar  str[N_BYTES_TO_STR_STRINGS][MAX_BYTE_STR_LEN+3+1];
261   static int    cur_idx;
262   gchar        *cur;
263   gchar        *p;
264   int           len;
265   static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
266                                 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
267
268   cur_idx++;
269   if (cur_idx >= N_BYTES_TO_STR_STRINGS)
270     cur_idx = 0;
271   cur = &str[cur_idx][0];
272   p = cur;
273   len = MAX_BYTE_STR_LEN;
274   while (bd_len > 0 && len > 0) {
275     *p++ = hex[(*bd) >> 4];
276     *p++ = hex[(*bd) & 0xF];
277     len -= 2;
278     bd++;
279     bd_len--;
280   }
281   if (bd_len != 0) {
282     /* Note that we're not showing the full string.  */
283     *p++ = '.';
284     *p++ = '.';
285     *p++ = '.';
286   }
287   *p = '\0';
288   return cur;
289 }
290
291 static const char *mon_names[12] = {
292         "Jan",
293         "Feb",
294         "Mar",
295         "Apr",
296         "May",
297         "Jun",
298         "Jul",
299         "Aug",
300         "Sep",
301         "Oct",
302         "Nov",
303         "Dec"
304 };
305
306 gchar *
307 abs_time_to_str(struct timeval *abs_time)
308 {
309         struct tm *tmp;
310         static gchar *cur;
311         static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
312
313         if (cur == &str[0][0]) {
314                 cur = &str[1][0];
315         } else if (cur == &str[1][0]) {
316                 cur = &str[2][0];
317         } else {
318                 cur = &str[0][0];
319         }
320
321         tmp = localtime(&abs_time->tv_sec);
322         sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
323             mon_names[tmp->tm_mon],
324             tmp->tm_mday,
325             tmp->tm_year + 1900,
326             tmp->tm_hour,
327             tmp->tm_min,
328             tmp->tm_sec,
329             (long)abs_time->tv_usec/100);
330
331         return cur;
332 }
333
334 gchar *
335 rel_time_to_str(struct timeval *rel_time)
336 {
337         static gchar *cur;
338         static char str[3][10+1+6+1];
339
340         if (cur == &str[0][0]) {
341                 cur = &str[1][0];
342         } else if (cur == &str[1][0]) {
343                 cur = &str[2][0];
344         } else {
345                 cur = &str[0][0];
346         }
347
348         sprintf(cur, "%ld.%06ld", (long)rel_time->tv_sec,
349                 (long)rel_time->tv_usec);
350
351         return cur;
352 }
353
354 /*
355  * Given a pointer into a data buffer, and to the end of the buffer,
356  * find the end of the (putative) line at that position in the data
357  * buffer.
358  * Return a pointer to the EOL character(s) in "*eol".
359  */
360 const u_char *
361 find_line_end(const u_char *data, const u_char *dataend, const u_char **eol)
362 {
363   const u_char *lineend;
364
365   lineend = memchr(data, '\n', dataend - data);
366   if (lineend == NULL) {
367     /*
368      * No LF - line is probably continued in next TCP segment.
369      */
370     lineend = dataend;
371     *eol = dataend;
372   } else {
373     /*
374      * Is the LF at the beginning of the line?
375      */
376     if (lineend > data) {
377       /*
378        * No - is it preceded by a carriage return?
379        * (Perhaps it's supposed to be, but that's not guaranteed....)
380        */
381       if (*(lineend - 1) == '\r') {
382         /*
383          * Yes.  The EOL starts with the CR.
384          */
385         *eol = lineend - 1;
386       } else {
387         /*
388          * No.  The EOL starts with the LF.
389          */
390         *eol = lineend;
391
392         /*
393          * I seem to remember that we once saw lines ending with LF-CR
394          * in an HTTP request or response, so check if it's *followed*
395          * by a carriage return.
396          */
397         if (lineend < (dataend - 1) && *(lineend + 1) == '\r') {
398           /*
399            * It's <non-LF><LF><CR>; say it ends with the CR.
400            */
401           lineend++;
402         }
403       }
404     }
405
406     /*
407      * Point to the character after the last character.
408      */
409     lineend++;
410   }
411   return lineend;
412 }
413
414 #define MAX_COLUMNS_LINE_DETAIL 62
415
416 /*
417  * Get the length of the next token in a line, and the beginning of the
418  * next token after that (if any).
419  * Return 0 if there is no next token.
420  */
421 int
422 get_token_len(const u_char *linep, const u_char *lineend,
423               const u_char **next_token)
424 {
425   const u_char *tokenp;
426   int token_len;
427
428   tokenp = linep;
429   
430   /*
431    * Search for a blank, a CR or an LF, or the end of the buffer.
432    */
433   while (linep < lineend && *linep != ' ' && *linep != '\r' && *linep != '\n')
434       linep++;
435   token_len = linep - tokenp;
436
437   /*
438    * Skip trailing blanks.
439    */
440   while (linep < lineend && *linep == ' ')
441     linep++;
442
443   *next_token = linep;
444
445   return token_len;
446 }
447
448 /*
449  * Given a string, generate a string from it that shows non-printable
450  * characters as C-style escapes, and return a pointer to it.
451  */
452 gchar *
453 format_text(const u_char *string, int len)
454 {
455   static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
456   gchar *fmtbufp;
457   int column;
458   const u_char *stringend = string + len;
459   u_char c;
460   int i;
461
462   column = 0;
463   fmtbufp = &fmtbuf[0];
464   while (string < stringend) {
465     if (column >= MAX_COLUMNS_LINE_DETAIL) {
466       /*
467        * Put "..." and quit.
468        */
469       strcpy(fmtbufp, " ...");
470       fmtbufp += 4;
471       break;
472     }
473     c = *string++;
474     if (isprint(c)) {
475       *fmtbufp++ = c;
476       column++;
477     } else {
478       *fmtbufp++ =  '\\';
479       column++;
480       switch (c) {
481
482       case '\\':
483         *fmtbufp++ = '\\';
484         column++;
485         break;
486
487       case '\a':
488         *fmtbufp++ = 'a';
489         column++;
490         break;
491
492       case '\b':
493         *fmtbufp++ = 'b';
494         column++;
495         break;
496
497       case '\f':
498         *fmtbufp++ = 'f';
499         column++;
500         break;
501
502       case '\n':
503         *fmtbufp++ = 'n';
504         column++;
505         break;
506
507       case '\r':
508         *fmtbufp++ = 'r';
509         column++;
510         break;
511
512       case '\t':
513         *fmtbufp++ = 't';
514         column++;
515         break;
516
517       case '\v':
518         *fmtbufp++ = 'v';
519         column++;
520         break;
521
522       default:
523         i = (c>>6)&03;
524         *fmtbufp++ = i + '0';
525         column++;
526         i = (c>>3)&07;
527         *fmtbufp++ = i + '0';
528         column++;
529         i = (c>>0)&07;
530         *fmtbufp++ = i + '0';
531         column++;
532         break;
533       }
534     }
535   }
536   *fmtbufp = '\0';
537   return fmtbuf;
538 }
539
540
541 /* Tries to match val against each element in the value_string array vs.
542    Returns the associated string ptr on a match.
543    Formats val with fmt, and returns the resulting string, on failure. */
544 gchar*
545 val_to_str(guint32 val, const value_string *vs, const char *fmt) {
546   gchar *ret;
547   static gchar  str[3][64];
548   static gchar *cur;
549
550   ret = match_strval(val, vs);
551   if (ret != NULL)
552     return ret;
553   if (cur == &str[0][0]) {
554     cur = &str[1][0];
555   } else if (cur == &str[1][0]) {  
556     cur = &str[2][0];
557   } else {  
558     cur = &str[0][0];
559   }
560   snprintf(cur, 64, fmt, val);
561   return cur;
562 }
563
564 /* Tries to match val against each element in the value_string array vs.
565    Returns the associated string ptr on a match, or NULL on failure. */
566 gchar*
567 match_strval(guint32 val, const value_string *vs) {
568   gint i = 0;
569   
570   while (vs[i].strptr) {
571     if (vs[i].value == val)
572       return(vs[i].strptr);
573     i++;
574   }
575
576   return(NULL);
577 }
578
579 /* Generate, into "buf", a string showing the bits of a bitfield.
580    Return a pointer to the character after that string. */
581 char *
582 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
583 {
584   int i;
585   guint32 bit;
586   char *p;
587
588   i = 0;
589   p = buf;
590   bit = 1 << (width - 1);
591   for (;;) {
592     if (mask & bit) {
593       /* This bit is part of the field.  Show its value. */
594       if (val & bit)
595         *p++ = '1';
596       else
597         *p++ = '0';
598     } else {
599       /* This bit is not part of the field. */
600       *p++ = '.';
601     }
602     bit >>= 1;
603     i++;
604     if (i >= width)
605       break;
606     if (i % 4 == 0)
607       *p++ = ' ';
608   }
609   strcpy(p, " = ");
610   p += 3;
611   return p;
612 }
613
614 /* Generate a string describing a Boolean bitfield (a one-bit field that
615    says something is either true of false). */
616 const char *
617 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
618     const char *truedesc, const char *falsedesc)
619 {
620   static char buf[1025];
621   char *p;
622
623   p = decode_bitfield_value(buf, val, mask, width);
624   if (val & mask)
625     strcpy(p, truedesc);
626   else
627     strcpy(p, falsedesc);
628   return buf;
629 }
630
631 /* Generate a string describing an enumerated bitfield (an N-bit field
632    with various specific values having particular names). */
633 const char *
634 decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
635     const value_string *tab, const char *fmt)
636 {
637   static char buf[1025];
638   char *p;
639
640   p = decode_bitfield_value(buf, val, mask, width);
641   sprintf(p, fmt, val_to_str(val & mask, tab, "Unknown"));
642   return buf;
643 }
644
645 /* Generate a string describing a numeric bitfield (an N-bit field whose
646    value is just a number). */
647 const char *
648 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
649     const char *fmt)
650 {
651   static char buf[1025];
652   char *p;
653   int shift = 0;
654
655   /* Compute the number of bits we have to shift the bitfield right
656      to extract its value. */
657   while ((mask & (1<<shift)) == 0)
658     shift++;
659
660   p = decode_bitfield_value(buf, val, mask, width);
661   sprintf(p, fmt, (val & mask) >> shift);
662   return buf;
663 }
664
665 /* Checks to see if a particular packet information element is needed for
666    the packet list */
667 gint
668 check_col(frame_data *fd, gint el) {
669   int i;
670
671   if (fd->cinfo) {
672     for (i = 0; i < fd->cinfo->num_cols; i++) {
673       if (fd->cinfo->fmt_matx[i][el])
674         return TRUE;
675     }
676   }
677   return FALSE;
678 }
679
680 /* Adds a vararg list to a packet info string. */
681 void
682 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
683   va_list ap;
684   int     i;
685   size_t  max_len;
686   
687   va_start(ap, format);
688   for (i = 0; i < fd->cinfo->num_cols; i++) {
689     if (fd->cinfo->fmt_matx[i][el]) {
690       if (el == COL_INFO)
691         max_len = COL_MAX_INFO_LEN;
692       else
693         max_len = COL_MAX_LEN;
694       vsnprintf(fd->cinfo->col_data[i], max_len, format, ap);
695     }
696   }
697 }
698
699 void
700 col_add_str(frame_data *fd, gint el, const gchar* str) {
701   int    i;
702   size_t max_len;
703
704   for (i = 0; i < fd->cinfo->num_cols; i++) {
705     if (fd->cinfo->fmt_matx[i][el]) {
706       if (el == COL_INFO)
707         max_len = COL_MAX_INFO_LEN;
708       else
709         max_len = COL_MAX_LEN;
710       strncpy(fd->cinfo->col_data[i], str, max_len);
711       fd->cinfo->col_data[i][max_len - 1] = 0;
712     }
713   }
714 }
715
716 /* Appends a vararg list to a packet info string. */
717 void
718 col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
719   va_list ap;
720   int     i;
721   size_t  len, max_len;
722   
723   va_start(ap, format);
724   for (i = 0; i < fd->cinfo->num_cols; i++) {
725     if (fd->cinfo->fmt_matx[i][el]) {
726       len = strlen(fd->cinfo->col_data[i]);
727       if (el == COL_INFO)
728         max_len = COL_MAX_INFO_LEN;
729       else
730         max_len = COL_MAX_LEN;
731       vsnprintf(&fd->cinfo->col_data[i][len], max_len - len, format, ap);
732     }
733   }
734 }
735
736 void
737 col_append_str(frame_data *fd, gint el, gchar* str) {
738   int    i;
739   size_t len, max_len;
740
741   for (i = 0; i < fd->cinfo->num_cols; i++) {
742     if (fd->cinfo->fmt_matx[i][el]) {
743       len = strlen(fd->cinfo->col_data[i]);
744       if (el == COL_INFO)
745         max_len = COL_MAX_LEN;
746       else
747         max_len = COL_MAX_INFO_LEN;
748       strncat(fd->cinfo->col_data[i], str, max_len - len);
749       fd->cinfo->col_data[i][max_len - 1] = 0;
750     }
751   }
752 }
753
754 /* To do: Add check_col checks to the col_add* routines */
755
756 static void
757 col_set_abs_time(frame_data *fd, int col)
758 {
759   struct tm *tmp;
760   time_t then;
761
762   then = fd->abs_secs;
763   tmp = localtime(&then);
764   snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
765     tmp->tm_hour,
766     tmp->tm_min,
767     tmp->tm_sec,
768     (long)fd->abs_usecs/100);
769 }
770
771 static void
772 col_set_rel_time(frame_data *fd, int col)
773 {
774   snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->rel_secs,
775     fd->rel_usecs);
776 }
777
778 static void
779 col_set_delta_time(frame_data *fd, int col)
780 {
781   snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->del_secs,
782     fd->del_usecs);
783 }
784
785 /* Add "command-line-specified" time.
786    XXX - this is called from "file.c" when the user changes the time
787    format they want for "command-line-specified" time; it's a bit ugly
788    that we have to export it, but if we go to a CList-like widget that
789    invokes callbacks to get the text for the columns rather than
790    requiring us to stuff the text into the widget from outside, we
791    might be able to clean this up. */
792 void
793 col_set_cls_time(frame_data *fd, int col)
794 {
795   switch (timestamp_type) {
796     case ABSOLUTE:
797       col_set_abs_time(fd, col);
798       break;
799
800     case RELATIVE:
801       col_set_rel_time(fd, col);
802       break;
803
804     case DELTA:
805       col_set_delta_time(fd, col);
806       break;
807   }
808 }
809
810 static void
811 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
812 {
813   u_int ipv4_addr;
814   struct e_in6_addr ipv6_addr;
815   struct atalk_ddp_addr ddp_addr;
816   struct sna_fid_type_4_addr sna_fid_type_4_addr;
817
818   switch (addr->type) {
819
820   case AT_ETHER:
821     if (is_res)
822       strncpy(fd->cinfo->col_data[col], get_ether_name(addr->data), COL_MAX_LEN);
823     else
824       strncpy(fd->cinfo->col_data[col], ether_to_str(addr->data), COL_MAX_LEN);
825     break;
826
827   case AT_IPv4:
828     memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
829     if (is_res)
830       strncpy(fd->cinfo->col_data[col], get_hostname(ipv4_addr), COL_MAX_LEN);
831     else
832       strncpy(fd->cinfo->col_data[col], ip_to_str(addr->data), COL_MAX_LEN);
833     break;
834
835   case AT_IPv6:
836     memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
837     if (is_res)
838       strncpy(fd->cinfo->col_data[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
839     else
840       strncpy(fd->cinfo->col_data[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
841     break;
842
843   case AT_IPX:
844     strncpy(fd->cinfo->col_data[col],
845       ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
846     break;
847
848   case AT_SNA:
849     switch (addr->len) {
850
851     case 1:
852       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X", addr->data[0]);
853       break;
854
855     case 2:
856       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X",
857         pntohs(&addr->data[0]));
858       break;
859
860     case SNA_FID_TYPE_4_ADDR_LEN:
861       memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
862       strncpy(fd->cinfo->col_data[col],
863         sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
864       break;
865     }
866     break;
867
868   case AT_ATALK:
869     memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
870     strncpy(fd->cinfo->col_data[col], atalk_addr_to_str(&ddp_addr),
871       COL_MAX_LEN);
872     break;
873
874   case AT_VINES:
875     strncpy(fd->cinfo->col_data[col], vines_addr_to_str(&addr->data[0]),
876       COL_MAX_LEN);
877     break;
878
879   default:
880     break;
881   }
882   fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
883 }
884
885 static void
886 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
887                 gboolean is_res)
888 {
889   switch (ptype) {
890
891   case PT_TCP:
892     if (is_res)
893       strncpy(fd->cinfo->col_data[col], get_tcp_port(port), COL_MAX_LEN);
894     else
895       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
896     break;
897
898   case PT_UDP:
899     if (is_res)
900       strncpy(fd->cinfo->col_data[col], get_udp_port(port), COL_MAX_LEN);
901     else
902       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
903     break;
904
905   default:
906     break;
907   }
908   fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
909 }
910
911 void
912 fill_in_columns(frame_data *fd)
913 {
914   int i;
915
916   for (i = 0; i < fd->cinfo->num_cols; i++) {
917     switch (fd->cinfo->col_fmt[i]) {
918
919     case COL_NUMBER:
920       snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%u", fd->num);
921       break;
922
923     case COL_CLS_TIME:
924       col_set_cls_time(fd, i);
925       break;
926
927     case COL_ABS_TIME:
928       col_set_abs_time(fd, i);
929       break;
930
931     case COL_REL_TIME:
932       col_set_rel_time(fd, i);
933       break;
934
935     case COL_DELTA_TIME:
936       col_set_delta_time(fd, i);
937       break;
938
939     case COL_DEF_SRC:
940     case COL_RES_SRC:   /* COL_DEF_SRC is currently just like COL_RES_SRC */
941       col_set_addr(fd, i, &pi.src, TRUE);
942       break;
943
944     case COL_UNRES_SRC:
945       col_set_addr(fd, i, &pi.src, FALSE);
946       break;
947
948     case COL_DEF_DL_SRC:
949     case COL_RES_DL_SRC:
950       col_set_addr(fd, i, &pi.dl_src, TRUE);
951       break;
952
953     case COL_UNRES_DL_SRC:
954       col_set_addr(fd, i, &pi.dl_src, FALSE);
955       break;
956
957     case COL_DEF_NET_SRC:
958     case COL_RES_NET_SRC:
959       col_set_addr(fd, i, &pi.net_src, TRUE);
960       break;
961
962     case COL_UNRES_NET_SRC:
963       col_set_addr(fd, i, &pi.net_src, FALSE);
964       break;
965
966     case COL_DEF_DST:
967     case COL_RES_DST:   /* COL_DEF_DST is currently just like COL_RES_DST */
968       col_set_addr(fd, i, &pi.dst, TRUE);
969       break;
970
971     case COL_UNRES_DST:
972       col_set_addr(fd, i, &pi.dst, FALSE);
973       break;
974
975     case COL_DEF_DL_DST:
976     case COL_RES_DL_DST:
977       col_set_addr(fd, i, &pi.dl_dst, TRUE);
978       break;
979
980     case COL_UNRES_DL_DST:
981       col_set_addr(fd, i, &pi.dl_dst, FALSE);
982       break;
983
984     case COL_DEF_NET_DST:
985     case COL_RES_NET_DST:
986       col_set_addr(fd, i, &pi.net_dst, TRUE);
987       break;
988
989     case COL_UNRES_NET_DST:
990       col_set_addr(fd, i, &pi.net_dst, FALSE);
991       break;
992
993     case COL_DEF_SRC_PORT:
994     case COL_RES_SRC_PORT:      /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
995       col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
996       break;
997
998     case COL_UNRES_SRC_PORT:
999       col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
1000       break;
1001
1002     case COL_DEF_DST_PORT:
1003     case COL_RES_DST_PORT:      /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
1004       col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
1005       break;
1006
1007     case COL_UNRES_DST_PORT:
1008       col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
1009       break;
1010
1011     case COL_PROTOCOL:  /* currently done by dissectors */
1012     case COL_INFO:      /* currently done by dissectors */
1013       break;
1014
1015     case COL_PACKET_LENGTH:
1016       snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%d", fd->pkt_len);
1017       break;
1018
1019     case NUM_COL_FMTS:  /* keep compiler happy - shouldn't get here */
1020       break;
1021     }
1022   }
1023 }
1024         
1025 void blank_packetinfo(void)
1026 {
1027   pi.dl_src.type = AT_NONE;
1028   pi.dl_dst.type = AT_NONE;
1029   pi.net_src.type = AT_NONE;
1030   pi.net_dst.type = AT_NONE;
1031   pi.src.type = AT_NONE;
1032   pi.dst.type = AT_NONE;
1033   pi.ipproto  = 0;
1034   pi.ptype = PT_NONE;
1035   pi.srcport  = 0;
1036   pi.destport = 0;
1037 }
1038
1039 /* Allow protocols to register "init" routines, which are called before
1040    we make a pass through a capture file and dissect all its packets
1041    (e.g., when we read in a new capture file, or run a "filter packets"
1042    or "colorize packets" pass over the current capture file). */
1043 static GSList *init_routines;
1044
1045 void
1046 register_init_routine(void (*func)(void))
1047 {
1048         init_routines = g_slist_append(init_routines, func);
1049 }
1050
1051 /* Call all the registered "init" routines. */
1052 static void
1053 call_init_routine(gpointer routine, gpointer dummy)
1054 {
1055         void (*func)(void) = routine;
1056
1057         (*func)();
1058 }
1059
1060 void
1061 init_all_protocols(void)
1062 {
1063         g_slist_foreach(init_routines, &call_init_routine, NULL);
1064 }
1065
1066 /* this routine checks the frame type from the cf structure */
1067 void
1068 dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
1069 {
1070         proto_tree *fh_tree;
1071         proto_item *ti;
1072         struct timeval tv;
1073
1074         /* Put in frame header information. */
1075         if (tree) {
1076           ti = proto_tree_add_protocol_format(tree, proto_frame, 0, fd->cap_len,
1077             "Frame %u (%u on wire, %u captured)", fd->num,
1078             fd->pkt_len, fd->cap_len);
1079
1080           fh_tree = proto_item_add_subtree(ti, ett_frame);
1081
1082           tv.tv_sec = fd->abs_secs;
1083           tv.tv_usec = fd->abs_usecs;
1084
1085           proto_tree_add_item(fh_tree, hf_frame_arrival_time,
1086                 0, 0, &tv);
1087
1088           tv.tv_sec = fd->del_secs;
1089           tv.tv_usec = fd->del_usecs;
1090
1091           proto_tree_add_item(fh_tree, hf_frame_time_delta,
1092                 0, 0, &tv);
1093
1094           proto_tree_add_item(fh_tree, hf_frame_number,
1095                 0, 0, fd->num);
1096
1097           proto_tree_add_uint_format(fh_tree, hf_frame_packet_len,
1098                 0, 0, fd->pkt_len, "Packet Length: %d byte%s", fd->pkt_len,
1099                 plurality(fd->pkt_len, "", "s"));
1100                 
1101           proto_tree_add_uint_format(fh_tree, hf_frame_capture_len,
1102                 0, 0, fd->cap_len, "Capture Length: %d byte%s", fd->cap_len,
1103                 plurality(fd->cap_len, "", "s"));
1104         }
1105
1106         blank_packetinfo();
1107
1108         /* Set the initial payload to the packet length, and the initial
1109            captured payload to the capture length (other protocols may
1110            reduce them if their headers say they're less). */
1111         pi.len = fd->pkt_len;
1112         pi.captured_len = fd->cap_len;
1113
1114         switch (fd->lnk_t) {
1115                 case WTAP_ENCAP_ETHERNET :
1116                         dissect_eth(pd, 0, fd, tree);
1117                         break;
1118                 case WTAP_ENCAP_FDDI :
1119                         dissect_fddi(pd, fd, tree, FALSE);
1120                         break;
1121                 case WTAP_ENCAP_FDDI_BITSWAPPED :
1122                         dissect_fddi(pd, fd, tree, TRUE);
1123                         break;
1124                 case WTAP_ENCAP_TR :
1125                         dissect_tr(pd, 0, fd, tree);
1126                         break;
1127                 case WTAP_ENCAP_NULL :
1128                         dissect_null(pd, fd, tree);
1129                         break;
1130                 case WTAP_ENCAP_PPP :
1131                         dissect_ppp(pd, fd, tree);
1132                         break;
1133                 case WTAP_ENCAP_LAPB :
1134                         dissect_lapb(pd, fd, tree);
1135                         break;
1136                 case WTAP_ENCAP_RAW_IP :
1137                         dissect_raw(pd, fd, tree);
1138                         break;
1139                 case WTAP_ENCAP_LINUX_ATM_CLIP :
1140                         dissect_clip(pd, fd, tree);
1141                         break;
1142                 case WTAP_ENCAP_ATM_SNIFFER :
1143                         dissect_atm(pd, fd, tree);
1144                         break;
1145                 case WTAP_ENCAP_ASCEND :
1146                         dissect_ascend(pd, fd, tree);
1147                         break;
1148                 case WTAP_ENCAP_LAPD :
1149                         dissect_lapd(pd, fd, tree);
1150                         break;
1151                 case WTAP_ENCAP_V120 :
1152                         dissect_v120(pd, fd, tree);
1153                         break;
1154         }
1155 }
1156
1157 gint p_compare(gconstpointer a, gconstpointer b)
1158 {
1159
1160   if (((frame_proto_data *)a) -> proto > ((frame_proto_data *)b) -> proto)
1161     return 1;
1162   else if (((frame_proto_data *)a) -> proto == ((frame_proto_data *)b) -> proto)
1163     return 0;
1164   else
1165     return -1;
1166
1167 }
1168
1169 void
1170 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
1171 {
1172   frame_proto_data *p1 = malloc(sizeof(frame_proto_data)); /* FIXME */
1173  
1174   g_assert(p1 != NULL);
1175
1176   p1 -> proto = proto;
1177   p1 -> proto_data = proto_data;
1178
1179   /* Allocate a frame_proto_data struct and then add it to the GSLIST */
1180
1181
1182   fd -> pfd = g_slist_insert_sorted(fd -> pfd,
1183                                     (gpointer *)p1,
1184                                     p_compare);
1185
1186 }
1187
1188 void *
1189 p_get_proto_data(frame_data *fd, int proto)
1190 {
1191
1192   return(NULL);
1193
1194 }
1195
1196 void
1197 p_rem_proto_data(frame_data *fd, int proto)
1198 {
1199
1200
1201 }
1202
1203 void
1204 proto_register_frame(void)
1205 {
1206         static hf_register_info hf[] = {
1207                 { &hf_frame_arrival_time,
1208                 { "Arrival Time",               "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1209                         ""}},
1210
1211                 { &hf_frame_time_delta,
1212                 { "Time delta from previous packet",    "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
1213                         0x0,
1214                         "" }},
1215
1216                 { &hf_frame_number,
1217                 { "Frame Number",               "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
1218                         "" }},
1219
1220                 { &hf_frame_packet_len,
1221                 { "Total Frame Length",         "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
1222                         "" }},
1223
1224                 { &hf_frame_capture_len,
1225                 { "Capture Frame Length",       "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
1226                         "" }},
1227         };
1228         static gint *ett[] = {
1229                 &ett_frame,
1230         };
1231
1232         proto_frame = proto_register_protocol("Frame", "frame");
1233         proto_register_field_array(proto_frame, hf, array_length(hf));
1234         proto_register_subtree_array(ett, array_length(ett));
1235 }