90d991991ec0c172b8162fe6f27b4b5d845e6332
[obnox/wireshark/wip.git] / packet.c
1 /* packet.c
2  * Routines for packet disassembly
3  *
4  * $Id: packet.c,v 1.7 1998/10/16 01:18:32 gerald 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, or NULL on failure.
199    Len is the length of the array. */
200 gchar*
201 match_strval(guint32 val, value_string *vs) {
202   gint i = 0;
203   
204   while (vs[i].strptr) {
205     if (vs[i].value == val)
206       return(vs[i].strptr);
207     i++;
208   }
209   
210   return(NULL);
211 }
212
213 static const char *mon_names[12] = {
214         "Jan",
215         "Feb",
216         "Mar",
217         "Apr",
218         "May",
219         "Jun",
220         "Jul",
221         "Aug",
222         "Sep",
223         "Oct",
224         "Nov",
225         "Dec"
226 };
227
228 /* this routine checks the frame type from the cf structure */
229 void
230 dissect_packet(const u_char *pd, guint32 ts_secs, guint32 ts_usecs,
231   frame_data *fd, GtkTree *tree)
232 {
233         GtkWidget *fh_tree, *ti;
234         struct tm *tmp;
235         time_t then;
236
237         /* Put in frame header information. */
238         if (fd->win_info[COL_NUM]) {
239           if (timestamp_type == ABSOLUTE) {
240             then = fd->secs;
241             tmp = localtime(&then);
242             sprintf(fd->win_info[COL_TIME], "%02d:%02d:%02d.%04ld",
243               tmp->tm_hour,
244               tmp->tm_min,                                                      
245               tmp->tm_sec,
246               (long)fd->usecs/100);
247           } else
248             sprintf(fd->win_info[COL_TIME], "%d.%06d", ts_secs, ts_usecs);
249         }
250
251         if (tree) {
252           ti = add_item_to_tree(GTK_WIDGET(tree), 0, fd->cap_len,
253             "Frame (%d on wire, %d captured)",
254             fd->pkt_len, fd->cap_len);
255
256           fh_tree = gtk_tree_new();
257           add_subtree(ti, fh_tree, ETT_FRAME);
258           then = fd->secs;
259           tmp = localtime(&then);
260           add_item_to_tree(fh_tree, 0, 0,
261             "Frame arrived on %s %2d, %d %02d:%02d:%02d.%04ld",
262             mon_names[tmp->tm_mon],
263             tmp->tm_mday,
264             tmp->tm_year + 1900,
265             tmp->tm_hour,
266             tmp->tm_min,                                                      
267             tmp->tm_sec,
268             (long)fd->usecs/100);
269
270           add_item_to_tree(fh_tree, 0, 0, "Total frame length: %d bytes",
271             fd->pkt_len);
272           add_item_to_tree(fh_tree, 0, 0, "Capture frame length: %d bytes",
273             fd->cap_len);
274         }
275
276         switch (cf.lnk_t) {
277                 case DLT_EN10MB :
278                         dissect_eth(pd, fd, tree);
279                         break;
280                 case DLT_FDDI :
281                         dissect_fddi(pd, fd, tree);
282                         break;
283                 case DLT_IEEE802 :
284                         dissect_tr(pd, fd, tree);
285                         break;
286                 case DLT_NULL :
287                         dissect_null(pd, fd, tree);
288                         break;
289                 case DLT_PPP :
290                         dissect_ppp(pd, fd, tree);
291                         break;
292                 case DLT_RAW :
293                         dissect_raw(pd, fd, tree);
294                         break;
295         }
296 }