2 * Routines for packet disassembly
4 * $Id: packet.c,v 1.91 2000/05/25 14:55:22 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.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/socket.h>
51 #ifdef NEED_SNPRINTF_H
52 # include "snprintf.h"
55 #ifdef HAVE_NETINET_IN_H
56 # include <netinet/in.h>
59 #ifdef HAVE_ARPA_INET_H
60 #include <arpa/inet.h>
63 #ifdef NEED_INET_V6DEFS_H
64 # include "inet_v6defs.h"
69 #include "timestamp.h"
72 #include "packet-ascend.h"
73 #include "packet-atalk.h"
74 #include "packet-atm.h"
75 #include "packet-clip.h"
76 #include "packet-eth.h"
77 #include "packet-fddi.h"
78 #include "packet-ipv6.h"
79 #include "packet-lapb.h"
80 #include "packet-lapd.h"
81 #include "packet-null.h"
82 #include "packet-ppp.h"
83 #include "packet-raw.h"
84 #include "packet-sna.h"
85 #include "packet-tr.h"
86 #include "packet-v120.h"
87 #include "packet-vines.h"
99 extern capture_file cf;
101 static int proto_frame = -1;
102 static int hf_frame_arrival_time = -1;
103 static int hf_frame_time_delta = -1;
104 static int hf_frame_number = -1;
105 static int hf_frame_packet_len = -1;
106 static int hf_frame_capture_len = -1;
107 static int proto_short = -1;
108 static int proto_malformed = -1;
110 static gint ett_frame = -1;
112 GMemChunk *frame_proto_data_area = NULL;
115 * Free up any space allocated for frame proto data areas and then
116 * allocate a new area.
118 * We can free the area, as the structures it contains are pointed to by
119 * frames, that will be freed as well.
122 packet_init_protocol(void)
125 if (frame_proto_data_area)
126 g_mem_chunk_destroy(frame_proto_data_area);
128 frame_proto_data_area = g_mem_chunk_new("frame_proto_data_area",
129 sizeof(frame_proto_data),
130 20 * sizeof(frame_proto_data), /* FIXME*/
135 /* Wrapper for the most common case of asking
136 * for a string using a colon as the hex-digit separator.
139 ether_to_str(const guint8 *ad)
141 return ether_to_str_punct(ad, ':');
144 /* Places char punct in the string as the hex-digit separator.
145 * If punct is '\0', no punctuation is applied (and thus
146 * the resulting string is 5 bytes shorter)
149 ether_to_str_punct(const guint8 *ad, char punct) {
150 static gchar str[3][18];
155 static const gchar hex_digits[16] = "0123456789abcdef";
157 if (cur == &str[0][0]) {
159 } else if (cur == &str[1][0]) {
169 *--p = hex_digits[octet&0xF];
171 *--p = hex_digits[octet&0xF];
182 ip_to_str(const guint8 *ad) {
183 static gchar str[3][16];
190 if (cur == &str[0][0]) {
192 } else if (cur == &str[1][0]) {
202 *--p = (octet%10) + '0';
206 if (digit != 0 || octet != 0)
219 ip6_to_str(struct e_in6_addr *ad) {
220 #ifndef INET6_ADDRSTRLEN
221 #define INET6_ADDRSTRLEN 46
223 static gchar buf[INET6_ADDRSTRLEN];
225 inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
230 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
231 #define COMMA(do_it) ((do_it) ? ", " : "")
234 time_secs_to_str(guint32 time)
236 static gchar str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
237 static gchar *cur, *p;
238 int hours, mins, secs;
241 if (cur == &str[0][0]) {
243 } else if (cur == &str[1][0]) {
250 sprintf(cur, "0 time");
263 sprintf(p, "%u day%s", time, PLURALIZE(time));
269 sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
275 sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
281 sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
285 /* Max string length for displaying byte string. */
286 #define MAX_BYTE_STR_LEN 32
288 /* Turn an array of bytes into a string showing the bytes in hex. */
289 #define N_BYTES_TO_STR_STRINGS 6
291 bytes_to_str(const guint8 *bd, int bd_len) {
292 static gchar str[N_BYTES_TO_STR_STRINGS][MAX_BYTE_STR_LEN+3+1];
297 static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
298 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
301 if (cur_idx >= N_BYTES_TO_STR_STRINGS)
303 cur = &str[cur_idx][0];
305 len = MAX_BYTE_STR_LEN;
306 while (bd_len > 0 && len > 0) {
307 *p++ = hex[(*bd) >> 4];
308 *p++ = hex[(*bd) & 0xF];
314 /* Note that we're not showing the full string. */
323 static const char *mon_names[12] = {
339 abs_time_to_str(struct timeval *abs_time)
343 static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
345 if (cur == &str[0][0]) {
347 } else if (cur == &str[1][0]) {
353 tmp = localtime(&abs_time->tv_sec);
354 sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
355 mon_names[tmp->tm_mon],
361 (long)abs_time->tv_usec/100);
367 rel_time_to_str(struct timeval *rel_time)
370 static char str[3][10+1+6+1];
372 if (cur == &str[0][0]) {
374 } else if (cur == &str[1][0]) {
380 sprintf(cur, "%ld.%06ld", (long)rel_time->tv_sec,
381 (long)rel_time->tv_usec);
387 * Given a pointer into a data buffer, and to the end of the buffer,
388 * find the end of the (putative) line at that position in the data
390 * Return a pointer to the EOL character(s) in "*eol".
393 find_line_end(const u_char *data, const u_char *dataend, const u_char **eol)
395 const u_char *lineend;
397 lineend = memchr(data, '\n', dataend - data);
398 if (lineend == NULL) {
400 * No LF - line is probably continued in next TCP segment.
406 * Is the LF at the beginning of the line?
408 if (lineend > data) {
410 * No - is it preceded by a carriage return?
411 * (Perhaps it's supposed to be, but that's not guaranteed....)
413 if (*(lineend - 1) == '\r') {
415 * Yes. The EOL starts with the CR.
420 * No. The EOL starts with the LF.
425 * I seem to remember that we once saw lines ending with LF-CR
426 * in an HTTP request or response, so check if it's *followed*
427 * by a carriage return.
429 if (lineend < (dataend - 1) && *(lineend + 1) == '\r') {
431 * It's <non-LF><LF><CR>; say it ends with the CR.
439 * Point to the character after the last character.
446 #define MAX_COLUMNS_LINE_DETAIL 62
449 * Get the length of the next token in a line, and the beginning of the
450 * next token after that (if any).
451 * Return 0 if there is no next token.
454 get_token_len(const u_char *linep, const u_char *lineend,
455 const u_char **next_token)
457 const u_char *tokenp;
463 * Search for a blank, a CR or an LF, or the end of the buffer.
465 while (linep < lineend && *linep != ' ' && *linep != '\r' && *linep != '\n')
467 token_len = linep - tokenp;
470 * Skip trailing blanks.
472 while (linep < lineend && *linep == ' ')
481 * Given a string, generate a string from it that shows non-printable
482 * characters as C-style escapes, and return a pointer to it.
485 format_text(const u_char *string, int len)
487 static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
490 const u_char *stringend = string + len;
495 fmtbufp = &fmtbuf[0];
496 while (string < stringend) {
497 if (column >= MAX_COLUMNS_LINE_DETAIL) {
499 * Put "..." and quit.
501 strcpy(fmtbufp, " ...");
556 *fmtbufp++ = i + '0';
559 *fmtbufp++ = i + '0';
562 *fmtbufp++ = i + '0';
573 /* Tries to match val against each element in the value_string array vs.
574 Returns the associated string ptr on a match.
575 Formats val with fmt, and returns the resulting string, on failure. */
577 val_to_str(guint32 val, const value_string *vs, const char *fmt) {
579 static gchar str[3][64];
582 ret = match_strval(val, vs);
585 if (cur == &str[0][0]) {
587 } else if (cur == &str[1][0]) {
592 snprintf(cur, 64, fmt, val);
596 /* Tries to match val against each element in the value_string array vs.
597 Returns the associated string ptr on a match, or NULL on failure. */
599 match_strval(guint32 val, const value_string *vs) {
602 while (vs[i].strptr) {
603 if (vs[i].value == val)
604 return(vs[i].strptr);
611 /* Generate, into "buf", a string showing the bits of a bitfield.
612 Return a pointer to the character after that string. */
614 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
622 bit = 1 << (width - 1);
625 /* This bit is part of the field. Show its value. */
631 /* This bit is not part of the field. */
646 /* Generate a string describing a Boolean bitfield (a one-bit field that
647 says something is either true of false). */
649 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
650 const char *truedesc, const char *falsedesc)
652 static char buf[1025];
655 p = decode_bitfield_value(buf, val, mask, width);
659 strcpy(p, falsedesc);
663 /* Generate a string describing an enumerated bitfield (an N-bit field
664 with various specific values having particular names). */
666 decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
667 const value_string *tab, const char *fmt)
669 static char buf[1025];
672 p = decode_bitfield_value(buf, val, mask, width);
673 sprintf(p, fmt, val_to_str(val & mask, tab, "Unknown"));
677 /* Generate a string describing a numeric bitfield (an N-bit field whose
678 value is just a number). */
680 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
683 static char buf[1025];
687 /* Compute the number of bits we have to shift the bitfield right
688 to extract its value. */
689 while ((mask & (1<<shift)) == 0)
692 p = decode_bitfield_value(buf, val, mask, width);
693 sprintf(p, fmt, (val & mask) >> shift);
697 /* Checks to see if a particular packet information element is needed for
700 check_col(frame_data *fd, gint el) {
704 for (i = 0; i < fd->cinfo->num_cols; i++) {
705 if (fd->cinfo->fmt_matx[i][el])
712 /* Adds a vararg list to a packet info string. */
714 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
719 va_start(ap, format);
720 for (i = 0; i < fd->cinfo->num_cols; i++) {
721 if (fd->cinfo->fmt_matx[i][el]) {
723 max_len = COL_MAX_INFO_LEN;
725 max_len = COL_MAX_LEN;
726 vsnprintf(fd->cinfo->col_data[i], max_len, format, ap);
732 col_add_str(frame_data *fd, gint el, const gchar* str) {
736 for (i = 0; i < fd->cinfo->num_cols; i++) {
737 if (fd->cinfo->fmt_matx[i][el]) {
739 max_len = COL_MAX_INFO_LEN;
741 max_len = COL_MAX_LEN;
742 strncpy(fd->cinfo->col_data[i], str, max_len);
743 fd->cinfo->col_data[i][max_len - 1] = 0;
748 /* Appends a vararg list to a packet info string. */
750 col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
755 va_start(ap, format);
756 for (i = 0; i < fd->cinfo->num_cols; i++) {
757 if (fd->cinfo->fmt_matx[i][el]) {
758 len = strlen(fd->cinfo->col_data[i]);
760 max_len = COL_MAX_INFO_LEN;
762 max_len = COL_MAX_LEN;
763 vsnprintf(&fd->cinfo->col_data[i][len], max_len - len, format, ap);
769 col_append_str(frame_data *fd, gint el, gchar* str) {
773 for (i = 0; i < fd->cinfo->num_cols; i++) {
774 if (fd->cinfo->fmt_matx[i][el]) {
775 len = strlen(fd->cinfo->col_data[i]);
777 max_len = COL_MAX_LEN;
779 max_len = COL_MAX_INFO_LEN;
780 strncat(fd->cinfo->col_data[i], str, max_len - len);
781 fd->cinfo->col_data[i][max_len - 1] = 0;
786 /* To do: Add check_col checks to the col_add* routines */
789 col_set_abs_time(frame_data *fd, int col)
795 tmp = localtime(&then);
796 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
800 (long)fd->abs_usecs/100);
804 col_set_rel_time(frame_data *fd, int col)
806 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->rel_secs,
811 col_set_delta_time(frame_data *fd, int col)
813 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->del_secs,
817 /* Add "command-line-specified" time.
818 XXX - this is called from "file.c" when the user changes the time
819 format they want for "command-line-specified" time; it's a bit ugly
820 that we have to export it, but if we go to a CList-like widget that
821 invokes callbacks to get the text for the columns rather than
822 requiring us to stuff the text into the widget from outside, we
823 might be able to clean this up. */
825 col_set_cls_time(frame_data *fd, int col)
827 switch (timestamp_type) {
829 col_set_abs_time(fd, col);
833 col_set_rel_time(fd, col);
837 col_set_delta_time(fd, col);
843 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
846 struct e_in6_addr ipv6_addr;
847 struct atalk_ddp_addr ddp_addr;
848 struct sna_fid_type_4_addr sna_fid_type_4_addr;
850 switch (addr->type) {
854 strncpy(fd->cinfo->col_data[col], get_ether_name(addr->data), COL_MAX_LEN);
856 strncpy(fd->cinfo->col_data[col], ether_to_str(addr->data), COL_MAX_LEN);
860 memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
862 strncpy(fd->cinfo->col_data[col], get_hostname(ipv4_addr), COL_MAX_LEN);
864 strncpy(fd->cinfo->col_data[col], ip_to_str(addr->data), COL_MAX_LEN);
868 memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
870 strncpy(fd->cinfo->col_data[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
872 strncpy(fd->cinfo->col_data[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
876 strncpy(fd->cinfo->col_data[col],
877 ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
884 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X", addr->data[0]);
888 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X",
889 pntohs(&addr->data[0]));
892 case SNA_FID_TYPE_4_ADDR_LEN:
893 memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
894 strncpy(fd->cinfo->col_data[col],
895 sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
901 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
902 strncpy(fd->cinfo->col_data[col], atalk_addr_to_str(&ddp_addr),
907 strncpy(fd->cinfo->col_data[col], vines_addr_to_str(&addr->data[0]),
914 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
918 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
925 strncpy(fd->cinfo->col_data[col], get_tcp_port(port), COL_MAX_LEN);
927 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
932 strncpy(fd->cinfo->col_data[col], get_udp_port(port), COL_MAX_LEN);
934 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
940 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
944 fill_in_columns(frame_data *fd)
948 for (i = 0; i < fd->cinfo->num_cols; i++) {
949 switch (fd->cinfo->col_fmt[i]) {
952 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%u", fd->num);
956 col_set_cls_time(fd, i);
960 col_set_abs_time(fd, i);
964 col_set_rel_time(fd, i);
968 col_set_delta_time(fd, i);
972 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
973 col_set_addr(fd, i, &pi.src, TRUE);
977 col_set_addr(fd, i, &pi.src, FALSE);
982 col_set_addr(fd, i, &pi.dl_src, TRUE);
985 case COL_UNRES_DL_SRC:
986 col_set_addr(fd, i, &pi.dl_src, FALSE);
989 case COL_DEF_NET_SRC:
990 case COL_RES_NET_SRC:
991 col_set_addr(fd, i, &pi.net_src, TRUE);
994 case COL_UNRES_NET_SRC:
995 col_set_addr(fd, i, &pi.net_src, FALSE);
999 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
1000 col_set_addr(fd, i, &pi.dst, TRUE);
1004 col_set_addr(fd, i, &pi.dst, FALSE);
1007 case COL_DEF_DL_DST:
1008 case COL_RES_DL_DST:
1009 col_set_addr(fd, i, &pi.dl_dst, TRUE);
1012 case COL_UNRES_DL_DST:
1013 col_set_addr(fd, i, &pi.dl_dst, FALSE);
1016 case COL_DEF_NET_DST:
1017 case COL_RES_NET_DST:
1018 col_set_addr(fd, i, &pi.net_dst, TRUE);
1021 case COL_UNRES_NET_DST:
1022 col_set_addr(fd, i, &pi.net_dst, FALSE);
1025 case COL_DEF_SRC_PORT:
1026 case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
1027 col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
1030 case COL_UNRES_SRC_PORT:
1031 col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
1034 case COL_DEF_DST_PORT:
1035 case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
1036 col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
1039 case COL_UNRES_DST_PORT:
1040 col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
1043 case COL_PROTOCOL: /* currently done by dissectors */
1044 case COL_INFO: /* currently done by dissectors */
1047 case COL_PACKET_LENGTH:
1048 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%d", fd->pkt_len);
1051 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
1057 void blank_packetinfo(void)
1059 pi.dl_src.type = AT_NONE;
1060 pi.dl_dst.type = AT_NONE;
1061 pi.net_src.type = AT_NONE;
1062 pi.net_dst.type = AT_NONE;
1063 pi.src.type = AT_NONE;
1064 pi.dst.type = AT_NONE;
1069 pi.current_proto = "<Missing Protocol Name>";
1072 /* Do all one-time initialization. */
1086 dissect_cleanup(void)
1094 /* Allow protocols to register "init" routines, which are called before
1095 we make a pass through a capture file and dissect all its packets
1096 (e.g., when we read in a new capture file, or run a "filter packets"
1097 or "colorize packets" pass over the current capture file). */
1098 static GSList *init_routines;
1101 register_init_routine(void (*func)(void))
1103 init_routines = g_slist_append(init_routines, func);
1106 /* Call all the registered "init" routines. */
1108 call_init_routine(gpointer routine, gpointer dummy)
1110 void (*func)(void) = routine;
1116 init_all_protocols(void)
1118 g_slist_foreach(init_routines, &call_init_routine, NULL);
1121 /* this routine checks the frame type from the cf structure */
1123 dissect_packet(union wtap_pseudo_header *pseudo_header, const u_char *pd,
1124 frame_data *fd, proto_tree *tree)
1126 proto_tree *fh_tree;
1131 /* Put in frame header information. */
1133 ti = proto_tree_add_protocol_format(tree, proto_frame, NullTVB, 0, fd->cap_len,
1134 "Frame %u (%u on wire, %u captured)", fd->num,
1135 fd->pkt_len, fd->cap_len);
1137 fh_tree = proto_item_add_subtree(ti, ett_frame);
1139 tv.tv_sec = fd->abs_secs;
1140 tv.tv_usec = fd->abs_usecs;
1142 proto_tree_add_item(fh_tree, hf_frame_arrival_time, NullTVB,
1145 tv.tv_sec = fd->del_secs;
1146 tv.tv_usec = fd->del_usecs;
1148 proto_tree_add_item(fh_tree, hf_frame_time_delta, NullTVB,
1151 proto_tree_add_item(fh_tree, hf_frame_number, NullTVB,
1154 proto_tree_add_uint_format(fh_tree, hf_frame_packet_len, NullTVB,
1155 0, 0, fd->pkt_len, "Packet Length: %d byte%s", fd->pkt_len,
1156 plurality(fd->pkt_len, "", "s"));
1158 proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, NullTVB,
1159 0, 0, fd->cap_len, "Capture Length: %d byte%s", fd->cap_len,
1160 plurality(fd->cap_len, "", "s"));
1165 /* Set the initial payload to the packet length, and the initial
1166 captured payload to the capture length (other protocols may
1167 reduce them if their headers say they're less). */
1168 pi.len = fd->pkt_len;
1169 pi.captured_len = fd->cap_len;
1171 tvb = tvb_new_real_data(pd, fd->cap_len, -1);
1173 pi.compat_top_tvb = tvb;
1174 pi.pseudo_header = pseudo_header;
1177 switch (fd->lnk_t) {
1178 case WTAP_ENCAP_ETHERNET :
1179 dissect_eth(tvb, &pi, tree);
1181 case WTAP_ENCAP_FDDI :
1182 dissect_fddi(tvb, &pi, tree, FALSE);
1184 case WTAP_ENCAP_FDDI_BITSWAPPED :
1185 dissect_fddi(tvb, &pi, tree, TRUE);
1187 case WTAP_ENCAP_TR :
1188 dissect_tr(tvb, &pi, tree);
1190 case WTAP_ENCAP_NULL :
1191 dissect_null(tvb, &pi, tree);
1193 case WTAP_ENCAP_PPP :
1194 dissect_ppp(tvb, &pi, tree);
1196 case WTAP_ENCAP_LAPB :
1197 dissect_lapb(tvb, &pi, tree);
1199 case WTAP_ENCAP_RAW_IP :
1200 dissect_raw(tvb, &pi, tree);
1202 case WTAP_ENCAP_LINUX_ATM_CLIP :
1203 dissect_clip(tvb, &pi, tree);
1205 case WTAP_ENCAP_ATM_SNIFFER :
1206 dissect_atm(pseudo_header, pd, fd, tree);
1208 case WTAP_ENCAP_ASCEND :
1209 dissect_ascend(tvb, &pi, tree);
1211 case WTAP_ENCAP_LAPD :
1212 dissect_lapd(pseudo_header, pd, fd, tree);
1214 case WTAP_ENCAP_V120 :
1215 dissect_v120(pseudo_header, pd, fd, tree);
1219 CATCH(BoundsError) {
1220 proto_tree_add_protocol_format(tree, proto_short, NullTVB, 0, 0,
1221 "[Short Frame: %s]", pi.current_proto );
1223 CATCH(ReportedBoundsError) {
1224 proto_tree_add_protocol_format(tree, proto_malformed, NullTVB, 0, 0,
1225 "[Malformed Frame: %s]", pi.current_proto );
1229 /* Free all tvb's created from this tvb, unless dissector
1230 * wanted to store the pointer (in which case, the dissector
1231 * would have incremented the usage count on that tvbuff_t*) */
1232 tvb_free_chain(tvb);
1234 fd->flags.visited = 1;
1237 gint p_compare(gconstpointer a, gconstpointer b)
1240 if (((frame_proto_data *)a) -> proto > ((frame_proto_data *)b) -> proto)
1242 else if (((frame_proto_data *)a) -> proto == ((frame_proto_data *)b) -> proto)
1250 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
1252 frame_proto_data *p1 = g_mem_chunk_alloc(frame_proto_data_area);
1254 g_assert(p1 != NULL);
1256 p1 -> proto = proto;
1257 p1 -> proto_data = proto_data;
1259 /* Add it to the GSLIST */
1261 fd -> pfd = g_slist_insert_sorted(fd -> pfd,
1268 p_get_proto_data(frame_data *fd, int proto)
1270 frame_proto_data temp;
1274 temp.proto_data = NULL;
1276 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
1278 if (item) return (void *)item->data;
1285 p_rem_proto_data(frame_data *fd, int proto)
1292 proto_register_frame(void)
1294 static hf_register_info hf[] = {
1295 { &hf_frame_arrival_time,
1296 { "Arrival Time", "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1299 { &hf_frame_time_delta,
1300 { "Time delta from previous packet", "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
1305 { "Frame Number", "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
1308 { &hf_frame_packet_len,
1309 { "Total Frame Length", "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
1312 { &hf_frame_capture_len,
1313 { "Capture Frame Length", "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
1316 static gint *ett[] = {
1320 proto_frame = proto_register_protocol("Frame", "frame");
1321 proto_register_field_array(proto_frame, hf, array_length(hf));
1322 proto_register_subtree_array(ett, array_length(ett));
1324 proto_short = proto_register_protocol("Short Frame", "short");
1325 proto_malformed = proto_register_protocol("Malformed Frame", "malformed");
1326 register_init_routine(&packet_init_protocol);
1330 /*********************** code added for sub-dissector lookup *********************/
1332 static GHashTable *dissector_tables = NULL;
1334 /* Finds a dissector table by field name. */
1335 static dissector_table_t
1336 find_dissector_table(const char *name)
1338 g_assert(dissector_tables);
1339 return g_hash_table_lookup( dissector_tables, name );
1342 /* lookup a dissector based upon pattern. */
1344 dissector_lookup( dissector_table_t table, guint32 pattern)
1346 return g_hash_table_lookup( table, GUINT_TO_POINTER( pattern));
1350 /* add an entry, lookup the dissector table for the specified field name, */
1351 /* if a valid table found, add the subdissector */
1353 dissector_add(const char *name, guint32 pattern, dissector_t dissector)
1355 dissector_table_t sub_dissectors = find_dissector_table( name);
1358 g_assert( sub_dissectors);
1360 /* do the table insertion */
1361 g_hash_table_insert( sub_dissectors, GUINT_TO_POINTER( pattern),
1362 (gpointer)dissector);
1365 /* delete the entry for this dissector at this pattern */
1367 /* NOTE: this doesn't use the dissector call variable. It is included to */
1368 /* be consistant with the dissector_add and more importantly to be used */
1369 /* if the technique of adding a temporary dissector is implemented. */
1370 /* If temporary dissectors are deleted, then the original dissector must */
1373 dissector_delete(const char *name, guint32 pattern, dissector_t dissector)
1375 dissector_table_t sub_dissectors = find_dissector_table( name);
1378 g_assert( sub_dissectors);
1380 /* remove the hash table entry */
1381 g_hash_table_remove( sub_dissectors, GUINT_TO_POINTER( pattern));
1384 /* Look for a given port in a given dissector table and, if found, call
1385 the dissector with the arguments supplied, and return TRUE, otherwise
1388 dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
1389 const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1391 dissector_t subdissector;
1393 subdissector = dissector_lookup(sub_dissectors, port);
1394 if (subdissector != NULL) {
1395 pi.match_port = port;
1396 (subdissector)(pd, offset, fd, tree);
1403 register_dissector_table(const char *name)
1405 dissector_table_t sub_dissectors;
1407 /* Create our hash-of-hashes if it doesn't already exist */
1408 if (!dissector_tables) {
1409 dissector_tables = g_hash_table_new( g_str_hash, g_str_equal );
1410 g_assert(dissector_tables);
1413 /* Make sure the registration is unique */
1414 g_assert(!g_hash_table_lookup( dissector_tables, name ));
1416 /* Create and register the dissector table for this name; returns */
1417 /* a pointer to the dissector table. */
1418 sub_dissectors = g_hash_table_new( g_direct_hash, g_direct_equal );
1419 g_hash_table_insert( dissector_tables, (gpointer)name, (gpointer) sub_dissectors );
1420 return sub_dissectors;
1423 static GHashTable *heur_dissector_lists = NULL;
1425 /* Finds a heuristic dissector table by field name. */
1426 static heur_dissector_list_t *
1427 find_heur_dissector_list(const char *name)
1429 g_assert(heur_dissector_lists != NULL);
1430 return g_hash_table_lookup(heur_dissector_lists, name);
1434 heur_dissector_add(const char *name, heur_dissector_t dissector)
1436 heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
1439 g_assert(sub_dissectors != NULL);
1441 /* do the table insertion */
1442 *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)dissector);
1446 dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
1447 const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1449 heur_dissector_t subdissector;
1452 for (entry = sub_dissectors; entry != NULL; entry = g_slist_next(entry)) {
1453 subdissector = (heur_dissector_t)entry->data;
1454 if ((subdissector)(pd, offset, fd, tree))
1461 register_heur_dissector_list(const char *name, heur_dissector_list_t *sub_dissectors)
1463 /* Create our hash-of-hashes if it doesn't already exist */
1464 if (heur_dissector_lists == NULL) {
1465 heur_dissector_lists = g_hash_table_new(g_str_hash, g_str_equal);
1466 g_assert(heur_dissector_lists != NULL);
1469 /* Make sure the registration is unique */
1470 g_assert(g_hash_table_lookup(heur_dissector_lists, name) == NULL);
1472 *sub_dissectors = NULL; /* initially empty */
1473 g_hash_table_insert(heur_dissector_lists, (gpointer)name,
1474 (gpointer) sub_dissectors);