change the signature that asn2wrs generates for functions to marm all parameters...
[obnox/wireshark/wip.git] / epan / dissectors / packet-mpls-echo.c
1 /* packet-mpls-echo.c
2  * Routines for Multiprotocol Label Switching Echo dissection
3  * Copyright 2004, Carlos Pignataro <cpignata@cisco.com>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <glib.h>
34 #include <epan/packet.h>
35 #include <epan/prefs.h>
36 #include <epan/sminmpec.h>
37 #include "packet-ntp.h"
38 #include "packet-ldp.h"
39 #include "packet-mpls.h"
40
41 #define UDP_PORT_MPLS_ECHO 3503
42
43 void proto_reg_handoff_mpls_echo(void);
44
45 static int proto_mpls_echo = -1;
46 static int hf_mpls_echo_version = -1;
47 static int hf_mpls_echo_mbz = -1;
48 static int hf_mpls_echo_gflags = -1;
49 static int hf_mpls_echo_flag_sbz = -1;
50 static int hf_mpls_echo_flag_v = -1;
51 static int hf_mpls_echo_msgtype = -1;
52 static int hf_mpls_echo_replymode = -1;
53 static int hf_mpls_echo_returncode = -1;
54 static int hf_mpls_echo_returnsubcode = -1;
55 static int hf_mpls_echo_handle = -1;
56 static int hf_mpls_echo_sequence = -1;
57 static int hf_mpls_echo_ts_sent = -1;
58 static int hf_mpls_echo_ts_rec = -1;
59 static int hf_mpls_echo_tlv_type = -1;
60 static int hf_mpls_echo_tlv_len = -1;
61 static int hf_mpls_echo_tlv_value = -1;
62 static int hf_mpls_echo_tlv_fec_type = -1;
63 static int hf_mpls_echo_tlv_fec_len = -1;
64 static int hf_mpls_echo_tlv_fec_value = -1;
65 static int hf_mpls_echo_tlv_fec_ldp_ipv4 = -1;
66 static int hf_mpls_echo_tlv_fec_ldp_ipv4_mask = -1;
67 static int hf_mpls_echo_tlv_fec_ldp_ipv6 = -1;
68 static int hf_mpls_echo_tlv_fec_ldp_ipv6_mask = -1;
69 static int hf_mpls_echo_tlv_fec_rsvp_ipv4_ipv4_endpoint = -1;
70 static int hf_mpls_echo_tlv_fec_rsvp_ipv6_ipv6_endpoint = -1;
71 static int hf_mpls_echo_tlv_fec_rsvp_ip_mbz1 = -1;
72 static int hf_mpls_echo_tlv_fec_rsvp_ip_tunnel_id = -1;
73 static int hf_mpls_echo_tlv_fec_rsvp_ipv4_ext_tunnel_id = -1;
74 static int hf_mpls_echo_tlv_fec_rsvp_ipv4_ipv4_sender = -1;
75 static int hf_mpls_echo_tlv_fec_rsvp_ipv6_ext_tunnel_id = -1;
76 static int hf_mpls_echo_tlv_fec_rsvp_ipv6_ipv6_sender = -1;
77 static int hf_mpls_echo_tlv_fec_rsvp_ip_mbz2 = -1;
78 static int hf_mpls_echo_tlv_fec_rsvp_ip_lsp_id = -1;
79 static int hf_mpls_echo_tlv_fec_l2cid_sender = -1;
80 static int hf_mpls_echo_tlv_fec_l2cid_remote = -1;
81 static int hf_mpls_echo_tlv_fec_l2cid_vcid = -1;
82 static int hf_mpls_echo_tlv_fec_l2cid_encap = -1;
83 static int hf_mpls_echo_tlv_fec_l2cid_mbz = -1;
84 static int hf_mpls_echo_tlv_fec_bgp_nh = -1;
85 static int hf_mpls_echo_tlv_fec_bgp_ipv4 = -1;
86 static int hf_mpls_echo_tlv_fec_bgp_len = -1;
87 static int hf_mpls_echo_tlv_fec_gen_ipv4 = -1;
88 static int hf_mpls_echo_tlv_fec_gen_ipv4_mask = -1;
89 static int hf_mpls_echo_tlv_fec_gen_ipv6 = -1;
90 static int hf_mpls_echo_tlv_fec_gen_ipv6_mask = -1;
91 static int hf_mpls_echo_tlv_fec_nil_label = -1;
92 static int hf_mpls_echo_tlv_ds_map_mtu = -1;
93 static int hf_mpls_echo_tlv_ds_map_addr_type = -1;
94 static int hf_mpls_echo_tlv_ds_map_res = -1;
95 static int hf_mpls_echo_tlv_ds_map_flag_res = -1;
96 static int hf_mpls_echo_tlv_ds_map_flag_i = -1;
97 static int hf_mpls_echo_tlv_ds_map_flag_n = -1;
98 static int hf_mpls_echo_tlv_ds_map_ds_ip = -1;
99 static int hf_mpls_echo_tlv_ds_map_int_ip = -1;
100 static int hf_mpls_echo_tlv_ds_map_if_index = -1;
101 static int hf_mpls_echo_tlv_ds_map_ds_ipv6 = -1;
102 static int hf_mpls_echo_tlv_ds_map_int_ipv6 = -1;
103 static int hf_mpls_echo_tlv_ds_map_hash_type = -1;
104 static int hf_mpls_echo_tlv_ds_map_depth = -1;
105 static int hf_mpls_echo_tlv_ds_map_muti_len = -1;
106 static int hf_mpls_echo_tlv_ds_map_mp_ip = -1;
107 static int hf_mpls_echo_tlv_ds_map_mp_mask = -1;
108 static int hf_mpls_echo_tlv_ds_map_mp_ip_low = -1;
109 static int hf_mpls_echo_tlv_ds_map_mp_ip_high = -1;
110 static int hf_mpls_echo_tlv_ds_map_mp_value = -1;
111 static int hf_mpls_echo_tlv_ds_map_mp_label = -1;
112 static int hf_mpls_echo_tlv_ds_map_mp_exp = -1;
113 static int hf_mpls_echo_tlv_ds_map_mp_bos = -1;
114 static int hf_mpls_echo_tlv_ds_map_mp_proto = -1;
115 static int hf_mpls_echo_tlv_padaction = -1;
116 static int hf_mpls_echo_tlv_padding = -1;
117 static int hf_mpls_echo_tlv_vendor = -1;
118 static int hf_mpls_echo_tlv_ilso_ipv4_addr = -1;
119 static int hf_mpls_echo_tlv_ilso_ipv4_int_addr = -1;
120 static int hf_mpls_echo_tlv_ilso_ipv6_addr = -1;
121 static int hf_mpls_echo_tlv_ilso_ipv6_int_addr = -1;
122 static int hf_mpls_echo_tlv_ilso_label = -1;
123 static int hf_mpls_echo_tlv_ilso_exp = -1;
124 static int hf_mpls_echo_tlv_ilso_bos = -1;
125 static int hf_mpls_echo_tlv_ilso_ttl = -1;
126 static int hf_mpls_echo_tlv_rto_ipv4 = -1;
127 static int hf_mpls_echo_tlv_rto_ipv6 = -1;
128 static int hf_mpls_echo_tlv_reply_tos = -1;
129 static int hf_mpls_echo_tlv_reply_tos_mbz = -1;
130 static int hf_mpls_echo_tlv_errored_type = -1;
131
132 static gint ett_mpls_echo = -1;
133 static gint ett_mpls_echo_gflags = -1;
134 static gint ett_mpls_echo_tlv = -1;
135 static gint ett_mpls_echo_tlv_fec = -1;
136 static gint ett_mpls_echo_tlv_ds_map = -1;
137 static gint ett_mpls_echo_tlv_ilso = -1;
138
139 static int mpls_echo_udp_port = 0;
140
141 static guint32 global_mpls_echo_udp_port = UDP_PORT_MPLS_ECHO;
142
143 static const value_string mpls_echo_msgtype[] = {
144   {1, "MPLS Echo Request"},
145   {2, "MPLS Echo Reply"},
146   {3, "MPLS Data Plane Verification Request"},
147   {4, "MPLS Data Plane Verification Reply"},
148   {0, NULL}
149 };
150
151 static const value_string mpls_echo_replymode[] = {
152   {1, "Do not reply"},
153   {2, "Reply via an IPv4/IPv6 UDP packet"},
154   {3, "Reply via an IPv4/IPv6 UDP packet with Router Alert"},
155   {4, "Reply via application level control channel"},
156   {0, NULL}
157 };
158
159 static const value_string mpls_echo_returncode[] = {
160   {0, "No return code"},
161   {1, "Malformed echo request received"},
162   {2, "One or more of the TLVs was not understood"},
163   {3, "Replying router is an egress for the FEC at stack depth RSC"},
164   {4, "Replying router has no mapping for the FEC at stack depth RSC"},
165   {5, "Reserved"},
166   {6, "Reserved"},
167   {7, "Reserved"},
168   {8, "Label switched at stack-depth RSC"},
169   {9, "Label switched but no MPLS forwarding at stack-depth RSC"},
170   {10, "Mapping for this FEC is not the given label at stack depth RSC"},
171   {11, "No label entry at stack-depth RSC"},
172   {12, "Protocol not associated with interface at FEC stack depth RSC"},
173   {13, "Premature termination, label stack shrinking to a single label"},
174   {0, NULL}
175 };
176
177 #define TLV_TARGET_FEC_STACK       0x0001
178 #define TLV_DOWNSTREAM_MAPPING     0x0002
179 #define TLV_PAD                    0x0003
180 #define TLV_ERROR_CODE             0x0004
181 #define TLV_VENDOR_CODE            0x0005
182 #define TLV_TBD                    0x0006
183 #define TLV_ILSO_IPv4              0x0007
184 #define TLV_ILSO_IPv6              0x0008
185 #define TLV_ERRORED_TLV            0x0009
186 #define TLV_REPLY_TOS              0x000A
187 #define TLV_RTO_IPv4               0x000B
188 #define TLV_RTO_IPv6               0x000C
189 #define TLV_VENDOR_PRIVATE_START   0xFC00
190 #define TLV_VENDOR_PRIVATE_END     0xFFFF
191
192 /* MPLS Echo TLV Type names */
193 static const value_string mpls_echo_tlv_type_names[] = {
194   { TLV_TARGET_FEC_STACK,          "Target FEC Stack" },
195   { TLV_DOWNSTREAM_MAPPING,        "Downstream Mapping" },
196   { TLV_PAD,                       "Pad" },
197   { TLV_ERROR_CODE,                "Error Code" },
198   { TLV_VENDOR_CODE,               "Vendor Enterprise Code" },
199   { TLV_TBD,                       "TDB" },
200   { TLV_ILSO_IPv4,                 "IPv4 Interface and Label Stack Object" },
201   { TLV_ILSO_IPv6,                 "IPv6 Interface and Label Stack Object" },
202   { TLV_ERRORED_TLV,               "Errored TLVs" },
203   { TLV_REPLY_TOS,                 "Reply TOS Byte" },
204   { TLV_RTO_IPv4,                  "IPv4 Reply-to Object" },
205   { TLV_RTO_IPv6,                  "IPv6 Reply-to Object" },
206   { TLV_VENDOR_PRIVATE_START,      "Vendor Private" },
207   { 0, NULL}
208 };
209
210 #define TLV_FEC_STACK_LDP_IPv4     1
211 #define TLV_FEC_STACK_LDP_IPv6     2
212 #define TLV_FEC_STACK_RSVP_IPv4    3
213 #define TLV_FEC_STACK_RSVP_IPv6    4
214 #define TLV_FEC_STACK_RES          5
215 #define TLV_FEC_STACK_VPN_IPv4     6
216 #define TLV_FEC_STACK_VPN_IPv6     7
217 #define TLV_FEC_STACK_L2_VPN       8
218 #define TLV_FEC_STACK_L2_CID_OLD   9
219 #define TLV_FEC_STACK_L2_CID_NEW  10
220 #define TLV_FEC_STACK_L2_FEC_129  11
221 #define TLV_FEC_STACK_BGP_LAB_v4  12
222 #define TLV_FEC_STACK_BGP_LAB_v6  13
223 #define TLV_FEC_STACK_GEN_IPv4    14
224 #define TLV_FEC_STACK_GEN_IPv6    15
225 #define TLV_FEC_STACK_NIL         16
226 #define TLV_FEC_VENDOR_PRIVATE_START   0xFC00
227 #define TLV_FEC_VENDOR_PRIVATE_END     0xFFFF
228
229 /* FEC sub-TLV Type names */
230 static const value_string mpls_echo_tlv_fec_names[] = {
231   { TLV_FEC_STACK_LDP_IPv4,    "LDP IPv4 prefix"},
232   { TLV_FEC_STACK_LDP_IPv6,    "LDP IPv6 prefix"},
233   { TLV_FEC_STACK_RSVP_IPv4,   "RSVP IPv4 Session Query"},
234   { TLV_FEC_STACK_RSVP_IPv6,   "RSVP IPv6 Session Query"},
235   { TLV_FEC_STACK_RES,         "Reserved"},
236   { TLV_FEC_STACK_VPN_IPv4,    "VPN IPv4 prefix"},
237   { TLV_FEC_STACK_VPN_IPv6,    "VPN IPv6 prefix"},
238   { TLV_FEC_STACK_L2_VPN,      "L2 VPN endpoint"},
239   { TLV_FEC_STACK_L2_CID_OLD,  "FEC 128 Pseudowire (old)"},
240   { TLV_FEC_STACK_L2_CID_NEW,  "FEC 128 Pseudowire (new)"},
241   { TLV_FEC_STACK_L2_FEC_129,  "FEC 129 Pseudowire"},
242   { TLV_FEC_STACK_BGP_LAB_v4,  "BGP labeled IPv4 prefix"},
243   { TLV_FEC_STACK_BGP_LAB_v6,  "BGP labeled IPv6 prefix"},
244   { TLV_FEC_STACK_GEN_IPv4,    "Generic IPv4 prefix"},
245   { TLV_FEC_STACK_GEN_IPv6,    "Generic IPv6 prefix"},
246   { TLV_FEC_STACK_NIL,         "Nil FEC"},
247   { TLV_FEC_VENDOR_PRIVATE_START, "Vendor Private"},
248   { 0, NULL}
249 };
250
251 static const value_string mpls_echo_tlv_pad[] = {
252   { 1, "Drop Pad TLV from reply" },
253   { 2, "Copy Pad TLV to reply" },
254   { 0, NULL}
255 };
256
257 #define TLV_DS_MAP_ADDR_IPv4            1
258 #define TLV_DS_MAP_ADDR_UNNUM_IPv4      2
259 #define TLV_DS_MAP_ADDR_IPv6            3
260 #define TLV_DS_MAP_ADDR_UNNUM_IPv6      4
261
262 static const value_string mpls_echo_tlv_ds_map_addr_type[] = {
263   {TLV_DS_MAP_ADDR_IPv4,        "IPv4 Numbered"},
264   {TLV_DS_MAP_ADDR_UNNUM_IPv4,  "IPv4 Unnumbered"},
265   {TLV_DS_MAP_ADDR_IPv6,        "IPv6 Numbered"},
266   {TLV_DS_MAP_ADDR_UNNUM_IPv6,  "IPv6 Unnumbered"},
267   {0, NULL}
268 };
269
270 #define TLV_DS_MAP_HASH_NO_MP           0
271 #define TLV_DS_MAP_HASH_LABEL           1
272 #define TLV_DS_MAP_HASH_IP              2
273 #define TLV_DS_MAP_HASH_LABEL_RANGE     3
274 #define TLV_DS_MAP_HASH_IP_RANGE        4
275 #define TLV_DS_MAP_HASH_NO_LABEL        5
276 #define TLV_DS_MAP_HASH_ALL_IP          6
277 #define TLV_DS_MAP_HASH_NO_MATCH        7
278 #define TLV_DS_MAP_HASH_BITMASK_IP      8
279 #define TLV_DS_MAP_HASH_BITMASK_LABEL   9
280
281 static const value_string mpls_echo_tlv_ds_map_hash_type[] = {
282   {TLV_DS_MAP_HASH_NO_MP,               "no multipath"},
283   {TLV_DS_MAP_HASH_LABEL,               "label"},
284   {TLV_DS_MAP_HASH_IP,                  "IP address"},
285   {TLV_DS_MAP_HASH_LABEL_RANGE,         "label range"},
286   {TLV_DS_MAP_HASH_IP_RANGE,            "IP address range"},
287   {TLV_DS_MAP_HASH_NO_LABEL,            "no more labels"},
288   {TLV_DS_MAP_HASH_ALL_IP,              "All IP addresses"},
289   {TLV_DS_MAP_HASH_NO_MATCH,            "no match"},
290   {TLV_DS_MAP_HASH_BITMASK_IP,          "Bit-masked IPv4 address set"},
291   {TLV_DS_MAP_HASH_BITMASK_LABEL,       "Bit-masked label set"},
292   {0, NULL}
293 };
294
295 static const value_string mpls_echo_tlv_ds_map_mp_proto[] = {
296   {0, "Unknown"},
297   {1, "Static"},
298   {2, "BGP"},
299   {3, "LDP"},
300   {4, "RSVP-TE"},
301   {5, "Reserved"},
302   {0, NULL}
303 };
304
305 /*
306  * Dissector for FEC sub-TLVs
307  */
308 static void
309 dissect_mpls_echo_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
310 {
311         proto_tree *ti = NULL, *tlv_fec_tree = NULL;
312         guint16 index = 1, nil_index = 1, type, saved_type;
313         int length, nil_length, pad;
314         guint32 label;
315         guint8  exp, bos, ttl;
316
317         if (tree){
318           while (rem >= 4){ /* Type, Length */
319             type = tvb_get_ntohs(tvb, offset);
320             saved_type = type;
321             /* Check for Vendor Private sub-TLVs */
322             if(type >= TLV_FEC_VENDOR_PRIVATE_START) /* && <= TLV_FEC_VENDOR_PRIVATE_END always true */
323                 type = TLV_FEC_VENDOR_PRIVATE_START;
324
325             length = tvb_get_ntohs(tvb, offset + 2);
326             ti = proto_tree_add_text(tree, tvb, offset, length + 4, "FEC Element %u: %s",
327                      index, val_to_str(type, mpls_echo_tlv_fec_names, 
328                      "Unknown FEC type (0x%04X)"));
329             tlv_fec_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_fec);
330             if(tlv_fec_tree == NULL) return;
331
332             /* FEC sub-TLV Type and Length */
333             proto_tree_add_uint_format(tlv_fec_tree, hf_mpls_echo_tlv_fec_type, tvb,
334                 offset, 2, saved_type, "Type: %s (%u)",
335                 val_to_str(type, mpls_echo_tlv_fec_names, "Unknown sub-TLV type"), saved_type);
336
337             proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_len, tvb, offset + 2,
338                 2, FALSE);
339
340             if (length + 4 > rem){
341                 proto_tree_add_text(tlv_fec_tree, tvb, offset, rem,
342                         "Error processing FEC sub-TLV: length is %u and reminder is %u",
343                         length, rem - 4);
344                 return;
345             }
346
347             /* FEC sub-TLV Value */
348             switch (type) {
349             case TLV_FEC_STACK_LDP_IPv4:
350                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_ldp_ipv4, 
351                     tvb, offset + 4, 4, FALSE);
352                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_ldp_ipv4_mask, 
353                     tvb, offset + 8, 1, FALSE);
354                 if (length == 8)
355                     proto_tree_add_text(tlv_fec_tree, tvb, offset + 9, 3, "Padding");
356                 break;
357             case TLV_FEC_STACK_LDP_IPv6:
358                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_ldp_ipv6,
359                     tvb, offset + 4, 16, FALSE);
360                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_ldp_ipv6_mask,
361                     tvb, offset + 20, 1, FALSE);
362                 if (length == 20)
363                     proto_tree_add_text(tlv_fec_tree, tvb, offset + 21, 3, "Padding");
364                 break;
365             case TLV_FEC_STACK_RSVP_IPv4:
366                 if (length != 20){
367                     proto_tree_add_text(tlv_fec_tree, tvb, offset, rem,
368                         "Error processing sub-TLV: length is %d, should be 20", length);
369                     return;
370                 }
371                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ipv4_ipv4_endpoint,
372                     tvb, offset + 4, 4, FALSE);
373                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ip_mbz1,
374                     tvb, offset + 8, 2, FALSE);
375                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ip_tunnel_id,
376                     tvb, offset + 10, 2, FALSE);
377                 proto_tree_add_text(tlv_fec_tree, tvb, offset + 12, 4,
378                     "Extended Tunnel ID: 0x%08X (%s)", tvb_get_ntohl(tvb, offset + 12),
379                     ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
380                 proto_tree_add_item_hidden(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ipv4_ext_tunnel_id,
381                     tvb, offset + 12, 4, FALSE);
382                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ipv4_ipv4_sender,
383                     tvb, offset + 16, 4, FALSE);
384                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ip_mbz2,
385                     tvb, offset + 20, 2, FALSE);
386                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ip_lsp_id,
387                     tvb, offset + 22, 2, FALSE);
388                 break;
389             case TLV_FEC_STACK_RSVP_IPv6:
390                 if (length != 56){
391                     proto_tree_add_text(tlv_fec_tree, tvb, offset, rem,
392                         "Error processing sub-TLV: length is %d, should be 56", length);
393                     return;
394                 }
395                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ipv6_ipv6_endpoint,
396                     tvb, offset + 4, 16, FALSE);
397                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ip_mbz1,
398                     tvb, offset + 20, 2, FALSE);
399                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ip_tunnel_id,
400                     tvb, offset + 22, 2, FALSE);
401                 proto_tree_add_text(tlv_fec_tree, tvb, offset + 24, 16,
402                     "Extended Tunnel ID: 0x%s (%s)",
403                     tvb_bytes_to_str(tvb, offset + 24, 16),
404                     ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 24, 16)));
405                 proto_tree_add_item_hidden(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ipv6_ext_tunnel_id,
406                     tvb, offset + 24, 16, FALSE);
407                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ipv6_ipv6_sender,
408                     tvb, offset + 40, 16, FALSE);
409                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ip_mbz2,
410                     tvb, offset + 56, 2, FALSE);
411                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_rsvp_ip_lsp_id,
412                     tvb, offset + 58, 2, FALSE);
413                 break;
414             case TLV_FEC_STACK_L2_CID_OLD:
415                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_remote,
416                     tvb, offset + 4, 4, FALSE);
417                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_vcid,
418                     tvb, offset + 8, 4, FALSE);
419                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_encap,
420                     tvb, offset + 12, 2, FALSE);
421                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_mbz,
422                     tvb, offset + 14, 2, FALSE);
423                 break;
424             case TLV_FEC_STACK_L2_CID_NEW:
425                 if (length < 14){
426                     proto_tree_add_text(tlv_fec_tree, tvb, offset, rem,
427                         "Error processing sub-TLV: length is %d, should be 14", length);
428                     return;
429                 }
430                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_sender,
431                     tvb, offset + 4, 4, FALSE);
432                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_remote,
433                     tvb, offset + 8, 4, FALSE);
434                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_vcid,
435                     tvb, offset + 12, 4, FALSE);
436                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_encap,
437                     tvb, offset + 16, 2, FALSE);
438                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_mbz,
439                     tvb, offset + 18, 2, FALSE);
440                 break;
441             case TLV_FEC_VENDOR_PRIVATE_START:
442                 if (length < 4) { /* SMI Enterprise code */
443                         proto_tree_add_text(tlv_fec_tree, tvb, offset + 4, length,
444                                 "Error processing Vendor Private sub-TLV: length is %d, should be >= 4",
445                                 length);
446                 } else {
447                         proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_vendor, tvb,
448                                 offset + 4, 4, FALSE);
449                         proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_value, tvb,
450                                 offset + 8, length - 4, FALSE);
451                 }
452                 break;
453             case TLV_FEC_STACK_BGP_LAB_v4:
454                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_bgp_nh,
455                     tvb, offset + 4, 4, FALSE);
456                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_bgp_ipv4,
457                     tvb, offset + 8, 4, FALSE);
458                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_bgp_len,
459                     tvb, offset + 12, 1, FALSE);
460                 if (length == 12)
461                     proto_tree_add_text(tlv_fec_tree, tvb, offset + 13, 3, "Padding");
462                 break;
463             case TLV_FEC_STACK_GEN_IPv4:
464                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_gen_ipv4,
465                     tvb, offset + 4, 4, FALSE);
466                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_gen_ipv4_mask,
467                     tvb, offset + 8, 1, FALSE);
468                 if (length == 8)
469                     proto_tree_add_text(tlv_fec_tree, tvb, offset + 9, 3, "Padding");
470                 break;
471             case TLV_FEC_STACK_GEN_IPv6:
472                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_gen_ipv6,
473                     tvb, offset + 4, 16, FALSE);
474                 proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_gen_ipv6_mask,
475                     tvb, offset + 20, 1, FALSE);
476                 if (length == 20)
477                     proto_tree_add_text(tlv_fec_tree, tvb, offset + 21, 3, "Padding");
478                 break;
479             case TLV_FEC_STACK_NIL:
480                 nil_length = length;
481                 while (nil_length >= 4){
482                         decode_mpls_label(tvb, offset + 4, &label, &exp, &bos, &ttl);
483                         if (label <= LABEL_MAX_RESERVED){
484                                 proto_tree_add_uint_format(tlv_fec_tree, hf_mpls_echo_tlv_fec_nil_label,
485                                         tvb, offset + 4, 3, label, "Label %u: %u (%s)", nil_index, label,
486                                         val_to_str(label, special_labels, "Reserved - Unknown"));
487                         } else {
488                                 proto_tree_add_uint_format(tlv_fec_tree, hf_mpls_echo_tlv_fec_nil_label,
489                                         tvb, offset + 4, 3, label, "Label %u: %u", nil_index, label);
490                         }
491                         nil_length -= 4;
492                         offset += 4;
493                         nil_index++;
494                 }
495                 break;
496
497             case TLV_FEC_STACK_RES:
498             case TLV_FEC_STACK_VPN_IPv4:
499             case TLV_FEC_STACK_VPN_IPv6:
500             case TLV_FEC_STACK_L2_VPN:
501             default:
502                 if(length)
503                         proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_value,
504                                             tvb, offset + 4, length, FALSE);
505                 break;
506             }
507
508             /*
509              * Check for padding based on sub-TLV length alignment;
510              * FEC sub-TLVs is zero-padded to align to four-octet boundary.
511              */
512             if (length  % 4){
513                 pad = 4 - (length % 4);
514                 if (length + 4 + pad > rem){
515                     proto_tree_add_text(tlv_fec_tree, tvb, offset, rem,
516                         "Error processing FEC sub-TLV: padded length is %u and reminder is %u",
517                         length + pad, rem - 4);
518                     return;
519                 } else {
520                     proto_tree_add_text(tlv_fec_tree, tvb, offset + 4 + length, pad, "Padding");
521                 }
522                 length += pad;
523             }
524
525             rem -= 4 + length;
526             offset += 4 + length;
527             index++;
528           }
529         }
530 }
531
532 /*
533  * Dissector for Downstream Mapping TLV
534  */
535 static void
536 dissect_mpls_echo_tlv_ds_map(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
537 {
538         proto_tree *ti = NULL, *tlv_ds_map_tree = NULL;
539         guint16 mplen, index = 1;
540         guint32 label;
541         guint8  exp, bos, proto;
542         guint8  hash_type, addr_type;
543
544         proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_mtu, tvb,
545                             offset, 2, FALSE);
546         proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_addr_type, tvb,
547                             offset + 2, 1, FALSE);
548         ti = proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_res, tvb,
549                             offset + 3, 1, FALSE);
550         tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map);
551
552         proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_flag_res, tvb,
553                             offset + 3, 1, FALSE);
554         proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_flag_i, tvb,
555                             offset + 3, 1, FALSE);
556         proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_flag_n, tvb,
557                             offset + 3, 1, FALSE);
558
559         addr_type = tvb_get_guint8(tvb, offset + 2);
560         switch(addr_type){
561         case TLV_DS_MAP_ADDR_IPv4:
562                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_ds_ip, tvb,
563                                 offset + 4, 4, FALSE);
564                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_int_ip, tvb,
565                                 offset + 8, 4, FALSE);
566                 break;
567         case TLV_DS_MAP_ADDR_UNNUM_IPv4:
568         case TLV_DS_MAP_ADDR_UNNUM_IPv6:
569                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_ds_ip, tvb,
570                                 offset + 4, 4, FALSE);
571                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_if_index, tvb,
572                                 offset + 8, 4, FALSE);
573                 break;
574         case TLV_DS_MAP_ADDR_IPv6:
575                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_ds_ipv6, tvb,
576                                 offset + 4, 16, FALSE);
577                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_int_ipv6, tvb,
578                                 offset + 20, 16, FALSE);
579                 rem -= 24;
580                 offset += 24;
581                 break;
582         default:
583                 proto_tree_add_text(tree, tvb, offset + 4, 8,
584                         "Error processing TLV: Unknown Address Type of %u",
585                         addr_type);
586                 break;
587         }
588         proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_hash_type, tvb,
589                             offset + 12, 1, FALSE);
590         proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_depth, tvb,
591                             offset + 13, 1, FALSE);
592         proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_muti_len, tvb,
593                             offset + 14, 2, FALSE);
594
595         /* Get the Multipath Length and Hash Type */
596         mplen = tvb_get_ntohs(tvb, offset + 14);
597         hash_type = tvb_get_guint8(tvb, offset + 12);
598
599         rem -= 16;
600         offset += 16;
601         if (rem < mplen){
602                 proto_tree_add_text(tree, tvb, offset, rem,
603                         "Error processing TLV: Multi Path length is %d and reminder is %u",
604                         mplen, rem);
605                 return;
606         }
607         rem -= mplen;
608         if(mplen){
609             switch(hash_type){
610             case TLV_DS_MAP_HASH_IP:
611                 if(mplen != 4){
612                         proto_tree_add_text(tree, tvb, offset, mplen,
613                                 "Multi Path length is %u and should be 4", mplen);
614                         break;
615                 }
616                 ti = proto_tree_add_text(tree, tvb, offset, 4,
617                         "Multipath Information");
618                 tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map);
619                 proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_ip, tvb,
620                         offset, 4, FALSE);
621                 break;
622             case TLV_DS_MAP_HASH_IP_RANGE:
623                 if(mplen != 8){
624                         proto_tree_add_text(tree, tvb, offset, mplen,
625                                 "Multi Path length is %u and should be 8", mplen);
626                         break;
627                 }
628                 ti = proto_tree_add_text(tree, tvb, offset, 8,
629                         "Multipath Information");
630                 tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map);
631                 proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_ip_low, tvb,
632                         offset, 4, FALSE);
633                 proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_ip_high, tvb,
634                         offset + 4, 4, FALSE);
635                 break;
636             case TLV_DS_MAP_HASH_NO_MP:
637             case TLV_DS_MAP_HASH_NO_LABEL:
638             case TLV_DS_MAP_HASH_ALL_IP:
639             case TLV_DS_MAP_HASH_NO_MATCH:
640                 proto_tree_add_text(tree, tvb, offset, mplen,
641                         "No Multipath Information");
642                 break;
643             case TLV_DS_MAP_HASH_BITMASK_IP:
644                 if(mplen < 4){
645                         proto_tree_add_text(tree, tvb, offset, mplen,
646                                 "Multi Path length is %u and should be >= 4", mplen);
647                         break;
648                 }
649                 ti = proto_tree_add_text(tree, tvb, offset, mplen,
650                         "Multipath Information");
651                 tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map);
652                 proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_ip, tvb,
653                         offset, 4, FALSE);
654                 if(mplen > 4)
655                         proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_mask, tvb,
656                                 offset + 4, mplen - 4, FALSE);
657                 break;
658             default:
659                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ds_map_mp_value, tvb,
660                         offset, mplen, FALSE);
661                 break;
662             }
663         }
664
665         offset += mplen;
666
667         while (rem >= 4){
668                 decode_mpls_label(tvb, offset, &label, &exp, &bos, &proto);
669                 ti = proto_tree_add_text(tree, tvb, offset, 4, "Downstream Label Element %u",
670                         index);
671                 tlv_ds_map_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ds_map);
672                 proto_item_append_text(ti, ", Label: %u", label);
673                 if (label <= LABEL_MAX_RESERVED){
674                         proto_tree_add_uint_format(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_label,
675                                 tvb, offset, 3, label, "Downstream Label: %u (%s)", label,
676                                 val_to_str(label, special_labels, "Reserved - Unknown"));
677                         proto_item_append_text(ti, " (%s)", val_to_str(label, special_labels,
678                                 "Reserved - Unknown"));
679                 } else {
680                         proto_tree_add_uint_format(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_label,
681                                 tvb, offset, 3, label, "Downstream Label: %u", label);
682                 }
683                 proto_item_append_text(ti, ", Exp: %u, BOS: %u", exp, bos);
684                 proto_tree_add_uint_format(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_exp,
685                         tvb, offset + 2, 1, exp, "Downstream Exp: %u", exp);
686                 proto_tree_add_uint_format(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_bos,
687                         tvb, offset + 2, 1, bos, "Downstream BOS: %u", bos);
688                 proto_tree_add_item(tlv_ds_map_tree, hf_mpls_echo_tlv_ds_map_mp_proto,
689                         tvb, offset + 3, 1, FALSE);
690                 proto_item_append_text(ti, ", Protocol: %u (%s)", proto, val_to_str(proto,
691                         mpls_echo_tlv_ds_map_mp_proto, "Unknown"));
692                 rem -= 4;
693                 offset += 4;
694                 index++;
695         }
696 }
697
698 /*
699  * Dissector for IPv4 and IPv6 Interface and Label Stack Object
700  */
701 static void
702 dissect_mpls_echo_tlv_ilso(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem, gboolean is_ipv6)
703 {
704         proto_tree *ti = NULL, *tlv_ilso = NULL;
705         guint16 index = 1;
706         guint32 label;
707         guint8  exp, bos, ttl;
708
709         if (is_ipv6){
710                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ilso_ipv6_addr, tvb,
711                         offset, 16, FALSE);
712                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ilso_ipv6_int_addr, tvb,
713                         offset + 16, 16, FALSE);
714
715                 offset += 32;
716                 rem -= 32;
717         } else {
718                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ilso_ipv4_addr, tvb,
719                         offset, 4, FALSE);
720                 proto_tree_add_item(tree, hf_mpls_echo_tlv_ilso_ipv4_int_addr, tvb,
721                         offset + 4, 4, FALSE);
722
723                 offset += 8;
724                 rem -= 8;
725         }
726
727
728         while (rem >= 4){
729                 decode_mpls_label(tvb, offset, &label, &exp, &bos, &ttl);
730                 ti = proto_tree_add_text(tree, tvb, offset, 4, "Label Stack Element %u",
731                         index);
732                 tlv_ilso = proto_item_add_subtree(ti, ett_mpls_echo_tlv_ilso);
733                 proto_item_append_text(ti, ", Label: %u", label);
734                 if (label <= LABEL_MAX_RESERVED){
735                         proto_tree_add_uint_format(tlv_ilso, hf_mpls_echo_tlv_ilso_label,
736                                 tvb, offset, 3, label, "Label: %u (%s)", label,
737                                 val_to_str(label, special_labels, "Reserved - Unknown"));
738                         proto_item_append_text(ti, " (%s)", val_to_str(label, special_labels,
739                                 "Reserved - Unknown"));
740                 } else {
741                         proto_tree_add_uint_format(tlv_ilso, hf_mpls_echo_tlv_ilso_label,
742                                 tvb, offset, 3, label, "Label: %u", label);
743                 }
744                 proto_item_append_text(ti, ", Exp: %u, BOS: %u, TTL: %u",
745                         exp, bos, ttl);
746                 proto_tree_add_uint_format(tlv_ilso, hf_mpls_echo_tlv_ilso_exp,
747                         tvb, offset + 2, 1, exp, "Exp: %u", exp);
748                 proto_tree_add_uint_format(tlv_ilso, hf_mpls_echo_tlv_ilso_bos,
749                         tvb, offset + 2, 1, bos, "BOS: %u", bos);
750                 proto_tree_add_item(tlv_ilso, hf_mpls_echo_tlv_ilso_ttl,
751                         tvb, offset + 3, 1, FALSE);
752                 rem -= 4;
753                 offset += 4;
754                 index++;
755         }
756 }
757
758 static int
759 dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem, gboolean in_errored);
760
761 /*
762  * Dissector for Errored TLVs
763  */
764 static void
765 dissect_mpls_echo_tlv_errored(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
766 {
767         int errored_tlv_length;
768
769         while(rem >= 4){
770                 errored_tlv_length = dissect_mpls_echo_tlv(tvb, offset, tree, rem, TRUE);
771                 rem -= errored_tlv_length;
772                 offset += errored_tlv_length;
773         }
774 }
775
776 /*
777  * Dissector for MPLS Echo TLVs and return bytes consumed
778  */
779 static int
780 dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem, gboolean in_errored)
781 {
782         guint16 type, saved_type;
783         int length;
784         proto_tree *ti = NULL, *mpls_echo_tlv_tree = NULL;
785
786         length = tvb_reported_length_remaining(tvb, offset);
787         rem = MIN(rem, length);
788
789         if( rem < 4 ) { /* Type Length */
790                 if(tree)
791                     proto_tree_add_text(tree, tvb, offset, rem,
792                         "Error processing TLV: length is %d, should be >= 4",
793                         rem);
794                 return rem;
795         }
796         type = tvb_get_ntohs(tvb, offset);
797         length = tvb_get_ntohs(tvb, offset + 2),
798         rem -= 4; /* do not count Type Length */
799         length = MIN(length, rem);
800
801         if (tree) {
802                 /* Check for Vendor Private TLVs */
803                 saved_type = type;
804                 if(type >= TLV_VENDOR_PRIVATE_START) /* && <= TLV_VENDOR_PRIVATE_END always true */
805                         type = TLV_VENDOR_PRIVATE_START;
806
807                 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s%s",
808                         in_errored ? "Errored TLV Type: " : "",
809                         val_to_str(type, mpls_echo_tlv_type_names, "Unknown TLV type (0x%04X)"));
810                 mpls_echo_tlv_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv);
811                 if(mpls_echo_tlv_tree == NULL) return length+4;
812
813                 /* MPLS Echo TLV Type and Length */
814                 if (in_errored){
815                         proto_tree_add_uint_format(mpls_echo_tlv_tree, hf_mpls_echo_tlv_errored_type, tvb,
816                             offset, 2, saved_type, "Errored TLV Type: %s (%u)",
817                             val_to_str(type, mpls_echo_tlv_type_names, "Unknown TLV type"), saved_type);
818                 } else {
819                         proto_tree_add_uint_format(mpls_echo_tlv_tree, hf_mpls_echo_tlv_type, tvb,
820                             offset, 2, saved_type, "Type: %s (%u)", 
821                             val_to_str(type, mpls_echo_tlv_type_names, "Unknown TLV type"), saved_type);
822                 }
823                 proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_len, tvb, offset + 2, 2, FALSE);
824
825                 /* MPLS Echo TLV Value */
826                 if (length == 0)
827                         return 4; /* Empty TLV, return Type and Length consumed. */
828
829                 switch (type) {
830                 case TLV_TARGET_FEC_STACK:
831                         dissect_mpls_echo_tlv_fec(tvb, offset + 4, mpls_echo_tlv_tree, length);
832                         break;
833                 case TLV_PAD:
834                         proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_padaction, tvb,
835                             offset + 4, 1, FALSE);
836                         if (length > 1)
837                                 proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_padding, tvb,
838                                         offset + 5, length - 1, FALSE);
839                         break;
840                 case TLV_VENDOR_CODE:
841                         proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_vendor, tvb,
842                         offset + 4, 4, FALSE);
843                         break;
844                 case TLV_ILSO_IPv4:
845                         if(length < 8) {
846                                 proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length,
847                                         "Error processing TLV: length is %d, should be >= 8",
848                                         length);
849                                 break;
850                         }
851                         dissect_mpls_echo_tlv_ilso(tvb, offset + 4, mpls_echo_tlv_tree, length, FALSE);
852                         break;
853                 case TLV_ILSO_IPv6:
854                         if(length < 32) {
855                                 proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length,
856                                         "Error processing TLV: length is %d, should be >= 32",
857                                         length);
858                                 break;
859                         }
860                         dissect_mpls_echo_tlv_ilso(tvb, offset + 4, mpls_echo_tlv_tree, length, TRUE);
861                         break;
862                 case TLV_RTO_IPv4:
863                         if(length != 4) {
864                                 proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length,
865                                         "Error processing TLV: length is %d, should be 4",
866                                         length);
867                                 break;
868                         }
869                         proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_rto_ipv4, 
870                             tvb, offset + 4, 4, FALSE);
871                         break;
872                 case TLV_RTO_IPv6:
873                         if(length != 16) {
874                                 proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length,
875                                         "Error processing TLV: length is %d, should be 16",
876                                         length);
877                                 break;
878                         }
879                         proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_rto_ipv6,    
880                             tvb, offset + 4, 16, FALSE);
881                         break;
882                 case TLV_VENDOR_PRIVATE_START:
883                         if (length < 4) { /* SMI Enterprise code */
884                                 proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length,
885                                         "Error processing Vendor Private TLV: length is %d, should be >= 4",
886                                         length);
887                         } else {
888                                 proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_vendor, tvb,
889                                         offset + 4, 4, FALSE);
890                                 proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_value, tvb,
891                                         offset + 8, length - 4, FALSE);
892                         }
893                         break;
894                 case TLV_DOWNSTREAM_MAPPING:
895                         if(length < 16) {
896                                 proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length,
897                                         "Error processing TLV: length is %d, should be >= 16",
898                                         length);
899                                 break;
900                         }
901                         dissect_mpls_echo_tlv_ds_map(tvb, offset + 4, mpls_echo_tlv_tree, length);
902                         break;
903                 case TLV_ERRORED_TLV:
904                         if (in_errored)
905                                 proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_value, tvb,
906                                         offset + 4, length, FALSE);
907                         else
908                                 dissect_mpls_echo_tlv_errored(tvb, offset + 4, mpls_echo_tlv_tree, length);
909                         break;
910                 case TLV_REPLY_TOS:
911                         if(length != 4) {
912                                 proto_tree_add_text(mpls_echo_tlv_tree, tvb, offset + 4, length,
913                                         "Error processing TLV: length is %d, should be 4",
914                                         length);
915                                 break;
916                         }
917                         proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_reply_tos, tvb,
918                                 offset + 4, 1, FALSE);
919                         proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_reply_tos_mbz, tvb,
920                                 offset + 5, 3, FALSE);
921                         break;
922                 case TLV_ERROR_CODE:
923                 default:
924                         proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_value, tvb,
925                             offset + 4, length, FALSE);
926                         break;
927                 }
928         }
929         return length + 4;  /* Length of the Value field + Type Length */
930 }
931
932 #define MSGTYPE_MPLS_ECHO(msgtype)      ((msgtype == 1) || (msgtype == 2))
933 #define MSGTYPE_DATAPLANE(msgtype)      ((msgtype == 3) || (msgtype == 4))
934
935 /*
936  * Dissector for MPLS Echo (LSP PING) packets
937  */
938 static void
939 dissect_mpls_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
940 {
941         int offset = 0, rem = 0, len;
942         proto_item *ti = NULL;
943         proto_tree *mpls_echo_tree = NULL, *mpls_echo_gflags = NULL;
944         guint8 msgtype;
945         const guint8 *ts_sent, *ts_rec;
946
947         /* If version != 1 we assume it's not an mpls ping packet */
948         if (!tvb_bytes_exist(tvb, 0, 5)) {
949                 return; /* Not enough information to tell version and message type. */
950         }
951         if (tvb_get_ntohs(tvb, 0) != 1) {
952                 return; /* Not version 1. */
953         }
954
955         if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
956                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPLS ECHO");
957     
958         rem = tvb_reported_length_remaining(tvb, offset);
959
960         /* Get the message type and fill in the Column info */
961         msgtype = tvb_get_guint8(tvb, offset + 4);
962
963         /* The minimum fixed part of the packet is 16 Bytes or 32 Bytes depending on Msg Type */
964         if( ((!MSGTYPE_MPLS_ECHO(msgtype)) && (rem < 16)) ||
965                 ((MSGTYPE_MPLS_ECHO(msgtype)) && (rem < 32)) ) {
966                 if( check_col(pinfo->cinfo, COL_INFO) )
967                         col_set_str(pinfo->cinfo, COL_INFO, "Malformed Message");
968                 if(tree) {
969                         ti = proto_tree_add_item(tree, proto_mpls_echo, tvb, 0, -1, FALSE);
970                         mpls_echo_tree = proto_item_add_subtree(ti, ett_mpls_echo);
971                         proto_tree_add_text(mpls_echo_tree, tvb, offset, rem,
972                             "Error processing Message: length is %d, should be >= %u",
973                             rem, (MSGTYPE_MPLS_ECHO(msgtype)) ? 32 : 16);
974                 }
975                 return;
976         }
977
978         if (check_col(pinfo->cinfo, COL_INFO))
979             col_set_str(pinfo->cinfo, COL_INFO,
980                 val_to_str(msgtype, mpls_echo_msgtype, "Unknown Message Type (0x%02X)"));
981
982
983         if (tree) {
984
985                 /* Add subtree and dissect the fixed part of the message */
986                 ti = proto_tree_add_item(tree, proto_mpls_echo, tvb, 0, -1, FALSE);
987                 mpls_echo_tree = proto_item_add_subtree(ti, ett_mpls_echo);
988
989                 proto_tree_add_item(mpls_echo_tree,
990                     hf_mpls_echo_version, tvb, offset, 2, FALSE);
991
992                 if(MSGTYPE_MPLS_ECHO(msgtype)){
993                     ti = proto_tree_add_item(mpls_echo_tree,
994                                 hf_mpls_echo_gflags, tvb, offset + 2, 2, FALSE);
995                     mpls_echo_gflags = proto_item_add_subtree(ti, ett_mpls_echo_gflags);
996                     proto_tree_add_item(mpls_echo_gflags,
997                         hf_mpls_echo_flag_sbz, tvb, offset + 2, 2, FALSE);
998                     proto_tree_add_item(mpls_echo_gflags,
999                         hf_mpls_echo_flag_v, tvb, offset + 2, 2, FALSE);
1000                 } else {
1001                     proto_tree_add_item(mpls_echo_tree,
1002                         hf_mpls_echo_mbz, tvb, offset + 2, 2, FALSE);
1003                 }
1004
1005                 proto_tree_add_item(mpls_echo_tree,
1006                     hf_mpls_echo_msgtype, tvb, offset + 4, 1, FALSE);
1007                 proto_tree_add_item(mpls_echo_tree,
1008                     hf_mpls_echo_replymode, tvb, offset + 5, 1, FALSE);
1009                 proto_tree_add_item(mpls_echo_tree,
1010                     hf_mpls_echo_returncode, tvb, offset + 6, 1, FALSE);
1011                 proto_tree_add_item(mpls_echo_tree,
1012                     hf_mpls_echo_returnsubcode, tvb, offset + 7, 1, FALSE);
1013                 proto_tree_add_item(mpls_echo_tree,
1014                     hf_mpls_echo_handle, tvb, offset + 8, 4, FALSE);
1015                 proto_tree_add_item(mpls_echo_tree,
1016                     hf_mpls_echo_sequence, tvb, offset + 12, 4, FALSE);
1017
1018                 if(MSGTYPE_MPLS_ECHO(msgtype)){
1019                         /* Using NTP routine to calculate the timestamp */
1020                         ts_sent = tvb_get_ptr(tvb, 16, 8);
1021                         proto_tree_add_bytes_format(mpls_echo_tree, hf_mpls_echo_ts_sent, tvb,
1022                             offset + 16, 8, ts_sent, "Timestamp Sent: %s", ntp_fmt_ts(ts_sent));
1023                         ts_rec = tvb_get_ptr(tvb, 24, 8);
1024                         proto_tree_add_bytes_format(mpls_echo_tree, hf_mpls_echo_ts_rec, tvb,
1025                             offset + 24, 8, ts_rec, "Timestamp Received: %s", ntp_fmt_ts(ts_rec));
1026                 }
1027
1028         }
1029
1030         if(MSGTYPE_MPLS_ECHO(msgtype)){
1031             offset += 32;
1032             rem -= 32;
1033         } else {
1034             offset += 16;
1035             rem -= 16;
1036         }
1037
1038         /* Dissect all TLVs */
1039         while(tvb_reported_length_remaining(tvb, offset) > 0 ) {
1040                 len = dissect_mpls_echo_tlv(tvb, offset, mpls_echo_tree, rem, FALSE);
1041                 offset += len;
1042                 rem -= len;
1043         }
1044
1045 }
1046
1047
1048 /* Register the protocol with Wireshark */
1049
1050 void
1051 proto_register_mpls_echo(void)
1052 {                 
1053
1054         static hf_register_info hf[] = {
1055                 { &hf_mpls_echo_version,
1056                         { "Version", "mpls_echo.version",
1057                         FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO Version Number", HFILL}
1058                 },
1059                 { &hf_mpls_echo_mbz,
1060                         { "MBZ", "mpls_echo.mbz",
1061                         FT_UINT16, BASE_HEX, NULL, 0x0, "MPLS ECHO Must be Zero", HFILL}
1062                 },
1063                 { &hf_mpls_echo_gflags,
1064                         { "Global Flags", "mpls_echo.flags",
1065                         FT_UINT16, BASE_HEX, NULL, 0x0, "MPLS ECHO Global Flags", HFILL}
1066                 },
1067                 { &hf_mpls_echo_flag_sbz,
1068                         { "Reserved", "mpls_echo.flag_sbz",
1069                         FT_UINT16, BASE_HEX, NULL, 0xFFFE, "MPLS ECHO Reserved Flags", HFILL}
1070                 },
1071                 { &hf_mpls_echo_flag_v,
1072                         { "Validate FEC Stack", "mpls_echo.flag_v",
1073                         FT_BOOLEAN, 16, NULL, 0x0001, "MPLS ECHO Validate FEC Stack Flag", HFILL}
1074                 },
1075                 { &hf_mpls_echo_msgtype,
1076                         { "Message Type", "mpls_echo.msg_type",
1077                         FT_UINT8, BASE_DEC, VALS(mpls_echo_msgtype), 0x0, "MPLS ECHO Message Type", HFILL}
1078                 },
1079                 { &hf_mpls_echo_replymode,
1080                         { "Reply Mode", "mpls_echo.reply_mode",
1081                         FT_UINT8, BASE_DEC, VALS(mpls_echo_replymode), 0x0, "MPLS ECHO Reply Mode", HFILL}
1082                 },
1083                 { &hf_mpls_echo_returncode,
1084                         { "Return Code", "mpls_echo.return_code",
1085                         FT_UINT8, BASE_DEC, VALS(mpls_echo_returncode), 0x0, "MPLS ECHO Return Code", HFILL}
1086                 },
1087                 { &hf_mpls_echo_returnsubcode,
1088                         { "Return Subcode", "mpls_echo.return_subcode",
1089                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO Return Subcode", HFILL}
1090                 },
1091                 { &hf_mpls_echo_handle,
1092                         { "Sender's Handle", "mpls_echo.sender_handle",
1093                         FT_UINT32, BASE_HEX, NULL, 0x0, "MPLS ECHO Sender's Handle", HFILL}
1094                 },
1095                 { &hf_mpls_echo_sequence,
1096                         { "Sequence Number", "mpls_echo.sequence",
1097                         FT_UINT32, BASE_DEC, NULL, 0x0, "MPLS ECHO Sequence Number", HFILL}
1098                 },
1099                 { &hf_mpls_echo_ts_sent,
1100                         { "Timestamp Sent", "mpls_echo.timestamp_sent",
1101                         FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO Timestamp Sent", HFILL}
1102                 },
1103                 { &hf_mpls_echo_ts_rec,
1104                         { "Timestamp Received", "mpls_echo.timestamp_rec",
1105                         FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO Timestamp Received", HFILL}
1106                 },
1107                 { &hf_mpls_echo_tlv_type,
1108                         { "Type", "mpls_echo.tlv.type",
1109                         FT_UINT16, BASE_DEC, VALS(mpls_echo_tlv_type_names), 0x0,
1110                         "MPLS ECHO TLV Type", HFILL}
1111                 },
1112                 { &hf_mpls_echo_tlv_len,
1113                         { "Length", "mpls_echo.tlv.len",
1114                         FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Length", HFILL}
1115                 },
1116                 { &hf_mpls_echo_tlv_value,
1117                         { "Value", "mpls_echo.tlv.value",
1118                         FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Value", HFILL}
1119                 },
1120                 { &hf_mpls_echo_tlv_fec_type,
1121                         { "Type", "mpls_echo.tlv.fec.type",
1122                         FT_UINT16, BASE_DEC, VALS(mpls_echo_tlv_fec_names), 0x0,
1123                         "MPLS ECHO TLV FEC Stack Type", HFILL}
1124                 },
1125                 { &hf_mpls_echo_tlv_fec_len,
1126                         { "Length", "mpls_echo.tlv.fec.len",
1127                         FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack Length", HFILL}
1128                 },
1129                 { &hf_mpls_echo_tlv_fec_value,
1130                         { "Value", "mpls_echo.tlv.fec.value",
1131                         FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack Value", HFILL}
1132                 },
1133                 { &hf_mpls_echo_tlv_fec_ldp_ipv4,
1134                         { "IPv4 Prefix", "mpls_echo.tlv.fec.ldp_ipv4",
1135                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack LDP IPv4", HFILL}
1136                 },
1137                 { &hf_mpls_echo_tlv_fec_ldp_ipv4_mask,
1138                         { "Prefix Length", "mpls_echo.tlv.fec.ldp_ipv4_mask",
1139                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack LDP IPv4 Prefix Length", HFILL}
1140                 },
1141                 { &hf_mpls_echo_tlv_fec_ldp_ipv6,
1142                         { "IPv6 Prefix", "mpls_echo.tlv.fec.ldp_ipv6",
1143                         FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack LDP IPv6", HFILL}
1144                 },
1145                 { &hf_mpls_echo_tlv_fec_ldp_ipv6_mask,
1146                         { "Prefix Length", "mpls_echo.tlv.fec.ldp_ipv6_mask",
1147                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack LDP IPv6 Prefix Length", HFILL}
1148                 },
1149                 { &hf_mpls_echo_tlv_fec_rsvp_ipv4_ipv4_endpoint,
1150                         { "IPv4 Tunnel endpoint address", "mpls_echo.tlv.fec.rsvp_ipv4_ep",
1151                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP IPv4 Tunnel Endpoint Address", HFILL}
1152                 },
1153                 { &hf_mpls_echo_tlv_fec_rsvp_ipv6_ipv6_endpoint,
1154                         { "IPv6 Tunnel endpoint address", "mpls_echo.tlv.fec.rsvp_ipv6_ep",
1155                         FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP IPv6 Tunnel Endpoint Address", HFILL}
1156                 },
1157                 { &hf_mpls_echo_tlv_fec_rsvp_ip_mbz1,
1158                         { "Must Be Zero", "mpls_echo.tlv.fec.rsvp_ip_mbz1",
1159                         FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP MBZ", HFILL}
1160                 },
1161                 { &hf_mpls_echo_tlv_fec_rsvp_ip_tunnel_id,
1162                         { "Tunnel ID", "mpls_echo.tlv.fec.rsvp_ip_tun_id",
1163                         FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP Tunnel ID", HFILL}
1164                 },
1165                 { &hf_mpls_echo_tlv_fec_rsvp_ipv4_ext_tunnel_id,
1166                         { "Extended Tunnel ID", "mpls_echo.tlv.fec.rsvp_ipv4_ext_tun_id",
1167                         FT_UINT32, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP IPv4 Extended Tunnel ID", HFILL}
1168                 },
1169                 { &hf_mpls_echo_tlv_fec_rsvp_ipv4_ipv4_sender,
1170                         { "IPv4 Tunnel sender address", "mpls_echo.tlv.fec.rsvp_ipv4_sender",
1171                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP IPv4 Sender", HFILL}
1172                 },
1173                 { &hf_mpls_echo_tlv_fec_rsvp_ipv6_ext_tunnel_id,
1174                         { "Extended Tunnel ID", "mpls_echo.tlv.fec.rsvp_ipv6_ext_tun_id",
1175                         FT_BYTES, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP IPv6 Extended Tunnel ID", HFILL}
1176                 },
1177                 { &hf_mpls_echo_tlv_fec_rsvp_ipv6_ipv6_sender,
1178                         { "IPv6 Tunnel sender address", "mpls_echo.tlv.fec.rsvp_ipv6_sender",
1179                         FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP IPv4 Sender", HFILL}
1180                 },
1181                 { &hf_mpls_echo_tlv_fec_rsvp_ip_mbz2,
1182                         { "Must Be Zero", "mpls_echo.tlv.fec.rsvp_ip_mbz2",
1183                         FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP MBZ", HFILL}
1184                 },
1185                 { &hf_mpls_echo_tlv_fec_rsvp_ip_lsp_id,
1186                         { "LSP ID", "mpls_echo.tlv.fec.rsvp_ip_lsp_id",
1187                         FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack RSVP LSP ID", HFILL}
1188                 },
1189                 { &hf_mpls_echo_tlv_fec_l2cid_sender,
1190                         { "Sender's PE Address", "mpls_echo.tlv.fec.l2cid_sender",
1191                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack L2CID Sender", HFILL}
1192                 },
1193                 { &hf_mpls_echo_tlv_fec_l2cid_remote,
1194                         { "Remote PE Address", "mpls_echo.tlv.fec.l2cid_remote",
1195                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack L2CID Remote", HFILL}
1196                 },
1197                 { &hf_mpls_echo_tlv_fec_l2cid_vcid,
1198                         { "VC ID", "mpls_echo.tlv.fec.l2cid_vcid",
1199                         FT_UINT32, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack L2CID VCID", HFILL}
1200                 },
1201                 { &hf_mpls_echo_tlv_fec_l2cid_encap,
1202                         { "Encapsulation", "mpls_echo.tlv.fec.l2cid_encap",
1203                         FT_UINT16, BASE_DEC, VALS(fec_vc_types_vals), 0x0, "MPLS ECHO TLV FEC Stack L2CID Encapsulation", HFILL}
1204                 },
1205                 { &hf_mpls_echo_tlv_fec_l2cid_mbz,
1206                         { "MBZ", "mpls_echo.tlv.fec.l2cid_mbz",
1207                         FT_UINT16, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV FEC Stack L2CID MBZ", HFILL}
1208                 },
1209                 { &hf_mpls_echo_tlv_fec_bgp_nh,
1210                         { "BGP Next Hop", "mpls_echo.tlv.fec.bgp_nh",
1211                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack BGP Next Hop", HFILL}
1212                 },
1213                 { &hf_mpls_echo_tlv_fec_bgp_ipv4,
1214                         { "IPv4 Prefix", "mpls_echo.tlv.fec.bgp_ipv4",
1215                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack BGP IPv4", HFILL}
1216                 },
1217                 { &hf_mpls_echo_tlv_fec_bgp_len,
1218                         { "Prefix Length", "mpls_echo.tlv.fec.bgp_len",
1219                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack BGP Prefix Length", HFILL}
1220                 },
1221                 { &hf_mpls_echo_tlv_fec_gen_ipv4,
1222                         { "IPv4 Prefix", "mpls_echo.tlv.fec.gen_ipv4",
1223                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack Generic IPv4", HFILL}
1224                 },
1225                 { &hf_mpls_echo_tlv_fec_gen_ipv4_mask,
1226                         { "Prefix Length", "mpls_echo.tlv.fec.gen_ipv4_mask",
1227                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack Generic IPv4 Prefix Length", HFILL}
1228                 },
1229                 { &hf_mpls_echo_tlv_fec_gen_ipv6,
1230                         { "IPv6 Prefix", "mpls_echo.tlv.fec.gen_ipv6",
1231                         FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack Generic IPv6", HFILL}
1232                 },
1233                 { &hf_mpls_echo_tlv_fec_gen_ipv6_mask,
1234                         { "Prefix Length", "mpls_echo.tlv.fec.gen_ipv6_mask",
1235                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack Generic IPv6 Prefix Length", HFILL}
1236                 },
1237                 { &hf_mpls_echo_tlv_fec_nil_label,
1238                         { "Label", "mpls_echo.tlv.fec.nil_label",
1239                         FT_UINT24, BASE_DEC, VALS(special_labels), 0x0, "MPLS ECHO TLV FEC Stack NIL Label", HFILL}
1240                 },
1241                 { &hf_mpls_echo_tlv_ds_map_mtu,
1242                         { "MTU", "mpls_echo.tlv.ds_map.mtu",
1243                         FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map MTU", HFILL}
1244                 },
1245                 { &hf_mpls_echo_tlv_ds_map_addr_type,
1246                         { "Address Type", "mpls_echo.tlv.ds_map.addr_type",
1247                         FT_UINT8, BASE_DEC, VALS(mpls_echo_tlv_ds_map_addr_type), 0x0,
1248                         "MPLS ECHO TLV Downstream Map Address Type", HFILL}
1249                 },
1250                 { &hf_mpls_echo_tlv_ds_map_res,
1251                         { "DS Flags", "mpls_echo.tlv.ds_map.res",
1252                         FT_UINT8, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV Downstream Map DS Flags", HFILL}
1253                 },
1254                 { &hf_mpls_echo_tlv_ds_map_flag_res,
1255                         { "MBZ", "mpls_echo.tlv.ds_map.flag_res",
1256                         FT_UINT8, BASE_HEX, NULL, 0xFC, "MPLS ECHO TLV Downstream Map Reserved Flags", HFILL}
1257                 },
1258                 { &hf_mpls_echo_tlv_ds_map_flag_i,
1259                         { "Interface and Label Stack Request", "mpls_echo.tlv.ds_map.flag_i",
1260                         FT_BOOLEAN, 8, NULL, 0x02, "MPLS ECHO TLV Downstream Map I-Flag", HFILL}
1261                 },
1262                 { &hf_mpls_echo_tlv_ds_map_flag_n,
1263                         { "Treat as Non-IP Packet", "mpls_echo.tlv.ds_map.flag_n",
1264                         FT_BOOLEAN, 8, NULL, 0x01, "MPLS ECHO TLV Downstream Map N-Flag", HFILL}
1265                 },
1266                 { &hf_mpls_echo_tlv_ds_map_ds_ip,
1267                         { "Downstream IP Address", "mpls_echo.tlv.ds_map.ds_ip",
1268                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map IP Address", HFILL}
1269                 },
1270                 { &hf_mpls_echo_tlv_ds_map_int_ip,
1271                         { "Downstream Interface Address", "mpls_echo.tlv.ds_map.int_ip",
1272                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Interface Address", HFILL}
1273                 },
1274                 { &hf_mpls_echo_tlv_ds_map_if_index,
1275                         { "Upstream Interface Index", "mpls_echo.tlv.ds_map.if_index",
1276                         FT_UINT32, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Interface Index", HFILL}
1277                 },
1278                 { &hf_mpls_echo_tlv_ds_map_ds_ipv6,
1279                         { "Downstream IPv6 Address", "mpls_echo.tlv.ds_map.ds_ipv6",
1280                         FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map IPv6 Address", HFILL}
1281                 },
1282                 { &hf_mpls_echo_tlv_ds_map_int_ipv6,
1283                         { "Downstream Interface IPv6 Address", "mpls_echo.tlv.ds_map.int_ipv6",
1284                         FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Interface IPv6 Address", HFILL}
1285                 },
1286                 { &hf_mpls_echo_tlv_ds_map_hash_type,
1287                         { "Multipath Type", "mpls_echo.tlv.ds_map.hash_type",
1288                         FT_UINT8, BASE_DEC, VALS(mpls_echo_tlv_ds_map_hash_type), 0x0,
1289                         "MPLS ECHO TLV Downstream Map Multipath Type", HFILL}
1290                 },
1291                 { &hf_mpls_echo_tlv_ds_map_depth,
1292                         { "Depth Limit", "mpls_echo.tlv.ds_map.depth",
1293                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Depth Limit", HFILL}
1294                 },
1295                 { &hf_mpls_echo_tlv_ds_map_muti_len,
1296                         { "Multipath Length", "mpls_echo.tlv.ds_map.multi_len",
1297                         FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath Length", HFILL}
1298                 },
1299                 { &hf_mpls_echo_tlv_ds_map_mp_ip,
1300                         { "IP Address", "mpls_echo.tlv.ds_map_mp.ip",
1301                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath IP Address", HFILL}
1302                 },
1303                 { &hf_mpls_echo_tlv_ds_map_mp_mask,
1304                         { "Mask", "mpls_echo.tlv.ds_map_mp.mask",
1305                         FT_BYTES, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath Mask", HFILL}
1306                 },
1307                 { &hf_mpls_echo_tlv_ds_map_mp_ip_low,
1308                         { "IP Address Low", "mpls_echo.tlv.ds_map_mp.ip_low",
1309                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath Low IP Address", HFILL}
1310                 },
1311                 { &hf_mpls_echo_tlv_ds_map_mp_ip_high,
1312                         { "IP Address High", "mpls_echo.tlv.ds_map_mp.ip_high",
1313                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Downstream Map Multipath High IP Address", HFILL}
1314                 },
1315                 { &hf_mpls_echo_tlv_ds_map_mp_value,
1316                         { "Multipath Value", "mpls_echo.tlv.ds_map_mp.value",
1317                         FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Multipath Value", HFILL}
1318                 },
1319                 { &hf_mpls_echo_tlv_ds_map_mp_label,
1320                         { "Downstream Label", "mpls_echo.tlv.ds_map.mp_label",
1321                         FT_UINT24, BASE_DEC, VALS(special_labels), 0x0, "MPLS ECHO TLV Downstream Map Downstream Label", HFILL}
1322                 },
1323                 { &hf_mpls_echo_tlv_ds_map_mp_exp,
1324                         { "Downstream Experimental", "mpls_echo.tlv.ds_map.mp_exp",
1325                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Downstream Experimental", HFILL}
1326                 },
1327                 { &hf_mpls_echo_tlv_ds_map_mp_bos,
1328                         { "Downstream BOS", "mpls_echo.tlv.ds_map.mp_bos",
1329                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Downstream Map Downstream BOS", HFILL}
1330                 },
1331                 { &hf_mpls_echo_tlv_ds_map_mp_proto,
1332                         { "Downstream Protocol", "mpls_echo.tlv.ds_map.mp_proto",
1333                         FT_UINT8, BASE_DEC, VALS(mpls_echo_tlv_ds_map_mp_proto), 0x0,
1334                         "MPLS ECHO TLV Downstream Map Downstream Protocol", HFILL}
1335                 },
1336                 { &hf_mpls_echo_tlv_padaction,
1337                         { "Pad Action", "mpls_echo.tlv.pad_action",
1338                         FT_UINT8, BASE_DEC, VALS(mpls_echo_tlv_pad), 0x0, "MPLS ECHO Pad TLV Action", HFILL}
1339                 },
1340                 { &hf_mpls_echo_tlv_padding,
1341                         { "Padding", "mpls_echo.tlv.pad_padding",
1342                         FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO Pad TLV Padding", HFILL}
1343                 },
1344                 { &hf_mpls_echo_tlv_vendor,
1345                         { "Vendor Id", "mpls_echo.tlv.vendor_id",
1346                         FT_UINT32, BASE_DEC, VALS(sminmpec_values), 0x0, "MPLS ECHO Vendor Id", HFILL}
1347                 },
1348                 { &hf_mpls_echo_tlv_ilso_ipv4_addr,
1349                         { "Downstream IPv4 Address", "mpls_echo.tlv.ilso_ipv4.addr",
1350                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Address", HFILL}
1351                 },
1352                 { &hf_mpls_echo_tlv_ilso_ipv4_int_addr,
1353                         { "Downstream Interface Address", "mpls_echo.tlv.ilso_ipv4.int_addr",
1354                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Address", HFILL}
1355                 },
1356                 { &hf_mpls_echo_tlv_ilso_ipv6_addr,
1357                         { "Downstream IPv6 Address", "mpls_echo.tlv.ilso_ipv6.addr",
1358                         FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Address", HFILL}
1359                 },
1360                 { &hf_mpls_echo_tlv_ilso_ipv6_int_addr,
1361                         { "Downstream Interface Address", "mpls_echo.tlv.ilso_ipv6.int_addr",
1362                         FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Address", HFILL}
1363                 },
1364                 { &hf_mpls_echo_tlv_ilso_label,
1365                         { "Label", "mpls_echo.tlv.ilso_ipv4.label",
1366                         FT_UINT24, BASE_DEC, VALS(special_labels), 0x0, "MPLS ECHO TLV Interface and Label Stack Label", HFILL}
1367                 },
1368                 { &hf_mpls_echo_tlv_ilso_exp,
1369                         { "Exp", "mpls_echo.tlv.ilso_ipv4.exp",
1370                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack Exp", HFILL}
1371                 },
1372                 { &hf_mpls_echo_tlv_ilso_bos,
1373                         { "BOS", "mpls_echo.tlv.ilso_ipv4.bos",
1374                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack BOS", HFILL}
1375                 },
1376                 { &hf_mpls_echo_tlv_ilso_ttl,
1377                         { "TTL", "mpls_echo.tlv.ilso_ipv4.ttl",
1378                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Interface and Label Stack TTL", HFILL}
1379                 },
1380                 { &hf_mpls_echo_tlv_rto_ipv4,
1381                         { "Reply-to IPv4 Address", "mpls_echo.tlv.rto.ipv4",
1382                         FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV IPv4 Reply-To Object", HFILL}
1383                 },
1384                 { &hf_mpls_echo_tlv_rto_ipv6,
1385                         { "Reply-to IPv6 Address", "mpls_echo.tlv.rto.ipv6",
1386                         FT_IPv6, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV IPv6 Reply-To Object", HFILL}
1387                 },
1388                 { &hf_mpls_echo_tlv_reply_tos,
1389                         { "Reply-TOS Byte", "mpls_echo.tlv.reply.tos",
1390                         FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Reply-TOS Byte", HFILL}
1391                 },
1392                 { &hf_mpls_echo_tlv_reply_tos_mbz,
1393                         { "MBZ", "mpls_echo.tlv.reply.tos.mbz",
1394                         FT_UINT24, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV Reply-TOS MBZ", HFILL}
1395                 },
1396                 { &hf_mpls_echo_tlv_errored_type,
1397                         { "Errored TLV Type", "mpls_echo.tlv.errored.type",
1398                         FT_UINT16, BASE_DEC, VALS(mpls_echo_tlv_type_names), 0x0,
1399                         "MPLS ECHO TLV Errored TLV Type", HFILL}
1400                 }
1401         };
1402
1403         static gint *ett[] = {
1404                 &ett_mpls_echo,
1405                 &ett_mpls_echo_gflags,
1406                 &ett_mpls_echo_tlv,
1407                 &ett_mpls_echo_tlv_fec,
1408                 &ett_mpls_echo_tlv_ds_map,
1409                 &ett_mpls_echo_tlv_ilso,
1410         };
1411
1412         module_t *mpls_echo_module;
1413
1414         proto_mpls_echo = proto_register_protocol("Multiprotocol Label Switching Echo",
1415             "MPLS Echo", "mpls-echo");
1416
1417         proto_register_field_array(proto_mpls_echo, hf, array_length(hf));
1418         proto_register_subtree_array(ett, array_length(ett));
1419
1420         mpls_echo_module = prefs_register_protocol(proto_mpls_echo, proto_reg_handoff_mpls_echo);
1421         prefs_register_uint_preference(mpls_echo_module, "udp.port", "MPLS Echo UDP Port",
1422             "Set the UDP port for messages (if other"
1423             " than the default of 3503)",
1424             10, &global_mpls_echo_udp_port);
1425 }
1426
1427
1428 void
1429 proto_reg_handoff_mpls_echo(void)
1430 {
1431         static gboolean mpls_echo_prefs_initialized = FALSE;
1432         static dissector_handle_t mpls_echo_handle;
1433
1434         if(!mpls_echo_prefs_initialized) {
1435             mpls_echo_handle = create_dissector_handle(dissect_mpls_echo,
1436                 proto_mpls_echo);
1437             mpls_echo_prefs_initialized = TRUE;
1438         } else {
1439             dissector_delete("udp.port", mpls_echo_udp_port, mpls_echo_handle);
1440         }
1441
1442         mpls_echo_udp_port = global_mpls_echo_udp_port;
1443         dissector_add("udp.port", global_mpls_echo_udp_port, mpls_echo_handle);
1444 }