2 * Routines for packet disassembly
4 * $Id: packet.c,v 1.80 2000/05/11 08:15:58 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;
108 static gint ett_frame = -1;
110 GMemChunk *frame_proto_data_area = NULL;
113 * Free up any space allocated for frame proto data areas and then
114 * allocate a new area.
116 * We can free the area, as the structures it contains are pointed to by
117 * frames, that will be freed as well.
120 packet_init_protocol(void)
123 if (frame_proto_data_area)
124 g_mem_chunk_destroy(frame_proto_data_area);
126 frame_proto_data_area = g_mem_chunk_new("frame_proto_data_area",
127 sizeof(frame_proto_data),
128 20 * sizeof(frame_proto_data), /* FIXME*/
133 /* Wrapper for the most common case of asking
134 * for a string using a colon as the hex-digit separator.
137 ether_to_str(const guint8 *ad)
139 return ether_to_str_punct(ad, ':');
142 /* Places char punct in the string as the hex-digit separator.
143 * If punct is '\0', no punctuation is applied (and thus
144 * the resulting string is 5 bytes shorter)
147 ether_to_str_punct(const guint8 *ad, char punct) {
148 static gchar str[3][18];
153 static const gchar hex_digits[16] = "0123456789abcdef";
155 if (cur == &str[0][0]) {
157 } else if (cur == &str[1][0]) {
167 *--p = hex_digits[octet&0xF];
169 *--p = hex_digits[octet&0xF];
180 ip_to_str(const guint8 *ad) {
181 static gchar str[3][16];
188 if (cur == &str[0][0]) {
190 } else if (cur == &str[1][0]) {
200 *--p = (octet%10) + '0';
204 if (digit != 0 || octet != 0)
217 ip6_to_str(struct e_in6_addr *ad) {
218 #ifndef INET6_ADDRSTRLEN
219 #define INET6_ADDRSTRLEN 46
221 static gchar buf[INET6_ADDRSTRLEN];
223 inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
228 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
229 #define COMMA(do_it) ((do_it) ? ", " : "")
232 time_secs_to_str(guint32 time)
234 static gchar str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
235 static gchar *cur, *p;
236 int hours, mins, secs;
239 if (cur == &str[0][0]) {
241 } else if (cur == &str[1][0]) {
248 sprintf(cur, "0 time");
261 sprintf(p, "%u day%s", time, PLURALIZE(time));
267 sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
273 sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
279 sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
283 /* Max string length for displaying byte string. */
284 #define MAX_BYTE_STR_LEN 32
286 /* Turn an array of bytes into a string showing the bytes in hex. */
287 #define N_BYTES_TO_STR_STRINGS 6
289 bytes_to_str(const guint8 *bd, int bd_len) {
290 static gchar str[N_BYTES_TO_STR_STRINGS][MAX_BYTE_STR_LEN+3+1];
295 static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
296 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
299 if (cur_idx >= N_BYTES_TO_STR_STRINGS)
301 cur = &str[cur_idx][0];
303 len = MAX_BYTE_STR_LEN;
304 while (bd_len > 0 && len > 0) {
305 *p++ = hex[(*bd) >> 4];
306 *p++ = hex[(*bd) & 0xF];
312 /* Note that we're not showing the full string. */
321 static const char *mon_names[12] = {
337 abs_time_to_str(struct timeval *abs_time)
341 static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
343 if (cur == &str[0][0]) {
345 } else if (cur == &str[1][0]) {
351 tmp = localtime(&abs_time->tv_sec);
352 sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
353 mon_names[tmp->tm_mon],
359 (long)abs_time->tv_usec/100);
365 rel_time_to_str(struct timeval *rel_time)
368 static char str[3][10+1+6+1];
370 if (cur == &str[0][0]) {
372 } else if (cur == &str[1][0]) {
378 sprintf(cur, "%ld.%06ld", (long)rel_time->tv_sec,
379 (long)rel_time->tv_usec);
385 * Given a pointer into a data buffer, and to the end of the buffer,
386 * find the end of the (putative) line at that position in the data
388 * Return a pointer to the EOL character(s) in "*eol".
391 find_line_end(const u_char *data, const u_char *dataend, const u_char **eol)
393 const u_char *lineend;
395 lineend = memchr(data, '\n', dataend - data);
396 if (lineend == NULL) {
398 * No LF - line is probably continued in next TCP segment.
404 * Is the LF at the beginning of the line?
406 if (lineend > data) {
408 * No - is it preceded by a carriage return?
409 * (Perhaps it's supposed to be, but that's not guaranteed....)
411 if (*(lineend - 1) == '\r') {
413 * Yes. The EOL starts with the CR.
418 * No. The EOL starts with the LF.
423 * I seem to remember that we once saw lines ending with LF-CR
424 * in an HTTP request or response, so check if it's *followed*
425 * by a carriage return.
427 if (lineend < (dataend - 1) && *(lineend + 1) == '\r') {
429 * It's <non-LF><LF><CR>; say it ends with the CR.
437 * Point to the character after the last character.
444 #define MAX_COLUMNS_LINE_DETAIL 62
447 * Get the length of the next token in a line, and the beginning of the
448 * next token after that (if any).
449 * Return 0 if there is no next token.
452 get_token_len(const u_char *linep, const u_char *lineend,
453 const u_char **next_token)
455 const u_char *tokenp;
461 * Search for a blank, a CR or an LF, or the end of the buffer.
463 while (linep < lineend && *linep != ' ' && *linep != '\r' && *linep != '\n')
465 token_len = linep - tokenp;
468 * Skip trailing blanks.
470 while (linep < lineend && *linep == ' ')
479 * Given a string, generate a string from it that shows non-printable
480 * characters as C-style escapes, and return a pointer to it.
483 format_text(const u_char *string, int len)
485 static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
488 const u_char *stringend = string + len;
493 fmtbufp = &fmtbuf[0];
494 while (string < stringend) {
495 if (column >= MAX_COLUMNS_LINE_DETAIL) {
497 * Put "..." and quit.
499 strcpy(fmtbufp, " ...");
554 *fmtbufp++ = i + '0';
557 *fmtbufp++ = i + '0';
560 *fmtbufp++ = i + '0';
571 /* Tries to match val against each element in the value_string array vs.
572 Returns the associated string ptr on a match.
573 Formats val with fmt, and returns the resulting string, on failure. */
575 val_to_str(guint32 val, const value_string *vs, const char *fmt) {
577 static gchar str[3][64];
580 ret = match_strval(val, vs);
583 if (cur == &str[0][0]) {
585 } else if (cur == &str[1][0]) {
590 snprintf(cur, 64, fmt, val);
594 /* Tries to match val against each element in the value_string array vs.
595 Returns the associated string ptr on a match, or NULL on failure. */
597 match_strval(guint32 val, const value_string *vs) {
600 while (vs[i].strptr) {
601 if (vs[i].value == val)
602 return(vs[i].strptr);
609 /* Generate, into "buf", a string showing the bits of a bitfield.
610 Return a pointer to the character after that string. */
612 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
620 bit = 1 << (width - 1);
623 /* This bit is part of the field. Show its value. */
629 /* This bit is not part of the field. */
644 /* Generate a string describing a Boolean bitfield (a one-bit field that
645 says something is either true of false). */
647 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
648 const char *truedesc, const char *falsedesc)
650 static char buf[1025];
653 p = decode_bitfield_value(buf, val, mask, width);
657 strcpy(p, falsedesc);
661 /* Generate a string describing an enumerated bitfield (an N-bit field
662 with various specific values having particular names). */
664 decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
665 const value_string *tab, const char *fmt)
667 static char buf[1025];
670 p = decode_bitfield_value(buf, val, mask, width);
671 sprintf(p, fmt, val_to_str(val & mask, tab, "Unknown"));
675 /* Generate a string describing a numeric bitfield (an N-bit field whose
676 value is just a number). */
678 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
681 static char buf[1025];
685 /* Compute the number of bits we have to shift the bitfield right
686 to extract its value. */
687 while ((mask & (1<<shift)) == 0)
690 p = decode_bitfield_value(buf, val, mask, width);
691 sprintf(p, fmt, (val & mask) >> shift);
695 /* Checks to see if a particular packet information element is needed for
698 check_col(frame_data *fd, gint el) {
702 for (i = 0; i < fd->cinfo->num_cols; i++) {
703 if (fd->cinfo->fmt_matx[i][el])
710 /* Adds a vararg list to a packet info string. */
712 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
717 va_start(ap, format);
718 for (i = 0; i < fd->cinfo->num_cols; i++) {
719 if (fd->cinfo->fmt_matx[i][el]) {
721 max_len = COL_MAX_INFO_LEN;
723 max_len = COL_MAX_LEN;
724 vsnprintf(fd->cinfo->col_data[i], max_len, format, ap);
730 col_add_str(frame_data *fd, gint el, const gchar* str) {
734 for (i = 0; i < fd->cinfo->num_cols; i++) {
735 if (fd->cinfo->fmt_matx[i][el]) {
737 max_len = COL_MAX_INFO_LEN;
739 max_len = COL_MAX_LEN;
740 strncpy(fd->cinfo->col_data[i], str, max_len);
741 fd->cinfo->col_data[i][max_len - 1] = 0;
746 /* Appends a vararg list to a packet info string. */
748 col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
753 va_start(ap, format);
754 for (i = 0; i < fd->cinfo->num_cols; i++) {
755 if (fd->cinfo->fmt_matx[i][el]) {
756 len = strlen(fd->cinfo->col_data[i]);
758 max_len = COL_MAX_INFO_LEN;
760 max_len = COL_MAX_LEN;
761 vsnprintf(&fd->cinfo->col_data[i][len], max_len - len, format, ap);
767 col_append_str(frame_data *fd, gint el, gchar* str) {
771 for (i = 0; i < fd->cinfo->num_cols; i++) {
772 if (fd->cinfo->fmt_matx[i][el]) {
773 len = strlen(fd->cinfo->col_data[i]);
775 max_len = COL_MAX_LEN;
777 max_len = COL_MAX_INFO_LEN;
778 strncat(fd->cinfo->col_data[i], str, max_len - len);
779 fd->cinfo->col_data[i][max_len - 1] = 0;
784 /* To do: Add check_col checks to the col_add* routines */
787 col_set_abs_time(frame_data *fd, int col)
793 tmp = localtime(&then);
794 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
798 (long)fd->abs_usecs/100);
802 col_set_rel_time(frame_data *fd, int col)
804 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->rel_secs,
809 col_set_delta_time(frame_data *fd, int col)
811 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->del_secs,
815 /* Add "command-line-specified" time.
816 XXX - this is called from "file.c" when the user changes the time
817 format they want for "command-line-specified" time; it's a bit ugly
818 that we have to export it, but if we go to a CList-like widget that
819 invokes callbacks to get the text for the columns rather than
820 requiring us to stuff the text into the widget from outside, we
821 might be able to clean this up. */
823 col_set_cls_time(frame_data *fd, int col)
825 switch (timestamp_type) {
827 col_set_abs_time(fd, col);
831 col_set_rel_time(fd, col);
835 col_set_delta_time(fd, col);
841 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
844 struct e_in6_addr ipv6_addr;
845 struct atalk_ddp_addr ddp_addr;
846 struct sna_fid_type_4_addr sna_fid_type_4_addr;
848 switch (addr->type) {
852 strncpy(fd->cinfo->col_data[col], get_ether_name(addr->data), COL_MAX_LEN);
854 strncpy(fd->cinfo->col_data[col], ether_to_str(addr->data), COL_MAX_LEN);
858 memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
860 strncpy(fd->cinfo->col_data[col], get_hostname(ipv4_addr), COL_MAX_LEN);
862 strncpy(fd->cinfo->col_data[col], ip_to_str(addr->data), COL_MAX_LEN);
866 memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
868 strncpy(fd->cinfo->col_data[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
870 strncpy(fd->cinfo->col_data[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
874 strncpy(fd->cinfo->col_data[col],
875 ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
882 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X", addr->data[0]);
886 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X",
887 pntohs(&addr->data[0]));
890 case SNA_FID_TYPE_4_ADDR_LEN:
891 memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
892 strncpy(fd->cinfo->col_data[col],
893 sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
899 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
900 strncpy(fd->cinfo->col_data[col], atalk_addr_to_str(&ddp_addr),
905 strncpy(fd->cinfo->col_data[col], vines_addr_to_str(&addr->data[0]),
912 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
916 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
923 strncpy(fd->cinfo->col_data[col], get_tcp_port(port), COL_MAX_LEN);
925 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
930 strncpy(fd->cinfo->col_data[col], get_udp_port(port), COL_MAX_LEN);
932 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
938 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
942 fill_in_columns(frame_data *fd)
946 for (i = 0; i < fd->cinfo->num_cols; i++) {
947 switch (fd->cinfo->col_fmt[i]) {
950 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%u", fd->num);
954 col_set_cls_time(fd, i);
958 col_set_abs_time(fd, i);
962 col_set_rel_time(fd, i);
966 col_set_delta_time(fd, i);
970 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
971 col_set_addr(fd, i, &pi.src, TRUE);
975 col_set_addr(fd, i, &pi.src, FALSE);
980 col_set_addr(fd, i, &pi.dl_src, TRUE);
983 case COL_UNRES_DL_SRC:
984 col_set_addr(fd, i, &pi.dl_src, FALSE);
987 case COL_DEF_NET_SRC:
988 case COL_RES_NET_SRC:
989 col_set_addr(fd, i, &pi.net_src, TRUE);
992 case COL_UNRES_NET_SRC:
993 col_set_addr(fd, i, &pi.net_src, FALSE);
997 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
998 col_set_addr(fd, i, &pi.dst, TRUE);
1002 col_set_addr(fd, i, &pi.dst, FALSE);
1005 case COL_DEF_DL_DST:
1006 case COL_RES_DL_DST:
1007 col_set_addr(fd, i, &pi.dl_dst, TRUE);
1010 case COL_UNRES_DL_DST:
1011 col_set_addr(fd, i, &pi.dl_dst, FALSE);
1014 case COL_DEF_NET_DST:
1015 case COL_RES_NET_DST:
1016 col_set_addr(fd, i, &pi.net_dst, TRUE);
1019 case COL_UNRES_NET_DST:
1020 col_set_addr(fd, i, &pi.net_dst, FALSE);
1023 case COL_DEF_SRC_PORT:
1024 case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
1025 col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
1028 case COL_UNRES_SRC_PORT:
1029 col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
1032 case COL_DEF_DST_PORT:
1033 case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
1034 col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
1037 case COL_UNRES_DST_PORT:
1038 col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
1041 case COL_PROTOCOL: /* currently done by dissectors */
1042 case COL_INFO: /* currently done by dissectors */
1045 case COL_PACKET_LENGTH:
1046 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%d", fd->pkt_len);
1049 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
1055 void blank_packetinfo(void)
1057 pi.dl_src.type = AT_NONE;
1058 pi.dl_dst.type = AT_NONE;
1059 pi.net_src.type = AT_NONE;
1060 pi.net_dst.type = AT_NONE;
1061 pi.src.type = AT_NONE;
1062 pi.dst.type = AT_NONE;
1067 pi.current_proto = "";
1070 /* Do all one-time initialization. */
1084 dissect_cleanup(void)
1092 /* Allow protocols to register "init" routines, which are called before
1093 we make a pass through a capture file and dissect all its packets
1094 (e.g., when we read in a new capture file, or run a "filter packets"
1095 or "colorize packets" pass over the current capture file). */
1096 static GSList *init_routines;
1099 register_init_routine(void (*func)(void))
1101 init_routines = g_slist_append(init_routines, func);
1104 /* Call all the registered "init" routines. */
1106 call_init_routine(gpointer routine, gpointer dummy)
1108 void (*func)(void) = routine;
1114 init_all_protocols(void)
1116 g_slist_foreach(init_routines, &call_init_routine, NULL);
1119 /* this routine checks the frame type from the cf structure */
1121 dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
1123 proto_tree *fh_tree;
1128 /* Put in frame header information. */
1130 ti = proto_tree_add_protocol_format(tree, proto_frame, NullTVB, 0, fd->cap_len,
1131 "Frame %u (%u on wire, %u captured)", fd->num,
1132 fd->pkt_len, fd->cap_len);
1134 fh_tree = proto_item_add_subtree(ti, ett_frame);
1136 tv.tv_sec = fd->abs_secs;
1137 tv.tv_usec = fd->abs_usecs;
1139 proto_tree_add_item(fh_tree, hf_frame_arrival_time, NullTVB,
1142 tv.tv_sec = fd->del_secs;
1143 tv.tv_usec = fd->del_usecs;
1145 proto_tree_add_item(fh_tree, hf_frame_time_delta, NullTVB,
1148 proto_tree_add_item(fh_tree, hf_frame_number, NullTVB,
1151 proto_tree_add_uint_format(fh_tree, hf_frame_packet_len, NullTVB,
1152 0, 0, fd->pkt_len, "Packet Length: %d byte%s", fd->pkt_len,
1153 plurality(fd->pkt_len, "", "s"));
1155 proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, NullTVB,
1156 0, 0, fd->cap_len, "Capture Length: %d byte%s", fd->cap_len,
1157 plurality(fd->cap_len, "", "s"));
1162 /* Set the initial payload to the packet length, and the initial
1163 captured payload to the capture length (other protocols may
1164 reduce them if their headers say they're less). */
1165 pi.len = fd->pkt_len;
1166 pi.captured_len = fd->cap_len;
1168 tvb = tvb_new_real_data(pd, fd->cap_len);
1170 pi.compat_top_tvb = tvb;
1173 switch (fd->lnk_t) {
1174 case WTAP_ENCAP_ETHERNET :
1175 /*dissect_eth(tvb, &pi, tree);*/
1176 dissect_eth(pd, 0, fd, tree);
1178 case WTAP_ENCAP_FDDI :
1179 dissect_fddi(tvb, &pi, tree, FALSE);
1181 case WTAP_ENCAP_FDDI_BITSWAPPED :
1182 dissect_fddi(tvb, &pi, tree, TRUE);
1184 case WTAP_ENCAP_TR :
1185 dissect_tr(pd, 0, fd, tree);
1187 case WTAP_ENCAP_NULL :
1188 dissect_null(pd, fd, tree);
1190 case WTAP_ENCAP_PPP :
1191 dissect_ppp(pd, 0, fd, tree);
1193 case WTAP_ENCAP_LAPB :
1194 dissect_lapb(pd, fd, tree);
1196 case WTAP_ENCAP_RAW_IP :
1197 dissect_raw(pd, fd, tree);
1199 case WTAP_ENCAP_LINUX_ATM_CLIP :
1200 dissect_clip(pd, fd, tree);
1202 case WTAP_ENCAP_ATM_SNIFFER :
1203 dissect_atm(pd, fd, tree);
1205 case WTAP_ENCAP_ASCEND :
1206 dissect_ascend(pd, fd, tree);
1208 case WTAP_ENCAP_LAPD :
1209 dissect_lapd(pd, fd, tree);
1211 case WTAP_ENCAP_V120 :
1212 dissect_v120(pd, fd, tree);
1216 CATCH(BoundsError) {
1217 proto_tree_add_text(tree, NullTVB, 0, 0, "Short Frame: [%s]", pi.current_proto );
1221 /* Free all tvb's created from this tvb, unless dissector
1222 * wanted to store the pointer (in which case, the dissector
1223 * would have incremented the usage count on that tvbuff_t*) */
1224 tvb_free_chain(tvb);
1226 fd->flags.visited = 1;
1229 gint p_compare(gconstpointer a, gconstpointer b)
1232 if (((frame_proto_data *)a) -> proto > ((frame_proto_data *)b) -> proto)
1234 else if (((frame_proto_data *)a) -> proto == ((frame_proto_data *)b) -> proto)
1242 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
1244 frame_proto_data *p1 = g_mem_chunk_alloc(frame_proto_data_area);
1246 g_assert(p1 != NULL);
1248 p1 -> proto = proto;
1249 p1 -> proto_data = proto_data;
1251 /* Add it to the GSLIST */
1253 fd -> pfd = g_slist_insert_sorted(fd -> pfd,
1260 p_get_proto_data(frame_data *fd, int proto)
1262 frame_proto_data temp;
1266 temp.proto_data = NULL;
1268 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
1270 if (item) return (void *)item->data;
1277 p_rem_proto_data(frame_data *fd, int proto)
1284 proto_register_frame(void)
1286 static hf_register_info hf[] = {
1287 { &hf_frame_arrival_time,
1288 { "Arrival Time", "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1291 { &hf_frame_time_delta,
1292 { "Time delta from previous packet", "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
1297 { "Frame Number", "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
1300 { &hf_frame_packet_len,
1301 { "Total Frame Length", "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
1304 { &hf_frame_capture_len,
1305 { "Capture Frame Length", "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
1308 static gint *ett[] = {
1312 proto_frame = proto_register_protocol("Frame", "frame");
1313 proto_register_field_array(proto_frame, hf, array_length(hf));
1314 proto_register_subtree_array(ett, array_length(ett));
1316 register_init_routine(&packet_init_protocol);
1320 /*********************** code added for sub-dissector lookup *********************/
1322 static GHashTable *dissector_tables = NULL;
1324 /* Finds a dissector table by field name. */
1325 static dissector_table_t
1326 find_dissector_table(const char *name)
1328 g_assert(dissector_tables);
1329 return g_hash_table_lookup( dissector_tables, name );
1332 /* lookup a dissector based upon pattern. */
1334 dissector_lookup( dissector_table_t table, guint32 pattern)
1336 return g_hash_table_lookup( table, GUINT_TO_POINTER( pattern));
1340 /* add an entry, lookup the dissector table for the specified field name, */
1341 /* if a valid table found, add the subdissector */
1343 dissector_add(const char *name, guint32 pattern, dissector_t dissector)
1345 dissector_table_t sub_dissectors = find_dissector_table( name);
1348 g_assert( sub_dissectors);
1350 /* do the table insertion */
1351 g_hash_table_insert( sub_dissectors, GUINT_TO_POINTER( pattern),
1352 (gpointer)dissector);
1355 /* delete the entry for this dissector at this pattern */
1357 /* NOTE: this doesn't use the dissector call variable. It is included to */
1358 /* be consistant with the dissector_add and more importantly to be used */
1359 /* if the technique of adding a temporary dissector is implemented. */
1360 /* If temporary dissectors are deleted, then the original dissector must */
1363 dissector_delete(const char *name, guint32 pattern, dissector_t dissector)
1365 dissector_table_t sub_dissectors = find_dissector_table( name);
1368 g_assert( sub_dissectors);
1370 /* remove the hash table entry */
1371 g_hash_table_remove( sub_dissectors, GUINT_TO_POINTER( pattern));
1374 /* Look for a given port in a given dissector table and, if found, call
1375 the dissector with the arguments supplied, and return TRUE, otherwise
1378 dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
1379 const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1381 dissector_t subdissector;
1383 subdissector = dissector_lookup(sub_dissectors, port);
1384 if (subdissector != NULL) {
1385 pi.match_port = port;
1386 (subdissector)(pd, offset, fd, tree);
1393 register_dissector_table(const char *name)
1395 dissector_table_t sub_dissectors;
1397 /* Create our hash-of-hashes if it doesn't already exist */
1398 if (!dissector_tables) {
1399 dissector_tables = g_hash_table_new( g_str_hash, g_str_equal );
1400 g_assert(dissector_tables);
1403 /* Make sure the registration is unique */
1404 g_assert(!g_hash_table_lookup( dissector_tables, name ));
1406 /* Create and register the dissector table for this name; returns */
1407 /* a pointer to the dissector table. */
1408 sub_dissectors = g_hash_table_new( g_direct_hash, g_direct_equal );
1409 g_hash_table_insert( dissector_tables, (gpointer)name, (gpointer) sub_dissectors );
1410 return sub_dissectors;
1413 static GHashTable *heur_dissector_lists = NULL;
1415 /* Finds a heuristic dissector table by field name. */
1416 static heur_dissector_list_t *
1417 find_heur_dissector_list(const char *name)
1419 g_assert(heur_dissector_lists != NULL);
1420 return g_hash_table_lookup(heur_dissector_lists, name);
1424 heur_dissector_add(const char *name, heur_dissector_t dissector)
1426 heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
1429 g_assert(sub_dissectors != NULL);
1431 /* do the table insertion */
1432 *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)dissector);
1436 dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
1437 const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1439 heur_dissector_t subdissector;
1442 for (entry = sub_dissectors; entry != NULL; entry = g_slist_next(entry)) {
1443 subdissector = (heur_dissector_t)entry->data;
1444 if ((subdissector)(pd, offset, fd, tree))
1451 register_heur_dissector_list(const char *name, heur_dissector_list_t *sub_dissectors)
1453 /* Create our hash-of-hashes if it doesn't already exist */
1454 if (heur_dissector_lists == NULL) {
1455 heur_dissector_lists = g_hash_table_new(g_str_hash, g_str_equal);
1456 g_assert(heur_dissector_lists != NULL);
1459 /* Make sure the registration is unique */
1460 g_assert(g_hash_table_lookup(heur_dissector_lists, name) == NULL);
1462 *sub_dissectors = NULL; /* initially empty */
1463 g_hash_table_insert(heur_dissector_lists, (gpointer)name,
1464 (gpointer) sub_dissectors);