/* packet-shim6.c * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later * * SHIM6 support added by Matthijs Mekking */ #include "config.h" #include #include #include #include #include #include #include "packet-ip.h" void proto_register_shim6(void); void proto_reg_handoff_shim6(void); /* SHIM6 header */ struct ip6_shim { guint8 ip6s_nxt; /* next header */ guint8 ip6s_len; /* header extension length */ guint8 ip6s_p; /* P field and first 7 bits of remainder */ /* followed by shim6 specific data*/ }; /* SHIM6 control message types */ #define SHIM6_TYPE_I1 0x01 /* 0 000 0001 */ #define SHIM6_TYPE_R1 0x02 /* 0 000 0010 */ #define SHIM6_TYPE_I2 0x03 /* 0 000 0011 */ #define SHIM6_TYPE_R2 0x04 /* 0 000 0100 */ #define SHIM6_TYPE_R1BIS 0x05 /* 0 000 0101 */ #define SHIM6_TYPE_I2BIS 0x06 /* 0 000 0110 */ #define SHIM6_TYPE_UPD_REQ 0x40 /* 0 100 0000 = 64 */ #define SHIM6_TYPE_UPD_ACK 0x41 /* 0 100 0001 = 65 */ #define SHIM6_TYPE_KEEPALIVE 0x42 /* 0 100 0010 = 66 */ #define SHIM6_TYPE_PROBE 0x43 /* 0 100 0011 = 67 */ /* SHIM6 Options */ #define SHIM6_OPT_RESPVAL 0x01 /* 0 000 0001 */ #define SHIM6_OPT_LOCLIST 0x02 /* 0 000 0010 */ #define SHIM6_OPT_LOCPREF 0x03 /* 0 000 0011 */ #define SHIM6_OPT_CGAPDM 0x04 /* 0 000 0100 */ #define SHIM6_OPT_CGASIG 0x05 /* 0 000 0101 */ #define SHIM6_OPT_ULIDPAIR 0x06 /* 0 000 0110 */ #define SHIM6_OPT_FII 0x07 /* 0 000 0111 */ /* SHIM6 Bitmasks */ #define SHIM6_BITMASK_P 0x80 /* 1 000 0000 */ #define SHIM6_BITMASK_TYPE 0x7F /* 0 111 1111 */ #define SHIM6_BITMASK_PROTOCOL 0x01 /* 0 000 0001 */ #define SHIM6_BITMASK_SPECIFIC 0xFE /* 1 111 1110 */ #define SHIM6_BITMASK_R 0x80 /* 1 000 0000 */ #define SHIM6_BITMASK_CT 0x7F /* 0 111 1111 */ #define SHIM6_BITMASK_OPT_TYPE 0xFFFE /* 1 111 1111 1 111 1110 */ #define SHIM6_BITMASK_CRITICAL 0x01 /* 0 000 0001 */ #define SHIM6_BITMASK_PRECVD 0xF0 /* 1 111 0000 */ #define SHIM6_BITMASK_PSENT 0x0F /* 0 000 1111 */ #define SHIM6_BITMASK_STA 0xC0 /* 1 100 0000 */ /* SHIM6 Verification Methods */ #define SHIM6_VERIF_HBA 0x01 /* 0 000 0001 */ #define SHIM6_VERIF_CGA 0x02 /* 0 000 0010 */ /* SHIM6 Flags */ #define SHIM6_FLAG_BROKEN 0x01 /* 0 000 0001 */ #define SHIM6_FLAG_TEMPORARY 0x02 /* 0 000 0010 */ /* SHIM6 REAP States */ #define SHIM6_REAP_OPERATIONAL 0x00 /* 0 000 0000 */ #define SHIM6_REAP_EXPLORING 0x01 /* 0 000 0001 */ #define SHIM6_REAP_INBOUNDOK 0x02 /* 0 000 0010 */ static int proto_shim6 = -1; static int hf_shim6_nxt = -1; static int hf_shim6_len = -1; static int hf_shim6_len_oct = -1; static int hf_shim6_p = -1; /* context tag is 49 bits, cannot be used for filter yet */ static int hf_shim6_ct = -1; static int hf_shim6_type = -1; static int hf_shim6_proto = -1; static int hf_shim6_checksum = -1; static int hf_shim6_checksum_status= -1; static int hf_shim6_inonce = -1; /* also for request nonce */ static int hf_shim6_rnonce = -1; static int hf_shim6_reserved = -1; static int hf_shim6_reserved2 = -1; static int hf_shim6_precvd = -1; static int hf_shim6_psent = -1; static int hf_shim6_psrc = -1; static int hf_shim6_pdst = -1; static int hf_shim6_pnonce = -1; static int hf_shim6_pdata = -1; static int hf_shim6_sulid = -1; static int hf_shim6_rulid = -1; static int hf_shim6_reap = -1; static int hf_shim6_opt_type = -1; static int hf_shim6_opt_len = -1; static int hf_shim6_opt_total_len = -1; static int hf_shim6_opt_loc_verif_methods = -1; static int hf_shim6_opt_critical = -1; static int hf_shim6_opt_loclist = -1; static int hf_shim6_locator = -1; static int hf_shim6_loc_flag = -1; static int hf_shim6_loc_prio = -1; static int hf_shim6_loc_weight = -1; static int hf_shim6_opt_locnum = -1; static int hf_shim6_opt_elemlen = -1; static int hf_shim6_opt_fii = -1; static int hf_shim6_validator = -1; static int hf_shim6_cga_parameter_data_structure = -1; static int hf_shim6_cga_signature = -1; static int hf_shim6_padding = -1; static gint ett_shim6_proto = -1; static gint ett_shim6_option = -1; static gint ett_shim6_locators = -1; static gint ett_shim6_verif_methods = -1; static gint ett_shim6_loc_pref = -1; static gint ett_shim6_probes_sent = -1; static gint ett_shim6_probe_sent = -1; static gint ett_shim6_probes_rcvd = -1; static gint ett_shim6_probe_rcvd = -1; static gint ett_shim6_cksum = -1; static expert_field ei_shim6_opt_elemlen_invalid = EI_INIT; static expert_field ei_shim6_checksum_bad = EI_INIT; static guint16 shim6_checksum(tvbuff_t *tvb, int offset, int len) { vec_t cksum_vec[1]; SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, offset, len); return in_cksum(&cksum_vec[0], 1); } static const value_string shimoptvals[] = { { SHIM6_OPT_RESPVAL, "Responder Validator Option" }, { SHIM6_OPT_LOCLIST, "Locator List Option" }, { SHIM6_OPT_LOCPREF, "Locator Preferences Option" }, { SHIM6_OPT_CGAPDM, "CGA Parameter Data Structure Option" }, { SHIM6_OPT_CGASIG, "CGA Signature Option" }, { SHIM6_OPT_ULIDPAIR, "ULID Pair Option" }, { SHIM6_OPT_FII, "Forked Instance Identifier Option" }, { 0, NULL } }; static const value_string shimverifmethods[] = { { SHIM6_VERIF_HBA, "HBA" }, { SHIM6_VERIF_CGA, "CGA" }, { 0, NULL } }; static const value_string shimflags[] _U_ = { { SHIM6_FLAG_BROKEN, "BROKEN" }, { SHIM6_FLAG_TEMPORARY, "TEMPORARY" }, { 0, NULL } }; static const value_string shimreapstates[] = { { SHIM6_REAP_OPERATIONAL, "Operational" }, { SHIM6_REAP_EXPLORING, "Exploring" }, { SHIM6_REAP_INBOUNDOK, "InboundOK" }, { 0, NULL } }; static const value_string shim6_protocol[] = { { 0, "SHIM6" }, { 1, "HIP" }, { 0, NULL } }; static void dissect_shim6_opt_loclist(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset) { proto_tree *subtree; guint count; guint optlen; proto_tree_add_item(opt_tree, hf_shim6_opt_loclist, tvb, *offset, 4, ENC_BIG_ENDIAN); *offset += 4; optlen = tvb_get_guint8(tvb, *offset); proto_tree_add_item(opt_tree, hf_shim6_opt_locnum, tvb, *offset, 1, ENC_BIG_ENDIAN); *offset += 1; /* Verification Methods */ subtree = proto_tree_add_subtree(opt_tree, tvb, *offset, optlen, ett_shim6_verif_methods, NULL, "Locator Verification Methods"); for (count=0; count < optlen; count++) proto_tree_add_item(subtree, hf_shim6_opt_loc_verif_methods, tvb, *offset+count, 1, ENC_BIG_ENDIAN); *offset += optlen; /* Padding, included in length field */ if ((7 - optlen % 8) > 0) { proto_tree_add_item(opt_tree, hf_shim6_padding, tvb, *offset, (7 - optlen % 8), ENC_NA); *offset += (7 - optlen % 8); } /* Locators */ subtree = proto_tree_add_subtree(opt_tree, tvb, *offset, 16 * optlen, ett_shim6_locators, NULL, "Locators"); for (count=0; count < optlen; count++) { proto_tree_add_item(subtree, hf_shim6_locator, tvb, *offset, 16, ENC_NA); *offset += 16; } } static void dissect_shim6_opt_loc_pref(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset, gint len, packet_info *pinfo) { proto_tree *subtree; gint optlen; gint count; proto_tree_add_item(opt_tree, hf_shim6_opt_loclist, tvb, *offset, 4, ENC_BIG_ENDIAN); *offset += 4; optlen = tvb_get_guint8(tvb, *offset); proto_tree_add_item(opt_tree, hf_shim6_opt_elemlen, tvb, *offset, 1, ENC_BIG_ENDIAN); if (optlen < 1 || optlen > 3) { proto_tree_add_expert_format(opt_tree, pinfo, &ei_shim6_opt_elemlen_invalid, tvb, *offset, 1, "Invalid element length: %u", optlen); return; } *offset += 1; /* Locator Preferences */ count = 1; while (*offset < len) { subtree = proto_tree_add_subtree_format(opt_tree, tvb, *offset, optlen, ett_shim6_loc_pref, NULL, "Locator Preferences %u", count); /* Flags */ if (optlen >= 1) proto_tree_add_item(subtree, hf_shim6_loc_flag, tvb, *offset, 1, ENC_BIG_ENDIAN); /* Priority */ if (optlen >= 2) proto_tree_add_item(subtree, hf_shim6_loc_prio, tvb, *offset+1, 1, ENC_BIG_ENDIAN); /* Weight */ if (optlen >= 3) proto_tree_add_item(subtree, hf_shim6_loc_weight, tvb, *offset+2, 1, ENC_BIG_ENDIAN); /* * Shim6 Draft 08 doesn't specify the format when the Element length is * more than three, except that any such formats MUST be defined so that * the first three octets are the same as in the above case, that is, a * of a 1 octet flags field followed by a 1 octet priority field, and a * 1 octet weight field. */ *offset += optlen; count++; } } static int dissect_shimopts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo) { int len, total_len; gint padding; proto_tree *opt_tree; proto_item *ti; offset += 4; len = tvb_get_ntohs(tvb, offset+2); padding = 7 - ((len + 3) % 8); total_len = 4 + len + padding; if (tree) { /* Option Type */ opt_tree = proto_tree_add_subtree(tree, tvb, offset, total_len, ett_shim6_option, NULL, val_to_str_const( (tvb_get_ntohs(tvb, offset) & SHIM6_BITMASK_OPT_TYPE) >> 1, shimoptvals, "Unknown Option Type")); proto_tree_add_item(opt_tree, hf_shim6_opt_type, tvb, offset, 2, ENC_BIG_ENDIAN); /* Critical */ proto_tree_add_item(opt_tree, hf_shim6_opt_critical, tvb, offset+1, 1, ENC_BIG_ENDIAN); /* Content Length */ proto_tree_add_item(opt_tree, hf_shim6_opt_len, tvb, offset + 2, 2, ENC_BIG_ENDIAN); ti = proto_tree_add_uint(opt_tree, hf_shim6_opt_total_len, tvb, offset+2, 2, total_len); PROTO_ITEM_SET_GENERATED(ti); /* Option Type Specific */ switch (tvb_get_ntohs(tvb, offset) >> 1) { case SHIM6_OPT_RESPVAL: proto_tree_add_item(opt_tree, hf_shim6_validator, tvb, offset, len, ENC_NA); offset += len; if (total_len-(len+4) > 0) proto_tree_add_item(opt_tree, hf_shim6_padding, tvb, offset, total_len-(len+4), ENC_NA); break; case SHIM6_OPT_LOCLIST: dissect_shim6_opt_loclist(opt_tree, tvb, &offset); break; case SHIM6_OPT_LOCPREF: dissect_shim6_opt_loc_pref(opt_tree, tvb, &offset, offset+len+4, pinfo); if (total_len-(len+4) > 0) proto_tree_add_item(opt_tree, hf_shim6_padding, tvb, offset, total_len-(len+4), ENC_NA); break; case SHIM6_OPT_CGAPDM: proto_tree_add_item(opt_tree, hf_shim6_cga_parameter_data_structure, tvb, offset, len, ENC_NA); offset += len; if (total_len-(len+4) > 0) proto_tree_add_item(opt_tree, hf_shim6_padding, tvb, offset, total_len-(len+4), ENC_NA); break; case SHIM6_OPT_CGASIG: proto_tree_add_item(opt_tree, hf_shim6_cga_signature, tvb, offset, len, ENC_NA); offset += len; if (total_len-(len+4) > 0) proto_tree_add_item(opt_tree, hf_shim6_padding, tvb, offset, total_len-(len+4), ENC_NA); break; case SHIM6_OPT_ULIDPAIR: proto_tree_add_item(opt_tree, hf_shim6_reserved, tvb, offset, 4, ENC_NA); offset += 4; proto_tree_add_item(opt_tree, hf_shim6_sulid, tvb, offset, 16, ENC_NA); offset += 16; proto_tree_add_item(opt_tree, hf_shim6_rulid, tvb, offset, 16, ENC_NA); offset += 16; break; case SHIM6_OPT_FII: proto_tree_add_item(opt_tree, hf_shim6_opt_fii, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; default: break; } } return total_len; } static void dissect_shim6_ct(proto_tree * shim_tree, gint hf_item, tvbuff_t * tvb, gint offset, const guchar * label) { guint8 tmp[6]; guchar *ct_str; tmp[0] = tvb_get_guint8(tvb, offset++); tmp[1] = tvb_get_guint8(tvb, offset++); tmp[2] = tvb_get_guint8(tvb, offset++); tmp[3] = tvb_get_guint8(tvb, offset++); tmp[4] = tvb_get_guint8(tvb, offset++); tmp[5] = tvb_get_guint8(tvb, offset++); ct_str = wmem_strdup_printf(wmem_packet_scope(), "%s: %02X %02X %02X %02X %02X %02X", label, tmp[0] & SHIM6_BITMASK_CT, tmp[1], tmp[2], tmp[3], tmp[4], tmp[5] ); proto_tree_add_none_format(shim_tree, hf_item, tvb, offset - 6, 6, "%s", ct_str); } static void dissect_shim6_probes(proto_tree * shim_tree, tvbuff_t * tvb, gint offset, const guchar * label, guint nbr_probe, gboolean probes_rcvd) { proto_tree *probes_tree; proto_tree *probe_tree; gint ett_probes; gint ett_probe; guint count; if (probes_rcvd) { ett_probes = ett_shim6_probes_rcvd; ett_probe = ett_shim6_probe_rcvd; } else { ett_probes = ett_shim6_probes_sent; ett_probe = ett_shim6_probe_sent; } probes_tree = proto_tree_add_subtree(shim_tree, tvb, offset, 40 * nbr_probe, ett_probes, NULL, label); for (count=0; count < nbr_probe; count++) { probe_tree = proto_tree_add_subtree_format(probes_tree, tvb, offset, 40, ett_probe, NULL, "Probe %u", count+1); proto_tree_add_item(probe_tree, hf_shim6_psrc, tvb, offset, 16, ENC_NA); offset += 16; proto_tree_add_item(probe_tree, hf_shim6_pdst, tvb, offset, 16, ENC_NA); offset += 16; proto_tree_add_item(probe_tree, hf_shim6_pnonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(probe_tree, hf_shim6_pdata, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } } /* Dissect SHIM6 data: control messages */ static int dissect_shimctrl(tvbuff_t *tvb, gint offset, guint type, proto_tree *shim_tree) { guint8 tmp; const gchar *sta; guint probes_sent; guint probes_rcvd; switch (type) { case SHIM6_TYPE_I1: dissect_shim6_ct(shim_tree, hf_shim6_ct, tvb, offset, "Initiator Context Tag"); offset += 6; proto_tree_add_item(shim_tree, hf_shim6_inonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case SHIM6_TYPE_R1: proto_tree_add_item(shim_tree, hf_shim6_reserved2, tvb, offset, 2, ENC_NA); offset += 2; proto_tree_add_item(shim_tree, hf_shim6_inonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(shim_tree, hf_shim6_rnonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case SHIM6_TYPE_I2: dissect_shim6_ct(shim_tree, hf_shim6_ct, tvb, offset, "Initiator Context Tag"); offset += 6; proto_tree_add_item(shim_tree, hf_shim6_inonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(shim_tree, hf_shim6_rnonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(shim_tree, hf_shim6_reserved2, tvb, offset, 4, ENC_NA); offset += 4; break; case SHIM6_TYPE_R2: dissect_shim6_ct(shim_tree, hf_shim6_ct, tvb, offset, "Responder Context Tag"); offset += 6; proto_tree_add_item(shim_tree, hf_shim6_inonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case SHIM6_TYPE_R1BIS: dissect_shim6_ct(shim_tree, hf_shim6_ct, tvb, offset, "Packet Context Tag"); offset += 6; proto_tree_add_item(shim_tree, hf_shim6_rnonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case SHIM6_TYPE_I2BIS: dissect_shim6_ct(shim_tree, hf_shim6_ct, tvb, offset, "Initiator Context Tag"); offset += 6; proto_tree_add_item(shim_tree, hf_shim6_inonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(shim_tree, hf_shim6_rnonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(shim_tree, hf_shim6_reserved2, tvb, offset, 6, ENC_NA); offset += 6; dissect_shim6_ct(shim_tree, hf_shim6_ct, tvb, offset, "Initiator Context Tag"); offset += 6; break; case SHIM6_TYPE_UPD_REQ: case SHIM6_TYPE_UPD_ACK: dissect_shim6_ct(shim_tree, hf_shim6_ct, tvb, offset, "Receiver Context Tag"); offset += 6; proto_tree_add_item(shim_tree, hf_shim6_rnonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case SHIM6_TYPE_KEEPALIVE: dissect_shim6_ct(shim_tree, hf_shim6_ct, tvb, offset, "Receiver Context Tag"); offset += 6; proto_tree_add_item(shim_tree, hf_shim6_reserved2, tvb, offset, 4, ENC_NA); offset += 4; break; case SHIM6_TYPE_PROBE: dissect_shim6_ct(shim_tree, hf_shim6_ct, tvb, offset, "Receiver Context Tag"); offset += 6; tmp = tvb_get_guint8(tvb, offset); probes_sent = tmp & SHIM6_BITMASK_PSENT; probes_rcvd = (tmp & SHIM6_BITMASK_PRECVD) >> 4; proto_tree_add_item(shim_tree, hf_shim6_psent, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(shim_tree, hf_shim6_precvd, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; sta = val_to_str_const((tvb_get_guint8(tvb, offset) & SHIM6_BITMASK_STA) >> 6, shimreapstates, "Unknown REAP State"); proto_tree_add_uint_format_value(shim_tree, hf_shim6_reap, tvb, offset, 1, (tvb_get_guint8(tvb, offset) & SHIM6_BITMASK_STA) >> 6, "%s", sta); proto_tree_add_item(shim_tree, hf_shim6_reserved2, tvb, offset, 3, ENC_NA); offset += 3; /* Probes Sent */ if (probes_sent) { dissect_shim6_probes(shim_tree, tvb, offset, "Probes Sent", probes_sent, FALSE); offset += 40 * probes_sent; } /* Probes Received */ if (probes_rcvd) { dissect_shim6_probes(shim_tree, tvb, offset, "Probes Received", probes_rcvd, TRUE); offset += 40 * probes_rcvd; } break; default: break; } return offset; } /* Dissect SHIM6 data: payload, common part, options */ static const value_string shimctrlvals[] = { { SHIM6_TYPE_I1, "I1" }, { SHIM6_TYPE_R1, "R1" }, { SHIM6_TYPE_I2, "I2" }, { SHIM6_TYPE_R2, "R2" }, { SHIM6_TYPE_R1BIS, "R1bis" }, { SHIM6_TYPE_I2BIS, "I2bis" }, { SHIM6_TYPE_UPD_REQ, "Update Request" }, { SHIM6_TYPE_UPD_ACK, "Update Acknowledgment" }, { SHIM6_TYPE_KEEPALIVE, "Keepalive" }, { SHIM6_TYPE_PROBE, "Probe" }, { 0, NULL } }; static int dissect_shim6(tvbuff_t *tvb, packet_info * pinfo, proto_tree *tree, void* data) { struct ip6_shim shim; int offset = 0, len; proto_tree *shim_tree, *root_tree; proto_item *ti, *ti_len; guint8 tmp[5]; tvbuff_t *next_tvb; tvb_memcpy(tvb, (guint8 *)&shim, offset, sizeof(shim)); len = (shim.ip6s_len + 1) << 3; if (shim.ip6s_p & SHIM6_BITMASK_P) { col_append_sep_str(pinfo->cinfo, COL_INFO, " , ", "Shim6 (Payload)"); } else { col_append_sep_fstr(pinfo->cinfo, COL_INFO, " , ", "Shim6 (%s)", val_to_str_const(shim.ip6s_p & SHIM6_BITMASK_TYPE, shimctrlvals, "Unknown")); } root_tree = p_ipv6_pinfo_select_root(pinfo, tree); p_ipv6_pinfo_add_len(pinfo, len); ti = proto_tree_add_item(root_tree, proto_shim6, tvb, offset, len, ENC_NA); shim_tree = proto_item_add_subtree(ti, ett_shim6_proto); /* Next Header */ proto_tree_add_uint_format_value(shim_tree, hf_shim6_nxt, tvb, offset, 1, shim.ip6s_nxt, "%s (%u)", ipprotostr(shim.ip6s_nxt), shim.ip6s_nxt); offset += 1; /* Header Extension Length */ ti_len = proto_tree_add_item(shim_tree, hf_shim6_len, tvb, offset, 1, ENC_BIG_ENDIAN); ti = proto_tree_add_uint(shim_tree, hf_shim6_len_oct, tvb, offset, 1, len); proto_item_append_text(ti, " bytes"); PROTO_ITEM_SET_GENERATED(ti); PROTO_ITEM_SET_HIDDEN(ti); proto_item_append_text(ti_len, " (%d bytes)", len); offset += 1; /* P Field */ proto_tree_add_item(shim_tree, hf_shim6_p, tvb, offset, 1, ENC_BIG_ENDIAN); if (shim.ip6s_p & SHIM6_BITMASK_P) { tmp[0] = tvb_get_guint8(tvb, offset+1); tmp[1] = tvb_get_guint8(tvb, offset+2); tmp[2] = tvb_get_guint8(tvb, offset+3); tmp[3] = tvb_get_guint8(tvb, offset+4); tmp[4] = tvb_get_guint8(tvb, offset+5); /* Payload Extension Header */ proto_tree_add_none_format(shim_tree, hf_shim6_ct, tvb, offset, 6, "Receiver Context Tag: %02x %02x %02x %02x %02x %02x", shim.ip6s_p & SHIM6_BITMASK_CT, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]); } else { /* Control Message */ guint16 csum; int advance; /* Message Type */ proto_tree_add_item(shim_tree, hf_shim6_type, tvb, offset, 1, ENC_BIG_ENDIAN); /* Protocol bit (Must be zero for SHIM6) */ proto_tree_add_item(shim_tree, hf_shim6_proto, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* Checksum */ csum = shim6_checksum(tvb, 0, len); proto_tree_add_checksum(shim_tree, tvb, offset, hf_shim6_checksum, hf_shim6_checksum_status, &ei_shim6_checksum_bad, pinfo, csum, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM); if (csum != 0) col_append_str(pinfo->cinfo, COL_INFO, " [Shim6 CHECKSUM INCORRECT]"); offset += 2; /* Type specific data */ advance = dissect_shimctrl(tvb, offset, shim.ip6s_p & SHIM6_BITMASK_TYPE, shim_tree); offset += advance; /* Options */ while (offset < len) { offset += dissect_shimopts(tvb, offset, shim_tree, pinfo); } } next_tvb = tvb_new_subset_remaining(tvb, len); ipv6_dissect_next(shim.ip6s_nxt, next_tvb, pinfo, tree, (ws_ip6 *)data); return tvb_captured_length(tvb); } void proto_register_shim6(void) { static hf_register_info hf_shim6[] = { { &hf_shim6_nxt, { "Next Header", "shim6.nxt", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_len, { "Length", "shim6.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Extension header length in 8-octet words (minus 1)", HFILL } }, { &hf_shim6_len_oct, { "Length", "shim6.len_oct", FT_UINT16, BASE_DEC, NULL, 0x0, "Extension header length in octets", HFILL } }, { &hf_shim6_p, { "P Bit", "shim6.p", FT_BOOLEAN, 8, NULL, SHIM6_BITMASK_P, NULL, HFILL } }, { &hf_shim6_ct, { "Context Tag", "shim6.ct", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_type, { "Message Type", "shim6.type", FT_UINT8, BASE_DEC, VALS(shimctrlvals), SHIM6_BITMASK_TYPE, NULL, HFILL } }, { &hf_shim6_proto, { "Protocol", "shim6.proto", FT_UINT8, BASE_DEC, VALS(shim6_protocol), SHIM6_BITMASK_PROTOCOL, NULL, HFILL } }, { &hf_shim6_checksum, { "Checksum", "shim6.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, "Shim6 Checksum", HFILL } }, { &hf_shim6_checksum_status, { "Checksum Status", "shim6.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL } }, { &hf_shim6_inonce, { "Initiator Nonce", "shim6.inonce", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_rnonce, { "Responder Nonce", "shim6.rnonce", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_reserved, { "Reserved", "shim6.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_reserved2, { "Reserved2", "shim6.reserved2", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_precvd, { "Probes Received", "shim6.precvd", FT_UINT8, BASE_DEC, NULL, SHIM6_BITMASK_PRECVD, NULL, HFILL } }, { &hf_shim6_psent, { "Probes Sent", "shim6.psent", FT_UINT8, BASE_DEC, NULL, SHIM6_BITMASK_PSENT, NULL, HFILL } }, { &hf_shim6_psrc, { "Source Address", "shim6.psrc", FT_IPv6, BASE_NONE, NULL, 0x0, "Shim6 Probe Source Address", HFILL } }, { &hf_shim6_pdst, { "Destination Address", "shim6.pdst", FT_IPv6, BASE_NONE, NULL, 0x0, "Shim6 Probe Destination Address", HFILL } }, { &hf_shim6_pnonce, { "Nonce", "shim6.pnonce", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, "Shim6 Probe Nonce", HFILL } }, { &hf_shim6_pdata, { "Data", "shim6.pdata", FT_UINT32, BASE_HEX, NULL, 0x0, "Shim6 Probe Data", HFILL } }, { &hf_shim6_sulid, { "Sender ULID", "shim6.sulid", FT_IPv6, BASE_NONE, NULL, 0x0, "Shim6 Sender ULID", HFILL } }, { &hf_shim6_rulid, { "Receiver ULID", "shim6.rulid", FT_IPv6, BASE_NONE, NULL, 0x0, "Shim6 Receiver ULID", HFILL } }, { &hf_shim6_reap, { "REAP State", "shim6.reap", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_opt_type, { "Option Type", "shim6.opt.type", FT_UINT16, BASE_DEC, VALS(shimoptvals), SHIM6_BITMASK_OPT_TYPE, "Shim6 Option Type", HFILL } }, { &hf_shim6_opt_critical, { "Option Critical Bit", "shim6.opt.critical", FT_BOOLEAN, 8, TFS(&tfs_yes_no), SHIM6_BITMASK_CRITICAL, "TRUE: option is critical, FALSE: option is not critical", HFILL } }, { &hf_shim6_opt_len, { "Content Length", "shim6.opt.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Content Length Option", HFILL } }, { &hf_shim6_opt_total_len, { "Total Length", "shim6.opt.total_len", FT_UINT16, BASE_DEC, NULL, 0x0, "Total Option Length", HFILL } }, { &hf_shim6_opt_loc_verif_methods, { "Verification Method", "shim6.opt.verif_method", FT_UINT8, BASE_DEC, VALS(shimverifmethods), 0x0, "Locator Verification Method", HFILL } }, { &hf_shim6_opt_loclist, { "Locator List Generation", "shim6.opt.loclist", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_locator, { "Locator", "shim6.locator", FT_IPv6, BASE_NONE, NULL, 0x0, "Shim6 Locator", HFILL } }, { &hf_shim6_opt_locnum, { "Num Locators", "shim6.opt.locnum", FT_UINT8, BASE_DEC, NULL, 0x0, "Number of locators in Locator List", HFILL } }, { &hf_shim6_opt_elemlen, { "Element Length", "shim6.opt.elemlen", FT_UINT8, BASE_DEC, NULL, 0x0, "Length of Elements in Locator Preferences Option", HFILL } }, { &hf_shim6_loc_flag, { "Flags", "shim6.loc.flags", FT_UINT8, BASE_DEC, NULL, 0x0, "Locator Preferences Flags", HFILL } }, { &hf_shim6_loc_prio, { "Priority", "shim6.loc.prio", FT_UINT8, BASE_DEC, NULL, 0x0, "Locator Preferences Priority", HFILL } }, { &hf_shim6_loc_weight, { "Weight", "shim6.loc.weight", FT_UINT8, BASE_DEC, NULL, 0x0, "Locator Preferences Weight", HFILL } }, { &hf_shim6_opt_fii, { "Forked Instance Identifier", "shim6.opt.fii", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_validator, { "Validator", "shim6.validator", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_cga_parameter_data_structure, { "CGA Parameter Data Structure", "shim6.cga_parameter_data_structure", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_cga_signature, { "CGA Signature", "shim6.cga_signature", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_shim6_padding, { "Padding", "shim6.padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } } }; static gint *ett_shim6[] = { &ett_shim6_proto, &ett_shim6_option, &ett_shim6_locators, &ett_shim6_verif_methods, &ett_shim6_loc_pref, &ett_shim6_probes_sent, &ett_shim6_probes_rcvd, &ett_shim6_probe_sent, &ett_shim6_probe_rcvd, &ett_shim6_cksum }; static ei_register_info ei_shim6[] = { { &ei_shim6_opt_elemlen_invalid, { "shim6.opt.elemlen.invalid", PI_MALFORMED, PI_ERROR, "Invalid element length", EXPFILL } }, { &ei_shim6_checksum_bad, { "shim6.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL } } }; expert_module_t* expert_shim6; proto_shim6 = proto_register_protocol("Shim6 Protocol", "Shim6", "shim6"); proto_register_field_array(proto_shim6, hf_shim6, array_length(hf_shim6)); proto_register_subtree_array(ett_shim6, array_length(ett_shim6)); expert_shim6 = expert_register_protocol(proto_shim6); expert_register_field_array(expert_shim6, ei_shim6, array_length(ei_shim6)); } void proto_reg_handoff_shim6(void) { dissector_handle_t shim6_handle; shim6_handle = create_dissector_handle(dissect_shim6, proto_shim6); dissector_add_uint("ip.proto", IP_PROTO_SHIM6, shim6_handle); } /* * Editor modelines * * Local Variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * ex: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */