OSPF database packets and OSPF hellos in DC mode are unicast. At
[metze/wireshark/wip.git] / epan / dissectors / packet-ip.c
index a1f8dec434763285e651838875b19adb0874f114..b6b8ab85f7d7a02ab1bcb5cf028c234f0e64141b 100644 (file)
@@ -27,9 +27,6 @@
 
 #include "config.h"
 
-#include <string.h>
-#include <glib.h>
-
 #include <epan/packet.h>
 #include <epan/addr_resolv.h>
 #include <epan/ipproto.h>
@@ -37,9 +34,9 @@
 #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-juniper.h"
+#include "packet-sflow.h"
+#include "packet-gre.h"
+#include "packet-l2tp.h"
 
 #ifdef HAVE_GEOIP
 #include <GeoIP.h>
@@ -258,6 +256,7 @@ 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
@@ -481,12 +480,13 @@ static dissector_handle_t data_handle;
 
 static void ip_prompt(packet_info *pinfo, gchar* result)
 {
-    g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IP protocol %u as", pinfo->ipproto);
+    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 GUINT_TO_POINTER(pinfo->ipproto);
+    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)
@@ -540,6 +540,20 @@ ip_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const
     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
  */
@@ -552,6 +566,12 @@ ip_defragment_init(void)
                         &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)) {
@@ -596,7 +616,7 @@ add_geoip_info_entry(proto_tree *geoip_info_tree, proto_item *geoip_info_item, t
   guint dbnum;
 
   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;
@@ -662,6 +682,7 @@ add_geoip_info_entry(proto_tree *geoip_info_tree, proto_item *geoip_info_item, t
       item_cnt++;
       proto_item_append_text(geoip_info_item, "%s%s",
                              plurality(item_cnt, "", ", "), geoip_str);
+      wmem_free(NULL, geoip_str);
     }
   }
 
@@ -1155,7 +1176,7 @@ dissect_option_route(proto_tree *tree, tvbuff_t *tvb, int offset, int hf,
   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));
@@ -1937,8 +1958,33 @@ static const true_false_string flags_sf_set_evil = {
   "Not evil"
 };
 
+gboolean
+ip_try_dissect(gboolean heur_first, tvbuff_t *tvb, packet_info *pinfo,
+               proto_tree *tree, ws_ip *iph)
+{
+  heur_dtbl_entry_t *hdtbl_entry;
+
+  if ((heur_first) && (dissector_try_heuristic(heur_subdissector_list, tvb,
+                       pinfo, tree, &hdtbl_entry, iph))) {
+    return TRUE;
+  }
+
+  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, *field_tree = NULL;
   proto_item *ti, *tf;
@@ -1946,7 +1992,6 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
   int        offset = 0, dst_off;
   guint      hlen, optlen;
   guint16    flags;
-  guint8     nxt;
   guint16    ipsum;
   guint16    expected_cksum;
   fragment_head *ipfd_head = NULL;
@@ -1954,13 +1999,11 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
   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;
   proto_tree *checksum_tree;
   guint16 ttl;
-  heur_dtbl_entry_t *hdtbl_entry;
 
   tree = parent_tree;
   iph = (ws_ip *)wmem_alloc(wmem_packet_scope(), sizeof(ws_ip));
@@ -1969,10 +2012,6 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
   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 */
 
@@ -2210,19 +2249,17 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
       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((const 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);
@@ -2254,11 +2291,10 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
   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
@@ -2275,28 +2311,31 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
                              "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((const 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));
@@ -2335,12 +2374,11 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
                            IPOPT_EOOL, &IP_OPT_TYPES, &ei_ip_opt_len_invalid, pinfo, field_tree, tf, iph);
   }
 
-  pinfo->ipproto = iph->ip_p;
+  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
@@ -2404,6 +2442,7 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
     return;
   }
 
+  if (tvb_reported_length(next_tvb) > 0) {
     /* Hand off to the next protocol.
 
      XXX - setting the columns only after trying various dissectors means
@@ -2411,11 +2450,7 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
      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. */
-  if ((try_heuristic_first) && (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, iph))) {
-    /* We're good */
-  } else if (!dissector_try_uint_new(ip_dissector_table, nxt, next_tvb, pinfo,
-                                 parent_tree, TRUE, iph)) {
-    if ((!try_heuristic_first) && (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, iph))) {
+    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)",
@@ -2427,6 +2462,34 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
   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_)
 {
@@ -2441,7 +2504,7 @@ dissect_ip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 */
-    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;
@@ -2450,7 +2513,6 @@ dissect_ip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
     ihl = oct & 0x0f;
     version = oct >> 4;
     if(version == 6){
-        /* TODO: Add IPv6 checks here */
 /*
     3.  IPv6 Header Format
 
@@ -2517,7 +2579,7 @@ dissect_ip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
         return FALSE;
     }
 
-    dissect_ip(tvb, pinfo, tree);
+    dissect_ip_v4(tvb, pinfo, tree);
     return TRUE;
 }
 
@@ -3014,6 +3076,7 @@ proto_register_ip(void)
      { &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 */
@@ -3034,7 +3097,7 @@ proto_register_ip(void)
   /* subdissector code */
   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);
@@ -3073,10 +3136,12 @@ proto_register_ip(void)
 
   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, NULL);
+  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
@@ -3106,9 +3171,14 @@ proto_reg_handoff_ip(void)
   dissector_add_uint("ax25.pid", AX25_P_IP, ip_handle);
   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, proto_ip);
+  heur_dissector_add("tipc", dissect_ip_heur, "IP over TIPC", "ip_tipc", proto_ip, HEURISTIC_ENABLE);
 }
 
 /*
@@ -3123,4 +3193,3 @@ proto_reg_handoff_ip(void)
  * vi: set shiftwidth=2 tabstop=8 expandtab:
  * :indentSize=2:tabSize=8:noTabs=true:
  */
-