Turn "arpaddr_to_str()" into "bytes_to_str()", and make it public, so it
[obnox/wireshark/wip.git] / packet.c
1 /* packet.c
2  * Routines for packet disassembly
3  *
4  * $Id: packet.c,v 1.25 1999/05/11 08:21:38 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 #include <sys/socket.h>
34
35 #include <glib.h>
36
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include <time.h>
42
43 #ifdef NEED_SNPRINTF_H
44 # include "snprintf.h"
45 #endif
46
47 #ifdef HAVE_NETINET_IN_H
48 # include <netinet/in.h>
49 #endif
50
51 #include "packet.h"
52 #include "file.h"
53
54 extern capture_file  cf;
55
56 gchar *
57 ether_to_str(const guint8 *ad) {
58   static gchar  str[3][18];
59   static gchar *cur;
60
61   if (cur == &str[0][0]) {
62     cur = &str[1][0];
63   } else if (cur == &str[1][0]) {  
64     cur = &str[2][0];
65   } else {  
66     cur = &str[0][0];
67   }
68   sprintf(cur, "%02x:%02x:%02x:%02x:%02x:%02x", ad[0], ad[1], ad[2],
69     ad[3], ad[4], ad[5]);
70   return cur;
71 }
72
73 gchar *
74 ip_to_str(const guint8 *ad) {
75   static gchar  str[3][16];
76   static gchar *cur;
77
78   if (cur == &str[0][0]) {
79     cur = &str[1][0];
80   } else if (cur == &str[1][0]) {  
81     cur = &str[2][0];
82   } else {  
83     cur = &str[0][0];
84   }
85   sprintf(cur, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
86   return cur;
87 }
88
89 #define PLURALIZE(n)    (((n) > 1) ? "s" : "")
90 #define COMMA(do_it)    ((do_it) ? ", " : "")
91
92 gchar *
93 time_secs_to_str(guint32 time)
94 {
95   static gchar  str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
96   static gchar *cur, *p;
97   int hours, mins, secs;
98   int do_comma;
99
100   if (cur == &str[0][0]) {
101     cur = &str[1][0];
102   } else if (cur == &str[1][0]) {  
103     cur = &str[2][0];
104   } else {  
105     cur = &str[0][0];
106   }
107
108   secs = time % 60;
109   time /= 60;
110   mins = time % 60;
111   time /= 60;
112   hours = time % 24;
113   time /= 24;
114
115   p = cur;
116   if (time != 0) {
117     sprintf(p, "%u day%s", time, PLURALIZE(time));
118     p += strlen(p);
119     do_comma = 1;
120   } else
121     do_comma = 0;
122   if (hours != 0) {
123     sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
124     p += strlen(p);
125     do_comma = 1;
126   } else
127     do_comma = 0;
128   if (mins != 0) {
129     sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
130     p += strlen(p);
131     do_comma = 1;
132   } else
133     do_comma = 0;
134   if (secs != 0)
135     sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
136   return cur;
137 }
138
139 /* Max string length for displaying byte string.  */
140 #define MAX_BYTE_STR_LEN        16
141
142 /* Turn an array of bytes into a string showing the bytes in hex. */
143 gchar *
144 bytes_to_str(const guint8 *bd, int bd_len) {
145   static gchar  str[3][MAX_BYTE_STR_LEN+3+1];
146   static gchar *cur;
147   gchar        *p;
148   int           len;
149   static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
150                                 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
151
152   if (cur == &str[0][0]) {
153     cur = &str[1][0];
154   } else if (cur == &str[1][0]) {  
155     cur = &str[2][0];
156   } else {  
157     cur = &str[0][0];
158   }
159   p = cur;
160   len = MAX_BYTE_STR_LEN;
161   while (bd_len > 0 && len > 0) {
162     *p++ = hex[(*bd) >> 4];
163     *p++ = hex[(*bd) & 0xF];
164     len -= 2;
165     bd++;
166     bd_len--;
167   }
168   if (bd_len != 0) {
169     /* Note that we're not showing the full string.  */
170     *p++ = '.';
171     *p++ = '.';
172     *p++ = '.';
173   }
174   *p = '\0';
175   return cur;
176 }
177
178 /*
179  * Given a pointer into a data buffer, and to the end of the buffer,
180  * find the end of the (putative) line at that position in the data
181  * buffer.
182  * Return a pointer to the EOL character(s) in "*eol".
183  */
184 const u_char *
185 find_line_end(const u_char *data, const u_char *dataend, const u_char **eol)
186 {
187   const u_char *lineend;
188
189   lineend = memchr(data, '\n', dataend - data);
190   if (lineend == NULL) {
191     /*
192      * No LF - line is probably continued in next TCP segment.
193      */
194     lineend = dataend;
195     *eol = dataend;
196   } else {
197     /*
198      * Is the LF at the beginning of the line?
199      */
200     if (lineend > data) {
201       /*
202        * No - is it preceded by a carriage return?
203        * (Perhaps it's supposed to be, but that's not guaranteed....)
204        */
205       if (*(lineend - 1) == '\r') {
206         /*
207          * Yes.  The EOL starts with the CR.
208          */
209         *eol = lineend - 1;
210       } else {
211         /*
212          * No.  The EOL starts with the LF.
213          */
214         *eol = lineend;
215
216         /*
217          * I seem to remember that we once saw lines ending with LF-CR
218          * in an HTTP request or response, so check if it's *followed*
219          * by a carriage return.
220          */
221         if (lineend < (dataend - 1) && *(lineend + 1) == '\r') {
222           /*
223            * It's <non-LF><LF><CR>; say it ends with the CR.
224            */
225           lineend++;
226         }
227       }
228     }
229
230     /*
231      * Point to the character after the last character.
232      */
233     lineend++;
234   }
235   return lineend;
236 }
237
238 #define MAX_COLUMNS_LINE_DETAIL 62
239
240 /*
241  * Get the length of the next token in a line, and the beginning of the
242  * next token after that (if any).
243  * Return 0 if there is no next token.
244  */
245 int
246 get_token_len(const u_char *linep, const u_char *lineend,
247               const u_char **next_token)
248 {
249   const u_char *tokenp;
250   int token_len;
251
252   tokenp = linep;
253   
254   /*
255    * Search for a blank, a CR or an LF, or the end of the buffer.
256    */
257   while (linep < lineend && *linep != ' ' && *linep != '\r' && *linep != '\n')
258       linep++;
259   token_len = linep - tokenp;
260
261   /*
262    * Skip trailing blanks.
263    */
264   while (linep < lineend && *linep == ' ')
265     linep++;
266
267   *next_token = linep;
268
269   return token_len;
270 }
271
272 /*
273  * Given a string, generate a string from it that shows non-printable
274  * characters as C-style escapes, and return a pointer to it.
275  */
276 gchar *
277 format_text(const u_char *string, int len)
278 {
279   static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
280   gchar *fmtbufp;
281   int column;
282   const u_char *stringend = string + len;
283   u_char c;
284   int i;
285
286   column = 0;
287   fmtbufp = &fmtbuf[0];
288   while (string < stringend) {
289     if (column >= MAX_COLUMNS_LINE_DETAIL) {
290       /*
291        * Put "..." and quit.
292        */
293       strcpy(fmtbufp, " ...");
294       break;
295     }
296     c = *string++;
297     if (isprint(c)) {
298       *fmtbufp++ = c;
299       column++;
300     } else {
301       *fmtbufp++ =  '\\';
302       column++;
303       switch (c) {
304
305       case '\\':
306         *fmtbufp++ = '\\';
307         column++;
308         break;
309
310       case '\a':
311         *fmtbufp++ = 'a';
312         column++;
313         break;
314
315       case '\b':
316         *fmtbufp++ = 'b';
317         column++;
318         break;
319
320       case '\f':
321         *fmtbufp++ = 'f';
322         column++;
323         break;
324
325       case '\n':
326         *fmtbufp++ = 'n';
327         column++;
328         break;
329
330       case '\r':
331         *fmtbufp++ = 'r';
332         column++;
333         break;
334
335       case '\t':
336         *fmtbufp++ = 't';
337         column++;
338         break;
339
340       case '\v':
341         *fmtbufp++ = 'v';
342         column++;
343         break;
344
345       default:
346         i = (c>>6)&03;
347         *fmtbufp++ = i + '0';
348         column++;
349         i = (c>>3)&07;
350         *fmtbufp++ = i + '0';
351         column++;
352         i = (c>>0)&07;
353         *fmtbufp++ = i + '0';
354         column++;
355         break;
356       }
357     }
358   }
359   *fmtbufp = '\0';
360   return fmtbuf;
361 }
362
363
364 /* Tries to match val against each element in the value_string array vs.
365    Returns the associated string ptr on a match.
366    Formats val with fmt, and returns the resulting string, on failure. */
367 gchar*
368 val_to_str(guint32 val, const value_string *vs, const char *fmt) {
369   gchar *ret;
370   static gchar  str[3][64];
371   static gchar *cur;
372
373   ret = match_strval(val, vs);
374   if (ret != NULL)
375     return ret;
376   if (cur == &str[0][0]) {
377     cur = &str[1][0];
378   } else if (cur == &str[1][0]) {  
379     cur = &str[2][0];
380   } else {  
381     cur = &str[0][0];
382   }
383   snprintf(cur, 64, fmt, val);
384   return cur;
385 }
386
387 /* Tries to match val against each element in the value_string array vs.
388    Returns the associated string ptr on a match, or NULL on failure. */
389 gchar*
390 match_strval(guint32 val, const value_string *vs) {
391   gint i = 0;
392   
393   while (vs[i].strptr) {
394     if (vs[i].value == val)
395       return(vs[i].strptr);
396     i++;
397   }
398   
399   return(NULL);
400 }
401
402 /* Generate, into "buf", a string showing the bits of a bitfield.
403    Return a pointer to the character after that string. */
404 static char *
405 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
406 {
407   int i;
408   guint32 bit;
409   char *p;
410
411   i = 0;
412   p = buf;
413   bit = 1 << (width - 1);
414   for (;;) {
415     if (mask & bit) {
416       /* This bit is part of the field.  Show its value. */
417       if (val & bit)
418         *p++ = '1';
419       else
420         *p++ = '0';
421     } else {
422       /* This bit is not part of the field. */
423       *p++ = '.';
424     }
425     bit >>= 1;
426     i++;
427     if (i >= width)
428       break;
429     if (i % 4 == 0)
430       *p++ = ' ';
431   }
432   strcpy(p, " = ");
433   p += 3;
434   return p;
435 }
436
437 /* Generate a string describing a Boolean bitfield (a one-bit field that
438    says something is either true of false). */
439 const char *
440 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
441     const char *truedesc, const char *falsedesc)
442 {
443   static char buf[1025];
444   char *p;
445
446   p = decode_bitfield_value(buf, val, mask, width);
447   if (val & mask)
448     strcpy(p, truedesc);
449   else
450     strcpy(p, falsedesc);
451   return buf;
452 }
453
454 /* Generate a string describing an enumerated bitfield (an N-bit field
455    with various specific values having particular names). */
456 const char *
457 decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
458     const value_string *tab, const char *fmt)
459 {
460   static char buf[1025];
461   char *p;
462
463   p = decode_bitfield_value(buf, val, mask, width);
464   sprintf(p, fmt, val_to_str(val & mask, tab, "Unknown"));
465   return buf;
466 }
467
468 /* Generate a string describing a numeric bitfield (an N-bit field whose
469    value is just a number). */
470 const char *
471 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
472     const char *fmt)
473 {
474   static char buf[1025];
475   char *p;
476
477   p = decode_bitfield_value(buf, val, mask, width);
478   sprintf(p, fmt, val & mask);
479   return buf;
480 }
481
482 /* Checks to see if a particular packet information element is needed for
483    the packet list */
484 gint
485 check_col(frame_data *fd, gint el) {
486   int i;
487   
488   if (fd->cinfo) {
489     for (i = 0; i < fd->cinfo->num_cols; i++) {
490       if (fd->cinfo->fmt_matx[i][el])
491         return TRUE;
492     }
493   }
494   return FALSE;
495 }
496
497 /* To do: Add check_col checks to the pinfo_add* routines */
498
499 /* Adds a vararg list to a packet info string. */
500 void
501 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
502   va_list    ap;
503   int        i;
504   
505   va_start(ap, format);
506   for (i = 0; i < fd->cinfo->num_cols; i++) {
507     if (fd->cinfo->fmt_matx[i][el])
508       vsnprintf(fd->cinfo->col_data[i], COL_MAX_LEN, format, ap);
509   }
510 }
511
512 void
513 col_add_str(frame_data *fd, gint el, gchar* str) {
514   int i;
515   
516   for (i = 0; i < fd->cinfo->num_cols; i++) {
517     if (fd->cinfo->fmt_matx[i][el]) {
518       strncpy(fd->cinfo->col_data[i], str, COL_MAX_LEN);
519       fd->cinfo->col_data[i][COL_MAX_LEN - 1] = 0;
520     }
521   }
522 }
523
524 static const char *mon_names[12] = {
525         "Jan",
526         "Feb",
527         "Mar",
528         "Apr",
529         "May",
530         "Jun",
531         "Jul",
532         "Aug",
533         "Sep",
534         "Oct",
535         "Nov",
536         "Dec"
537 };
538
539 /* this routine checks the frame type from the cf structure */
540 void
541 dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
542 {
543         proto_tree *fh_tree;
544         proto_item *ti;
545         struct tm *tmp;
546         time_t then;
547
548         /* Put in frame header information. */
549         if (check_col(fd, COL_ABS_TIME)) {
550           then = fd->abs_secs;
551           tmp = localtime(&then);
552           col_add_fstr(fd, COL_ABS_TIME, "%02d:%02d:%02d.%04ld",
553             tmp->tm_hour,
554             tmp->tm_min,                                                      
555             tmp->tm_sec,
556             (long)fd->abs_usecs/100);
557   }
558         if (check_col(fd, COL_REL_TIME)) {
559             col_add_fstr(fd, COL_REL_TIME, "%d.%06d", fd->rel_secs, fd->rel_usecs);
560         }
561         if (check_col(fd, COL_DELTA_TIME)) {
562             col_add_fstr(fd, COL_DELTA_TIME, "%d.%06d", fd->del_secs, fd->del_usecs);
563         }
564
565         if (tree) {
566           ti = proto_tree_add_item(tree, 0, fd->cap_len,
567             "Frame (%d on wire, %d captured)",
568             fd->pkt_len, fd->cap_len);
569
570           fh_tree = proto_tree_new();
571           proto_item_add_subtree(ti, fh_tree, ETT_FRAME);
572           then = fd->abs_secs;
573           tmp = localtime(&then);
574           proto_tree_add_item(fh_tree, 0, 0,
575             "Frame arrived on %s %2d, %d %02d:%02d:%02d.%04ld",
576             mon_names[tmp->tm_mon],
577             tmp->tm_mday,
578             tmp->tm_year + 1900,
579             tmp->tm_hour,
580             tmp->tm_min,                                                      
581             tmp->tm_sec,
582             (long)fd->abs_usecs/100);
583
584           proto_tree_add_item(fh_tree, 0, 0, "Total frame length: %d bytes",
585             fd->pkt_len);
586           proto_tree_add_item(fh_tree, 0, 0, "Capture frame length: %d bytes",
587             fd->cap_len);
588         }
589
590 #ifdef WITH_WIRETAP
591         switch (fd->lnk_t) {
592                 case WTAP_ENCAP_ETHERNET :
593                         dissect_eth(pd, fd, tree);
594                         break;
595                 case WTAP_ENCAP_FDDI :
596                         dissect_fddi(pd, fd, tree);
597                         break;
598                 case WTAP_ENCAP_TR :
599                         dissect_tr(pd, fd, tree);
600                         break;
601                 case WTAP_ENCAP_NONE :
602                         dissect_null(pd, fd, tree);
603                         break;
604                 case WTAP_ENCAP_PPP :
605                         dissect_ppp(pd, fd, tree);
606                         break;
607                 case WTAP_ENCAP_RAW_IP :
608                         dissect_raw(pd, fd, tree);
609                         break;
610         }
611 #else
612         switch (cf.lnk_t) {
613                 case DLT_EN10MB :
614                         dissect_eth(pd, fd, tree);
615                         break;
616                 case DLT_FDDI :
617                         dissect_fddi(pd, fd, tree);
618                         break;
619                 case DLT_IEEE802 :
620                         dissect_tr(pd, fd, tree);
621                         break;
622                 case DLT_NULL :
623                         dissect_null(pd, fd, tree);
624                         break;
625                 case DLT_PPP :
626                         dissect_ppp(pd, fd, tree);
627                         break;
628                 case DLT_RAW :
629                         dissect_raw(pd, fd, tree);
630                         break;
631         }
632 #endif
633 }