A lengthy patch to add the wiretap library. Wiretap is not used by default
[obnox/wireshark/wip.git] / packet.c
1 /* packet.c
2  * Routines for packet disassembly
3  *
4  * $Id: packet.c,v 1.10 1998/11/12 00:06:40 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 #include <gtk/gtk.h>
35
36 #include <stdio.h>
37 #include <stdarg.h>
38 #include <ctype.h>
39 #include <time.h>
40
41 #ifdef NEED_SNPRINTF_H
42 # include "snprintf.h"
43 #endif
44
45 #ifdef HAVE_NETINET_IN_H
46 # include <netinet/in.h>
47 #endif
48
49 #include "ethereal.h"
50 #include "packet.h"
51 #include "etypes.h"
52 #include "file.h"
53
54 extern GtkWidget    *byte_view;
55 extern GdkFont      *m_r_font, *m_b_font;
56 extern capture_file  cf;
57
58 gchar *
59 ether_to_str(guint8 *ad) {
60   static gchar  str[3][18];
61   static gchar *cur;
62
63   if (cur == &str[0][0]) {
64     cur = &str[1][0];
65   } else if (cur == &str[1][0]) {  
66     cur = &str[2][0];
67   } else {  
68     cur = &str[0][0];
69   }
70   sprintf(cur, "%02x:%02x:%02x:%02x:%02x:%02x", ad[0], ad[1], ad[2],
71     ad[3], ad[4], ad[5]);
72   return cur;
73 }
74
75 gchar *
76 ip_to_str(guint8 *ad) {
77   static gchar  str[3][16];
78   static gchar *cur;
79
80   if (cur == &str[0][0]) {
81     cur = &str[1][0];
82   } else if (cur == &str[1][0]) {  
83     cur = &str[2][0];
84   } else {  
85     cur = &str[0][0];
86   }
87   sprintf(cur, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
88   return cur;
89 }
90
91 void
92 packet_hex_print(GtkText *bv, guchar *pd, gint len, gint bstart, gint blen) {
93   gint     i = 0, j, k, cur;
94   gchar    line[128], hexchars[] = "0123456789abcdef";
95   GdkFont *cur_font, *new_font;
96   
97   while (i < len) {
98     /* Print the line number */
99     sprintf(line, "%04x  ", i);
100     gtk_text_insert(bv, m_r_font, NULL, NULL, line, -1);
101     /* Do we start in bold? */
102     cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
103     j   = i;
104     k   = i + BYTE_VIEW_WIDTH;
105     cur = 0;
106     /* Print the hex bit */
107     while (i < k) {
108       if (i < len) {
109         line[cur++] = hexchars[(pd[i] & 0xf0) >> 4];
110         line[cur++] = hexchars[pd[i] & 0x0f];
111       } else {
112         line[cur++] = ' '; line[cur++] = ' ';
113       }
114       line[cur++] = ' ';
115       i++;
116       /* Did we cross a bold/plain boundary? */
117       new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
118       if (cur_font != new_font) {
119         gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
120         cur_font = new_font;
121         cur = 0;
122       }
123     }
124     line[cur++] = ' ';
125     gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
126     cur = 0;
127     i = j;
128     /* Print the ASCII bit */
129     cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
130     while (i < k) {
131       if (i < len) {
132         line[cur++] = (isgraph(pd[i])) ? pd[i] : '.';
133       } else {
134         line[cur++] = ' ';
135       }
136       i++;
137       /* Did we cross a bold/plain boundary? */
138       new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
139       if (cur_font != new_font) {
140         gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
141         cur_font = new_font;
142         cur = 0;
143       }
144     }
145     line[cur++] = '\n';
146     line[cur]   = '\0';
147     gtk_text_insert(bv, cur_font, NULL, NULL, line, -1);
148   }
149 }
150
151 GtkWidget *
152 add_item_to_tree(GtkWidget *tree, gint start, gint len,
153   gchar *format, ...) {
154   GtkWidget *ti;
155   va_list    ap;
156   gchar      label_str[256];
157   
158   /* This limits us to a max packet size of 65535 bytes. */
159   /* Are there any systems out there with < 32-bit pointers? */
160   /* To do: use gtk_object_set_data instead, now that I know it exists. */
161   va_start(ap, format);
162   vsnprintf(label_str, 256, format, ap);
163   ti = gtk_tree_item_new_with_label(label_str);
164   gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_START_KEY, (gpointer) start);
165   gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_LEN_KEY, (gpointer) len);
166   gtk_tree_append(GTK_TREE(tree), ti);
167   gtk_widget_show(ti);
168
169   return ti;
170 }
171
172 void
173 add_subtree(GtkWidget *ti, GtkWidget *subtree, gint idx) {
174   static gint tree_type[NUM_TREE_TYPES];
175
176   gtk_tree_item_set_subtree(GTK_TREE_ITEM(ti), subtree);
177   if (tree_type[idx])
178     gtk_tree_item_expand(GTK_TREE_ITEM(ti));
179   gtk_signal_connect(GTK_OBJECT(ti), "expand", (GtkSignalFunc) expand_tree,
180     (gpointer) &tree_type[idx]);
181   gtk_signal_connect(GTK_OBJECT(ti), "collapse", (GtkSignalFunc) collapse_tree,
182     (gpointer) &tree_type[idx]);
183 }
184
185 void
186 expand_tree(GtkWidget *w, gpointer data) {
187   gint *val = (gint *) data;
188   *val = 1;
189 }
190
191 void
192 collapse_tree(GtkWidget *w, gpointer data) {
193   gint *val = (gint *) data;
194   *val = 0;
195 }
196
197 /* Tries to match val against each element in the value_string array vs.
198    Returns the associated string ptr on a match.
199    Formats val with fmt, and returns the resulting string, on failure. */
200 gchar*
201 val_to_str(guint32 val, const value_string *vs, const char *fmt) {
202   gchar *ret;
203   static gchar  str[3][64];
204   static gchar *cur;
205
206   ret = match_strval(val, vs);
207   if (ret != NULL)
208     return ret;
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   snprintf(cur, 64, fmt, val);
217   return cur;
218 }
219
220 /* Tries to match val against each element in the value_string array vs.
221    Returns the associated string ptr on a match, or NULL on failure. */
222 gchar*
223 match_strval(guint32 val, const value_string *vs) {
224   gint i = 0;
225   
226   while (vs[i].strptr) {
227     if (vs[i].value == val)
228       return(vs[i].strptr);
229     i++;
230   }
231   
232   return(NULL);
233 }
234
235 static const char *mon_names[12] = {
236         "Jan",
237         "Feb",
238         "Mar",
239         "Apr",
240         "May",
241         "Jun",
242         "Jul",
243         "Aug",
244         "Sep",
245         "Oct",
246         "Nov",
247         "Dec"
248 };
249
250 /* this routine checks the frame type from the cf structure */
251 void
252 dissect_packet(const u_char *pd, guint32 ts_secs, guint32 ts_usecs,
253   frame_data *fd, GtkTree *tree)
254 {
255         GtkWidget *fh_tree, *ti;
256         struct tm *tmp;
257         time_t then;
258
259         /* Put in frame header information. */
260         if (fd->win_info[COL_NUM]) {
261           if (timestamp_type == ABSOLUTE) {
262             then = fd->secs;
263             tmp = localtime(&then);
264             sprintf(fd->win_info[COL_TIME], "%02d:%02d:%02d.%04ld",
265               tmp->tm_hour,
266               tmp->tm_min,                                                      
267               tmp->tm_sec,
268               (long)fd->usecs/100);
269           } else
270             sprintf(fd->win_info[COL_TIME], "%d.%06d", ts_secs, ts_usecs);
271         }
272
273         if (tree) {
274           ti = add_item_to_tree(GTK_WIDGET(tree), 0, fd->cap_len,
275             "Frame (%d on wire, %d captured)",
276             fd->pkt_len, fd->cap_len);
277
278           fh_tree = gtk_tree_new();
279           add_subtree(ti, fh_tree, ETT_FRAME);
280           then = fd->secs;
281           tmp = localtime(&then);
282           add_item_to_tree(fh_tree, 0, 0,
283             "Frame arrived on %s %2d, %d %02d:%02d:%02d.%04ld",
284             mon_names[tmp->tm_mon],
285             tmp->tm_mday,
286             tmp->tm_year + 1900,
287             tmp->tm_hour,
288             tmp->tm_min,                                                      
289             tmp->tm_sec,
290             (long)fd->usecs/100);
291
292           add_item_to_tree(fh_tree, 0, 0, "Total frame length: %d bytes",
293             fd->pkt_len);
294           add_item_to_tree(fh_tree, 0, 0, "Capture frame length: %d bytes",
295             fd->cap_len);
296         }
297
298 #ifdef WITH_WIRETAP
299         switch (cf.lnk_t) {
300                 case WTAP_ENCAP_ETHERNET :
301                         dissect_eth(pd, fd, tree);
302                         break;
303                 case WTAP_ENCAP_FDDI :
304                         dissect_fddi(pd, fd, tree);
305                         break;
306                 case WTAP_ENCAP_TR :
307                         dissect_tr(pd, fd, tree);
308                         break;
309                 case WTAP_ENCAP_NONE :
310                         dissect_null(pd, fd, tree);
311                         break;
312                 case WTAP_ENCAP_PPP :
313                         dissect_ppp(pd, fd, tree);
314                         break;
315                 case WTAP_ENCAP_RAW_IP :
316                         dissect_raw(pd, fd, tree);
317                         break;
318         }
319 #else
320         switch (cf.lnk_t) {
321                 case DLT_EN10MB :
322                         dissect_eth(pd, fd, tree);
323                         break;
324                 case DLT_FDDI :
325                         dissect_fddi(pd, fd, tree);
326                         break;
327                 case DLT_IEEE802 :
328                         dissect_tr(pd, fd, tree);
329                         break;
330                 case DLT_NULL :
331                         dissect_null(pd, fd, tree);
332                         break;
333                 case DLT_PPP :
334                         dissect_ppp(pd, fd, tree);
335                         break;
336                 case DLT_RAW :
337                         dissect_raw(pd, fd, tree);
338                         break;
339         }
340 #endif
341 }