Neither "ether_to_str()" nor "ip_to_str()" modify the data pointed to by
[obnox/wireshark/wip.git] / packet.c
1 /* packet.c
2  * Routines for packet disassembly
3  *
4  * $Id: packet.c,v 1.17 1999/01/05 07:33: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
34 #include <gtk/gtk.h>
35
36 #include <stdio.h>
37 #include <stdarg.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <time.h>
41
42 #ifdef NEED_SNPRINTF_H
43 # include "snprintf.h"
44 #endif
45
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49
50 #include "ethereal.h"
51 #include "packet.h"
52 #include "etypes.h"
53 #include "file.h"
54
55 extern GtkWidget    *byte_view;
56 extern GdkFont      *m_r_font, *m_b_font;
57 extern capture_file  cf;
58
59 gchar *
60 ether_to_str(const guint8 *ad) {
61   static gchar  str[3][18];
62   static gchar *cur;
63
64   if (cur == &str[0][0]) {
65     cur = &str[1][0];
66   } else if (cur == &str[1][0]) {  
67     cur = &str[2][0];
68   } else {  
69     cur = &str[0][0];
70   }
71   sprintf(cur, "%02x:%02x:%02x:%02x:%02x:%02x", ad[0], ad[1], ad[2],
72     ad[3], ad[4], ad[5]);
73   return cur;
74 }
75
76 gchar *
77 ip_to_str(const guint8 *ad) {
78   static gchar  str[3][16];
79   static gchar *cur;
80
81   if (cur == &str[0][0]) {
82     cur = &str[1][0];
83   } else if (cur == &str[1][0]) {  
84     cur = &str[2][0];
85   } else {  
86     cur = &str[0][0];
87   }
88   sprintf(cur, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
89   return cur;
90 }
91
92 void
93 packet_hex_print(GtkText *bv, guchar *pd, gint len, gint bstart, gint blen) {
94   gint     i = 0, j, k, cur;
95   gchar    line[128], hexchars[] = "0123456789abcdef";
96   GdkFont *cur_font, *new_font;
97   
98   while (i < len) {
99     /* Print the line number */
100     sprintf(line, "%04x  ", i);
101     gtk_text_insert(bv, m_r_font, NULL, NULL, line, -1);
102     /* Do we start in bold? */
103     cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
104     j   = i;
105     k   = i + BYTE_VIEW_WIDTH;
106     cur = 0;
107     /* Print the hex bit */
108     while (i < k) {
109       if (i < len) {
110         line[cur++] = hexchars[(pd[i] & 0xf0) >> 4];
111         line[cur++] = hexchars[pd[i] & 0x0f];
112       } else {
113         line[cur++] = ' '; line[cur++] = ' ';
114       }
115       line[cur++] = ' ';
116       i++;
117       /* Did we cross a bold/plain boundary? */
118       new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
119       if (cur_font != new_font) {
120         gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
121         cur_font = new_font;
122         cur = 0;
123       }
124     }
125     line[cur++] = ' ';
126     gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
127     cur = 0;
128     i = j;
129     /* Print the ASCII bit */
130     cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
131     while (i < k) {
132       if (i < len) {
133         line[cur++] = (isgraph(pd[i])) ? pd[i] : '.';
134       } else {
135         line[cur++] = ' ';
136       }
137       i++;
138       /* Did we cross a bold/plain boundary? */
139       new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
140       if (cur_font != new_font) {
141         gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
142         cur_font = new_font;
143         cur = 0;
144       }
145     }
146     line[cur++] = '\n';
147     line[cur]   = '\0';
148     gtk_text_insert(bv, cur_font, NULL, NULL, line, -1);
149   }
150 }
151
152 static void
153 set_item_style(GtkWidget *widget, gpointer dummy)
154 {
155   gtk_widget_set_style(widget, item_style);
156 }
157
158 GtkWidget *
159 add_item_to_tree(GtkWidget *tree, gint start, gint len,
160   gchar *format, ...) {
161   GtkWidget *ti;
162   va_list    ap;
163   gchar      label_str[256];
164   
165   if (!tree)
166     return(NULL);
167   
168   va_start(ap, format);
169   vsnprintf(label_str, 256, format, ap);
170   ti = gtk_tree_item_new_with_label(label_str);
171   gtk_container_foreach(GTK_CONTAINER(ti), set_item_style, NULL);
172   gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_START_KEY, (gpointer) start);
173   gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_LEN_KEY, (gpointer) len);
174   gtk_tree_append(GTK_TREE(tree), ti);
175   gtk_widget_show(ti);
176
177   return ti;
178 }
179
180 void
181 set_item_len(GtkWidget *ti, gint len)
182 {
183   gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_LEN_KEY, (gpointer) len);
184 }
185
186 void
187 add_subtree(GtkWidget *ti, GtkWidget *subtree, gint idx) {
188   static gint tree_type[NUM_TREE_TYPES];
189
190   gtk_tree_item_set_subtree(GTK_TREE_ITEM(ti), subtree);
191   if (tree_type[idx])
192     gtk_tree_item_expand(GTK_TREE_ITEM(ti));
193   gtk_signal_connect(GTK_OBJECT(ti), "expand", (GtkSignalFunc) expand_tree,
194     (gpointer) &tree_type[idx]);
195   gtk_signal_connect(GTK_OBJECT(ti), "collapse", (GtkSignalFunc) collapse_tree,
196     (gpointer) &tree_type[idx]);
197 }
198
199 void
200 expand_tree(GtkWidget *w, gpointer data) {
201   gint *val = (gint *) data;
202   *val = 1;
203 }
204
205 void
206 collapse_tree(GtkWidget *w, gpointer data) {
207   gint *val = (gint *) data;
208   *val = 0;
209 }
210
211 /* Tries to match val against each element in the value_string array vs.
212    Returns the associated string ptr on a match.
213    Formats val with fmt, and returns the resulting string, on failure. */
214 gchar*
215 val_to_str(guint32 val, const value_string *vs, const char *fmt) {
216   gchar *ret;
217   static gchar  str[3][64];
218   static gchar *cur;
219
220   ret = match_strval(val, vs);
221   if (ret != NULL)
222     return ret;
223   if (cur == &str[0][0]) {
224     cur = &str[1][0];
225   } else if (cur == &str[1][0]) {  
226     cur = &str[2][0];
227   } else {  
228     cur = &str[0][0];
229   }
230   snprintf(cur, 64, fmt, val);
231   return cur;
232 }
233
234 /* Tries to match val against each element in the value_string array vs.
235    Returns the associated string ptr on a match, or NULL on failure. */
236 gchar*
237 match_strval(guint32 val, const value_string *vs) {
238   gint i = 0;
239   
240   while (vs[i].strptr) {
241     if (vs[i].value == val)
242       return(vs[i].strptr);
243     i++;
244   }
245   
246   return(NULL);
247 }
248
249 /* Checks to see if a particular packet information element is needed for
250    the packet list */
251 gint
252 check_col(frame_data *fd, gint el) {
253   int i;
254   
255   if (fd->cinfo) {
256     for (i = 0; i < fd->cinfo->num_cols; i++) {
257       if (fd->cinfo->fmt_matx[i][el])
258         return TRUE;
259     }
260   }
261   return FALSE;
262 }
263
264 /* To do: Add check_col checks to the pinfo_add* routines */
265
266 /* Adds a vararg list to a packet info string. */
267 void
268 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
269   va_list    ap;
270   int        i;
271   
272   va_start(ap, format);
273   for (i = 0; i < fd->cinfo->num_cols; i++) {
274     if (fd->cinfo->fmt_matx[i][el])
275       vsnprintf(fd->cinfo->col_data[i], COL_MAX_LEN, format, ap);
276   }
277 }
278
279 void
280 col_add_str(frame_data *fd, gint el, gchar* str) {
281   int i;
282   
283   for (i = 0; i < fd->cinfo->num_cols; i++) {
284     if (fd->cinfo->fmt_matx[i][el]) {
285       strncpy(fd->cinfo->col_data[i], str, COL_MAX_LEN);
286       fd->cinfo->col_data[i][COL_MAX_LEN - 1] = 0;
287     }
288   }
289 }
290
291 static const char *mon_names[12] = {
292         "Jan",
293         "Feb",
294         "Mar",
295         "Apr",
296         "May",
297         "Jun",
298         "Jul",
299         "Aug",
300         "Sep",
301         "Oct",
302         "Nov",
303         "Dec"
304 };
305
306 /* this routine checks the frame type from the cf structure */
307 void
308 dissect_packet(const u_char *pd, frame_data *fd, GtkTree *tree)
309 {
310         GtkWidget *fh_tree, *ti;
311         struct tm *tmp;
312         time_t then;
313 #ifdef WITH_WIRETAP
314         guint32 lnk_t;
315 #endif
316
317         /* Put in frame header information. */
318         if (check_col(fd, COL_ABS_TIME)) {
319           then = fd->abs_secs;
320           tmp = localtime(&then);
321           col_add_fstr(fd, COL_ABS_TIME, "%02d:%02d:%02d.%04ld",
322             tmp->tm_hour,
323             tmp->tm_min,                                                      
324             tmp->tm_sec,
325             (long)fd->abs_usecs/100);
326   }
327         if (check_col(fd, COL_REL_TIME)) {
328             col_add_fstr(fd, COL_REL_TIME, "%d.%06d", fd->rel_secs, fd->rel_usecs);
329         }
330         if (check_col(fd, COL_DELTA_TIME)) {
331             col_add_fstr(fd, COL_DELTA_TIME, "%d.%06d", fd->del_secs, fd->del_usecs);
332         }
333
334         if (tree) {
335           ti = add_item_to_tree(GTK_WIDGET(tree), 0, fd->cap_len,
336             "Frame (%d on wire, %d captured)",
337             fd->pkt_len, fd->cap_len);
338
339           fh_tree = gtk_tree_new();
340           add_subtree(ti, fh_tree, ETT_FRAME);
341           then = fd->abs_secs;
342           tmp = localtime(&then);
343           add_item_to_tree(fh_tree, 0, 0,
344             "Frame arrived on %s %2d, %d %02d:%02d:%02d.%04ld",
345             mon_names[tmp->tm_mon],
346             tmp->tm_mday,
347             tmp->tm_year + 1900,
348             tmp->tm_hour,
349             tmp->tm_min,                                                      
350             tmp->tm_sec,
351             (long)fd->abs_usecs/100);
352
353           add_item_to_tree(fh_tree, 0, 0, "Total frame length: %d bytes",
354             fd->pkt_len);
355           add_item_to_tree(fh_tree, 0, 0, "Capture frame length: %d bytes",
356             fd->cap_len);
357         }
358
359 #ifdef WITH_WIRETAP
360         if (cf.lnk_t == WTAP_ENCAP_PER_PACKET) {
361                 lnk_t = fd->lnk_t;
362         }
363         else {
364                 lnk_t = cf.lnk_t;
365         }
366
367         switch (lnk_t) {
368                 case WTAP_ENCAP_ETHERNET :
369                         dissect_eth(pd, fd, tree);
370                         break;
371                 case WTAP_ENCAP_FDDI :
372                         dissect_fddi(pd, fd, tree);
373                         break;
374                 case WTAP_ENCAP_TR :
375                         dissect_tr(pd, fd, tree);
376                         break;
377                 case WTAP_ENCAP_NONE :
378                         dissect_null(pd, fd, tree);
379                         break;
380                 case WTAP_ENCAP_PPP :
381                         dissect_ppp(pd, fd, tree);
382                         break;
383                 case WTAP_ENCAP_RAW_IP :
384                         dissect_raw(pd, fd, tree);
385                         break;
386         }
387 #else
388         switch (cf.lnk_t) {
389                 case DLT_EN10MB :
390                         dissect_eth(pd, fd, tree);
391                         break;
392                 case DLT_FDDI :
393                         dissect_fddi(pd, fd, tree);
394                         break;
395                 case DLT_IEEE802 :
396                         dissect_tr(pd, fd, tree);
397                         break;
398                 case DLT_NULL :
399                         dissect_null(pd, fd, tree);
400                         break;
401                 case DLT_PPP :
402                         dissect_ppp(pd, fd, tree);
403                         break;
404                 case DLT_RAW :
405                         dissect_raw(pd, fd, tree);
406                         break;
407         }
408 #endif
409 }