Add DHCPv6 options for Softwire provisioning

Bug: 12719

Signed-off-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Signed-off-by: Sander Steffann <sander@steffann.nl>
Change-Id: I2792ef4a5851cd2fba75fc253aa3d635cb7f1fa6
Reviewed-on: https://code.wireshark.org/review/16860
This commit is contained in:
Niels Widger 2016-11-08 11:41:41 -05:00 committed by Alexis La Goutte
parent 8e5e6ddc5e
commit f1486a9f93
1 changed files with 247 additions and 0 deletions

View File

@ -24,6 +24,7 @@
* RFC5908.txt (Network Time Protocol (NTP) Server Option)
* RFC6334.txt (Dual-Stack Lite Option)
* RFC6603.txt (Prefix Exclude Option)
* RFC7598.txt (Configuration of Softwire Address and Port-Mapped Clients)
* draft-ietf-dhc-dhcpv6-opt-timeconfig-03.txt
* draft-ietf-dhc-dhcpv6-opt-lifetime-00.txt
* CL-SP-CANN-DHCP-Reg-I10-130808.pdf
@ -191,6 +192,23 @@ static int hf_cablelabs_ipv6_server = -1;
static int hf_cablelabs_docsis_version_number = -1;
static int hf_cablelabs_interface_id = -1;
static int hf_cablelabs_interface_id_link_address = -1;
static int hf_option_s46_rule_flags = -1;
static int hf_option_s46_rule_reserved_flag = -1;
static int hf_option_s46_rule_fmr_flag = -1;
static int hf_option_s46_rule_ea_len = -1;
static int hf_option_s46_rule_ipv4_pref_len = -1;
static int hf_option_s46_rule_ipv4_prefix = -1;
static int hf_option_s46_rule_ipv6_pref_len = -1;
static int hf_option_s46_rule_ipv6_prefix = -1;
static int hf_option_s46_br_address = -1;
static int hf_option_s46_dmr_pref_len = -1;
static int hf_option_s46_dmr_prefix = -1;
static int hf_option_s46_v4v6bind_ipv4_address = -1;
static int hf_option_s46_v4v6bind_ipv6_pref_len = -1;
static int hf_option_s46_v4v6bind_ipv6_prefix = -1;
static int hf_option_s46_portparam_offset = -1;
static int hf_option_s46_portparam_psid_len = -1;
static int hf_option_s46_portparam_psid = -1;
static gint ett_dhcpv6 = -1;
static gint ett_dhcpv6_option = -1;
@ -204,6 +222,7 @@ static gint ett_dhcpv6_dns_domain_search_list_option = -1;
static gint ett_dhcpv6_nis_domain_name_option = -1;
static gint ett_dhcpv6_nisp_domain_name_option = -1;
static gint ett_dhcpv6_bcmcs_servers_domain_search_list_option = -1;
static gint ett_dhcpv6_s46_rule_flags = -1;
static expert_field ei_dhcpv6_bogus_length = EI_INIT;
static expert_field ei_dhcpv6_malformed_option = EI_INIT;
@ -341,6 +360,14 @@ static dissector_handle_t dhcpv6_handle;
#define OPTION_V6_PCP_SERVER 86 /* RFC 7291 */
#define OPTION_DHCPV4_MSG 87 /* RFC 7341 */
#define OPTION_DHCP4_O_DHCP6_SERVER 88 /* RFC 7341 */
#define OPTION_S46_RULE 89 /* RFC 7598 */
#define OPTION_S46_BR 90 /* RFC 7598 */
#define OPTION_S46_DMR 91 /* RFC 7598 */
#define OPTION_S46_V4V6BIND 92 /* RFC 7598 */
#define OPTION_S46_PORTPARAMS 93 /* RFC 7598 */
#define OPTION_S46_CONT_MAPE 94 /* RFC 7598 */
#define OPTION_S46_CONT_MAPT 95 /* RFC 7598 */
#define OPTION_S46_CONT_LW 96 /* RFC 7598 */
#define OPTION_4RD 97 /* RFC 7600 */
#define OPTION_4RD_MAP_RULE 98 /* RFC 7600 */
#define OPTION_4RD_NON_MAP_RULE 99 /* RFC 7600 */
@ -479,6 +506,14 @@ static const value_string opttype_vals[] = {
{ OPTION_V6_PCP_SERVER, "PCP Server" },
{ OPTION_DHCPV4_MSG, "DHCPv4 Message" },
{ OPTION_DHCP4_O_DHCP6_SERVER, "DHCP 4o6 Servers Address" },
{ OPTION_S46_RULE, "S46 Rule" },
{ OPTION_S46_BR, "S46 BR" },
{ OPTION_S46_DMR, "S46 DMR" },
{ OPTION_S46_V4V6BIND, "S46 IPv4/IPv6 Address Binding" },
{ OPTION_S46_PORTPARAMS, "S46 Port Parameters" },
{ OPTION_S46_CONT_MAPE, "S46 MAP-E Container" },
{ OPTION_S46_CONT_MAPT, "S46 MAP-T Container" },
{ OPTION_S46_CONT_LW, "S46 Lightweight 4over6 Container" },
{ OPTION_4RD, "4rd Options" },
{ OPTION_4RD_MAP_RULE, "4rd Mapping Rule" },
{ OPTION_4RD_NON_MAP_RULE, "4rd Non-Mapping Rule" },
@ -776,6 +811,12 @@ typedef struct hopcount_info_t {
gboolean relay_message_previously_detected;
} hopcount_info;
static const int *dhcpv6_s46_rule_flags_fields[] = {
&hf_option_s46_rule_reserved_flag,
&hf_option_s46_rule_fmr_flag,
NULL
};
static void
initialize_hopount_info(hopcount_info *hpi) {
memset(hpi, 0, sizeof(hopcount_info));
@ -785,6 +826,9 @@ static void
dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
int off, int eoff, hopcount_info hpi);
static int
dissect_dhcpv6_s46_ipv6_prefix(tvbuff_t *tvb, int hf, int offset, int prefix_length, proto_tree *tree);
static int
dissect_packetcable_ccc_option(proto_tree *v_tree, proto_item *v_item, packet_info *pinfo, tvbuff_t *tvb, int optoff,
int optend)
@ -1456,7 +1500,158 @@ dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree,
temp_optlen += subopt_len;
}
break;
case OPTION_S46_RULE:
{
guint8 ipv4_pref_len, ipv6_pref_len;
int ipv6_pref_len_bytes;
if (optlen < 8) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_RULE: malformed option");
break;
}
/* 0 1 2 3 4 5 6 7
* +-+-+-+-+-+-+-+-+
* |Reserved |F|
* +-+-+-+-+-+-+-+-+
*/
proto_tree_add_bitmask(subtree, tvb, off, hf_option_s46_rule_flags, ett_dhcpv6_s46_rule_flags, dhcpv6_s46_rule_flags_fields, ENC_BIG_ENDIAN);
proto_tree_add_item(subtree, hf_option_s46_rule_ea_len, tvb, off + 1, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(subtree, hf_option_s46_rule_ipv4_pref_len, tvb, off + 2, 1, ENC_BIG_ENDIAN);
ipv4_pref_len = tvb_get_guint8(tvb, off + 2);
if (ipv4_pref_len > 32) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_RULE: malformed option");
break;
}
proto_tree_add_item(subtree, hf_option_s46_rule_ipv4_prefix, tvb, off + 3, 4, ENC_NA);
proto_tree_add_item(subtree, hf_option_s46_rule_ipv6_pref_len, tvb, off + 7, 1, ENC_BIG_ENDIAN);
ipv6_pref_len = tvb_get_guint8(tvb, off + 7);
if (ipv6_pref_len > 128) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_RULE: malformed option");
break;
}
ipv6_pref_len_bytes =
dissect_dhcpv6_s46_ipv6_prefix(tvb, hf_option_s46_rule_ipv6_prefix, off + 8, ipv6_pref_len, subtree);
temp_optlen = 8 + ipv6_pref_len_bytes;
while ((optlen - temp_optlen) > 0) {
temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
off+temp_optlen, off + optlen, at_end, protocol, hpi);
if (*at_end) {
/* Bad option - just skip to the end */
temp_optlen = optlen;
}
}
}
break;
case OPTION_S46_BR:
if (optlen != 16) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_BR: malformed option");
break;
}
proto_tree_add_item(subtree, hf_option_s46_br_address, tvb, off, 16, ENC_NA);
break;
case OPTION_S46_DMR:
{
guint8 dmr_pref_len;
if (optlen < 1 || optlen > 17) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_DMR: malformed option");
break;
}
proto_tree_add_item(subtree, hf_option_s46_dmr_pref_len, tvb, off, 1, ENC_BIG_ENDIAN);
dmr_pref_len = tvb_get_guint8(tvb, off);
if (dmr_pref_len > 128) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_DMR: malformed option");
break;
}
dissect_dhcpv6_s46_ipv6_prefix(tvb, hf_option_s46_dmr_prefix, off + 1, dmr_pref_len, subtree);
}
break;
case OPTION_S46_V4V6BIND:
{
guint8 ipv6_pref_len;
int ipv6_pref_len_bytes;
if (optlen < 5) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_V4V6BIND: malformed option");
break;
}
proto_tree_add_item(subtree, hf_option_s46_v4v6bind_ipv4_address, tvb, off, 4, ENC_NA);
proto_tree_add_item(subtree, hf_option_s46_v4v6bind_ipv6_pref_len, tvb, off + 4, 1, ENC_BIG_ENDIAN);
ipv6_pref_len = tvb_get_guint8(tvb, off + 4);
if (ipv6_pref_len > 128) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_V4V6BIND: malformed option");
break;
}
ipv6_pref_len_bytes =
dissect_dhcpv6_s46_ipv6_prefix(tvb, hf_option_s46_v4v6bind_ipv6_prefix, off + 5, ipv6_pref_len, subtree);
temp_optlen = 5 + ipv6_pref_len_bytes;
while ((optlen - temp_optlen) > 0) {
temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
off+temp_optlen, off + optlen, at_end, protocol, hpi);
if (*at_end) {
/* Bad option - just skip to the end */
temp_optlen = optlen;
}
}
}
break;
case OPTION_S46_PORTPARAMS:
{
guint16 psid;
guint8 offset, psid_len;
if (optlen != 4) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_PORTPARAMS: malformed option");
break;
}
proto_tree_add_item(subtree, hf_option_s46_portparam_offset, tvb, off, 1, ENC_BIG_ENDIAN);
offset = tvb_get_guint8(tvb, off);
if (offset > 15) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_PORTPARAMS: malformed option");
break;
}
proto_tree_add_item(subtree, hf_option_s46_portparam_psid_len, tvb, off + 1, 1, ENC_BIG_ENDIAN);
psid_len = tvb_get_guint8(tvb, off + 1);
if (psid_len > 16) {
expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_PORTPARAMS: malformed option");
break;
}
psid = tvb_get_ntohs(tvb, off + 2);
proto_tree_add_uint(subtree, hf_option_s46_portparam_psid, tvb, off + 2, 2, psid >> (16 - psid_len));
}
break;
case OPTION_S46_CONT_MAPE:
case OPTION_S46_CONT_MAPT:
case OPTION_S46_CONT_LW:
temp_optlen = 0;
while ((optlen - temp_optlen) > 0) {
temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
off+temp_optlen, off + optlen, at_end, protocol, hpi);
if (*at_end) {
/* Bad option - just skip to the end */
temp_optlen = optlen;
}
}
break;
case OPTION_IA_NA:
case OPTION_IA_PD:
if (optlen < 12) {
@ -2114,6 +2309,23 @@ dissect_dhcpv6_bulk_leasequery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr
return tvb_reported_length(tvb);
}
static int dissect_dhcpv6_s46_ipv6_prefix(tvbuff_t *tvb, int hf, int offset, int prefix_length, proto_tree *tree)
{
int bytes_to_process;
struct e_in6_addr prefix;
bytes_to_process = (((prefix_length + 7) & 0xf8) >> 3);
memset(prefix.bytes, 0, sizeof prefix.bytes);
if (bytes_to_process != 0) {
tvb_memcpy(tvb, prefix.bytes, offset, bytes_to_process);
}
proto_tree_add_ipv6(tree, hf, tvb, offset, bytes_to_process, &prefix);
return bytes_to_process;
}
void
proto_register_dhcpv6(void)
{
@ -2367,6 +2579,40 @@ proto_register_dhcpv6(void)
{ "Interface-ID", "dhcpv6.cablelabs.interface_id", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
{ &hf_cablelabs_interface_id_link_address,
{ "Link Address", "dhcpv6.cablelabs.interface_id_link_address", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_rule_flags,
{ "Flags", "dhcpv6.s46_rule.flags", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_rule_reserved_flag,
{ "Reserved", "dhcpv6.s46_rule.flags.reserved", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0xfe, NULL, HFILL }},
{ &hf_option_s46_rule_fmr_flag,
{ "Forwarding Mapping Rule", "dhcpv6.s46_rule.flags.fmr", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }},
{ &hf_option_s46_rule_ea_len,
{ "EA-bit length", "dhcpv6.s46_rule.ea_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_rule_ipv4_pref_len,
{ "IPv4 prefix length", "dhcpv6.s46_rule.ipv4_pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_rule_ipv4_prefix,
{ "IPv4 prefix", "dhcpv6.s46_rule.ipv4_prefix", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_rule_ipv6_pref_len,
{ "IPv6 prefix length", "dhcpv6.s46_rule.ipv6_prefix_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_rule_ipv6_prefix,
{ "IPv6 prefix", "dhcpv6.s46_rule.ipv6_prefix", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_br_address,
{ "BR address", "dhcpv6.s46_br.address", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_dmr_pref_len,
{ "IPv6 prefix length", "dhcpv6.s46_dmr.dmr_pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_dmr_prefix,
{ "IPv6 prefix", "dhcpv6.s46_dmr.dmr_prefix", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_v4v6bind_ipv4_address,
{ "IPv4 Address", "dhcpv6.s46_v4v6bind.ipv4_address", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_v4v6bind_ipv6_pref_len,
{ "IPv6 prefix length", "dhcpv6.s46_v4v6bind.ipv6_pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_v4v6bind_ipv6_prefix,
{ "IPv6 prefix", "dhcpv6.s46_v4v6bind.ipv6_prefix", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_portparam_offset,
{ "Offset", "dhcpv6.s46_portparam.offset", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_portparam_psid_len,
{ "PSID length", "dhcpv6.s46_portparam.psid_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_option_s46_portparam_psid,
{ "PSID", "dhcpv6.s46_portparam.psid", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
};
static gint *ett[] = {
@ -2382,6 +2628,7 @@ proto_register_dhcpv6(void)
&ett_dhcpv6_nis_domain_name_option,
&ett_dhcpv6_nisp_domain_name_option,
&ett_dhcpv6_bcmcs_servers_domain_search_list_option,
&ett_dhcpv6_s46_rule_flags,
};
static ei_register_info ei[] = {