diff options
Diffstat (limited to 'epan/dissectors/packet-ipv6.c')
-rw-r--r-- | epan/dissectors/packet-ipv6.c | 2355 |
1 files changed, 2039 insertions, 316 deletions
diff --git a/epan/dissectors/packet-ipv6.c b/epan/dissectors/packet-ipv6.c index 03969772d4..9c1afe0ece 100644 --- a/epan/dissectors/packet-ipv6.c +++ b/epan/dissectors/packet-ipv6.c @@ -24,6 +24,7 @@ #include <epan/addr_resolv.h> #include <epan/maxmind_db.h> #include <epan/prefs.h> +#include <epan/uat.h> #include <epan/conversation_table.h> #include <epan/conversation_filter.h> #include <epan/reassemble.h> @@ -36,6 +37,9 @@ #include <epan/decode_as.h> #include <epan/proto_data.h> #include <epan/to_str.h> +#include <epan/exported_pdu.h> +#include <epan/exceptions.h> +#include <epan/iana-ip.h> #include <wiretap/erf_record.h> #include <wsutil/str_util.h> @@ -66,13 +70,16 @@ void proto_reg_handoff_ipv6(void); #define IP6OPT_CALIPSO 0x07 /* 00 0 00111 = 7 */ #define IP6OPT_SMF_DPD 0x08 /* 00 0 01000 = 8 */ #define IP6OPT_PDM 0x0F /* 00 0 01111 = 15 */ +#define IP6OPT_APN6 0x13 /* 00 0 10003 = 19 */ #define IP6OPT_EXP_1E 0x1E /* 00 0 11110 = 30 */ +#define IP6OPT_RPL 0x23 /* 00 1 00011 = 35 */ #define IP6OPT_QUICKSTART 0x26 /* 00 1 00110 = 38 */ #define IP6OPT_PMTU 0x30 /* 00 1 10000 = 48 */ +#define IP6OPT_IOAM 0x31 /* 00 1 10001 = 49 */ #define IP6OPT_EXP_3E 0x3E /* 00 1 11110 = 62 */ #define IP6OPT_TPF 0x41 /* 01 0 00001 = 65 */ #define IP6OPT_EXP_5E 0x5E /* 01 0 11110 = 94 */ -#define IP6OPT_RPL 0x63 /* 01 1 00011 = 99 */ +#define IP6OPT_RPL_OLD 0x63 /* 01 1 00011 = 99 */ /* DEPRECATED */ #define IP6OPT_MPL 0x6D /* 01 1 01101 = 109 */ #define IP6OPT_EXP_7E 0x7E /* 01 1 11110 = 126 */ #define IP6OPT_ENDI 0x8A /* 10 0 01010 = 138 */ /* DEPRECATED */ @@ -96,250 +103,455 @@ void proto_reg_handoff_ipv6(void); #define IP6RRPL_BITMASK_PAD 0x00F00000 #define IP6RRPL_BITMASK_RESERVED 0x000FFFFF +/* IOAM Option-Types */ +#define IP6IOAM_PRE_TRACE 0 /* Pre-allocated Trace */ +#define IP6IOAM_INC_TRACE 1 /* Incremental Trace */ +#define IP6IOAM_POT 2 /* Proof of Transit */ +#define IP6IOAM_E2E 3 /* Edge to Edge */ + +/* IOAM Trace Types */ +#define IP6IOAM_TRACE_MASK_BIT0 (1 << 23) /* Hop_lim + Node ID */ +#define IP6IOAM_TRACE_MASK_BIT1 (1 << 22) /* Ingress and Egress IDs */ +#define IP6IOAM_TRACE_MASK_BIT2 (1 << 21) /* Timestamp seconds */ +#define IP6IOAM_TRACE_MASK_BIT3 (1 << 20) /* Timestamp fraction */ +#define IP6IOAM_TRACE_MASK_BIT4 (1 << 19) /* Transit delay */ +#define IP6IOAM_TRACE_MASK_BIT5 (1 << 18) /* IOAM-Namespace data */ +#define IP6IOAM_TRACE_MASK_BIT6 (1 << 17) /* Queue depth */ +#define IP6IOAM_TRACE_MASK_BIT7 (1 << 16) /* Checksum complement */ +#define IP6IOAM_TRACE_MASK_BIT8 (1 << 15) /* (wide) Hop_lim + Node ID */ +#define IP6IOAM_TRACE_MASK_BIT9 (1 << 14) /* (wide) Ingress and Egress IDs */ +#define IP6IOAM_TRACE_MASK_BIT10 (1 << 13) /* (wide) IOAM-Namespace data */ +#define IP6IOAM_TRACE_MASK_BIT11 (1 << 12) /* Buffer occupancy */ +#define IP6IOAM_TRACE_MASK_BIT12 (1 << 11) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT13 (1 << 10) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT14 (1 << 9) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT15 (1 << 8) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT16 (1 << 7) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT17 (1 << 6) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT18 (1 << 5) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT19 (1 << 4) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT20 (1 << 3) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT21 (1 << 2) /* Undefined */ +#define IP6IOAM_TRACE_MASK_BIT22 (1 << 1) /* Opaque state snapshot */ + /* Protocol specific data indices */ #define IPV6_PROTO_VALUE 1 #define IPV6_PROTO_PINFO 2 -static int ipv6_tap = -1; - -static int proto_ipv6 = -1; -static int proto_ipv6_hopopts = -1; -static int proto_ipv6_routing = -1; -static int proto_ipv6_fraghdr = -1; -static int proto_ipv6_dstopts = -1; - -static int proto_ipv6_routing_rt0 = -1; -static int proto_ipv6_routing_mipv6 = -1; -static int proto_ipv6_routing_rpl = -1; -static int proto_ipv6_routing_srh = -1; -static int proto_ipv6_routing_crh = -1; - -static int hf_ipv6_version = -1; -static int hf_ip_version = -1; -static int hf_ipv6_tclass = -1; -static int hf_ipv6_tclass_dscp = -1; -static int hf_ipv6_tclass_ecn = -1; -static int hf_ipv6_flow = -1; -static int hf_ipv6_plen = -1; -static int hf_ipv6_nxt = -1; -static int hf_ipv6_hlim = -1; -static int hf_ipv6_src = -1; -static int hf_ipv6_src_host = -1; -static int hf_ipv6_src_slaac_mac = -1; -static int hf_ipv6_src_isatap_ipv4 = -1; -static int hf_ipv6_src_6to4_gateway_ipv4 = -1; -static int hf_ipv6_src_6to4_sla_id = -1; -static int hf_ipv6_src_teredo_server_ipv4 = -1; -static int hf_ipv6_src_teredo_port = -1; -static int hf_ipv6_src_teredo_client_ipv4 = -1; -static int hf_ipv6_src_embed_ipv4 = -1; -static int hf_ipv6_dst = -1; -static int hf_ipv6_dst_host = -1; -static int hf_ipv6_dst_slaac_mac = -1; -static int hf_ipv6_dst_isatap_ipv4 = -1; -static int hf_ipv6_dst_6to4_gateway_ipv4 = -1; -static int hf_ipv6_dst_6to4_sla_id = -1; -static int hf_ipv6_dst_teredo_server_ipv4 = -1; -static int hf_ipv6_dst_teredo_port = -1; -static int hf_ipv6_dst_teredo_client_ipv4 = -1; -static int hf_ipv6_dst_embed_ipv4 = -1; -static int hf_ipv6_addr = -1; -static int hf_ipv6_host = -1; -static int hf_ipv6_slaac_mac = -1; -static int hf_ipv6_isatap_ipv4 = -1; -static int hf_ipv6_6to4_gateway_ipv4 = -1; -static int hf_ipv6_6to4_sla_id = -1; -static int hf_ipv6_teredo_server_ipv4 = -1; -static int hf_ipv6_teredo_port = -1; -static int hf_ipv6_teredo_client_ipv4 = -1; -static int hf_ipv6_embed_ipv4 = -1; -static int hf_ipv6_opt = -1; -static int hf_ipv6_opt_type = -1; -static int hf_ipv6_opt_type_action = -1; -static int hf_ipv6_opt_type_change = -1; -static int hf_ipv6_opt_type_rest = -1; -static int hf_ipv6_opt_length = -1; -static int hf_ipv6_opt_pad1 = -1; -static int hf_ipv6_opt_padn = -1; -static int hf_ipv6_opt_tel = -1; -static int hf_ipv6_opt_rtalert = -1; -static int hf_ipv6_opt_pmtu_min = -1; -static int hf_ipv6_opt_pmtu_rtn = -1; -static int hf_ipv6_opt_pmtu_rtn_flag = -1; -static int hf_ipv6_opt_jumbo = -1; -static int hf_ipv6_opt_calipso_doi = -1; -static int hf_ipv6_opt_calipso_cmpt_length = -1; -static int hf_ipv6_opt_calipso_sens_level = -1; -static int hf_ipv6_opt_calipso_checksum = -1; -static int hf_ipv6_opt_calipso_cmpt_bitmap = -1; -static int hf_ipv6_opt_smf_dpd_hash_bit = -1; -static int hf_ipv6_opt_smf_dpd_tid_type = -1; -static int hf_ipv6_opt_smf_dpd_tid_len = -1; -static int hf_ipv6_opt_smf_dpd_tagger_id = -1; -static int hf_ipv6_opt_smf_dpd_ident = -1; -static int hf_ipv6_opt_smf_dpd_hav = -1; -static int hf_ipv6_opt_pdm_scale_dtlr = -1; -static int hf_ipv6_opt_pdm_scale_dtls = -1; -static int hf_ipv6_opt_pdm_psn_this_pkt = -1; -static int hf_ipv6_opt_pdm_psn_last_recv = -1; -static int hf_ipv6_opt_pdm_delta_last_recv = -1; -static int hf_ipv6_opt_pdm_delta_last_sent = -1; -static int hf_ipv6_opt_qs_func = -1; -static int hf_ipv6_opt_qs_rate = -1; -static int hf_ipv6_opt_qs_ttl = -1; -static int hf_ipv6_opt_qs_ttl_diff = -1; -static int hf_ipv6_opt_qs_unused = -1; -static int hf_ipv6_opt_qs_nonce = -1; -static int hf_ipv6_opt_qs_reserved = -1; -static int hf_ipv6_opt_tpf_information = -1; -static int hf_ipv6_opt_mipv6_home_address = -1; -static int hf_ipv6_opt_rpl_flag = -1; -static int hf_ipv6_opt_rpl_flag_o = -1; -static int hf_ipv6_opt_rpl_flag_r = -1; -static int hf_ipv6_opt_rpl_flag_f = -1; -static int hf_ipv6_opt_rpl_flag_rsv = -1; -static int hf_ipv6_opt_rpl_instance_id = -1; -static int hf_ipv6_opt_rpl_senderrank = -1; -static int hf_ipv6_opt_ilnp_nonce = -1; -static int hf_ipv6_opt_lio_len = -1; -static int hf_ipv6_opt_lio_id = -1; -static int hf_ipv6_opt_mpl_flag = -1; -static int hf_ipv6_opt_mpl_flag_s = -1; -static int hf_ipv6_opt_mpl_flag_m = -1; -static int hf_ipv6_opt_mpl_flag_v = -1; -static int hf_ipv6_opt_mpl_flag_rsv = -1; -static int hf_ipv6_opt_mpl_sequence = -1; -static int hf_ipv6_opt_mpl_seed_id = -1; -static int hf_ipv6_opt_dff_flags = -1; -static int hf_ipv6_opt_dff_flag_ver = -1; -static int hf_ipv6_opt_dff_flag_dup = -1; -static int hf_ipv6_opt_dff_flag_ret = -1; -static int hf_ipv6_opt_dff_flag_rsv = -1; -static int hf_ipv6_opt_dff_seqnum = -1; -static int hf_ipv6_opt_experimental = -1; -static int hf_ipv6_opt_unknown_data = -1; -static int hf_ipv6_opt_unknown = -1; -static int hf_ipv6_dstopts_nxt = -1; -static int hf_ipv6_dstopts_len = -1; -static int hf_ipv6_dstopts_len_oct = -1; -static int hf_ipv6_hopopts_nxt = -1; -static int hf_ipv6_hopopts_len = -1; -static int hf_ipv6_hopopts_len_oct = -1; -static int hf_ipv6_routing_nxt = -1; -static int hf_ipv6_routing_len = -1; -static int hf_ipv6_routing_len_oct = -1; -static int hf_ipv6_routing_type = -1; -static int hf_ipv6_routing_segleft = -1; -static int hf_ipv6_routing_unknown_data = -1; -static int hf_ipv6_fraghdr_nxt = -1; -static int hf_ipv6_fraghdr_reserved_octet = -1; -static int hf_ipv6_fraghdr_offset = -1; -static int hf_ipv6_fraghdr_reserved_bits = -1; -static int hf_ipv6_fraghdr_more = -1; -static int hf_ipv6_fraghdr_ident = -1; -static int hf_ipv6_fragment = -1; -static int hf_ipv6_fragment_overlap = -1; -static int hf_ipv6_fragment_overlap_conflict = -1; -static int hf_ipv6_fragment_multiple_tails = -1; -static int hf_ipv6_fragment_too_long_fragment = -1; -static int hf_ipv6_fragment_error = -1; -static int hf_ipv6_fragment_count = -1; -static int hf_ipv6_fragments = -1; -static int hf_ipv6_reassembled_in = -1; -static int hf_ipv6_reassembled_length = -1; -static int hf_ipv6_reassembled_data = -1; - -static int hf_ipv6_routing_src_reserved = -1; -static int hf_ipv6_routing_src_addr = -1; - -static int hf_ipv6_routing_mipv6_reserved = -1; -static int hf_ipv6_routing_mipv6_home_address = -1; - -static int hf_ipv6_routing_rpl_cmprI = -1; -static int hf_ipv6_routing_rpl_cmprE = -1; -static int hf_ipv6_routing_rpl_pad = -1; -static int hf_ipv6_routing_rpl_reserved = -1; -static int hf_ipv6_routing_rpl_addr_count = -1; -static int hf_ipv6_routing_rpl_addr = -1; -static int hf_ipv6_routing_rpl_fulladdr = -1; - -static int hf_ipv6_routing_srh_last_entry = -1; -static int hf_ipv6_routing_srh_flags = -1; -static int hf_ipv6_routing_srh_tag = -1; -static int hf_ipv6_routing_srh_addr = -1; - -static int hf_ipv6_routing_crh16_current_sid = -1; -static int hf_ipv6_routing_crh32_current_sid = -1; -static int hf_ipv6_routing_crh16_segment_id = -1; -static int hf_ipv6_routing_crh32_segment_id = -1; - -static int hf_geoip_country = -1; -static int hf_geoip_country_iso = -1; -static int hf_geoip_city = -1; -static int hf_geoip_as_number = -1; -static int hf_geoip_as_org = -1; -static int hf_geoip_latitude = -1; -static int hf_geoip_longitude = -1; -static int hf_geoip_src_summary = -1; -static int hf_geoip_src_country = -1; -static int hf_geoip_src_country_iso = -1; -static int hf_geoip_src_city = -1; -static int hf_geoip_src_as_number = -1; -static int hf_geoip_src_as_org = -1; -static int hf_geoip_src_latitude = -1; -static int hf_geoip_src_longitude = -1; -static int hf_geoip_dst_summary = -1; -static int hf_geoip_dst_country = -1; -static int hf_geoip_dst_country_iso = -1; -static int hf_geoip_dst_city = -1; -static int hf_geoip_dst_as_number = -1; -static int hf_geoip_dst_as_org = -1; -static int hf_geoip_dst_latitude = -1; -static int hf_geoip_dst_longitude = -1; - -static gint ett_ipv6_proto = -1; -static gint ett_ipv6_traffic_class = -1; -static gint ett_ipv6_opt = -1; -static gint ett_ipv6_opt_type = -1; -static gint ett_ipv6_opt_rpl = -1; -static gint ett_ipv6_opt_mpl = -1; -static gint ett_ipv6_opt_dff_flags = -1; -static gint ett_ipv6_hopopts_proto = -1; -static gint ett_ipv6_fraghdr_proto = -1; -static gint ett_ipv6_routing_proto = -1; -static gint ett_ipv6_routing_srh_vect = -1; -static gint ett_ipv6_fragments = -1; -static gint ett_ipv6_fragment = -1; -static gint ett_ipv6_dstopts_proto = -1; - -static gint ett_geoip_info = -1; - -static expert_field ei_ipv6_routing_invalid_length = EI_INIT; -static expert_field ei_ipv6_routing_invalid_segleft = EI_INIT; -static expert_field ei_ipv6_routing_undecoded = EI_INIT; -static expert_field ei_ipv6_dst_addr_not_multicast = EI_INIT; -static expert_field ei_ipv6_src_route_list_mult_inst_same_addr = EI_INIT; -static expert_field ei_ipv6_src_route_list_src_addr = EI_INIT; -static expert_field ei_ipv6_src_route_list_dst_addr = EI_INIT; -static expert_field ei_ipv6_src_route_list_multicast_addr = EI_INIT; -static expert_field ei_ipv6_routing_rpl_cmpri_cmpre_pad = EI_INIT; -static expert_field ei_ipv6_routing_rpl_addr_count_ge0 = EI_INIT; -static expert_field ei_ipv6_routing_rpl_reserved = EI_INIT; -static expert_field ei_ipv6_routing_deprecated = EI_INIT; -static expert_field ei_ipv6_opt_jumbo_missing = EI_INIT; -static expert_field ei_ipv6_opt_jumbo_prohibited = EI_INIT; -static expert_field ei_ipv6_opt_jumbo_truncated = EI_INIT; -static expert_field ei_ipv6_opt_jumbo_fragment = EI_INIT; -static expert_field ei_ipv6_opt_invalid_len = EI_INIT; -static expert_field ei_ipv6_opt_unknown_data = EI_INIT; -static expert_field ei_ipv6_opt_deprecated = EI_INIT; -static expert_field ei_ipv6_opt_mpl_ipv6_src_seed_id = EI_INIT; -static expert_field ei_ipv6_hopopts_not_first = EI_INIT; -static expert_field ei_ipv6_plen_exceeds_framing = EI_INIT; -static expert_field ei_ipv6_plen_zero = EI_INIT; -static expert_field ei_ipv6_bogus_ipv6_version = EI_INIT; -static expert_field ei_ipv6_invalid_header = EI_INIT; -static expert_field ei_ipv6_opt_header_mismatch = EI_INIT; +static int ipv6_tap; + +static int exported_pdu_tap; + +static int proto_ipv6; +static int proto_ipv6_hopopts; +static int proto_ipv6_routing; +static int proto_ipv6_fraghdr; +static int proto_ipv6_dstopts; + +static int proto_ipv6_routing_rt0; +static int proto_ipv6_routing_mipv6; +static int proto_ipv6_routing_rpl; +static int proto_ipv6_routing_srh; +static int proto_ipv6_routing_crh; + +static int hf_ipv6_version; +static int hf_ip_version; +static int hf_ipv6_tclass; +static int hf_ipv6_tclass_dscp; +static int hf_ipv6_tclass_ecn; +static int hf_ipv6_flow; +static int hf_ipv6_stream; +static int hf_ipv6_plen; +static int hf_ipv6_nxt; +static int hf_ipv6_hlim; +static int hf_ipv6_src; +static int hf_ipv6_src_addr_space; +static int hf_ipv6_src_multicast_flags; +static int hf_ipv6_src_multicast_flags_reserved; +static int hf_ipv6_src_multicast_flags_transient; +static int hf_ipv6_src_multicast_flags_network_prefix; +static int hf_ipv6_src_multicast_flags_embed_rp; +static int hf_ipv6_src_special_purpose; +static int hf_ipv6_src_special_purpose_source; +static int hf_ipv6_src_special_purpose_destination; +static int hf_ipv6_src_special_purpose_forwardable; +static int hf_ipv6_src_special_purpose_global; +static int hf_ipv6_src_special_purpose_reserved; +static int hf_ipv6_src_multicast_scope; +static int hf_ipv6_src_host; +static int hf_ipv6_src_slaac_mac; +static int hf_ipv6_src_isatap_ipv4; +static int hf_ipv6_src_6to4_gateway_ipv4; +static int hf_ipv6_src_6to4_sla_id; +static int hf_ipv6_src_teredo_server_ipv4; +static int hf_ipv6_src_teredo_port; +static int hf_ipv6_src_teredo_client_ipv4; +static int hf_ipv6_src_embed_ipv4; +static int hf_ipv6_dst; +static int hf_ipv6_dst_addr_space; +static int hf_ipv6_dst_multicast_flags; +static int hf_ipv6_dst_multicast_flags_reserved; +static int hf_ipv6_dst_multicast_flags_transient; +static int hf_ipv6_dst_multicast_flags_network_prefix; +static int hf_ipv6_dst_multicast_flags_embed_rp; +static int hf_ipv6_dst_multicast_scope; +static int hf_ipv6_dst_special_purpose; +static int hf_ipv6_dst_special_purpose_source; +static int hf_ipv6_dst_special_purpose_destination; +static int hf_ipv6_dst_special_purpose_forwardable; +static int hf_ipv6_dst_special_purpose_global; +static int hf_ipv6_dst_special_purpose_reserved; +static int hf_ipv6_dst_host; +static int hf_ipv6_dst_slaac_mac; +static int hf_ipv6_dst_isatap_ipv4; +static int hf_ipv6_dst_6to4_gateway_ipv4; +static int hf_ipv6_dst_6to4_sla_id; +static int hf_ipv6_dst_teredo_server_ipv4; +static int hf_ipv6_dst_teredo_port; +static int hf_ipv6_dst_teredo_client_ipv4; +static int hf_ipv6_dst_embed_ipv4; +static int hf_ipv6_addr; +static int hf_ipv6_addr_space; +static int hf_ipv6_multicast_flags; +static int hf_ipv6_multicast_flags_reserved; +static int hf_ipv6_multicast_flags_transient; +static int hf_ipv6_multicast_flags_network_prefix; +static int hf_ipv6_multicast_flags_embed_rp; +static int hf_ipv6_multicast_scope; +static int hf_ipv6_addr_special_purpose; +static int hf_ipv6_addr_special_purpose_source; +static int hf_ipv6_addr_special_purpose_destination; +static int hf_ipv6_addr_special_purpose_forwardable; +static int hf_ipv6_addr_special_purpose_global; +static int hf_ipv6_addr_special_purpose_reserved; +static int hf_ipv6_host; +static int hf_ipv6_slaac_mac; +static int hf_ipv6_isatap_ipv4; +static int hf_ipv6_6to4_gateway_ipv4; +static int hf_ipv6_6to4_sla_id; +static int hf_ipv6_teredo_server_ipv4; +static int hf_ipv6_teredo_port; +static int hf_ipv6_teredo_client_ipv4; +static int hf_ipv6_embed_ipv4_prefix; +static int hf_ipv6_embed_ipv4; +static int hf_ipv6_embed_ipv4_u; +static int hf_ipv6_embed_ipv4_suffix; +static int hf_ipv6_opt; +static int hf_ipv6_opt_type; +static int hf_ipv6_opt_type_action; +static int hf_ipv6_opt_type_change; +static int hf_ipv6_opt_type_rest; +static int hf_ipv6_opt_length; +static int hf_ipv6_opt_pad1; +static int hf_ipv6_opt_padn; +static int hf_ipv6_opt_tel; +static int hf_ipv6_opt_rtalert; +static int hf_ipv6_opt_pmtu_min; +static int hf_ipv6_opt_pmtu_rtn; +static int hf_ipv6_opt_pmtu_rtn_flag; +static int hf_ipv6_opt_apn_id_type; +static int hf_ipv6_opt_apn_flags; +static int hf_ipv6_opt_apn_param_type; +static int hf_ipv6_opt_apn_id_part1; +static int hf_ipv6_opt_apn_id_part2; +static int hf_ipv6_opt_apn_id_part3; +static int hf_ipv6_opt_apn_id_part4; +static int hf_ipv6_opt_jumbo; +static int hf_ipv6_opt_calipso_doi; +static int hf_ipv6_opt_calipso_cmpt_length; +static int hf_ipv6_opt_calipso_sens_level; +static int hf_ipv6_opt_calipso_checksum; +static int hf_ipv6_opt_calipso_cmpt_bitmap; +static int hf_ipv6_opt_smf_dpd_hash_bit; +static int hf_ipv6_opt_smf_dpd_tid_type; +static int hf_ipv6_opt_smf_dpd_tid_len; +static int hf_ipv6_opt_smf_dpd_tagger_id; +static int hf_ipv6_opt_smf_dpd_ident; +static int hf_ipv6_opt_smf_dpd_hav; +static int hf_ipv6_opt_pdm_scale_dtlr; +static int hf_ipv6_opt_pdm_scale_dtls; +static int hf_ipv6_opt_pdm_psn_this_pkt; +static int hf_ipv6_opt_pdm_psn_last_recv; +static int hf_ipv6_opt_pdm_delta_last_recv; +static int hf_ipv6_opt_pdm_delta_last_sent; +static int hf_ipv6_opt_qs_func; +static int hf_ipv6_opt_qs_rate; +static int hf_ipv6_opt_qs_ttl; +static int hf_ipv6_opt_qs_ttl_diff; +static int hf_ipv6_opt_qs_unused; +static int hf_ipv6_opt_qs_nonce; +static int hf_ipv6_opt_qs_reserved; +static int hf_ipv6_opt_ioam_rsv; +static int hf_ipv6_opt_ioam_opt_type; +static int hf_ipv6_opt_ioam_trace_ns; +static int hf_ipv6_opt_ioam_trace_nodelen; +static int hf_ipv6_opt_ioam_trace_flags; +static int hf_ipv6_opt_ioam_trace_flag_o; +static int hf_ipv6_opt_ioam_trace_flag_l; +static int hf_ipv6_opt_ioam_trace_flag_a; +static int hf_ipv6_opt_ioam_trace_flag_rsv; +static int hf_ipv6_opt_ioam_trace_remlen; +static int hf_ipv6_opt_ioam_trace_type; +static int hf_ipv6_opt_ioam_trace_type_bit0; +static int hf_ipv6_opt_ioam_trace_type_bit1; +static int hf_ipv6_opt_ioam_trace_type_bit2; +static int hf_ipv6_opt_ioam_trace_type_bit3; +static int hf_ipv6_opt_ioam_trace_type_bit4; +static int hf_ipv6_opt_ioam_trace_type_bit5; +static int hf_ipv6_opt_ioam_trace_type_bit6; +static int hf_ipv6_opt_ioam_trace_type_bit7; +static int hf_ipv6_opt_ioam_trace_type_bit8; +static int hf_ipv6_opt_ioam_trace_type_bit9; +static int hf_ipv6_opt_ioam_trace_type_bit10; +static int hf_ipv6_opt_ioam_trace_type_bit11; +static int hf_ipv6_opt_ioam_trace_type_undef; +static int hf_ipv6_opt_ioam_trace_type_bit22; +static int hf_ipv6_opt_ioam_trace_type_rsv; +static int hf_ipv6_opt_ioam_trace_rsv; +static int hf_ipv6_opt_ioam_trace_free_space; +static int hf_ipv6_opt_ioam_trace_node_hlim; +static int hf_ipv6_opt_ioam_trace_node_id; +static int hf_ipv6_opt_ioam_trace_node_iif; +static int hf_ipv6_opt_ioam_trace_node_eif; +static int hf_ipv6_opt_ioam_trace_node_tss; +static int hf_ipv6_opt_ioam_trace_node_tsf; +static int hf_ipv6_opt_ioam_trace_node_trdelay; +static int hf_ipv6_opt_ioam_trace_node_nsdata; +static int hf_ipv6_opt_ioam_trace_node_qdepth; +static int hf_ipv6_opt_ioam_trace_node_csum; +static int hf_ipv6_opt_ioam_trace_node_id_wide; +static int hf_ipv6_opt_ioam_trace_node_iif_wide; +static int hf_ipv6_opt_ioam_trace_node_eif_wide; +static int hf_ipv6_opt_ioam_trace_node_nsdata_wide; +static int hf_ipv6_opt_ioam_trace_node_bufoccup; +static int hf_ipv6_opt_ioam_trace_node_undefined; +static int hf_ipv6_opt_ioam_trace_node_oss_len; +static int hf_ipv6_opt_ioam_trace_node_oss_scid; +static int hf_ipv6_opt_ioam_trace_node_oss_data; +static int hf_ipv6_opt_tpf_information; +static int hf_ipv6_opt_mipv6_home_address; +static int hf_ipv6_opt_rpl_flag; +static int hf_ipv6_opt_rpl_flag_o; +static int hf_ipv6_opt_rpl_flag_r; +static int hf_ipv6_opt_rpl_flag_f; +static int hf_ipv6_opt_rpl_flag_rsv; +static int hf_ipv6_opt_rpl_instance_id; +static int hf_ipv6_opt_rpl_senderrank; +static int hf_ipv6_opt_ilnp_nonce; +static int hf_ipv6_opt_lio_len; +static int hf_ipv6_opt_lio_id; +static int hf_ipv6_opt_mpl_flag; +static int hf_ipv6_opt_mpl_flag_s; +static int hf_ipv6_opt_mpl_flag_m; +static int hf_ipv6_opt_mpl_flag_v; +static int hf_ipv6_opt_mpl_flag_rsv; +static int hf_ipv6_opt_mpl_sequence; +static int hf_ipv6_opt_mpl_seed_id; +static int hf_ipv6_opt_dff_flags; +static int hf_ipv6_opt_dff_flag_ver; +static int hf_ipv6_opt_dff_flag_dup; +static int hf_ipv6_opt_dff_flag_ret; +static int hf_ipv6_opt_dff_flag_rsv; +static int hf_ipv6_opt_dff_seqnum; +static int hf_ipv6_opt_experimental; +static int hf_ipv6_opt_unknown_data; +static int hf_ipv6_opt_unknown; +static int hf_ipv6_dstopts_nxt; +static int hf_ipv6_dstopts_len; +static int hf_ipv6_dstopts_len_oct; +static int hf_ipv6_hopopts_nxt; +static int hf_ipv6_hopopts_len; +static int hf_ipv6_hopopts_len_oct; +static int hf_ipv6_routing_nxt; +static int hf_ipv6_routing_len; +static int hf_ipv6_routing_len_oct; +static int hf_ipv6_routing_type; +static int hf_ipv6_routing_segleft; +static int hf_ipv6_routing_unknown_data; +static int hf_ipv6_fraghdr_nxt; +static int hf_ipv6_fraghdr_reserved_octet; +static int hf_ipv6_fraghdr_offset; +static int hf_ipv6_fraghdr_reserved_bits; +static int hf_ipv6_fraghdr_more; +static int hf_ipv6_fraghdr_ident; +static int hf_ipv6_fragment; +static int hf_ipv6_fragment_overlap; +static int hf_ipv6_fragment_overlap_conflict; +static int hf_ipv6_fragment_multiple_tails; +static int hf_ipv6_fragment_too_long_fragment; +static int hf_ipv6_fragment_error; +static int hf_ipv6_fragment_count; +static int hf_ipv6_fragments; +static int hf_ipv6_reassembled_in; +static int hf_ipv6_reassembled_length; +static int hf_ipv6_reassembled_data; + +static int hf_ipv6_routing_src_reserved; +static int hf_ipv6_routing_src_addr; + +static int hf_ipv6_routing_mipv6_reserved; +static int hf_ipv6_routing_mipv6_home_address; + +static int hf_ipv6_routing_rpl_cmprI; +static int hf_ipv6_routing_rpl_cmprE; +static int hf_ipv6_routing_rpl_pad; +static int hf_ipv6_routing_rpl_reserved; +static int hf_ipv6_routing_rpl_addr_count; +static int hf_ipv6_routing_rpl_addr; +static int hf_ipv6_routing_rpl_fulladdr; + +static int hf_ipv6_routing_srh_last_entry; +static int hf_ipv6_routing_srh_flags; +static int hf_ipv6_routing_srh_tag; +static int hf_ipv6_routing_srh_addr; + +static int hf_ipv6_routing_crh16_current_sid; +static int hf_ipv6_routing_crh32_current_sid; +static int hf_ipv6_routing_crh16_segment_id; +static int hf_ipv6_routing_crh32_segment_id; + +struct ipv6_addr_info_s { + int *hf_addr; + int *hf_addr_space; + int *hf_multicast_flags; + int *const *hf_multicast_flags_bits; + int *hf_multicast_scope; + int *hf_special_purpose; + int *hf_special_purpose_source; + int *hf_special_purpose_destination; + int *hf_special_purpose_forwardable; + int *hf_special_purpose_global; + int *hf_special_purpose_reserved; + int *hf_host; +}; + +static int *const ipv6_src_multicast_flags_bits[5] = { + &hf_ipv6_src_multicast_flags_reserved, + &hf_ipv6_src_multicast_flags_embed_rp, + &hf_ipv6_src_multicast_flags_network_prefix, + &hf_ipv6_src_multicast_flags_transient, + NULL +}; + +static struct ipv6_addr_info_s ipv6_src_info = { + &hf_ipv6_src, + &hf_ipv6_src_addr_space, + &hf_ipv6_src_multicast_flags, + ipv6_src_multicast_flags_bits, + &hf_ipv6_src_multicast_scope, + &hf_ipv6_src_special_purpose, + &hf_ipv6_src_special_purpose_source, + &hf_ipv6_src_special_purpose_destination, + &hf_ipv6_src_special_purpose_forwardable, + &hf_ipv6_src_special_purpose_global, + &hf_ipv6_src_special_purpose_reserved, + &hf_ipv6_src_host, +}; + +static int *const ipv6_dst_multicast_flags_bits[5] = { + &hf_ipv6_dst_multicast_flags_reserved, + &hf_ipv6_dst_multicast_flags_embed_rp, + &hf_ipv6_dst_multicast_flags_network_prefix, + &hf_ipv6_dst_multicast_flags_transient, + NULL +}; + +static struct ipv6_addr_info_s ipv6_dst_info = { + &hf_ipv6_dst, + &hf_ipv6_dst_addr_space, + &hf_ipv6_dst_multicast_flags, + ipv6_dst_multicast_flags_bits, + &hf_ipv6_dst_multicast_scope, + &hf_ipv6_dst_special_purpose, + &hf_ipv6_dst_special_purpose_source, + &hf_ipv6_dst_special_purpose_destination, + &hf_ipv6_dst_special_purpose_forwardable, + &hf_ipv6_dst_special_purpose_global, + &hf_ipv6_dst_special_purpose_reserved, + &hf_ipv6_dst_host, +}; + +static int hf_geoip_country; +static int hf_geoip_country_iso; +static int hf_geoip_city; +static int hf_geoip_as_number; +static int hf_geoip_as_org; +static int hf_geoip_latitude; +static int hf_geoip_longitude; +static int hf_geoip_src_summary; +static int hf_geoip_src_country; +static int hf_geoip_src_country_iso; +static int hf_geoip_src_city; +static int hf_geoip_src_as_number; +static int hf_geoip_src_as_org; +static int hf_geoip_src_latitude; +static int hf_geoip_src_longitude; +static int hf_geoip_dst_summary; +static int hf_geoip_dst_country; +static int hf_geoip_dst_country_iso; +static int hf_geoip_dst_city; +static int hf_geoip_dst_as_number; +static int hf_geoip_dst_as_org; +static int hf_geoip_dst_latitude; +static int hf_geoip_dst_longitude; + +static gint ett_ipv6_proto; +static gint ett_ipv6_detail; +static gint ett_ipv6_detail_special_purpose; +static gint ett_ipv6_multicast_flags; +static gint ett_ipv6_traffic_class; +static gint ett_ipv6_opt; +static gint ett_ipv6_opt_type; +static gint ett_ipv6_opt_rpl; +static gint ett_ipv6_opt_mpl; +static gint ett_ipv6_opt_dff_flags; +static gint ett_ipv6_opt_ioam_trace_flags; +static gint ett_ipv6_opt_ioam_trace_types; +static gint ett_ipv6_hopopts_proto; +static gint ett_ipv6_fraghdr_proto; +static gint ett_ipv6_routing_proto; +static gint ett_ipv6_routing_srh_vect; +static gint ett_ipv6_fragments; +static gint ett_ipv6_fragment; +static gint ett_ipv6_dstopts_proto; + +static gint ett_geoip_info; + +static guint32 ipv6_stream_count; + +static expert_field ei_ipv6_routing_invalid_length; +static expert_field ei_ipv6_routing_invalid_segleft; +static expert_field ei_ipv6_routing_undecoded; +static expert_field ei_ipv6_dst_addr_not_unspecified; +static expert_field ei_ipv6_src_addr_not_multicast; +static expert_field ei_ipv6_dst_addr_not_multicast; +static expert_field ei_ipv6_src_route_list_mult_inst_same_addr; +static expert_field ei_ipv6_src_route_list_src_addr; +static expert_field ei_ipv6_src_route_list_dst_addr; +static expert_field ei_ipv6_src_route_list_multicast_addr; +static expert_field ei_ipv6_routing_rpl_cmpri_cmpre_pad; +static expert_field ei_ipv6_routing_rpl_addr_count_ge0; +static expert_field ei_ipv6_routing_rpl_reserved; +static expert_field ei_ipv6_routing_deprecated; +static expert_field ei_ipv6_opt_jumbo_missing; +static expert_field ei_ipv6_opt_jumbo_prohibited; +static expert_field ei_ipv6_opt_jumbo_truncated; +static expert_field ei_ipv6_opt_jumbo_fragment; +static expert_field ei_ipv6_opt_invalid_len; +static expert_field ei_ipv6_opt_apn_invalid_id_type; +static expert_field ei_ipv6_opt_unknown_data; +static expert_field ei_ipv6_opt_deprecated; +static expert_field ei_ipv6_opt_mpl_ipv6_src_seed_id; +static expert_field ei_ipv6_hopopts_not_first; +static expert_field ei_ipv6_plen_exceeds_framing; +static expert_field ei_ipv6_plen_zero; +static expert_field ei_ipv6_bogus_ipv6_version; +static expert_field ei_ipv6_invalid_header; +static expert_field ei_ipv6_opt_header_mismatch; +static expert_field ei_ipv6_opt_ioam_invalid_nodelen; +static expert_field ei_ipv6_opt_ioam_invalid_remlen; +static expert_field ei_ipv6_opt_ioam_invalid_trace_type; +static expert_field ei_ipv6_embed_ipv4_u_value; static dissector_handle_t ipv6_handle; @@ -415,7 +627,7 @@ static void ipv6_prompt(packet_info *pinfo, gchar *result) { gpointer value = ipv6_value(pinfo); - g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IP protocol %u as", GPOINTER_TO_UINT(value)); + snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IP protocol %u as", GPOINTER_TO_UINT(value)); } static const char* ipv6_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter) @@ -435,56 +647,140 @@ static const char* ipv6_conv_get_filter_type(conv_item_t* conv, conv_filter_type static ct_dissector_info_t ipv6_ct_dissector_info = {&ipv6_conv_get_filter_type}; static tap_packet_status -ipv6_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip) +ipv6_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags) { conv_hash_t *hash = (conv_hash_t*) pct; + hash->flags = flags; + const ipv6_tap_info_t *ip6 = (const ipv6_tap_info_t *)vip; - add_conversation_table_data(hash, &ip6->ip6_src, &ip6->ip6_dst, 0, 0, 1, - pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, - &ipv6_ct_dissector_info, ENDPOINT_NONE); + add_conversation_table_data_with_conv_id(hash, &ip6->ip6_src, &ip6->ip6_dst, 0, 0, + (conv_id_t)ip6->ip6_stream, 1, pinfo->fd->pkt_len, + &pinfo->rel_ts, &pinfo->abs_ts, &ipv6_ct_dissector_info, CONVERSATION_IPV6); return TAP_PACKET_REDRAW; } -static const char* ipv6_host_get_filter_type(hostlist_talker_t* host, conv_filter_type_e filter) +static const char* ipv6_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter) { - if ((filter == CONV_FT_ANY_ADDRESS) && (host->myaddress.type == AT_IPv6)) + if ((filter == CONV_FT_ANY_ADDRESS) && (endpoint->myaddress.type == AT_IPv6)) return "ipv6.addr"; return CONV_FILTER_INVALID; } -static hostlist_dissector_info_t ipv6_host_dissector_info = {&ipv6_host_get_filter_type}; +static et_dissector_info_t ipv6_endpoint_dissector_info = {&ipv6_endpoint_get_filter_type}; static tap_packet_status -ipv6_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip) +ipv6_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags) { conv_hash_t *hash = (conv_hash_t*) pit; + hash->flags = flags; + const ipv6_tap_info_t *ip6 = (const ipv6_tap_info_t *)vip; - add_hostlist_table_data(hash, &ip6->ip6_src, 0, TRUE, 1, - pinfo->fd->pkt_len, &ipv6_host_dissector_info, ENDPOINT_NONE); - add_hostlist_table_data(hash, &ip6->ip6_dst, 0, FALSE, 1, - pinfo->fd->pkt_len, &ipv6_host_dissector_info, ENDPOINT_NONE); + add_endpoint_table_data(hash, &ip6->ip6_src, 0, TRUE, 1, + pinfo->fd->pkt_len, &ipv6_endpoint_dissector_info, ENDPOINT_NONE); + add_endpoint_table_data(hash, &ip6->ip6_dst, 0, FALSE, 1, + pinfo->fd->pkt_len, &ipv6_endpoint_dissector_info, ENDPOINT_NONE); return TAP_PACKET_REDRAW; } static gboolean -ipv6_filter_valid(packet_info *pinfo) +ipv6_filter_valid(packet_info *pinfo, void *user_data _U_) { return proto_is_frame_protocol(pinfo->layers, "ipv6"); } static gchar* -ipv6_build_filter(packet_info *pinfo) +ipv6_build_filter(packet_info *pinfo, void *user_data _U_) { - return g_strdup_printf("ipv6.addr eq %s and ipv6.addr eq %s", + return ws_strdup_printf("ipv6.addr eq %s and ipv6.addr eq %s", address_to_str(pinfo->pool, &pinfo->net_src), address_to_str(pinfo->pool, &pinfo->net_dst)); } + +/* UAT for providing a list of NAT64 prefixes */ + +struct nat64_prefix_data { + char *ipaddr; + uint8_t prefix_len; + uint32_t prefix_wildcard_len; +}; + + +static uat_t *nat64_prefix_uat = NULL; +static struct nat64_prefix_data *nat64_prefix_uats = NULL; +static guint number_of_nat64_prefix = 0; + + +UAT_CSTRING_CB_DEF(nat64_prefix_uats, ipaddr, struct nat64_prefix_data) + +static bool +nat64_prefix_uat_fld_ip_chk_cb(void *r _U_, const char *ipaddr, guint len _U_, const void *u1 _U_, const void *u2 _U_, char **err) +{ + /* Check for a valid IPv6 address */ + ws_in6_addr addr; + + if (ws_inet_pton6(ipaddr, &addr)) { + *err = NULL; + return TRUE; + } + + *err = ws_strdup_printf("No valid IPv6 address given."); + return FALSE; +} + +static const value_string nat64_prefix_length_vals[] = +{ + { 32, "32" }, + { 40, "40" }, + { 48, "48" }, + { 56, "56" }, + { 64, "64" }, + { 96, "96" }, + { 0, NULL } +}; + +UAT_VS_DEF(nat64_prefix_uats, prefix_len, struct nat64_prefix_data, uint8_t, 96, "96") + +static const value_string nat64_prefix_wildcard_length_vals[] = +{ + { 0, "0" }, + { 8, "8" }, + { 16, "16" }, + { 32, "32" }, + { 64, "64" }, + { 0, NULL } +}; + +UAT_VS_DEF(nat64_prefix_uats, prefix_wildcard_len, struct nat64_prefix_data, uint8_t, 0, "0") + + +static void +nat64_prefix_free_cb(void *data) +{ + struct nat64_prefix_data *h = (struct nat64_prefix_data *)data; + + g_free(h->ipaddr); +} + +static void * +nat64_prefix_copy_cb(void *dst_, const void *src_, size_t len _U_) +{ + const struct nat64_prefix_data *src = (const struct nat64_prefix_data *)src_; + struct nat64_prefix_data *dst = (struct nat64_prefix_data *)dst_; + + dst->ipaddr = g_strdup(src->ipaddr); + dst->prefix_len = src->prefix_len; + dst->prefix_wildcard_len = src->prefix_wildcard_len; + + return dst; +} + + static gint ipv6_previous_layer_id(packet_info *pinfo) { @@ -525,8 +821,8 @@ static gboolean ipv6_reassemble = TRUE; /* Place IPv6 summary in proto tree */ static gboolean ipv6_summary_in_tree = TRUE; -/* Look up addresses via mmdbresolve */ -static gboolean ipv6_use_geoip = TRUE; +/* Show expanded information about IPv6 address */ +static gboolean ipv6_address_detail = TRUE; /* Perform strict RFC adherence checking */ static gboolean g_ipv6_rpl_srh_strict_rfc_checking = FALSE; @@ -557,13 +853,16 @@ static const value_string ipv6_opt_type_vals[] = { { IP6OPT_CALIPSO, "CALIPSO" }, { IP6OPT_SMF_DPD, "SMF_DPD" }, { IP6OPT_PDM, "Performance and Diagnostic Metrics" }, + { IP6OPT_APN6, "Application-Aware IPv6 Networking (APN6)" }, { IP6OPT_EXP_1E, "Experimental (0x1E)" }, + { IP6OPT_RPL, "RPL Option" }, { IP6OPT_QUICKSTART, "Quick-Start" }, { IP6OPT_PMTU, "Path MTU Option" }, + { IP6OPT_IOAM, "IOAM Option" }, { IP6OPT_EXP_3E, "Experimental (0x3E)" }, { IP6OPT_TPF, "Tunnel Payload Forwarding (TPF) Information" }, { IP6OPT_EXP_5E, "Experimental (0x5E)" }, - { IP6OPT_RPL, "RPL Option" }, + { IP6OPT_RPL_OLD, "RPL Option (deprecated)" }, { IP6OPT_MPL, "MPL Option" }, { IP6OPT_EXP_7E, "Experimental (0x7E)" }, { IP6OPT_ENDI, "Endpoint Identification" }, @@ -627,12 +926,15 @@ static const gint _ipv6_opt_type_hdr[][2] = { { IP6OPT_TEL, IPv6_OPT_HDR_DST }, { IP6OPT_RTALERT, IPv6_OPT_HDR_HBH }, { IP6OPT_PMTU, IPv6_OPT_HDR_HBH }, + { IP6OPT_APN6, IPv6_OPT_HDR_ANY }, { IP6OPT_CALIPSO, IPv6_OPT_HDR_HBH }, { IP6OPT_SMF_DPD, IPv6_OPT_HDR_HBH }, { IP6OPT_PDM, IPv6_OPT_HDR_DST }, + { IP6OPT_RPL, IPv6_OPT_HDR_HBH }, { IP6OPT_QUICKSTART, IPv6_OPT_HDR_HBH }, + { IP6OPT_IOAM, IPv6_OPT_HDR_HBH }, { IP6OPT_TPF, IPv6_OPT_HDR_DST }, - { IP6OPT_RPL, IPv6_OPT_HDR_HBH }, + { IP6OPT_RPL_OLD, IPv6_OPT_HDR_HBH }, { IP6OPT_MPL, IPv6_OPT_HDR_HBH }, { IP6OPT_ILNP_NONCE, IPv6_OPT_HDR_DST }, { IP6OPT_LIO, IPv6_OPT_HDR_DST }, @@ -689,6 +991,37 @@ static const value_string mpl_seed_id_len_vals[] = { { 0, NULL } }; +static const value_string ipv6_multicast_scope_vals[] = { + { 0x0, "Reserved" }, + { 0x1, "Interface-Local scope" }, + { 0x2, "Link-Local scope" }, + { 0x3, "Realm-Local scope" }, + { 0x4, "Admin-Local scope" }, + { 0x5, "Site-Local scope" }, + { 0x6, "Unassigned" }, + { 0x7, "Unassigned" }, + { 0x8, "Organization-Local scope" }, + { 0x9, "Unassigned" }, + { 0xA, "Unassigned" }, + { 0xB, "Unassigned" }, + { 0xC, "Unassigned" }, + { 0xD, "Unassigned" }, + { 0xE, "Global scope" }, + { 0xF, "Reserved" }, + { 0, NULL } +}; + +#define APN_ID_32BIT 1 +#define APN_ID_64BIT 2 +#define APN_ID_128BIT 3 +static const value_string apn_id_type_strs[] = { + { 0, "Invalid" }, + { APN_ID_32BIT, "32-bit" }, + { APN_ID_64BIT, "64-bit" }, + { APN_ID_128BIT, "128-bit" }, + { 0, NULL } +}; + static gboolean capture_ipv6(const guchar *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header) { @@ -730,7 +1063,7 @@ capture_ipv6_exthdr(const guchar *pd, int offset, int len, capture_packet_info_t } static void -add_geoip_info_entry(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset, const ws_in6_addr *ip6, int isdst) +add_geoip_info_entry(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset, const ws_in6_addr *ip6, gboolean isdst) { const mmdb_lookup_t *lookup = maxmind_db_lookup_ipv6(ip6); if (!lookup->found) return; @@ -755,7 +1088,7 @@ add_geoip_info_entry(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint o wmem_strbuf_append(summary, lookup->as_org); } - int addr_offset = offset + isdst ? IP6H_DST : IP6H_SRC; + int addr_offset = offset + (isdst ? IP6H_DST : IP6H_SRC); int dir_hf = isdst ? hf_geoip_dst_summary : hf_geoip_src_summary; proto_item *geoip_info_item = proto_tree_add_string(tree, dir_hf, tvb, addr_offset, 16, wmem_strbuf_finalize(summary)); proto_item_set_generated(geoip_info_item); @@ -1496,7 +1829,7 @@ dissect_opt_tel(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *opt_ less than the IPv6 minimum link MTU [RFC8200] should be ignored. - Rtn-PMTU: n 15-bits. The returned mimimum PMTU, carrying the 15 + Rtn-PMTU: n 15-bits. The returned minimum PMTU, carrying the 15 most significant bits of the latest received Min-PMTU field. The value zero means that no Reported MTU is being returned. @@ -1533,6 +1866,90 @@ dissect_opt_pmtu(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *opt } /* + * IETF APN6 + * + * Application-Aware IPv6 Networking (APN6) + * + * https://datatracker.ietf.org/wg/apn/about/ + * https://datatracker.ietf.org/doc/draft-li-apn-header/ + * https://datatracker.ietf.org/doc/draft-li-apn-ipv6-encap/ + * + * 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | APN-ID-Type | Flags | APN-Para-Type | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | APN-ID | + | (32-bit/64-bit/128-bit) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * */ +static gint +dissect_opt_apn6(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *opt_tree, + struct opt_proto_item *opt_ti, guint8 opt_len) +{ + if (opt_len < 8) { + expert_add_info_format(pinfo, opt_ti->len, &ei_ipv6_opt_invalid_len, + "APN6 Option: Invalid Length (%u bytes) for basic APN header and shortest APN ID(32-bit)", opt_len); + } + + guint32 parsed_offset = 0; // offset is for DOH header; parsed_offset is for APN option. + proto_tree *sub_tree = proto_tree_add_subtree(opt_tree, tvb, offset, opt_len, 0, NULL, "APN Header"); + + guint8 apn_id_type = tvb_get_guint8(tvb, offset); + proto_item *apn_id_type_i = proto_tree_add_item(sub_tree, hf_ipv6_opt_apn_id_type, tvb, offset, 1, ENC_BIG_ENDIAN); + + offset++; + parsed_offset++; + + if (apn_id_type < APN_ID_32BIT || apn_id_type > APN_ID_128BIT) { + expert_add_info_format(pinfo, apn_id_type_i, &ei_ipv6_opt_apn_invalid_id_type, + "APN6 Option: Invalid APN ID Type (%u)", apn_id_type); + } + + + proto_tree_add_item(sub_tree, hf_ipv6_opt_apn_flags, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + parsed_offset++; + + proto_tree_add_item(sub_tree, hf_ipv6_opt_apn_param_type, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + parsed_offset += 2; + + + if (apn_id_type >= APN_ID_32BIT) { + proto_tree_add_item(sub_tree, hf_ipv6_opt_apn_id_part1, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + parsed_offset += 4; + } + if (apn_id_type >= APN_ID_64BIT) { + if (opt_len - parsed_offset < 4) { + expert_add_info_format(pinfo, opt_ti->len, &ei_ipv6_opt_invalid_len, + "APN6 Option: Invalid Length (%u bytes) for 64-bit APN ID, parsed offset %u", + opt_len, parsed_offset); + } + proto_tree_add_item(sub_tree, hf_ipv6_opt_apn_id_part2, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + parsed_offset += 4; + } + if (apn_id_type >= APN_ID_128BIT) { + if (opt_len - parsed_offset < 8) { + expert_add_info_format(pinfo, opt_ti->len, &ei_ipv6_opt_invalid_len, + "APN6 Option: Invalid Length (%u bytes) for 128-bit APN ID, parsed offset %u", + opt_len, parsed_offset); + } + + proto_tree_add_item(sub_tree, hf_ipv6_opt_apn_id_part3, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + proto_tree_add_item(sub_tree, hf_ipv6_opt_apn_id_part4, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + return offset; +} + + +/* * IPv6 Router Alert Option * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -1624,6 +2041,386 @@ dissect_opt_quickstart(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tre return offset; } +static const value_string ipv6_ioam_opt_types[] = { + { IP6IOAM_PRE_TRACE, "Pre-allocated Trace" }, + { IP6IOAM_INC_TRACE, "Incremental Trace" }, + { IP6IOAM_POT, "Proof of Transit" }, + { IP6IOAM_E2E, "Edge to Edge" }, + { 0, NULL} +}; + +static gint +dissect_opt_ioam_trace_node(tvbuff_t *tvb, gint offset, + proto_tree *opt_tree, guint32 trace_type) +{ + proto_tree* sub_tree; + + if (trace_type & IP6IOAM_TRACE_MASK_BIT0) { + sub_tree = proto_tree_add_subtree(opt_tree, tvb, offset, 4, 0, NULL, + "Hop_Lim and Node ID (short)"); + proto_tree_add_item(sub_tree, hf_ipv6_opt_ioam_trace_node_hlim, + tvb, offset, 1, ENC_NA); + proto_tree_add_item(sub_tree, hf_ipv6_opt_ioam_trace_node_id, + tvb, offset + 1, 3, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT1) { + sub_tree = proto_tree_add_subtree(opt_tree, tvb, offset, 4, 0, NULL, + "Ingress and Egress IDs (short)"); + proto_tree_add_item(sub_tree, hf_ipv6_opt_ioam_trace_node_iif, + tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_ipv6_opt_ioam_trace_node_eif, + tvb, offset + 2, 2, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT2) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_tss, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT3) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_tsf, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT4) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_trdelay, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT5) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_nsdata, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT6) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_qdepth, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT7) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_csum, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT8) { + sub_tree = proto_tree_add_subtree(opt_tree, tvb, offset, 8, 0, NULL, + "Hop_Lim and Node ID (wide)"); + proto_tree_add_item(sub_tree, hf_ipv6_opt_ioam_trace_node_hlim, + tvb, offset, 1, ENC_NA); + proto_tree_add_item(sub_tree, hf_ipv6_opt_ioam_trace_node_id_wide, + tvb, offset + 1, 7, ENC_BIG_ENDIAN); + offset += 8; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT9) { + sub_tree = proto_tree_add_subtree(opt_tree, tvb, offset, 8, 0, NULL, + "Ingress and Egress IDs (wide)"); + proto_tree_add_item(sub_tree, hf_ipv6_opt_ioam_trace_node_iif_wide, + tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_ipv6_opt_ioam_trace_node_eif_wide, + tvb, offset + 4, 4, ENC_BIG_ENDIAN); + offset += 8; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT10) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_nsdata_wide, + tvb, offset, 8, ENC_BIG_ENDIAN); + offset += 8; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT11) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_bufoccup, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT12) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT13) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT14) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT15) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT16) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT17) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT18) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT19) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT20) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (trace_type & IP6IOAM_TRACE_MASK_BIT21) { + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_node_undefined, + tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + return offset; +} + +/* + * IOAM Trace Option Header + * + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Namespace-ID | NodeLen | Flags | RemainingLen| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | IOAM-Trace-Type | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<-+ + | | | + | node data list [0] | | + | | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ D + | | a + | node data list [1] | t + | | a + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ~ ........ ~ S + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ p + | | a + | node data list [n-1] | c + | | e + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | + | | | + | node data list [n] | | + | | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<-+ +*/ +static gint +dissect_opt_ioam_trace(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *opt_tree, struct opt_proto_item *opt_ti, guint8 opt_len) +{ + proto_item *ti; + guint32 trace_type, oss_scid; + guint16 len; + guint8 remlen, nodelen, oss_len, i = 0; + gint new_offset; + + static int * const ioam_trace_flags[] = { + &hf_ipv6_opt_ioam_trace_flag_o, + &hf_ipv6_opt_ioam_trace_flag_l, + &hf_ipv6_opt_ioam_trace_flag_a, + &hf_ipv6_opt_ioam_trace_flag_rsv, + NULL + }; + + static int * const ioam_trace_types[] = { + &hf_ipv6_opt_ioam_trace_type_bit0, + &hf_ipv6_opt_ioam_trace_type_bit1, + &hf_ipv6_opt_ioam_trace_type_bit2, + &hf_ipv6_opt_ioam_trace_type_bit3, + &hf_ipv6_opt_ioam_trace_type_bit4, + &hf_ipv6_opt_ioam_trace_type_bit5, + &hf_ipv6_opt_ioam_trace_type_bit6, + &hf_ipv6_opt_ioam_trace_type_bit7, + &hf_ipv6_opt_ioam_trace_type_bit8, + &hf_ipv6_opt_ioam_trace_type_bit9, + &hf_ipv6_opt_ioam_trace_type_bit10, + &hf_ipv6_opt_ioam_trace_type_bit11, + &hf_ipv6_opt_ioam_trace_type_undef, + &hf_ipv6_opt_ioam_trace_type_bit22, + &hf_ipv6_opt_ioam_trace_type_rsv, + NULL + }; + + if (opt_len < 10) { + expert_add_info_format(pinfo, opt_ti->len, &ei_ipv6_opt_invalid_len, + "IOAM Option: Invalid length (%u bytes)", opt_len); + } + + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_ns, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + nodelen = tvb_get_bits8(tvb, offset * 8, 5); + ti = proto_tree_add_bits_item(opt_tree, hf_ipv6_opt_ioam_trace_nodelen, tvb, + offset * 8, 5, ENC_BIG_ENDIAN); + if (!nodelen) + expert_add_info(pinfo, ti, &ei_ipv6_opt_ioam_invalid_nodelen); + + proto_tree_add_bitmask(opt_tree, tvb, offset, hf_ipv6_opt_ioam_trace_flags, + ett_ipv6_opt_ioam_trace_flags, ioam_trace_flags, ENC_NA); + + remlen = tvb_get_bits8(tvb, offset * 8 + 9, 7); + ti = proto_tree_add_bits_item(opt_tree, hf_ipv6_opt_ioam_trace_remlen, tvb, + offset * 8 + 9, 7, ENC_BIG_ENDIAN); + if (remlen * 4 > opt_len - 10) { + expert_add_info_format(pinfo, ti, &ei_ipv6_opt_ioam_invalid_remlen, + "IOAM RemLen: Invalid length (%u bytes)", remlen * 4); + } + + offset += 2; + + trace_type = tvb_get_bits32(tvb, offset * 8, 24, ENC_BIG_ENDIAN); + ti = proto_tree_add_bitmask(opt_tree, tvb, offset, hf_ipv6_opt_ioam_trace_type, + ett_ipv6_opt_ioam_trace_types, ioam_trace_types, ENC_BIG_ENDIAN); + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_trace_rsv, tvb, offset + 3, 1, ENC_NA); + offset += 4; + + /* node data list parsing starts here */ + if (!nodelen || remlen * 4 > opt_len - 10) + return offset; + + proto_tree* trace_tree + = proto_tree_add_subtree(opt_tree, tvb, offset, opt_len - 10, 0, NULL, "Trace Data"); + + if (remlen) { + proto_tree_add_item(trace_tree, hf_ipv6_opt_ioam_trace_free_space, tvb, + offset, remlen * 4, ENC_NA); + offset += remlen * 4; + } + + len = opt_len - 10 - remlen * 4; + while (len && len >= nodelen * 4) { + proto_tree* node_tree + = proto_tree_add_subtree_format(trace_tree, tvb, offset, + nodelen * 4, 0, NULL, "Node %u", ++i); + + new_offset = dissect_opt_ioam_trace_node(tvb, offset, node_tree, trace_type); + if (new_offset - offset != nodelen * 4) { + expert_add_info(pinfo, ti, &ei_ipv6_opt_ioam_invalid_trace_type); + return offset; + } + + offset = new_offset; + len -= nodelen * 4; + + /* Opaque State Snapshot */ + if (trace_type & IP6IOAM_TRACE_MASK_BIT22) { + if (len < 4) { + expert_add_info_format(pinfo, opt_ti->len, &ei_ipv6_opt_invalid_len, + "IOAM Option: Invalid length (%u bytes)", opt_len); + return offset; + } + + oss_len = tvb_get_guint8(tvb, offset); + + proto_tree* oss_tree + = proto_tree_add_subtree(node_tree, tvb, offset, (oss_len + 1) * 4, + 0, NULL, "Opaque State Snapshot"); + proto_tree_add_item(oss_tree, hf_ipv6_opt_ioam_trace_node_oss_len, + tvb, offset, 1, ENC_NA); + proto_tree_add_item_ret_uint(oss_tree, hf_ipv6_opt_ioam_trace_node_oss_scid, + tvb, offset + 1, 3, ENC_BIG_ENDIAN, &oss_scid); + offset += 4; + + len -= 4; + if (len < oss_len * 4) { + expert_add_info_format(pinfo, opt_ti->len, &ei_ipv6_opt_invalid_len, + "IOAM Option: Invalid length (%u bytes)", opt_len); + return offset; + } + + if (oss_len > 0) { + proto_tree_add_item(oss_tree, hf_ipv6_opt_ioam_trace_node_oss_data, + tvb, offset, oss_len * 4, ENC_NA); + + len -= oss_len * 4; + offset += oss_len * 4; + } + } + } + + if (len) { + expert_add_info_format(pinfo, opt_ti->len, &ei_ipv6_opt_invalid_len, + "IOAM Option: Invalid length (%u bytes)", opt_len); + } + + return offset; +} + +/* + * IOAM Option Header + * + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Option Type | Opt Data Len | Reserved | IOAM Type | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +static gint +dissect_opt_ioam(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *opt_tree, struct opt_proto_item *opt_ti, guint8 opt_len) +{ + guint32 opt_type; + + if (opt_len < 2) { + expert_add_info_format(pinfo, opt_ti->len, &ei_ipv6_opt_invalid_len, + "IOAM Option: Invalid length (%u bytes)", opt_len); + } + + proto_tree_add_item(opt_tree, hf_ipv6_opt_ioam_rsv, tvb, offset, 1, ENC_NA); + proto_tree_add_item_ret_uint(opt_tree, hf_ipv6_opt_ioam_opt_type, tvb, + offset + 1, 1, ENC_NA, &opt_type); + offset += 2; + + proto_tree* opt_type_tree + = proto_tree_add_subtree(opt_tree, tvb, offset, opt_len - 2, 0, NULL, + val_to_str_const(opt_type, ipv6_ioam_opt_types, + "Unknown Option-Type")); + + switch (opt_type) { + case IP6IOAM_PRE_TRACE: + case IP6IOAM_INC_TRACE: + offset = dissect_opt_ioam_trace(tvb, offset, pinfo, opt_type_tree, opt_ti, opt_len); + break; + case IP6IOAM_POT: + break; + case IP6IOAM_E2E: + break; + } + + return offset; +} + /* * Tunnel Payload Forwarding Option for IPv6 * @@ -2088,6 +2885,7 @@ dissect_opts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, ws offset = dissect_opt_jumbo(tvb, offset, pinfo, opt_tree, &opt_ti, opt_len); break; case IP6OPT_RPL: + case IP6OPT_RPL_OLD: offset = dissect_opt_rpl(tvb, offset, pinfo, opt_tree, &opt_ti, opt_len); break; case IP6OPT_TEL: @@ -2099,9 +2897,15 @@ dissect_opts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, ws case IP6OPT_PMTU: offset = dissect_opt_pmtu(tvb, offset, pinfo, opt_tree, &opt_ti, opt_len); break; + case IP6OPT_APN6: + offset = dissect_opt_apn6(tvb, offset, pinfo, opt_tree, &opt_ti, opt_len); + break; case IP6OPT_QUICKSTART: offset = dissect_opt_quickstart(tvb, offset, pinfo, opt_tree, &opt_ti, opt_len, iph); break; + case IP6OPT_IOAM: + offset = dissect_opt_ioam(tvb, offset, pinfo, opt_tree, &opt_ti, opt_len); + break; case IP6OPT_TPF: offset = dissect_opt_tpf(tvb, offset, pinfo, opt_tree, &opt_ti, opt_len); break; @@ -2217,21 +3021,160 @@ ipv6_get_jumbo_plen(tvbuff_t *tvb, gint offset) } static void +add_ipv6_address_detail(packet_info *pinfo, proto_item *vis, proto_item *invis, + tvbuff_t *tvb, int offset, struct ipv6_addr_info_s *addr_info) +{ + proto_item *ti; + proto_tree *vtree; /* visible tree */ + proto_tree *itree; /* invisible tree */ + + vtree = proto_item_add_subtree(vis, ett_ipv6_detail); + itree = proto_item_add_subtree(invis, ett_ipv6_detail); + + /* + * Internet Protocol Version 6 Address Space + * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml + */ + if (tvb_get_guint8(tvb, offset) == 0xFF) { + /* RFC 4291 section 2.4: multicast prefix */ + ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, 1, "Multicast"); + proto_item_set_generated(ti); + if (addr_info == &ipv6_src_info) { + /* "Shouldn't" see this one as a source */ + expert_add_info(pinfo, ti, &ei_ipv6_src_addr_not_multicast); + } + + ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, 1, "Multicast"); + proto_item_set_generated(ti); + + /* + * Multicast address scope and flags. + * + * RFC 4291 Section 2.7: + * https://www.rfc-editor.org/rfc/rfc4291#section-2.7 + * + * RFC 7346: + * https://www.rfc-editor.org/rfc/rfc7346.html + * + * IANA Registry: + * https://www.iana.org/assignments/ipv6-multicast-addresses/ipv6-multicast-addresses.xhtml#ipv6-scope + */ + + static int *const hf_ipv6_multicast_flags_bits[] = { + &hf_ipv6_multicast_flags_reserved, + &hf_ipv6_multicast_flags_embed_rp, + &hf_ipv6_multicast_flags_network_prefix, + &hf_ipv6_multicast_flags_transient, + NULL + }; + + /* Add multicast address flags. */ + ti = proto_tree_add_bitmask(vtree, tvb, offset, *addr_info->hf_multicast_flags, + ett_ipv6_multicast_flags, addr_info->hf_multicast_flags_bits, ENC_BIG_ENDIAN); + proto_item_set_generated(ti); + ti = proto_tree_add_bitmask(itree, tvb, offset, hf_ipv6_multicast_flags, + ett_ipv6_multicast_flags, hf_ipv6_multicast_flags_bits, ENC_BIG_ENDIAN); + proto_item_set_generated(ti); + + /* Add multicast address scope. */ + ti = proto_tree_add_item(vtree, *addr_info->hf_multicast_scope, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_item_set_generated(ti); + ti = proto_tree_add_item(itree, hf_ipv6_multicast_scope, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_item_set_generated(ti); + } + else if ((tvb_get_ntohs(tvb, offset) & 0xFFC0) == 0xFE80) { + ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, 2, "Link-Local Unicast"); + proto_item_set_generated(ti); + ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, 2, "Link-Local Unicast"); + proto_item_set_generated(ti); + } + else if ((tvb_get_guint8(tvb, offset) & 0x30) == 0x20) { + ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, 2, "Global Unicast"); + proto_item_set_generated(ti); + ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, 2, "Global Unicast"); + proto_item_set_generated(ti); + } + else if ((tvb_get_guint8(tvb, offset) & 0xFE) == 0xFC) { + ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, 2, "Unique Local Unicast"); + proto_item_set_generated(ti); + ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, 2, "Unique Local Unicast"); + proto_item_set_generated(ti); + } + else { + ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, 2, "Reserved by IETF"); + proto_item_set_generated(ti); + ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, 2, "Reserved by IETF"); + proto_item_set_generated(ti); + } + + /* Check for IPv6 address special-purpose ranges. */ + const ws_in6_addr *addr = tvb_get_ptr_ipv6(tvb, offset); + const struct ws_iana_ip_special_block *block; + proto_tree *vtree2; + proto_tree *itree2; + + if ((block = ws_iana_ipv6_special_block_lookup(addr)) != NULL) { + ti = proto_tree_add_string(vtree, *addr_info->hf_special_purpose, tvb, offset, IPv6_ADDR_SIZE, block->name); + proto_item_set_generated(ti); + vtree2 = proto_item_add_subtree(ti, ett_ipv6_detail_special_purpose); + + ti = proto_tree_add_string(itree, hf_ipv6_addr_special_purpose, tvb, offset, IPv6_ADDR_SIZE, block->name); + proto_item_set_generated(ti); + itree2 = proto_item_add_subtree(ti, ett_ipv6_detail_special_purpose); + + if (block->source >= 0) { + ti = proto_tree_add_boolean(vtree2, *addr_info->hf_special_purpose_source, tvb, offset, IPv6_ADDR_SIZE, block->source); + proto_item_set_generated(ti); + ti = proto_tree_add_boolean(itree2, hf_ipv6_addr_special_purpose_source, tvb, offset, IPv6_ADDR_SIZE, block->source); + proto_item_set_generated(ti); + } + if (block->destination >= 0) { + ti = proto_tree_add_boolean(vtree2, *addr_info->hf_special_purpose_destination, tvb, offset, IPv6_ADDR_SIZE, block->destination); + proto_item_set_generated(ti); + ti = proto_tree_add_boolean(itree2, hf_ipv6_addr_special_purpose_destination, tvb, offset, IPv6_ADDR_SIZE, block->destination); + proto_item_set_generated(ti); + } + if (block->forwardable >= 0) { + ti = proto_tree_add_boolean(vtree2, *addr_info->hf_special_purpose_forwardable, tvb, offset, IPv6_ADDR_SIZE, block->forwardable); + proto_item_set_generated(ti); + ti = proto_tree_add_boolean(itree2, hf_ipv6_addr_special_purpose_forwardable, tvb, offset, IPv6_ADDR_SIZE, block->forwardable); + proto_item_set_generated(ti); + } + if (block->global >= 0) { + ti = proto_tree_add_boolean(vtree2, *addr_info->hf_special_purpose_global, tvb, offset, IPv6_ADDR_SIZE, block->global); + proto_item_set_generated(ti); + ti = proto_tree_add_boolean(itree2, hf_ipv6_addr_special_purpose_global, tvb, offset, IPv6_ADDR_SIZE, block->global); + proto_item_set_generated(ti); + } + if (block->reserved >= 0) { + ti = proto_tree_add_boolean(vtree2, *addr_info->hf_special_purpose_reserved, tvb, offset, IPv6_ADDR_SIZE, block->reserved); + proto_item_set_generated(ti); + ti = proto_tree_add_boolean(itree2, hf_ipv6_addr_special_purpose_reserved, tvb, offset, IPv6_ADDR_SIZE, block->reserved); + proto_item_set_generated(ti); + } + } +} + +static void add_ipv6_address(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, - gint hf_addr, gint hf_host) + struct ipv6_addr_info_s *addr_info) { address addr; const char *name; - proto_item *ti; + proto_item *ti, *vis, *invis; - proto_tree_add_item(tree, hf_addr, tvb, offset, IPv6_ADDR_SIZE, ENC_NA); - ti = proto_tree_add_item(tree, hf_ipv6_addr, tvb, offset, IPv6_ADDR_SIZE, ENC_NA); - proto_item_set_hidden(ti); + vis = proto_tree_add_item(tree, *addr_info->hf_addr, tvb, offset, IPv6_ADDR_SIZE, ENC_NA); + invis = proto_tree_add_item(tree, hf_ipv6_addr, tvb, offset, IPv6_ADDR_SIZE, ENC_NA); + proto_item_set_hidden(invis); set_address_ipv6_tvb(&addr, tvb, offset); name = address_to_display(pinfo->pool, &addr); - ti = proto_tree_add_string(tree, hf_host, tvb, offset, IPv6_ADDR_SIZE, name); + if (ipv6_address_detail) { + add_ipv6_address_detail(pinfo, vis, invis, tvb, offset, addr_info); + } + + ti = proto_tree_add_string(tree, *addr_info->hf_host, tvb, offset, IPv6_ADDR_SIZE, name); proto_item_set_generated(ti); proto_item_set_hidden(ti); ti = proto_tree_add_string(tree, hf_ipv6_host, tvb, offset, IPv6_ADDR_SIZE, name); @@ -2337,29 +3280,178 @@ add_ipv6_address_isatap(proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_isa /* RFC 6052 */ static void -add_ipv6_address_embed_ipv4(proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_embed) +add_ipv6_address_embed_ipv4(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_embed) { - /* Well-Known Prefix for IPv4-Embedded IPv6 Address: 64:FF9B::/96 */ - static const guint8 ipv6_embedded_ipv4_well_known_prefix[] = { + /* Section 2.1: Well-Known Prefix for IPv4-Embedded IPv6 Address: 64:FF9B::/96 */ + static const guint8 well_known_prefix[] = { 0x00, 0x64, 0xFF, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - /* Check for well-known prefix */ - if (tvb_memeql(tvb, offset, ipv6_embedded_ipv4_well_known_prefix, 12) != 0) - return; - struct { gint embed; } hf[2] = { - { hf_embed }, - { hf_ipv6_embed_ipv4 } - }; - proto_item *ti; - for (int i = 0; i < 2; i++) { - ti = proto_tree_add_item(tree, hf[i].embed, tvb, offset + 12, 4, ENC_NA); - ADDRESS_SET_GENERATED_HIDDEN(ti); + ws_in6_addr ipv6_addr; + ws_in4_addr ipv4_addr; + gint ipv4_prefix; + gint ipv4_offset; + gboolean ipv6_embed_ipv4 = false; + + if (tvb_memeql(tvb, offset, well_known_prefix, sizeof well_known_prefix) == 0) { + ipv4_addr = tvb_get_bits32(tvb, (offset * 8) + 96, 32, ENC_BIG_ENDIAN); + ipv4_prefix = 96; + ipv4_offset = 96; + ipv6_embed_ipv4 = true; + } else { + for (size_t j = 0; j < number_of_nat64_prefix; j++) { + if (nat64_prefix_uats[j].prefix_len <= nat64_prefix_uats[j].prefix_wildcard_len) { + continue; + } + + if (ws_inet_pton6(nat64_prefix_uats[j].ipaddr, &ipv6_addr)) { + if (tvb_memeql(tvb, offset, (const guint8 *)&ipv6_addr, + (nat64_prefix_uats[j].prefix_len - nat64_prefix_uats[j].prefix_wildcard_len) / 8) == 0) { + switch (nat64_prefix_uats[j].prefix_len) + { + case 32: + ipv4_addr = tvb_get_bits32(tvb, (offset * 8) + 32, 32, ENC_BIG_ENDIAN); + break; + case 40: + ipv4_addr = tvb_get_bits32(tvb, (offset * 8) + 40, 24, ENC_BIG_ENDIAN) << 8; + ipv4_addr |= tvb_get_bits32(tvb, (offset * 8) + 72, 8, ENC_BIG_ENDIAN); + break; + case 48: + ipv4_addr = tvb_get_bits32(tvb, (offset * 8) + 48, 16, ENC_BIG_ENDIAN) << 16; + ipv4_addr |= tvb_get_bits32(tvb, (offset * 8) + 72, 16, ENC_BIG_ENDIAN); + break; + case 56: + ipv4_addr = tvb_get_bits32(tvb, (offset * 8) + 56, 8, ENC_BIG_ENDIAN) << 24; + ipv4_addr |= tvb_get_bits32(tvb, (offset * 8) + 72, 24, ENC_BIG_ENDIAN); + break; + case 64: + ipv4_addr = tvb_get_bits32(tvb, (offset * 8) + 72, 32, ENC_BIG_ENDIAN); + break; + case 96: + ipv4_addr = tvb_get_bits32(tvb, (offset * 8) + 96, 32, ENC_BIG_ENDIAN); + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + } + + ipv4_prefix = nat64_prefix_uats[j].prefix_len; + if (ipv4_prefix != 64) { + ipv4_offset = ipv4_prefix; + } else { + ipv4_offset = 72; + } + ipv6_embed_ipv4 = true; + break; + } + } + } + } + + if (ipv6_embed_ipv4) { + proto_item *ti; + + // The prefix + ti = proto_tree_add_item(tree, hf_ipv6_embed_ipv4_prefix, tvb, offset, ipv4_prefix / 8, ENC_NA); + proto_item_set_generated(ti); + + // Majority of IPv4 address is after u-field + if (ipv4_prefix >= 56) { + if (ipv4_prefix < 96) { + ti = proto_tree_add_item(tree, hf_ipv6_embed_ipv4_u, tvb, offset + 8, 1, ENC_NA); + proto_item_set_generated(ti); + } + if (tvb_get_guint8(tvb, offset + 8)) { + expert_add_info(pinfo, ti, &ei_ipv6_embed_ipv4_u_value); + } + } + + // IPv4 embedded address + ipv4_addr = g_ntohl(ipv4_addr); + ti = proto_tree_add_ipv4(tree, hf_embed, tvb, + offset + (ipv4_offset / 8), + (ipv4_offset > 32 && ipv4_offset < 64) ? 5 : 4, ipv4_addr); + proto_item_set_generated(ti); + + ti = proto_tree_add_ipv4(tree, hf_ipv6_embed_ipv4, tvb, + offset + (ipv4_offset / 8), + (ipv4_offset > 32 && ipv4_offset < 64) ? 5 : 4, ipv4_addr); + proto_item_set_generated(ti); + + // Majority of IPv4 address is before u-field + if (ipv4_prefix < 56) { + ti = proto_tree_add_item(tree, hf_ipv6_embed_ipv4_u, tvb, offset + 8, 1, ENC_NA); + proto_item_set_generated(ti); + if (tvb_get_guint8(tvb, offset + 8)) { + expert_add_info(pinfo, ti, &ei_ipv6_embed_ipv4_u_value); + } + } + + // Suffix, if present + if (ipv4_prefix < 96) { + ti = proto_tree_add_item(tree, hf_ipv6_embed_ipv4_suffix, tvb, + offset + ((72 + ipv4_prefix - 32) / 8), + (56 - (ipv4_prefix - 32)) / 8, + ENC_NA); + proto_item_set_generated(ti); + } } } +static void +export_pdu(tvbuff_t *tvb, packet_info *pinfo) +{ + if (have_tap_listener(exported_pdu_tap)) { + exp_pdu_data_t *exp_pdu_data = wmem_new0(pinfo->pool, exp_pdu_data_t); + + exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); + exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); + exp_pdu_data->pdu_tvb = tvb; + tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); + } +} + +static struct ipv6_analysis * +init_ipv6_conversation_data(packet_info *pinfo) +{ + struct ipv6_analysis *ipv6d; + + /* Initialize the ip protocol data structure to add to the ip conversation */ + ipv6d=wmem_new0(wmem_file_scope(), struct ipv6_analysis); + + ipv6d->initial_frame = pinfo->num; + ipv6d->stream = 0; + ipv6d->stream = ipv6_stream_count++; + + return ipv6d; +} + +struct ipv6_analysis * +get_ipv6_conversation_data(conversation_t *conv, packet_info *pinfo) +{ + struct ipv6_analysis *ipv6d; + + /* Did the caller supply the conversation pointer? */ + if( conv==NULL ) { + return NULL; + } + + /* Get the data for this conversation */ + ipv6d=(struct ipv6_analysis *)conversation_get_proto_data(conv, proto_ipv6); + + if (!ipv6d) { + ipv6d = init_ipv6_conversation_data(pinfo); + conversation_add_proto_data(conv, proto_ipv6, ipv6d); + } + + if (!ipv6d) { + return NULL; + } + + return ipv6d; +} + static int dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { @@ -2377,15 +3469,19 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ gboolean save_fragmented; int version; ws_ip6 *iph; + struct ipv6_analysis *ipv6d=NULL; offset = 0; + iph = wmem_new0(pinfo->pool, ws_ip6); + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPv6"); col_clear(pinfo->cinfo, COL_INFO); ipv6_item = proto_tree_add_item(tree, proto_ipv6, tvb, offset, IPv6_HDR_SIZE, ENC_NA); ipv6_tree = proto_item_add_subtree(ipv6_item, ett_ipv6_proto); + /* Validate IP version (6) */ version = tvb_get_bits8(tvb, (offset + IP6H_CTL_VFC) * 8, 4); ti_ipv6_version = proto_tree_add_bits_item(ipv6_tree, hf_ipv6_version, tvb, @@ -2459,13 +3555,13 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ ip6_hlim = tvb_get_guint8(tvb, offset + IP6H_CTL_HLIM); /* Source address */ - add_ipv6_address(pinfo, ipv6_tree, tvb, offset + IP6H_SRC, hf_ipv6_src, hf_ipv6_src_host); + add_ipv6_address(pinfo, ipv6_tree, tvb, offset + IP6H_SRC, &ipv6_src_info); ip6_src = tvb_get_ptr_ipv6(tvb, offset + IP6H_SRC); alloc_address_wmem_ipv6(pinfo->pool, &pinfo->net_src, ip6_src); copy_address_shallow(&pinfo->src, &pinfo->net_src); /* Destination address */ - add_ipv6_address(pinfo, ipv6_tree, tvb, offset + IP6H_DST, hf_ipv6_dst, hf_ipv6_dst_host); + add_ipv6_address(pinfo, ipv6_tree, tvb, offset + IP6H_DST, &ipv6_dst_info); ip6_dst = tvb_get_ptr_ipv6(tvb, offset + IP6H_DST); alloc_address_wmem_ipv6(pinfo->pool, &pinfo->net_dst, ip6_dst); copy_address_shallow(&pinfo->dst, &pinfo->net_dst); @@ -2494,10 +3590,10 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ add_ipv6_address_isatap(ipv6_tree, tvb, offset + IP6H_SRC, hf_ipv6_src_isatap_ipv4); add_ipv6_address_isatap(ipv6_tree, tvb, offset + IP6H_DST, hf_ipv6_dst_isatap_ipv4); - add_ipv6_address_embed_ipv4(ipv6_tree, tvb, offset + IP6H_SRC, hf_ipv6_src_embed_ipv4); - add_ipv6_address_embed_ipv4(ipv6_tree, tvb, offset + IP6H_DST, hf_ipv6_dst_embed_ipv4); + add_ipv6_address_embed_ipv4(pinfo, ipv6_tree, tvb, offset + IP6H_SRC, hf_ipv6_src_embed_ipv4); + add_ipv6_address_embed_ipv4(pinfo, ipv6_tree, tvb, offset + IP6H_DST, hf_ipv6_dst_embed_ipv4); - if (ipv6_use_geoip) { + if (gbl_resolv_flags.maxmind_geoip) { add_geoip_info(ipv6_tree, pinfo, tvb, offset, ip6_src, ip6_dst); } } @@ -2525,8 +3621,33 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ "IPv6 payload length exceeds framing length (%d bytes)", reported_plen); } + /* conversation management */ + conversation_t *conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_IPV6, 0, 0, NO_PORT_X); + if(!conv) { + conv = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_IPV6, 0, 0, NO_PORTS); + } + else { + /* + * while not strictly necessary because there is only 1 + * conversation between 2 IPs, we still move the last frame + * indicator as being a usual practice. + */ + if (!(pinfo->fd->visited)) { + if (pinfo->num > conv->last_frame) { + conv->last_frame = pinfo->num; + } + } + } + + ipv6d = get_ipv6_conversation_data(conv, pinfo); + if(ipv6d) { + iph->ip6_stream = ipv6d->stream; + + ipv6_item = proto_tree_add_uint(ipv6_tree, hf_ipv6_stream, tvb, 0, 0, ipv6d->stream); + proto_item_set_generated(ipv6_item); + } + /* Fill in IP header fields for subdissectors */ - iph = wmem_new0(pinfo->pool, ws_ip6); iph->ip6_ver = 6; iph->ip6_tc = ip6_tcls; iph->ip6_flw = ip6_flow; @@ -2549,12 +3670,31 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ /* Adjust the length of this tvbuff to include only the IPv6 datagram. */ set_actual_length(tvb, IPv6_HDR_SIZE + plen); + /* Only export after adjusting the length */ + export_pdu(tvb, pinfo); save_fragmented = pinfo->fragmented; p_add_ipv6_nxt(pinfo, ip6_nxt); next_tvb = tvb_new_subset_remaining(tvb, offset); - ipv6_dissect_next(ip6_nxt, next_tvb, pinfo, tree, iph); + TRY { + ipv6_dissect_next(ip6_nxt, next_tvb, pinfo, tree, iph); + } + FINALLY { + /* If we need to extend the length due to an ext header and haven't + * yet, do so now. This might be due to an exception or unreassembled + * fragments. + * XXX: What about the tap? We want to tap if we haven't yet, but + * if we always tapped here we would send to the tap in reverse order + * for IP-in-IP. + */ + if (ipv6_pinfo != NULL && ipv6_pinfo->ipv6_tree != NULL) { + /* Set IPv6 Header length */ + proto_item_set_len(proto_tree_get_parent(ipv6_pinfo->ipv6_tree), ipv6_pinfo->ipv6_item_len); + ipv6_pinfo->ipv6_tree = NULL; + } + } + ENDTRY; pinfo->fragmented = save_fragmented; return tvb_captured_length(tvb); @@ -2566,13 +3706,19 @@ ipv6_dissect_next(guint nxt, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree dissector_handle_t nxt_handle; ipv6_pinfo_t *ipv6_pinfo = p_get_ipv6_pinfo(pinfo); + /* https://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml#extension-header */ + switch (nxt) { case IP_PROTO_HOPOPTS: case IP_PROTO_ROUTING: case IP_PROTO_FRAGMENT: - case IP_PROTO_DSTOPTS: + //case IP_PROTO_ESP: Even though ESP is technically an extension header, + // we treat it as a payload container. case IP_PROTO_AH: + case IP_PROTO_DSTOPTS: case IP_PROTO_MIPV6: + //case IP_PROTO_HIP: Even though HIP is technically an extension header, the only defined + // next header is IP_NONE. Also the HIP dissector is not ready for this. case IP_PROTO_SHIM6: nxt_handle = dissector_get_uint_handle(ip_dissector_table, nxt); break; @@ -2615,6 +3761,12 @@ ipv6_dissect_next(guint nxt, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree call_data_dissector(tvb, pinfo, tree); } +static void +ipv6_init(void) +{ + ipv6_stream_count = 0; +} + void proto_register_ipv6(void) { @@ -2669,6 +3821,76 @@ proto_register_ipv6(void) FT_IPv6, BASE_NONE, NULL, 0x0, "Source IPv6 Address", HFILL } }, + { &hf_ipv6_src_addr_space, + { "Address Space", "ipv6.src_addr_space", + FT_STRING, BASE_NONE, NULL, 0x0, + "Source IPv6 Address Space", HFILL } + }, + { &hf_ipv6_src_multicast_flags, + { "Multicast Flags", "ipv6.src_multicast_flags", + FT_UINT16, BASE_HEX, NULL, 0x00F0, + "Source Address Multicast Flags", HFILL } + }, + { &hf_ipv6_src_multicast_flags_transient, + { "Transient", "ipv6.src_multicast_flags.transient", + FT_BOOLEAN, 16, NULL, 0x0010, + "Source Address Transient Multicast Flag", HFILL } + }, + { &hf_ipv6_src_multicast_flags_network_prefix, + { "Network Prefix", "ipv6.src_multicast_flags.network_prefix", + FT_BOOLEAN, 16, NULL, 0x0020, + "Source Address Network Prefix Multicast Flag", HFILL } + }, + { &hf_ipv6_src_multicast_flags_embed_rp, + { "Rendezvous Point (RP)", "ipv6.src_multicast_flags.embed_rp", + FT_BOOLEAN, 16, NULL, 0x0040, + "Source Address Rendezvous Point (RP) Multicast Flag", HFILL } + }, + { &hf_ipv6_src_multicast_flags_reserved, + { "Reserved", "ipv6.src_multicast_flags.reserved", + FT_UINT16, BASE_DEC, NULL, 0x0080, + "Source Address Reserved Multicast Flag", HFILL } + }, + { &hf_ipv6_src_multicast_scope, + { "Multicast Scope", "ipv6.src_multicast_scope", + FT_UINT16, BASE_HEX, VALS(ipv6_multicast_scope_vals), 0x000F, + "Source Address Multicast Scope", HFILL } + }, + { &hf_ipv6_src_special_purpose, + { "Special-Purpose Allocation", "ipv6.src_special_purpose", + FT_STRING, BASE_NONE, NULL, 0x0, + "Source Address Special-Purpose Allocation", HFILL } + }, + { &hf_ipv6_src_special_purpose_source, + { "Source", "ipv6.src_special_purpose_source", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether an address from the allocated special-purpose address " + "block is valid when used as the source address of an IP datagram", HFILL } + }, + { &hf_ipv6_src_special_purpose_destination, + { "Destination", "ipv6.src_special_purpose_destination", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether an address from the allocated special-purpose address " + "block is valid when used as the destination address of an IP datagram", HFILL } + }, + { &hf_ipv6_src_special_purpose_forwardable, + { "Forwardable", "ipv6.src_special_purpose_forwardable", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether a router may forward an IP datagram whose destination " + "address is drawn from the allocated special-purpose address block", HFILL } + }, + { &hf_ipv6_src_special_purpose_global, + { "Globally Reachable", "ipv6.src_special_purpose_global", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether an IP datagram whose destination address is drawn " + "from the allocated special-purpose address block is " + "forwardable beyond a specified administrative domain", HFILL } + }, + { &hf_ipv6_src_special_purpose_reserved, + { "Reserved-by-Protocol", "ipv6.src_special_purpose_reserved", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether the special-purpose address block is reserved by IP itself", HFILL } + }, { &hf_ipv6_src_host, { "Source Host", "ipv6.src_host", FT_STRING, BASE_NONE, NULL, 0x0, @@ -2712,13 +3934,83 @@ proto_register_ipv6(void) { &hf_ipv6_src_embed_ipv4, { "Source Embedded IPv4", "ipv6.src_embed_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, - "Source IPv4-Embedded IPv6 Address with Well-Known Prefix", HFILL } + "Source IPv4-Embedded IPv6 Address", HFILL } }, { &hf_ipv6_dst, { "Destination Address", "ipv6.dst", FT_IPv6, BASE_NONE, NULL, 0x0, "Destination IPv6 Address", HFILL } }, + { &hf_ipv6_dst_addr_space, + { "Address Space", "ipv6.dst_addr_space", + FT_STRING, BASE_NONE, NULL, 0x0, + "Destination IPv6 Address Space", HFILL } + }, + { &hf_ipv6_dst_multicast_flags, + { "Multicast Flags", "ipv6.dst_multicast_flags", + FT_UINT16, BASE_HEX, NULL, 0x00F0, + "Destination Address Multicast Flags", HFILL } + }, + { &hf_ipv6_dst_multicast_flags_transient, + { "Transient", "ipv6.dst_multicast_flags.transient", + FT_BOOLEAN, 16, NULL, 0x0010, + "Destination Address Transient Multicast Flag", HFILL } + }, + { &hf_ipv6_dst_multicast_flags_network_prefix, + { "Network Prefix", "ipv6.dst_multicast_flags.network_prefix", + FT_BOOLEAN, 16, NULL, 0x0020, + "Destination Address Network Prefix Multicast Flag", HFILL } + }, + { &hf_ipv6_dst_multicast_flags_embed_rp, + { "Rendezvous Point (RP)", "ipv6.dst_multicast_flags.embed_rp", + FT_BOOLEAN, 16, NULL, 0x0040, + "Destination Address Rendezvous Point (RP) Multicast Flag", HFILL } + }, + { &hf_ipv6_dst_multicast_flags_reserved, + { "Reserved", "ipv6.dst_multicast_flags.reserved", + FT_UINT16, BASE_DEC, NULL, 0x0080, + "Destination Address Reserved Multicast Flag", HFILL } + }, + { &hf_ipv6_dst_multicast_scope, + { "Multicast Scope", "ipv6.dst_multicast_scope", + FT_UINT16, BASE_HEX, VALS(ipv6_multicast_scope_vals), 0x000F, + "Destination Address Multicast Scope", HFILL } + }, + { &hf_ipv6_dst_special_purpose, + { "Special-Purpose Allocation", "ipv6.dst_special_purpose", + FT_STRING, BASE_NONE, NULL, 0x0, + "Destination Address Special-Purpose Allocation", HFILL } + }, + { &hf_ipv6_dst_special_purpose_source, + { "Source", "ipv6.dst_special_purpose_source", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether an address from the allocated special-purpose address " + "block is valid when used as the source address of an IP datagram", HFILL } + }, + { &hf_ipv6_dst_special_purpose_destination, + { "Destination", "ipv6.dst_special_purpose_destination", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether an address from the allocated special-purpose address " + "block is valid when used as the destination address of an IP datagram", HFILL } + }, + { &hf_ipv6_dst_special_purpose_forwardable, + { "Forwardable", "ipv6.dst_special_purpose_forwardable", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether a router may forward an IP datagram whose destination " + "address is drawn from the allocated special-purpose address block", HFILL } + }, + { &hf_ipv6_dst_special_purpose_global, + { "Globally Reachable", "ipv6.dst_special_purpose_global", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether an IP datagram whose destination address is drawn " + "from the allocated special-purpose address block is " + "forwardable beyond a specified administrative domain", HFILL } + }, + { &hf_ipv6_dst_special_purpose_reserved, + { "Reserved-by-Protocol", "ipv6.dst_special_purpose_reserved", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether the special-purpose address block is reserved by IP itself", HFILL } + }, { &hf_ipv6_dst_host, { "Destination Host", "ipv6.dst_host", FT_STRING, BASE_NONE, NULL, 0x0, @@ -2762,13 +4054,83 @@ proto_register_ipv6(void) { &hf_ipv6_dst_embed_ipv4, { "Destination Embedded IPv4", "ipv6.dst_embed_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, - "Destination IPv4-Embedded IPv6 Address with Well-Known Prefix", HFILL } + "Destination IPv4-Embedded IPv6 Address", HFILL } }, { &hf_ipv6_addr, { "Source or Destination Address", "ipv6.addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_ipv6_addr_space, + { "Address Space", "ipv6.addr_space", + FT_STRING, BASE_NONE, NULL, 0x0, + "Source or Destination Address Space", HFILL } + }, + { &hf_ipv6_multicast_flags, + { "Multicast Flags", "ipv6.multicast_flags", + FT_UINT16, BASE_HEX, NULL, 0x00F0, + "Source or Destination Address Multicast Flags", HFILL } + }, + { &hf_ipv6_multicast_flags_transient, + { "Transient", "ipv6.multicast_flags.transient", + FT_BOOLEAN, 16, NULL, 0x0010, + "Source or Destination Address Transient Multicast Flag", HFILL } + }, + { &hf_ipv6_multicast_flags_network_prefix, + { "Network Prefix", "ipv6.multicast_flags.network_prefix", + FT_BOOLEAN, 16, NULL, 0x0020, + "Source or Destination Address Network Prefix Multicast Flag", HFILL } + }, + { &hf_ipv6_multicast_flags_embed_rp, + { "Rendezvous Point (RP)", "ipv6.multicast_flags.embed_rp", + FT_BOOLEAN, 16, NULL, 0x0040, + "Source or Destination Address Rendezvous Point (RP) Multicast Flag", HFILL } + }, + { &hf_ipv6_multicast_flags_reserved, + { "Reserved", "ipv6.multicast_flags.reserved", + FT_UINT16, BASE_DEC, NULL, 0x0080, + "Source or Destination Address Reserved Multicast Flag", HFILL } + }, + { &hf_ipv6_multicast_scope, + { "Multicast Scope", "ipv6.multicast_scope", + FT_UINT16, BASE_HEX, VALS(ipv6_multicast_scope_vals), 0x000F, + "Source or Destination Address Multicast Scope", HFILL } + }, + { &hf_ipv6_addr_special_purpose, + { "Special-Purpose Allocation", "ipv6.addr_special_purpose", + FT_STRING, BASE_NONE, NULL, 0x0, + "Source or Destination Address Special-Purpose Allocation", HFILL } + }, + { &hf_ipv6_addr_special_purpose_source, + { "Source", "ipv6.addr_special_purpose_source", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether an address from the allocated special-purpose address " + "block is valid when used as the source address of an IP datagram", HFILL } + }, + { &hf_ipv6_addr_special_purpose_destination, + { "Destination", "ipv6.addr_special_purpose_destination", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether an address from the allocated special-purpose address " + "block is valid when used as the destination address of an IP datagram", HFILL } + }, + { &hf_ipv6_addr_special_purpose_forwardable, + { "Forwardable", "ipv6.addr_special_purpose_forwardable", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether a router may forward an IP datagram whose destination " + "address is drawn from the allocated special-purpose address block", HFILL } + }, + { &hf_ipv6_addr_special_purpose_global, + { "Globally Reachable", "ipv6.addr_special_purpose_global", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether an IP datagram whose destination address is drawn " + "from the allocated special-purpose address block is " + "forwardable beyond a specified administrative domain", HFILL } + }, + { &hf_ipv6_addr_special_purpose_reserved, + { "Reserved-by-Protocol", "ipv6.addr_special_purpose_reserved", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Whether the special-purpose address block is reserved by IP itself", HFILL } + }, { &hf_ipv6_host, { "Source or Destination Host", "ipv6.host", FT_STRING, BASE_NONE, NULL, 0x0, @@ -2809,25 +4171,46 @@ proto_register_ipv6(void) FT_IPv4, BASE_NONE, NULL, 0x0, "IPv6 Teredo Client Encapsulated IPv4 Address", HFILL } }, + { &hf_ipv6_embed_ipv4_prefix, + { "Embedded IPv4 Prefix", "ipv6.embed_ipv4_prefix", + FT_BYTES, BASE_NONE, NULL, 0x0, + "IPv4-Embedded IPv6 Address Prefix", HFILL } + }, { &hf_ipv6_embed_ipv4, { "Embedded IPv4", "ipv6.embed_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, - "IPv4-Embedded IPv6 Address with Well-Known Prefix", HFILL } + "IPv4-Embedded IPv6 Address", HFILL } + }, + { &hf_ipv6_embed_ipv4_u, + { "Embedded IPv4 u field", "ipv6.embed_ipv4_u", + FT_BYTES, BASE_NONE, NULL, 0x0, + "IPv4-Embedded IPv6 Address u field", HFILL } + }, + { &hf_ipv6_embed_ipv4_suffix, + { "Embedded IPv4 Suffix", "ipv6.embed_ipv4_suffix", + FT_BYTES, BASE_NONE, NULL, 0x0, + "IPv4-Embedded IPv6 Address Suffix", HFILL } + }, + + { &hf_ipv6_stream, + { "Stream index", "ipv6.stream", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, { &hf_geoip_country, { "Source or Destination GeoIP Country", "ipv6.geoip.country", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_country_iso, { "Source or Destination GeoIP ISO Two Letter Country Code", "ipv6.geoip.country_iso", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_city, { "Source or Destination GeoIP City", "ipv6.geoip.city", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_as_number, @@ -2837,7 +4220,7 @@ proto_register_ipv6(void) }, { &hf_geoip_as_org, { "Source or Destination GeoIP AS Organization", "ipv6.geoip.org", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_latitude, @@ -2852,22 +4235,22 @@ proto_register_ipv6(void) }, { &hf_geoip_src_summary, { "Source GeoIP", "ipv6.geoip.src_summary", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_src_country, { "Source GeoIP Country", "ipv6.geoip.src_country", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_src_country_iso, { "Source GeoIP ISO Two Letter Country Code", "ipv6.geoip.src_country_iso", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_src_city, { "Source GeoIP City", "ipv6.geoip.src_city", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_src_as_number, @@ -2877,7 +4260,7 @@ proto_register_ipv6(void) }, { &hf_geoip_src_as_org, { "Source GeoIP AS Organization", "ipv6.geoip.src_org", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_src_latitude, @@ -2892,22 +4275,22 @@ proto_register_ipv6(void) }, { &hf_geoip_dst_summary, { "Destination GeoIP", "ipv6.geoip.dst_summary", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_dst_country, { "Destination GeoIP Country", "ipv6.geoip.dst_country", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_dst_country_iso, { "Destination GeoIP ISO Two Letter Country Code", "ipv6.geoip.dst_country_iso", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_dst_city, { "Destination GeoIP City", "ipv6.geoip.dst_city", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_dst_as_number, @@ -2917,7 +4300,7 @@ proto_register_ipv6(void) }, { &hf_geoip_dst_as_org, { "Destination GeoIP AS Organization", "ipv6.geoip.dst_org", - FT_STRING, STR_UNICODE, NULL, 0x0, + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_geoip_dst_latitude, @@ -2986,6 +4369,41 @@ proto_register_ipv6(void) FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Destination should include the received reported PMTU", HFILL } }, + { &hf_ipv6_opt_apn_id_type, + { "ID Type", "ipv6.opt.apn.id.type", + FT_UINT8, BASE_DEC, VALS(apn_id_type_strs), 0x0, + "The type of the APN ID", HFILL } + }, + { &hf_ipv6_opt_apn_flags, + { "Flags", "ipv6.opt.apn.flags", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Flags for advanced processing", HFILL } + }, + { &hf_ipv6_opt_apn_param_type, + { "Parameters Types", "ipv6.opt.apn.param.type", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Bitmap to identify the existence of APN Parameters", HFILL } + }, + { &hf_ipv6_opt_apn_id_part1, + { "ID Part1", "ipv6.opt.apn.id.part1", + FT_UINT32, BASE_HEX, NULL, 0x0, + "The first 32-bit of the APN ID", HFILL } + }, + { &hf_ipv6_opt_apn_id_part2, + { "ID Part2", "ipv6.opt.apn.id.part2", + FT_UINT32, BASE_HEX, NULL, 0x0, + "The second 32-bit of the APN ID", HFILL } + }, + { &hf_ipv6_opt_apn_id_part3, + { "ID Part3", "ipv6.opt.apn.id.part3", + FT_UINT32, BASE_HEX, NULL, 0x0, + "The third 32-bit of the APN ID", HFILL } + }, + { &hf_ipv6_opt_apn_id_part4, + { "ID Part4", "ipv6.opt.apn.id.part4", + FT_UINT32, BASE_HEX, NULL, 0x0, + "The last 32-bit of the APN ID", HFILL } + }, { &hf_ipv6_opt_rtalert, { "Router Alert", "ipv6.opt.router_alert", FT_UINT16, BASE_DEC, VALS(ipv6_opt_rtalert_vals), 0x0, @@ -3003,7 +4421,7 @@ proto_register_ipv6(void) }, { &hf_ipv6_opt_calipso_doi, { "CALIPSO Domain of Interpretation", "ipv6.opt.calipso.doi", - FT_UINT8, BASE_DEC, NULL, 0x0, + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_ipv6_opt_calipso_cmpt_length, @@ -3121,6 +4539,241 @@ proto_register_ipv6(void) FT_UINT32, BASE_HEX, NULL, 0x0003, NULL, HFILL } }, + { &hf_ipv6_opt_ioam_rsv, + { "Reserved", "ipv6.opt.ioam.rsv", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Reserved (must be zero)", HFILL } + }, + { &hf_ipv6_opt_ioam_opt_type, + { "Option-Type", "ipv6.opt.ioam.opt_type", + FT_UINT8, BASE_DEC, VALS(ipv6_ioam_opt_types), 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_ns, + { "Namespace ID", "ipv6.opt.ioam.trace.ns", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_nodelen, + { "Node Length", "ipv6.opt.ioam.trace.nodelen", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_flags, + { "Flags", "ipv6.opt.ioam.trace.flags", + FT_UINT16, BASE_HEX, NULL, 0x0780, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_flag_o, + { "Overflow", "ipv6.opt.ioam.trace.flag.o", + FT_BOOLEAN, 16, NULL, 0x0400, + "Not enough free space", HFILL } + }, + { &hf_ipv6_opt_ioam_trace_flag_l, + { "Loopback", "ipv6.opt.ioam.trace.flag.l", + FT_BOOLEAN, 16, NULL, 0x0200, + "Send a copy of the packet back towards the source", HFILL } + }, + { &hf_ipv6_opt_ioam_trace_flag_a, + { "Active", "ipv6.opt.ioam.trace.flag.a", + FT_BOOLEAN, 16, NULL, 0x0100, + "Active measurement packet", HFILL } + }, + { &hf_ipv6_opt_ioam_trace_flag_rsv, + { "Reserved", "ipv6.opt.ioam.trace.flag.rsv", + FT_BOOLEAN, 16, NULL, 0x0080, + "Reserved (must be zero)", HFILL } + }, + { &hf_ipv6_opt_ioam_trace_remlen, + { "Remaining Length", "ipv6.opt.ioam.trace.remlen", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type, + { "Trace Type", "ipv6.opt.ioam.trace.type", + FT_UINT24, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit0, + { "Hop_Lim and Node ID (short)", "ipv6.opt.ioam.trace.type.bit0", + FT_BOOLEAN, 24, NULL, 0x800000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit1, + { "Ingress and Egress IDs (short)", "ipv6.opt.ioam.trace.type.bit1", + FT_BOOLEAN, 24, NULL, 0x400000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit2, + { "Timestamp seconds", "ipv6.opt.ioam.trace.type.bit2", + FT_BOOLEAN, 24, NULL, 0x200000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit3, + { "Timestamp fraction", "ipv6.opt.ioam.trace.type.bit3", + FT_BOOLEAN, 24, NULL, 0x100000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit4, + { "Transit delay", "ipv6.opt.ioam.trace.type.bit4", + FT_BOOLEAN, 24, NULL, 0x080000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit5, + { "IOAM-Namespace specific data (short)", "ipv6.opt.ioam.trace.type.bit5", + FT_BOOLEAN, 24, NULL, 0x040000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit6, + { "Queue depth", "ipv6.opt.ioam.trace.type.bit6", + FT_BOOLEAN, 24, NULL, 0x020000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit7, + { "Checksum complement", "ipv6.opt.ioam.trace.type.bit7", + FT_BOOLEAN, 24, NULL, 0x010000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit8, + { "Hop_Lim and Node ID (wide)", "ipv6.opt.ioam.trace.type.bit8", + FT_BOOLEAN, 24, NULL, 0x008000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit9, + { "Ingress and Egress IDs (wide)", "ipv6.opt.ioam.trace.type.bit9", + FT_BOOLEAN, 24, NULL, 0x004000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit10, + { "IOAM-Namespace specific data (wide)", "ipv6.opt.ioam.trace.type.bit10", + FT_BOOLEAN, 24, NULL, 0x002000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit11, + { "Buffer occupancy", "ipv6.opt.ioam.trace.type.bit11", + FT_BOOLEAN, 24, NULL, 0x001000, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_undef, + { "Undefined", "ipv6.opt.ioam.trace.type.undef", + FT_BOOLEAN, 24, NULL, 0x000ffc, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_bit22, + { "Opaque State Snapshot", "ipv6.opt.ioam.trace.type.bit22", + FT_BOOLEAN, 24, NULL, 0x000002, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_type_rsv, + { "Reserved", "ipv6.opt.ioam.trace.type.rsv", + FT_BOOLEAN, 24, NULL, 0x000001, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_rsv, + { "Reserved", "ipv6.opt.ioam.trace.rsv", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Reserved (must be zero)", HFILL } + }, + { &hf_ipv6_opt_ioam_trace_free_space, + { "Free space", "ipv6.opt.ioam.trace.free_space", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_hlim, + { "Hop Limit", "ipv6.opt.ioam.trace.node.hlim", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_id, + { "ID", "ipv6.opt.ioam.trace.node.id", + FT_UINT24, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_iif, + { "Ingress ID", "ipv6.opt.ioam.trace.node.iif", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_eif, + { "Egress ID", "ipv6.opt.ioam.trace.node.eif", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_tss, + { "Timestamp Seconds", "ipv6.opt.ioam.trace.node.tss", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_tsf, + { "Timestamp Fraction", "ipv6.opt.ioam.trace.node.tsf", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_trdelay, + { "Transit Delay", "ipv6.opt.ioam.trace.node.trdelay", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_nsdata, + { "Namespace Data (short)", "ipv6.opt.ioam.trace.node.nsdata", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_qdepth, + { "Queue Depth", "ipv6.opt.ioam.trace.node.qdepth", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_csum, + { "Checksum Complement", "ipv6.opt.ioam.trace.node.csum", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_id_wide, + { "ID", "ipv6.opt.ioam.trace.node.id_wide", + FT_UINT56, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_iif_wide, + { "Ingress ID", "ipv6.opt.ioam.trace.node.iif_wide", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_eif_wide, + { "Egress ID", "ipv6.opt.ioam.trace.node.eif_wide", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_nsdata_wide, + { "Namespace Data (wide)", "ipv6.opt.ioam.trace.node.nsdata_wide", + FT_UINT64, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_bufoccup, + { "Buffer Occupancy", "ipv6.opt.ioam.trace.node.bufoccup", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_undefined, + { "Undefined bit", "ipv6.opt.ioam.trace.node.undefined", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_oss_len, + { "Length", "ipv6.opt.ioam.trace.node.oss.len", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_oss_scid, + { "Schema ID", "ipv6.opt.ioam.trace.node.oss.scid", + FT_UINT24, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ipv6_opt_ioam_trace_node_oss_data, + { "Data", "ipv6.opt.ioam.trace.node.oss.data", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, { &hf_ipv6_opt_tpf_information, { "TPF Information", "ipv6.opt.tpf_information", FT_UINT32, BASE_HEX, NULL, 0x0, @@ -3528,6 +5181,9 @@ proto_register_ipv6(void) static gint *ett_ipv6[] = { &ett_ipv6_proto, + &ett_ipv6_detail, + &ett_ipv6_detail_special_purpose, + &ett_ipv6_multicast_flags, &ett_ipv6_traffic_class, &ett_geoip_info, &ett_ipv6_opt, @@ -3535,6 +5191,8 @@ proto_register_ipv6(void) &ett_ipv6_opt_rpl, &ett_ipv6_opt_mpl, &ett_ipv6_opt_dff_flags, + &ett_ipv6_opt_ioam_trace_flags, + &ett_ipv6_opt_ioam_trace_types, &ett_ipv6_fragment, &ett_ipv6_fragments }; @@ -3577,6 +5235,10 @@ proto_register_ipv6(void) { "ipv6.opt.invalid_len", PI_MALFORMED, PI_ERROR, "Invalid IPv6 option length", EXPFILL } }, + { &ei_ipv6_opt_apn_invalid_id_type, + { "ipv6.opt.apn.invalid.id_type", PI_MALFORMED, PI_ERROR, + "Invalid APN ID Type", EXPFILL } + }, { &ei_ipv6_opt_unknown_data, { "ipv6.opt.unknown_data.expert", PI_UNDECODED, PI_NOTE, "Unknown Data (not interpreted)", EXPFILL } @@ -3608,6 +5270,26 @@ proto_register_ipv6(void) { &ei_ipv6_opt_mpl_ipv6_src_seed_id, { "ipv6.opt.mpl.ipv6_src_seed_id", PI_PROTOCOL, PI_COMMENT, "Seed ID is the IPv6 Source Address", EXPFILL } + }, + { &ei_ipv6_opt_ioam_invalid_nodelen, + { "ipv6.opt.ioam.trace.invalid_nodelen", PI_PROTOCOL, PI_ERROR, + "Invalid \"NodeLen\" value: cannot be 0", EXPFILL } + }, + { &ei_ipv6_opt_ioam_invalid_remlen, + { "ipv6.opt.ioam.trace.invalid_remlen", PI_PROTOCOL, PI_ERROR, + "Invalid \"RemLen\" value", EXPFILL } + }, + { &ei_ipv6_opt_ioam_invalid_trace_type, + { "ipv6.opt.ioam.trace.invalid_type", PI_PROTOCOL, PI_ERROR, + "Mismatch between Trace Type and NodeLen", EXPFILL } + }, + { &ei_ipv6_embed_ipv4_u_value, + { "ipv6.embed_ipv4.u.nonzero", PI_PROTOCOL, PI_WARN, + "IPv4-Embedded IPv6 address bit 64 to 71 must be zero", EXPFILL } + }, + { &ei_ipv6_dst_addr_not_unspecified, + { "ipv6.addr.not_unspecified", PI_PROTOCOL, PI_WARN, + "Unspecified address cannot appear as a destination", EXPFILL } } }; @@ -3619,6 +5301,10 @@ proto_register_ipv6(void) }; static ei_register_info ei_ipv6_routing[] = { + { &ei_ipv6_src_addr_not_multicast, + { "ipv6.src_addr.not_multicast", PI_PROTOCOL, PI_WARN, + "Source address must not be a multicast address", EXPFILL } + }, { &ei_ipv6_dst_addr_not_multicast, { "ipv6.dst_addr.not_multicast", PI_PROTOCOL, PI_WARN, "Destination address must not be a multicast address", EXPFILL } @@ -3738,10 +5424,12 @@ proto_register_ipv6(void) "Show IPv6 summary in protocol tree", "Whether the IPv6 summary line should be shown in the protocol tree", &ipv6_summary_in_tree); - prefs_register_bool_preference(ipv6_module, "use_geoip" , - "Enable IPv6 geolocation", - "Whether to look up IPv6 addresses in each MaxMind database we have loaded", - &ipv6_use_geoip); + prefs_register_bool_preference(ipv6_module, "address_detail" , + "Show details about IPv6 addresses", + "Whether to show extended information about IPv6 addresses", + &ipv6_address_detail); + + prefs_register_obsolete_preference(ipv6_module, "use_geoip"); /* RPL Strict Header Checking */ prefs_register_bool_preference(ipv6_module, "perform_strict_rpl_srh_rfc_checking", @@ -3769,6 +5457,39 @@ proto_register_ipv6(void) "Whether to correct for TSO-enabled (TCP segmentation offload) hardware " "captures, such as spoofing the IPv6 packet length", &ipv6_tso_supported); + prefs_register_static_text_preference(ipv6_module, "text_use_geoip" , + "IP geolocation settings can be changed in the Name Resolution preferences", + "IP geolocation settings can be changed in the Name Resolution preferences"); + + static uat_field_t nat64_uats_flds[] = { + UAT_FLD_CSTRING_OTHER(nat64_prefix_uats, ipaddr, "NAT64 Prefix", nat64_prefix_uat_fld_ip_chk_cb, "IPv6 prefix address"), + UAT_FLD_VS(nat64_prefix_uats, prefix_len, "Prefix length", nat64_prefix_length_vals, "IPv6 prefix address length"), + UAT_FLD_VS(nat64_prefix_uats, prefix_wildcard_len, "Prefix wildcard length", nat64_prefix_wildcard_length_vals, "IPv6 prefix address wildcard length"), + UAT_END_FIELDS + }; + + nat64_prefix_uat = uat_new("NAT64 Network-Specific Prefixes", + sizeof(struct nat64_prefix_data), + "NAT64_NSP_list", /* filename */ + TRUE, /* from_profile */ + &nat64_prefix_uats, /* data_ptr */ + &number_of_nat64_prefix, /* numitems_ptr */ + UAT_AFFECTS_DISSECTION, + NULL, + nat64_prefix_copy_cb, + NULL, + nat64_prefix_free_cb, + NULL, + NULL, + nat64_uats_flds); + + prefs_register_uat_preference(ipv6_module, "nat64_prefixes", + "NAT64 Prefixes", + "A list of IPv6 prefixes used for NAT64s", + nat64_prefix_uat); + + register_init_routine(ipv6_init); + ipv6_handle = register_dissector("ipv6", dissect_ipv6, proto_ipv6); reassembly_table_register(&ipv6_reassembly_table, &addresses_reassembly_table_functions); @@ -3780,8 +5501,8 @@ proto_register_ipv6(void) register_decode_as(&ipv6_fraghdr_da); register_decode_as(&ipv6_dstopts_da); - register_conversation_table(proto_ipv6, TRUE, ipv6_conversation_packet, ipv6_hostlist_packet); - register_conversation_filter("ipv6", "IPv6", ipv6_filter_valid, ipv6_build_filter); + register_conversation_table(proto_ipv6, TRUE, ipv6_conversation_packet, ipv6_endpoint_packet); + register_conversation_filter("ipv6", "IPv6", ipv6_filter_valid, ipv6_build_filter, NULL); register_capture_dissector("ipv6", capture_ipv6, proto_ipv6); } @@ -3865,6 +5586,8 @@ proto_reg_handoff_ipv6(void) h = create_dissector_handle(dissect_routing6_crh, proto_ipv6_routing_crh); dissector_add_uint("ipv6.routing.type", IPv6_RT_HEADER_COMPACT_16, h); dissector_add_uint("ipv6.routing.type", IPv6_RT_HEADER_COMPACT_32, h); + + exported_pdu_tap = find_tap_id("IP"); } /* |