diff --git a/Makefile.am b/Makefile.am index 81ec1ba069..f37065f8d7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.231 2000/09/28 03:52:03 gram Exp $ +# $Id: Makefile.am,v 1.232 2000/10/06 10:10:44 gram Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs @@ -58,6 +58,7 @@ DISSECTOR_SOURCES = \ packet-eth.c \ packet-ethertype.c \ packet-fddi.c \ + packet-frame.c \ packet-ftp.c \ packet-giop.c \ packet-gre.c \ @@ -188,6 +189,7 @@ noinst_HEADERS = \ packet-esis.h \ packet-eth.h \ packet-fddi.h \ + packet-frame.h \ packet-http.h \ packet-ip.h \ packet-ipp.h \ @@ -413,8 +415,7 @@ editcap_LDADD = wiretap/libwiretap.a @GLIB_LIBS@ # start in column zero, or must be preceded only by "void " starting in # column zero, and must not be inside #if. # -# We assume that all dissector routines are in "packet-XXX.c" files, -# or in "packet.c". +# We assume that all dissector routines are in "packet-XXX.c" files. # # For some unknown reason, having a big "for" loop in the Makefile # to scan all the "packet-XXX.c" files doesn't work with some "make"s; @@ -426,9 +427,9 @@ editcap_LDADD = wiretap/libwiretap.a @GLIB_LIBS@ # The first argument is the directory in which the source files live. # All subsequent arguments are the files to scan. # -register.c: $(srcdir)/epan/packet.c $(DISSECTOR_SOURCES) $(srcdir)/make-reg-dotc +register.c: $(DISSECTOR_SOURCES) $(srcdir)/make-reg-dotc @echo Making register.c - @$(srcdir)/make-reg-dotc $(srcdir) $(srcdir)/epan/packet.c $(DISSECTOR_SOURCES) + @$(srcdir)/make-reg-dotc $(srcdir) $(DISSECTOR_SOURCES) ps.c: print.ps rdps ./rdps $(srcdir)/print.ps ps.c diff --git a/epan/epan.c b/epan/epan.c index a3734c7cbb..2dd19ac811 100644 --- a/epan/epan.c +++ b/epan/epan.c @@ -10,6 +10,7 @@ #include "conversation.h" #include "dfilter.h" #include "except.h" +#include "packet.h" #include "proto.h" #include "tvbuff.h" @@ -18,6 +19,7 @@ epan_init(void) { except_init(); tvbuff_init(); + packet_init(); proto_init(); dfilter_init(); #ifdef HAVE_PLUGINS @@ -30,6 +32,7 @@ epan_cleanup(void) { dfilter_cleanup(); proto_cleanup(); + packet_cleanup(); tvbuff_cleanup(); except_deinit(); } @@ -40,3 +43,35 @@ epan_conversation_init(void) { conversation_init(); } + + +struct epan_dissect { + + tvbuff_t *tvb; + proto_tree *tree; +}; + +epan_dissect_t* +epan_dissect_new(void* pseudo_header, const guint8* data, frame_data *fd, proto_tree *tree) +{ + epan_dissect_t *edt; + + edt = g_new(epan_dissect_t, 1); + + /* XXX - init tree */ + dissect_packet(&edt->tvb, pseudo_header, data, fd, tree); + + return edt; +} + + +void +epan_dissect_free(epan_dissect_t* edt) +{ + /* Free all tvb's created from this tvb, unless dissector + * wanted to store the pointer (in which case, the dissector + * would have incremented the usage count on that tvbuff_t*) */ + tvb_free_chain(edt->tvb); + + g_free(edt); +} diff --git a/epan/epan.h b/epan/epan.h index 649627c44e..f38067d284 100644 --- a/epan/epan.h +++ b/epan/epan.h @@ -5,13 +5,19 @@ */ #ifndef EPAN_H +#define EPAN_H #include - + +/* XXX - for now */ +#include "packet.h" + void epan_init(void); void epan_cleanup(void); void epan_conversation_init(void); + + /* A client will create one epan_t for an entire dissection session. * A single epan_t will be used to analyze the entire sequence of packets, * sequentially, in a single session. A session corresponds to a single @@ -21,7 +27,6 @@ void epan_conversation_init(void); */ typedef struct epan_session epan_t; - epan_t* epan_new(void); @@ -39,17 +44,21 @@ epan_free(epan_t*); */ typedef struct epan_dissect epan_dissect_t; - epan_dissect_t* -epan_dissect_new(epan_t*, guint8* data, guint len, guint32 wtap_encap, - void* pseudo_header); +epan_dissect_new(void* pseudo_header, const guint8* data, frame_data *fd, proto_tree *tree); void -epan_dissect_free(epan_t*, epan_dissect_t*); +epan_dissect_free(epan_dissect_t* edt); + + + + /* Should this be ".libepan"? For backwards-compatibility, I'll keep * it ".ethereal" for now. */ #define PF_DIR ".ethereal" + + #endif /* EPAN_H */ diff --git a/epan/packet.c b/epan/packet.c index 676e0970cf..c68de7ce61 100644 --- a/epan/packet.c +++ b/epan/packet.c @@ -1,7 +1,7 @@ /* packet.c * Routines for packet disassembly * - * $Id: packet.c,v 1.1 2000/09/27 05:18:05 gram Exp $ + * $Id: packet.c,v 1.2 2000/10/06 10:11:15 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -73,22 +73,10 @@ #include "timestamp.h" #include "file.h" -#include "packet-ascend.h" #include "packet-atalk.h" -#include "packet-atm.h" -#include "packet-clip.h" -#include "packet-eth.h" -#include "packet-fddi.h" +#include "packet-frame.h" #include "packet-ipv6.h" -#include "packet-lapb.h" -#include "packet-lapd.h" -#include "packet-llc.h" -#include "packet-null.h" -#include "packet-ppp.h" -#include "packet-raw.h" #include "packet-sna.h" -#include "packet-tr.h" -#include "packet-v120.h" #include "packet-vines.h" #include "resolv.h" @@ -97,29 +85,15 @@ extern capture_file cfile; -static int proto_frame = -1; -static int hf_frame_arrival_time = -1; -static int hf_frame_time_delta = -1; -static int hf_frame_number = -1; -static int hf_frame_packet_len = -1; -static int hf_frame_capture_len = -1; -static int hf_frame_p2p_dir = -1; -static int proto_short = -1; -static int proto_malformed = -1; -static gint ett_frame = -1; +extern int proto_malformed; + static void display_signed_time(gchar *, int, gint32, gint32); -static const value_string p2p_dirs[] = { - { P2P_DIR_SENT, "Sent" }, - { P2P_DIR_RECV, "Received" }, - { 0, NULL } -}; - -/* Protocol-specific data attched to a frame_data structure - protocol +/* Protocol-specific data attached to a frame_data structure - protocol index and opaque pointer. */ typedef struct _frame_proto_data { int proto; @@ -128,6 +102,7 @@ typedef struct _frame_proto_data { GMemChunk *frame_proto_data_area = NULL; + /* * Free up any space allocated for frame proto data areas and then * allocate a new area. @@ -149,6 +124,19 @@ packet_init_protocol(void) } + +void +packet_init(void) +{ + register_init_routine(&packet_init_protocol); +} + +void +packet_cleanup(void) +{ + /* nothing */ +} + /* Wrapper for the most common case of asking * for a string using a colon as the hex-digit separator. */ @@ -980,63 +968,13 @@ init_all_protocols(void) g_slist_foreach(init_routines, &call_init_routine, NULL); } -/* this routine checks the frame type from the cf structure */ +/* Creates the top-most tvbuff and calls dissect_frame() */ void -dissect_packet(union wtap_pseudo_header *pseudo_header, const u_char *pd, - frame_data *fd, proto_tree *tree) +dissect_packet(tvbuff_t **p_tvb, union wtap_pseudo_header *pseudo_header, + const u_char *pd, frame_data *fd, proto_tree *tree) { - proto_tree *fh_tree; - proto_item *ti; - struct timeval tv; - static tvbuff_t *tvb; - blank_packetinfo(); - if (fd->lnk_t == WTAP_ENCAP_LAPD || - fd->lnk_t == WTAP_ENCAP_PPP_WITH_PHDR) { - - pi.p2p_dir = pseudo_header->p2p.sent ? P2P_DIR_SENT : P2P_DIR_RECV; - } - - /* Put in frame header information. */ - if (tree) { - ti = proto_tree_add_protocol_format(tree, proto_frame, NullTVB, 0, fd->cap_len, - "Frame %u (%u on wire, %u captured)", fd->num, - fd->pkt_len, fd->cap_len); - - fh_tree = proto_item_add_subtree(ti, ett_frame); - - tv.tv_sec = fd->abs_secs; - tv.tv_usec = fd->abs_usecs; - - proto_tree_add_time(fh_tree, hf_frame_arrival_time, NullTVB, - 0, 0, &tv); - - tv.tv_sec = fd->del_secs; - tv.tv_usec = fd->del_usecs; - - proto_tree_add_time(fh_tree, hf_frame_time_delta, NullTVB, - 0, 0, &tv); - - proto_tree_add_uint(fh_tree, hf_frame_number, NullTVB, - 0, 0, fd->num); - - proto_tree_add_uint_format(fh_tree, hf_frame_packet_len, NullTVB, - 0, 0, fd->pkt_len, "Packet Length: %d byte%s", fd->pkt_len, - plurality(fd->pkt_len, "", "s")); - - proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, NullTVB, - 0, 0, fd->cap_len, "Capture Length: %d byte%s", fd->cap_len, - plurality(fd->cap_len, "", "s")); - - /* Check for existences of P2P pseudo header */ - if (fd->lnk_t == WTAP_ENCAP_LAPD || fd->lnk_t == WTAP_ENCAP_PPP_WITH_PHDR) { - proto_tree_add_uint(fh_tree, hf_frame_p2p_dir, NullTVB, - 0, 0, pi.p2p_dir); - } - } - - /* Set the initial payload to the packet length, and the initial captured payload to the capture length (other protocols may reduce them if their headers say they're less). */ @@ -1045,81 +983,29 @@ dissect_packet(union wtap_pseudo_header *pseudo_header, const u_char *pd, pi.fd = fd; pi.pseudo_header = pseudo_header; - pi.current_proto = "Frame"; col_set_writable(fd, TRUE); TRY { - tvb = tvb_new_real_data(pd, fd->cap_len, fd->pkt_len); - pi.compat_top_tvb = tvb; - - switch (fd->lnk_t) { - case WTAP_ENCAP_ETHERNET : - dissect_eth(tvb, &pi, tree); - break; - case WTAP_ENCAP_FDDI : - dissect_fddi(tvb, &pi, tree, FALSE); - break; - case WTAP_ENCAP_FDDI_BITSWAPPED : - dissect_fddi(tvb, &pi, tree, TRUE); - break; - case WTAP_ENCAP_TOKEN_RING : - dissect_tr(tvb, &pi, tree); - break; - case WTAP_ENCAP_NULL : - dissect_null(tvb, &pi, tree); - break; - case WTAP_ENCAP_PPP : - case WTAP_ENCAP_PPP_WITH_PHDR : - dissect_ppp(tvb, &pi, tree); - break; - case WTAP_ENCAP_LAPB : - dissect_lapb(tvb, &pi, tree); - break; - case WTAP_ENCAP_RAW_IP : - dissect_raw(tvb, &pi, tree); - break; - case WTAP_ENCAP_LINUX_ATM_CLIP : - dissect_clip(tvb, &pi, tree); - break; - case WTAP_ENCAP_ATM_SNIFFER : - dissect_atm(tvb, &pi, tree); - break; - case WTAP_ENCAP_ASCEND : - dissect_ascend(tvb, &pi, tree); - break; - case WTAP_ENCAP_LAPD : - dissect_lapd(tvb, &pi, tree); - break; - case WTAP_ENCAP_V120 : - dissect_v120(tvb, &pi, tree); - break; - case WTAP_ENCAP_ATM_RFC1483: - dissect_llc(tvb, &pi, tree); - break; - default: - g_assert_not_reached(); - break; - } + *p_tvb = tvb_new_real_data(pd, fd->cap_len, fd->pkt_len); + pi.compat_top_tvb = *p_tvb; } CATCH(BoundsError) { - proto_tree_add_protocol_format(tree, proto_short, NullTVB, 0, 0, - "[Short Frame: %s]", pi.current_proto ); + g_assert_not_reached(); } CATCH(ReportedBoundsError) { - proto_tree_add_protocol_format(tree, proto_malformed, NullTVB, 0, 0, - "[Malformed Frame: %s]", pi.current_proto ); + proto_tree_add_protocol_format(tree, proto_malformed, *p_tvb, 0, 0, + "[Malformed Frame: Packet Length]" ); } ENDTRY; - /* Free all tvb's created from this tvb, unless dissector - * wanted to store the pointer (in which case, the dissector - * would have incremented the usage count on that tvbuff_t*) */ - tvb_free_chain(tvb); + dissect_frame(*p_tvb, &pi, tree); fd->flags.visited = 1; } + + gint p_compare(gconstpointer a, gconstpointer b) { @@ -1189,48 +1075,6 @@ p_rem_proto_data(frame_data *fd, int proto) } -void -proto_register_frame(void) -{ - static hf_register_info hf[] = { - { &hf_frame_arrival_time, - { "Arrival Time", "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, - ""}}, - - { &hf_frame_time_delta, - { "Time delta from previous packet", "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, - 0x0, - "" }}, - - { &hf_frame_number, - { "Frame Number", "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_frame_packet_len, - { "Total Frame Length", "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_frame_capture_len, - { "Capture Frame Length", "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_frame_p2p_dir, - { "Point-to-Point Direction", "frame.p2p_dir", FT_UINT8, BASE_DEC, VALS(p2p_dirs), 0x0, - "" }}, - }; - static gint *ett[] = { - &ett_frame, - }; - - proto_frame = proto_register_protocol("Frame", "frame"); - proto_register_field_array(proto_frame, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); - - proto_short = proto_register_protocol("Short Frame", "short"); - proto_malformed = proto_register_protocol("Malformed Frame", "malformed"); - register_init_routine(&packet_init_protocol); - -} /*********************** code added for sub-dissector lookup *********************/ diff --git a/epan/packet.h b/epan/packet.h index 19623772dc..b7df0f0d1b 100644 --- a/epan/packet.h +++ b/epan/packet.h @@ -1,7 +1,7 @@ /* packet.h * Definitions for packet disassembly structures and routines * - * $Id: packet.h,v 1.1 2000/09/27 05:18:06 gram Exp $ + * $Id: packet.h,v 1.2 2000/10/06 10:11:17 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -190,6 +190,9 @@ typedef struct true_false_string { char *false_string; } true_false_string; +void packet_init(void); +void packet_cleanup(void); + /* Hash table for matching port numbers and dissectors */ typedef GHashTable* dissector_table_t; @@ -305,12 +308,10 @@ void init_all_protocols(void); void init_dissect_rpc(void); /* - * Routines should take four args: packet data *, offset, frame_data *, - * tree * - * They should never modify the packet data. + * Dissectors should never modify the packet data. */ -void dissect_packet(union wtap_pseudo_header *, const u_char *, frame_data *, - proto_tree *); +void dissect_packet(tvbuff_t **p_tvb, union wtap_pseudo_header *pseudo_header, + const u_char *pd, frame_data *fd, proto_tree *tree); void old_dissect_data(const u_char *, int, frame_data *, proto_tree *); void dissect_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); diff --git a/file.c b/file.c index 2e719265fe..b73db738eb 100644 --- a/file.c +++ b/file.c @@ -1,7 +1,7 @@ /* file.c * File I/O routines * - * $Id: file.c,v 1.223 2000/09/27 04:54:28 gram Exp $ + * $Id: file.c,v 1.224 2000/10/06 10:10:46 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -604,6 +604,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, apply_color_filter_args args; gint i, row; proto_tree *protocol_tree = NULL; + epan_dissect_t *edt; /* We don't yet have a color filter to apply. */ args.colorf = NULL; @@ -640,7 +641,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, protocol_tree = proto_tree_create_root(); /* Dissect the frame. */ - dissect_packet(pseudo_header, buf, fdata, protocol_tree); + edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree); /* If we have a display filter, apply it if we're refiltering, otherwise leave the "passed_dfilter" flag alone. @@ -672,6 +673,8 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, if (protocol_tree != NULL) proto_tree_free(protocol_tree); + epan_dissect_free(edt); + if (fdata->flags.passed_dfilter) { /* This frame passed the display filter, so add it to the clist. */ @@ -759,6 +762,7 @@ read_packet(capture_file *cf, int offset) int passed; proto_tree *protocol_tree; frame_data *plist_end; + epan_dissect_t *edt; /* Allocate the next list entry, and add it to the list. */ fdata = g_mem_chunk_alloc(cf->plist_chunk); @@ -780,9 +784,10 @@ read_packet(capture_file *cf, int offset) passed = TRUE; if (cf->rfcode) { protocol_tree = proto_tree_create_root(); - dissect_packet(pseudo_header, buf, fdata, protocol_tree); + edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree); passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata->cap_len); proto_tree_free(protocol_tree); + epan_dissect_free(edt); } if (passed) { plist_end = cf->plist_end; @@ -1052,6 +1057,7 @@ print_packets(capture_file *cf, print_args_t *print_args) char *cp; int column_len; int line_len; + epan_dissect_t *edt = NULL; cf->print_fh = open_print_dest(print_args->to_file, print_args->dest); if (cf->print_fh == NULL) @@ -1167,7 +1173,7 @@ print_packets(capture_file *cf, print_args_t *print_args) for (i = 0; i < fdata->cinfo->num_cols; i++) { fdata->cinfo->col_data[i][0] = '\0'; } - dissect_packet(&cf->pseudo_header, cf->pd, fdata, NULL); + edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, NULL); fill_in_columns(fdata); cp = &line_buf[0]; line_len = 0; @@ -1204,7 +1210,7 @@ print_packets(capture_file *cf, print_args_t *print_args) /* Create the logical protocol tree. */ protocol_tree = proto_tree_create_root(); - dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree); + edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree); /* Print the information in that tree. */ proto_tree_print(FALSE, print_args, (GNode *)protocol_tree, @@ -1221,6 +1227,7 @@ print_packets(capture_file *cf, print_args_t *print_args) /* Print a blank line if we print anything after this. */ print_separator = TRUE; } + epan_dissect_free(edt); } } @@ -1380,6 +1387,7 @@ find_packet(capture_file *cf, dfilter *sfcode) proto_tree *protocol_tree; gboolean frame_matched; int row; + epan_dissect_t *edt; start_fd = cf->current_frame; if (start_fd != NULL) { @@ -1444,9 +1452,10 @@ find_packet(capture_file *cf, dfilter *sfcode) protocol_tree = proto_tree_create_root(); wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header, cf->pd, fdata->cap_len); - dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree); + edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree); frame_matched = dfilter_apply(sfcode, protocol_tree, cf->pd, fdata->cap_len); proto_tree_free(protocol_tree); + epan_dissect_free(edt); if (frame_matched) { new_fd = fdata; break; /* found it! */ @@ -1552,7 +1561,7 @@ select_packet(capture_file *cf, int row) proto_tree_free(cf->protocol_tree); cf->protocol_tree = proto_tree_create_root(); proto_tree_is_visible = TRUE; - dissect_packet(&cf->pseudo_header, cf->pd, cf->current_frame, + cf->edt = epan_dissect_new(&cf->pseudo_header, cf->pd, cf->current_frame, cf->protocol_tree); proto_tree_is_visible = FALSE; @@ -1573,6 +1582,7 @@ unselect_packet(capture_file *cf) if (cf->protocol_tree != NULL) { proto_tree_free(cf->protocol_tree); cf->protocol_tree = NULL; + epan_dissect_free(cf->edt); } finfo_selected = NULL; diff --git a/file.h b/file.h index 070f3c1cc6..0aa56c2387 100644 --- a/file.h +++ b/file.h @@ -1,7 +1,7 @@ /* file.h * Definitions for file structures and routines * - * $Id: file.h,v 1.76 2000/08/21 15:45:21 deniel Exp $ + * $Id: file.h,v 1.77 2000/10/06 10:10:48 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -42,6 +42,8 @@ #include +#include + #ifdef HAVE_LIBZ #include "zlib.h" #define FILE_T gzFile @@ -106,6 +108,7 @@ typedef struct _capture_file { column_info cinfo; /* Column formatting information */ frame_data *current_frame; /* Frame data for current frame */ proto_tree *protocol_tree; /* Protocol tree for currently selected packet */ + epan_dissect_t *edt; /* Protocol dissection fo rcurrently selected packet */ FILE *print_fh; /* File we're printing to */ } capture_file; diff --git a/gtk/packet_win.c b/gtk/packet_win.c index a5688dfa25..abf4e8a917 100644 --- a/gtk/packet_win.c +++ b/gtk/packet_win.c @@ -3,7 +3,7 @@ * * Copyright 2000, Jeffrey C. Foster * - * $Id: packet_win.c,v 1.15 2000/09/09 10:26:56 guy Exp $ + * $Id: packet_win.c,v 1.16 2000/10/06 10:11:40 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -46,6 +46,7 @@ #include #endif +#include #include "main.h" #include "timestamp.h" #include "packet.h" @@ -80,6 +81,7 @@ struct PacketWinData { GtkWidget *bv_scrollw; GtkWidget *byte_view; field_info *finfo_selected; + epan_dissect_t *edt; }; /* List of all the packet-detail windows popped up. */ @@ -171,7 +173,7 @@ create_new_window ( char *Title, gint tv_size, gint bv_size){ memcpy(DataPtr->pd, cfile.pd, DataPtr->frame->cap_len); DataPtr->protocol_tree = proto_tree_create_root(); proto_tree_is_visible = TRUE; - dissect_packet(&DataPtr->pseudo_header, DataPtr->pd, DataPtr->frame, + DataPtr->edt = epan_dissect_new(&DataPtr->pseudo_header, DataPtr->pd, DataPtr->frame, DataPtr->protocol_tree); proto_tree_is_visible = FALSE; DataPtr->main = main_w; @@ -206,6 +208,7 @@ destroy_new_window(GtkObject *object, gpointer user_data) detail_windows = g_list_remove(detail_windows, DataPtr); proto_tree_free(DataPtr->protocol_tree); + epan_dissect_free(DataPtr->edt); g_free(DataPtr->pd); g_free(DataPtr); } diff --git a/packet-frame.c b/packet-frame.c new file mode 100644 index 0000000000..01456f429c --- /dev/null +++ b/packet-frame.c @@ -0,0 +1,233 @@ +/* packet-frame.c + * + * Top-most dissector. Decides dissector based on Wiretap Encapsulation Type. + * + * $Id: packet-frame.c,v 1.1 2000/10/06 10:10:49 gram Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 2000 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "packet.h" +#include "timestamp.h" +#include "tvbuff.h" +#include "packet-frame.h" + +#include "packet-ascend.h" +#include "packet-atalk.h" +#include "packet-atm.h" +#include "packet-clip.h" +#include "packet-eth.h" +#include "packet-fddi.h" +#include "packet-ipv6.h" +#include "packet-lapb.h" +#include "packet-lapd.h" +#include "packet-llc.h" +#include "packet-null.h" +#include "packet-ppp.h" +#include "packet-raw.h" +#include "packet-sna.h" +#include "packet-tr.h" +#include "packet-v120.h" +#include "packet-vines.h" + + +static int proto_frame = -1; +static int hf_frame_arrival_time = -1; +static int hf_frame_time_delta = -1; +static int hf_frame_number = -1; +static int hf_frame_packet_len = -1; +static int hf_frame_capture_len = -1; +static int hf_frame_p2p_dir = -1; +static int proto_short = -1; +int proto_malformed = -1; + +static gint ett_frame = -1; + +static const value_string p2p_dirs[] = { + { P2P_DIR_SENT, "Sent" }, + { P2P_DIR_RECV, "Received" }, + { 0, NULL } +}; + +void +dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *fh_tree; + proto_item *ti; + struct timeval tv; + int cap_len, pkt_len; + + pinfo->current_proto = "Frame"; + + if (pinfo->fd->lnk_t == WTAP_ENCAP_LAPD || + pinfo->fd->lnk_t == WTAP_ENCAP_PPP_WITH_PHDR) { + + pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ? P2P_DIR_SENT : P2P_DIR_RECV; + } + + /* Put in frame header information. */ + if (tree) { + + cap_len = tvb_length(tvb); + pkt_len = tvb_reported_length(tvb); + + ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_length(tvb), + "Frame %u (%u on wire, %u captured)", pinfo->fd->num, pkt_len, cap_len); + + fh_tree = proto_item_add_subtree(ti, ett_frame); + + tv.tv_sec = pinfo->fd->abs_secs; + tv.tv_usec = pinfo->fd->abs_usecs; + + proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb, + 0, 0, &tv); + + tv.tv_sec = pinfo->fd->del_secs; + tv.tv_usec = pinfo->fd->del_usecs; + + proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb, + 0, 0, &tv); + + proto_tree_add_uint(fh_tree, hf_frame_number, tvb, + 0, 0, pinfo->fd->num); + + proto_tree_add_uint_format(fh_tree, hf_frame_packet_len, tvb, + 0, 0, pkt_len, "Packet Length: %d byte%s", pkt_len, + plurality(pkt_len, "", "s")); + + proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb, + 0, 0, cap_len, "Capture Length: %d byte%s", cap_len, + plurality(cap_len, "", "s")); + + /* Check for existences of P2P pseudo header */ + if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) { + proto_tree_add_uint(fh_tree, hf_frame_p2p_dir, tvb, + 0, 0, pinfo->p2p_dir); + } + } + + + TRY { + switch (pinfo->fd->lnk_t) { + case WTAP_ENCAP_ETHERNET : + dissect_eth(tvb, pinfo, tree); + break; + case WTAP_ENCAP_FDDI : + dissect_fddi(tvb, pinfo, tree, FALSE); + break; + case WTAP_ENCAP_FDDI_BITSWAPPED : + dissect_fddi(tvb, pinfo, tree, TRUE); + break; + case WTAP_ENCAP_TOKEN_RING : + dissect_tr(tvb, pinfo, tree); + break; + case WTAP_ENCAP_NULL : + dissect_null(tvb, pinfo, tree); + break; + case WTAP_ENCAP_PPP : + case WTAP_ENCAP_PPP_WITH_PHDR : + dissect_ppp(tvb, pinfo, tree); + break; + case WTAP_ENCAP_LAPB : + dissect_lapb(tvb, pinfo, tree); + break; + case WTAP_ENCAP_RAW_IP : + dissect_raw(tvb, pinfo, tree); + break; + case WTAP_ENCAP_LINUX_ATM_CLIP : + dissect_clip(tvb, pinfo, tree); + break; + case WTAP_ENCAP_ATM_SNIFFER : + dissect_atm(tvb, pinfo, tree); + break; + case WTAP_ENCAP_ASCEND : + dissect_ascend(tvb, pinfo, tree); + break; + case WTAP_ENCAP_LAPD : + dissect_lapd(tvb, pinfo, tree); + break; + case WTAP_ENCAP_V120 : + dissect_v120(tvb, pinfo, tree); + break; + case WTAP_ENCAP_ATM_RFC1483: + dissect_llc(tvb, pinfo, tree); + break; + default: + g_assert_not_reached(); + break; + } + } + CATCH(BoundsError) { + proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0, + "[Short Frame: %s]", pinfo->current_proto ); + } + CATCH(ReportedBoundsError) { + proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0, + "[Malformed Frame: %s]", pinfo->current_proto ); + } + ENDTRY; +} + +void +proto_register_frame(void) +{ + static hf_register_info hf[] = { + { &hf_frame_arrival_time, + { "Arrival Time", "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, + ""}}, + + { &hf_frame_time_delta, + { "Time delta from previous packet", "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, + 0x0, + "" }}, + + { &hf_frame_number, + { "Frame Number", "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0, + "" }}, + + { &hf_frame_packet_len, + { "Total Frame Length", "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0, + "" }}, + + { &hf_frame_capture_len, + { "Capture Frame Length", "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0, + "" }}, + + { &hf_frame_p2p_dir, + { "Point-to-Point Direction", "frame.p2p_dir", FT_UINT8, BASE_DEC, VALS(p2p_dirs), 0x0, + "" }}, + }; + static gint *ett[] = { + &ett_frame, + }; + + proto_frame = proto_register_protocol("Frame", "frame"); + proto_register_field_array(proto_frame, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + proto_short = proto_register_protocol("Short Frame", "short"); + proto_malformed = proto_register_protocol("Malformed Frame", "malformed"); + +} diff --git a/packet-frame.h b/packet-frame.h new file mode 100644 index 0000000000..62ed6584a9 --- /dev/null +++ b/packet-frame.h @@ -0,0 +1,28 @@ +/* packet-frame.h + * + * Top-most dissector. Decides dissector based on Wiretap Encapsulation Type. + * + * $Id: packet-frame.h,v 1.1 2000/10/06 10:10:49 gram Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 2000 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +void +dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); diff --git a/tethereal.c b/tethereal.c index bbcb539532..3190fcd340 100644 --- a/tethereal.c +++ b/tethereal.c @@ -1,6 +1,6 @@ /* tethereal.c * - * $Id: tethereal.c,v 1.48 2000/09/27 04:54:33 gram Exp $ + * $Id: tethereal.c,v 1.49 2000/10/06 10:10:50 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -883,16 +883,18 @@ wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset, proto_tree *protocol_tree; int err; gboolean passed; + epan_dissect_t *edt; cf->count++; if (cf->rfcode) { fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset); protocol_tree = proto_tree_create_root(); - dissect_packet(pseudo_header, buf, &fdata, protocol_tree); + edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree); passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata.cap_len); } else { protocol_tree = NULL; passed = TRUE; + edt = NULL; } if (passed) { /* XXX - do something if this fails */ @@ -900,6 +902,8 @@ wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset, } if (protocol_tree != NULL) proto_tree_free(protocol_tree); + if (edt != NULL) + epan_dissect_free(edt); } static void @@ -912,6 +916,7 @@ wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset, proto_tree *protocol_tree; gboolean passed; print_args_t print_args; + epan_dissect_t *edt; cf->count++; @@ -926,7 +931,7 @@ wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset, protocol_tree = proto_tree_create_root(); else protocol_tree = NULL; - dissect_packet(pseudo_header, buf, &fdata, protocol_tree); + edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree); if (cf->rfcode) passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata.cap_len); if (passed) { @@ -975,6 +980,8 @@ wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset, if (protocol_tree != NULL) proto_tree_free(protocol_tree); + epan_dissect_free(edt); + proto_tree_is_visible = FALSE; }