/* packet.c
* Routines for packet disassembly
*
- * $Id: packet.c,v 1.30 1999/07/13 02:52:57 gram Exp $
+ * $Id: packet.c,v 1.52 1999/10/29 02:25:54 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
# include <netinet/in.h>
#endif
+#include <arpa/inet.h>
+
+#ifdef NEED_INET_V6DEFS_H
+# include "inet_v6defs.h"
+#endif
+
#include "packet.h"
+#include "print.h"
#include "file.h"
-#include "timestamp.h"
extern capture_file cf;
+gboolean tree_is_expanded[NUM_TREE_TYPES];
+
int proto_frame = -1;
int hf_frame_arrival_time = -1;
+int hf_frame_time_delta = -1;
+int hf_frame_number = -1;
int hf_frame_packet_len = -1;
int hf_frame_capture_len = -1;
ether_to_str(const guint8 *ad) {
static gchar str[3][18];
static gchar *cur;
+ gchar *p;
+ int i;
+ guint32 octet;
+ static const gchar hex_digits[16] = "0123456789abcdef";
if (cur == &str[0][0]) {
cur = &str[1][0];
} else {
cur = &str[0][0];
}
- sprintf(cur, "%02x:%02x:%02x:%02x:%02x:%02x", ad[0], ad[1], ad[2],
- ad[3], ad[4], ad[5]);
- return cur;
+ p = &cur[18];
+ *--p = '\0';
+ i = 5;
+ for (;;) {
+ octet = ad[i];
+ *--p = hex_digits[octet&0xF];
+ octet >>= 4;
+ *--p = hex_digits[octet&0xF];
+ if (i == 0)
+ break;
+ *--p = ':';
+ i--;
+ }
+ return p;
}
gchar *
ip_to_str(const guint8 *ad) {
static gchar str[3][16];
static gchar *cur;
+ gchar *p;
+ int i;
+ guint32 octet;
+ guint32 digit;
if (cur == &str[0][0]) {
cur = &str[1][0];
} else {
cur = &str[0][0];
}
- sprintf(cur, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
- return cur;
+ p = &cur[16];
+ *--p = '\0';
+ i = 3;
+ for (;;) {
+ octet = ad[i];
+ *--p = (octet%10) + '0';
+ octet /= 10;
+ digit = octet%10;
+ octet /= 10;
+ if (digit != 0 || octet != 0)
+ *--p = digit + '0';
+ if (octet != 0)
+ *--p = octet + '0';
+ if (i == 0)
+ break;
+ *--p = '.';
+ i--;
+ }
+ return p;
}
+gchar *
+ip6_to_str(struct e_in6_addr *ad) {
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+ static gchar buf[INET6_ADDRSTRLEN];
+
+ inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
+ return buf;
+}
+
+
#define PLURALIZE(n) (((n) > 1) ? "s" : "")
#define COMMA(do_it) ((do_it) ? ", " : "")
}
/* Max string length for displaying byte string. */
-#define MAX_BYTE_STR_LEN 16
+#define MAX_BYTE_STR_LEN 20
/* Turn an array of bytes into a string showing the bytes in hex. */
gchar *
return cur;
}
+gchar *
+rel_time_to_str(struct timeval *rel_time)
+{
+ static gchar *cur;
+ static char str[3][10+1+6+1];
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+ sprintf(cur, "%ld.%06ld", (long)rel_time->tv_sec,
+ (long)rel_time->tv_usec);
+
+ return cur;
+}
/*
* Given a pointer into a data buffer, and to the end of the buffer,
/* Generate, into "buf", a string showing the bits of a bitfield.
Return a pointer to the character after that string. */
-static char *
+char *
decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
{
int i;
{
static char buf[1025];
char *p;
+ int shift = 0;
+
+ /* Compute the number of bits we have to shift the bitfield right
+ to extract its value. */
+ while ((mask & (1<<shift)) == 0)
+ shift++;
p = decode_bitfield_value(buf, val, mask, width);
- sprintf(p, fmt, val & mask);
+ sprintf(p, fmt, (val & mask) >> shift);
return buf;
}
return FALSE;
}
-/* To do: Add check_col checks to the col_add* routines */
-
-static void
-col_add_abs_time(frame_data *fd, gint el)
-{
- struct tm *tmp;
- time_t then;
-
- then = fd->abs_secs;
- tmp = localtime(&then);
- col_add_fstr(fd, el, "%02d:%02d:%02d.%04ld",
- tmp->tm_hour,
- tmp->tm_min,
- tmp->tm_sec,
- (long)fd->abs_usecs/100);
-}
-
-static void
-col_add_rel_time(frame_data *fd, gint el)
-{
- col_add_fstr(fd, el, "%d.%06d", fd->rel_secs, fd->rel_usecs);
-}
-
-static void
-col_add_delta_time(frame_data *fd, gint el)
-{
- col_add_fstr(fd, el, "%d.%06d", fd->del_secs, fd->del_usecs);
+/* Adds a vararg list to a packet info string. */
+void
+col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
+ va_list ap;
+ int i;
+ size_t max_len;
+
+ va_start(ap, format);
+ for (i = 0; i < fd->cinfo->num_cols; i++) {
+ if (fd->cinfo->fmt_matx[i][el]) {
+ if (el == COL_INFO)
+ max_len = COL_MAX_INFO_LEN;
+ else
+ max_len = COL_MAX_LEN;
+ vsnprintf(fd->cinfo->col_data[i], max_len, format, ap);
+ }
+ }
}
-/* Add "command-line-specified" time. */
void
-col_add_cls_time(frame_data *fd)
-{
- switch (timestamp_type) {
- case ABSOLUTE:
- col_add_abs_time(fd, COL_CLS_TIME);
- break;
-
- case RELATIVE:
- col_add_rel_time(fd, COL_CLS_TIME);
- break;
+col_add_str(frame_data *fd, gint el, const gchar* str) {
+ int i;
+ size_t max_len;
- case DELTA:
- col_add_delta_time(fd, COL_CLS_TIME);
- break;
+ for (i = 0; i < fd->cinfo->num_cols; i++) {
+ if (fd->cinfo->fmt_matx[i][el]) {
+ if (el == COL_INFO)
+ max_len = COL_MAX_INFO_LEN;
+ else
+ max_len = COL_MAX_LEN;
+ strncpy(fd->cinfo->col_data[i], str, max_len);
+ fd->cinfo->col_data[i][max_len - 1] = 0;
+ }
}
}
-/* Adds a vararg list to a packet info string. */
+/* Appends a vararg list to a packet info string. */
void
-col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
- va_list ap;
- int i;
+col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
+ va_list ap;
+ int i;
+ size_t len, max_len;
va_start(ap, format);
for (i = 0; i < fd->cinfo->num_cols; i++) {
- if (fd->cinfo->fmt_matx[i][el])
- vsnprintf(fd->cinfo->col_data[i], COL_MAX_LEN, format, ap);
+ if (fd->cinfo->fmt_matx[i][el]) {
+ len = strlen(fd->cinfo->col_data[i]);
+ if (el == COL_INFO)
+ max_len = COL_MAX_INFO_LEN;
+ else
+ max_len = COL_MAX_LEN;
+ vsnprintf(&fd->cinfo->col_data[i][len], max_len - len, format, ap);
+ }
}
}
void
-col_add_str(frame_data *fd, gint el, const gchar* str) {
- int i;
-
+col_append_str(frame_data *fd, gint el, gchar* str) {
+ int i;
+ size_t len, max_len;
+
for (i = 0; i < fd->cinfo->num_cols; i++) {
if (fd->cinfo->fmt_matx[i][el]) {
- strncpy(fd->cinfo->col_data[i], str, COL_MAX_LEN);
- fd->cinfo->col_data[i][COL_MAX_LEN - 1] = 0;
+ len = strlen(fd->cinfo->col_data[i]);
+ if (el == COL_INFO)
+ max_len = COL_MAX_LEN;
+ else
+ max_len = COL_MAX_INFO_LEN;
+ strncat(fd->cinfo->col_data[i], str, max_len - len);
+ fd->cinfo->col_data[i][max_len - 1] = 0;
}
}
}
+
+void blank_packetinfo(void)
+{
+ pi.dl_src.type = AT_NONE;
+ pi.dl_dst.type = AT_NONE;
+ pi.net_src.type = AT_NONE;
+ pi.net_dst.type = AT_NONE;
+ pi.src.type = AT_NONE;
+ pi.dst.type = AT_NONE;
+ pi.ipproto = 0;
+ pi.ptype = PT_NONE;
+ pi.srcport = 0;
+ pi.destport = 0;
+}
/* this routine checks the frame type from the cf structure */
void
struct timeval tv;
/* Put in frame header information. */
- if (check_col(fd, COL_CLS_TIME))
- col_add_cls_time(fd);
- if (check_col(fd, COL_ABS_TIME))
- col_add_abs_time(fd, COL_ABS_TIME);
- if (check_col(fd, COL_REL_TIME))
- col_add_rel_time(fd, COL_REL_TIME);
- if (check_col(fd, COL_DELTA_TIME))
- col_add_delta_time(fd, COL_DELTA_TIME);
-
if (tree) {
ti = proto_tree_add_item_format(tree, proto_frame, 0, fd->cap_len,
NULL, "Frame (%d on wire, %d captured)", fd->pkt_len, fd->cap_len);
proto_tree_add_item(fh_tree, hf_frame_arrival_time,
0, 0, &tv);
+ tv.tv_sec = fd->del_secs;
+ tv.tv_usec = fd->del_usecs;
+
+ proto_tree_add_item(fh_tree, hf_frame_time_delta,
+ 0, 0, &tv);
+
+ proto_tree_add_item(fh_tree, hf_frame_number,
+ 0, 0, fd->num);
+
proto_tree_add_item_format(fh_tree, hf_frame_packet_len,
0, 0, fd->pkt_len, "Packet Length: %d byte%s", fd->pkt_len,
plurality(fd->pkt_len, "", "s"));
plurality(fd->cap_len, "", "s"));
}
+ blank_packetinfo();
+
+ /* 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). */
+ pi.len = fd->pkt_len;
+ pi.captured_len = fd->cap_len;
+
switch (fd->lnk_t) {
case WTAP_ENCAP_ETHERNET :
- dissect_eth(pd, fd, tree);
+ dissect_eth(pd, 0, fd, tree);
break;
case WTAP_ENCAP_FDDI :
- dissect_fddi(pd, fd, tree);
+ 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, fd, tree);
+ dissect_tr(pd, 0, fd, tree);
break;
- case WTAP_ENCAP_NONE :
+ 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;
}
}
void
proto_register_frame(void)
{
- proto_frame = proto_register_protocol (
- /* name */ "Frame",
- /* abbrev */ "frame");
-
- hf_frame_arrival_time = proto_register_field (
- /* name */ "Arrival Time",
- /* abbrev */ "frame.time",
- /* ftype */ FT_ABSOLUTE_TIME,
- /* parent */ proto_frame,
- /* vals[] */ NULL );
-
- hf_frame_packet_len = proto_register_field(
- /* name */ "Total Frame Length",
- /* abbrev */ "frame.frame_len",
- /* ftype */ FT_UINT32,
- /* parent */ proto_frame,
- /* vals[] */ NULL );
-
- hf_frame_capture_len = proto_register_field(
- /* name */ "Capture Frame Length",
- /* abbrev */ "frame.cap_len",
- /* ftype */ FT_UINT32,
- /* parent */ proto_frame,
- /* vals[] */ NULL );
+ 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,
+ "" }},
+ };
+
+ proto_frame = proto_register_protocol("Frame", "frame");
+ proto_register_field_array(proto_frame, hf, array_length(hf));
}