Add a routine to dissect IP or TCP options (and, from a look at RFC

1883, it should, perhaps with some additions, be able to handle IPv6
options as well).

Make the IPv4 and TCP dissectors use it.

Fix a typo in the IP dissector ("Unknon" for "Unknown").

Show the IP and TCP header lengths as byte counts rather than
4-byte-word counts.

Show the protocol field value of an IP header as a name if it's a
protocol we know about.

List the acknowledgment and urgent pointer values in a TCP header only
if the corresponding flag is set.

Make the ETT_ values members of an enum, so that the compiler
automatically assigns them sequential integer values (at least if said
compiler conforms to the ANSI C standard).

svn path=/trunk/; revision=45
This commit is contained in:
Guy Harris 1998-10-13 05:40:04 +00:00
parent d6907f93bc
commit 7f2da15d6b
3 changed files with 769 additions and 93 deletions

View File

@ -1,7 +1,7 @@
/* packet-ip.c
* Routines for IP and miscellaneous IP protocol packet disassembly
*
* $Id: packet-ip.c,v 1.6 1998/10/10 18:23:42 gerald Exp $
* $Id: packet-ip.c,v 1.7 1998/10/13 05:40:03 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -47,11 +47,364 @@
extern packet_info pi;
static void
dissect_ipopt_security(GtkWidget *opt_tree, const char *name,
const u_char *opd, int offset, guint optlen)
{
GtkWidget *field_tree = NULL, *tf;
guint val;
gchar *secl_str;
static value_string secl_vals[] = {
{IPSEC_UNCLASSIFIED, "Unclassified"},
{IPSEC_CONFIDENTIAL, "Confidential"},
{IPSEC_EFTO, "EFTO" },
{IPSEC_MMMM, "MMMM" },
{IPSEC_RESTRICTED, "Restricted" },
{IPSEC_SECRET, "Secret" },
{IPSEC_TOPSECRET, "Top secret" },
{IPSEC_RESERVED1, "Reserved" },
{IPSEC_RESERVED2, "Reserved" },
{IPSEC_RESERVED3, "Reserved" },
{IPSEC_RESERVED4, "Reserved" },
{IPSEC_RESERVED5, "Reserved" },
{IPSEC_RESERVED6, "Reserved" },
{IPSEC_RESERVED7, "Reserved" },
{IPSEC_RESERVED8, "Reserved" } };
#define N_SECL_VALS (sizeof secl_vals / sizeof secl_vals[0])
tf = add_item_to_tree(opt_tree, offset, optlen, "%s:", name);
field_tree = gtk_tree_new();
add_subtree(tf, field_tree, ETT_IP_OPTION_SEC);
offset += 2;
val = pntohs(opd);
if ((secl_str = match_strval(val, secl_vals, N_SECL_VALS)))
add_item_to_tree(field_tree, offset, 2,
"Security: %s", secl_str);
else
add_item_to_tree(field_tree, offset, 2,
"Security: Unknown (0x%x)", val);
offset += 2;
opd += 2;
val = pntohs(opd);
add_item_to_tree(field_tree, offset, 2,
"Compartments: %d", val);
offset += 2;
opd += 2;
add_item_to_tree(field_tree, offset, 2,
"Handling restrictions: %c%c", opd[0], opd[1]);
offset += 2;
opd += 2;
add_item_to_tree(field_tree, offset, 3,
"Transmission control code: %c%c%c", opd[0], opd[1], opd[2]);
}
static void
dissect_ipopt_route(GtkWidget *opt_tree, const char *name,
const u_char *opd, int offset, guint optlen)
{
GtkWidget *field_tree = NULL, *tf;
int ptr;
int optoffset = 0;
struct in_addr addr;
tf = add_item_to_tree(opt_tree, offset, optlen, "%s (%d bytes)", name,
optlen);
field_tree = gtk_tree_new();
add_subtree(tf, field_tree, ETT_IP_OPTION_ROUTE);
optoffset += 2; /* skip past type and length */
optlen -= 2; /* subtract size of type and length */
ptr = *opd;
add_item_to_tree(field_tree, offset + optoffset, 1,
"Pointer: %d%s", ptr,
((ptr < 4) ? " (points before first address)" :
((ptr & 3) ? " (points to middle of address)" : "")));
optoffset++;
opd++;
optlen--;
ptr--; /* ptr is 1-origin */
while (optlen > 0) {
if (optlen < 4) {
add_item_to_tree(field_tree, offset, optlen,
"(suboption would go past end of option)");
break;
}
/* Avoids alignment problems on many architectures. */
memcpy((char *)&addr, (char *)opd, sizeof(addr));
add_item_to_tree(field_tree, offset + optoffset, 4,
"%s%s",
((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
((optoffset == ptr) ? " <- (current)" : ""));
optoffset += 4;
opd += 4;
optlen -= 4;
}
}
static void
dissect_ipopt_sid(GtkWidget *opt_tree, const char *name, const u_char *opd,
int offset, guint optlen)
{
add_item_to_tree(opt_tree, offset, optlen,
"%s: %d", name, pntohs(opd));
return;
}
static void
dissect_ipopt_timestamp(GtkWidget *opt_tree, const char *name, const u_char *opd,
int offset, guint optlen)
{
GtkWidget *field_tree = NULL, *tf;
int ptr;
int optoffset = 0;
int flg;
gchar *flg_str;
static value_string flag_vals[] = {
{IPOPT_TS_TSONLY, "Time stamps only" },
{IPOPT_TS_TSANDADDR, "Time stamp and address" },
{IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"} };
#define N_FLAG_VALS (sizeof flag_vals / sizeof flag_vals[0])
struct in_addr addr;
guint ts;
tf = add_item_to_tree(opt_tree, offset, optlen, "%s:", name);
field_tree = gtk_tree_new();
add_subtree(tf, field_tree, ETT_IP_OPTION_TIMESTAMP);
optoffset += 2; /* skip past type and length */
optlen -= 2; /* subtract size of type and length */
ptr = *opd;
add_item_to_tree(field_tree, offset + optoffset, 1,
"Pointer: %d%s", ptr,
((ptr < 5) ? " (points before first address)" :
(((ptr - 1) & 3) ? " (points to middle of address)" : "")));
optoffset++;
opd++;
optlen--;
ptr--; /* ptr is 1-origin */
flg = *opd;
add_item_to_tree(field_tree, offset + optoffset, 1,
"Overflow: %d", flg >> 4);
flg &= 0xF;
if ((flg_str = match_strval(flg, flag_vals, N_FLAG_VALS)))
add_item_to_tree(field_tree, offset + optoffset, 1,
"Flag: %s", flg_str);
else
add_item_to_tree(field_tree, offset + optoffset, 1,
"Flag: Unknown (0x%x)", flg);
optoffset++;
opd++;
optlen--;
while (optlen > 0) {
if (flg == IPOPT_TS_TSANDADDR) {
if (optlen < 4) {
add_item_to_tree(field_tree, offset + optoffset, optlen,
"(suboption would go past end of option)");
break;
}
/* XXX - check whether it goes past end of packet */
ts = pntohl(opd);
opd += 4;
optlen -= 4;
if (optlen < 4) {
add_item_to_tree(field_tree, offset + optoffset, optlen,
"(suboption would go past end of option)");
break;
}
/* XXX - check whether it goes past end of packet */
memcpy((char *)&addr, (char *)opd, sizeof(addr));
opd += 4;
optlen -= 4;
add_item_to_tree(field_tree, offset, 8,
"Address = %s, time stamp = %u",
((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
ts);
optoffset += 8;
} else {
if (optlen < 4) {
add_item_to_tree(field_tree, offset + optoffset, optlen,
"(suboption would go past end of option)");
break;
}
/* XXX - check whether it goes past end of packet */
ts = pntohl(opd);
opd += 4;
optlen -= 4;
add_item_to_tree(field_tree, offset + optoffset, 4,
"Time stamp = %u", ts);
optoffset += 4;
}
}
}
static ip_tcp_opt ipopts[] = {
{
IPOPT_END,
"EOL",
NO_LENGTH,
0,
NULL,
},
{
IPOPT_NOOP,
"NOP",
NO_LENGTH,
0,
NULL,
},
{
IPOPT_SEC,
"Security",
FIXED_LENGTH,
IPOLEN_SEC,
dissect_ipopt_security
},
{
IPOPT_SSRR,
"Strict source route",
VARIABLE_LENGTH,
IPOLEN_SSRR_MIN,
dissect_ipopt_route
},
{
IPOPT_LSRR,
"Loose source route",
VARIABLE_LENGTH,
IPOLEN_LSRR_MIN,
dissect_ipopt_route
},
{
IPOPT_RR,
"Record route",
VARIABLE_LENGTH,
IPOLEN_RR_MIN,
dissect_ipopt_route
},
{
IPOPT_SID,
"Stream identifier",
FIXED_LENGTH,
IPOLEN_SID,
dissect_ipopt_sid
},
{
IPOPT_TIMESTAMP,
"Time stamp",
VARIABLE_LENGTH,
IPOLEN_TIMESTAMP_MIN,
dissect_ipopt_timestamp
}
};
#define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
/* Dissect the IP or TCP options in a packet. */
void
dissect_ip_tcp_options(GtkWidget *opt_tree, const u_char *opd, int offset,
guint length, ip_tcp_opt *opttab, int nopts, int eol)
{
u_char opt;
ip_tcp_opt *optp;
guint len;
while (length > 0) {
opt = *opd++;
for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
if (optp->optcode == opt)
break;
}
if (optp == &opttab[nopts]) {
add_item_to_tree(opt_tree, offset, 1, "Unknown");
/* We don't know how long this option is, so we don't know how much
of it to skip, so we just bail. */
return;
}
--length; /* account for type byte */
if (optp->len_type != NO_LENGTH) {
/* Option has a length. Is it in the packet? */
if (length == 0) {
/* Bogus - packet must at least include option code byte and
length byte! */
add_item_to_tree(opt_tree, offset, 1,
"%s (length byte past end of header)", optp->name);
return;
}
len = *opd++; /* total including type, len */
--length; /* account for length byte */
if (len < 2) {
/* Bogus - option length is too short to include option code and
option length. */
add_item_to_tree(opt_tree, offset, 2,
"%s (with too-short option length = %u bytes)", optp->name, 2);
return;
} else if (len - 2 > length) {
/* Bogus - option goes past the end of the header. */
add_item_to_tree(opt_tree, offset, length,
"%s (option goes past end of header)", optp->name);
return;
} else if (optp->len_type == FIXED_LENGTH && len != optp->optlen) {
/* Bogus - option length isn't what it's supposed to be for this
option. */
add_item_to_tree(opt_tree, offset, len,
"%s (with option length = %u bytes; should be %u)", optp->name,
len, optp->optlen);
return;
} else if (optp->len_type == VARIABLE_LENGTH && len < optp->optlen) {
/* Bogus - option length is less than what it's supposed to be for
this option. */
add_item_to_tree(opt_tree, offset, len,
"%s (with option length = %u bytes; should be >= %u)", optp->name,
len, optp->optlen);
return;
} else {
if (optp->dissect != NULL) {
/* Option has a dissector. */
(*optp->dissect)(opt_tree, optp->name, opd, offset, len);
} else {
/* Option has no data, hence no dissector. */
add_item_to_tree(opt_tree, offset, len, "%s", optp->name);
}
len -= 2; /* subtract size of type and length */
offset += 2 + len;
}
opd += len;
length -= len;
} else {
add_item_to_tree(opt_tree, offset, 1, "%s", optp->name);
offset += 1;
}
if (opt == eol)
break;
}
}
void
dissect_ip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
e_ip iph;
GtkWidget *ip_tree, *ti;
GtkWidget *ip_tree, *ti, *field_tree, *tf;
gchar tos_str[32];
guint hlen, optlen;
gchar *proto_str;
static value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
{IP_PROTO_IGMP, "IGMP"},
{IP_PROTO_TCP, "TCP" },
{IP_PROTO_UDP, "UDP" },
{IP_PROTO_OSPF, "OSPF"} };
#define N_PROTO_VALS (sizeof proto_vals / sizeof proto_vals[0])
/* To do: check for runts, errs, etc. */
/* Avoids alignment problems on many architectures. */
@ -60,6 +413,8 @@ dissect_ip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
iph.ip_id = ntohs(iph.ip_id);
iph.ip_off = ntohs(iph.ip_off);
iph.ip_sum = ntohs(iph.ip_sum);
hlen = iph.ip_hl * 4; /* IP header length, in bytes */
if (fd->win_info[COL_NUM]) {
switch (iph.ip_p) {
@ -97,17 +452,16 @@ dissect_ip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
strcpy(tos_str, "Minimize cost");
break;
default:
strcpy(tos_str, "Unknon. Malformed?");
strcpy(tos_str, "Unknown. Malformed?");
break;
}
if (tree) {
ti = add_item_to_tree(GTK_WIDGET(tree), offset, (iph.ip_hl * 4),
"Internet Protocol");
ti = add_item_to_tree(GTK_WIDGET(tree), offset, hlen, "Internet Protocol");
ip_tree = gtk_tree_new();
add_subtree(ti, ip_tree, ETT_IP);
add_item_to_tree(ip_tree, offset, 1, "Version: %d", iph.ip_v);
add_item_to_tree(ip_tree, offset, 1, "Header length: %d", iph.ip_hl);
add_item_to_tree(ip_tree, offset, 1, "Header length: %d bytes", hlen);
add_item_to_tree(ip_tree, offset + 1, 1, "Type of service: 0x%02x (%s)",
iph.ip_tos, tos_str);
add_item_to_tree(ip_tree, offset + 2, 2, "Total length: %d", iph.ip_len);
@ -115,17 +469,33 @@ dissect_ip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
iph.ip_id);
/* To do: add flags */
add_item_to_tree(ip_tree, offset + 6, 2, "Fragment offset: %d",
iph.ip_off & 0x1fff);
iph.ip_off & IP_OFFSET);
add_item_to_tree(ip_tree, offset + 8, 1, "Time to live: %d",
iph.ip_ttl);
add_item_to_tree(ip_tree, offset + 9, 1, "Protocol: 0x%02x",
iph.ip_p);
if ((proto_str = match_strval(iph.ip_p, proto_vals, N_PROTO_VALS)))
add_item_to_tree(ip_tree, offset + 9, 1, "Protocol: %s", proto_str);
else
add_item_to_tree(ip_tree, offset + 9, 1, "Protocol: Unknown (%x)",
iph.ip_p);
add_item_to_tree(ip_tree, offset + 10, 2, "Header checksum: 0x%04x",
iph.ip_sum);
add_item_to_tree(ip_tree, offset + 12, 4, "Source address: %s",
get_hostname(iph.ip_src));
add_item_to_tree(ip_tree, offset + 16, 4, "Destination address: %s",
get_hostname(iph.ip_dst));
/* Decode IP options, if any. */
if (hlen > sizeof (e_ip)) {
/* There's more than just the fixed-length header. Decode the
options. */
optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
tf = add_item_to_tree(ip_tree, offset + 20, optlen,
"Options: (%d bytes)", optlen);
field_tree = gtk_tree_new();
add_subtree(tf, field_tree, ETT_IP_OPTIONS);
dissect_ip_tcp_options(field_tree, &pd[offset + 20], offset + 20, optlen,
ipopts, N_IP_OPTS, IPOPT_END);
}
}
pi.srcip = ip_to_str( (guint8 *) &iph.ip_src);
@ -135,7 +505,7 @@ dissect_ip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
pi.iphdrlen = iph.ip_hl;
pi.ip_src = iph.ip_src;
offset += iph.ip_hl * 4;
offset += hlen;
switch (iph.ip_p) {
case IP_PROTO_ICMP:
dissect_icmp(pd, offset, fd, tree);

View File

@ -1,7 +1,7 @@
/* packet-tcp.c
* Routines for TCP packet disassembly
*
* $Id: packet-tcp.c,v 1.4 1998/09/27 22:12:38 gerald Exp $
* $Id: packet-tcp.c,v 1.5 1998/10/13 05:40:04 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -46,14 +46,185 @@
extern FILE* data_out_file;
extern packet_info pi;
static void
dissect_tcpopt_maxseg(GtkWidget *opt_tree, const char *name, const u_char *opd,
int offset, guint optlen)
{
add_item_to_tree(opt_tree, offset, optlen,
"%s: %u bytes", name, pntohs(opd));
}
static void
dissect_tcpopt_wscale(GtkWidget *opt_tree, const char *name, const u_char *opd,
int offset, guint optlen)
{
add_item_to_tree(opt_tree, offset, optlen,
"%s: %u bytes", name, *opd);
}
static void
dissect_tcpopt_sack(GtkWidget *opt_tree, const char *name, const u_char *opd,
int offset, guint optlen)
{
GtkWidget *field_tree = NULL, *tf;
guint leftedge, rightedge;
tf = add_item_to_tree(opt_tree, offset, optlen, "%s:", name);
offset += 2; /* skip past type and length */
optlen -= 2; /* subtract size of type and length */
while (optlen > 0) {
if (field_tree == NULL) {
/* Haven't yet made a subtree out of this option. Do so. */
field_tree = gtk_tree_new();
add_subtree(tf, field_tree, ETT_TCP_OPTION_SACK);
}
if (optlen < 4) {
add_item_to_tree(field_tree, offset, optlen,
"(suboption would go past end of option)");
break;
}
/* XXX - check whether it goes past end of packet */
leftedge = pntohl(opd);
opd += 4;
optlen -= 4;
if (optlen < 4) {
add_item_to_tree(field_tree, offset, optlen,
"(suboption would go past end of option)");
break;
}
/* XXX - check whether it goes past end of packet */
rightedge = pntohl(opd);
opd += 4;
optlen -= 4;
add_item_to_tree(field_tree, offset, 8,
"left edge = %u, right edge = %u", leftedge, rightedge);
offset += 8;
}
}
static void
dissect_tcpopt_echo(GtkWidget *opt_tree, const char *name, const u_char *opd,
int offset, guint optlen)
{
add_item_to_tree(opt_tree, offset, optlen,
"%s: %u", name, pntohl(opd));
}
static void
dissect_tcpopt_timestamp(GtkWidget *opt_tree, const char *name,
const u_char *opd, int offset, guint optlen)
{
add_item_to_tree(opt_tree, offset, optlen,
"%s: tsval %u, tsecr %u", name, pntohl(opd), pntohl(opd + 4));
}
static void
dissect_tcpopt_cc(GtkWidget *opt_tree, const char *name, const u_char *opd,
int offset, guint optlen)
{
add_item_to_tree(opt_tree, offset, optlen,
"%s: %u", name, pntohl(opd));
}
static ip_tcp_opt tcpopts[] = {
{
TCPOPT_EOL,
"EOL",
NO_LENGTH,
0,
NULL,
},
{
TCPOPT_NOP,
"NOP",
NO_LENGTH,
0,
NULL,
},
{
TCPOPT_MSS,
"Maximum segment size",
FIXED_LENGTH,
TCPOLEN_MSS,
dissect_tcpopt_maxseg
},
{
TCPOPT_WINDOW,
"Window scale",
FIXED_LENGTH,
TCPOLEN_WINDOW,
dissect_tcpopt_wscale
},
{
TCPOPT_SACK_PERM,
"SACK permitted",
FIXED_LENGTH,
TCPOLEN_SACK_PERM,
NULL,
},
{
TCPOPT_SACK,
"SACK",
VARIABLE_LENGTH,
TCPOLEN_SACK_MIN,
dissect_tcpopt_sack
},
{
TCPOPT_ECHO,
"Echo",
FIXED_LENGTH,
TCPOLEN_ECHO,
dissect_tcpopt_echo
},
{
TCPOPT_ECHOREPLY,
"Echo reply",
FIXED_LENGTH,
TCPOLEN_ECHOREPLY,
dissect_tcpopt_echo
},
{
TCPOPT_TIMESTAMP,
"Time stamp",
FIXED_LENGTH,
TCPOLEN_TIMESTAMP,
dissect_tcpopt_timestamp
},
{
TCPOPT_CC,
"CC",
FIXED_LENGTH,
TCPOLEN_CC,
dissect_tcpopt_cc
},
{
TCPOPT_CCNEW,
"CC.NEW",
FIXED_LENGTH,
TCPOPT_CCNEW,
dissect_tcpopt_cc
},
{
TCPOPT_CCECHO,
"CC.ECHO",
FIXED_LENGTH,
TCPOLEN_CCECHO,
dissect_tcpopt_cc
}
};
#define N_TCP_OPTS (sizeof tcpopts / sizeof tcpopts[0])
void
dissect_tcp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
e_tcphdr th;
GtkWidget *tcp_tree, *ti;
GtkWidget *tcp_tree, *ti, *field_tree, *tf;
gchar flags[64] = "<None>";
gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG"};
gint fpos = 0, i;
guint bpos;
guint hlen;
guint optlen;
/* To do: Check for {cap len,pkt len} < struct len */
/* Avoids alignment problems on many architectures. */
@ -85,51 +256,65 @@ dissect_tcp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
th.th_sport, th.th_dport);
}
hlen = th.th_off * 4; /* TCP header length, in bytes */
if (tree) {
ti = add_item_to_tree(GTK_WIDGET(tree), offset, 20,
ti = add_item_to_tree(GTK_WIDGET(tree), offset, hlen,
"Transmission Control Protocol");
tcp_tree = gtk_tree_new();
add_subtree(ti, tcp_tree, ETT_TCP);
add_item_to_tree(tcp_tree, offset, 2, "Source port: %d", th.th_sport);
add_item_to_tree(tcp_tree, offset + 2, 2, "Destination port: %d", th.th_dport);
add_item_to_tree(tcp_tree, offset + 4, 4, "Sequence number: 0x%08x",
add_item_to_tree(tcp_tree, offset + 4, 4, "Sequence number: %u",
th.th_seq);
add_item_to_tree(tcp_tree, offset + 8, 4, "Acknowledgement number: 0x%08x",
th.th_ack);
add_item_to_tree(tcp_tree, offset + 12, 1, "Header length: %d", th.th_off);
if (th.th_flags & TH_ACK)
add_item_to_tree(tcp_tree, offset + 8, 4, "Acknowledgement number: %u",
th.th_ack);
add_item_to_tree(tcp_tree, offset + 12, 1, "Header length: %d bytes", hlen);
add_item_to_tree(tcp_tree, offset + 13, 1, "Flags: %s", flags);
add_item_to_tree(tcp_tree, offset + 14, 2, "Window size: %d", th.th_win);
add_item_to_tree(tcp_tree, offset + 16, 2, "Checksum: 0x%04x", th.th_sum);
add_item_to_tree(tcp_tree, offset + 18, 2, "Urgent pointer: 0x%04x",
th.th_urp);
/* To do: TCP options */
if (th.th_flags & TH_URG)
add_item_to_tree(tcp_tree, offset + 18, 2, "Urgent pointer: 0x%04x",
th.th_urp);
/* Decode TCP options, if any. */
if (hlen > sizeof (e_tcphdr)) {
/* There's more than just the fixed-length header. Decode the
options. */
optlen = hlen - sizeof (e_tcphdr); /* length of options, in bytes */
tf = add_item_to_tree(tcp_tree, offset + 20, optlen,
"Options: (%d bytes)", optlen);
field_tree = gtk_tree_new();
add_subtree(tf, field_tree, ETT_TCP_OPTIONS);
dissect_ip_tcp_options(field_tree, &pd[offset + 20], offset + 20, optlen,
tcpopts, N_TCP_OPTS, TCPOPT_EOL);
}
}
/* Skip over header + options */
offset += 4 * th.th_off;
/* until we decode those options, I'll check the packet length
to see if there's more data. -- gilbert */
if (fd->cap_len > offset) {
switch(MIN(th.th_sport, th.th_dport)) {
case TCP_PORT_PRINTER:
dissect_lpd(pd, offset, fd, tree);
break;
default:
dissect_data(pd, offset, fd, tree);
}
}
/* Skip over header + options */
offset += hlen;
/* until we decode those options, I'll check the packet length
to see if there's more data. -- gilbert */
if (fd->cap_len > offset) {
switch(MIN(th.th_sport, th.th_dport)) {
case TCP_PORT_PRINTER:
dissect_lpd(pd, offset, fd, tree);
break;
default:
dissect_data(pd, offset, fd, tree);
}
}
pi.srcport = th.th_sport;
pi.destport = th.th_dport;
if( data_out_file ) {
reassemble_tcp( th.th_seq, /* sequence number */
( pi.iplen -( pi.iphdrlen * 4 )-( th.th_off * 4 ) ), /* length */
( pd+offset ), /* data */
( th.th_flags & 0x02 ), /* is syn set? */
pi.ip_src ); /* src ip */
}
pi.srcport = th.th_sport;
pi.destport = th.th_dport;
if( data_out_file ) {
reassemble_tcp( th.th_seq, /* sequence number */
( pi.iplen -( pi.iphdrlen * 4 )-( th.th_off * 4 ) ), /* length */
( pd+offset ), /* data */
( th.th_flags & 0x02 ), /* is syn set? */
pi.ip_src ); /* src ip */
}
}

217
packet.h
View File

@ -1,7 +1,7 @@
/* packet.h
* Definitions for packet disassembly structures and routines
*
* $Id: packet.h,v 1.12 1998/10/12 01:40:53 gerald Exp $
* $Id: packet.h,v 1.13 1998/10/13 05:40:02 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -200,6 +200,12 @@ typedef struct _e_ip {
guint32 ip_dst;
} e_ip;
/* IP flags. */
#define IP_CE 0x8000 /* Flag: "Congestion" */
#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
#define IP_MF 0x2000 /* Flag: "More Fragments" */
#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
#define IPTOS_TOS_MASK 0x1E
#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
#define IPTOS_NONE 0x00
@ -208,6 +214,63 @@ typedef struct _e_ip {
#define IPTOS_RELIABILITY 0x04
#define IPTOS_LOWCOST 0x02
#define IPTOS_PREC_MASK 0xE0
#define IPTOS_PREC(tos) ((tos)&IPTOS_PREC_MASK)
#define IPTOS_PREC_NETCONTROL 0xe0
#define IPTOS_PREC_INTERNETCONTROL 0xc0
#define IPTOS_PREC_CRITIC_ECP 0xa0
#define IPTOS_PREC_FLASHOVERRIDE 0x80
#define IPTOS_PREC_FLASH 0x60
#define IPTOS_PREC_IMMEDIATE 0x40
#define IPTOS_PREC_PRIORITY 0x20
#define IPTOS_PREC_ROUTINE 0x00
/* IP options */
#define IPOPT_COPY 0x80
#define IPOPT_CONTROL 0x00
#define IPOPT_RESERVED1 0x20
#define IPOPT_MEASUREMENT 0x40
#define IPOPT_RESERVED2 0x60
#define IPOPT_END (0 |IPOPT_CONTROL)
#define IPOPT_NOOP (1 |IPOPT_CONTROL)
#define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
#define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
#define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
#define IPOPT_RR (7 |IPOPT_CONTROL)
#define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
#define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
#define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
/* IP option lengths */
#define IPOLEN_SEC 11
#define IPOLEN_LSRR_MIN 3
#define IPOLEN_TIMESTAMP_MIN 5
#define IPOLEN_RR_MIN 3
#define IPOLEN_SID 4
#define IPOLEN_SSRR_MIN 3
#define IPSEC_UNCLASSIFIED 0x0000
#define IPSEC_CONFIDENTIAL 0xF135
#define IPSEC_EFTO 0x789A
#define IPSEC_MMMM 0xBC4D
#define IPSEC_RESTRICTED 0xAF13
#define IPSEC_SECRET 0xD788
#define IPSEC_TOPSECRET 0x6BC5
#define IPSEC_RESERVED1 0x35E2
#define IPSEC_RESERVED2 0x9AF1
#define IPSEC_RESERVED3 0x4D78
#define IPSEC_RESERVED4 0x24BD
#define IPSEC_RESERVED5 0x135E
#define IPSEC_RESERVED6 0x89AF
#define IPSEC_RESERVED7 0xC4D6
#define IPSEC_RESERVED8 0xE26B
#define IPOPT_TS_TSONLY 0 /* timestamps only */
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
#define IP_PROTO_ICMP 1
#define IP_PROTO_IGMP 2
#define IP_PROTO_TCP 6
@ -256,6 +319,38 @@ typedef struct _e_tcphdr {
guint16 th_urp;
} e_tcphdr;
/*
* TCP option
*/
#define TCPOPT_NOP 1 /* Padding */
#define TCPOPT_EOL 0 /* End of options */
#define TCPOPT_MSS 2 /* Segment size negotiating */
#define TCPOPT_WINDOW 3 /* Window scaling */
#define TCPOPT_SACK_PERM 4 /* SACK Permitted */
#define TCPOPT_SACK 5 /* SACK Block */
#define TCPOPT_ECHO 6
#define TCPOPT_ECHOREPLY 7
#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
#define TCPOPT_CC 11
#define TCPOPT_CCNEW 12
#define TCPOPT_CCECHO 13
/*
* TCP option lengths
*/
#define TCPOLEN_MSS 4
#define TCPOLEN_WINDOW 3
#define TCPOLEN_SACK_PERM 2
#define TCPOLEN_SACK_MIN 2
#define TCPOLEN_ECHO 6
#define TCPOLEN_ECHOREPLY 6
#define TCPOLEN_TIMESTAMP 10
#define TCPOLEN_CC 6
#define TCPOLEN_CCNEW 6
#define TCPOLEN_CCECHO 6
/* UDP structs and definitions */
typedef struct _e_udphdr {
@ -279,53 +374,59 @@ typedef struct _e_udphdr {
/* Tree types. Each dissect_* routine should have one for each
add_subtree() call. */
#define ETT_FRAME 0
#define ETT_IEEE8023 1
#define ETT_ETHER2 2
#define ETT_LLC 3
#define ETT_TOKEN_RING 4
#define ETT_TR_IERR_CNT 5
#define ETT_TR_NERR_CNT 6
#define ETT_TR_MAC 7
#define ETT_PPP 8
#define ETT_ARP 9
#define ETT_IP 10
#define ETT_UDP 11
#define ETT_TCP 12
#define ETT_ICMP 13
#define ETT_IGMP 14
#define ETT_IPX 15
#define ETT_SPX 16
#define ETT_NCP 17
#define ETT_DNS 18
#define ETT_DNS_ANS 19
#define ETT_DNS_QRY 20
#define ETT_RIP 21
#define ETT_RIP_VEC 22
#define ETT_OSPF 23
#define ETT_OSPF_HDR 24
#define ETT_OSPF_HELLO 25
#define ETT_OSPF_DESC 26
#define ETT_OSPF_LSR 27
#define ETT_OSPF_LSA_UPD 28
#define ETT_OSPF_LSA 29
#define ETT_LPD 30
#define ETT_RAW 31
#define ETT_BOOTP 32
#define ETT_BOOTP_OPTION 33
#define ETT_IPv6 34
#define ETT_CLNP 35
#define ETT_COTP 36
#define ETT_VINES 37
#define ETT_VSPP 38
#define ETT_IPXRIP 39
#define ETT_IPXSAP 40
#define ETT_IPXSAP_SERVER 41
#define ETT_NULL 42
#define ETT_FDDI 43
/* Should be the last item number plus one */
#define NUM_TREE_TYPES 44
enum {
ETT_FRAME,
ETT_IEEE8023,
ETT_ETHER2,
ETT_LLC,
ETT_TOKEN_RING,
ETT_TR_IERR_CNT,
ETT_TR_NERR_CNT,
ETT_TR_MAC,
ETT_PPP,
ETT_ARP,
ETT_FDDI,
ETT_NULL,
ETT_IP,
ETT_IP_OPTIONS,
ETT_IP_OPTION_SEC,
ETT_IP_OPTION_ROUTE,
ETT_IP_OPTION_TIMESTAMP,
ETT_UDP,
ETT_TCP,
ETT_TCP_OPTIONS,
ETT_TCP_OPTION_SACK,
ETT_ICMP,
ETT_IGMP,
ETT_IPX,
ETT_SPX,
ETT_NCP,
ETT_DNS,
ETT_DNS_ANS,
ETT_DNS_QRY,
ETT_RIP,
ETT_RIP_VEC,
ETT_OSPF,
ETT_OSPF_HDR,
ETT_OSPF_HELLO,
ETT_OSPF_DESC,
ETT_OSPF_LSR,
ETT_OSPF_LSA_UPD,
ETT_OSPF_LSA,
ETT_LPD,
ETT_RAW,
ETT_BOOTP,
ETT_BOOTP_OPTION,
ETT_IPv6,
ETT_CLNP,
ETT_COTP,
ETT_VINES,
ETT_VSPP,
ETT_IPXRIP,
ETT_IPXSAP,
ETT_IPXSAP_SERVER,
NUM_TREE_TYPES /* last item number plus one */
};
/* The version of pcap.h that comes with some systems is missing these
* #defines.
@ -343,6 +444,26 @@ typedef struct _e_udphdr {
#define DLT_PPP_BSDOS 14
#endif
typedef enum {
NO_LENGTH, /* option has no data, hence no length */
FIXED_LENGTH, /* option always has the same length */
VARIABLE_LENGTH /* option is variable-length - optlen is minimum */
} opt_len_type;
/* Member of table of IP or TCP options. */
typedef struct {
int optcode; /* code for option */
char *name; /* name of option */
opt_len_type len_type; /* type of option length field */
int optlen; /* value length should be (minimum if VARIABLE) */
void (*dissect)(GtkWidget *, const char *, const u_char *, int, guint);
/* routine to dissect option */
} ip_tcp_opt;
/* Routine to dissect IP or TCP options. */
void dissect_ip_tcp_options(GtkWidget *, const u_char *, int, guint,
ip_tcp_opt *, int, int);
/* Utility routines used by packet*.c */
gchar* ether_to_str(guint8 *);
gchar* ip_to_str(guint8 *);