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