diff options
author | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-03-04 22:32:06 +0000 |
---|---|---|
committer | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-03-04 22:32:06 +0000 |
commit | 413deb9130d495549e142147148d8d573e2ec043 (patch) | |
tree | 24360bd323c70842969701d281e5ceb78c866559 /epan | |
parent | 91a8ef6b5f74333032bd41d8093271c0c2009900 (diff) |
from Carlos Pignataro
update MPLS to support MPLS Echo
svn path=/trunk/; revision=13590
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/Makefile.common | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-mpls-echo.c | 832 | ||||
-rw-r--r-- | epan/dissectors/packet-mpls.c | 23 | ||||
-rw-r--r-- | epan/dissectors/packet-mpls.h | 45 |
4 files changed, 841 insertions, 60 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 0f6159f57d..d482ac1ee1 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -715,6 +715,7 @@ DISSECTOR_INCLUDES = \ packet-MAP_DialoguePDU.h \ packet-mip6.h \ packet-mount.h \ + packet-mpls.h \ packet-mq.h \ packet-mrdisc.h \ packet-msnip.h \ diff --git a/epan/dissectors/packet-mpls-echo.c b/epan/dissectors/packet-mpls-echo.c index ec2b2b99f8..9f0df19381 100644 --- a/epan/dissectors/packet-mpls-echo.c +++ b/epan/dissectors/packet-mpls-echo.c @@ -36,6 +36,7 @@ #include <epan/sminmpec.h> #include "packet-ntp.h" #include "packet-ldp.h" +#include "packet-mpls.h" #define UDP_PORT_MPLS_ECHO 3503 @@ -44,6 +45,9 @@ void proto_reg_handoff_mpls_echo(void); static int proto_mpls_echo = -1; static int hf_mpls_echo_version = -1; static int hf_mpls_echo_mbz = -1; +static int hf_mpls_echo_gflags = -1; +static int hf_mpls_echo_flag_sbz = -1; +static int hf_mpls_echo_flag_v = -1; static int hf_mpls_echo_msgtype = -1; static int hf_mpls_echo_replymode = -1; static int hf_mpls_echo_returncode = -1; @@ -77,13 +81,60 @@ static int hf_mpls_echo_tlv_fec_l2cid_remote = -1; static int hf_mpls_echo_tlv_fec_l2cid_vcid = -1; static int hf_mpls_echo_tlv_fec_l2cid_encap = -1; static int hf_mpls_echo_tlv_fec_l2cid_mbz = -1; +static int hf_mpls_echo_tlv_fec_bgp_nh = -1; +static int hf_mpls_echo_tlv_fec_bgp_ipv4 = -1; +static int hf_mpls_echo_tlv_fec_bgp_len = -1; +static int hf_mpls_echo_tlv_fec_gen_ipv4 = -1; +static int hf_mpls_echo_tlv_fec_gen_ipv4_mask = -1; +static int hf_mpls_echo_tlv_fec_gen_ipv6 = -1; +static int hf_mpls_echo_tlv_fec_gen_ipv6_mask = -1; +static int hf_mpls_echo_tlv_fec_nil_label = -1; +static int hf_mpls_echo_tlv_ds_map_mtu = -1; +static int hf_mpls_echo_tlv_ds_map_addr_type = -1; +static int hf_mpls_echo_tlv_ds_map_res = -1; +static int hf_mpls_echo_tlv_ds_map_flag_res = -1; +static int hf_mpls_echo_tlv_ds_map_flag_i = -1; +static int hf_mpls_echo_tlv_ds_map_flag_n = -1; +static int hf_mpls_echo_tlv_ds_map_ds_ip = -1; +static int hf_mpls_echo_tlv_ds_map_int_ip = -1; +static int hf_mpls_echo_tlv_ds_map_if_index = -1; +static int hf_mpls_echo_tlv_ds_map_ds_ipv6 = -1; +static int hf_mpls_echo_tlv_ds_map_int_ipv6 = -1; +static int hf_mpls_echo_tlv_ds_map_hash_type = -1; +static int hf_mpls_echo_tlv_ds_map_depth = -1; +static int hf_mpls_echo_tlv_ds_map_muti_len = -1; +static int hf_mpls_echo_tlv_ds_map_mp_ip = -1; +static int hf_mpls_echo_tlv_ds_map_mp_mask = -1; +static int hf_mpls_echo_tlv_ds_map_mp_ip_low = -1; +static int hf_mpls_echo_tlv_ds_map_mp_ip_high = -1; +static int hf_mpls_echo_tlv_ds_map_mp_value = -1; +static int hf_mpls_echo_tlv_ds_map_mp_label = -1; +static int hf_mpls_echo_tlv_ds_map_mp_exp = -1; +static int hf_mpls_echo_tlv_ds_map_mp_bos = -1; +static int hf_mpls_echo_tlv_ds_map_mp_proto = -1; static int hf_mpls_echo_tlv_padaction = -1; static int hf_mpls_echo_tlv_padding = -1; static int hf_mpls_echo_tlv_vendor = -1; +static int hf_mpls_echo_tlv_ilso_ipv4_addr = -1; +static int hf_mpls_echo_tlv_ilso_ipv4_int_addr = -1; +static int hf_mpls_echo_tlv_ilso_ipv6_addr = -1; +static int hf_mpls_echo_tlv_ilso_ipv6_int_addr = -1; +static int hf_mpls_echo_tlv_ilso_label = -1; +static int hf_mpls_echo_tlv_ilso_exp = -1; +static int hf_mpls_echo_tlv_ilso_bos = -1; +static int hf_mpls_echo_tlv_ilso_ttl = -1; +static int hf_mpls_echo_tlv_rto_ipv4 = -1; +static int hf_mpls_echo_tlv_rto_ipv6 = -1; +static int hf_mpls_echo_tlv_reply_tos = -1; +static int hf_mpls_echo_tlv_reply_tos_mbz = -1; +static int hf_mpls_echo_tlv_errored_type = -1; static gint ett_mpls_echo = -1; +static gint ett_mpls_echo_gflags = -1; static gint ett_mpls_echo_tlv = -1; static gint ett_mpls_echo_tlv_fec = -1; +static gint ett_mpls_echo_tlv_ds_map = -1; +static gint ett_mpls_echo_tlv_ilso = -1; static int mpls_echo_udp_port = 0; @@ -92,6 +143,8 @@ static guint32 global_mpls_echo_udp_port = UDP_PORT_MPLS_ECHO; static const value_string mpls_echo_msgtype[] = { {1, "MPLS Echo Request"}, {2, "MPLS Echo Reply"}, + {3, "MPLS Data Plane Verification Request"}, + {4, "MPLS Data Plane Verification Reply"}, {0, NULL} }; @@ -117,6 +170,7 @@ static const value_string mpls_echo_returncode[] = { {10, "Mapping for this FEC is not the given label at stack depth RSC"}, {11, "No label entry at stack-depth RSC"}, {12, "Protocol not associated with interface at FEC stack depth RSC"}, + {13, "Premature termination, label stack shrinking to a single label"}, {0, NULL} }; @@ -125,6 +179,13 @@ static const value_string mpls_echo_returncode[] = { #define TLV_PAD 0x0003 #define TLV_ERROR_CODE 0x0004 #define TLV_VENDOR_CODE 0x0005 +#define TLV_TBD 0x0006 +#define TLV_ILSO_IPv4 0x0007 +#define TLV_ILSO_IPv6 0x0008 +#define TLV_ERRORED_TLV 0x0009 +#define TLV_REPLY_TOS 0x000A +#define TLV_RTO_IPv4 0x000B +#define TLV_RTO_IPv6 0x000C #define TLV_VENDOR_PRIVATE_START 0xFC00 #define TLV_VENDOR_PRIVATE_END 0xFFFF @@ -135,6 +196,13 @@ static const value_string mpls_echo_tlv_type_names[] = { { TLV_PAD, "Pad" }, { TLV_ERROR_CODE, "Error Code" }, { TLV_VENDOR_CODE, "Vendor Enterprise Code" }, + { TLV_TBD, "TDB" }, + { TLV_ILSO_IPv4, "IPv4 Interface and Label Stack Object" }, + { TLV_ILSO_IPv6, "IPv6 Interface and Label Stack Object" }, + { TLV_ERRORED_TLV, "Errored TLVs" }, + { TLV_REPLY_TOS, "Reply TOS Byte" }, + { TLV_RTO_IPv4, "IPv4 Reply-to Object" }, + { TLV_RTO_IPv6, "IPv6 Reply-to Object" }, { TLV_VENDOR_PRIVATE_START, "Vendor Private" }, { 0, NULL} }; @@ -149,6 +217,12 @@ static const value_string mpls_echo_tlv_type_names[] = { #define TLV_FEC_STACK_L2_VPN 8 #define TLV_FEC_STACK_L2_CID_OLD 9 #define TLV_FEC_STACK_L2_CID_NEW 10 +#define TLV_FEC_STACK_L2_FEC_129 11 +#define TLV_FEC_STACK_BGP_LAB_v4 12 +#define TLV_FEC_STACK_BGP_LAB_v6 13 +#define TLV_FEC_STACK_GEN_IPv4 14 +#define TLV_FEC_STACK_GEN_IPv6 15 +#define TLV_FEC_STACK_NIL 16 #define TLV_FEC_VENDOR_PRIVATE_START 0xFC00 #define TLV_FEC_VENDOR_PRIVATE_END 0xFFFF @@ -162,8 +236,14 @@ static const value_string mpls_echo_tlv_fec_names[] = { { TLV_FEC_STACK_VPN_IPv4, "VPN IPv4 prefix"}, { TLV_FEC_STACK_VPN_IPv6, "VPN IPv6 prefix"}, { TLV_FEC_STACK_L2_VPN, "L2 VPN endpoint"}, - { TLV_FEC_STACK_L2_CID_OLD, "L2 cirtuit ID (deprecated)"}, - { TLV_FEC_STACK_L2_CID_NEW, "L2 cirtuit ID (current)"}, + { TLV_FEC_STACK_L2_CID_OLD, "FEC 128 Pseudowire (old)"}, + { TLV_FEC_STACK_L2_CID_NEW, "FEC 128 Pseudowire (new)"}, + { TLV_FEC_STACK_L2_FEC_129, "FEC 129 Pseudowire"}, + { TLV_FEC_STACK_BGP_LAB_v4, "BGP labeled IPv4 prefix"}, + { TLV_FEC_STACK_BGP_LAB_v6, "BGP labeled IPv6 prefix"}, + { TLV_FEC_STACK_GEN_IPv4, "Generic IPv4 prefix"}, + { TLV_FEC_STACK_GEN_IPv6, "Generic IPv6 prefix"}, + { TLV_FEC_STACK_NIL, "Nil FEC"}, { TLV_FEC_VENDOR_PRIVATE_START, "Vendor Private"}, { 0, NULL} }; @@ -174,6 +254,54 @@ static const value_string mpls_echo_tlv_pad[] = { { 0, NULL} }; +#define TLV_DS_MAP_ADDR_IPv4 1 +#define TLV_DS_MAP_ADDR_UNNUM_IPv4 2 +#define TLV_DS_MAP_ADDR_IPv6 3 +#define TLV_DS_MAP_ADDR_UNNUM_IPv6 4 + +static const value_string mpls_echo_tlv_ds_map_addr_type[] = { + {TLV_DS_MAP_ADDR_IPv4, "IPv4 Numbered"}, + {TLV_DS_MAP_ADDR_UNNUM_IPv4, "IPv4 Unnumbered"}, + {TLV_DS_MAP_ADDR_IPv6, "IPv6 Numbered"}, + {TLV_DS_MAP_ADDR_UNNUM_IPv6, "IPv6 Unnumbered"}, + {0, NULL} +}; + +#define TLV_DS_MAP_HASH_NO_MP 0 +#define TLV_DS_MAP_HASH_LABEL 1 +#define TLV_DS_MAP_HASH_IP 2 +#define TLV_DS_MAP_HASH_LABEL_RANGE 3 +#define TLV_DS_MAP_HASH_IP_RANGE 4 +#define TLV_DS_MAP_HASH_NO_LABEL 5 +#define TLV_DS_MAP_HASH_ALL_IP 6 +#define TLV_DS_MAP_HASH_NO_MATCH 7 +#define TLV_DS_MAP_HASH_BITMASK_IP 8 +#define TLV_DS_MAP_HASH_BITMASK_LABEL 9 + +static const value_string mpls_echo_tlv_ds_map_hash_type[] = { + {TLV_DS_MAP_HASH_NO_MP, "no multipath"}, + {TLV_DS_MAP_HASH_LABEL, "label"}, + {TLV_DS_MAP_HASH_IP, "IP address"}, + {TLV_DS_MAP_HASH_LABEL_RANGE, "label range"}, + {TLV_DS_MAP_HASH_IP_RANGE, "IP address range"}, + {TLV_DS_MAP_HASH_NO_LABEL, "no more labels"}, + {TLV_DS_MAP_HASH_ALL_IP, "All IP addresses"}, + {TLV_DS_MAP_HASH_NO_MATCH, "no match"}, + {TLV_DS_MAP_HASH_BITMASK_IP, "Bit-masked IPv4 address set"}, + {TLV_DS_MAP_HASH_BITMASK_LABEL, "Bit-masked label set"}, + {0, NULL} +}; + +static const value_string mpls_echo_tlv_ds_map_mp_proto[] = { + {0, "Unknown"}, + {1, "Static"}, + {2, "BGP"}, + {3, "LDP"}, + {4, "RSVP-TE"}, + {5, "Reserved"}, + {0, NULL} +}; + /* * Dissector for FEC sub-TLVs */ @@ -181,12 +309,15 @@ static void dissect_mpls_echo_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem) { proto_tree *ti = NULL, *tlv_fec_tree = NULL; - guint16 index = 1, type; - int length; + guint16 index = 1, nil_index = 1, type, saved_type; + int length, nil_length, pad; + guint32 label; + guint8 exp, bos, ttl; if (tree){ while (rem >= 4){ /* Type, Length */ type = tvb_get_ntohs(tvb, offset); + saved_type = type; /* Check for Vendor Private sub-TLVs */ if(type >= TLV_FEC_VENDOR_PRIVATE_START) /* && <= TLV_FEC_VENDOR_PRIVATE_END always true */ type = TLV_FEC_VENDOR_PRIVATE_START; @@ -199,11 +330,20 @@ dissect_mpls_echo_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem if(tlv_fec_tree == NULL) return; /* FEC sub-TLV Type and Length */ - proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_type, tvb, offset, - 2, FALSE); + proto_tree_add_uint_format(tlv_fec_tree, hf_mpls_echo_tlv_fec_type, tvb, + offset, 2, saved_type, "Type: %s (%u)", + val_to_str(type, mpls_echo_tlv_fec_names, "Unknown sub-TLV type"), saved_type); + proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_len, tvb, offset + 2, 2, FALSE); + if (length + 4 > rem){ + proto_tree_add_text(tlv_fec_tree, tvb, offset, rem, + "Error processing FEC sub-TLV: length is %u and reminder is %u", + length, rem - 4); + return; + } + /* FEC sub-TLV Value */ switch (type) { case TLV_FEC_STACK_LDP_IPv4: @@ -310,15 +450,78 @@ dissect_mpls_echo_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem offset + 8, length - 4, FALSE); } break; + case TLV_FEC_STACK_BGP_LAB_v4: + proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_bgp_nh, + tvb, offset + 4, 4, FALSE); + proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_bgp_ipv4, + tvb, offset + 8, 4, FALSE); + proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_bgp_len, + tvb, offset + 12, 1, FALSE); + if (length == 12) + proto_tree_add_text(tlv_fec_tree, tvb, offset + 13, 3, "Padding"); + break; + case TLV_FEC_STACK_GEN_IPv4: + proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_gen_ipv4, + tvb, offset + 4, 4, FALSE); + proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_gen_ipv4_mask, + tvb, offset + 8, 1, FALSE); + if (length == 8) + proto_tree_add_text(tlv_fec_tree, tvb, offset + 9, 3, "Padding"); + break; + case TLV_FEC_STACK_GEN_IPv6: + proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_gen_ipv6, + tvb, offset + 4, 16, FALSE); + proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_gen_ipv6_mask, + tvb, offset + 20, 1, FALSE); + if (length == 20) + proto_tree_add_text(tlv_fec_tree, tvb, offset + 21, 3, "Padding"); + break; + case TLV_FEC_STACK_NIL: + nil_length = length; + while (nil_length >= 4){ + decode_mpls_label(tvb, offset + 4, &label, &exp, &bos, &ttl); + if (label <= LABEL_MAX_RESERVED){ + proto_tree_add_uint_format(tlv_fec_tree, hf_mpls_echo_tlv_fec_nil_label, + tvb, offset + 4, 3, label, "Label %u: %u (%s)", nil_index, label, + val_to_str(label, special_labels, "Reserved - Unknown")); + } else { + proto_tree_add_uint_format(tlv_fec_tree, hf_mpls_echo_tlv_fec_nil_label, + tvb, offset + 4, 3, label, "Label %u: %u", nil_index, label); + } + nil_length -= 4; + offset += 4; + nil_index++; + } + break; + case TLV_FEC_STACK_RES: case TLV_FEC_STACK_VPN_IPv4: case TLV_FEC_STACK_VPN_IPv6: case TLV_FEC_STACK_L2_VPN: default: - proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_value, tvb, offset + 4, - length, FALSE); + if(length) + proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_value, + tvb, offset + 4, length, FALSE); break; } + + /* + * Check for padding based on sub-TLV length alignment; + * FEC sub-TLVs is zero-padded to align to four-octet boundary. + */ + if (length % 4){ + pad = 4 - (length % 4); + if (length + 4 + pad > rem){ + proto_tree_add_text(tlv_fec_tree, tvb, offset, rem, + "Error processing FEC sub-TLV: padded length is %u and reminder is %u", + length + pad, rem - 4); + return; + } else { + proto_tree_add_text(tlv_fec_tree, tvb, offset + 4 + length, pad, "Padding"); + } + length += pad; + } + rem -= 4 + length; offset += 4 + length; index++; @@ -327,12 +530,256 @@ dissect_mpls_echo_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem } /* + * Dissector for Downstream Mapping TLV + */ +static void +dissect_mpls_echo_tlv_ds_map(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem) +{ + proto_tree *ti = NULL, *tlv_ds_map_tree = NULL; + guint16 mplen, index = 1; + guint32 label; + guint8 exp, bos, proto; + guint8 hash_type, addr_type; + + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_mtu, tvb, + offset, 2, FALSE); + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_addr_type, tvb, + offset + 2, 1, FALSE); + ti = proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_res, tvb, + offset + 3, 1, FALSE); + tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map); + + proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_flag_res, tvb, + offset + 3, 1, FALSE); + proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_flag_i, tvb, + offset + 3, 1, FALSE); + proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_flag_n, tvb, + offset + 3, 1, FALSE); + + addr_type = tvb_get_guint8(tvb, offset + 2); + switch(addr_type){ + case TLV_DS_MAP_ADDR_IPv4: + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_ds_ip, tvb, + offset + 4, 4, FALSE); + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_int_ip, tvb, + offset + 8, 4, FALSE); + break; + case TLV_DS_MAP_ADDR_UNNUM_IPv4: + case TLV_DS_MAP_ADDR_UNNUM_IPv6: + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_ds_ip, tvb, + offset + 4, 4, FALSE); + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_if_index, tvb, + offset + 8, 4, FALSE); + break; + case TLV_DS_MAP_ADDR_IPv6: + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_ds_ipv6, tvb, + offset + 4, 16, FALSE); + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_int_ipv6, tvb, + offset + 20, 16, FALSE); + rem -= 24; + offset += 24; + break; + default: + proto_tree_add_text(tree, tvb, offset + 4, 8, + "Error processing TLV: Unknown Address Type of %u", + addr_type); + break; + } + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_hash_type, tvb, + offset + 12, 1, FALSE); + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_depth, tvb, + offset + 13, 1, FALSE); + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_muti_len, tvb, + offset + 14, 2, FALSE); + + /* Get the Multipath Length and Hash Type */ + mplen = tvb_get_ntohs(tvb, offset + 14); + hash_type = tvb_get_guint8(tvb, offset + 12); + + rem -= 16; + offset += 16; + if (rem < mplen){ + proto_tree_add_text(tree, tvb, offset, rem, + "Error processing TLV: Multi Path length is %d and reminder is %u", + mplen, rem); + return; + } + rem -= mplen; + if(mplen){ + switch(hash_type){ + case TLV_DS_MAP_HASH_IP: + if(mplen != 4){ + proto_tree_add_text(tree, tvb, offset, mplen, + "Multi Path length is %u and should be 4", mplen); + break; + } + ti = proto_tree_add_text(tree, tvb, offset, 4, + "Multipath Information"); + tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map); + proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_ip, tvb, + offset, 4, FALSE); + break; + case TLV_DS_MAP_HASH_IP_RANGE: + if(mplen != 8){ + proto_tree_add_text(tree, tvb, offset, mplen, + "Multi Path length is %u and should be 8", mplen); + break; + } + ti = proto_tree_add_text(tree, tvb, offset, 8, + "Multipath Information"); + tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map); + proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_ip_low, tvb, + offset, 4, FALSE); + proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_ip_high, tvb, + offset + 4, 4, FALSE); + break; + case TLV_DS_MAP_HASH_NO_MP: + case TLV_DS_MAP_HASH_NO_LABEL: + case TLV_DS_MAP_HASH_ALL_IP: + case TLV_DS_MAP_HASH_NO_MATCH: + proto_tree_add_text(tree, tvb, offset, mplen, + "No Multipath Information"); + break; + case TLV_DS_MAP_HASH_BITMASK_IP: + if(mplen < 4){ + proto_tree_add_text(tree, tvb, offset, mplen, + "Multi Path length is %u and should be >= 4", mplen); + break; + } + ti = proto_tree_add_text(tree, tvb, offset, mplen, + "Multipath Information"); + tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map); + proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_ip, tvb, + offset, 4, FALSE); + if(mplen > 4) + proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_mask, tvb, + offset + 4, mplen - 4, FALSE); + break; + default: + proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_mp_value, tvb, + offset, mplen, FALSE); + break; + } + } + + offset += mplen; + + while (rem >= 4){ + decode_mpls_label(tvb, offset, &label, &exp, &bos, &proto); + ti = proto_tree_add_text(tree, tvb, offset, 4, "Downstream Label Element %u", + index); + tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map); + proto_item_append_text(ti, ", Label: %u", label); + if (label <= LABEL_MAX_RESERVED){ + proto_tree_add_uint_format(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_label, + tvb, offset, 3, label, "Downstream Label: %u (%s)", label, + val_to_str(label, special_labels, "Reserved - Unknown")); + proto_item_append_text(ti, " (%s)", val_to_str(label, special_labels, + "Reserved - Unknown")); + } else { + proto_tree_add_uint_format(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_label, + tvb, offset, 3, label, "Downstream Label: %u", label); + } + proto_item_append_text(ti, ", Exp: %u, BOS: %u", exp, bos); + proto_tree_add_uint_format(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_exp, + tvb, offset + 2, 1, exp, "Downstream Exp: %u", exp); + proto_tree_add_uint_format(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_bos, + tvb, offset + 2, 1, bos, "Downstream BOS: %u", bos); + proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_proto, + tvb, offset + 3, 1, FALSE); + proto_item_append_text(ti, ", Protocol: %u (%s)", proto, val_to_str(proto, + mpls_echo_tlv_ds_map_mp_proto, "Unknown")); + rem -= 4; + offset += 4; + index++; + } +} + +/* + * Dissector for IPv4 and IPv6 Interface and Label Stack Object + */ +static void +dissect_mpls_echo_tlv_ilso(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem, gboolean is_ipv6) +{ + proto_tree *ti = NULL, *tlv_ilso = NULL; + guint16 index = 1; + guint32 label; + guint8 exp, bos, ttl; + + if (is_ipv6){ + proto_tree_add_item(tree, hf_mpls_echo_tlv_ilso_ipv6_addr, tvb, + offset, 16, FALSE); + proto_tree_add_item(tree, hf_mpls_echo_tlv_ilso_ipv6_int_addr, tvb, + offset + 16, 16, FALSE); + + offset += 32; + rem -= 32; + } else { + proto_tree_add_item(tree, hf_mpls_echo_tlv_ilso_ipv4_addr, tvb, + offset, 4, FALSE); + proto_tree_add_item(tree, hf_mpls_echo_tlv_ilso_ipv4_int_addr, tvb, + offset + 4, 4, FALSE); + + offset += 8; + rem -= 8; + } + + + while (rem >= 4){ + decode_mpls_label(tvb, offset, &label, &exp, &bos, &ttl); + ti = proto_tree_add_text(tree, tvb, offset, 4, "Label Stack Element %u", + index); + tlv_ilso = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ilso); + proto_item_append_text(ti, ", Label: %u", label); + if (label <= LABEL_MAX_RESERVED){ + proto_tree_add_uint_format(tlv_ilso, hf_mpls_echo_tlv_ilso_label, + tvb, offset, 3, label, "Label: %u (%s)", label, + val_to_str(label, special_labels, "Reserved - Unknown")); + proto_item_append_text(ti, " (%s)", val_to_str(label, special_labels, + "Reserved - Unknown")); + } else { + proto_tree_add_uint_format(tlv_ilso, hf_mpls_echo_tlv_ilso_label, + tvb, offset, 3, label, "Label: %u", label); + } + proto_item_append_text(ti, ", Exp: %u, BOS: %u, TTL: %u", + exp, bos, ttl); + proto_tree_add_uint_format(tlv_ilso, hf_mpls_echo_tlv_ilso_exp, + tvb, offset + 2, 1, exp, "Exp: %u", exp); + proto_tree_add_uint_format(tlv_ilso, hf_mpls_echo_tlv_ilso_bos, + tvb, offset + 2, 1, bos, "BOS: %u", bos); + proto_tree_add_item(tlv_ilso, hf_mpls_echo_tlv_ilso_ttl, + tvb, offset + 3, 1, FALSE); + rem -= 4; + offset += 4; + index++; + } +} + +static int +dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem, gboolean in_errored); + +/* + * Dissector for Errored TLVs + */ +static void +dissect_mpls_echo_tlv_errored(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem) +{ + int errored_tlv_length; + + while(rem >= 4){ + errored_tlv_length = dissect_mpls_echo_tlv(tvb, offset, tree, rem, TRUE); + rem -= errored_tlv_length; + offset += errored_tlv_length; + } +} + +/* * Dissector for MPLS Echo TLVs and return bytes consumed */ static int -dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem) +dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem, gboolean in_errored) { - guint16 type; + guint16 type, saved_type; int length; proto_tree *ti = NULL, *mpls_echo_tlv_tree = NULL; @@ -353,18 +800,26 @@ dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem) if (tree) { /* Check for Vendor Private TLVs */ + saved_type = type; if(type >= TLV_VENDOR_PRIVATE_START) /* && <= TLV_VENDOR_PRIVATE_END always true */ type = TLV_VENDOR_PRIVATE_START; - ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s", + ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s%s", + in_errored ? "Errored TLV Type: " : "", val_to_str(type, mpls_echo_tlv_type_names, "Unknown TLV type (0x%04X)")); mpls_echo_tlv_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv); if(mpls_echo_tlv_tree == NULL) return length+4; /* MPLS Echo TLV Type and Length */ - proto_tree_add_uint_format(mpls_echo_tlv_tree, hf_mpls_echo_tlv_type, tvb, - offset, 2, type, "Type: %s (%u)", - val_to_str(type, mpls_echo_tlv_type_names, "Unknown TLV type"), type ); + if (in_errored){ + proto_tree_add_uint_format(mpls_echo_tlv_tree, hf_mpls_echo_tlv_errored_type, tvb, + offset, 2, saved_type, "Errored TLV Type: %s (%u)", + val_to_str(type, mpls_echo_tlv_type_names, "Unknown TLV type"), saved_type); + } else { + proto_tree_add_uint_format(mpls_echo_tlv_tree, hf_mpls_echo_tlv_type, tvb, + offset, 2, saved_type, "Type: %s (%u)", + val_to_str(type, mpls_echo_tlv_type_names, "Unknown TLV type"), saved_type); + } proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_len, tvb, offset + 2, 2, FALSE); /* MPLS Echo TLV Value */ @@ -378,13 +833,52 @@ dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem) case TLV_PAD: proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_padaction, tvb, offset + 4, 1, FALSE); - proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_padding, tvb, - offset + 5, length - 1, FALSE); + if (length > 1) + proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_padding, tvb, + offset + 5, length - 1, FALSE); break; case TLV_VENDOR_CODE: proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_vendor, tvb, offset + 4, 4, FALSE); break; + case TLV_ILSO_IPv4: + if(length < 8) { + proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length, + "Error processing TLV: length is %d, should be >= 8", + length); + break; + } + dissect_mpls_echo_tlv_ilso(tvb, offset + 4, mpls_echo_tlv_tree, length, FALSE); + break; + case TLV_ILSO_IPv6: + if(length < 32) { + proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length, + "Error processing TLV: length is %d, should be >= 32", + length); + break; + } + dissect_mpls_echo_tlv_ilso(tvb, offset + 4, mpls_echo_tlv_tree, length, TRUE); + break; + case TLV_RTO_IPv4: + if(length != 4) { + proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length, + "Error processing TLV: length is %d, should be 4", + length); + break; + } + proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_rto_ipv4, + tvb, offset + 4, 4, FALSE); + break; + case TLV_RTO_IPv6: + if(length != 16) { + proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length, + "Error processing TLV: length is %d, should be 16", + length); + break; + } + proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_rto_ipv6, + tvb, offset + 4, 16, FALSE); + break; case TLV_VENDOR_PRIVATE_START: if (length < 4) { /* SMI Enterprise code */ proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length, @@ -398,6 +892,33 @@ dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem) } break; case TLV_DOWNSTREAM_MAPPING: + if(length < 16) { + proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length, + "Error processing TLV: length is %d, should be >= 16", + length); + break; + } + dissect_mpls_echo_tlv_ds_map(tvb, offset + 4, mpls_echo_tlv_tree, length); + break; + case TLV_ERRORED_TLV: + if (in_errored) + proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_value, tvb, + offset + 4, length, FALSE); + else + dissect_mpls_echo_tlv_errored(tvb, offset + 4, mpls_echo_tlv_tree, length); + break; + case TLV_REPLY_TOS: + if(length != 4) { + proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length, + "Error processing TLV: length is %d, should be 4", + length); + break; + } + proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_reply_tos, tvb, + offset + 4, 1, FALSE); + proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_reply_tos_mbz, tvb, + offset + 5, 3, FALSE); + break; case TLV_ERROR_CODE: default: proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_value, tvb, @@ -408,6 +929,9 @@ dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem) return length + 4; /* Length of the Value field + Type Length */ } +#define MSGTYPE_MPLS_ECHO(msgtype) ((msgtype == 1) || (msgtype == 2)) +#define MSGTYPE_DATAPLANE(msgtype) ((msgtype == 3) || (msgtype == 4)) + /* * Dissector for MPLS Echo (LSP PING) packets */ @@ -416,14 +940,14 @@ dissect_mpls_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0, rem = 0, len; proto_item *ti = NULL; - proto_tree *mpls_echo_tree = NULL; + proto_tree *mpls_echo_tree = NULL, *mpls_echo_gflags = NULL; guint8 msgtype; const guint8 *ts_sent, *ts_rec; gchar buff[NTP_TS_SIZE]; /* If version != 1 we assume it's not an mpls ping packet */ - if (!tvb_bytes_exist(tvb, 0, 2)) { - return; /* Not enough information to tell. */ + if (!tvb_bytes_exist(tvb, 0, 5)) { + return; /* Not enough information to tell version and message type. */ } if (tvb_get_ntohs(tvb, 0) != 1) { return; /* Not version 1. */ @@ -434,18 +958,24 @@ dissect_mpls_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) rem = tvb_reported_length_remaining(tvb, offset); - if( rem < 32 ) { /* The fixed part of the packet is 32 Bytes */ + /* Get the message type and fill in the Column info */ + msgtype = tvb_get_guint8(tvb, offset + 4); + + /* The minimum fixed part of the packet is 16 Bytes or 32 Bytes depending on Msg Type */ + if( ((!MSGTYPE_MPLS_ECHO(msgtype)) && (rem < 16)) || + ((MSGTYPE_MPLS_ECHO(msgtype)) && (rem < 32)) ) { if( check_col(pinfo->cinfo, COL_INFO) ) col_set_str(pinfo->cinfo, COL_INFO, "Malformed Message"); - if(tree) - proto_tree_add_text(tree, tvb, offset, rem, - "Error processing Message: length is %d, should be >= 32", - rem); + if(tree) { + ti = proto_tree_add_item(tree, proto_mpls_echo, tvb, 0, -1, FALSE); + mpls_echo_tree = proto_item_add_subtree(ti, ett_mpls_echo); + proto_tree_add_text(mpls_echo_tree, tvb, offset, rem, + "Error processing Message: length is %d, should be >= %u", + rem, (MSGTYPE_MPLS_ECHO(msgtype)) ? 32 : 16); + } return; } - /* Get the message type and fill in the Column info */ - msgtype = tvb_get_guint8(tvb, offset + 4); if (check_col(pinfo->cinfo, COL_INFO)) col_set_str(pinfo->cinfo, COL_INFO, val_to_str(msgtype, mpls_echo_msgtype, "Unknown Message Type (0x%02X)")); @@ -459,8 +989,20 @@ dissect_mpls_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_tree_add_item(mpls_echo_tree, hf_mpls_echo_version, tvb, offset, 2, FALSE); - proto_tree_add_item(mpls_echo_tree, - hf_mpls_echo_mbz, tvb, offset + 2, 2, FALSE); + + if(MSGTYPE_MPLS_ECHO(msgtype)){ + ti = proto_tree_add_item(mpls_echo_tree, + hf_mpls_echo_gflags, tvb, offset + 2, 2, FALSE); + mpls_echo_gflags = proto_item_add_subtree(ti, ett_mpls_echo_gflags); + proto_tree_add_item(mpls_echo_gflags, + hf_mpls_echo_flag_sbz, tvb, offset + 2, 2, FALSE); + proto_tree_add_item(mpls_echo_gflags, + hf_mpls_echo_flag_v, tvb, offset + 2, 2, FALSE); + } else { + proto_tree_add_item(mpls_echo_tree, + hf_mpls_echo_mbz, tvb, offset + 2, 2, FALSE); + } + proto_tree_add_item(mpls_echo_tree, hf_mpls_echo_msgtype, tvb, offset + 4, 1, FALSE); proto_tree_add_item(mpls_echo_tree, @@ -474,22 +1016,29 @@ dissect_mpls_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_tree_add_item(mpls_echo_tree, hf_mpls_echo_sequence, tvb, offset + 12, 4, FALSE); - /* Using NTP routine to calculate the timestamp */ - ts_sent = tvb_get_ptr(tvb, 16, 8); - proto_tree_add_bytes_format(mpls_echo_tree, hf_mpls_echo_ts_sent, tvb, - offset + 16, 8, ts_sent, "Timestamp Sent: %s", ntp_fmt_ts(ts_sent, buff)); - ts_rec = tvb_get_ptr(tvb, 24, 8); - proto_tree_add_bytes_format(mpls_echo_tree, hf_mpls_echo_ts_rec, tvb, - offset + 24, 8, ts_rec, "Timestamp Received: %s", ntp_fmt_ts(ts_rec, buff)); + if(MSGTYPE_MPLS_ECHO(msgtype)){ + /* Using NTP routine to calculate the timestamp */ + ts_sent = tvb_get_ptr(tvb, 16, 8); + proto_tree_add_bytes_format(mpls_echo_tree, hf_mpls_echo_ts_sent, tvb, + offset + 16, 8, ts_sent, "Timestamp Sent: %s", ntp_fmt_ts(ts_sent, buff)); + ts_rec = tvb_get_ptr(tvb, 24, 8); + proto_tree_add_bytes_format(mpls_echo_tree, hf_mpls_echo_ts_rec, tvb, + offset + 24, 8, ts_rec, "Timestamp Received: %s", ntp_fmt_ts(ts_rec, buff)); + } } - offset += 32; - rem -= 32; + if(MSGTYPE_MPLS_ECHO(msgtype)){ + offset += 32; + rem -= 32; + } else { + offset += 16; + rem -= 16; + } /* Dissect all TLVs */ while(tvb_reported_length_remaining(tvb, offset) > 0 ) { - len = dissect_mpls_echo_tlv(tvb, offset, mpls_echo_tree, rem); + len = dissect_mpls_echo_tlv(tvb, offset, mpls_echo_tree, rem, FALSE); offset += len; rem -= len; } @@ -510,7 +1059,19 @@ proto_register_mpls_echo(void) }, { &hf_mpls_echo_mbz, { "MBZ", "mpls_echo.mbz", - FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO Must Be Zero", HFILL} + FT_UINT16, BASE_HEX, NULL, 0x0, "MPLS ECHO Must be Zero", HFILL} + }, + { &hf_mpls_echo_gflags, + { "Global Flags", "mpls_echo.flags", + FT_UINT16, BASE_HEX, NULL, 0x0, "MPLS ECHO Global Flags", HFILL} + }, + { &hf_mpls_echo_flag_sbz, + { "Reserved", "mpls_echo.flag_sbz", + FT_UINT16, BASE_HEX, NULL, 0xFFFE, "MPLS ECHO Reserved Flags", HFILL} + }, + { &hf_mpls_echo_flag_v, + { "Validate FEC Stack", "mpls_echo.flag_v", + FT_BOOLEAN, 16, NULL, 0x0001, "MPLS ECHO Validate FEC Stack Flag", HFILL} }, { &hf_mpls_echo_msgtype, { "Message Type", "mpls_echo.msg_type", @@ -572,19 +1133,19 @@ proto_register_mpls_echo(void) }, { &hf_mpls_echo_tlv_fec_ldp_ipv4, { "IPv4 Prefix", "mpls_echo.tlv.fec.ldp_ipv4", - FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack IPv4", HFILL} + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack LDP IPv4", HFILL} }, { &hf_mpls_echo_tlv_fec_ldp_ipv4_mask, { "Prefix Length", "mpls_echo.tlv.fec.ldp_ipv4_mask", - FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack IPv4 Prefix Length", HFILL} + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack LDP IPv4 Prefix Length", HFILL} }, { &hf_mpls_echo_tlv_fec_ldp_ipv6, { "IPv6 Prefix", "mpls_echo.tlv.fec.ldp_ipv6", - FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack IPv6", HFILL} + FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack LDP IPv6", HFILL} }, { &hf_mpls_echo_tlv_fec_ldp_ipv6_mask, { "Prefix Length", "mpls_echo.tlv.fec.ldp_ipv6_mask", - FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack IPv6 Prefix Length", HFILL} + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack LDP IPv6 Prefix Length", HFILL} }, { &hf_mpls_echo_tlv_fec_rsvp_ipv4_ipv4_endpoint, { "IPv4 Tunnel endpoint address", "mpls_echo.tlv.fec.rsvp_ipv4_ep", @@ -646,6 +1207,133 @@ proto_register_mpls_echo(void) { "MBZ", "mpls_echo.tlv.fec.l2cid_mbz", FT_UINT16, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV FEC Stack L2CID MBZ", HFILL} }, + { &hf_mpls_echo_tlv_fec_bgp_nh, + { "BGP Next Hop", "mpls_echo.tlv.fec.bgp_nh", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack BGP Next Hop", HFILL} + }, + { &hf_mpls_echo_tlv_fec_bgp_ipv4, + { "IPv4 Prefix", "mpls_echo.tlv.fec.bgp_ipv4", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack BGP IPv4", HFILL} + }, + { &hf_mpls_echo_tlv_fec_bgp_len, + { "Prefix Length", "mpls_echo.tlv.fec.bgp_len", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack BGP Prefix Length", HFILL} + }, + { &hf_mpls_echo_tlv_fec_gen_ipv4, + { "IPv4 Prefix", "mpls_echo.tlv.fec.gen_ipv4", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack Generic IPv4", HFILL} + }, + { &hf_mpls_echo_tlv_fec_gen_ipv4_mask, + { "Prefix Length", "mpls_echo.tlv.fec.gen_ipv4_mask", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack Generic IPv4 Prefix Length", HFILL} + }, + { &hf_mpls_echo_tlv_fec_gen_ipv6, + { "IPv6 Prefix", "mpls_echo.tlv.fec.gen_ipv6", + FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack Generic IPv6", HFILL} + }, + { &hf_mpls_echo_tlv_fec_gen_ipv6_mask, + { "Prefix Length", "mpls_echo.tlv.fec.gen_ipv6_mask", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack Generic IPv6 Prefix Length", HFILL} + }, + { &hf_mpls_echo_tlv_fec_nil_label, + { "Label", "mpls_echo.tlv.fec.nil_label", + FT_UINT24, BASE_DEC, VALS(special_labels), 0x0, "MPLS ECHO TLV FEC Stack NIL Label", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mtu, + { "MTU", "mpls_echo.tlv.ds_map.mtu", + FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map MTU", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_addr_type, + { "Address Type", "mpls_echo.tlv.ds_map.addr_type", + FT_UINT8, BASE_DEC, VALS(mpls_echo_tlv_ds_map_addr_type), 0x0, + "MPLS ECHO TLV Downstream Map Address Type", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_res, + { "DS Flags", "mpls_echo.tlv.ds_map.res", + FT_UINT8, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV Downstream Map DS Flags", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_flag_res, + { "MBZ", "mpls_echo.tlv.ds_map.flag_res", + FT_UINT8, BASE_HEX, NULL, 0xFC, "MPLS ECHO TLV Downstream Map Reserved Flags", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_flag_i, + { "Interface and Label Stack Request", "mpls_echo.tlv.ds_map.flag_i", + FT_BOOLEAN, 8, NULL, 0x02, "MPLS ECHO TLV Downstream Map I-Flag", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_flag_n, + { "Treat as Non-IP Packet", "mpls_echo.tlv.ds_map.flag_n", + FT_BOOLEAN, 8, NULL, 0x01, "MPLS ECHO TLV Downstream Map N-Flag", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_ds_ip, + { "Downstream IP Address", "mpls_echo.tlv.ds_map.ds_ip", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map IP Address", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_int_ip, + { "Downstream Interface Address", "mpls_echo.tlv.ds_map.int_ip", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Interface Address", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_if_index, + { "Upstream Interface Index", "mpls_echo.tlv.ds_map.if_index", + FT_UINT32, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Interface Index", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_ds_ipv6, + { "Downstream IPv6 Address", "mpls_echo.tlv.ds_map.ds_ipv6", + FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map IPv6 Address", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_int_ipv6, + { "Downstream Interface IPv6 Address", "mpls_echo.tlv.ds_map.int_ipv6", + FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Interface IPv6 Address", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_hash_type, + { "Multipath Type", "mpls_echo.tlv.ds_map.hash_type", + FT_UINT8, BASE_DEC, VALS(mpls_echo_tlv_ds_map_hash_type), 0x0, + "MPLS ECHO TLV Downstream Map Multipath Type", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_depth, + { "Depth Limit", "mpls_echo.tlv.ds_map.depth", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Depth Limit", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_muti_len, + { "Multipath Length", "mpls_echo.tlv.ds_map.multi_len", + FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath Length", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mp_ip, + { "IP Address", "mpls_echo.tlv.ds_map_mp.ip", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath IP Address", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mp_mask, + { "Mask", "mpls_echo.tlv.ds_map_mp.mask", + FT_BYTES, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath Mask", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mp_ip_low, + { "IP Address Low", "mpls_echo.tlv.ds_map_mp.ip_low", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath Low IP Address", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mp_ip_high, + { "IP Address High", "mpls_echo.tlv.ds_map_mp.ip_high", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath High IP Address", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mp_value, + { "Multipath Value", "mpls_echo.tlv.ds_map_mp.value", + FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Multipath Value", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mp_label, + { "Downstream Label", "mpls_echo.tlv.ds_map.mp_label", + FT_UINT24, BASE_DEC, VALS(special_labels), 0x0, "MPLS ECHO TLV Downstream Map Downstream Label", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mp_exp, + { "Downstream Experimental", "mpls_echo.tlv.ds_map.mp_exp", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Downstream Experimental", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mp_bos, + { "Downstream BOS", "mpls_echo.tlv.ds_map.mp_bos", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Downstream BOS", HFILL} + }, + { &hf_mpls_echo_tlv_ds_map_mp_proto, + { "Downstream Protocol", "mpls_echo.tlv.ds_map.mp_proto", + FT_UINT8, BASE_DEC, VALS(mpls_echo_tlv_ds_map_mp_proto), 0x0, + "MPLS ECHO TLV Downstream Map Downstream Protocol", HFILL} + }, { &hf_mpls_echo_tlv_padaction, { "Pad Action", "mpls_echo.tlv.pad_action", FT_UINT8, BASE_DEC, VALS(mpls_echo_tlv_pad), 0x0, "MPLS ECHO Pad TLV Action", HFILL} @@ -657,13 +1345,69 @@ proto_register_mpls_echo(void) { &hf_mpls_echo_tlv_vendor, { "Vendor Id", "mpls_echo.tlv.vendor_id", FT_UINT32, BASE_DEC, VALS(sminmpec_values), 0x0, "MPLS ECHO Vendor Id", HFILL} - } + }, + { &hf_mpls_echo_tlv_ilso_ipv4_addr, + { "Downstream IPv4 Address", "mpls_echo.tlv.ilso_ipv4.addr", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Address", HFILL} + }, + { &hf_mpls_echo_tlv_ilso_ipv4_int_addr, + { "Downstream Interface Address", "mpls_echo.tlv.ilso_ipv4.int_addr", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Address", HFILL} + }, + { &hf_mpls_echo_tlv_ilso_ipv6_addr, + { "Downstream IPv6 Address", "mpls_echo.tlv.ilso_ipv6.addr", + FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Address", HFILL} + }, + { &hf_mpls_echo_tlv_ilso_ipv6_int_addr, + { "Downstream Interface Address", "mpls_echo.tlv.ilso_ipv6.int_addr", + FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Address", HFILL} + }, + { &hf_mpls_echo_tlv_ilso_label, + { "Label", "mpls_echo.tlv.ilso_ipv4.label", + FT_UINT24, BASE_DEC, VALS(special_labels), 0x0, "MPLS ECHO TLV Interface and Label Stack Label", HFILL} + }, + { &hf_mpls_echo_tlv_ilso_exp, + { "Exp", "mpls_echo.tlv.ilso_ipv4.exp", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Exp", HFILL} + }, + { &hf_mpls_echo_tlv_ilso_bos, + { "BOS", "mpls_echo.tlv.ilso_ipv4.bos", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack BOS", HFILL} + }, + { &hf_mpls_echo_tlv_ilso_ttl, + { "TTL", "mpls_echo.tlv.ilso_ipv4.ttl", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack TTL", HFILL} + }, + { &hf_mpls_echo_tlv_rto_ipv4, + { "Reply-to IPv4 Address", "mpls_echo.tlv.rto.ipv4", + FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV IPv4 Reply-To Object", HFILL} + }, + { &hf_mpls_echo_tlv_rto_ipv6, + { "Reply-to IPv6 Address", "mpls_echo.tlv.rto.ipv6", + FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV IPv6 Reply-To Object", HFILL} + }, + { &hf_mpls_echo_tlv_reply_tos, + { "Reply-TOS Byte", "mpls_echo.tlv.reply.tos", + FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Reply-TOS Byte", HFILL} + }, + { &hf_mpls_echo_tlv_reply_tos_mbz, + { "MBZ", "mpls_echo.tlv.reply.tos.mbz", + FT_UINT24, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV Reply-TOS MBZ", HFILL} + }, + { &hf_mpls_echo_tlv_errored_type, + { "Errored TLV Type", "mpls_echo.tlv.errored.type", + FT_UINT16, BASE_DEC, VALS(mpls_echo_tlv_type_names), 0x0, + "MPLS ECHO TLV Errored TLV Type", HFILL} + } }; static gint *ett[] = { &ett_mpls_echo, + &ett_mpls_echo_gflags, &ett_mpls_echo_tlv, &ett_mpls_echo_tlv_fec, + &ett_mpls_echo_tlv_ds_map, + &ett_mpls_echo_tlv_ilso, }; module_t *mpls_echo_module; diff --git a/epan/dissectors/packet-mpls.c b/epan/dissectors/packet-mpls.c index aec3c1997c..abad7c198c 100644 --- a/epan/dissectors/packet-mpls.c +++ b/epan/dissectors/packet-mpls.c @@ -44,27 +44,18 @@ #include "etypes.h" #include <epan/prefs.h> #include "packet-ppp.h" +#include "packet-mpls.h" static gint proto_mpls = -1; static gint ett_mpls = -1; static gint ett_mpls_control = -1; -/* Special labels in MPLS */ -enum { - IP4_EXPLICIT_NULL = 0, - ROUTER_ALERT, - IP6_EXPLICIT_NULL, - IMPLICIT_NULL, - - MAX_RESERVED = 15 -}; - -static const value_string special_labels[] = { - {IP4_EXPLICIT_NULL, "IPv4 Explicit-Null"}, - {ROUTER_ALERT, "Router Alert"}, - {IP6_EXPLICIT_NULL, "IPv6 Explicit-Null"}, - {IMPLICIT_NULL, "Implicit-Null"}, +const value_string special_labels[] = { + {LABEL_IP4_EXPLICIT_NULL, "IPv4 Explicit-Null"}, + {LABEL_ROUTER_ALERT, "Router Alert"}, + {LABEL_IP6_EXPLICIT_NULL, "IPv6 Explicit-Null"}, + {LABEL_IMPLICIT_NULL, "Implicit-Null"}, {0, NULL } }; @@ -215,7 +206,7 @@ dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) mpls_tree = proto_item_add_subtree(ti, ett_mpls); proto_item_append_text(ti, ", Label: %u", label); - if (label <= MAX_RESERVED){ + if (label <= LABEL_MAX_RESERVED){ proto_tree_add_uint_format(mpls_tree, mpls_filter[MPLSF_LABEL], tvb, offset, 3, label, "MPLS Label: %u (%s)", label, val_to_str(label, special_labels, diff --git a/epan/dissectors/packet-mpls.h b/epan/dissectors/packet-mpls.h new file mode 100644 index 0000000000..48b8b36e31 --- /dev/null +++ b/epan/dissectors/packet-mpls.h @@ -0,0 +1,45 @@ +/* packet-mpls.h + * Declarations of exported routines from MPLS dissector + * Author: Carlos Pignataro <cpignata@cisco.com> + * Copyright 2005, cisco Systems, Inc. + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PACKET_MPLS_H_ +#define __PACKET_MPLS_H__ + +/* Special labels in MPLS */ +enum { + LABEL_IP4_EXPLICIT_NULL = 0, + LABEL_ROUTER_ALERT, + LABEL_IP6_EXPLICIT_NULL, + LABEL_IMPLICIT_NULL, + + LABEL_MAX_RESERVED = 15 +}; + +extern const value_string special_labels[]; +extern void decode_mpls_label(tvbuff_t *tvb, int offset, + guint32 *label, guint8 *exp, + guint8 *bos, guint8 *ttl); + +#endif |