2 * Routines for IPv6 packet disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SHIM6 support added by Matthijs Mekking <matthijs@NLnetLabs.nl>
12 * MobileIPv6 support added by Tomislav Borosa <tomislav.borosa@siemens.hr>
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #include <epan/packet.h>
38 #include "packet-ipsec.h"
39 #include "packet-ipv6.h"
40 #include <epan/ip_opts.h>
41 #include <epan/addr_resolv.h>
42 #include <epan/prefs.h>
43 #include <epan/reassemble.h>
44 #include <epan/ipproto.h>
45 #include <epan/ipv6-utils.h>
46 #include <epan/etypes.h>
47 #include <epan/ppptypes.h>
48 #include <epan/aftypes.h>
49 #include <epan/nlpid.h>
50 #include <epan/arcnet_pids.h>
51 #include <epan/in_cksum.h>
52 #include <epan/value_string.h>
53 #include <epan/expert.h>
54 #include <epan/emem.h>
57 * NOTE: ipv6.nxt is not very useful as we will have chained header.
58 * now testing ipv6.final, but it raises SEGV.
62 static int proto_ipv6 = -1;
63 static int hf_ipv6_version = -1;
64 static int hf_ip_version = -1;
65 static int hf_ipv6_class = -1;
66 static int hf_ipv6_flow = -1;
67 static int hf_ipv6_plen = -1;
68 static int hf_ipv6_nxt = -1;
69 static int hf_ipv6_hlim = -1;
70 static int hf_ipv6_src = -1;
71 static int hf_ipv6_src_host = -1;
72 static int hf_ipv6_dst = -1;
73 static int hf_ipv6_dst_host = -1;
74 static int hf_ipv6_addr = -1;
75 static int hf_ipv6_host = -1;
76 static int hf_ipv6_opt_pad1 = -1;
77 static int hf_ipv6_opt_padn = -1;
78 static int hf_ipv6_dst_opt = -1;
79 static int hf_ipv6_hop_opt = -1;
80 static int hf_ipv6_unk_hdr = -1;
81 static int hf_ipv6_routing_hdr_opt = -1;
82 static int hf_ipv6_routing_hdr_type = -1;
83 static int hf_ipv6_routing_hdr_left = -1;
84 static int hf_ipv6_routing_hdr_addr = -1;
86 static int hf_ipv6_final = -1;
88 static int hf_ipv6_frag_offset = -1;
89 static int hf_ipv6_frag_more = -1;
90 static int hf_ipv6_frag_id = -1;
91 static int hf_ipv6_fragments = -1;
92 static int hf_ipv6_fragment = -1;
93 static int hf_ipv6_fragment_overlap = -1;
94 static int hf_ipv6_fragment_overlap_conflict = -1;
95 static int hf_ipv6_fragment_multiple_tails = -1;
96 static int hf_ipv6_fragment_too_long_fragment = -1;
97 static int hf_ipv6_fragment_error = -1;
98 static int hf_ipv6_reassembled_in = -1;
100 static int hf_ipv6_mipv6_type = -1;
101 static int hf_ipv6_mipv6_length = -1;
102 static int hf_ipv6_mipv6_home_address = -1;
104 static int hf_ipv6_shim6 = -1;
105 static int hf_ipv6_shim6_nxt = -1;
106 static int hf_ipv6_shim6_len = -1;
107 static int hf_ipv6_shim6_p = -1;
108 /* context tag is 49 bits, cannot be used for filter yet */
109 static int hf_ipv6_shim6_ct = -1;
110 static int hf_ipv6_shim6_type = -1;
111 static int hf_ipv6_shim6_proto = -1;
112 static int hf_ipv6_shim6_checksum = -1;
113 static int hf_ipv6_shim6_checksum_bad = -1;
114 static int hf_ipv6_shim6_checksum_good= -1;
115 static int hf_ipv6_shim6_inonce = -1; /* also for request nonce */
116 static int hf_ipv6_shim6_rnonce = -1;
117 static int hf_ipv6_shim6_precvd = -1;
118 static int hf_ipv6_shim6_psent = -1;
119 static int hf_ipv6_shim6_psrc = -1;
120 static int hf_ipv6_shim6_pdst = -1;
121 static int hf_ipv6_shim6_pnonce = -1;
122 static int hf_ipv6_shim6_pdata = -1;
123 static int hf_ipv6_shim6_sulid = -1;
124 static int hf_ipv6_shim6_rulid = -1;
125 static int hf_ipv6_shim6_reap = -1;
126 static int hf_ipv6_shim6_opt_type = -1;
127 static int hf_ipv6_shim6_opt_len = -1;
128 static int hf_ipv6_shim6_opt_total_len= -1;
129 static int hf_ipv6_shim6_opt_loc_verif_methods = -1;
130 static int hf_ipv6_shim6_opt_critical = -1;
131 static int hf_ipv6_shim6_opt_loclist = -1;
132 static int hf_ipv6_shim6_locator = -1;
133 static int hf_ipv6_shim6_loc_flag = -1;
134 static int hf_ipv6_shim6_loc_prio = -1;
135 static int hf_ipv6_shim6_loc_weight = -1;
136 static int hf_ipv6_shim6_opt_locnum = -1;
137 static int hf_ipv6_shim6_opt_elemlen = -1;
138 static int hf_ipv6_shim6_opt_fii = -1;
140 static gint ett_ipv6 = -1;
141 static gint ett_ipv6_version = -1;
142 static gint ett_ipv6_shim6 = -1;
143 static gint ett_ipv6_shim6_option = -1;
144 static gint ett_ipv6_shim6_locators = -1;
145 static gint ett_ipv6_shim6_verif_methods = -1;
146 static gint ett_ipv6_shim6_loc_pref = -1;
147 static gint ett_ipv6_shim6_probes_sent = -1;
148 static gint ett_ipv6_shim6_probe_sent = -1;
149 static gint ett_ipv6_shim6_probes_rcvd = -1;
150 static gint ett_ipv6_shim6_probe_rcvd = -1;
151 static gint ett_ipv6_shim6_cksum = -1;
152 static gint ett_ipv6_fragments = -1;
153 static gint ett_ipv6_fragment = -1;
155 static const fragment_items ipv6_frag_items = {
160 &hf_ipv6_fragment_overlap,
161 &hf_ipv6_fragment_overlap_conflict,
162 &hf_ipv6_fragment_multiple_tails,
163 &hf_ipv6_fragment_too_long_fragment,
164 &hf_ipv6_fragment_error,
165 &hf_ipv6_reassembled_in,
169 static dissector_handle_t data_handle;
171 static dissector_table_t ip_dissector_table;
173 /* Reassemble fragmented datagrams */
174 static gboolean ipv6_reassemble = TRUE;
177 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
181 * defragmentation of IPv6
183 static GHashTable *ipv6_fragment_table = NULL;
184 static GHashTable *ipv6_reassembled_table = NULL;
187 capture_ipv6(const guchar *pd, int offset, int len, packet_counts *ld)
192 if (!BYTES_ARE_IN_FRAME(offset, len, 4+4+16+16)) {
196 nxt = pd[offset+6]; /* get the "next header" value */
197 offset += 4+4+16+16; /* skip past the IPv6 header */
201 case IP_PROTO_HOPOPTS:
202 case IP_PROTO_ROUTING:
203 case IP_PROTO_DSTOPTS:
204 if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
209 advance = (pd[offset+1] + 1) << 3;
210 if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
216 case IP_PROTO_FRAGMENT:
217 if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
223 if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
230 if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
235 advance = 8 + ((pd[offset+1] - 1) << 2);
236 if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
243 case IP_PROTO_SHIM6_OLD:
244 if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
249 advance = (pd[offset+1] + 1) << 3;
250 if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
266 case IP_PROTO_UDPLITE:
270 case IP_PROTO_ICMPV6: /* XXX - separate counters? */
288 ipv6_reassemble_init(void)
290 fragment_table_init(&ipv6_fragment_table);
291 reassembled_table_init(&ipv6_reassembled_table);
295 IPv6_RT_HEADER_SOURCE_ROUTING=0,
296 IPv6_RT_HEADER_NIMROD,
297 IPv6_RT_HEADER_MobileIP
300 /* Routeing Header Types */
301 static const value_string routing_header_type[] = {
302 { IPv6_RT_HEADER_SOURCE_ROUTING, "IPv6 Source Routing" },
303 { IPv6_RT_HEADER_NIMROD, "Nimrod" },
304 { IPv6_RT_HEADER_MobileIP, "Mobile IP" },
309 dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo) {
312 proto_tree *rthdr_tree;
314 guint8 buf[sizeof(struct ip6_rthdr0) + sizeof(struct e_in6_addr) * 23];
316 tvb_memcpy(tvb, (guint8 *)&rt, offset, sizeof(rt));
317 len = (rt.ip6r_len + 1) << 3;
320 /* !!! specify length */
321 ti = proto_tree_add_uint_format(tree, hf_ipv6_routing_hdr_opt, tvb,
322 offset, len, rt.ip6r_type,
323 "Routing Header, Type : %s (%u)",
324 val_to_str(rt.ip6r_type, routing_header_type, "Unknown"),
326 rthdr_tree = proto_item_add_subtree(ti, ett_ipv6);
328 proto_tree_add_text(rthdr_tree, tvb,
329 offset + offsetof(struct ip6_rthdr, ip6r_nxt), 1,
330 "Next header: %s (0x%02x)", ipprotostr(rt.ip6r_nxt), rt.ip6r_nxt);
332 proto_tree_add_text(rthdr_tree, tvb,
333 offset + offsetof(struct ip6_rthdr, ip6r_len), 1,
334 "Length: %u (%d bytes)", rt.ip6r_len, len);
336 proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_type, tvb,
337 offset + offsetof(struct ip6_rthdr, ip6r_type), 1, FALSE);
339 proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_left, tvb,
340 offset + offsetof(struct ip6_rthdr, ip6r_segleft), 1, FALSE);
342 if (rt.ip6r_type == IPv6_RT_HEADER_SOURCE_ROUTING && len <= sizeof(buf)) {
343 struct e_in6_addr *a;
345 struct ip6_rthdr0 *rt0;
347 tvb_memcpy(tvb, buf, offset, len);
348 rt0 = (struct ip6_rthdr0 *)buf;
350 for (a = rt0->ip6r0_addr, n = 0;
351 a < (struct e_in6_addr *)(buf + len); a++, n++) {
353 proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_addr, tvb,
354 offset + offsetof(struct ip6_rthdr0, ip6r0_addr)
355 + n * sizeof(struct e_in6_addr),
356 sizeof(struct e_in6_addr), FALSE);
357 SET_ADDRESS(&pinfo->dst, AT_IPv6, 16, tvb_get_ptr(tvb,
358 offset + offsetof(struct ip6_rthdr0, ip6r0_addr)
359 + n * sizeof(struct e_in6_addr), 16));
362 if (rt.ip6r_type == IPv6_RT_HEADER_MobileIP) {
363 proto_tree_add_item(rthdr_tree, hf_ipv6_mipv6_home_address, tvb,
364 offset + 8, 16, FALSE);
365 SET_ADDRESS(&pinfo->dst, AT_IPv6, 16, tvb_get_ptr(tvb, offset + 8, 16));
373 dissect_frag6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
374 guint16 *offlg, guint32 *ident) {
375 struct ip6_frag frag;
378 proto_tree *rthdr_tree;
380 tvb_memcpy(tvb, (guint8 *)&frag, offset, sizeof(frag));
382 frag.ip6f_offlg = g_ntohs(frag.ip6f_offlg);
383 frag.ip6f_ident = g_ntohl(frag.ip6f_ident);
384 *offlg = frag.ip6f_offlg;
385 *ident = frag.ip6f_ident;
386 if (check_col(pinfo->cinfo, COL_INFO)) {
387 col_add_fstr(pinfo->cinfo, COL_INFO,
388 "IPv6 fragment (nxt=%s (0x%02x) off=%u id=0x%x)",
389 ipprotostr(frag.ip6f_nxt), frag.ip6f_nxt,
390 frag.ip6f_offlg & IP6F_OFF_MASK, frag.ip6f_ident);
393 ti = proto_tree_add_text(tree, tvb, offset, len,
394 "Fragmentation Header");
395 rthdr_tree = proto_item_add_subtree(ti, ett_ipv6);
397 proto_tree_add_text(rthdr_tree, tvb,
398 offset + offsetof(struct ip6_frag, ip6f_nxt), 1,
399 "Next header: %s (0x%02x)",
400 ipprotostr(frag.ip6f_nxt), frag.ip6f_nxt);
403 proto_tree_add_text(rthdr_tree, tvb,
404 offset + offsetof(struct ip6_frag, ip6f_reserved), 1,
409 proto_tree_add_item(rthdr_tree, hf_ipv6_frag_offset, tvb,
410 offset + offsetof(struct ip6_frag, ip6f_offlg), 2, FALSE);
412 proto_tree_add_item(rthdr_tree, hf_ipv6_frag_more, tvb,
413 offset + offsetof(struct ip6_frag, ip6f_offlg), 2, FALSE);
415 proto_tree_add_item(rthdr_tree, hf_ipv6_frag_id, tvb,
416 offset + offsetof(struct ip6_frag, ip6f_ident), 4, FALSE);
422 dissect_mipv6_hoa(tvbuff_t *tvb, proto_tree *dstopt_tree, int offset, packet_info *pinfo)
426 proto_tree_add_uint_format(dstopt_tree, hf_ipv6_mipv6_type, tvb,
428 tvb_get_guint8(tvb, offset + len),
429 "Option Type: %u (0x%02x) - Home Address Option",
430 tvb_get_guint8(tvb, offset + len),
431 tvb_get_guint8(tvb, offset + len));
434 proto_tree_add_uint(dstopt_tree, hf_ipv6_mipv6_length, tvb, offset + len,
435 1, tvb_get_guint8(tvb, offset + len));
438 proto_tree_add_ipv6(dstopt_tree, hf_ipv6_mipv6_home_address, tvb,
439 offset + len, 16, tvb_get_ptr(tvb, offset + len, 16));
440 SET_ADDRESS(&pinfo->src, AT_IPv6, 16, tvb_get_ptr(tvb, offset + len, 16));
445 static const value_string rtalertvals[] = {
446 { IP6OPT_RTALERT_MLD, "MLD" },
447 { IP6OPT_RTALERT_RSVP, "RSVP" },
451 /* Like "dissect_ip_tcp_options()", but assumes the length of an option
452 *doesn't* include the type and length bytes. */
454 dissect_ipv6_options(tvbuff_t *tvb, int offset, guint length,
455 const ip_tcp_opt *opttab, int nopts, int eol,
456 packet_info *pinfo, proto_tree *opt_tree)
459 const ip_tcp_opt *optp;
460 opt_len_type len_type;
463 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
464 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
465 int, guint, packet_info *, proto_tree *);
469 opt = tvb_get_guint8(tvb, offset);
470 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
471 if (optp->optcode == opt)
474 if (optp == &opttab[nopts]) {
475 /* We assume that the only NO_LENGTH options are Pad1 options,
476 so that we can treat unknown options as VARIABLE_LENGTH with a
477 minimum of 0, and at least be able to move on to the next option
478 by using the length in the option. */
479 optp = NULL; /* indicate that we don't know this option */
480 len_type = VARIABLE_LENGTH;
482 g_snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
486 len_type = optp->len_type;
487 optlen = optp->optlen;
489 dissect = optp->dissect;
491 --length; /* account for type byte */
492 if (len_type != NO_LENGTH) {
493 /* Option has a length. Is it in the packet? */
495 /* Bogus - packet must at least include option code byte and
497 proto_tree_add_text(opt_tree, tvb, offset, 1,
498 "%s (length byte past end of options)", name);
501 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
502 --length; /* account for length byte */
504 /* Bogus - option goes past the end of the header. */
505 proto_tree_add_text(opt_tree, tvb, offset, length,
506 "%s (option length = %u byte%s says option goes past end of options)",
507 name, len, plurality(len, "", "s"));
509 } else if (len_type == FIXED_LENGTH && len != optlen) {
510 /* Bogus - option length isn't what it's supposed to be for this
512 proto_tree_add_text(opt_tree, tvb, offset, 2 + len,
513 "%s (with option length = %u byte%s; should be %u)", name,
514 len, plurality(len, "", "s"), optlen);
516 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
517 /* Bogus - option length is less than what it's supposed to be for
519 proto_tree_add_text(opt_tree, tvb, offset, 2 + len,
520 "%s (with option length = %u byte%s; should be >= %u)", name,
521 len, plurality(len, "", "s"), optlen);
525 proto_tree_add_text(opt_tree, tvb, offset, 2 + len, "%s (%u byte%s)",
526 name, len, plurality(len, "", "s"));
528 if (dissect != NULL) {
529 /* Option has a dissector. */
530 (*dissect)(optp, tvb, offset, 2 + len, pinfo, opt_tree);
532 /* Option has no data, hence no dissector. */
533 proto_tree_add_text(opt_tree, tvb, offset, 2 + len, "%s", name);
540 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
549 dissect_unknown_option(tvbuff_t *tvb, int offset, proto_tree *tree)
553 proto_tree *unkopt_tree;
556 tvb_memcpy(tvb, (guint8 *)&ext, offset, sizeof(ext));
557 len = (ext.ip6e_len + 1) << 3;
560 /* !!! specify length */
561 ti = proto_tree_add_item(tree, hf_ipv6_unk_hdr, tvb, offset, len, FALSE);
563 unkopt_tree = proto_item_add_subtree(ti, ett_ipv6);
565 proto_tree_add_text(unkopt_tree, tvb,
566 offset + offsetof(struct ip6_ext, ip6e_nxt), 1,
567 "Next header: %s (0x%02x)", ipprotostr(ext.ip6e_nxt), ext.ip6e_nxt);
569 proto_tree_add_text(unkopt_tree, tvb,
570 offset + offsetof(struct ip6_ext, ip6e_len), 1,
571 "Length: %u (%d bytes)", ext.ip6e_len, len);
577 dissect_opts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo, const int hf_option_item)
581 proto_tree *dstopt_tree;
585 int mip_offset = 0, delta = 0;
587 tvb_memcpy(tvb, (guint8 *)&ext, offset, sizeof(ext));
588 len = (ext.ip6e_len + 1) << 3;
591 /* !!! specify length */
592 ti = proto_tree_add_item(tree, hf_option_item, tvb, offset, len, FALSE);
594 dstopt_tree = proto_item_add_subtree(ti, ett_ipv6);
596 proto_tree_add_text(dstopt_tree, tvb,
597 offset + offsetof(struct ip6_ext, ip6e_nxt), 1,
598 "Next header: %s (0x%02x)", ipprotostr(ext.ip6e_nxt), ext.ip6e_nxt);
600 proto_tree_add_text(dstopt_tree, tvb,
601 offset + offsetof(struct ip6_ext, ip6e_len), 1,
602 "Length: %u (%d bytes)", ext.ip6e_len, len);
609 while (p < offset + len) {
610 switch (tvb_get_guint8(tvb, p)) {
612 proto_tree_add_item(dstopt_tree, hf_ipv6_opt_pad1, tvb, p, 1, FALSE);
618 * "The PadN option is used to insert two or more octets of
619 * padding into the Options area of a header. For N octets of
620 * padding, the Opt Data Len field contains the value N-2, and
621 * the Option Data consists of N-2 zero-valued octets."
623 tmp = tvb_get_guint8(tvb, p + 1);
624 proto_tree_add_uint_format(dstopt_tree, hf_ipv6_opt_padn, tvb,
626 "PadN: %u bytes", tmp + 2);
628 mip_offset += tvb_get_guint8(tvb, mip_offset + 1) + 2;
631 tmp = tvb_get_guint8(tvb, p + 1);
633 proto_tree_add_text(dstopt_tree, tvb, p, tmp + 2,
634 "Jumbo payload: %u (%u bytes)",
635 tvb_get_ntohl(tvb, p + 2), tmp + 2);
637 ti = proto_tree_add_text(dstopt_tree, tvb, p, tmp + 2,
638 "Jumbo payload: Invalid length (%u bytes)", tmp);
639 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
640 "Jumbo payload: Invalid length (%u bytes)", tmp);
643 mip_offset += tvb_get_guint8(tvb, mip_offset+1)+2;
647 tmp = tvb_get_guint8(tvb, p + 1);
649 proto_tree_add_text(dstopt_tree, tvb, p , tmp + 2,
650 "Router alert: %s (%u bytes)",
651 val_to_str(tvb_get_ntohs(tvb, p + 2),
652 rtalertvals, "Unknown"),
655 ti = proto_tree_add_text(dstopt_tree, tvb, p , tmp + 2,
656 "Router alert: Invalid Length (%u bytes)",
658 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
659 "Router alert: Invalid Length (%u bytes)",
664 mip_offset += tvb_get_guint8(tvb, mip_offset + 1) + 2;
667 case IP6OPT_HOME_ADDRESS:
668 delta = dissect_mipv6_hoa(tvb, dstopt_tree, mip_offset, pinfo);
684 dissect_hopopts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo)
686 return dissect_opts(tvb, offset, tree, pinfo, hf_ipv6_hop_opt);
690 dissect_dstopts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo)
692 return dissect_opts(tvb, offset, tree, pinfo, hf_ipv6_dst_opt);
695 /* START SHIM6 PART */
696 static guint16 shim_checksum(const guint8 *ptr, int len)
700 cksum_vec[0].ptr = ptr;
701 cksum_vec[0].len = len;
702 return in_cksum(&cksum_vec[0], 1);
706 dissect_shim_hex(tvbuff_t *tvb, int offset, int len, const char *itemname, guint8 bitmask, proto_tree *tree)
714 ti = proto_tree_add_text(tree, tvb, offset, len, "%s", itemname);
716 proto_item_append_text(ti, " 0x%02x", tvb_get_guint8(tvb, p) & bitmask);
717 for (count=1; count<len; count++)
718 proto_item_append_text(ti, "%02x", tvb_get_guint8(tvb, p+count));
723 static const value_string shimoptvals[] = {
724 { SHIM6_OPT_RESPVAL, "Responder Validator Option" },
725 { SHIM6_OPT_LOCLIST, "Locator List Option" },
726 { SHIM6_OPT_LOCPREF, "Locator Preferences Option" },
727 { SHIM6_OPT_CGAPDM, "CGA Parameter Data Structure Option" },
728 { SHIM6_OPT_CGASIG, "CGA Signature Option" },
729 { SHIM6_OPT_ULIDPAIR, "ULID Pair Option" },
730 { SHIM6_OPT_FII, "Forked Instance Identifier Option" },
734 static const value_string shimverifmethods[] = {
735 { SHIM6_VERIF_HBA, "HBA" },
736 { SHIM6_VERIF_CGA, "CGA" },
740 static const value_string shimflags[] _U_ = {
741 { SHIM6_FLAG_BROKEN, "BROKEN" },
742 { SHIM6_FLAG_TEMPORARY, "TEMPORARY" },
746 static const value_string shimreapstates[] = {
747 { SHIM6_REAP_OPERATIONAL, "Operational" },
748 { SHIM6_REAP_EXPLORING, "Exploring" },
749 { SHIM6_REAP_INBOUNDOK, "InboundOK" },
753 static const value_string shim6_protocol[] = {
760 dissect_shim6_opt_loclist(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset)
763 proto_tree * subtree;
768 proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_loclist, tvb, p, 4, FALSE);
771 optlen = tvb_get_guint8(tvb, p);
772 proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_locnum, tvb, p, 1, FALSE);
775 /* Verification Methods */
776 it = proto_tree_add_text(opt_tree, tvb, p, optlen,
777 "Locator Verification Methods");
778 subtree = proto_item_add_subtree(it, ett_ipv6_shim6_verif_methods);
780 for (count=0; count < optlen; count++)
781 proto_tree_add_item(subtree, hf_ipv6_shim6_opt_loc_verif_methods, tvb,
785 /* Padding, included in length field */
786 if ((7 - optlen % 8) > 0) {
787 proto_tree_add_text(opt_tree, tvb, p, (7 - optlen % 8), "Padding");
788 p += (7 - optlen % 8);
792 it = proto_tree_add_text(opt_tree, tvb, p, 16 * optlen, "Locators");
793 subtree = proto_item_add_subtree(it, ett_ipv6_shim6_locators);
795 for (count=0; count < optlen; count++) {
796 proto_tree_add_item(subtree, hf_ipv6_shim6_locator, tvb, p, 16, FALSE);
803 dissect_shim6_opt_loc_pref(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset, gint len, packet_info *pinfo)
805 proto_tree * subtree;
814 proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_loclist, tvb, p, 4, FALSE);
817 optlen = tvb_get_guint8(tvb, p);
818 proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_elemlen, tvb, p, 1, FALSE);
820 if (optlen < 1 || optlen > 3) {
821 it = proto_tree_add_text(opt_tree, tvb, p, 1,
822 "Invalid element length: %u", optlen);
823 expert_add_info_format(pinfo, it, PI_MALFORMED, PI_ERROR,
824 "Invalid element length: %u", optlen);
830 /* Locator Preferences */
833 it = proto_tree_add_text(opt_tree, tvb, p, optlen, "Locator Preferences %u", count);
834 subtree = proto_item_add_subtree(it, ett_ipv6_shim6_loc_pref);
838 proto_tree_add_item(subtree, hf_ipv6_shim6_loc_flag, tvb, p, 1, FALSE);
841 proto_tree_add_item(subtree, hf_ipv6_shim6_loc_prio, tvb, p+1, 1, FALSE);
844 proto_tree_add_item(subtree, hf_ipv6_shim6_loc_weight, tvb, p+2, 1, FALSE);
846 * Shim6 Draft 08 doesn't specify the format when the Element length is
847 * more than three, except that any such formats MUST be defined so that
848 * the first three octets are the same as in the above case, that is, a
849 * of a 1 octet flags field followed by a 1 octet priority field, and a
850 * 1 octet weight field.
860 dissect_shimopts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo)
865 proto_tree *opt_tree;
873 tmp[0] = tvb_get_guint8(tvb, p++);
874 tmp[1] = tvb_get_guint8(tvb, p++);
877 len = tvb_get_ntohs(tvb, offset+2);
878 padding = 7 - ((len + 3) % 8);
879 total_len = 4 + len + padding;
884 ctype = val_to_str( (tvb_get_ntohs(tvb, offset) & SHIM6_BITMASK_OPT_TYPE) >> 1, shimoptvals, "Unknown Option Type");
885 ti = proto_tree_add_text(tree, tvb, offset, total_len, "%s", ctype);
886 opt_tree = proto_item_add_subtree(ti, ett_ipv6_shim6_option);
888 proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_type, tvb, offset, 2, FALSE);
891 proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_critical, tvb, offset+1, 1, FALSE);
894 proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_len, tvb, offset + 2, 2, FALSE);
895 ti = proto_tree_add_uint_format(opt_tree, hf_ipv6_shim6_opt_total_len, tvb, offset+2, 2,
896 total_len, "Total Length: %u", total_len);
897 PROTO_ITEM_SET_GENERATED(ti);
899 /* Option Type Specific */
900 switch (tvb_get_ntohs(tvb, offset) >> 1)
902 case SHIM6_OPT_RESPVAL:
903 p += dissect_shim_hex(tvb, p, len, "Validator:", 0xff, opt_tree);
904 if (total_len-(len+4) > 0)
905 proto_tree_add_text(opt_tree, tvb, p, total_len-(len+4), "Padding");
907 case SHIM6_OPT_LOCLIST:
908 dissect_shim6_opt_loclist(opt_tree, tvb, &p);
910 case SHIM6_OPT_LOCPREF:
911 dissect_shim6_opt_loc_pref(opt_tree, tvb, &p, offset+len+4, pinfo);
912 if (total_len-(len+4) > 0)
913 proto_tree_add_text(opt_tree, tvb, p, total_len-(len+4), "Padding");
915 case SHIM6_OPT_CGAPDM:
916 p += dissect_shim_hex(tvb, p, len, "CGA Parameter Data Structure:", 0xff, opt_tree);
917 if (total_len-(len+4) > 0)
918 proto_tree_add_text(opt_tree, tvb, p, total_len-(len+4), "Padding");
920 case SHIM6_OPT_CGASIG:
921 p += dissect_shim_hex(tvb, p, len, "CGA Signature:", 0xff, opt_tree);
922 if (total_len-(len+4) > 0)
923 proto_tree_add_text(opt_tree, tvb, p, total_len-(len+4), "Padding");
925 case SHIM6_OPT_ULIDPAIR:
926 proto_tree_add_text(opt_tree, tvb, p, 4, "Reserved");
928 proto_tree_add_item(opt_tree, hf_ipv6_shim6_sulid, tvb, p, 16, FALSE);
930 proto_tree_add_item(opt_tree, hf_ipv6_shim6_rulid, tvb, p, 16, FALSE);
934 proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_fii, tvb, p, 4, FALSE);
945 dissect_shim6_ct(proto_tree * shim_tree, gint hf_item, tvbuff_t * tvb, gint offset, const guchar * label)
950 tmp[0] = tvb_get_guint8(tvb, offset++);
951 tmp[1] = tvb_get_guint8(tvb, offset++);
952 tmp[2] = tvb_get_guint8(tvb, offset++);
953 tmp[3] = tvb_get_guint8(tvb, offset++);
954 tmp[4] = tvb_get_guint8(tvb, offset++);
955 tmp[5] = tvb_get_guint8(tvb, offset++);
957 ct_str = ep_strdup_printf("%s: %02X %02X %02X %02X %02X %02X", label,
958 tmp[0] & SHIM6_BITMASK_CT, tmp[1], tmp[2],
959 tmp[3], tmp[4], tmp[5]
961 proto_tree_add_none_format(shim_tree, hf_item, tvb, offset - 6, 6, "%s", ct_str);
965 dissect_shim6_probes(proto_tree * shim_tree, tvbuff_t * tvb, gint offset,
966 const guchar * label, guint nbr_probe,
967 gboolean probes_rcvd)
969 proto_tree * probes_tree;
970 proto_tree * probe_tree;
977 ett_probes = ett_ipv6_shim6_probes_rcvd;
978 ett_probe = ett_ipv6_shim6_probe_rcvd;
980 ett_probes = ett_ipv6_shim6_probes_sent;
981 ett_probe = ett_ipv6_shim6_probe_sent;
983 it = proto_tree_add_text(shim_tree, tvb, offset, 40 * nbr_probe, "%s", label);
984 probes_tree = proto_item_add_subtree(it, ett_probes);
986 for (count=0; count < nbr_probe; count++) {
987 it = proto_tree_add_text(probes_tree, tvb, offset, 40, "Probe %u", count+1);
988 probe_tree = proto_item_add_subtree(it, ett_probe);
990 proto_tree_add_item(probe_tree, hf_ipv6_shim6_psrc, tvb, offset, 16, FALSE);
992 proto_tree_add_item(probe_tree, hf_ipv6_shim6_pdst, tvb, offset, 16, FALSE);
995 proto_tree_add_item(probe_tree, hf_ipv6_shim6_pnonce, tvb, offset, 4, FALSE);
998 proto_tree_add_item(probe_tree, hf_ipv6_shim6_pdata, tvb, offset, 4, FALSE);
1003 /* Dissect SHIM6 data: control messages */
1005 dissect_shimctrl(tvbuff_t *tvb, gint offset, guint type, proto_tree *shim_tree)
1018 dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Initiator Context Tag");
1020 proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
1024 proto_tree_add_text(shim_tree, tvb, p, 2, "Reserved2");
1026 proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
1028 proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
1032 dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Initiator Context Tag");
1034 proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
1036 proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
1038 proto_tree_add_text(shim_tree, tvb, p, 4, "Reserved2");
1042 dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Responder Context Tag");
1044 proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
1047 case SHIM6_TYPE_R1BIS:
1048 dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Packet Context Tag");
1050 proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
1053 case SHIM6_TYPE_I2BIS:
1054 dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Initiator Context Tag");
1056 proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
1058 proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
1060 proto_tree_add_text(shim_tree, tvb, p, 6, "Reserved2");
1062 dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Initiator Context Tag");
1065 case SHIM6_TYPE_UPD_REQ:
1066 case SHIM6_TYPE_UPD_ACK:
1067 dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Receiver Context Tag");
1069 proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
1072 case SHIM6_TYPE_KEEPALIVE:
1073 dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Receiver Context Tag");
1075 proto_tree_add_text(shim_tree, tvb, p, 4, "Reserved2");
1078 case SHIM6_TYPE_PROBE:
1079 dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Receiver Context Tag");
1082 tmp = tvb_get_guint8(tvb, p);
1083 probes_sent = tmp & SHIM6_BITMASK_PSENT;
1084 probes_rcvd = (tmp & SHIM6_BITMASK_PRECVD) >> 4;
1086 proto_tree_add_uint_format(shim_tree, hf_ipv6_shim6_psent, tvb,
1088 "Probes Sent: %u", probes_sent);
1089 proto_tree_add_uint_format(shim_tree, hf_ipv6_shim6_precvd, tvb,
1091 "Probes Received: %u", probes_rcvd);
1094 sta = val_to_str((tvb_get_guint8(tvb, p) & SHIM6_BITMASK_STA) >> 6,
1095 shimreapstates, "Unknown REAP State");
1096 proto_tree_add_uint_format(shim_tree, hf_ipv6_shim6_reap, tvb,
1097 p, 1, (tvb_get_guint8(tvb, p) & SHIM6_BITMASK_STA) >> 6,
1098 "REAP State: %s", sta);
1100 proto_tree_add_text(shim_tree, tvb, p, 3, "Reserved2");
1105 dissect_shim6_probes(shim_tree, tvb, p, "Probes Sent",
1106 probes_sent, FALSE);
1107 p += 40 * probes_sent;
1110 /* Probes Received */
1112 dissect_shim6_probes(shim_tree, tvb, p, "Probes Received",
1114 p += 40 * probes_rcvd;
1123 /* Dissect SHIM6 data: payload, common part, options */
1124 static const value_string shimctrlvals[] = {
1125 { SHIM6_TYPE_I1, "I1" },
1126 { SHIM6_TYPE_R1, "R1" },
1127 { SHIM6_TYPE_I2, "I2" },
1128 { SHIM6_TYPE_R2, "R2" },
1129 { SHIM6_TYPE_R1BIS, "R1bis" },
1130 { SHIM6_TYPE_I2BIS, "I2bis" },
1131 { SHIM6_TYPE_UPD_REQ, "Update Request" },
1132 { SHIM6_TYPE_UPD_ACK, "Update Acknowledgement" },
1133 { SHIM6_TYPE_KEEPALIVE, "Keepalive" },
1134 { SHIM6_TYPE_PROBE, "Probe" },
1138 static void ipv6_shim6_checkum_additional_info(tvbuff_t * tvb, packet_info * pinfo,
1139 proto_item * it_cksum, int offset, gboolean is_cksum_correct)
1141 proto_tree * checksum_tree;
1144 checksum_tree = proto_item_add_subtree(it_cksum, ett_ipv6_shim6_cksum);
1145 item = proto_tree_add_boolean(checksum_tree, hf_ipv6_shim6_checksum_good, tvb,
1146 offset, 2, is_cksum_correct);
1147 PROTO_ITEM_SET_GENERATED(item);
1148 item = proto_tree_add_boolean(checksum_tree, hf_ipv6_shim6_checksum_bad, tvb,
1149 offset, 2, !is_cksum_correct);
1150 PROTO_ITEM_SET_GENERATED(item);
1151 if (!is_cksum_correct) {
1152 expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
1153 col_append_str(pinfo->cinfo, COL_INFO, " [Shim6 CHECKSUM INCORRECT]");
1158 dissect_shim6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo)
1160 struct ip6_shim shim;
1163 proto_tree *shim_tree;
1167 tvb_memcpy(tvb, (guint8 *)&shim, offset, sizeof(shim));
1168 len = (shim.ip6s_len + 1) << 3;
1172 ti = proto_tree_add_item(tree, hf_ipv6_shim6, tvb, offset, len, FALSE);
1173 shim_tree = proto_item_add_subtree(ti, ett_ipv6_shim6);
1176 proto_tree_add_uint_format(shim_tree, hf_ipv6_shim6_nxt, tvb,
1177 offset + offsetof(struct ip6_shim, ip6s_nxt), 1, shim.ip6s_nxt,
1178 "Next header: %s (0x%02x)", ipprotostr(shim.ip6s_nxt), shim.ip6s_nxt);
1180 /* Header Extension Length */
1181 proto_tree_add_uint_format(shim_tree, hf_ipv6_shim6_len, tvb,
1182 offset + offsetof(struct ip6_shim, ip6s_len), 1, shim.ip6s_len,
1183 "Header Ext Length: %u (%d bytes)", shim.ip6s_len, len);
1186 proto_tree_add_item(shim_tree, hf_ipv6_shim6_p, tvb,
1187 offset + offsetof(struct ip6_shim, ip6s_p), 1, FALSE);
1189 /* skip the first 2 bytes (nxt hdr, hdr ext len, p+7bits) */
1192 if (shim.ip6s_p & SHIM6_BITMASK_P)
1194 tmp[0] = tvb_get_guint8(tvb, p++);
1195 tmp[1] = tvb_get_guint8(tvb, p++);
1196 tmp[2] = tvb_get_guint8(tvb, p++);
1197 tmp[3] = tvb_get_guint8(tvb, p++);
1198 tmp[4] = tvb_get_guint8(tvb, p++);
1200 /* Payload Extension Header */
1201 proto_tree_add_none_format(shim_tree, hf_ipv6_shim6_ct, tvb,
1202 offset + offsetof(struct ip6_shim, ip6s_p), 6,
1203 "Receiver Context Tag: %02x %02x %02x %02x %02x %02x",
1204 shim.ip6s_p & SHIM6_BITMASK_CT, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]);
1208 /* Control Message */
1213 proto_tree_add_item(shim_tree, hf_ipv6_shim6_type, tvb,
1214 offset + offsetof(struct ip6_shim, ip6s_p), 1,
1218 /* Protocol bit (Must be zero for SHIM6) */
1219 proto_tree_add_item(shim_tree, hf_ipv6_shim6_proto, tvb, p, 1, FALSE);
1223 csum = shim_checksum(tvb_get_ptr(tvb, offset, len), len);
1226 ti = proto_tree_add_uint_format(shim_tree, hf_ipv6_shim6_checksum, tvb, p, 2,
1227 tvb_get_ntohs(tvb, p), "Checksum: 0x%04x [correct]", tvb_get_ntohs(tvb, p));
1228 ipv6_shim6_checkum_additional_info(tvb, pinfo, ti, p, TRUE);
1230 ti = proto_tree_add_uint_format(shim_tree, hf_ipv6_shim6_checksum, tvb, p, 2,
1231 tvb_get_ntohs(tvb, p), "Checksum: 0x%04x [incorrect: should be 0x%04x]",
1232 tvb_get_ntohs(tvb, p), in_cksum_shouldbe(tvb_get_ntohs(tvb, p), csum));
1233 ipv6_shim6_checkum_additional_info(tvb, pinfo, ti, p, FALSE);
1237 /* Type specific data */
1238 advance = dissect_shimctrl(tvb, p, shim.ip6s_p & SHIM6_BITMASK_TYPE, shim_tree);
1242 while (p < offset+len) {
1243 p += dissect_shimopts(tvb, p, shim_tree, pinfo);
1250 /* END SHIM6 PART */
1253 dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1255 proto_tree *ipv6_tree = NULL;
1262 gboolean hopopts, routing, frag, ah, shim6, dstopts;
1266 fragment_data *ipfd_head;
1268 gboolean update_col_info = TRUE;
1269 gboolean save_fragmented = FALSE;
1270 const char *sep = "IPv6 ";
1272 struct ip6_hdr ipv6;
1274 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPv6");
1275 col_clear(pinfo->cinfo, COL_INFO);
1278 tvb_memcpy(tvb, (guint8 *)&ipv6, offset, sizeof(ipv6));
1280 /* Get extension header and payload length */
1281 plen = g_ntohs(ipv6.ip6_plen);
1283 /* Adjust the length of this tvbuff to include only the IPv6 datagram. */
1284 set_actual_length(tvb, plen + sizeof (struct ip6_hdr));
1286 SET_ADDRESS(&pinfo->net_src, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_SRC, 16));
1287 SET_ADDRESS(&pinfo->src, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_SRC, 16));
1288 SET_ADDRESS(&pinfo->net_dst, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_DST, 16));
1289 SET_ADDRESS(&pinfo->dst, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_DST, 16));
1295 /* !!! specify length */
1296 ti = proto_tree_add_item(tree, proto_ipv6, tvb, offset, 40, FALSE);
1297 ipv6_tree = proto_item_add_subtree(ti, ett_ipv6);
1299 /* !!! warning: version also contains 4 Bit priority */
1300 pi = proto_tree_add_item(ipv6_tree, hf_ipv6_version, tvb,
1301 offset + offsetof(struct ip6_hdr, ip6_vfc), 1, FALSE);
1302 pt = proto_item_add_subtree(pi,ett_ipv6_version);
1303 pi = proto_tree_add_item(pt, hf_ip_version, tvb,
1304 offset + offsetof(struct ip6_hdr, ip6_vfc), 1, FALSE);
1305 PROTO_ITEM_SET_GENERATED(pi);
1307 proto_tree_add_item(ipv6_tree, hf_ipv6_class, tvb,
1308 offset + offsetof(struct ip6_hdr, ip6_flow), 4, FALSE);
1310 proto_tree_add_item(ipv6_tree, hf_ipv6_flow, tvb,
1311 offset + offsetof(struct ip6_hdr, ip6_flow), 4, FALSE);
1313 proto_tree_add_item(ipv6_tree, hf_ipv6_plen, tvb,
1314 offset + offsetof(struct ip6_hdr, ip6_plen), 2, FALSE);
1316 proto_tree_add_uint_format(ipv6_tree, hf_ipv6_nxt, tvb,
1317 offset + offsetof(struct ip6_hdr, ip6_nxt), 1,
1319 "Next header: %s (0x%02x)",
1320 ipprotostr(ipv6.ip6_nxt), ipv6.ip6_nxt);
1322 proto_tree_add_item(ipv6_tree, hf_ipv6_hlim, tvb,
1323 offset + offsetof(struct ip6_hdr, ip6_hlim), 1, FALSE);
1325 /* Adds the different items for the source address */
1326 proto_tree_add_item(ipv6_tree, hf_ipv6_src, tvb,
1327 offset + offsetof(struct ip6_hdr, ip6_src), 16, FALSE);
1328 ti = proto_tree_add_ipv6(ipv6_tree, hf_ipv6_addr, tvb,
1329 offset + offsetof(struct ip6_hdr, ip6_src),
1330 16, (guint8 *)&ipv6.ip6_src);
1331 PROTO_ITEM_SET_HIDDEN(ti);
1332 ti = proto_tree_add_string(ipv6_tree, hf_ipv6_src_host, tvb,
1333 offset + offsetof(struct ip6_hdr, ip6_src),
1334 16, get_addr_name(&pinfo->src));
1335 PROTO_ITEM_SET_GENERATED(ti);
1336 PROTO_ITEM_SET_HIDDEN(ti);
1337 ti = proto_tree_add_string(ipv6_tree, hf_ipv6_host, tvb,
1338 offset + offsetof(struct ip6_hdr, ip6_src),
1339 16, get_addr_name(&pinfo->src));
1340 PROTO_ITEM_SET_GENERATED(ti);
1341 PROTO_ITEM_SET_HIDDEN(ti);
1343 /* Adds different items for the destination address */
1344 proto_tree_add_item(ipv6_tree, hf_ipv6_dst, tvb,
1345 offset + offsetof(struct ip6_hdr, ip6_dst), 16, FALSE);
1346 ti = proto_tree_add_ipv6(ipv6_tree, hf_ipv6_addr, tvb,
1347 offset + offsetof(struct ip6_hdr, ip6_dst),
1348 16, (guint8 *)&ipv6.ip6_dst);
1349 PROTO_ITEM_SET_HIDDEN(ti);
1350 ti = proto_tree_add_string(ipv6_tree, hf_ipv6_dst_host, tvb,
1351 offset + offsetof(struct ip6_hdr, ip6_dst),
1352 16, get_addr_name(&pinfo->dst));
1353 PROTO_ITEM_SET_GENERATED(ti);
1354 PROTO_ITEM_SET_HIDDEN(ti);
1355 ti = proto_tree_add_string(ipv6_tree, hf_ipv6_host, tvb,
1356 offset + offsetof(struct ip6_hdr, ip6_dst),
1357 16, get_addr_name(&pinfo->dst));
1358 PROTO_ITEM_SET_GENERATED(ti);
1359 PROTO_ITEM_SET_HIDDEN(ti);
1362 /* start of the new header (could be a extension header) */
1363 poffset = offset + offsetof(struct ip6_hdr, ip6_nxt);
1364 nxt = tvb_get_guint8(tvb, poffset);
1365 offset += sizeof(struct ip6_hdr);
1369 /* start out assuming this isn't fragmented, and has none of the other
1370 non-final headers */
1381 case IP_PROTO_HOPOPTS:
1383 advance = dissect_hopopts(tvb, offset, ipv6_tree, pinfo);
1384 nxt = tvb_get_guint8(tvb, offset);
1390 case IP_PROTO_ROUTING:
1392 advance = dissect_routing6(tvb, offset, ipv6_tree, pinfo);
1393 nxt = tvb_get_guint8(tvb, offset);
1399 case IP_PROTO_FRAGMENT:
1400 advance = dissect_frag6(tvb, offset, pinfo, ipv6_tree,
1402 nxt = tvb_get_guint8(tvb, offset);
1406 frag = offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG);
1407 save_fragmented |= frag;
1408 if (ipv6_reassemble && frag && tvb_bytes_exist(tvb, offset, plen)) {
1409 ipfd_head = fragment_add_check(tvb, offset, pinfo, ident,
1410 ipv6_fragment_table,
1411 ipv6_reassembled_table,
1412 offlg & IP6F_OFF_MASK,
1414 offlg & IP6F_MORE_FRAG);
1415 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv6",
1416 ipfd_head, &ipv6_frag_items, &update_col_info, ipv6_tree);
1417 if (next_tvb) { /* Process post-fragment headers after reassembly... */
1425 if (!(offlg & IP6F_OFF_MASK)) /*...or in the first fragment */
1431 advance = dissect_ah_header(tvb_new_subset_remaining(tvb, offset),
1432 pinfo, ipv6_tree, NULL, NULL);
1433 nxt = tvb_get_guint8(tvb, offset);
1439 case IP_PROTO_SHIM6:
1440 case IP_PROTO_SHIM6_OLD:
1442 advance = dissect_shim6(tvb, offset, ipv6_tree, pinfo);
1443 nxt = tvb_get_guint8(tvb, offset);
1444 stype = tvb_get_guint8(tvb, offset+2);
1450 case IP_PROTO_DSTOPTS:
1452 advance = dissect_dstopts(tvb, offset, ipv6_tree, pinfo);
1453 nxt = tvb_get_guint8(tvb, offset);
1463 /* Since we did not recognize this IPv6 option, check
1464 * whether it is a known protocol. If not, then it
1465 * is an unknown IPv6 option
1467 if (!dissector_get_port_handle(ip_dissector_table, nxt)) {
1468 advance = dissect_unknown_option(tvb, offset, ipv6_tree);
1469 nxt = tvb_get_guint8(tvb, offset);
1477 #ifdef TEST_FINALHDR
1478 ti = proto_tree_add_uint(ipv6_tree, hf_ipv6_final, tvb, poffset, 1, nxt);
1479 PROTO_ITEM_SET_HIDDEN(ti);
1482 /* collect packet info */
1483 pinfo->ipproto = nxt;
1484 pinfo->iplen = sizeof(ipv6) + plen + offset;
1485 pinfo->iphdrlen = offset;
1487 if (offlg & IP6F_OFF_MASK || (ipv6_reassemble && offlg & IP6F_MORE_FRAG)) {
1488 /* Not the first fragment, or the first when we are reassembling and there are more. */
1489 /* Don't dissect it; just show this as a fragment. */
1490 /* COL_INFO was filled in by "dissect_frag6()" */
1491 call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
1494 /* First fragment, not fragmented, or already reassembled. Dissect what we have here. */
1496 /* Get a tvbuff for the payload. */
1497 next_tvb = tvb_new_subset_remaining(tvb, offset);
1500 * If this is the first fragment, but not the only fragment,
1501 * tell the next protocol that.
1503 if (offlg & IP6F_MORE_FRAG)
1504 pinfo->fragmented = TRUE;
1506 pinfo->fragmented = FALSE;
1510 /* do lookup with the subdissector table */
1511 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1512 /* Unknown protocol.
1513 Handle "no next header" specially. */
1514 if (nxt == IP_PROTO_NONE) {
1515 if (check_col(pinfo->cinfo, COL_INFO)) {
1516 /* If we had an Authentication Header, the AH dissector already
1517 put something in the Info column; leave it there. */
1519 if (hopopts || routing || dstopts || shim6) {
1521 col_append_fstr(pinfo->cinfo, COL_INFO, "%shop-by-hop options",
1526 col_append_fstr(pinfo->cinfo, COL_INFO, "%srouting", sep);
1530 col_append_fstr(pinfo->cinfo, COL_INFO, "%sdestination options",
1534 if (stype & SHIM6_BITMASK_P) {
1535 col_append_str(pinfo->cinfo, COL_INFO, "Shim6 (Payload)");
1538 col_append_fstr(pinfo->cinfo, COL_INFO, "Shim6 (%s)",
1539 val_to_str(stype & SHIM6_BITMASK_TYPE, shimctrlvals, "Unknown"));
1543 col_set_str(pinfo->cinfo, COL_INFO, "IPv6 no next header");
1547 if (check_col(pinfo->cinfo, COL_INFO))
1548 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(nxt),nxt);
1550 call_dissector(data_handle, next_tvb, pinfo, tree);
1552 pinfo->fragmented = save_fragmented;
1556 proto_register_ipv6(void)
1558 static hf_register_info hf[] = {
1560 { "Version", "ipv6.version",
1561 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
1563 { "This field makes the filter \"ip.version == 6\" possible", "ip.version",
1564 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
1566 { "Traffic class", "ipv6.class",
1567 FT_UINT32, BASE_HEX, NULL, 0x0FF00000, NULL, HFILL }},
1569 { "Flowlabel", "ipv6.flow",
1570 FT_UINT32, BASE_HEX, NULL, 0x000FFFFF, NULL, HFILL }},
1572 { "Payload length", "ipv6.plen",
1573 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1575 { "Next header", "ipv6.nxt",
1576 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1578 { "Hop limit", "ipv6.hlim",
1579 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1581 { "Source", "ipv6.src",
1582 FT_IPv6, BASE_NONE, NULL, 0x0,
1583 "Source IPv6 Address", HFILL }},
1584 { &hf_ipv6_src_host,
1585 { "Source Host", "ipv6.src_host",
1586 FT_STRING, BASE_NONE, NULL, 0x0,
1587 "Source IPv6 Host", HFILL }},
1589 { "Destination", "ipv6.dst",
1590 FT_IPv6, BASE_NONE, NULL, 0x0,
1591 "Destination IPv6 Address", HFILL }},
1592 { &hf_ipv6_dst_host,
1593 { "Destination Host", "ipv6.dst_host",
1594 FT_STRING, BASE_NONE, NULL, 0x0,
1595 "Destination IPv6 Host", HFILL }},
1597 { "Address", "ipv6.addr",
1598 FT_IPv6, BASE_NONE, NULL, 0x0,
1599 "Source or Destination IPv6 Address", HFILL }},
1601 { "Host", "ipv6.host",
1602 FT_STRING, BASE_NONE, NULL, 0x0,
1603 "IPv6 Host", HFILL }},
1605 { &hf_ipv6_opt_pad1,
1606 { "Pad1", "ipv6.opt.pad1",
1607 FT_NONE, BASE_NONE, NULL, 0x0,
1608 "Pad1 Option", HFILL }},
1609 { &hf_ipv6_opt_padn,
1610 { "PadN", "ipv6.opt.padn",
1611 FT_UINT8, BASE_DEC, NULL, 0x0,
1612 "PadN Option", HFILL }},
1614 { "Destination Option", "ipv6.dst_opt",
1615 FT_NONE, BASE_NONE, NULL, 0x0,
1618 { "Hop-by-Hop Option", "ipv6.hop_opt",
1619 FT_NONE, BASE_NONE, NULL, 0x0,
1622 { "Unknown Extension Header", "ipv6.unknown_hdr",
1623 FT_NONE, BASE_NONE, NULL, 0x0,
1625 { &hf_ipv6_routing_hdr_opt,
1626 { "Routing Header, Type","ipv6.routing_hdr",
1627 FT_UINT8, BASE_DEC, NULL, 0x0,
1628 "Routing Header Option", HFILL }},
1629 { &hf_ipv6_routing_hdr_type,
1630 { "Type", "ipv6.routing_hdr.type",
1631 FT_UINT8, BASE_DEC, VALS(&routing_header_type), 0x0,
1632 "Routeing Header Type", HFILL }},
1633 { &hf_ipv6_routing_hdr_left,
1634 { "Left Segments", "ipv6.routing_hdr.left",
1635 FT_UINT8, BASE_DEC, NULL, 0x0,
1636 "Routing Header Left Segments", HFILL }},
1637 { &hf_ipv6_routing_hdr_addr,
1638 { "Address", "ipv6.routing_hdr.addr",
1639 FT_IPv6, BASE_NONE, NULL, 0x0,
1640 "Routing Header Address", HFILL }},
1641 { &hf_ipv6_frag_offset,
1642 { "Offset", "ipv6.fragment.offset",
1643 FT_UINT16, BASE_DEC_HEX, NULL, IP6F_OFF_MASK,
1644 "Fragment Offset", HFILL }},
1645 { &hf_ipv6_frag_more,
1646 { "More Fragment", "ipv6.fragment.more",
1647 FT_BOOLEAN, 16, TFS(&tfs_yes_no), IP6F_MORE_FRAG,
1648 "More Fragments", HFILL }},
1650 { "Identification", "ipv6.framgent.id",
1651 FT_UINT32, BASE_HEX, NULL, 0x0,
1652 "Fragment Identification", HFILL }},
1653 { &hf_ipv6_fragment_overlap,
1654 { "Fragment overlap", "ipv6.fragment.overlap",
1655 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1656 "Fragment overlaps with other fragments", HFILL }},
1658 { &hf_ipv6_fragment_overlap_conflict,
1659 { "Conflicting data in fragment overlap", "ipv6.fragment.overlap.conflict",
1660 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1661 "Overlapping fragments contained conflicting data", HFILL }},
1663 { &hf_ipv6_fragment_multiple_tails,
1664 { "Multiple tail fragments found", "ipv6.fragment.multipletails",
1665 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1666 "Several tails were found when defragmenting the packet", HFILL }},
1668 { &hf_ipv6_fragment_too_long_fragment,
1669 { "Fragment too long", "ipv6.fragment.toolongfragment",
1670 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1671 "Fragment contained data past end of packet", HFILL }},
1673 { &hf_ipv6_fragment_error,
1674 { "Defragmentation error", "ipv6.fragment.error",
1675 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1676 "Defragmentation error due to illegal fragments", HFILL }},
1678 { &hf_ipv6_fragment,
1679 { "IPv6 Fragment", "ipv6.fragment",
1680 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1683 { &hf_ipv6_fragments,
1684 { "IPv6 Fragments", "ipv6.fragments",
1685 FT_NONE, BASE_NONE, NULL, 0x0,
1688 { &hf_ipv6_reassembled_in,
1689 { "Reassembled IPv6 in frame", "ipv6.reassembled_in",
1690 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1691 "This IPv6 packet is reassembled in this frame", HFILL }},
1694 { &hf_ipv6_mipv6_type,
1695 { "Option Type", "ipv6.mipv6_type",
1696 FT_UINT8, BASE_DEC, NULL, 0x0,
1698 { &hf_ipv6_mipv6_length,
1699 { "Option Length", "ipv6.mipv6_length",
1700 FT_UINT8, BASE_DEC, NULL, 0x0,
1702 { &hf_ipv6_mipv6_home_address,
1703 { "Home Address", "ipv6.mipv6_home_address",
1704 FT_IPv6, BASE_NONE, NULL, 0x0,
1709 { "SHIM6", "ipv6.shim6",
1710 FT_NONE, BASE_NONE, NULL, 0x0,
1713 { &hf_ipv6_shim6_nxt,
1714 { "Next Header", "ipv6.shim6.nxt",
1715 FT_UINT8, BASE_DEC, NULL, 0x0,
1718 { &hf_ipv6_shim6_len,
1719 { "Header Ext Length", "ipv6.shim6.len",
1720 FT_UINT8, BASE_DEC, NULL, 0x0,
1724 { "P Bit", "ipv6.shim6.p",
1725 FT_BOOLEAN, 8, NULL, SHIM6_BITMASK_P,
1728 { &hf_ipv6_shim6_ct,
1729 { "Context Tag", "ipv6.shim6.ct",
1730 FT_NONE, BASE_NONE, NULL, 0x0,
1733 { &hf_ipv6_shim6_type,
1734 { "Message Type", "ipv6.shim6.type",
1736 VALS(shimctrlvals), SHIM6_BITMASK_TYPE,
1739 { &hf_ipv6_shim6_proto,
1740 { "Protocol", "ipv6.shim6.proto",
1742 VALS(shim6_protocol), SHIM6_BITMASK_PROTOCOL,
1745 { &hf_ipv6_shim6_checksum,
1746 { "Checksum", "ipv6.shim6.checksum",
1747 FT_UINT16, BASE_HEX, NULL, 0x0,
1748 "Shim6 Checksum", HFILL }},
1749 { &hf_ipv6_shim6_checksum_bad,
1750 { "Bad Checksum", "ipv6.shim6.checksum_bad",
1751 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1752 "Shim6 Bad Checksum", HFILL }},
1754 { &hf_ipv6_shim6_checksum_good,
1755 { "Good Checksum", "ipv6.shim6.checksum_good",
1756 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1759 { &hf_ipv6_shim6_inonce,
1760 { "Initiator Nonce", "ipv6.shim6.inonce",
1761 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1764 { &hf_ipv6_shim6_rnonce,
1765 { "Responder Nonce", "ipv6.shim6.rnonce",
1766 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1769 { &hf_ipv6_shim6_precvd,
1770 { "Probes Received", "ipv6.shim6.precvd",
1771 FT_UINT8, BASE_DEC, NULL, 0x0,
1774 { &hf_ipv6_shim6_psent,
1775 { "Probes Sent", "ipv6.shim6.psent",
1776 FT_UINT8, BASE_DEC, NULL, 0x0,
1779 { &hf_ipv6_shim6_psrc,
1780 { "Source Address", "ipv6.shim6.psrc",
1781 FT_IPv6, BASE_NONE, NULL, 0x0,
1782 "Shim6 Probe Source Address", HFILL }},
1784 { &hf_ipv6_shim6_pdst,
1785 { "Destination Address", "ipv6.shim6.pdst",
1786 FT_IPv6, BASE_NONE, NULL, 0x0,
1787 "Shim6 Probe Destination Address", HFILL }},
1789 { &hf_ipv6_shim6_pnonce,
1790 { "Nonce", "ipv6.shim6.pnonce",
1791 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1792 "Shim6 Probe Nonce", HFILL }},
1794 { &hf_ipv6_shim6_pdata,
1795 { "Data", "ipv6.shim6.pdata",
1796 FT_UINT32, BASE_HEX, NULL, 0x0,
1797 "Shim6 Probe Data", HFILL }},
1799 { &hf_ipv6_shim6_sulid,
1800 { "Sender ULID", "ipv6.shim6.sulid",
1801 FT_IPv6, BASE_NONE, NULL, 0x0,
1802 "Shim6 Sender ULID", HFILL }},
1804 { &hf_ipv6_shim6_rulid,
1805 { "Receiver ULID", "ipv6.shim6.rulid",
1806 FT_IPv6, BASE_NONE, NULL, 0x0,
1807 "Shim6 Receiver ULID", HFILL }},
1809 { &hf_ipv6_shim6_reap,
1810 { "REAP State", "ipv6.shim6.reap",
1811 FT_UINT8, BASE_DEC, NULL, 0x0,
1814 { &hf_ipv6_shim6_opt_type,
1815 { "Option Type", "ipv6.shim6.opt.type",
1816 FT_UINT16, BASE_DEC,
1817 VALS(shimoptvals), SHIM6_BITMASK_OPT_TYPE,
1818 "Shim6 Option Type", HFILL }},
1820 { &hf_ipv6_shim6_opt_critical,
1821 { "Option Critical Bit", "ipv6.shim6.opt.critical",
1824 SHIM6_BITMASK_CRITICAL,
1825 "TRUE : option is critical, FALSE: option is not critical",
1828 { &hf_ipv6_shim6_opt_len,
1829 { "Content Length", "ipv6.shim6.opt.len",
1830 FT_UINT16, BASE_DEC, NULL, 0x0,
1831 "Content Length Option", HFILL }},
1833 { &hf_ipv6_shim6_opt_total_len,
1834 { "Total Length", "ipv6.shim6.opt.total_len",
1835 FT_UINT16, BASE_DEC, NULL, 0x0,
1836 "Total Option Length", HFILL }},
1838 { &hf_ipv6_shim6_opt_loc_verif_methods,
1839 { "Verification Method", "ipv6.shim6.opt.verif_method",
1841 VALS(shimverifmethods), 0x0,
1842 "Locator Verification Method", HFILL }},
1844 { &hf_ipv6_shim6_opt_loclist,
1845 { "Locator List Generation", "ipv6.shim6.opt.loclist",
1846 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1849 { &hf_ipv6_shim6_locator,
1850 { "Locator", "ipv6.shim6.locator",
1851 FT_IPv6, BASE_NONE, NULL, 0x0,
1852 "Shim6 Locator", HFILL }},
1854 { &hf_ipv6_shim6_opt_locnum,
1855 { "Num Locators", "ipv6.shim6.opt.locnum",
1856 FT_UINT8, BASE_DEC, NULL, 0x0,
1857 "Number of Locators in Locator List", HFILL }},
1859 { &hf_ipv6_shim6_opt_elemlen,
1860 { "Element Length", "ipv6.shim6.opt.elemlen",
1861 FT_UINT8, BASE_DEC, NULL, 0x0,
1862 "Length of Elements in Locator Preferences Option", HFILL }},
1863 { &hf_ipv6_shim6_loc_flag,
1864 { "Flags", "ipv6.shim6.loc.flags",
1865 FT_UINT8, BASE_DEC, NULL, 0x0,
1866 "Locator Preferences Flags", HFILL }},
1868 { &hf_ipv6_shim6_loc_prio,
1869 { "Priority", "ipv6.shim6.loc.prio",
1870 FT_UINT8, BASE_DEC, NULL, 0x0,
1871 "Locator Preferences Priority", HFILL }},
1873 { &hf_ipv6_shim6_loc_weight,
1874 { "Weight", "ipv6.shim6.loc.weight",
1875 FT_UINT8, BASE_DEC, NULL, 0x0,
1876 "Locator Preferences Weight", HFILL }},
1878 { &hf_ipv6_shim6_opt_fii,
1879 { "Forked Instance Identifier", "ipv6.shim6.opt.fii",
1880 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1883 #ifdef TEST_FINALHDR
1885 { "Final next header", "ipv6.final",
1886 FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
1889 static gint *ett[] = {
1893 &ett_ipv6_shim6_option,
1894 &ett_ipv6_shim6_locators,
1895 &ett_ipv6_shim6_verif_methods,
1896 &ett_ipv6_shim6_loc_pref,
1897 &ett_ipv6_shim6_probes_sent,
1898 &ett_ipv6_shim6_probes_rcvd,
1899 &ett_ipv6_shim6_probe_sent,
1900 &ett_ipv6_shim6_probe_rcvd,
1901 &ett_ipv6_shim6_cksum,
1902 &ett_ipv6_fragments,
1905 module_t *ipv6_module;
1907 proto_ipv6 = proto_register_protocol("Internet Protocol Version 6", "IPv6", "ipv6");
1908 proto_register_field_array(proto_ipv6, hf, array_length(hf));
1909 proto_register_subtree_array(ett, array_length(ett));
1911 /* Register configuration options */
1912 ipv6_module = prefs_register_protocol(proto_ipv6, NULL);
1913 prefs_register_bool_preference(ipv6_module, "defragment",
1914 "Reassemble fragmented IPv6 datagrams",
1915 "Whether fragmented IPv6 datagrams should be reassembled",
1918 register_dissector("ipv6", dissect_ipv6, proto_ipv6);
1919 register_init_routine(ipv6_reassemble_init);
1923 proto_reg_handoff_ipv6(void)
1925 dissector_handle_t ipv6_handle;
1927 data_handle = find_dissector("data");
1928 ipv6_handle = find_dissector("ipv6");
1929 dissector_add("ethertype", ETHERTYPE_IPv6, ipv6_handle);
1930 dissector_add("ppp.protocol", PPP_IPV6, ipv6_handle);
1931 dissector_add("ppp.protocol", ETHERTYPE_IPv6, ipv6_handle);
1932 dissector_add("gre.proto", ETHERTYPE_IPv6, ipv6_handle);
1933 dissector_add("ip.proto", IP_PROTO_IPV6, ipv6_handle);
1934 dissector_add("null.type", BSD_AF_INET6_BSD, ipv6_handle);
1935 dissector_add("null.type", BSD_AF_INET6_FREEBSD, ipv6_handle);
1936 dissector_add("null.type", BSD_AF_INET6_DARWIN, ipv6_handle);
1937 dissector_add("chdlctype", ETHERTYPE_IPv6, ipv6_handle);
1938 dissector_add("fr.ietf", NLPID_IP6, ipv6_handle);
1939 dissector_add("osinl.excl", NLPID_IP6, ipv6_handle);
1940 dissector_add("x.25.spi", NLPID_IP6, ipv6_handle);
1941 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IPv6, ipv6_handle);
1943 ip_dissector_table = find_dissector_table("ip.proto");