/* packet-ip.c
* Routines for IP and miscellaneous IP protocol packet disassembly
*
- * $Id: packet-ip.c,v 1.184 2003/03/03 23:20:57 sahlberg Exp $
+ * $Id: packet-ip.c,v 1.202 2004/02/18 06:43:00 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include <epan/packet.h>
#include <epan/resolv.h>
#include "ipproto.h"
+#include "ip_opts.h"
#include "prefs.h"
#include "reassemble.h"
#include "etypes.h"
static int hf_ip_src = -1;
static int hf_ip_addr = -1;
static int hf_ip_flags = -1;
+static int hf_ip_flags_rf = -1;
static int hf_ip_flags_df = -1;
static int hf_ip_flags_mf = -1;
static int hf_ip_frag_offset = -1;
static int hf_ip_fragment_multiple_tails = -1;
static int hf_ip_fragment_too_long_fragment = -1;
static int hf_ip_fragment_error = -1;
+static int hf_ip_reassembled_in = -1;
static gint ett_ip = -1;
static gint ett_ip_dsfield = -1;
&hf_ip_fragment_multiple_tails,
&hf_ip_fragment_too_long_fragment,
&hf_ip_fragment_error,
+ &hf_ip_reassembled_in,
"fragments"
};
-/* Used by IPv6 as well, so not static */
-dissector_table_t ip_dissector_table;
+static dissector_table_t ip_dissector_table;
static dissector_handle_t ip_handle;
static dissector_handle_t data_handle;
static int hf_icmp_code = -1;
static int hf_icmp_checksum = -1;
static int hf_icmp_checksum_bad = -1;
+static int hf_icmp_ident = -1;
+static int hf_icmp_seq_num = -1;
+static int hf_icmp_mtu = -1;
+static int hf_icmp_redir_gw = -1;
+
/* Mobile ip */
static int hf_icmp_mip_type = -1;
#define IPH_MIN_LEN 20
/* IP flags. */
-#define IP_CE 0x8000 /* Flag: "Congestion" */
+#define IP_RF 0x8000 /* Flag: "Reserved bit" */
#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
#define IP_MF 0x2000 /* Flag: "More Fragments" */
#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
* defragmentation of IPv4
*/
static GHashTable *ip_fragment_table = NULL;
+static GHashTable *ip_reassembled_table = NULL;
static void
ip_defragment_init(void)
{
fragment_table_init(&ip_fragment_table);
+ reassembled_table_init(&ip_reassembled_table);
}
void
"Normal"
};
-static const true_false_string flags_set_truth = {
- "Set",
- "Not set"
-};
-
static guint16 ip_checksum(const guint8 *ptr, int len)
{
vec_t cksum_vec[1];
{
proto_tree *ip_tree = NULL, *field_tree;
proto_item *ti = NULL, *tf;
+ guint32 addr;
int offset = 0;
guint hlen, optlen;
guint16 flags;
guint8 nxt;
guint16 ipsum;
- fragment_data *ipfd_head;
+ fragment_data *ipfd_head=NULL;
tvbuff_t *next_tvb;
gboolean update_col_info = TRUE;
gboolean save_fragmented;
eip_current=0;
}
iph=&eip_arr[eip_current];
- pinfo->private_data=iph;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
iph->ip_id = tvb_get_ntohs(tvb, offset + 4);
if (tree)
- proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph->ip_id);
+ proto_tree_add_uint_format(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph->ip_id, "Identification: 0x%04x (%d)", iph->ip_id, iph->ip_id);
iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
if (tree) {
- flags = (iph->ip_off & (IP_DF|IP_MF)) >> 12;
+ flags = (iph->ip_off & (IP_RF | IP_DF | IP_MF)) >> 12;
tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
field_tree = proto_item_add_subtree(tf, ett_ip_off);
- proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
- proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
+ proto_tree_add_boolean(field_tree, hf_ip_flags_rf, tvb, offset + 6, 1, flags);
+ proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags);
+ proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags);
proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
(iph->ip_off & IP_OFFSET)*8);
proto_tree_add_uint(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum);
}
- tvb_memcpy(tvb, (guint8 *)&iph->ip_src, offset + 12, 4);
+ SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
+ SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
+ SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
if (tree) {
+ memcpy(&addr, iph->ip_src.data, 4);
if (ip_summary_in_tree) {
proto_item_append_text(ti, ", Src Addr: %s (%s)",
- get_hostname(iph->ip_src), ip_to_str((guint8 *) &iph->ip_src));
+ get_hostname(addr), ip_to_str((guint8 *) iph->ip_src.data));
}
- proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, iph->ip_src);
- proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, iph->ip_src);
+ proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
+ proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
}
- tvb_memcpy(tvb, (guint8 *)&iph->ip_dst, offset + 16, 4);
+ SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
+ SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
+ SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
+
if (tree) {
+ memcpy(&addr, iph->ip_dst.data, 4);
if (ip_summary_in_tree) {
proto_item_append_text(ti, ", Dst Addr: %s (%s)",
- get_hostname(iph->ip_dst), ip_to_str((guint8 *) &iph->ip_dst));
+ get_hostname(addr), ip_to_str((guint8 *) iph->ip_dst.data));
}
- proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, iph->ip_dst);
- proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, iph->ip_dst);
+ proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, addr);
+ proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, addr);
}
if (tree) {
pinfo->iplen = iph->ip_len;
- pinfo->iphdrlen = lo_nibble(iph->ip_v_hl);
-
- SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
- SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
- SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
- SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
+ pinfo->iphdrlen = hlen;
/* Skip over header + options */
offset += hlen;
*/
save_fragmented = pinfo->fragmented;
if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
- tvb_reported_length(tvb) <= tvb_length(tvb) && ipsum == 0) {
- ipfd_head = fragment_add(tvb, offset, pinfo, iph->ip_id,
+ tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
+ ipsum == 0) {
+ ipfd_head = fragment_add_check(tvb, offset, pinfo, iph->ip_id,
ip_fragment_table,
+ ip_reassembled_table,
(iph->ip_off & IP_OFFSET)*8,
- pinfo->iplen - (pinfo->iphdrlen*4),
+ pinfo->iplen - pinfo->iphdrlen,
iph->ip_off & IP_MF);
- if (ipfd_head != NULL) {
- /* OK, we have the complete reassembled payload.
- Allocate a new tvbuff, referring to the reassembled payload. */
- next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen,
- ipfd_head->datalen);
-
- /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
- were handed refers, so it'll get cleaned up when that tvbuff
- is cleaned up. */
- tvb_set_child_real_data_tvbuff(tvb, next_tvb);
-
- /* Add the defragmented data to the data source list. */
- add_new_data_source(pinfo, next_tvb, "Reassembled IPv4");
-
- /* show all fragments */
- update_col_info = !show_fragment_tree(ipfd_head, &ip_frag_items,
- ip_tree, pinfo, next_tvb);
- } else {
- /* We don't have the complete reassembled payload. */
- next_tvb = NULL;
- }
+ next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
+ ipfd_head, &ip_frag_items, &update_col_info, ip_tree);
} else {
/* If this is the first fragment, dissect its contents, otherwise
just show it as a fragment.
if (next_tvb == NULL) {
/* Just show this as a fragment. */
- if (check_col(pinfo->cinfo, COL_INFO))
+ if (check_col(pinfo->cinfo, COL_INFO)) {
col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
ipprotostr(iph->ip_p), iph->ip_p, (iph->ip_off & IP_OFFSET) * 8);
+ }
+ if( ipfd_head && ipfd_head->reassembled_in != pinfo->fd->num ){
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]",
+ ipfd_head->reassembled_in);
+ }
+ }
+
call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
tree);
pinfo->fragmented = save_fragmented;
#define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
-static const gchar *ttl_str[] = {"TTL equals 0 during transit",
- "TTL equals 0 during reassembly"};
+static const gchar *ttl_str[] = {"Time to live exceeded in transit",
+ "Fragment reassembly time exceeded"};
#define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
case ICMP_IREQREPLY:
case ICMP_MASKREQ:
case ICMP_MASKREPLY:
- proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
- tvb_get_ntohs(tvb, 4));
- proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
- tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
+ proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, FALSE);
+ proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2, FALSE);
break;
case ICMP_UNREACH:
switch (icmp_code) {
case ICMP_FRAG_NEEDED:
- proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
- tvb_get_ntohs(tvb, 6));
+ proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, FALSE);
break;
}
break;
break;
case ICMP_REDIRECT:
- proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
- ip_to_str(tvb_get_ptr(tvb, 4, 4)));
+ proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, FALSE);
break;
}
{ "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
"", HFILL }},
+ { &hf_ip_flags_rf,
+ { "Reserved bit", "ip.flags.rb", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_RF >> 12,
+ "", HFILL }},
+
{ &hf_ip_flags_df,
- { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
+ { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF >> 12,
"", HFILL }},
{ &hf_ip_flags_mf,
- { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
+ { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF >> 12,
"", HFILL }},
{ &hf_ip_frag_offset,
{ &hf_ip_fragments,
{ "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
"IP Fragments", HFILL }},
+
+ { &hf_ip_reassembled_in,
+ { "Reassembled IP in frame", "ip.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This IP packet is reassembled in this frame", HFILL }}
};
static gint *ett[] = {
&ett_ip,
{ "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"", HFILL }},
+ { &hf_icmp_ident,
+ {"Identifier", "icmp.ident", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_icmp_seq_num,
+ {"Sequence number", "icmp.seq", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_icmp_mtu,
+ {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_icmp_redir_gw,
+ {"Gateway address", "icmp.redir_gw", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
{ &hf_icmp_mip_type,
{ "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
VALS(mip_extensions), 0x0,"", HFILL}},