2 * Routines for packet disassembly
4 * $Id: packet.c,v 1.79 2000/05/05 09:32:07 guy 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"
95 extern capture_file cf;
97 static int proto_frame = -1;
98 static int hf_frame_arrival_time = -1;
99 static int hf_frame_time_delta = -1;
100 static int hf_frame_number = -1;
101 static int hf_frame_packet_len = -1;
102 static int hf_frame_capture_len = -1;
104 static gint ett_frame = -1;
106 GMemChunk *frame_proto_data_area = NULL;
109 * Free up any space allocated for frame proto data areas and then
110 * allocate a new area.
112 * We can free the area, as the structures it contains are pointed to by
113 * frames, that will be freed as well.
116 packet_init_protocol(void)
119 if (frame_proto_data_area)
120 g_mem_chunk_destroy(frame_proto_data_area);
122 frame_proto_data_area = g_mem_chunk_new("frame_proto_data_area",
123 sizeof(frame_proto_data),
124 20 * sizeof(frame_proto_data), /* FIXME*/
129 /* Wrapper for the most common case of asking
130 * for a string using a colon as the hex-digit separator.
133 ether_to_str(const guint8 *ad)
135 return ether_to_str_punct(ad, ':');
138 /* Places char punct in the string as the hex-digit separator.
139 * If punct is '\0', no punctuation is applied (and thus
140 * the resulting string is 5 bytes shorter)
143 ether_to_str_punct(const guint8 *ad, char punct) {
144 static gchar str[3][18];
149 static const gchar hex_digits[16] = "0123456789abcdef";
151 if (cur == &str[0][0]) {
153 } else if (cur == &str[1][0]) {
163 *--p = hex_digits[octet&0xF];
165 *--p = hex_digits[octet&0xF];
176 ip_to_str(const guint8 *ad) {
177 static gchar str[3][16];
184 if (cur == &str[0][0]) {
186 } else if (cur == &str[1][0]) {
196 *--p = (octet%10) + '0';
200 if (digit != 0 || octet != 0)
213 ip6_to_str(struct e_in6_addr *ad) {
214 #ifndef INET6_ADDRSTRLEN
215 #define INET6_ADDRSTRLEN 46
217 static gchar buf[INET6_ADDRSTRLEN];
219 inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
224 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
225 #define COMMA(do_it) ((do_it) ? ", " : "")
228 time_secs_to_str(guint32 time)
230 static gchar str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
231 static gchar *cur, *p;
232 int hours, mins, secs;
235 if (cur == &str[0][0]) {
237 } else if (cur == &str[1][0]) {
244 sprintf(cur, "0 time");
257 sprintf(p, "%u day%s", time, PLURALIZE(time));
263 sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
269 sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
275 sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
279 /* Max string length for displaying byte string. */
280 #define MAX_BYTE_STR_LEN 32
282 /* Turn an array of bytes into a string showing the bytes in hex. */
283 #define N_BYTES_TO_STR_STRINGS 6
285 bytes_to_str(const guint8 *bd, int bd_len) {
286 static gchar str[N_BYTES_TO_STR_STRINGS][MAX_BYTE_STR_LEN+3+1];
291 static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
292 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
295 if (cur_idx >= N_BYTES_TO_STR_STRINGS)
297 cur = &str[cur_idx][0];
299 len = MAX_BYTE_STR_LEN;
300 while (bd_len > 0 && len > 0) {
301 *p++ = hex[(*bd) >> 4];
302 *p++ = hex[(*bd) & 0xF];
308 /* Note that we're not showing the full string. */
317 static const char *mon_names[12] = {
333 abs_time_to_str(struct timeval *abs_time)
337 static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
339 if (cur == &str[0][0]) {
341 } else if (cur == &str[1][0]) {
347 tmp = localtime(&abs_time->tv_sec);
348 sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
349 mon_names[tmp->tm_mon],
355 (long)abs_time->tv_usec/100);
361 rel_time_to_str(struct timeval *rel_time)
364 static char str[3][10+1+6+1];
366 if (cur == &str[0][0]) {
368 } else if (cur == &str[1][0]) {
374 sprintf(cur, "%ld.%06ld", (long)rel_time->tv_sec,
375 (long)rel_time->tv_usec);
381 * Given a pointer into a data buffer, and to the end of the buffer,
382 * find the end of the (putative) line at that position in the data
384 * Return a pointer to the EOL character(s) in "*eol".
387 find_line_end(const u_char *data, const u_char *dataend, const u_char **eol)
389 const u_char *lineend;
391 lineend = memchr(data, '\n', dataend - data);
392 if (lineend == NULL) {
394 * No LF - line is probably continued in next TCP segment.
400 * Is the LF at the beginning of the line?
402 if (lineend > data) {
404 * No - is it preceded by a carriage return?
405 * (Perhaps it's supposed to be, but that's not guaranteed....)
407 if (*(lineend - 1) == '\r') {
409 * Yes. The EOL starts with the CR.
414 * No. The EOL starts with the LF.
419 * I seem to remember that we once saw lines ending with LF-CR
420 * in an HTTP request or response, so check if it's *followed*
421 * by a carriage return.
423 if (lineend < (dataend - 1) && *(lineend + 1) == '\r') {
425 * It's <non-LF><LF><CR>; say it ends with the CR.
433 * Point to the character after the last character.
440 #define MAX_COLUMNS_LINE_DETAIL 62
443 * Get the length of the next token in a line, and the beginning of the
444 * next token after that (if any).
445 * Return 0 if there is no next token.
448 get_token_len(const u_char *linep, const u_char *lineend,
449 const u_char **next_token)
451 const u_char *tokenp;
457 * Search for a blank, a CR or an LF, or the end of the buffer.
459 while (linep < lineend && *linep != ' ' && *linep != '\r' && *linep != '\n')
461 token_len = linep - tokenp;
464 * Skip trailing blanks.
466 while (linep < lineend && *linep == ' ')
475 * Given a string, generate a string from it that shows non-printable
476 * characters as C-style escapes, and return a pointer to it.
479 format_text(const u_char *string, int len)
481 static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
484 const u_char *stringend = string + len;
489 fmtbufp = &fmtbuf[0];
490 while (string < stringend) {
491 if (column >= MAX_COLUMNS_LINE_DETAIL) {
493 * Put "..." and quit.
495 strcpy(fmtbufp, " ...");
550 *fmtbufp++ = i + '0';
553 *fmtbufp++ = i + '0';
556 *fmtbufp++ = i + '0';
567 /* Tries to match val against each element in the value_string array vs.
568 Returns the associated string ptr on a match.
569 Formats val with fmt, and returns the resulting string, on failure. */
571 val_to_str(guint32 val, const value_string *vs, const char *fmt) {
573 static gchar str[3][64];
576 ret = match_strval(val, vs);
579 if (cur == &str[0][0]) {
581 } else if (cur == &str[1][0]) {
586 snprintf(cur, 64, fmt, val);
590 /* Tries to match val against each element in the value_string array vs.
591 Returns the associated string ptr on a match, or NULL on failure. */
593 match_strval(guint32 val, const value_string *vs) {
596 while (vs[i].strptr) {
597 if (vs[i].value == val)
598 return(vs[i].strptr);
605 /* Generate, into "buf", a string showing the bits of a bitfield.
606 Return a pointer to the character after that string. */
608 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
616 bit = 1 << (width - 1);
619 /* This bit is part of the field. Show its value. */
625 /* This bit is not part of the field. */
640 /* Generate a string describing a Boolean bitfield (a one-bit field that
641 says something is either true of false). */
643 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
644 const char *truedesc, const char *falsedesc)
646 static char buf[1025];
649 p = decode_bitfield_value(buf, val, mask, width);
653 strcpy(p, falsedesc);
657 /* Generate a string describing an enumerated bitfield (an N-bit field
658 with various specific values having particular names). */
660 decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
661 const value_string *tab, const char *fmt)
663 static char buf[1025];
666 p = decode_bitfield_value(buf, val, mask, width);
667 sprintf(p, fmt, val_to_str(val & mask, tab, "Unknown"));
671 /* Generate a string describing a numeric bitfield (an N-bit field whose
672 value is just a number). */
674 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
677 static char buf[1025];
681 /* Compute the number of bits we have to shift the bitfield right
682 to extract its value. */
683 while ((mask & (1<<shift)) == 0)
686 p = decode_bitfield_value(buf, val, mask, width);
687 sprintf(p, fmt, (val & mask) >> shift);
691 /* Checks to see if a particular packet information element is needed for
694 check_col(frame_data *fd, gint el) {
698 for (i = 0; i < fd->cinfo->num_cols; i++) {
699 if (fd->cinfo->fmt_matx[i][el])
706 /* Adds a vararg list to a packet info string. */
708 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
713 va_start(ap, format);
714 for (i = 0; i < fd->cinfo->num_cols; i++) {
715 if (fd->cinfo->fmt_matx[i][el]) {
717 max_len = COL_MAX_INFO_LEN;
719 max_len = COL_MAX_LEN;
720 vsnprintf(fd->cinfo->col_data[i], max_len, format, ap);
726 col_add_str(frame_data *fd, gint el, const gchar* str) {
730 for (i = 0; i < fd->cinfo->num_cols; i++) {
731 if (fd->cinfo->fmt_matx[i][el]) {
733 max_len = COL_MAX_INFO_LEN;
735 max_len = COL_MAX_LEN;
736 strncpy(fd->cinfo->col_data[i], str, max_len);
737 fd->cinfo->col_data[i][max_len - 1] = 0;
742 /* Appends a vararg list to a packet info string. */
744 col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
749 va_start(ap, format);
750 for (i = 0; i < fd->cinfo->num_cols; i++) {
751 if (fd->cinfo->fmt_matx[i][el]) {
752 len = strlen(fd->cinfo->col_data[i]);
754 max_len = COL_MAX_INFO_LEN;
756 max_len = COL_MAX_LEN;
757 vsnprintf(&fd->cinfo->col_data[i][len], max_len - len, format, ap);
763 col_append_str(frame_data *fd, gint el, gchar* str) {
767 for (i = 0; i < fd->cinfo->num_cols; i++) {
768 if (fd->cinfo->fmt_matx[i][el]) {
769 len = strlen(fd->cinfo->col_data[i]);
771 max_len = COL_MAX_LEN;
773 max_len = COL_MAX_INFO_LEN;
774 strncat(fd->cinfo->col_data[i], str, max_len - len);
775 fd->cinfo->col_data[i][max_len - 1] = 0;
780 /* To do: Add check_col checks to the col_add* routines */
783 col_set_abs_time(frame_data *fd, int col)
789 tmp = localtime(&then);
790 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
794 (long)fd->abs_usecs/100);
798 col_set_rel_time(frame_data *fd, int col)
800 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->rel_secs,
805 col_set_delta_time(frame_data *fd, int col)
807 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->del_secs,
811 /* Add "command-line-specified" time.
812 XXX - this is called from "file.c" when the user changes the time
813 format they want for "command-line-specified" time; it's a bit ugly
814 that we have to export it, but if we go to a CList-like widget that
815 invokes callbacks to get the text for the columns rather than
816 requiring us to stuff the text into the widget from outside, we
817 might be able to clean this up. */
819 col_set_cls_time(frame_data *fd, int col)
821 switch (timestamp_type) {
823 col_set_abs_time(fd, col);
827 col_set_rel_time(fd, col);
831 col_set_delta_time(fd, col);
837 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
840 struct e_in6_addr ipv6_addr;
841 struct atalk_ddp_addr ddp_addr;
842 struct sna_fid_type_4_addr sna_fid_type_4_addr;
844 switch (addr->type) {
848 strncpy(fd->cinfo->col_data[col], get_ether_name(addr->data), COL_MAX_LEN);
850 strncpy(fd->cinfo->col_data[col], ether_to_str(addr->data), COL_MAX_LEN);
854 memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
856 strncpy(fd->cinfo->col_data[col], get_hostname(ipv4_addr), COL_MAX_LEN);
858 strncpy(fd->cinfo->col_data[col], ip_to_str(addr->data), COL_MAX_LEN);
862 memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
864 strncpy(fd->cinfo->col_data[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
866 strncpy(fd->cinfo->col_data[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
870 strncpy(fd->cinfo->col_data[col],
871 ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
878 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X", addr->data[0]);
882 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X",
883 pntohs(&addr->data[0]));
886 case SNA_FID_TYPE_4_ADDR_LEN:
887 memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
888 strncpy(fd->cinfo->col_data[col],
889 sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
895 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
896 strncpy(fd->cinfo->col_data[col], atalk_addr_to_str(&ddp_addr),
901 strncpy(fd->cinfo->col_data[col], vines_addr_to_str(&addr->data[0]),
908 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
912 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
919 strncpy(fd->cinfo->col_data[col], get_tcp_port(port), COL_MAX_LEN);
921 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
926 strncpy(fd->cinfo->col_data[col], get_udp_port(port), COL_MAX_LEN);
928 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
934 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
938 fill_in_columns(frame_data *fd)
942 for (i = 0; i < fd->cinfo->num_cols; i++) {
943 switch (fd->cinfo->col_fmt[i]) {
946 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%u", fd->num);
950 col_set_cls_time(fd, i);
954 col_set_abs_time(fd, i);
958 col_set_rel_time(fd, i);
962 col_set_delta_time(fd, i);
966 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
967 col_set_addr(fd, i, &pi.src, TRUE);
971 col_set_addr(fd, i, &pi.src, FALSE);
976 col_set_addr(fd, i, &pi.dl_src, TRUE);
979 case COL_UNRES_DL_SRC:
980 col_set_addr(fd, i, &pi.dl_src, FALSE);
983 case COL_DEF_NET_SRC:
984 case COL_RES_NET_SRC:
985 col_set_addr(fd, i, &pi.net_src, TRUE);
988 case COL_UNRES_NET_SRC:
989 col_set_addr(fd, i, &pi.net_src, FALSE);
993 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
994 col_set_addr(fd, i, &pi.dst, TRUE);
998 col_set_addr(fd, i, &pi.dst, FALSE);
1001 case COL_DEF_DL_DST:
1002 case COL_RES_DL_DST:
1003 col_set_addr(fd, i, &pi.dl_dst, TRUE);
1006 case COL_UNRES_DL_DST:
1007 col_set_addr(fd, i, &pi.dl_dst, FALSE);
1010 case COL_DEF_NET_DST:
1011 case COL_RES_NET_DST:
1012 col_set_addr(fd, i, &pi.net_dst, TRUE);
1015 case COL_UNRES_NET_DST:
1016 col_set_addr(fd, i, &pi.net_dst, FALSE);
1019 case COL_DEF_SRC_PORT:
1020 case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
1021 col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
1024 case COL_UNRES_SRC_PORT:
1025 col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
1028 case COL_DEF_DST_PORT:
1029 case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
1030 col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
1033 case COL_UNRES_DST_PORT:
1034 col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
1037 case COL_PROTOCOL: /* currently done by dissectors */
1038 case COL_INFO: /* currently done by dissectors */
1041 case COL_PACKET_LENGTH:
1042 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%d", fd->pkt_len);
1045 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
1051 void blank_packetinfo(void)
1053 pi.dl_src.type = AT_NONE;
1054 pi.dl_dst.type = AT_NONE;
1055 pi.net_src.type = AT_NONE;
1056 pi.net_dst.type = AT_NONE;
1057 pi.src.type = AT_NONE;
1058 pi.dst.type = AT_NONE;
1065 /* Do all one-time initialization. */
1077 dissect_cleanup(void)
1083 /* Allow protocols to register "init" routines, which are called before
1084 we make a pass through a capture file and dissect all its packets
1085 (e.g., when we read in a new capture file, or run a "filter packets"
1086 or "colorize packets" pass over the current capture file). */
1087 static GSList *init_routines;
1090 register_init_routine(void (*func)(void))
1092 init_routines = g_slist_append(init_routines, func);
1095 /* Call all the registered "init" routines. */
1097 call_init_routine(gpointer routine, gpointer dummy)
1099 void (*func)(void) = routine;
1105 init_all_protocols(void)
1107 g_slist_foreach(init_routines, &call_init_routine, NULL);
1110 /* this routine checks the frame type from the cf structure */
1112 dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
1114 proto_tree *fh_tree;
1118 /* Put in frame header information. */
1120 ti = proto_tree_add_protocol_format(tree, proto_frame, 0, fd->cap_len,
1121 "Frame %u (%u on wire, %u captured)", fd->num,
1122 fd->pkt_len, fd->cap_len);
1124 fh_tree = proto_item_add_subtree(ti, ett_frame);
1126 tv.tv_sec = fd->abs_secs;
1127 tv.tv_usec = fd->abs_usecs;
1129 proto_tree_add_item(fh_tree, hf_frame_arrival_time,
1132 tv.tv_sec = fd->del_secs;
1133 tv.tv_usec = fd->del_usecs;
1135 proto_tree_add_item(fh_tree, hf_frame_time_delta,
1138 proto_tree_add_item(fh_tree, hf_frame_number,
1141 proto_tree_add_uint_format(fh_tree, hf_frame_packet_len,
1142 0, 0, fd->pkt_len, "Packet Length: %d byte%s", fd->pkt_len,
1143 plurality(fd->pkt_len, "", "s"));
1145 proto_tree_add_uint_format(fh_tree, hf_frame_capture_len,
1146 0, 0, fd->cap_len, "Capture Length: %d byte%s", fd->cap_len,
1147 plurality(fd->cap_len, "", "s"));
1152 /* Set the initial payload to the packet length, and the initial
1153 captured payload to the capture length (other protocols may
1154 reduce them if their headers say they're less). */
1155 pi.len = fd->pkt_len;
1156 pi.captured_len = fd->cap_len;
1158 switch (fd->lnk_t) {
1159 case WTAP_ENCAP_ETHERNET :
1160 dissect_eth(pd, 0, fd, tree);
1162 case WTAP_ENCAP_FDDI :
1163 dissect_fddi(pd, fd, tree, FALSE);
1165 case WTAP_ENCAP_FDDI_BITSWAPPED :
1166 dissect_fddi(pd, fd, tree, TRUE);
1168 case WTAP_ENCAP_TR :
1169 dissect_tr(pd, 0, fd, tree);
1171 case WTAP_ENCAP_NULL :
1172 dissect_null(pd, fd, tree);
1174 case WTAP_ENCAP_PPP :
1175 dissect_ppp(pd, 0, fd, tree);
1177 case WTAP_ENCAP_LAPB :
1178 dissect_lapb(pd, fd, tree);
1180 case WTAP_ENCAP_RAW_IP :
1181 dissect_raw(pd, fd, tree);
1183 case WTAP_ENCAP_LINUX_ATM_CLIP :
1184 dissect_clip(pd, fd, tree);
1186 case WTAP_ENCAP_ATM_SNIFFER :
1187 dissect_atm(pd, fd, tree);
1189 case WTAP_ENCAP_ASCEND :
1190 dissect_ascend(pd, fd, tree);
1192 case WTAP_ENCAP_LAPD :
1193 dissect_lapd(pd, fd, tree);
1195 case WTAP_ENCAP_V120 :
1196 dissect_v120(pd, fd, tree);
1200 fd->flags.visited = 1;
1203 gint p_compare(gconstpointer a, gconstpointer b)
1206 if (((frame_proto_data *)a) -> proto > ((frame_proto_data *)b) -> proto)
1208 else if (((frame_proto_data *)a) -> proto == ((frame_proto_data *)b) -> proto)
1216 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
1218 frame_proto_data *p1 = g_mem_chunk_alloc(frame_proto_data_area);
1220 g_assert(p1 != NULL);
1222 p1 -> proto = proto;
1223 p1 -> proto_data = proto_data;
1225 /* Add it to the GSLIST */
1227 fd -> pfd = g_slist_insert_sorted(fd -> pfd,
1234 p_get_proto_data(frame_data *fd, int proto)
1236 frame_proto_data temp;
1240 temp.proto_data = NULL;
1242 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
1244 if (item) return (void *)item->data;
1251 p_rem_proto_data(frame_data *fd, int proto)
1258 proto_register_frame(void)
1260 static hf_register_info hf[] = {
1261 { &hf_frame_arrival_time,
1262 { "Arrival Time", "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1265 { &hf_frame_time_delta,
1266 { "Time delta from previous packet", "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
1271 { "Frame Number", "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
1274 { &hf_frame_packet_len,
1275 { "Total Frame Length", "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
1278 { &hf_frame_capture_len,
1279 { "Capture Frame Length", "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
1282 static gint *ett[] = {
1286 proto_frame = proto_register_protocol("Frame", "frame");
1287 proto_register_field_array(proto_frame, hf, array_length(hf));
1288 proto_register_subtree_array(ett, array_length(ett));
1290 register_init_routine(&packet_init_protocol);
1294 /*********************** code added for sub-dissector lookup *********************/
1296 static GHashTable *dissector_tables = NULL;
1298 /* Finds a dissector table by field name. */
1299 static dissector_table_t
1300 find_dissector_table(const char *name)
1302 g_assert(dissector_tables);
1303 return g_hash_table_lookup( dissector_tables, name );
1306 /* lookup a dissector based upon pattern. */
1308 dissector_lookup( dissector_table_t table, guint32 pattern)
1310 return g_hash_table_lookup( table, GUINT_TO_POINTER( pattern));
1314 /* add an entry, lookup the dissector table for the specified field name, */
1315 /* if a valid table found, add the subdissector */
1317 dissector_add(const char *name, guint32 pattern, dissector_t dissector)
1319 dissector_table_t sub_dissectors = find_dissector_table( name);
1322 g_assert( sub_dissectors);
1324 /* do the table insertion */
1325 g_hash_table_insert( sub_dissectors, GUINT_TO_POINTER( pattern),
1326 (gpointer)dissector);
1329 /* delete the entry for this dissector at this pattern */
1331 /* NOTE: this doesn't use the dissector call variable. It is included to */
1332 /* be consistant with the dissector_add and more importantly to be used */
1333 /* if the technique of adding a temporary dissector is implemented. */
1334 /* If temporary dissectors are deleted, then the original dissector must */
1337 dissector_delete(const char *name, guint32 pattern, dissector_t dissector)
1339 dissector_table_t sub_dissectors = find_dissector_table( name);
1342 g_assert( sub_dissectors);
1344 /* remove the hash table entry */
1345 g_hash_table_remove( sub_dissectors, GUINT_TO_POINTER( pattern));
1348 /* Look for a given port in a given dissector table and, if found, call
1349 the dissector with the arguments supplied, and return TRUE, otherwise
1352 dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
1353 const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1355 dissector_t subdissector;
1357 subdissector = dissector_lookup(sub_dissectors, port);
1358 if (subdissector != NULL) {
1359 pi.match_port = port;
1360 (subdissector)(pd, offset, fd, tree);
1367 register_dissector_table(const char *name)
1369 dissector_table_t sub_dissectors;
1371 /* Create our hash-of-hashes if it doesn't already exist */
1372 if (!dissector_tables) {
1373 dissector_tables = g_hash_table_new( g_str_hash, g_str_equal );
1374 g_assert(dissector_tables);
1377 /* Make sure the registration is unique */
1378 g_assert(!g_hash_table_lookup( dissector_tables, name ));
1380 /* Create and register the dissector table for this name; returns */
1381 /* a pointer to the dissector table. */
1382 sub_dissectors = g_hash_table_new( g_direct_hash, g_direct_equal );
1383 g_hash_table_insert( dissector_tables, (gpointer)name, (gpointer) sub_dissectors );
1384 return sub_dissectors;
1387 static GHashTable *heur_dissector_lists = NULL;
1389 /* Finds a heuristic dissector table by field name. */
1390 static heur_dissector_list_t *
1391 find_heur_dissector_list(const char *name)
1393 g_assert(heur_dissector_lists != NULL);
1394 return g_hash_table_lookup(heur_dissector_lists, name);
1398 heur_dissector_add(const char *name, heur_dissector_t dissector)
1400 heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
1403 g_assert(sub_dissectors != NULL);
1405 /* do the table insertion */
1406 *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)dissector);
1410 dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
1411 const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1413 heur_dissector_t subdissector;
1416 for (entry = sub_dissectors; entry != NULL; entry = g_slist_next(entry)) {
1417 subdissector = (heur_dissector_t)entry->data;
1418 if ((subdissector)(pd, offset, fd, tree))
1425 register_heur_dissector_list(const char *name, heur_dissector_list_t *sub_dissectors)
1427 /* Create our hash-of-hashes if it doesn't already exist */
1428 if (heur_dissector_lists == NULL) {
1429 heur_dissector_lists = g_hash_table_new(g_str_hash, g_str_equal);
1430 g_assert(heur_dissector_lists != NULL);
1433 /* Make sure the registration is unique */
1434 g_assert(g_hash_table_lookup(heur_dissector_lists, name) == NULL);
1436 *sub_dissectors = NULL; /* initially empty */
1437 g_hash_table_insert(heur_dissector_lists, (gpointer)name,
1438 (gpointer) sub_dissectors);