Ethereal-dev: Re: [ethereal-dev] Short packets / Bad data
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Gilbert Ramirez <gram@xxxxxxxxxx>
Date: Sat, 04 Dec 1999 23:17:33 -0600
On Sat, Dec 04, 1999 at 08:28:47PM -0600, Nathan Neulinger wrote: > > In a few of the dissectors I have written, I have defined a macro like: > > #define TRUNC(x) { if(!BYTES_ARE_IN_FRAME(offset,(x)) { \ > dissect_data(pd,offset,fd,tree); \ > return; } > > That could be extended a bit to put some text on the proto tree saying > it was truncated or whatever. > > I then just prefix any of my dissections with calls to TRUNC(). It's not > the most efficient method in the world, but it makes coding really easy. I was starting to experiment with a setjmp()/longjmp() system, where dissect_packet() would call setjmp(), and all data accesses into pd[] were done via macros. In fact, I'd probably move pd into the packet_info struct, and keep it out of the argument stack. If code tries to retrieve data from beyond the bounds of pd[], longjmp() is called and we return safely back to dissect_packet(). What I didn't like about my code is that if a dissector does a bunch of data retrievals at its beginning, and then later puts all this data into the proto_tree, then it may longjmp() before it puts *anything* into the proto_tree. This is not good; I was striving to put as much as possible into the proto_tree. Anyway, here's the diff of what I was playing with, and a sample very-short-packet ethernet trace made with randpkt, in case anyone is interested. --gilbert
Index: packet-eth.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-eth.c,v retrieving revision 1.25 diff -u -r1.25 packet-eth.c --- packet-eth.c 1999/11/30 23:56:35 1.25 +++ packet-eth.c 1999/12/05 04:41:05 @@ -111,25 +111,24 @@ void dissect_eth(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { - guint16 etype, length; - proto_tree *fh_tree = NULL; - proto_item *ti; - int ethhdr_type; /* the type of ethernet frame */ - - if (fd->cap_len < ETH_HEADER_SIZE) { - dissect_data(pd, offset, fd, tree); - return; - } - - SET_ADDRESS(&pi.dl_src, AT_ETHER, 6, &pd[offset+6]); - SET_ADDRESS(&pi.src, AT_ETHER, 6, &pd[offset+6]); - SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, &pd[offset+0]); - SET_ADDRESS(&pi.dst, AT_ETHER, 6, &pd[offset+0]); + guint16 etype, length, ipx_check; + proto_tree *fh_tree = NULL; + proto_item *ti; + int ethhdr_type; /* the type of ethernet frame */ + const guint8 *src_mac, *dst_mac; + + dst_mac = FRAME_DATA_PTR(offset, 6); + src_mac = FRAME_DATA_PTR(offset+6, 6); + + SET_ADDRESS(&pi.dl_src, AT_ETHER, 6, src_mac); + SET_ADDRESS(&pi.src, AT_ETHER, 6, src_mac); + SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, dst_mac); + SET_ADDRESS(&pi.dst, AT_ETHER, 6, dst_mac); if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, "Ethernet"); - etype = pntohs(&pd[offset+12]); + etype = FRAME_DATA_NTOHS(offset+12); /* either ethernet802.3 or ethernet802.2 */ if (etype <= IEEE_802_3_MAX_LEN) { @@ -141,7 +140,9 @@ (IPX/SPX is they only thing that can be contained inside a straight 802.3 packet). A non-0xffff value means that there's an 802.2 layer inside the 802.3 layer */ - if (pd[offset+14] == 0xff && pd[offset+15] == 0xff) { + + ipx_check = FRAME_DATA_NTOHS(offset+14); + if (ipx_check == 0xffff) { ethhdr_type = ETHERNET_802_3; } else { @@ -159,8 +160,8 @@ fh_tree = proto_item_add_subtree(ti, ett_ieee8023); - proto_tree_add_item(fh_tree, hf_eth_dst, offset+0, 6, &pd[offset+0]); - proto_tree_add_item(fh_tree, hf_eth_src, offset+6, 6, &pd[offset+6]); + proto_tree_add_item(fh_tree, hf_eth_dst, offset+0, 6, dst_mac); + proto_tree_add_item(fh_tree, hf_eth_src, offset+6, 6, src_mac); proto_tree_add_item(fh_tree, hf_eth_len, offset+12, 2, length); /* Convert the LLC length from the 802.3 header to a total @@ -185,8 +186,8 @@ fh_tree = proto_item_add_subtree(ti, ett_ether2); - proto_tree_add_item(fh_tree, hf_eth_dst, offset+0, 6, &pd[offset+0]); - proto_tree_add_item(fh_tree, hf_eth_src, offset+6, 6, &pd[offset+6]); + proto_tree_add_item(fh_tree, hf_eth_dst, offset+0, 6, dst_mac); + proto_tree_add_item(fh_tree, hf_eth_src, offset+6, 6, src_mac); } } offset += ETH_HEADER_SIZE; Index: packet.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet.c,v retrieving revision 1.58 diff -u -r1.58 packet.c --- packet.c 1999/12/02 01:33:55 1.58 +++ packet.c 1999/12/05 04:41:08 @@ -763,13 +763,21 @@ g_slist_foreach(init_routines, &call_init_routine, NULL); } + +int +longjmp_retval(jmp_buf env, int retval) +{ + longjmp(env, retval); + return 1; +} + /* this routine checks the frame type from the cf structure */ void dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree) { - proto_tree *fh_tree; - proto_item *ti; - struct timeval tv; + proto_tree *fh_tree; + proto_item *ti; + struct timeval tv; /* Put in frame header information. */ if (tree) { @@ -810,43 +818,51 @@ pi.len = fd->pkt_len; pi.captured_len = fd->cap_len; - switch (fd->lnk_t) { - case WTAP_ENCAP_ETHERNET : - dissect_eth(pd, 0, fd, tree); - break; - case WTAP_ENCAP_FDDI : - dissect_fddi(pd, fd, tree, FALSE); - break; - case WTAP_ENCAP_FDDI_BITSWAPPED : - dissect_fddi(pd, fd, tree, TRUE); - break; - case WTAP_ENCAP_TR : - dissect_tr(pd, 0, fd, tree); - break; - case WTAP_ENCAP_NULL : - dissect_null(pd, fd, tree); - break; - case WTAP_ENCAP_PPP : - dissect_ppp(pd, fd, tree); - break; - case WTAP_ENCAP_LAPB : - dissect_lapb(pd, fd, tree); - break; - case WTAP_ENCAP_RAW_IP : - dissect_raw(pd, fd, tree); - break; - case WTAP_ENCAP_LINUX_ATM_CLIP : - dissect_clip(pd, fd, tree); - break; - case WTAP_ENCAP_ATM_SNIFFER : - dissect_atm(pd, fd, tree); - break; - case WTAP_ENCAP_ASCEND : - dissect_ascend(pd, fd, tree); - break; - case WTAP_ENCAP_LAPD : - dissect_lapd(pd, fd, tree); - break; + if (setjmp(pi.jmp_env) == 0) { + switch (fd->lnk_t) { + case WTAP_ENCAP_ETHERNET : + dissect_eth(pd, 0, fd, tree); + break; + case WTAP_ENCAP_FDDI : + dissect_fddi(pd, fd, tree, FALSE); + break; + case WTAP_ENCAP_FDDI_BITSWAPPED : + dissect_fddi(pd, fd, tree, TRUE); + break; + case WTAP_ENCAP_TR : + dissect_tr(pd, 0, fd, tree); + break; + case WTAP_ENCAP_NULL : + dissect_null(pd, fd, tree); + break; + case WTAP_ENCAP_PPP : + dissect_ppp(pd, fd, tree); + break; + case WTAP_ENCAP_LAPB : + dissect_lapb(pd, fd, tree); + break; + case WTAP_ENCAP_RAW_IP : + dissect_raw(pd, fd, tree); + break; + case WTAP_ENCAP_LINUX_ATM_CLIP : + dissect_clip(pd, fd, tree); + break; + case WTAP_ENCAP_ATM_SNIFFER : + dissect_atm(pd, fd, tree); + break; + case WTAP_ENCAP_ASCEND : + dissect_ascend(pd, fd, tree); + break; + case WTAP_ENCAP_LAPD : + dissect_lapd(pd, fd, tree); + break; + } + } + else { + /* we returned from a longjmp */ +/* if (tree) { + proto_tree_add_text(fh_tree, 0, 0, "[Unexpected end of frame]"); + }*/ } } Index: packet.h =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet.h,v retrieving revision 1.155 diff -u -r1.155 packet.h --- packet.h 1999/12/03 21:50:31 1.155 +++ packet.h 1999/12/05 04:41:11 @@ -27,6 +27,8 @@ #ifndef __PACKET_H__ #define __PACKET_H__ +#include <setjmp.h> + #ifndef __WTAP_H__ #include "wiretap/wtap.h" #endif @@ -79,10 +81,27 @@ /* Check whether there's any data at all starting at "offset". */ #define IS_DATA_IN_FRAME(offset) ((offset) < pi.captured_len) - + +/* Return pointer to frame data, checking frame length */ +#define FRAME_DATA_PTR(offset, len) \ + ((offset) + (len) <= pi.captured_len) ? \ + &pd[(offset)] : \ + (guint8*)longjmp_retval(pi.jmp_env, 1) + +/* Return host short converted from network short, checking frame length */ +#define FRAME_DATA_NTOHS(offset) \ + ((offset) + 2 <= pi.captured_len) ? \ + pntohs(&pd[(offset)]) : \ + longjmp_retval(pi.jmp_env, 1) + +/* Calls longjmp() and pretends to return a value, to placate + * the compiler when I use longjmp() as part of a "?:" expression. */ +int longjmp_retval(jmp_buf, int); + /* To pass one of two strings, singular or plural */ #define plurality(d,s,p) ((d) == 1 ? (s) : (p)) + typedef struct _column_info { gint num_cols; /* Number of columns */ gint *col_fmt; /* Format of column */ @@ -187,6 +206,7 @@ guint32 match_port; int iplen; int iphdrlen; + jmp_buf jmp_env; } packet_info; extern packet_info pi;
Attachment:
short-eth.cap
Description: Binary data
- References:
- [ethereal-dev] Short packets / Bad data
- From: Gilbert Ramirez
- Re: [ethereal-dev] Short packets / Bad data
- From: Nathan Neulinger
- [ethereal-dev] Short packets / Bad data
- Prev by Date: Re: [ethereal-dev] Checked in code to write "snoop" and NetMon capture files
- Next by Date: [ethereal-dev] misc. suggestions for go to frame
- Previous by thread: Re: [ethereal-dev] Short packets / Bad data
- Next by thread: [ethereal-dev] Checked in code to write "snoop" and NetMon capture files
- Index(es):