/* packet-ip.c
* Routines for IP and miscellaneous IP protocol packet disassembly
*
- * $Id$
- *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
#include "config.h"
-#include <string.h>
-#include <glib.h>
-
#include <epan/packet.h>
#include <epan/addr_resolv.h>
#include <epan/ipproto.h>
#include <epan/expert.h>
#include <epan/ip_opts.h>
#include <epan/prefs.h>
+#include <epan/conversation_table.h>
+#include <epan/color_dissector_filters.h>
#include <epan/reassemble.h>
#include <epan/etypes.h>
-#include <epan/greproto.h>
#include <epan/ppptypes.h>
#include <epan/llcsaps.h>
#include <epan/aftypes.h>
#include <epan/in_cksum.h>
#include <epan/nlpid.h>
#include <epan/ax25_pids.h>
-#include <epan/tap.h>
-#include <epan/wmem/wmem.h>
+#include <epan/decode_as.h>
+#include <wiretap/erf.h>
#include "packet-ip.h"
-#include "packet-ipsec.h"
+#include "packet-juniper.h"
+#include "packet-sflow.h"
+#include "packet-gre.h"
+#include "packet-l2tp.h"
#ifdef HAVE_GEOIP
#include <GeoIP.h>
#include <epan/geoip_db.h>
#endif /* HAVE_GEOIP */
+void proto_register_ip(void);
+void proto_reg_handoff_ip(void);
static int ip_tap = -1;
static gboolean ip_summary_in_tree = TRUE;
/* Perform IP checksum */
-static gboolean ip_check_checksum = TRUE;
+static gboolean ip_check_checksum = FALSE;
/* Assume TSO and correct zero-length IP packets */
static gboolean ip_tso_supported = TRUE;
/* Interpret the reserved flag as security flag (RFC 3514) */
static gboolean ip_security_flag = FALSE;
-static int proto_ip = -1;
+int proto_ip = -1;
static int hf_ip_version = -1;
static int hf_ip_hdr_len = -1;
static int hf_ip_dsfield = -1;
static int hf_ip_ttl = -1;
static int hf_ip_proto = -1;
static int hf_ip_checksum = -1;
+static int hf_ip_checksum_calculated = -1;
static int hf_ip_checksum_good = -1;
static int hf_ip_checksum_bad = -1;
static int hf_ip_src_rt_host = -1;
static int hf_ip_empty_rt = -1;
static int hf_ip_empty_rt_host = -1;
+static int hf_ip_cipso_tag_type = -1;
static int hf_ip_fragments = -1;
static int hf_ip_fragment = -1;
static int hf_ip_reassembled_length = -1;
static int hf_ip_reassembled_data = -1;
+/* Generated from convert_proto_tree_add_text.pl */
+static int hf_ip_opt_flag = -1;
+static int hf_ip_opt_overflow = -1;
+static int hf_ip_cipso_tag_data = -1;
+static int hf_ip_cipso_sensitivity_level = -1;
+static int hf_ip_cipso_categories = -1;
+static int hf_ip_cipso_doi = -1;
+static int hf_ip_opt_time_stamp = -1;
+static int hf_ip_opt_time_stamp_addr = -1;
+
#ifdef HAVE_GEOIP
static int hf_geoip_country = -1;
static int hf_geoip_city = -1;
static gint ett_ip_checksum = -1;
static gint ett_ip_opt_type = -1;
static gint ett_ip_opt_sec_prot_auth_flags = -1;
+static gint ett_unknown_ip_tcp_opt = -1;
static expert_field ei_ip_opt_len_invalid = EI_INIT;
static expert_field ei_ip_opt_sec_prot_auth_fti = EI_INIT;
static expert_field ei_ip_checksum_bad = EI_INIT;
static expert_field ei_ip_ttl_lncb = EI_INIT;
static expert_field ei_ip_ttl_too_small = EI_INIT;
+static expert_field ei_ip_cipso_tag = EI_INIT;
+static expert_field ei_ip_bogus_ip_version = EI_INIT;
#ifdef HAVE_GEOIP
static dissector_handle_t ipv6_handle;
static dissector_handle_t data_handle;
-static dissector_handle_t tapa_handle;
/* IP structs and definitions */
#define is_a_multicast_addr(addr) \
((addr & 0xf0000000) == 0xe0000000)
+static void ip_prompt(packet_info *pinfo, gchar* result)
+{
+ g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IP protocol %u as",
+ GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_ip, 0)));
+}
+
+static gpointer ip_value(packet_info *pinfo)
+{
+ return p_get_proto_data(pinfo->pool, pinfo, proto_ip, 0);
+}
+
+static const char* ip_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
+{
+ if ((filter == CONV_FT_SRC_ADDRESS) && (conv->src_address.type == AT_IPv4))
+ return "ip.src";
+
+ if ((filter == CONV_FT_DST_ADDRESS) && (conv->dst_address.type == AT_IPv4))
+ return "ip.dst";
+
+ if ((filter == CONV_FT_ANY_ADDRESS) && (conv->src_address.type == AT_IPv4))
+ return "ip.addr";
+
+ return CONV_FILTER_INVALID;
+}
+
+static ct_dissector_info_t ip_ct_dissector_info = {&ip_conv_get_filter_type};
+
+static int
+ip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
+{
+ conv_hash_t *hash = (conv_hash_t*) pct;
+ const ws_ip *iph=(const ws_ip *)vip;
+
+ add_conversation_table_data(hash, &iph->ip_src, &iph->ip_dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->fd->abs_ts, &ip_ct_dissector_info, PT_NONE);
+
+ return 1;
+}
+
+static const char* ip_host_get_filter_type(hostlist_talker_t* host, conv_filter_type_e filter)
+{
+ if ((filter == CONV_FT_ANY_ADDRESS) && (host->myaddress.type == AT_IPv4))
+ return "ip.addr";
+
+ return CONV_FILTER_INVALID;
+}
+
+static hostlist_dissector_info_t ip_host_dissector_info = {&ip_host_get_filter_type};
+
+static int
+ip_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
+{
+ conv_hash_t *hash = (conv_hash_t*) pit;
+ const ws_ip *iph=(const ws_ip *)vip;
+
+ /* Take two "add" passes per packet, adding for each direction, ensures that all
+ packets are counted properly (even if address is sending to itself)
+ XXX - this could probably be done more efficiently inside hostlist_table */
+ add_hostlist_table_data(hash, &iph->ip_src, 0, TRUE, 1, pinfo->fd->pkt_len, &ip_host_dissector_info, PT_NONE);
+ add_hostlist_table_data(hash, &iph->ip_dst, 0, FALSE, 1, pinfo->fd->pkt_len, &ip_host_dissector_info, PT_NONE);
+ return 1;
+}
+
+static gboolean
+ip_color_filter_valid(packet_info *pinfo)
+{
+ return proto_is_frame_protocol(pinfo->layers, "ip");
+}
+
+static gchar*
+ip_build_color_filter(packet_info *pinfo)
+{
+ return g_strdup_printf("ip.addr eq %s and ip.addr eq %s",
+ address_to_str(pinfo->pool, &pinfo->net_src),
+ address_to_str(pinfo->pool, &pinfo->net_dst));
+}
+
/*
* defragmentation of IPv4
*/
&addresses_reassembly_table_functions);
}
+static void
+ip_defragment_cleanup(void)
+{
+ reassembly_table_destroy(&ip_reassembly_table);
+}
+
void
capture_ip(const guchar *pd, int offset, int len, packet_counts *ld) {
if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
#ifdef HAVE_GEOIP
static void
-add_geoip_info_entry(proto_item *geoip_info_item, tvbuff_t *tvb, gint offset, guint32 ip, int isdst)
+add_geoip_info_entry(proto_tree *geoip_info_tree, proto_item *geoip_info_item, tvbuff_t *tvb, gint offset, guint32 ip, int isdst)
{
- proto_tree *geoip_info_tree;
-
guint num_dbs = geoip_db_num_dbs();
guint item_cnt = 0;
guint dbnum;
- geoip_info_tree = proto_item_add_subtree(geoip_info_item, ett_geoip_info);
-
for (dbnum = 0; dbnum < num_dbs; dbnum++) {
- const char *geoip_str = geoip_db_lookup_ipv4(dbnum, ip, NULL);
+ char *geoip_str = geoip_db_lookup_ipv4(dbnum, ip, NULL);
int db_type = geoip_db_type(dbnum);
int geoip_hf, geoip_local_hf;
break;
default:
continue;
- break;
}
if (geoip_str) {
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_HIDDEN(item);
} else {
- item = proto_tree_add_unicode_string(geoip_info_tree, geoip_local_hf,
+ item = proto_tree_add_string(geoip_info_tree, geoip_local_hf,
tvb, offset, 4, geoip_str);
PROTO_ITEM_SET_GENERATED(item);
- item = proto_tree_add_unicode_string(geoip_info_tree, geoip_hf,
+ item = proto_tree_add_string(geoip_info_tree, geoip_hf,
tvb, offset, 4, geoip_str);
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_HIDDEN(item);
item_cnt++;
proto_item_append_text(geoip_info_item, "%s%s",
plurality(item_cnt, "", ", "), geoip_str);
+ wmem_free(NULL, geoip_str);
}
}
{
guint num_dbs;
proto_item *geoip_info_item;
+ proto_tree *geoip_info_tree;
num_dbs = geoip_db_num_dbs();
if (num_dbs < 1)
return;
- geoip_info_item = proto_tree_add_text(tree, tvb, offset + IPH_SRC, 4, "Source GeoIP: ");
+ geoip_info_tree = proto_tree_add_subtree(tree, tvb, offset + IPH_SRC, 4, ett_geoip_info, &geoip_info_item, "Source GeoIP: ");
PROTO_ITEM_SET_GENERATED(geoip_info_item);
- add_geoip_info_entry(geoip_info_item, tvb, offset + IPH_SRC, src32, 0);
+ add_geoip_info_entry(geoip_info_tree, geoip_info_item, tvb, offset + IPH_SRC, src32, 0);
- geoip_info_item = proto_tree_add_text(tree, tvb, offset + IPH_DST, 4,
- "Destination GeoIP: ");
+ geoip_info_tree = proto_tree_add_subtree(tree, tvb, offset + IPH_DST, 4, ett_geoip_info, &geoip_info_item, "Destination GeoIP: ");
PROTO_ITEM_SET_GENERATED(geoip_info_item);
- add_geoip_info_entry(geoip_info_item, tvb, offset + IPH_DST, dst32, 1);
+ add_geoip_info_entry(geoip_info_tree, geoip_info_item, tvb, offset + IPH_DST, dst32, 1);
}
#endif /* HAVE_GEOIP */
proto_tree *opt_tree, void * data _U_)
{
proto_tree *field_tree;
- proto_item *tf;
- tf = proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", optp->name);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree(opt_tree, tvb, offset, 1, *optp->subtree_index, NULL, optp->name);
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
}
guint val;
guint curr_offset = offset;
- tf = proto_tree_add_text(opt_tree, tvb, curr_offset, optlen, "%s (%u bytes)",
- optp->name, optlen);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, curr_offset, optlen, *optp->subtree_index, &tf,
+ "%s (%u bytes)", optp->name, optlen);
dissect_ipopt_type(tvb, curr_offset, field_tree, &IP_OPT_TYPES);
curr_offset++;
tf_sub = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, curr_offset, 1, ENC_NA);
void * data _U_)
{
proto_tree *field_tree;
- proto_item *tf;
proto_item *tf_sub;
guint curr_offset = offset;
gint remaining;
- tf = proto_tree_add_text(opt_tree, tvb, curr_offset, optlen, "%s (%u bytes)",
- optp->name, optlen);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, curr_offset, optlen,
+ *optp->subtree_index, NULL, "%s (%u bytes)", optp->name, optlen);
dissect_ipopt_type(tvb, curr_offset, field_tree, &IP_OPT_TYPES);
curr_offset++;
tf_sub = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, curr_offset, 1, ENC_NA);
* draft-ietf-cipso-ipsecurity-01.txt and FIPS 188, a copy of both documents
* can be found at the NetLabel project page, http://netlabel.sf.net or at
* http://tools.ietf.org/html/draft-ietf-cipso-ipsecurity-01 */
+static const value_string cipso_tag_type_vals[] = {
+ {0, "Padding"},
+ {1, "Restrictive Category Bitmap"},
+ {2, "Enumerated Categories"},
+ {5, "Ranged Categories"},
+ {6, "Permissive Categories"},
+ {7, "Free Form"},
+
+ { 0, NULL }
+};
+
static void
dissect_ipopt_cipso(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
guint optlen, packet_info *pinfo, proto_tree *opt_tree,
void * data _U_)
{
proto_tree *field_tree;
- proto_item *tf;
+ proto_item *tf, *tag_item;
guint tagtype, taglen;
int offset_max = offset + optlen;
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
- optp->name, optlen);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, *optp->subtree_index, &tf,
+ "%s (%u bytes)", optp->name, optlen);
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen > IPOLEN_MAX)
offset += 2;
- proto_tree_add_text(field_tree, tvb, offset, 4, "DOI: %u",
- tvb_get_ntohl(tvb, offset));
+ proto_tree_add_item(field_tree, hf_ip_cipso_doi, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
/* loop through all of the tags in the CIPSO option */
while (offset < offset_max) {
tagtype = tvb_get_guint8(tvb, offset);
+ tag_item = proto_tree_add_item(field_tree, hf_ip_cipso_tag_type, tvb, offset, 1, ENC_NA);
if ((offset + 1) < offset_max)
taglen = tvb_get_guint8(tvb, offset + 1);
/* restrictive bitmap, see CIPSO draft section 3.4.2 for tag format */
if ((taglen < 4) || (taglen > CIPSO_TAG_LEN_MAX) ||
((offset + (int)taglen - 1) > offset_max)) {
- proto_tree_add_text(field_tree, tvb, offset, offset_max - offset,
- "Malformed CIPSO tag");
+ expert_add_info(pinfo, tag_item, &ei_ip_cipso_tag);
return;
}
- proto_tree_add_text(field_tree, tvb, offset, 1,
- "Tag Type: Restrictive Category Bitmap (%u)",
- tagtype);
-
/* skip past alignment octet */
offset += 3;
- proto_tree_add_text(field_tree, tvb, offset, 1, "Sensitivity Level: %u",
- tvb_get_guint8(tvb, offset));
+ proto_tree_add_item(field_tree, hf_ip_cipso_sensitivity_level, tvb, offset, 1, ENC_NA);
offset += 1;
if (taglen > 4) {
}
if (cat_str)
- proto_tree_add_text(field_tree, tvb, offset, taglen - 4,
- "Categories: %s", cat_str);
+ proto_tree_add_string(field_tree, hf_ip_cipso_categories, tvb, offset, taglen - 4, cat_str);
else
- proto_tree_add_text(field_tree, tvb, offset, taglen - 4,
- "Categories: ERROR PARSING CATEGORIES");
+ proto_tree_add_string(field_tree, hf_ip_cipso_categories, tvb, offset, taglen - 4, "ERROR PARSING CATEGORIES");
offset += taglen - 4;
}
break;
/* enumerated categories, see CIPSO draft section 3.4.3 for tag format */
if ((taglen < 4) || (taglen > CIPSO_TAG_LEN_MAX) ||
((offset + (int)taglen - 1) > offset_max)) {
- proto_tree_add_text(field_tree, tvb, offset, offset_max - offset,
- "Malformed CIPSO tag");
+ expert_add_info(pinfo, tag_item, &ei_ip_cipso_tag);
return;
}
- proto_tree_add_text(field_tree, tvb, offset, 1,
- "Tag Type: Enumerated Categories (%u)", tagtype);
-
/* skip past alignment octet */
offset += 3;
/* sensitivity level */
- proto_tree_add_text(field_tree, tvb, offset, 1, "Sensitivity Level: %u",
- tvb_get_guint8(tvb, offset));
+ proto_tree_add_item(field_tree, hf_ip_cipso_sensitivity_level, tvb, offset, 1, ENC_NA);
offset += 1;
if (taglen > 4) {
g_strlcat(cat_str, cat_str_tmp, USHRT_MAX_STRLEN * 15);
}
- proto_tree_add_text(field_tree, tvb, offset - taglen + 4, taglen - 4,
- "Categories: %s", cat_str);
+ proto_tree_add_string(field_tree, hf_ip_cipso_categories, tvb, offset - taglen + 4, taglen - 4, cat_str);
}
break;
case 5:
/* ranged categories, see CIPSO draft section 3.4.4 for tag format */
if ((taglen < 4) || (taglen > CIPSO_TAG_LEN_MAX) ||
((offset + (int)taglen - 1) > offset_max)) {
- proto_tree_add_text(field_tree, tvb, offset, offset_max - offset,
- "Malformed CIPSO tag");
+ expert_add_info(pinfo, tag_item, &ei_ip_cipso_tag);
return;
}
- proto_tree_add_text(field_tree, tvb, offset, 1,
- "Tag Type: Ranged Categories (%u)", tagtype);
-
/* skip past alignment octet */
offset += 3;
/* sensitivity level */
- proto_tree_add_text(field_tree, tvb, offset, 1, "Sensitivity Level: %u",
- tvb_get_guint8(tvb, offset));
+ proto_tree_add_item(field_tree, hf_ip_cipso_sensitivity_level, tvb, offset, 1, ENC_NA);
offset += 1;
if (taglen > 4) {
g_strlcat(cat_str, cat_str_tmp, USHRT_MAX_STRLEN * 16);
}
- proto_tree_add_text(field_tree, tvb, offset - taglen + 4, taglen - 4,
- "Categories: %s", cat_str);
+ proto_tree_add_string(field_tree, hf_ip_cipso_categories, tvb, offset - taglen + 4, taglen - 4, cat_str);
}
break;
case 6:
/* permissive categories, see FIPS 188 section 6.9 for tag format */
if ((taglen < 4) || (taglen > CIPSO_TAG_LEN_MAX) ||
((offset + (int)taglen - 1) > offset_max)) {
- proto_tree_add_text(field_tree, tvb, offset, offset_max - offset,
- "Malformed CIPSO tag");
+ expert_add_info(pinfo, tag_item, &ei_ip_cipso_tag);
return;
}
- proto_tree_add_text(field_tree, tvb, offset, 1,
- "Tag Type: Permissive Categories (%u)", tagtype);
- proto_tree_add_text(field_tree, tvb, offset + 2, taglen - 2, "Tag data");
+ proto_tree_add_item(field_tree, hf_ip_cipso_tag_data, tvb, offset + 2, taglen - 2, ENC_NA);
offset += taglen;
break;
case 7:
/* free form, see FIPS 188 section 6.10 for tag format */
if ((taglen < 2) || (taglen > CIPSO_TAG_LEN_MAX) ||
((offset + (int)taglen - 1) > offset_max)) {
- proto_tree_add_text(field_tree, tvb, offset, offset_max - offset,
- "Malformed CIPSO tag");
+ expert_add_info(pinfo, tag_item, &ei_ip_cipso_tag);
return;
}
- proto_tree_add_text(field_tree, tvb, offset, 1,
- "Tag Type: Free Form (%u)", tagtype);
- proto_tree_add_text(field_tree, tvb, offset + 2, taglen - 2, "Tag data");
+ proto_tree_add_item(field_tree, hf_ip_cipso_tag_data, tvb, offset + 2, taglen - 2, ENC_NA);
offset += taglen;
break;
default:
/* unknown tag - stop parsing this IPv4 option */
if ((offset + 1) <= offset_max) {
taglen = tvb_get_guint8(tvb, offset + 1);
- proto_tree_add_text(field_tree, tvb, offset, 1,
- "Tag Type: Unknown (%u) (%u bytes)",
- tagtype, taglen);
+ proto_item_append_text(tag_item, " (%u bytes)", taglen);
return;
}
- proto_tree_add_text(field_tree, tvb, offset, 1,
- "Tag Type: Unknown (%u) (invalid format)", tagtype);
return;
}
}
if (next)
proto_tree_add_ipv4_format_value(tree, hf, tvb, offset, 4, route,
"%s <- (next)",
- ip_to_str((gchar *)&route));
+ tvb_ip_to_str(tvb, offset));
else
proto_tree_add_ipv4(tree, hf, tvb, offset, 4, route);
ti = proto_tree_add_string(tree, hf_host, tvb, offset, 4, get_hostname(route));
guint8 len, ptr;
int optoffset = 0;
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
- optp->name, optlen);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, *optp->subtree_index, NULL,
+ "%s (%u bytes)", optp->name, optlen);
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen > IPOLEN_MAX)
guint8 len, ptr;
int optoffset = 0;
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
- optp->name, optlen);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, *optp->subtree_index, NULL,
+ "%s (%u bytes)", optp->name, optlen);
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen > IPOLEN_MAX)
proto_tree *field_tree;
proto_item *tf;
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes): %u",
- optp->name, optlen, tvb_get_ntohs(tvb, offset + 2));
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, *optp->subtree_index, NULL,
+ "%s (%u bytes): %u", optp->name, optlen, tvb_get_ntohs(tvb, offset + 2));
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen != (guint)optp->optlen)
proto_tree *field_tree;
proto_item *tf;
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes): %u",
- optp->name, optlen, tvb_get_ntohs(tvb, offset + 2));
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, *optp->subtree_index, NULL,
+ "%s (%u bytes): %u", optp->name, optlen, tvb_get_ntohs(tvb, offset + 2));
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen != (guint)optp->optlen)
proto_tree *field_tree;
proto_item *tf;
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
- optp->name, optlen);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, *optp->subtree_index, NULL,
+ "%s (%u bytes)", optp->name, optlen);
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen != (guint)optp->optlen)
proto_tree_add_item(field_tree, hf_ip_opt_originator, tvb, offset + 8, 4, ENC_BIG_ENDIAN);
}
+static const value_string ipopt_timestamp_flag_vals[] = {
+ {IPOPT_TS_TSONLY, "Time stamps only" },
+ {IPOPT_TS_TSANDADDR, "Time stamp and address" },
+ {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
+ {0, NULL }};
+
static void
dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
int offset, guint optlen, packet_info *pinfo,
int ptr;
int optoffset = 0;
int flg;
- static const 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"},
- {0, NULL }};
guint32 addr;
- guint ts;
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
- optp->name, optlen);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, *optp->subtree_index, NULL,
+ "%s (%u bytes)", optp->name, optlen);
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen > IPOLEN_MAX)
optlen -= 2; /* subtract size of type and length */
ptr = tvb_get_guint8(tvb, offset + optoffset);
- proto_tree_add_text(field_tree, tvb, offset + optoffset, 1, "Pointer: %d%s",
+ proto_tree_add_uint_format_value(field_tree, hf_ip_opt_ptr, tvb, offset + optoffset, 1, ptr, "%d%s",
ptr, ((ptr == 1) ? " (header is full)" :
(ptr < 5) ? " (points before first address)" :
(((ptr - 1) & 3) ? " (points to middle of field)" : "")));
ptr--; /* ptr is 1-origin */
flg = tvb_get_guint8(tvb, offset + optoffset);
- proto_tree_add_text(field_tree, tvb, offset + optoffset, 1, "Overflow: %u",
- flg >> 4);
+ proto_tree_add_item(field_tree, hf_ip_opt_overflow, tvb, offset + optoffset, 1, ENC_NA);
flg &= 0xF;
- proto_tree_add_text(field_tree, tvb, offset + optoffset, 1, "Flag: %s",
- val_to_str(flg, flag_vals, "Unknown (0x%x)"));
+ proto_tree_add_item(field_tree, hf_ip_opt_flag, tvb, offset + optoffset, 1, ENC_NA);
optoffset++;
optlen--;
while (optlen > 0) {
if (flg == IPOPT_TS_TSANDADDR || flg == IPOPT_TS_PRESPEC) {
if (optlen < 8) {
- proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
- "(suboption would go past end of option)");
+ proto_tree_add_expert(field_tree, pinfo, &ei_ip_subopt_too_long, tvb, offset + optoffset, optlen);
break;
}
addr = tvb_get_ipv4(tvb, offset + optoffset);
- ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
- optlen -= 8;
- proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
- "Address = %s, time stamp = %u",
- ((addr == 0) ? "-" :
- get_hostname(addr)), ts);
- optoffset += 8;
+ proto_tree_add_ipv4_format_value(field_tree, hf_ip_opt_time_stamp_addr, tvb, offset + optoffset, 4, addr,
+ "%s", ((addr == 0) ? "-" : get_hostname(addr)));
+ optoffset += 4;
+ optlen -= 4;
+
+ proto_tree_add_item(field_tree, hf_ip_opt_time_stamp, tvb, offset + optoffset, 4, ENC_BIG_ENDIAN);
+ optoffset += 4;
+ optlen -= 4;
} else {
if (optlen < 4) {
- proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
- "(suboption would go past end of option)");
+ proto_tree_add_expert(field_tree, pinfo, &ei_ip_subopt_too_long, tvb, offset + optoffset, optlen);
break;
}
- ts = tvb_get_ntohl(tvb, offset + optoffset);
- optlen -= 4;
- proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
- "Time stamp = %u", ts);
+ proto_tree_add_item(field_tree, hf_ip_opt_time_stamp, tvb, offset + optoffset, 4, ENC_BIG_ENDIAN);
optoffset += 4;
+ optlen -= 4;
}
}
}
proto_item *tf;
guint16 value = tvb_get_ntohs(tvb, offset + 2);
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen,
- "%s (%u bytes): %s (%u)", optp->name, optlen,
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen,
+ *optp->subtree_index, NULL, "%s (%u bytes): %s (%u)", optp->name, optlen,
rval_to_str(value, ra_rvals, "Unknown (%u)"),
value);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen != (guint)optp->optlen)
proto_tree *field_tree;
proto_item *tf;
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
- optp->name, optlen);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, *optp->subtree_index, NULL,
+ "%s (%u bytes)", optp->name, optlen);
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen > IPOLEN_MAX)
static void
dissect_ipopt_qs(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
guint optlen, packet_info *pinfo, proto_tree *opt_tree,
- void * data _U_)
+ void * data)
{
proto_tree *field_tree;
proto_item *tf;
proto_item *ti;
+ ws_ip *iph = (ws_ip*)data;
guint8 command = tvb_get_guint8(tvb, offset + 2);
guint8 function = command >> 4;
guint8 rate = command & QS_RATE_MASK;
guint8 ttl_diff;
- tf = proto_tree_add_text(opt_tree, tvb, offset, optlen,
- "%s (%u bytes): %s (%u)", optp->name, optlen,
+ field_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen,
+ *optp->subtree_index, NULL, "%s (%u bytes): %s (%u)", optp->name, optlen,
val_to_str(function, qs_func_vals, "Unknown (%u)"),
function);
- field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
dissect_ipopt_type(tvb, offset, field_tree, &IP_OPT_TYPES);
- proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
+ tf = proto_tree_add_item(field_tree, hf_ip_opt_len, tvb, offset + 1, 1, ENC_NA);
if (optlen != (guint)optp->optlen)
expert_add_info(pinfo, tf, &ei_ip_opt_len_invalid);
proto_tree_add_item(field_tree, hf_ip_opt_qs_func, tvb, offset + 2, 1, ENC_NA);
if (function == QS_RATE_REQUEST) {
proto_tree_add_item(field_tree, hf_ip_opt_qs_rate, tvb, offset + 2, 1, ENC_NA);
proto_tree_add_item(field_tree, hf_ip_opt_qs_ttl, tvb, offset + 3, 1, ENC_NA);
- ttl_diff = (pinfo->ip_ttl - tvb_get_guint8(tvb, offset + 3) % 256);
+ ttl_diff = (iph->ip_ttl - tvb_get_guint8(tvb, offset + 3) % 256);
ti = proto_tree_add_uint_format_value(field_tree, hf_ip_opt_qs_ttl_diff,
tvb, offset + 3, 1, ttl_diff,
"%u", ttl_diff);
proto_item_append_text(tf, ", %s, QS TTL %u, QS TTL diff %u",
val_to_str_ext(rate, &qs_rate_vals_ext, "Unknown (%u)"),
tvb_get_guint8(tvb, offset + 3), ttl_diff);
- proto_tree_add_item(field_tree, hf_ip_opt_qs_nonce, tvb, offset + 4, 4, ENC_NA);
- proto_tree_add_item(field_tree, hf_ip_opt_qs_reserved, tvb, offset + 4, 4, ENC_NA);
+ proto_tree_add_item(field_tree, hf_ip_opt_qs_nonce, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ip_opt_qs_reserved, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
} else if (function == QS_RATE_REPORT) {
proto_tree_add_item(field_tree, hf_ip_opt_qs_rate, tvb, offset + 2, 1, ENC_NA);
proto_item_append_text(tf, ", %s",
val_to_str_ext(rate, &qs_rate_vals_ext, "Unknown (%u)"));
proto_tree_add_item(field_tree, hf_ip_opt_qs_unused, tvb, offset + 3, 1, ENC_NA);
- proto_tree_add_item(field_tree, hf_ip_opt_qs_nonce, tvb, offset + 4, 4, ENC_NA);
- proto_tree_add_item(field_tree, hf_ip_opt_qs_reserved, tvb, offset + 4, 4, ENC_NA);
+ proto_tree_add_item(field_tree, hf_ip_opt_qs_nonce, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ip_opt_qs_reserved, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
}
}
return;
} else {
if (optp == NULL) {
- proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
+ proto_tree_add_subtree_format(opt_tree, tvb, offset, len, ett_unknown_ip_tcp_opt, NULL, "%s (%u byte%s)",
name, len, plurality(len, "", "s"));
} else {
if (dissect != NULL) {
(*dissect)(optp, tvb, offset, len, pinfo, opt_tree, data);
} else {
proto_tree *field_tree;
- proto_item *tf;
/* Option has no data, hence no dissector. */
proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s",
name);
- tf = proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
- field_tree = proto_item_add_subtree(tf, ett_ip_option_other);
+ field_tree = proto_tree_add_subtree(opt_tree, tvb, offset, len, ett_ip_option_other, NULL, name);
dissect_ipopt_type(tvb, offset, field_tree, opttypes);
}
}
(*dissect)(optp, tvb, offset, 1, pinfo, opt_tree, data);
} else {
proto_tree *field_tree;
- proto_item *tf;
/* Option has no data, hence no dissector. */
proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", name);
- tf = proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
- field_tree = proto_item_add_subtree(tf, ett_ip_option_other);
+ field_tree = proto_tree_add_subtree(opt_tree, tvb, offset, 1, ett_ip_option_other, NULL, name);
dissect_ipopt_type(tvb, offset, field_tree, opttypes);
}
offset += 1;
"Not evil"
};
-guint16
-ip_checksum(const guint8 *ptr, int len)
+gboolean
+ip_try_dissect(gboolean heur_first, tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, ws_ip *iph)
{
- vec_t cksum_vec[1];
+ heur_dtbl_entry_t *hdtbl_entry;
+
+ if ((heur_first) && (dissector_try_heuristic(heur_subdissector_list, tvb,
+ pinfo, tree, &hdtbl_entry, iph))) {
+ return TRUE;
+ }
- cksum_vec[0].ptr = ptr;
- cksum_vec[0].len = len;
- return in_cksum(&cksum_vec[0], 1);
+ if (dissector_try_uint_new(ip_dissector_table, iph->ip_p, tvb, pinfo,
+ tree, TRUE, iph)) {
+ return TRUE;
+ }
+
+ if ((!heur_first) && (!dissector_try_heuristic(heur_subdissector_list, tvb,
+ pinfo, tree, &hdtbl_entry,
+ iph))) {
+ return TRUE;
+ }
+
+ return FALSE;
}
static void
-dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+dissect_ip_v4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
- proto_tree *ip_tree = NULL, *field_tree = NULL;
- proto_item *ti = NULL, *tf;
+ proto_tree *ip_tree, *field_tree = NULL;
+ proto_item *ti, *tf;
guint32 addr;
int offset = 0, dst_off;
guint hlen, optlen;
guint16 flags;
- guint8 nxt;
guint16 ipsum;
+ guint16 expected_cksum;
fragment_head *ipfd_head = NULL;
tvbuff_t *next_tvb;
gboolean update_col_info = TRUE;
gboolean save_fragmented;
ws_ip *iph;
- const guchar *src_addr, *dst_addr;
guint32 src32, dst32;
proto_tree *tree;
proto_item *item = NULL, *ttl_item;
col_clear(pinfo->cinfo, COL_INFO);
iph->ip_v_hl = tvb_get_guint8(tvb, offset);
- if ( hi_nibble(iph->ip_v_hl) == 6) {
- call_dissector(ipv6_handle, tvb, pinfo, parent_tree);
- return;
- }
hlen = lo_nibble(iph->ip_v_hl) * 4; /* IP header length, in bytes */
- if (tree) {
- ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, ENC_NA);
- ip_tree = proto_item_add_subtree(ti, ett_ip);
+ ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, ENC_NA);
+ ip_tree = proto_item_add_subtree(ti, ett_ip);
- proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1,
- hi_nibble(iph->ip_v_hl));
- }
+ proto_tree_add_item(ip_tree, hf_ip_version, tvb, offset, 1, ENC_NA);
/* if IP is not referenced from any filters we don't need to worry about
generating any tree items. We must do this after we created the actual
col_add_fstr(pinfo->cinfo, COL_INFO,
"Bogus IP header length (%u, must be at least %u)",
hlen, IPH_MIN_LEN);
- if (tree) {
- proto_tree_add_uint_format_value(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
+
+ proto_tree_add_uint_format_value(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
"%u bytes (bogus, must be at least %u)", hlen, IPH_MIN_LEN);
- }
return;
}
- if (tree) {
- proto_tree_add_uint_format_value(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
+ proto_tree_add_uint_format_value(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen/4,
"%u bytes", hlen);
- }
iph->ip_tos = tvb_get_guint8(tvb, offset + 1);
if (g_ip_dscp_actif) {
}
iph->ip_ttl = tvb_get_guint8(tvb, offset + 8);
- pinfo->ip_ttl = iph->ip_ttl;
if (tree) {
ttl_item = proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
} else {
* checksum.
*/
if (ip_check_checksum && tvb_bytes_exist(tvb, offset, hlen)&&(!pinfo->flags.in_error_pkt)) {
- ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
+ ipsum = ip_checksum_tvb(tvb, offset, hlen);
if (tree) {
if (ipsum == 0) {
item = proto_tree_add_uint_format_value(ip_tree, hf_ip_checksum, tvb,
"0x%04x [correct]",
iph->ip_sum);
checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
+ item = proto_tree_add_uint(checksum_tree, hf_ip_checksum_calculated, tvb,
+ offset + 10, 2, iph->ip_sum);
+ PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb,
offset + 10, 2, TRUE);
PROTO_ITEM_SET_GENERATED(item);
offset + 10, 2, FALSE);
PROTO_ITEM_SET_GENERATED(item);
} else {
+ expected_cksum = in_cksum_shouldbe(iph->ip_sum, ipsum);
+
item = proto_tree_add_uint_format_value(ip_tree, hf_ip_checksum, tvb,
offset + 10, 2, iph->ip_sum,
"0x%04x"
"[incorrect, should be 0x%04x "
"(may be caused by \"IP checksum "
"offload\"?)]", iph->ip_sum,
- in_cksum_shouldbe(iph->ip_sum,
- ipsum));
+ expected_cksum);
checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
+ item = proto_tree_add_uint(checksum_tree, hf_ip_checksum_calculated, tvb,
+ offset + 10, 2, expected_cksum);
+ PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb,
offset + 10, 2, FALSE);
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_GENERATED(item);
}
}
- src_addr = tvb_get_ptr(tvb, offset + IPH_SRC, 4);
src32 = tvb_get_ntohl(tvb, offset + IPH_SRC);
- SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, src_addr);
- SET_ADDRESS(&pinfo->src, AT_IPv4, 4, src_addr);
- SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, src_addr);
+ TVB_SET_ADDRESS(&pinfo->net_src, AT_IPv4, tvb, offset + IPH_SRC, 4);
+ COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src);
+ COPY_ADDRESS_SHALLOW(&iph->ip_src, &pinfo->src);
if (tree) {
const char *src_host;
memcpy(&addr, iph->ip_src.data, 4);
src_host = get_hostname(addr);
if (ip_summary_in_tree) {
- proto_item_append_text(ti, ", Src: %s (%s)", src_host,
- ip_to_str((guint8 *)iph->ip_src.data));
+ proto_item_append_text(ti, ", Src: %s", address_with_resolution_to_str(wmem_packet_scope(), &iph->ip_src));
}
proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
item = proto_tree_add_ipv4(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
else
dst_off = 0;
- dst_addr = tvb_get_ptr(tvb, offset + IPH_DST + dst_off, 4);
dst32 = tvb_get_ntohl(tvb, offset + IPH_DST + dst_off);
- SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, dst_addr);
- SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, dst_addr);
- SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, dst_addr);
+ TVB_SET_ADDRESS(&pinfo->net_dst, AT_IPv4, tvb, offset + IPH_DST + dst_off, 4);
+ COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst);
+ COPY_ADDRESS_SHALLOW(&iph->ip_dst, &pinfo->net_dst);
/* If an IP is destined for an IP address in the Local Network Control Block
* (e.g. 224.0.0.0/24), the packet should never be routed and the TTL would
"Local Network Control Block (see RFC 3171)",
ttl);
}
- } else if (!is_a_multicast_addr(dst32) && iph->ip_ttl < 5 &&
- (iph->ip_p != IP_PROTO_PIM)) {
+ } else if (!is_a_multicast_addr(dst32) &&
+ /* At least BGP should appear here as well */
+ iph->ip_ttl < 5 &&
+ iph->ip_p != IP_PROTO_PIM &&
+ iph->ip_p != IP_PROTO_OSPF) {
expert_add_info_format(pinfo, ttl_item, &ei_ip_ttl_too_small, "\"Time To Live\" only %u", iph->ip_ttl);
}
if (tree) {
const char *dst_host;
- guint32 cur_rt;
memcpy(&addr, iph->ip_dst.data, 4);
dst_host = get_hostname(addr);
- if (dst_off)
- cur_rt = tvb_get_ipv4(tvb, offset + 16);
if (ip_summary_in_tree) {
- proto_item_append_text(ti, ", Dst: %s (%s)", dst_host,
- ip_to_str((guint8 *)iph->ip_dst.data));
- if (dst_off)
- proto_item_append_text(ti, ", Via: %s (%s)", get_hostname(cur_rt),
- ip_to_str((gchar *)&cur_rt));
+ proto_item_append_text(ti, ", Dst: %s", address_with_resolution_to_str(wmem_packet_scope(), &iph->ip_dst));
}
if (dst_off) {
+ guint32 cur_rt;
+
+ cur_rt = tvb_get_ipv4(tvb, offset + 16);
+ if (ip_summary_in_tree) {
+ proto_item_append_text(ti, ", Via: %s",
+ tvb_address_with_resolution_to_str(wmem_packet_scope(), tvb, AT_IPv4, offset + 16));
+ }
proto_tree_add_ipv4(ip_tree, hf_ip_cur_rt, tvb, offset + 16, 4, cur_rt);
item = proto_tree_add_string(ip_tree, hf_ip_cur_rt_host, tvb,
offset + 16, 4, get_hostname(cur_rt));
if (hlen > IPH_MIN_LEN) {
/* There's more than just the fixed-length header. Decode the options. */
optlen = hlen - IPH_MIN_LEN; /* length of options, in bytes */
- tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
- "Options: (%u bytes)", optlen);
- field_tree = proto_item_add_subtree(tf, ett_ip_options);
+ field_tree = proto_tree_add_subtree_format(ip_tree, tvb, offset + 20, optlen,
+ ett_ip_options, &tf, "Options: (%u bytes)", optlen);
dissect_ip_tcp_options(tvb, offset + 20, optlen, ipopts, N_IP_OPTS,
- IPOPT_EOOL, &IP_OPT_TYPES, &ei_ip_opt_len_invalid, pinfo, field_tree, tf, NULL);
+ IPOPT_EOOL, &IP_OPT_TYPES, &ei_ip_opt_len_invalid, pinfo, field_tree, tf, iph);
}
- pinfo->ipproto = iph->ip_p;
- pinfo->iplen = iph->ip_len;
- pinfo->iphdrlen = hlen;
+ p_add_proto_data(pinfo->pool, pinfo, proto_ip, 0, GUINT_TO_POINTER((guint)iph->ip_p));
tap_queue_packet(ip_tap, pinfo, iph);
/* Skip over header + options */
offset += hlen;
- nxt = iph->ip_p; /* XXX - what if this isn't the same for all fragments? */
/* If ip_defragment is on, this is a fragment, we have all the data
* in the fragment, and the header checksum is valid, then just add
*/
save_fragmented = pinfo->fragmented;
if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
- tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
+ tvb_bytes_exist(tvb, offset, iph->ip_len - hlen) &&
ipsum == 0) {
ipfd_head = fragment_add_check(&ip_reassembly_table, tvb, offset,
pinfo,
iph->ip_p ^ iph->ip_id ^ src32 ^ dst32,
NULL,
(iph->ip_off & IP_OFFSET) * 8,
- pinfo->iplen - pinfo->iphdrlen,
+ iph->ip_len - hlen,
iph->ip_off & IP_MF);
next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
return;
}
- /* XXX This is an ugly hack because I didn't manage to make the IPIP
- * dissector a heuristic one [JMayer]
- * The TAPA protocol also uses IP protocol number 4 but it isn't really
- * IPIP, so try to detect it first and call it explicitly before calling
- * the generic ip.proto dispatcher
- */
- if (nxt == IP_PROTO_IPIP && (tvb_get_guint8(next_tvb, 0) & 0xF0) != 0x40 &&
- tvb_get_ntohs(next_tvb, 2) < 20) {
- call_dissector(tapa_handle,next_tvb, pinfo, parent_tree);
-
+ if (tvb_reported_length(next_tvb) > 0) {
/* Hand off to the next protocol.
XXX - setting the columns only after trying various dissectors means
even be labeled as an IP frame; ideally, if a frame being dissected
throws an exception, it'll be labeled as a mangled frame of the
type in question. */
- } else if ((try_heuristic_first) && (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, NULL))) {
- /* We're good */
- } else if (!dissector_try_uint(ip_dissector_table, nxt, next_tvb, pinfo,
- parent_tree)) {
- if ((!try_heuristic_first) && (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, NULL))) {
+ if (!ip_try_dissect(try_heuristic_first, next_tvb, pinfo, parent_tree, iph)) {
/* Unknown protocol */
if (update_col_info) {
col_add_fstr(pinfo->cinfo, COL_INFO, "%s (%u)",
pinfo->fragmented = save_fragmented;
}
+static void
+dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ip_tree;
+ proto_item *ti, *tf;
+ guint8 version;
+
+ version = tvb_get_guint8(tvb, 0) >> 4;
+
+ if(version == 4){
+ dissect_ip_v4(tvb, pinfo, tree);
+ return;
+ }
+ if(version == 6){
+ call_dissector(ipv6_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ /* Bogus IP version */
+ ti = proto_tree_add_protocol_format(tree, proto_ip, tvb, 0, 1, "Internet Protocol, bogus version (%u)", version);
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP version (%u)", version);
+ ip_tree = proto_item_add_subtree(ti, ett_ip);
+ tf = proto_tree_add_item(ip_tree, hf_ip_version, tvb, 0, 1, ENC_NA);
+ expert_add_info(pinfo, tf, &ei_ip_bogus_ip_version);
+}
+
static gboolean
dissect_ip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
- length = tvb_length(tvb);
+ length = tvb_captured_length(tvb);
if(length<4){
/* Need at least 4 bytes to make some sort of decision */
return FALSE;
ihl = oct & 0x0f;
version = oct >> 4;
if(version == 6){
- /* TODO: Add IPv6 checks here */
/*
3. IPv6 Header Format
return FALSE;
}
- dissect_ip(tvb, pinfo, tree);
+ dissect_ip_v4(tvb, pinfo, tree);
return TRUE;
}
static hf_register_info hf[] = {
{ &hf_ip_version,
{ "Version", "ip.version", FT_UINT8, BASE_DEC,
- NULL, 0x0, NULL, HFILL }},
+ NULL, 0xF0, NULL, HFILL }},
{ &hf_ip_hdr_len,
{ "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC,
- NULL, 0x0, NULL, HFILL }},
+ NULL, 0x0F, NULL, HFILL }},
{ &hf_ip_dsfield,
{ "Differentiated Services Field", "ip.dsfield", FT_UINT8, BASE_DEC,
#ifdef HAVE_GEOIP
{ &hf_geoip_country,
{ "Source or Destination GeoIP Country", "ip.geoip.country",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_city,
{ "Source or Destination GeoIP City", "ip.geoip.city",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_org,
{ "Source or Destination GeoIP Organization", "ip.geoip.org",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_isp,
{ "Source or Destination GeoIP ISP", "ip.geoip.isp",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_asnum,
{ "Source or Destination GeoIP AS Number", "ip.geoip.asnum",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_lat,
{ "Source or Destination GeoIP Latitude", "ip.geoip.lat",
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_country,
{ "Source GeoIP Country", "ip.geoip.src_country",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_city,
{ "Source GeoIP City", "ip.geoip.src_city",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_org,
{ "Source GeoIP Organization", "ip.geoip.src_org",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_isp,
{ "Source GeoIP ISP", "ip.geoip.src_isp",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_asnum,
{ "Source GeoIP AS Number", "ip.geoip.src_asnum",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_src_lat,
{ "Source GeoIP Latitude", "ip.geoip.src_lat",
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_country,
{ "Destination GeoIP Country", "ip.geoip.dst_country",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_city,
{ "Destination GeoIP City", "ip.geoip.dst_city",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_org,
{ "Destination GeoIP Organization", "ip.geoip.dst_org",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_isp,
{ "Destination GeoIP ISP", "ip.geoip.dst_isp",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_asnum,
{ "Destination GeoIP AS Number", "ip.geoip.dst_asnum",
- FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL }},
{ &hf_geoip_dst_lat,
{ "Destination GeoIP Latitude", "ip.geoip.dst_lat",
FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX,
NULL, 0x0, NULL, HFILL }},
+ { &hf_ip_checksum_calculated,
+ { "Calculated Checksum", "ip.checksum_calculated", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "The expected IP checksum field as calculated from the IP datagram", HFILL }},
+
{ &hf_ip_checksum_good,
{ "Good", "ip.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
{ "Empty Route Host", "ip.empty_rt_host", FT_STRING, BASE_NONE,
NULL, 0x0, NULL, HFILL }},
+ { &hf_ip_cipso_tag_type,
+ { "Tag Type", "ip.cipso.tag_type", FT_UINT8, BASE_DEC,
+ VALS(cipso_tag_type_vals), 0x0, NULL, HFILL }},
+
+
{ &hf_ip_fragment_overlap,
{ "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE,
NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
{ &hf_ip_reassembled_data,
{ "Reassembled IPv4 data", "ip.reassembled.data", FT_BYTES, BASE_NONE,
- NULL, 0x0, "The reassembled payload", HFILL }}
+ NULL, 0x0, "The reassembled payload", HFILL }},
+
+ /* Generated from convert_proto_tree_add_text.pl */
+ { &hf_ip_cipso_doi, { "DOI", "ip.cipso.doi", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_ip_cipso_sensitivity_level, { "Sensitivity Level", "ip.cipso.sensitivity_level", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_ip_cipso_categories, { "Categories", "ip.cipso.categories", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_ip_cipso_tag_data, { "Tag data", "ip.cipso.tag_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_ip_opt_overflow, { "Overflow", "ip.opt.overflow", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
+ { &hf_ip_opt_flag, { "Flag", "ip.opt.flag", FT_UINT8, BASE_HEX, VALS(ipopt_timestamp_flag_vals), 0x0F, NULL, HFILL }},
+ { &hf_ip_opt_time_stamp, { "Time stamp", "ip.opt.time_stamp", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_ip_opt_time_stamp_addr, { "Address", "ip.opt.time_stamp_addr", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+
};
static gint *ett[] = {
&ett_ip_checksum,
&ett_ip_opt_type,
&ett_ip_opt_sec_prot_auth_flags,
+ &ett_unknown_ip_tcp_opt,
#ifdef HAVE_GEOIP
&ett_geoip_info
#endif
{ &ei_ip_checksum_bad, { "ip.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
{ &ei_ip_ttl_lncb, { "ip.ttl.lncb", PI_SEQUENCE, PI_NOTE, "Time To Live", EXPFILL }},
{ &ei_ip_ttl_too_small, { "ip.ttl.too_small", PI_SEQUENCE, PI_NOTE, "Time To Live", EXPFILL }},
+ { &ei_ip_cipso_tag, { "ip.cipso.malformed", PI_SEQUENCE, PI_ERROR, "Malformed CIPSO tag", EXPFILL }},
+ { &ei_ip_bogus_ip_version, { "ip.bogus_ip_version", PI_PROTOCOL, PI_ERROR, "Bogus IP version", EXPFILL }},
};
+ /* Decode As handling */
+ static build_valid_func ip_da_build_value[1] = {ip_value};
+ static decode_as_value_t ip_da_values = {ip_prompt, 1, ip_da_build_value};
+ static decode_as_t ip_da = {"ip", "Network", "ip.proto", 1, 0, &ip_da_values, NULL, NULL,
+ decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
+
module_t *ip_module;
expert_module_t* expert_ip;
expert_register_field_array(expert_ip, ei, array_length(ei));
/* subdissector code */
- ip_dissector_table = register_dissector_table("ip.proto", "IPv4 protocol",
+ ip_dissector_table = register_dissector_table("ip.proto", "IP protocol",
FT_UINT8, BASE_DEC);
- register_heur_dissector_list("ip", &heur_subdissector_list);
+ heur_subdissector_list = register_heur_dissector_list("ip");
/* Register configuration options */
ip_module = prefs_register_protocol(proto_ip, NULL);
register_dissector("ip", dissect_ip, proto_ip);
register_init_routine(ip_defragment_init);
+ register_cleanup_routine(ip_defragment_cleanup);
ip_tap = register_tap("ip");
+
+ register_decode_as(&ip_da);
+ register_conversation_table(proto_ip, TRUE, ip_conversation_packet, ip_hostlist_packet);
+ register_color_conversation_filter("ip", "IPv4", ip_color_filter_valid, ip_build_color_filter);
}
void
ip_handle = find_dissector("ip");
ipv6_handle = find_dissector("ipv6");
- tapa_handle = find_dissector("tapa");
data_handle = find_dissector("data");
dissector_add_uint("ethertype", ETHERTYPE_IP, ip_handle);
+ dissector_add_uint("erf.types.type", ERF_TYPE_IPV4, ip_handle);
dissector_add_uint("ppp.protocol", PPP_IP, ip_handle);
dissector_add_uint("ppp.protocol", ETHERTYPE_IP, ip_handle);
dissector_add_uint("gre.proto", ETHERTYPE_IP, ip_handle);
dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_IP_1051, ip_handle);
dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_IP_1201, ip_handle);
dissector_add_uint("ax25.pid", AX25_P_IP, ip_handle);
- dissector_add_handle("udp.port", ip_handle);
-
- heur_dissector_add("tipc", dissect_ip_heur, proto_ip);
+ dissector_add_uint("juniper.proto", JUNIPER_PROTO_IP, ip_handle);
+ dissector_add_uint("juniper.proto", JUNIPER_PROTO_MPLS_IP, ip_handle);
+ dissector_add_uint("pwach.channel_type", 0x21, ip_handle); /* IPv4, RFC4385 clause 6. */
+ dissector_add_uint("sflow_245.header_protocol", SFLOW_245_HEADER_IPv4, ip_handle);
+ dissector_add_uint("l2tp.pw_type", L2TPv3_PROTOCOL_IP, ip_handle);
+ dissector_add_for_decode_as("udp.port", ip_handle);
+ dissector_add_for_decode_as("pcli.payload", ip_handle);
+ dissector_add_uint("wtap_encap", WTAP_ENCAP_RAW_IP4, ip_handle);
+
+ heur_dissector_add("tipc", dissect_ip_heur, "IP over TIPC", "ip_tipc", proto_ip, HEURISTIC_ENABLE);
}
/*
* vi: set shiftwidth=2 tabstop=8 expandtab:
* :indentSize=2:tabSize=8:noTabs=true:
*/
-