4 * $Id: file.c,v 1.11 1998/11/12 00:06:20 gram Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
42 #ifdef NEED_SNPRINTF_H
48 # include "snprintf.h"
51 #ifdef HAVE_SYS_TYPES_H
52 # include <sys/types.h>
55 #ifdef HAVE_NETINET_IN_H
56 # include <netinet/in.h>
65 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
66 extern guint file_ctx;
68 static guint32 ssec, susec;
69 static guint32 lastsec, lastusec;
72 open_cap_file(char *fname, capture_file *cf) {
76 char err_str[PCAP_ERRBUF_SIZE];
79 /* First, make sure the file is valid */
80 if (stat(fname, &cf_stat)) {
81 simple_dialog(ESD_TYPE_WARN, NULL, "File does not exist.");
84 if (! S_ISREG(cf_stat.st_mode) && ! S_ISFIFO(cf_stat.st_mode)) {
85 simple_dialog(ESD_TYPE_WARN, NULL, "The file you have chosen is invalid.");
89 /* Next, try to open the file */
90 cf->fh = fopen(fname, "r");
94 fseek(cf->fh, 0L, SEEK_END);
95 cf->f_len = ftell(cf->fh);
97 fseek(cf->fh, 0L, SEEK_SET);
98 fread(magic, sizeof(guint32), 2, cf->fh);
99 fseek(cf->fh, 0L, SEEK_SET);
103 /* set the file name beacuse we need it to set the follow stream filter */
104 cf->filename = g_strdup( fname );
106 /* Next, find out what type of file we're dealing with */
108 cf->cd_t = WTAP_FILE_UNKNOWN;
109 cf->lnk_t = WTAP_ENCAP_NONE;
111 cf->cd_t = CD_UNKNOWN;
112 cf->lnk_t = DLT_NULL;
120 if (cf->plist == NULL) {
121 cf->plist = g_list_alloc();
122 cf->plist->data = (frame_data *) g_malloc(sizeof(frame_data));
124 cf->plist = g_list_first(cf->plist);
127 lastsec = 0, lastusec = 0;
130 if (magic[0] == PCAP_MAGIC || magic[0] == SWAP32(PCAP_MAGIC)) {
132 /* Pcap/Tcpdump file */
133 cf->pfh = pcap_open_offline(fname, err_str);
134 if (cf->pfh == NULL) {
136 cf->wth = wtap_open_offline(fname, WTAP_FILE_UNKNOWN);
137 if (cf->wth == NULL) {
140 simple_dialog(ESD_TYPE_WARN, NULL, "Could not open file.");
146 if (pcap_compile(cf->pfh, &cf->fcode, cf->dfilter, 1, 0) < 0) {
147 simple_dialog(ESD_TYPE_WARN, NULL, "Unable to parse filter string "
148 "\"%s\".", cf->dfilter);
149 } else if (pcap_setfilter(cf->pfh, &cf->fcode) < 0) {
150 simple_dialog(ESD_TYPE_WARN, NULL, "Can't install filter.");
154 cf->fh = pcap_file(cf->pfh);
155 cf->swap = pcap_is_swapped(cf->pfh);
156 if ((cf->swap && BYTE_ORDER == BIG_ENDIAN) ||
157 (!cf->swap && BYTE_ORDER == LITTLE_ENDIAN)) {
158 /* Data is big-endian */
159 cf->cd_t = CD_PCAP_BE;
161 cf->cd_t = CD_PCAP_LE;
163 cf->vers = ( ((pcap_major_version(cf->pfh) & 0x0000ffff) << 16) |
164 pcap_minor_version(cf->pfh) );
165 cf->snap = pcap_snapshot(cf->pfh);
166 cf->lnk_t = pcap_datalink(cf->pfh);
167 } else if (ntohl(magic[0]) == SNOOP_MAGIC_1 && ntohl(magic[1]) == SNOOP_MAGIC_2) {
169 simple_dialog(ESD_TYPE_WARN, NULL, "The snoop format is not yet supported.");
172 fread(&sfh, sizeof(snoop_file_hdr), 1, cf->fh);
174 cf->vers = ntohl(sfh.vers);
175 if (cf->vers < SNOOP_MIN_VERSION || cf->vers > SNOOP_MAX_VERSION) {
176 g_warning("ethereal:open_cap_file:%s:bad snoop file version(%d)",
180 switch (ntohl(sfh.s_lnk_t)) {
182 cf->lnk_t = DLT_EN10MB;
188 if (cf->cd_t == CD_UNKNOWN) {
189 simple_dialog(ESD_TYPE_WARN, NULL, "Can't determine file type.");
193 cf->fh = wtap_file(cf->wth);
194 cf->cd_t = wtap_file_type(cf->wth);
195 cf->snap = wtap_snapshot_length(cf->wth);
196 cf->lnk_t = wtap_encapsulation(cf->wth);
202 /* Reset everything to a pristine state */
204 close_cap_file(capture_file *cf, GtkWidget *w, guint context) {
220 gtk_text_freeze(GTK_TEXT(byte_view));
221 gtk_text_set_point(GTK_TEXT(byte_view), 0);
222 gtk_text_forward_delete(GTK_TEXT(byte_view),
223 gtk_text_get_length(GTK_TEXT(byte_view)));
224 gtk_text_thaw(GTK_TEXT(byte_view));
225 gtk_tree_clear_items(GTK_TREE(tree_view), 0,
226 g_list_length(GTK_TREE(tree_view)->children));
228 gtk_clist_freeze(GTK_CLIST(packet_list));
229 gtk_clist_clear(GTK_CLIST(packet_list));
230 gtk_clist_thaw(GTK_CLIST(packet_list));
231 gtk_statusbar_pop(GTK_STATUSBAR(w), context);
235 load_cap_file(char *fname, capture_file *cf) {
236 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
237 gchar *done_fmt = " File: %s Drops: %d";
238 gchar *err_fmt = " Error: Could not load '%s'";
243 close_cap_file(cf, info_bar, file_ctx);
245 if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
249 load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2);
250 sprintf(load_msg, load_fmt, name_ptr);
251 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
253 timeout = gtk_timeout_add(250, file_progress_cb, (gpointer) &cf);
255 err = open_cap_file(fname, cf);
257 if ((err == 0) && (cf->cd_t != WTAP_FILE_UNKNOWN)) {
259 if ((err == 0) && (cf->cd_t != CD_UNKNOWN)) {
261 gtk_clist_freeze(GTK_CLIST(packet_list));
263 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
267 pcap_loop(cf->pfh, 0, pcap_dispatch_cb, (u_char *) cf);
271 cf->plist = g_list_first(cf->plist);
272 cf->fh = fopen(fname, "r");
273 gtk_clist_thaw(GTK_CLIST(packet_list));
276 gtk_timeout_remove(timeout);
277 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
279 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
282 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
283 load_msg = g_realloc(load_msg, msg_len);
284 snprintf(load_msg, msg_len, done_fmt, name_ptr, cf->drops);
285 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
289 set_menu_sensitivity("<Main>/File/Close", TRUE);
290 set_menu_sensitivity("<Main>/File/Reload", TRUE);
292 msg_len = strlen(name_ptr) + strlen(err_fmt) + 2;
293 load_msg = g_realloc(load_msg, msg_len);
294 snprintf(load_msg, msg_len, err_fmt, name_ptr);
295 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
297 set_menu_sensitivity("<Main>/File/Close", FALSE);
298 set_menu_sensitivity("<Main>/File/Reload", FALSE);
306 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr,
308 pcap_dispatch_cb(u_char *user, const struct pcap_pkthdr *phdr,
312 /* To do: make sure this is big enough. */
313 gchar p_info[NUM_COLS][256];
315 capture_file *cf = (capture_file *) user;
316 guint32 tssecs, tsusecs;
318 while (gtk_events_pending())
319 gtk_main_iteration();
321 fdata = cf->plist->data;
325 fdata->pkt_len = phdr->len;
326 fdata->cap_len = phdr->caplen;
327 fdata->file_off = ftell(cf->fh) - phdr->caplen;
328 fdata->secs = phdr->ts.tv_sec;
329 fdata->usecs = phdr->ts.tv_usec;
331 /* If we don't have the time stamp of the first packet, it's because this
332 is the first packet. Save the time stamp of this packet as the time
333 stamp of the first packet. */
334 if (!ssec && !susec) {
336 susec = fdata->usecs;
339 /* Do the same for the time stamp of the previous packet. */
340 if (!lastsec && !lastusec) {
341 lastsec = fdata->secs;
342 lastusec = fdata->usecs;
345 /* Get the time elapsed between the first packet and this packet. */
346 cf->esec = fdata->secs - ssec;
347 if (susec <= fdata->usecs) {
348 cf->eusec = fdata->usecs - susec;
350 cf->eusec = (fdata->usecs + 1000000) - susec;
354 /* Compute the time stamp. */
355 switch (timestamp_type) {
356 case RELATIVE: /* Relative to the first packet */
360 case DELTA: /* Relative to the previous packet */
361 tssecs = fdata->secs - lastsec;
362 if (lastusec <= fdata->usecs) {
363 tsusecs = fdata->usecs - lastusec;
365 tsusecs = (fdata->usecs + 1000000) - lastusec;
369 default: /* Absolute time, or bogus timestamp_type value */
370 tssecs = 0; /* Not used */
374 for (i = 0; i < NUM_COLS; i++) { fdata->win_info[i] = &p_info[i][0]; }
375 sprintf(fdata->win_info[COL_NUM], "%d", cf->count);
376 dissect_packet(buf, tssecs, tsusecs, fdata, NULL);
377 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->win_info);
378 for (i = 0; i < NUM_COLS; i++) { fdata->win_info[i] = NULL; }
380 /* Make sure we always have an available list entry */
381 if (cf->plist->next == NULL) {
382 fdata = (frame_data *) g_malloc(sizeof(frame_data));
383 g_list_append(cf->plist, (gpointer) fdata);
385 cf->plist = cf->plist->next;
388 /* Uncomment when we handle snoop files again.
391 read_frame_header(capture_file *cf) {
392 snoop_frame_hdr shdr;
394 gint16 pkt_len, cap_len;
399 if ((cf->cd_t == CD_PCAP_BE) || (cf->cd_t == CD_PCAP_LE)) {
400 err = fread((char *)&phdr, sizeof(pcap_frame_hdr), 1, cf->fh);
401 if (!err) { return err; }
402 fdata = (frame_data *) g_malloc(sizeof(frame_data));
404 pkt_len = SWAP32(phdr.pkt_len);
405 cap_len = SWAP32(phdr.cap_len);
406 secs = SWAP32(phdr.tm.tv_sec);
407 usecs = SWAP32(phdr.tm.tv_usec);
409 pkt_len = phdr.pkt_len;
410 cap_len = phdr.cap_len;
411 secs = phdr.tm.tv_sec;
412 usecs = phdr.tm.tv_usec;
414 } else if (cf->cd_t == CD_SNOOP) {
415 err = fread(&shdr, sizeof(snoop_frame_hdr), 1, cf->fh);
416 fdata = (frame_data *) g_malloc(sizeof(frame_data));
417 if (!err) { return err; }
418 pkt_len = ntohl(shdr.inc_len);
419 cap_len = ntohl(shdr.pr_len) - 24;
420 secs = ntohl(shdr.secs);
421 usecs = ntohl(shdr.usecs);
422 shdr.drops = ntohl(shdr.drops);
423 if (!ssec && !susec) { ssec = secs; susec = usecs; }
424 cf->drops = shdr.drops;
425 cf->esec = secs - ssec;
426 if (susec < shdr.usecs) {
427 cf->eusec = usecs - susec;
429 cf->eusec = susec - usecs;
434 fdata->pkt_len = pkt_len;
435 fdata->cap_len = cap_len;
437 fdata->usecs = usecs;
438 g_list_append(cf->plist, (gpointer) fdata);
439 if (!ssec && !susec) {
443 cf->esec = secs - ssec;
445 cf->eusec = usecs - susec;
447 cf->eusec = susec - usecs;