diff options
-rw-r--r-- | epan/dissectors/packet-pim.c | 287 |
1 files changed, 279 insertions, 8 deletions
diff --git a/epan/dissectors/packet-pim.c b/epan/dissectors/packet-pim.c index 9c8bfc0074..945060414a 100644 --- a/epan/dissectors/packet-pim.c +++ b/epan/dissectors/packet-pim.c @@ -77,6 +77,31 @@ void proto_reg_handoff_pim(void); #define PIM_BDIR_DF_BACKOFF 3 #define PIM_BDIR_DF_PASS 4 +/* PIM Address Encoding Types */ + +#define PIM_ADDR_ET_NATIVE 0 /* RFC7761 */ +#define PIM_ADDR_ET_NATIVE_JA 1 /* RFC5384 */ + +#define PIM_JOIN_ATTRIBUTE_TYPE_RPF 0 /* RFC5496 */ +#define PIM_JOIN_ATTRIBUTE_TYPE_MVPN 1 /* RFC6513 */ +#define PIM_JOIN_ATTRIBUTE_TYPE_MTID 2 /* RFC6420 */ +#define PIM_JOIN_ATTRIBUTE_TYPE_PC 3 /* RFC6807 */ +#define PIM_JOIN_ATTRIBUTE_TYPE_EX_RPF 4 /* RFC7891 */ +#define PIM_JOIN_ATTRIBUTE_TYPE_TA 5 /* RFC8059 */ +#define PIM_JOIN_ATTRIBUTE_TYPE_RLOC 6 /* RFC8059 */ + +#define PIM_GROUP_ADDR_FLAGS_B 0x80 +#define PIM_GROUP_ADDR_FLAGS_RESERVED 0x7E +#define PIM_GROUP_ADDR_FLAGS_Z 0x01 + +#define PIM_SOURCE_ADDR_FLAGS_RESERVED 0xF8 +#define PIM_SOURCE_ADDR_FLAGS_S 0x04 +#define PIM_SOURCE_ADDR_FLAGS_W 0x02 +#define PIM_SOURCE_ADDR_FLAGS_R 0x01 + +#define PIM_SOURCE_JA_FLAGS_F 0x80 +#define PIM_SOURCE_JA_FLAGS_E 0x40 +#define PIM_SOURCE_JA_FLAGS_ATTR_TYPE 0x3F static const value_string pimtypevals[] = { { PIM_TYPE_HELLO, "Hello" }, @@ -130,6 +155,23 @@ static const value_string pim_opt_vals[] = { { 0, NULL } }; +static const value_string pim_addr_et_vals[] = { + { PIM_ADDR_ET_NATIVE, "Native"}, + { PIM_ADDR_ET_NATIVE_JA, "Native with Join Attribute"}, + { 0, NULL } +}; + +static const value_string pim_join_attribute_type_vals[] = { + { PIM_JOIN_ATTRIBUTE_TYPE_RPF, "RPF Vector TLV"}, + { PIM_JOIN_ATTRIBUTE_TYPE_MVPN, "MVPN Join Attribute"}, + { PIM_JOIN_ATTRIBUTE_TYPE_MTID, "MT-ID Join Attribute"}, + { PIM_JOIN_ATTRIBUTE_TYPE_PC, "Pop-Count"}, + { PIM_JOIN_ATTRIBUTE_TYPE_EX_RPF, "Explicit RPF Vector"}, + { PIM_JOIN_ATTRIBUTE_TYPE_TA, "Transport Attribute"}, + { PIM_JOIN_ATTRIBUTE_TYPE_RLOC, "Receiver RLOC Attribute"}, + { 0, NULL } +}; + enum pimv2_addrtype { pimv2_unicast, pimv2_group, pimv2_source }; @@ -219,12 +261,34 @@ static int hf_pim_src_flags_w = -1; static int hf_pim_src_flags_r = -1; static int hf_pim_src_flags_rsv = -1; static int hf_pim_mask_len = -1; +static int hf_pim_addr_af = -1; +static int hf_pim_addr_et = -1; +static int hf_pim_unicast_addr_ipv4 = -1; +static int hf_pim_unicast_addr_ipv6 = -1; +static int hf_pim_group = -1; +static int hf_pim_group_addr_flags = -1; +static int hf_pim_group_addr_flags_b = -1; +static int hf_pim_group_addr_flags_reserved = -1; +static int hf_pim_group_addr_flags_z = -1; +static int hf_pim_source_addr_flags = -1; +static int hf_pim_source_addr_flags_reserved = -1; +static int hf_pim_source_addr_flags_s = -1; +static int hf_pim_source_addr_flags_w = -1; +static int hf_pim_source_addr_flags_r = -1; +static int hf_pim_source_join_attribute = -1; +static int hf_pim_source_ja_flags = -1; +static int hf_pim_source_ja_flags_f = -1; +static int hf_pim_source_ja_flags_e = -1; +static int hf_pim_source_ja_flags_attr_type = -1; +static int hf_pim_source_ja_length = -1; +static int hf_pim_source_ja_value = -1; static int hf_pim_ttl = -1; static int hf_pim_interval = -1; static gint ett_pim = -1; static gint ett_pim_opts = -1; static gint ett_pim_opt = -1; +static gint ett_pim_addr_flags = -1; static expert_field ei_pim_cksum = EI_INIT; @@ -294,6 +358,28 @@ static const gint *pim_src_flags_fields[] = { NULL }; +static const int *pim_group_addr_flags[] = { + &hf_pim_group_addr_flags_b, + &hf_pim_group_addr_flags_reserved, + &hf_pim_group_addr_flags_z, + NULL +}; + +static const int *pim_source_addr_flags[] = { + &hf_pim_source_addr_flags_reserved, + &hf_pim_source_addr_flags_s, + &hf_pim_source_addr_flags_w, + &hf_pim_source_addr_flags_r, + NULL +}; + +static const int *pim_source_ja_flags[] = { + &hf_pim_source_ja_flags_f, + &hf_pim_source_ja_flags_e, + &hf_pim_source_ja_flags_attr_type, + NULL +}; + static void dissect_pimv1_addr(tvbuff_t *tvb, int offset, proto_tree *pim_tree, int hf_ip) { @@ -647,7 +733,13 @@ dissect_pim_addr(proto_tree* tree, tvbuff_t *tvb, int offset, enum pimv2_addrtyp ws_in6_addr ipv6; guint32 ipv4; proto_item* ti = NULL; + proto_tree* addr_tree = NULL; + proto_tree* ja_tree = NULL; int len = 0; + int ja_offset = 0; + guint8 ja_eos_type = 0; + guint8 ja_length = 0; + int ja_length_sum = 0; af = tvb_get_guint8(tvb, offset); if (af != AFNUM_INET && af != AFNUM_INET6) { @@ -659,9 +751,10 @@ dissect_pim_addr(proto_tree* tree, tvbuff_t *tvb, int offset, enum pimv2_addrtyp } et = tvb_get_guint8(tvb, offset + 1); - if (et != 0) { + if ((et != PIM_ADDR_ET_NATIVE) && (et != PIM_ADDR_ET_NATIVE_JA)) { /* - * The only defined encoding type is 0, for the native encoding; + * The only defined encoding type is 0 and 1, for the native encoding + * and native with Join Attribute TLVs; * again, as addresses don't include a length field, we can't * even show addresses with a different encoding type as raw * bytes. @@ -700,6 +793,17 @@ dissect_pim_addr(proto_tree* tree, tvbuff_t *tvb, int offset, enum pimv2_addrtyp } break; } + addr_tree = proto_item_add_subtree(ti, ett_pim); + proto_tree_add_item(addr_tree, hf_pim_addr_af, tvb, offset, 1, ENC_NA); + proto_tree_add_item(addr_tree, hf_pim_addr_et, tvb, offset+1, 1, ENC_NA); + switch (af) { + case AFNUM_INET: + proto_tree_add_item(addr_tree, hf_pim_unicast_addr_ipv4, tvb, offset+2, 4, ENC_BIG_ENDIAN); + break; + case AFNUM_INET6: + proto_tree_add_item(addr_tree, hf_pim_unicast_addr_ipv6, tvb, offset+2, 16, ENC_NA); + break; + } *advance = 2 + len; break; @@ -737,6 +841,20 @@ dissect_pim_addr(proto_tree* tree, tvbuff_t *tvb, int offset, enum pimv2_addrtyp proto_item_append_text(ti, "/%u", mask_len); break; } + addr_tree = proto_item_add_subtree(ti, ett_pim); + proto_tree_add_item(addr_tree, hf_pim_addr_af, tvb, offset, 1, ENC_NA); + proto_tree_add_item(addr_tree, hf_pim_addr_et, tvb, offset+1, 1, ENC_NA); + proto_tree_add_bitmask(addr_tree, tvb, offset+2, hf_pim_group_addr_flags, + ett_pim_addr_flags, pim_group_addr_flags, ENC_BIG_ENDIAN); + proto_tree_add_item(addr_tree, hf_pim_mask_len, tvb, offset+3, 1, ENC_NA); + switch (af) { + case AFNUM_INET: + proto_tree_add_item(addr_tree, hf_pim_group_ip4, tvb, offset+4, 4, ENC_BIG_ENDIAN); + break; + case AFNUM_INET6: + proto_tree_add_item(addr_tree, hf_pim_group_ip6, tvb, offset+4, 16, ENC_NA); + break; + } *advance = 4 + len; break; @@ -782,7 +900,53 @@ dissect_pim_addr(proto_tree* tree, tvbuff_t *tvb, int offset, enum pimv2_addrtyp flags & 0x02 ? "W" : "", flags & 0x01 ? "R" : ""); } - *advance = 4 + len; + addr_tree = proto_item_add_subtree(ti, ett_pim); + proto_tree_add_item(addr_tree, hf_pim_addr_af, tvb, offset, 1, ENC_NA); + proto_tree_add_item(addr_tree, hf_pim_addr_et, tvb, offset+1, 1, ENC_NA); + proto_tree_add_bitmask(addr_tree, tvb, offset+2, hf_pim_source_addr_flags, + ett_pim_addr_flags, pim_source_addr_flags, ENC_BIG_ENDIAN); + proto_tree_add_item(addr_tree, hf_pim_mask_len, tvb, offset+3, 1, ENC_NA); + switch (af) { + case AFNUM_INET: + proto_tree_add_item(addr_tree, hf_pim_source_ip4, tvb, offset+4, 4, ENC_BIG_ENDIAN); + break; + case AFNUM_INET6: + proto_tree_add_item(addr_tree, hf_pim_source_ip6, tvb, offset+4, 16, ENC_NA); + break; + } + + if (et == PIM_ADDR_ET_NATIVE_JA) { + ja_offset = offset + 4 + len; + while (((ja_eos_type & 0x40) != 0x40) && (tvb_reported_length_remaining(tvb, ja_offset) >= 2)) { + ja_length = tvb_get_guint8(tvb, ja_offset+1); + ti = proto_tree_add_item(addr_tree, hf_pim_source_join_attribute, tvb, ja_offset, ja_length + 2, ENC_NA); + ja_tree = proto_item_add_subtree(ti, ett_pim); + ja_eos_type = tvb_get_guint8(tvb, ja_offset); + proto_tree_add_bitmask(ja_tree, tvb, ja_offset, hf_pim_source_ja_flags, + ett_pim_addr_flags, pim_source_ja_flags, ENC_BIG_ENDIAN); + proto_item_append_text(ti, ": %s", val_to_str(ja_eos_type & 0x3F, pim_join_attribute_type_vals, "Unknown")); + ja_offset += 1; + proto_tree_add_item(ja_tree, hf_pim_source_ja_length, tvb, ja_offset, 1, ENC_BIG_ENDIAN); + ja_offset += 1; + switch(ja_eos_type & 0x3F) { + case PIM_JOIN_ATTRIBUTE_TYPE_RPF: + if ((ja_length == 6) || (ja_length == 18)) { + int advance_attr; + dissect_pim_addr(ja_tree, tvb, ja_offset, pimv2_unicast, NULL, NULL, + hf_pim_unicast_addr_ipv4, hf_pim_unicast_addr_ipv6, &advance_attr); + } else { + proto_tree_add_item(ja_tree, hf_pim_source_ja_value, tvb, ja_offset, ja_length, ENC_NA); + } + break; + default: + proto_tree_add_item(ja_tree, hf_pim_source_ja_value, tvb, ja_offset, ja_length, ENC_NA); + } + ja_offset += ja_length; + ja_length_sum += (2 + (int)ja_length); + } + } + *advance = 4 + len + ja_length_sum; + break; default: return FALSE; @@ -1123,12 +1287,13 @@ dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) offset += 2; for (i = 0; i < ngroup; i++) { - if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_group, - wmem_strdup_printf(wmem_packet_scope(), "Group %d", i), &tigroup, + tigroup=proto_tree_add_string_format(pimopt_tree, hf_pim_group, tvb, offset, -1, "", "Group %d", i); + grouptree = proto_item_add_subtree(tigroup, ett_pim); + if (!dissect_pim_addr(grouptree, tvb, offset, pimv2_group, + wmem_strdup_printf(wmem_packet_scope(), "Group %d", i), NULL, hf_pim_group_ip4, hf_pim_group_ip6, &advance)) goto breakbreak3; - grouptree = proto_item_add_subtree(tigroup, ett_pim); offset += advance; njoin = tvb_get_ntohs(tvb, offset); @@ -1804,12 +1969,118 @@ proto_register_pim(void) FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_pim_addr_af, + { "Address Family", "pim.addr_address_family", + FT_UINT8, BASE_DEC, VALS(afn_vals), 0x0, + NULL, HFILL } + }, + { &hf_pim_addr_et, + { "Encoding Type", "pim.addr_encoding_type", + FT_UINT8, BASE_DEC, VALS(pim_addr_et_vals), 0x0, + NULL, HFILL } + }, + { &hf_pim_unicast_addr_ipv4, + { "Unicast", "pim.unicast", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pim_unicast_addr_ipv6, + { "Unicast", "pim.unicast_ipv6", + FT_IPv6, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pim_group, + { "Group", "pim.group_set", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pim_group_addr_flags, + { "Flags", "pim.group_addr.flags", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pim_group_addr_flags_b, + { "Bidirectional PIM", "pim.group_addr.flags.b", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_GROUP_ADDR_FLAGS_B, + NULL, HFILL } + }, + { &hf_pim_group_addr_flags_reserved, + { "Reserved", "pim.group_addr.flags.reserved", + FT_UINT8, BASE_HEX, NULL, PIM_GROUP_ADDR_FLAGS_RESERVED, + NULL, HFILL } + }, + { &hf_pim_group_addr_flags_z, + { "Admin Scope Zone", "pim.group_addr.flags.z", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_GROUP_ADDR_FLAGS_Z, + NULL, HFILL } + }, + { &hf_pim_source_addr_flags, + { "Flags", "pim.source_addr.flags", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pim_source_addr_flags_reserved, + { "Reserved", "pim.source_addr.flags.reserved", + FT_UINT8, BASE_HEX, NULL, PIM_SOURCE_ADDR_FLAGS_RESERVED, + NULL, HFILL } + }, + { &hf_pim_source_addr_flags_s, + { "Sparse", "pim.source_addr.flags.s", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_ADDR_FLAGS_S, + NULL, HFILL } + }, + { &hf_pim_source_addr_flags_w, + { "WildCard", "pim.source_addr.flags.w", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_ADDR_FLAGS_W, + NULL, HFILL } + }, + { &hf_pim_source_addr_flags_r, + { "Rendezvous Point Tree", "pim.source_addr.flags.r", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_ADDR_FLAGS_R, + NULL, HFILL } + }, + { &hf_pim_source_join_attribute, + { "Join Attribute", "pim.source_ja", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pim_source_ja_flags, + { "Flags", "pim.source_ja.flags", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pim_source_ja_flags_f, + { "Forward", "pim.source_ja.flags.f", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_JA_FLAGS_F, + NULL, HFILL } + }, + { &hf_pim_source_ja_flags_e, + { "End of Attributes", "pim.source_ja.flags.e", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_JA_FLAGS_E, + NULL, HFILL } + }, + { &hf_pim_source_ja_flags_attr_type, + { "Attribute Type", "pim.source_ja.flags.attr_type", + FT_UINT8, BASE_DEC, VALS(pim_join_attribute_type_vals), PIM_SOURCE_JA_FLAGS_ATTR_TYPE, + NULL, HFILL } + }, + { &hf_pim_source_ja_length, + { "Length", "pim.source_ja.length", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pim_source_ja_value, + { "Value", "pim.source_ja.length", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, }; static gint *ett[] = { &ett_pim, - &ett_pim_opts, /* Tree for all options */ - &ett_pim_opt /* Tree for each option */ + &ett_pim_opts, /* Tree for all options */ + &ett_pim_opt, /* Tree for each option */ + &ett_pim_addr_flags /* Tree for flags */ }; static ei_register_info ei[] = { |