Add an item to the "File/Print" dialog box to ask that the full hex data
[obnox/wireshark/wip.git] / packet.c
1 /* packet.c
2  * Routines for packet disassembly
3  *
4  * $Id: packet.c,v 1.45 1999/09/29 22:19:12 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 <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 #include "packet.h"
59 #include "print.h"
60 #include "file.h"
61
62 extern capture_file  cf;
63
64 gboolean        tree_is_expanded[NUM_TREE_TYPES];
65
66 int proto_frame = -1;
67 int hf_frame_arrival_time = -1;
68 int hf_frame_time_delta = -1;
69 int hf_frame_number = -1;
70 int hf_frame_packet_len = -1;
71 int hf_frame_capture_len = -1;
72
73 gchar *
74 ether_to_str(const guint8 *ad) {
75   static gchar  str[3][18];
76   static gchar *cur;
77   gchar        *p;
78   int          i;
79   guint32      octet;
80   static const gchar hex_digits[16] = "0123456789abcdef";
81
82   if (cur == &str[0][0]) {
83     cur = &str[1][0];
84   } else if (cur == &str[1][0]) {  
85     cur = &str[2][0];
86   } else {  
87     cur = &str[0][0];
88   }
89   p = &cur[18];
90   *--p = '\0';
91   i = 5;
92   for (;;) {
93     octet = ad[i];
94     *--p = hex_digits[octet&0xF];
95     octet >>= 4;
96     *--p = hex_digits[octet&0xF];
97     if (i == 0)
98       break;
99     *--p = ':';
100     i--;
101   }
102   return p;
103 }
104
105 gchar *
106 ip_to_str(const guint8 *ad) {
107   static gchar  str[3][16];
108   static gchar *cur;
109   gchar        *p;
110   int           i;
111   guint32       octet;
112   guint32       digit;
113
114   if (cur == &str[0][0]) {
115     cur = &str[1][0];
116   } else if (cur == &str[1][0]) {  
117     cur = &str[2][0];
118   } else {  
119     cur = &str[0][0];
120   }
121   p = &cur[16];
122   *--p = '\0';
123   i = 3;
124   for (;;) {
125     octet = ad[i];
126     *--p = (octet%10) + '0';
127     octet /= 10;
128     digit = octet%10;
129     octet /= 10;
130     if (digit != 0 || octet != 0)
131       *--p = digit + '0';
132     if (octet != 0)
133       *--p = octet + '0';
134     if (i == 0)
135       break;
136     *--p = '.';
137     i--;
138   }
139   return p;
140 }
141
142 #define PLURALIZE(n)    (((n) > 1) ? "s" : "")
143 #define COMMA(do_it)    ((do_it) ? ", " : "")
144
145 gchar *
146 time_secs_to_str(guint32 time)
147 {
148   static gchar  str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
149   static gchar *cur, *p;
150   int hours, mins, secs;
151   int do_comma;
152
153   if (cur == &str[0][0]) {
154     cur = &str[1][0];
155   } else if (cur == &str[1][0]) {  
156     cur = &str[2][0];
157   } else {  
158     cur = &str[0][0];
159   }
160
161   secs = time % 60;
162   time /= 60;
163   mins = time % 60;
164   time /= 60;
165   hours = time % 24;
166   time /= 24;
167
168   p = cur;
169   if (time != 0) {
170     sprintf(p, "%u day%s", time, PLURALIZE(time));
171     p += strlen(p);
172     do_comma = 1;
173   } else
174     do_comma = 0;
175   if (hours != 0) {
176     sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
177     p += strlen(p);
178     do_comma = 1;
179   } else
180     do_comma = 0;
181   if (mins != 0) {
182     sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
183     p += strlen(p);
184     do_comma = 1;
185   } else
186     do_comma = 0;
187   if (secs != 0)
188     sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
189   return cur;
190 }
191
192 /* Max string length for displaying byte string.  */
193 #define MAX_BYTE_STR_LEN        20
194
195 /* Turn an array of bytes into a string showing the bytes in hex. */
196 gchar *
197 bytes_to_str(const guint8 *bd, int bd_len) {
198   static gchar  str[3][MAX_BYTE_STR_LEN+3+1];
199   static gchar *cur;
200   gchar        *p;
201   int           len;
202   static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
203                                 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
204
205   if (cur == &str[0][0]) {
206     cur = &str[1][0];
207   } else if (cur == &str[1][0]) {  
208     cur = &str[2][0];
209   } else {  
210     cur = &str[0][0];
211   }
212   p = cur;
213   len = MAX_BYTE_STR_LEN;
214   while (bd_len > 0 && len > 0) {
215     *p++ = hex[(*bd) >> 4];
216     *p++ = hex[(*bd) & 0xF];
217     len -= 2;
218     bd++;
219     bd_len--;
220   }
221   if (bd_len != 0) {
222     /* Note that we're not showing the full string.  */
223     *p++ = '.';
224     *p++ = '.';
225     *p++ = '.';
226   }
227   *p = '\0';
228   return cur;
229 }
230
231 static const char *mon_names[12] = {
232         "Jan",
233         "Feb",
234         "Mar",
235         "Apr",
236         "May",
237         "Jun",
238         "Jul",
239         "Aug",
240         "Sep",
241         "Oct",
242         "Nov",
243         "Dec"
244 };
245
246 gchar *
247 abs_time_to_str(struct timeval *abs_time)
248 {
249         struct tm *tmp;
250         static gchar *cur;
251         static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
252
253         if (cur == &str[0][0]) {
254                 cur = &str[1][0];
255         } else if (cur == &str[1][0]) {
256                 cur = &str[2][0];
257         } else {
258                 cur = &str[0][0];
259         }
260
261         tmp = localtime(&abs_time->tv_sec);
262         sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
263             mon_names[tmp->tm_mon],
264             tmp->tm_mday,
265             tmp->tm_year + 1900,
266             tmp->tm_hour,
267             tmp->tm_min,
268             tmp->tm_sec,
269             (long)abs_time->tv_usec/100);
270
271         return cur;
272 }
273
274 gchar *
275 rel_time_to_str(struct timeval *rel_time)
276 {
277         static gchar *cur;
278         static char str[3][10+1+6+1];
279
280         if (cur == &str[0][0]) {
281                 cur = &str[1][0];
282         } else if (cur == &str[1][0]) {
283                 cur = &str[2][0];
284         } else {
285                 cur = &str[0][0];
286         }
287
288         sprintf(cur, "%ld.%06ld", (long)rel_time->tv_sec,
289                 (long)rel_time->tv_usec);
290
291         return cur;
292 }
293
294 /*
295  * Given a pointer into a data buffer, and to the end of the buffer,
296  * find the end of the (putative) line at that position in the data
297  * buffer.
298  * Return a pointer to the EOL character(s) in "*eol".
299  */
300 const u_char *
301 find_line_end(const u_char *data, const u_char *dataend, const u_char **eol)
302 {
303   const u_char *lineend;
304
305   lineend = memchr(data, '\n', dataend - data);
306   if (lineend == NULL) {
307     /*
308      * No LF - line is probably continued in next TCP segment.
309      */
310     lineend = dataend;
311     *eol = dataend;
312   } else {
313     /*
314      * Is the LF at the beginning of the line?
315      */
316     if (lineend > data) {
317       /*
318        * No - is it preceded by a carriage return?
319        * (Perhaps it's supposed to be, but that's not guaranteed....)
320        */
321       if (*(lineend - 1) == '\r') {
322         /*
323          * Yes.  The EOL starts with the CR.
324          */
325         *eol = lineend - 1;
326       } else {
327         /*
328          * No.  The EOL starts with the LF.
329          */
330         *eol = lineend;
331
332         /*
333          * I seem to remember that we once saw lines ending with LF-CR
334          * in an HTTP request or response, so check if it's *followed*
335          * by a carriage return.
336          */
337         if (lineend < (dataend - 1) && *(lineend + 1) == '\r') {
338           /*
339            * It's <non-LF><LF><CR>; say it ends with the CR.
340            */
341           lineend++;
342         }
343       }
344     }
345
346     /*
347      * Point to the character after the last character.
348      */
349     lineend++;
350   }
351   return lineend;
352 }
353
354 #define MAX_COLUMNS_LINE_DETAIL 62
355
356 /*
357  * Get the length of the next token in a line, and the beginning of the
358  * next token after that (if any).
359  * Return 0 if there is no next token.
360  */
361 int
362 get_token_len(const u_char *linep, const u_char *lineend,
363               const u_char **next_token)
364 {
365   const u_char *tokenp;
366   int token_len;
367
368   tokenp = linep;
369   
370   /*
371    * Search for a blank, a CR or an LF, or the end of the buffer.
372    */
373   while (linep < lineend && *linep != ' ' && *linep != '\r' && *linep != '\n')
374       linep++;
375   token_len = linep - tokenp;
376
377   /*
378    * Skip trailing blanks.
379    */
380   while (linep < lineend && *linep == ' ')
381     linep++;
382
383   *next_token = linep;
384
385   return token_len;
386 }
387
388 /*
389  * Given a string, generate a string from it that shows non-printable
390  * characters as C-style escapes, and return a pointer to it.
391  */
392 gchar *
393 format_text(const u_char *string, int len)
394 {
395   static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
396   gchar *fmtbufp;
397   int column;
398   const u_char *stringend = string + len;
399   u_char c;
400   int i;
401
402   column = 0;
403   fmtbufp = &fmtbuf[0];
404   while (string < stringend) {
405     if (column >= MAX_COLUMNS_LINE_DETAIL) {
406       /*
407        * Put "..." and quit.
408        */
409       strcpy(fmtbufp, " ...");
410       break;
411     }
412     c = *string++;
413     if (isprint(c)) {
414       *fmtbufp++ = c;
415       column++;
416     } else {
417       *fmtbufp++ =  '\\';
418       column++;
419       switch (c) {
420
421       case '\\':
422         *fmtbufp++ = '\\';
423         column++;
424         break;
425
426       case '\a':
427         *fmtbufp++ = 'a';
428         column++;
429         break;
430
431       case '\b':
432         *fmtbufp++ = 'b';
433         column++;
434         break;
435
436       case '\f':
437         *fmtbufp++ = 'f';
438         column++;
439         break;
440
441       case '\n':
442         *fmtbufp++ = 'n';
443         column++;
444         break;
445
446       case '\r':
447         *fmtbufp++ = 'r';
448         column++;
449         break;
450
451       case '\t':
452         *fmtbufp++ = 't';
453         column++;
454         break;
455
456       case '\v':
457         *fmtbufp++ = 'v';
458         column++;
459         break;
460
461       default:
462         i = (c>>6)&03;
463         *fmtbufp++ = i + '0';
464         column++;
465         i = (c>>3)&07;
466         *fmtbufp++ = i + '0';
467         column++;
468         i = (c>>0)&07;
469         *fmtbufp++ = i + '0';
470         column++;
471         break;
472       }
473     }
474   }
475   *fmtbufp = '\0';
476   return fmtbuf;
477 }
478
479
480 /* Tries to match val against each element in the value_string array vs.
481    Returns the associated string ptr on a match.
482    Formats val with fmt, and returns the resulting string, on failure. */
483 gchar*
484 val_to_str(guint32 val, const value_string *vs, const char *fmt) {
485   gchar *ret;
486   static gchar  str[3][64];
487   static gchar *cur;
488
489   ret = match_strval(val, vs);
490   if (ret != NULL)
491     return ret;
492   if (cur == &str[0][0]) {
493     cur = &str[1][0];
494   } else if (cur == &str[1][0]) {  
495     cur = &str[2][0];
496   } else {  
497     cur = &str[0][0];
498   }
499   snprintf(cur, 64, fmt, val);
500   return cur;
501 }
502
503 /* Tries to match val against each element in the value_string array vs.
504    Returns the associated string ptr on a match, or NULL on failure. */
505 gchar*
506 match_strval(guint32 val, const value_string *vs) {
507   gint i = 0;
508   
509   while (vs[i].strptr) {
510     if (vs[i].value == val)
511       return(vs[i].strptr);
512     i++;
513   }
514
515   return(NULL);
516 }
517
518 /* Generate, into "buf", a string showing the bits of a bitfield.
519    Return a pointer to the character after that string. */
520 static char *
521 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
522 {
523   int i;
524   guint32 bit;
525   char *p;
526
527   i = 0;
528   p = buf;
529   bit = 1 << (width - 1);
530   for (;;) {
531     if (mask & bit) {
532       /* This bit is part of the field.  Show its value. */
533       if (val & bit)
534         *p++ = '1';
535       else
536         *p++ = '0';
537     } else {
538       /* This bit is not part of the field. */
539       *p++ = '.';
540     }
541     bit >>= 1;
542     i++;
543     if (i >= width)
544       break;
545     if (i % 4 == 0)
546       *p++ = ' ';
547   }
548   strcpy(p, " = ");
549   p += 3;
550   return p;
551 }
552
553 /* Generate a string describing a Boolean bitfield (a one-bit field that
554    says something is either true of false). */
555 const char *
556 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
557     const char *truedesc, const char *falsedesc)
558 {
559   static char buf[1025];
560   char *p;
561
562   p = decode_bitfield_value(buf, val, mask, width);
563   if (val & mask)
564     strcpy(p, truedesc);
565   else
566     strcpy(p, falsedesc);
567   return buf;
568 }
569
570 /* Generate a string describing an enumerated bitfield (an N-bit field
571    with various specific values having particular names). */
572 const char *
573 decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
574     const value_string *tab, const char *fmt)
575 {
576   static char buf[1025];
577   char *p;
578
579   p = decode_bitfield_value(buf, val, mask, width);
580   sprintf(p, fmt, val_to_str(val & mask, tab, "Unknown"));
581   return buf;
582 }
583
584 /* Generate a string describing a numeric bitfield (an N-bit field whose
585    value is just a number). */
586 const char *
587 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
588     const char *fmt)
589 {
590   static char buf[1025];
591   char *p;
592   int shift = 0;
593
594   /* Compute the number of bits we have to shift the bitfield right
595      to extract its value. */
596   while ((mask & (1<<shift)) == 0)
597     shift++;
598
599   p = decode_bitfield_value(buf, val, mask, width);
600   sprintf(p, fmt, (val & mask) >> shift);
601   return buf;
602 }
603
604 /* Checks to see if a particular packet information element is needed for
605    the packet list */
606 gint
607 check_col(frame_data *fd, gint el) {
608   int i;
609
610   if (fd->cinfo) {
611     for (i = 0; i < fd->cinfo->num_cols; i++) {
612       if (fd->cinfo->fmt_matx[i][el])
613         return TRUE;
614     }
615   }
616   return FALSE;
617 }
618
619 /* Adds a vararg list to a packet info string. */
620 void
621 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
622   va_list    ap;
623   int        i;
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       vsnprintf(fd->cinfo->col_data[i], COL_MAX_LEN, format, ap);
629   }
630 }
631
632 void
633 col_add_str(frame_data *fd, gint el, const gchar* str) {
634   int i;
635   
636   for (i = 0; i < fd->cinfo->num_cols; i++) {
637     if (fd->cinfo->fmt_matx[i][el]) {
638       strncpy(fd->cinfo->col_data[i], str, COL_MAX_LEN);
639       fd->cinfo->col_data[i][COL_MAX_LEN - 1] = 0;
640     }
641   }
642 }
643
644 /* this routine checks the frame type from the cf structure */
645 void
646 dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
647 {
648         proto_tree *fh_tree;
649         proto_item *ti;
650         struct timeval tv;
651
652         /* Put in frame header information. */
653         if (tree) {
654           ti = proto_tree_add_item_format(tree, proto_frame, 0, fd->cap_len,
655             NULL, "Frame (%d on wire, %d captured)", fd->pkt_len, fd->cap_len);
656
657           fh_tree = proto_item_add_subtree(ti, ETT_FRAME);
658
659           tv.tv_sec = fd->abs_secs;
660           tv.tv_usec = fd->abs_usecs;
661
662           proto_tree_add_item(fh_tree, hf_frame_arrival_time,
663                 0, 0, &tv);
664
665           tv.tv_sec = fd->del_secs;
666           tv.tv_usec = fd->del_usecs;
667
668           proto_tree_add_item(fh_tree, hf_frame_time_delta,
669                 0, 0, &tv);
670
671           proto_tree_add_item(fh_tree, hf_frame_number,
672                 0, 0, fd->num);
673
674           proto_tree_add_item_format(fh_tree, hf_frame_packet_len,
675                 0, 0, fd->pkt_len, "Packet Length: %d byte%s", fd->pkt_len,
676                 plurality(fd->pkt_len, "", "s"));
677                 
678           proto_tree_add_item_format(fh_tree, hf_frame_capture_len,
679                 0, 0, fd->cap_len, "Capture Length: %d byte%s", fd->cap_len,
680                 plurality(fd->cap_len, "", "s"));
681         }
682
683         /* Set the initial payload to the packet length, and the initial
684            captured payload to the capture length (other protocols may
685            reduce them if their headers say they're less). */
686         pi.len = fd->pkt_len;
687         pi.captured_len = fd->cap_len;
688
689         switch (fd->lnk_t) {
690                 case WTAP_ENCAP_ETHERNET :
691                         dissect_eth(pd, 0, fd, tree);
692                         break;
693                 case WTAP_ENCAP_FDDI :
694                         dissect_fddi(pd, fd, tree, FALSE);
695                         break;
696                 case WTAP_ENCAP_FDDI_BITSWAPPED :
697                         dissect_fddi(pd, fd, tree, TRUE);
698                         break;
699                 case WTAP_ENCAP_TR :
700                         dissect_tr(pd, 0, fd, tree);
701                         break;
702                 case WTAP_ENCAP_NULL :
703                         dissect_null(pd, fd, tree);
704                         break;
705                 case WTAP_ENCAP_PPP :
706                         dissect_ppp(pd, fd, tree);
707                         break;
708                 case WTAP_ENCAP_LAPB :
709                         dissect_lapb(pd, fd, tree);
710                         break;
711                 case WTAP_ENCAP_RAW_IP :
712                         dissect_raw(pd, fd, tree);
713                         break;
714                 case WTAP_ENCAP_LINUX_ATM_CLIP :
715                         dissect_clip(pd, fd, tree);
716                         break;
717                 case WTAP_ENCAP_ATM_SNIFFER :
718                         dissect_atm(pd, fd, tree);
719                         break;
720                 case WTAP_ENCAP_ASCEND :
721                         dissect_ascend(pd, fd, tree);
722                         break;
723         }
724 }
725
726 void
727 proto_register_frame(void)
728 {
729         static hf_register_info hf[] = {
730                 { &hf_frame_arrival_time,
731                 { "Arrival Time",               "frame.time", FT_ABSOLUTE_TIME, NULL }},
732
733                 { &hf_frame_time_delta,
734                 { "Time delta from previous packet",    "frame.time_delta", FT_RELATIVE_TIME, NULL }},
735
736                 { &hf_frame_number,
737                 { "Frame Number",               "frame.number", FT_UINT32, NULL }},
738
739                 { &hf_frame_packet_len,
740                 { "Total Frame Length",         "frame.pkt_len", FT_UINT32, NULL }},
741
742                 { &hf_frame_capture_len,
743                 { "Capture Frame Length",       "frame.cap_len", FT_UINT32, NULL }}
744         };
745
746         proto_frame = proto_register_protocol("Frame", "frame");
747         proto_register_field_array(proto_frame, hf, array_length(hf));
748 }