4 * $Id: file.c,v 1.16 1999/01/02 06:10:52 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 firstsec, firstusec;
69 static guint32 lastsec, lastusec;
72 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
75 static void pcap_dispatch_cb(u_char *, const struct pcap_pkthdr *,
80 open_cap_file(char *fname, capture_file *cf) {
83 char err_str[PCAP_ERRBUF_SIZE];
87 /* First, make sure the file is valid */
88 if (stat(fname, &cf_stat)) {
89 simple_dialog(ESD_TYPE_WARN, NULL, "File does not exist.");
92 if (! S_ISREG(cf_stat.st_mode) && ! S_ISFIFO(cf_stat.st_mode)) {
93 simple_dialog(ESD_TYPE_WARN, NULL, "The file you have chosen is invalid.");
97 /* Next, try to open the file */
98 cf->fh = fopen(fname, "r");
102 fseek(cf->fh, 0L, SEEK_END);
103 cf->f_len = ftell(cf->fh);
105 fseek(cf->fh, 0L, SEEK_SET);
106 fread(magic, sizeof(guint32), 2, cf->fh);
107 fseek(cf->fh, 0L, SEEK_SET);
111 /* set the file name beacuse we need it to set the follow stream filter */
112 cf->filename = g_strdup( fname );
114 /* Next, find out what type of file we're dealing with */
116 cf->cd_t = WTAP_FILE_UNKNOWN;
117 cf->lnk_t = WTAP_ENCAP_NONE;
119 cf->cd_t = CD_UNKNOWN;
120 cf->lnk_t = DLT_NULL;
128 if (cf->plist == NULL) {
129 cf->plist = g_list_alloc();
130 cf->plist->data = (frame_data *) g_malloc(sizeof(frame_data));
132 cf->plist = g_list_first(cf->plist);
134 firstsec = 0, firstusec = 0;
135 lastsec = 0, lastusec = 0;
138 if (magic[0] == PCAP_MAGIC || magic[0] == SWAP32(PCAP_MAGIC)) {
140 /* Pcap/Tcpdump file */
141 cf->pfh = pcap_open_offline(fname, err_str);
142 if (cf->pfh == NULL) {
144 cf->wth = wtap_open_offline(fname, WTAP_FILE_UNKNOWN);
145 if (cf->wth == NULL) {
148 simple_dialog(ESD_TYPE_WARN, NULL, "Could not open file.");
154 if (pcap_compile(cf->pfh, &cf->fcode, cf->dfilter, 1, 0) < 0) {
155 simple_dialog(ESD_TYPE_WARN, NULL, "Unable to parse filter string "
156 "\"%s\".", cf->dfilter);
157 } else if (pcap_setfilter(cf->pfh, &cf->fcode) < 0) {
158 simple_dialog(ESD_TYPE_WARN, NULL, "Can't install filter.");
162 cf->fh = pcap_file(cf->pfh);
163 cf->swap = pcap_is_swapped(cf->pfh);
164 if ((cf->swap && BYTE_ORDER == BIG_ENDIAN) ||
165 (!cf->swap && BYTE_ORDER == LITTLE_ENDIAN)) {
166 /* Data is big-endian */
167 cf->cd_t = CD_PCAP_BE;
169 cf->cd_t = CD_PCAP_LE;
171 cf->vers = ( ((pcap_major_version(cf->pfh) & 0x0000ffff) << 16) |
172 pcap_minor_version(cf->pfh) );
173 cf->snap = pcap_snapshot(cf->pfh);
174 cf->lnk_t = pcap_datalink(cf->pfh);
175 } else if (ntohl(magic[0]) == SNOOP_MAGIC_1 && ntohl(magic[1]) == SNOOP_MAGIC_2) {
176 simple_dialog(ESD_TYPE_WARN, NULL, "The snoop format is not yet supported.");
180 if (cf->cd_t == CD_UNKNOWN) {
181 simple_dialog(ESD_TYPE_WARN, NULL, "Can't determine file type.");
185 cf->fh = wtap_file(cf->wth);
186 cf->cd_t = wtap_file_type(cf->wth);
187 cf->snap = wtap_snapshot_length(cf->wth);
188 cf->lnk_t = wtap_encapsulation(cf->wth);
194 /* Reset everything to a pristine state */
196 close_cap_file(capture_file *cf, GtkWidget *w, guint context) {
212 gtk_text_freeze(GTK_TEXT(byte_view));
213 gtk_text_set_point(GTK_TEXT(byte_view), 0);
214 gtk_text_forward_delete(GTK_TEXT(byte_view),
215 gtk_text_get_length(GTK_TEXT(byte_view)));
216 gtk_text_thaw(GTK_TEXT(byte_view));
217 gtk_tree_clear_items(GTK_TREE(tree_view), 0,
218 g_list_length(GTK_TREE(tree_view)->children));
220 gtk_clist_freeze(GTK_CLIST(packet_list));
221 gtk_clist_clear(GTK_CLIST(packet_list));
222 gtk_clist_thaw(GTK_CLIST(packet_list));
223 gtk_statusbar_pop(GTK_STATUSBAR(w), context);
227 load_cap_file(char *fname, capture_file *cf) {
228 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
229 gchar *done_fmt = " File: %s Drops: %d";
230 gchar *err_fmt = " Error: Could not load '%s'";
235 close_cap_file(cf, info_bar, file_ctx);
237 if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
241 load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2);
242 sprintf(load_msg, load_fmt, name_ptr);
243 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
245 timeout = gtk_timeout_add(250, file_progress_cb, (gpointer) &cf);
247 err = open_cap_file(fname, cf);
249 if ((err == 0) && (cf->cd_t != WTAP_FILE_UNKNOWN)) {
251 if ((err == 0) && (cf->cd_t != CD_UNKNOWN)) {
253 gtk_clist_freeze(GTK_CLIST(packet_list));
255 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
259 pcap_loop(cf->pfh, 0, pcap_dispatch_cb, (u_char *) cf);
263 cf->plist = g_list_first(cf->plist);
264 cf->fh = fopen(fname, "r");
265 gtk_clist_thaw(GTK_CLIST(packet_list));
268 gtk_timeout_remove(timeout);
269 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
271 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
274 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
275 load_msg = g_realloc(load_msg, msg_len);
276 snprintf(load_msg, msg_len, done_fmt, name_ptr, cf->drops);
277 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
282 set_menu_sensitivity("/File/Close", TRUE);
283 set_menu_sensitivity("/File/Reload", TRUE);
285 set_menu_sensitivity("<Main>/File/Close", TRUE);
286 set_menu_sensitivity("<Main>/File/Reload", TRUE);
289 msg_len = strlen(name_ptr) + strlen(err_fmt) + 2;
290 load_msg = g_realloc(load_msg, msg_len);
291 snprintf(load_msg, msg_len, err_fmt, name_ptr);
292 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
295 set_menu_sensitivity("<Main>/File/Close", FALSE);
296 set_menu_sensitivity("<Main>/File/Reload", FALSE);
298 set_menu_sensitivity("<Main>/File/Close", FALSE);
299 set_menu_sensitivity("<Main>/File/Reload", FALSE);
308 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
310 pcap_dispatch_cb(u_char *user, const struct pcap_pkthdr *phdr,
315 capture_file *cf = (capture_file *) user;
317 while (gtk_events_pending())
318 gtk_main_iteration();
320 fdata = cf->plist->data;
324 fdata->pkt_len = phdr->len;
325 fdata->cap_len = phdr->caplen;
327 fdata->file_off = offset;
329 fdata->file_off = ftell(cf->fh) - phdr->caplen;
331 fdata->abs_secs = phdr->ts.tv_sec;
332 fdata->abs_usecs = phdr->ts.tv_usec;
333 fdata->lnk_t = phdr->pkt_encap;
335 /* If we don't have the time stamp of the first packet, it's because this
336 is the first packet. Save the time stamp of this packet as the time
337 stamp of the first packet. */
338 if (!firstsec && !firstusec) {
339 firstsec = fdata->abs_secs;
340 firstusec = fdata->abs_usecs;
343 /* Do the same for the time stamp of the previous packet. */
344 if (!lastsec && !lastusec) {
345 lastsec = fdata->abs_secs;
346 lastusec = fdata->abs_usecs;
349 /* Get the time elapsed between the first packet and this packet. */
350 cf->esec = fdata->abs_secs - firstsec;
351 if (firstusec <= fdata->abs_usecs) {
352 cf->eusec = fdata->abs_usecs - firstusec;
354 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
357 fdata->rel_secs = cf->esec;
358 fdata->rel_usecs = cf->eusec;
360 /* Do the same for the previous packet */
361 fdata->del_secs = fdata->abs_secs - lastsec;
362 if (lastusec <= fdata->abs_usecs) {
363 fdata->del_usecs = fdata->abs_usecs - lastusec;
365 fdata->del_usecs = (fdata->abs_usecs + 1000000) - lastusec;
368 lastsec = fdata->abs_secs;
369 lastusec = fdata->abs_usecs;
371 fdata->cinfo = &cf->cinfo;
372 for (i = 0; i < fdata->cinfo->num_cols; i++) {
373 fdata->cinfo->col_data[i][0] = '\0';
375 if (check_col(fdata, COL_NUMBER))
376 col_add_fstr(fdata, COL_NUMBER, "%d", cf->count);
377 dissect_packet(buf, fdata, NULL);
378 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
381 /* Make sure we always have an available list entry */
382 if (cf->plist->next == NULL) {
383 fdata = (frame_data *) g_malloc(sizeof(frame_data));
384 g_list_append(cf->plist, (gpointer) fdata);
386 cf->plist = cf->plist->next;