The "next_submsg" argument passed to "get_bitmap()" is an offset within
[obnox/wireshark/wip.git] / packet-ldp.c
1 /* packet-ldp.c
2  * Routines for LDP (RFC 3036) packet disassembly
3  *
4  * $Id: packet-ldp.c,v 1.50 2004/01/17 12:51:00 ulfl Exp $
5  *
6  * Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
7  *
8  * CRLDP (RFC3212) is now supported
9  *   - (c) 2002 Michael Rozhavsky <mike[AT]tochna.technion.ac.il>
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@ethereal.com>
13  * Copyright 1999 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <ctype.h>
37 #include <time.h>
38 #include <glib.h>
39 #include <string.h>
40 #include <epan/packet.h>
41 #include <epan/resolv.h>
42 #include "prefs.h"
43 #include "afn.h"
44
45 #include "packet-frame.h"
46 #include "packet-diffserv-mpls-common.h"
47
48 #define TCP_PORT_LDP 646
49 #define UDP_PORT_LDP 646
50
51 void proto_reg_handoff_ldp(void);
52
53 static int proto_ldp = -1;
54
55 /* Delete the following if you do not use it, or add to it if you need */
56 static int hf_ldp_req = -1;
57 static int hf_ldp_rsp = -1;
58 static int hf_ldp_version = -1;
59 static int hf_ldp_pdu_len = -1;
60 static int hf_ldp_lsr = -1;
61 static int hf_ldp_ls_id = -1;
62 static int hf_ldp_msg_ubit = -1;
63 static int hf_ldp_msg_type = -1;
64 static int hf_ldp_msg_len = -1;
65 static int hf_ldp_msg_id = -1;
66 static int hf_ldp_msg_vendor_id = -1;
67 static int hf_ldp_msg_experiment_id = -1;
68 static int hf_ldp_tlv_value = -1;
69 static int hf_ldp_tlv_type = -1;
70 static int hf_ldp_tlv_unknown = -1;
71 static int hf_ldp_tlv_len = -1;
72 static int hf_ldp_tlv_val_hold = -1;
73 static int hf_ldp_tlv_val_target = -1;
74 static int hf_ldp_tlv_val_request = -1;
75 static int hf_ldp_tlv_val_res = -1;
76 static int hf_ldp_tlv_ipv4_taddr = -1;
77 static int hf_ldp_tlv_config_seqno = -1;
78 static int hf_ldp_tlv_ipv6_taddr = -1;
79 static int hf_ldp_tlv_fec_wc = -1;
80 static int hf_ldp_tlv_fec_af = -1;
81 static int hf_ldp_tlv_fec_len = -1;
82 static int hf_ldp_tlv_fec_pfval = -1;
83 static int hf_ldp_tlv_fec_hoval = -1;
84 static int hf_ldp_tlv_addrl_addr_family = -1;
85 static int hf_ldp_tlv_addrl_addr = -1;
86 static int hf_ldp_tlv_hc_value = -1;
87 static int hf_ldp_tlv_pv_lsrid = -1;
88 static int hf_ldp_tlv_generic_label = -1;
89 static int hf_ldp_tlv_atm_label_vbits = -1;
90 static int hf_ldp_tlv_atm_label_vpi = -1;
91 static int hf_ldp_tlv_atm_label_vci = -1;
92 static int hf_ldp_tlv_fr_label_len = -1;
93 static int hf_ldp_tlv_fr_label_dlci = -1;
94 static int hf_ldp_tlv_status_ebit = -1;
95 static int hf_ldp_tlv_status_fbit = -1;
96 static int hf_ldp_tlv_status_data = -1;
97 static int hf_ldp_tlv_status_msg_id = -1;
98 static int hf_ldp_tlv_status_msg_type = -1;
99 static int hf_ldp_tlv_extstatus_data = -1;
100 static int hf_ldp_tlv_returned_version = -1;
101 static int hf_ldp_tlv_returned_pdu_len = -1;
102 static int hf_ldp_tlv_returned_lsr = -1;
103 static int hf_ldp_tlv_returned_ls_id = -1;
104 static int hf_ldp_tlv_returned_msg_ubit = -1;
105 static int hf_ldp_tlv_returned_msg_type = -1;
106 static int hf_ldp_tlv_returned_msg_len = -1;
107 static int hf_ldp_tlv_returned_msg_id = -1;
108 static int hf_ldp_tlv_mac = -1;
109 static int hf_ldp_tlv_sess_ver = -1;
110 static int hf_ldp_tlv_sess_ka = -1;
111 static int hf_ldp_tlv_sess_advbit = -1;
112 static int hf_ldp_tlv_sess_ldetbit = -1;
113 static int hf_ldp_tlv_sess_pvlim = -1;
114 static int hf_ldp_tlv_sess_mxpdu = -1;
115 static int hf_ldp_tlv_sess_rxlsr = -1;
116 static int hf_ldp_tlv_sess_rxls = -1;
117 static int hf_ldp_tlv_sess_atm_merge = -1;
118 static int hf_ldp_tlv_sess_atm_lr = -1;
119 static int hf_ldp_tlv_sess_atm_dir = -1;
120 static int hf_ldp_tlv_sess_atm_minvpi = -1;
121 static int hf_ldp_tlv_sess_atm_maxvpi = -1;
122 static int hf_ldp_tlv_sess_atm_minvci = -1;
123 static int hf_ldp_tlv_sess_atm_maxvci = -1;
124 static int hf_ldp_tlv_sess_fr_merge = -1;
125 static int hf_ldp_tlv_sess_fr_lr = -1;
126 static int hf_ldp_tlv_sess_fr_dir = -1;
127 static int hf_ldp_tlv_sess_fr_len = -1;
128 static int hf_ldp_tlv_sess_fr_mindlci = -1;
129 static int hf_ldp_tlv_sess_fr_maxdlci = -1;
130 static int hf_ldp_tlv_lbl_req_msg_id = -1;
131 static int hf_ldp_tlv_vendor_id = -1;
132 static int hf_ldp_tlv_experiment_id = -1;
133 static int hf_ldp_tlv_fec_vc_controlword = -1;
134 static int hf_ldp_tlv_fec_vc_vctype = -1;
135 static int hf_ldp_tlv_fec_vc_infolength = -1;
136 static int hf_ldp_tlv_fec_vc_groupid = -1;
137 static int hf_ldp_tlv_fec_vc_vcid = -1;
138 static int hf_ldp_tlv_fec_vc_intparam_length = -1;
139 static int hf_ldp_tlv_fec_vc_intparam_mtu = -1;
140 static int hf_ldp_tlv_fec_vc_intparam_tdmbps = -1;
141 static int hf_ldp_tlv_fec_vc_intparam_id = -1;
142 static int hf_ldp_tlv_fec_vc_intparam_maxcatmcells = -1;
143 static int hf_ldp_tlv_fec_vc_intparam_desc = -1;
144 static int hf_ldp_tlv_fec_vc_intparam_cembytes = -1;
145 static int hf_ldp_tlv_fec_vc_intparam_vpnid_oui = -1;
146 static int hf_ldp_tlv_fec_vc_intparam_vpnid_index = -1;
147 static int hf_ldp_tlv_lspid_act_flg = -1;
148 static int hf_ldp_tlv_lspid_cr_lsp = -1;
149 static int hf_ldp_tlv_lspid_ldpid = -1;
150 static int hf_ldp_tlv_er_hop_loose = -1;
151 static int hf_ldp_tlv_er_hop_prelen = -1;
152 static int hf_ldp_tlv_er_hop_prefix4 = -1;
153 static int hf_ldp_tlv_er_hop_prefix6 = -1;
154 static int hf_ldp_tlv_er_hop_as = -1;
155 static int hf_ldp_tlv_er_hop_cr_lsp = -1;
156 static int hf_ldp_tlv_er_hop_ldpid = -1;
157 static int hf_ldp_tlv_flags_reserv = -1;
158 static int hf_ldp_tlv_flags_weight = -1;
159 static int hf_ldp_tlv_flags_ebs = -1;
160 static int hf_ldp_tlv_flags_cbs = -1;
161 static int hf_ldp_tlv_flags_cdr = -1;
162 static int hf_ldp_tlv_flags_pbs = -1;
163 static int hf_ldp_tlv_flags_pdr = -1;
164 static int hf_ldp_tlv_frequency = -1;
165 static int hf_ldp_tlv_pdr = -1;
166 static int hf_ldp_tlv_pbs = -1;
167 static int hf_ldp_tlv_cdr = -1;
168 static int hf_ldp_tlv_cbs = -1;
169 static int hf_ldp_tlv_ebs = -1;
170 static int hf_ldp_tlv_weight = -1;
171 static int hf_ldp_tlv_set_prio = -1;
172 static int hf_ldp_tlv_hold_prio = -1;
173 static int hf_ldp_tlv_route_pinning = -1;
174 static int hf_ldp_tlv_resource_class = -1;
175 static int hf_ldp_tlv_diffserv = -1;
176 static int hf_ldp_tlv_diffserv_type = -1;
177 static int hf_ldp_tlv_diffserv_mapnb = -1;
178 static int hf_ldp_tlv_diffserv_map = -1;
179 static int hf_ldp_tlv_diffserv_map_exp = -1;
180 static int hf_ldp_tlv_diffserv_phbid = -1;
181 static int hf_ldp_tlv_diffserv_phbid_dscp = -1;
182 static int hf_ldp_tlv_diffserv_phbid_code = -1;
183 static int hf_ldp_tlv_diffserv_phbid_bit14 = -1;
184 static int hf_ldp_tlv_diffserv_phbid_bit15 = -1;
185 static int ett_ldp = -1;
186 static int ett_ldp_header = -1;
187 static int ett_ldp_ldpid = -1;
188 static int ett_ldp_message = -1;
189 static int ett_ldp_tlv = -1;
190 static int ett_ldp_tlv_val = -1;
191 static int ett_ldp_fec = -1;
192 static int ett_ldp_fec_vc_interfaceparam = -1;
193 static int ett_ldp_diffserv_map = -1;
194 static int ett_ldp_diffserv_map_phbid = -1;
195
196 static int tcp_port = 0;
197 static int udp_port = 0;
198
199 /* desegmentation of LDP over TCP */
200 static gboolean ldp_desegment = FALSE;
201
202 /* Add your functions here */
203
204 static guint32 global_ldp_tcp_port = TCP_PORT_LDP;
205 static guint32 global_ldp_udp_port = UDP_PORT_LDP;
206
207 /*
208  * The following define all the TLV types I know about
209  */
210
211 #define TLV_FEC                    0x0100
212 #define TLV_ADDRESS_LIST           0x0101
213 #define TLV_HOP_COUNT              0x0103
214 #define TLV_PATH_VECTOR            0x0104
215 #define TLV_GENERIC_LABEL          0x0200
216 #define TLV_ATM_LABEL              0x0201
217 #define TLV_FRAME_LABEL            0x0202
218 #define TLV_STATUS                 0x0300
219 #define TLV_EXTENDED_STATUS        0x0301
220 #define TLV_RETURNED_PDU           0x0302
221 #define TLV_RETURNED_MESSAGE       0x0303
222 #define TLV_COMMON_HELLO_PARMS     0x0400
223 #define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
224 #define TLV_CONFIGURATION_SEQNO    0x0402
225 #define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
226 #define TLV_MAC                    0x0404
227 #define TLV_COMMON_SESSION_PARMS   0x0500
228 #define TLV_ATM_SESSION_PARMS      0x0501
229 #define TLV_FRAME_RELAY_SESSION_PARMS 0x0502
230 #define TLV_LABEL_REQUEST_MESSAGE_ID 0x0600
231 #define TLV_ER                     0x0800
232 #define TLV_ER_HOP_IPV4            0x0801
233 #define TLV_ER_HOP_IPV6            0x0802
234 #define TLV_ER_HOP_AS              0x0803
235 #define TLV_ER_HOP_LSPID           0x0804
236 #define TLV_TRAFFIC_PARAM          0x0810
237 #define TLV_PREEMPTION             0x0820
238 #define TLV_LSPID                  0x0821
239 #define TLV_RESOURCE_CLASS         0x0822
240 #define TLV_ROUTE_PINNING          0x0823
241 #define TLV_DIFFSERV               0x0901
242 #define TLV_VENDOR_PRIVATE_START   0x3E00
243 #define TLV_VENDOR_PRIVATE_END     0x3EFF
244 #define TLV_EXPERIMENTAL_START     0x3F00
245 #define TLV_EXPERIMENTAL_END       0x3FFF
246
247 static const value_string tlv_type_names[] = {
248   { TLV_FEC,                       "Forwarding Equivalence Classes TLV" },
249   { TLV_ADDRESS_LIST,              "Address List TLV"},
250   { TLV_HOP_COUNT,                 "Hop Count TLV"},
251   { TLV_PATH_VECTOR,               "Path Vector TLV"},
252   { TLV_GENERIC_LABEL,             "Generic Label TLV"},
253   { TLV_ATM_LABEL,                 "ATM Label TLV"},
254   { TLV_FRAME_LABEL,               "Frame Label TLV"},
255   { TLV_STATUS,                    "Status TLV"},
256   { TLV_EXTENDED_STATUS,           "Extended Status TLV"},
257   { TLV_RETURNED_PDU,              "Returned PDU TLV"},
258   { TLV_RETURNED_MESSAGE,          "Returned Message TLV"},
259   { TLV_COMMON_HELLO_PARMS,        "Common Hello Parameters TLV"},
260   { TLV_IPV4_TRANSPORT_ADDRESS,    "IPv4 Transport Address TLV"},
261   { TLV_CONFIGURATION_SEQNO,       "Configuration Sequence Number TLV"},
262   { TLV_IPV6_TRANSPORT_ADDRESS,    "IPv6 Transport Address TLV"},
263   { TLV_MAC,                       "MAC TLV"},
264   { TLV_COMMON_SESSION_PARMS,      "Common Session Parameters TLV"},
265   { TLV_ATM_SESSION_PARMS,         "ATM Session Parameters TLV"},
266   { TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters TLV"},
267   { TLV_LABEL_REQUEST_MESSAGE_ID,  "Label Request Message ID TLV"},
268   { TLV_LSPID,                     "LSP ID TLV"},
269   { TLV_ER,                        "Explicit route TLV"},
270   { TLV_ER_HOP_IPV4,               "ER hop IPv4 prefix TLV"},
271   { TLV_ER_HOP_IPV6,               "ER hop IPv6 prefix TLV"},
272   { TLV_ER_HOP_AS,                 "ER hop Autonomous system number prefix TLV"},
273   { TLV_TRAFFIC_PARAM,             "Traffic parameters TLV"},
274   { TLV_PREEMPTION,                "Preemption TLV"},
275   { TLV_ER_HOP_LSPID,              "ER hop LSPID prefix TLV"},
276   { TLV_RESOURCE_CLASS,            "Resource Class (Color) TLV"},
277   { TLV_ROUTE_PINNING,             "Route Pinning TLV"},
278   { TLV_DIFFSERV,                  "Diff-Serv TLV"},
279   { TLV_VENDOR_PRIVATE_START,   "Vendor Private TLV"},
280   { TLV_EXPERIMENTAL_START,     "Experimental TLV"},
281   { 0, NULL}
282 };
283
284 /*
285  * The following define all the message types I know about
286  */
287
288 #define LDP_NOTIFICATION       0x0001
289 #define LDP_HELLO              0x0100
290 #define LDP_INITIALIZATION     0x0200
291 #define LDP_KEEPALIVE          0x0201
292 #define LDP_ADDRESS            0x0300
293 #define LDP_ADDRESS_WITHDRAWAL 0x0301
294 #define LDP_LABEL_MAPPING      0x0400
295 #define LDP_LABEL_REQUEST      0x0401
296 #define LDP_LABEL_WITHDRAWAL   0x0402
297 #define LDP_LABEL_RELEASE      0x0403
298 #define LDP_LABEL_ABORT_REQUEST 0x0404
299 #define LDP_VENDOR_PRIVATE_START 0x3E00
300 #define LDP_VENDOR_PRIVATE_END   0x3EFF
301 #define LDP_EXPERIMENTAL_MESSAGE_START 0x3F00
302 #define LDP_EXPERIMENTAL_MESSAGE_END   0x3FFF
303
304 static const value_string ldp_message_types[] = {
305   {LDP_NOTIFICATION,             "Notification Message"},
306   {LDP_HELLO,                    "Hello Message"},
307   {LDP_INITIALIZATION,           "Initialization Message"},
308   {LDP_KEEPALIVE,                "Keep Alive Message"},
309   {LDP_ADDRESS,                  "Address Message"},
310   {LDP_ADDRESS_WITHDRAWAL,       "Address Withdrawal Message"},
311   {LDP_LABEL_MAPPING,            "Label Mapping Message"},
312   {LDP_LABEL_REQUEST,            "Label Request Message"},
313   {LDP_LABEL_WITHDRAWAL,         "Label Withdrawal Message"},
314   {LDP_LABEL_RELEASE,            "Label Release Message"},
315   {LDP_LABEL_ABORT_REQUEST,      "Label Abort Request Message"},
316   {LDP_VENDOR_PRIVATE_START,     "Vendor-Private Message"},
317   {LDP_EXPERIMENTAL_MESSAGE_START,     "Experimental Message"},
318   {0, NULL}
319 };
320
321 static const true_false_string ldp_message_ubit = {
322   "Unknown bit set",
323   "Unknown bit not set"
324 };
325
326 static const true_false_string hello_targeted_vals = {
327   "Targeted Hello",
328   "Link Hello"
329 };
330
331 static const value_string tlv_unknown_vals[] = {
332   {0, "Known TLV, do not Forward"},
333   {1, "Known TLV, do Forward"},
334   {2, "Unknown TLV, do not Forward"},
335   {3, "Unknown TLV, do Forward"},
336   {0, NULL}
337 };
338
339 #define WILDCARD_FEC    1
340 #define PREFIX_FEC      2
341 #define HOST_FEC        3
342 #define CRLSP_FEC       4
343 #define VC_FEC          0x80    /* draft-martini-l2circuit-trans-mpls */
344
345 static const value_string fec_types[] = {
346   {WILDCARD_FEC, "Wildcard FEC"},
347   {PREFIX_FEC, "Prefix FEC"},
348   {HOST_FEC, "Host Address FEC"},
349   {CRLSP_FEC, "CR LSP FEC"},
350   {VC_FEC, "Virtual Circuit FEC"},
351   {0, NULL}
352 };
353
354
355 static const value_string fec_vc_types_vals[] = {
356   {0x0001, "Frame Relay DLCI"},
357   {0x0002, "ATM VCC transport"},
358   {0x0003, "ATM VPC transport"},
359   {0x0004, "Ethernet VLAN"},
360   {0x0005, "Ethernet"},
361   {0x0006, "HDLC"},
362   {0x0007, "PPP"},
363   {0x0008, "SONET/SDH Circuit Emulation Service"},
364   {0x0009, "ATM n-to-one VCC cell transport"},
365   {0x000A, "ATM n-to one VPC cell transport"},
366   {0x000B, "IP layer2 transport"},
367   {0x000C, "ATM one-to-one VCC Cell Mode"},
368   {0x000D, "ATM one-to-one VPC Cell Mode"},
369   {0x000E, "ATM AAL5 PDU VCC transport"},
370   {0x000F, "Frame-Relay Port mode"},
371   {0x0010, "SONET/SDH Circuit Emulation over Packet"},
372   {0, NULL}
373 };
374
375
376 #define FEC_VC_INTERFACEPARAM_MTU          0x01
377 #define FEC_VC_INTERFACEPARAM_MAXCATMCELLS 0x02
378 #define FEC_VC_INTERFACEPARAM_DESCRIPTION  0x03
379 #define FEC_VC_INTERFACEPARAM_CEMBYTES     0x04
380 #define FEC_VC_INTERFACEPARAM_CEMOPTIONS   0x05
381 #define FEC_VC_INTERFACEPARAM_VPNID        0x06
382 #define FEC_VC_INTERFACEPARAM_TDMBPS       0x07
383 #define FEC_VC_INTERFACEPARAM_FRDLCILEN    0x08
384
385
386
387 static const value_string fec_vc_interfaceparm[] = {
388   {FEC_VC_INTERFACEPARAM_MTU, "MTU"},
389   {FEC_VC_INTERFACEPARAM_MAXCATMCELLS, "Max Concatenated ATM cells"},
390   {FEC_VC_INTERFACEPARAM_DESCRIPTION, "Interface Description"},
391   {FEC_VC_INTERFACEPARAM_CEMBYTES, "CEM Payload Bytes"},
392   {FEC_VC_INTERFACEPARAM_CEMOPTIONS, "CEM options"},
393   {FEC_VC_INTERFACEPARAM_VPNID, "VPN Id"},
394   {FEC_VC_INTERFACEPARAM_TDMBPS, "CEP/TDM bit-rate"},
395   {FEC_VC_INTERFACEPARAM_FRDLCILEN, "Frame-Relay DLCI Length"},
396   {0, NULL},
397 };
398
399 static const true_false_string fec_vc_cbit = {
400   "Contorl Word Present",
401   "Control Word NOT Present"
402 };
403
404
405
406 static const value_string tlv_atm_merge_vals[] = {
407   {0, "Merge not supported"},
408   {1, "VP merge supported"},
409   {2, "VC merge supported"},
410   {3, "VP & VC merge supported"},
411   {0, NULL}
412 };
413
414 static const value_string tlv_atm_vbits_vals[] = {
415   {0, "VPI & VCI Significant"},
416   {1, "Only VPI Significant"},
417   {2, "Only VCI Significant"},
418   {3, "VPI & VCI not Significant, nonsense"},
419   {0, NULL}
420 };
421
422 static const value_string tlv_fr_merge_vals[] = {
423   {0, "Merge not supported"},
424   {1, "Merge supported"},
425   {2, "Unspecified"},
426   {3, "Unspecified"},
427   {0, NULL}
428 };
429
430 static const value_string tlv_fr_len_vals[] = {
431   {0, "10 bits"},
432   {1, "Reserved"},
433   {2, "23 bits"},
434   {3, "Reserved"},
435   {0, NULL}
436 };
437
438 static const value_string ldp_act_flg_vals[] = {
439   {0, "indicates initial LSP setup"},
440   {1, "indicates modify LSP"},
441   {0, NULL}
442 };
443
444 static const value_string route_pinning_vals[] = {
445   {0, "route pinning is not requested"},
446   {1, "route pinning is requested"},
447   {0, NULL}
448 };
449
450 static const value_string diffserv_type_vals[] = {
451   {0, "E-LSP"},
452   {1, "L-LSP"},
453   {0, NULL}
454 };
455
456 static const value_string ldp_loose_vals[] = {
457   {0, "strict hop"},
458   {1, "loose hop"},
459   {0, NULL}
460 };
461
462 static const true_false_string tlv_negotiable = {
463   "Negotiable",
464   "Not negotiable"
465 };
466
467 static const value_string freq_values[] = {
468   {0, "Unspecified"},
469   {1, "Frequent"},
470   {2, "VeryFrequent"},
471   {0, NULL}
472 };
473
474 static const true_false_string tlv_atm_dirbit = {
475   "Bidirectional capability",
476   "Unidirectional capability"
477 };
478
479 static const true_false_string hello_requested_vals = {
480   "Source requests periodic hellos",
481   "Source does not request periodic hellos"
482 };
483
484 static const true_false_string tlv_sess_advbit_vals = {
485   "Downstream On Demand proposed",
486   "Downstream Unsolicited proposed"
487 };
488
489 static const true_false_string tlv_sess_ldetbit_vals = {
490   "Loop Detection Enabled",
491   "Loop Detection Disabled"
492 };
493
494 static const true_false_string tlv_status_ebit = {
495   "Fatal Error Notification",
496   "Advisory Notification"
497 };
498
499 static const true_false_string tlv_status_fbit = {
500   "Notification should be Forwarded",
501   "Notification should NOT be Forwarded"
502 };
503
504 static const value_string tlv_status_data[] = {
505   {0, "Success"},
506   {1, "Bad LDP Identifier"},
507   {2, "Bad Protocol Version"},
508   {3, "Bad PDU Length"},
509   {4, "Unknown Message Type"},
510   {5, "Bad Message Length"},
511   {6, "Unknown TLV"},
512   {7, "Bad TLV Length"},
513   {8, "Malformed TLV Value"},
514   {9, "Hold Timer Expired"},
515   {10, "Shutdown"},
516   {11, "Loop Detected"},
517   {12, "Unknown FEC"},
518   {13, "No Route"},
519   {14, "No Label Resources"},
520   {15, "Label Resources / Available"},
521   {16, "Session Rejected / No Hello"},
522   {17, "Session Rejected / Parameters Advertisement Mode"},
523   {18, "Session Rejected / Parameters Max PDU Length"},
524   {19, "Session Rejected / Parameters Label Range"},
525   {20, "KeepAlive Timer Expired"},
526   {21, "Label Request Aborted"},
527   {22, "Missing Message Parameters"},
528   {23, "Unsoported Address Family"},
529   {24, "Session Rejected / Bad KeepAlive Time"},
530   {25, "Internal Error"},
531   {0x01000001,"Unexpected Diff-Serv TLV"},
532   {0x01000002,"Unsupported PHB"},
533   {0x01000003,"Invalid EXP<->PHB Mapping"},
534   {0x01000004,"Unsupported PSC"},
535   {0x01000005,"Per-LSP context allocation failure"},
536   {0x04000001,"Bad Explicit Routing TLV Error"},
537   {0x04000002,"Bad Strict Node Error"},
538   {0x04000003,"Bad Strict Node Error"},
539   {0x04000004,"Bad Initial ER-Hop Error"},
540   {0x04000005,"Resource Unavailable"},
541   {0x04000006,"Traffic Parameters Unavailable"},
542   {0x04000007,"LSP Preempted"},
543   {0x04000008,"Modify Request Not Supported"},
544   {0x20000001,"Illegal C-Bit"},
545   {0x20000002,"Wrong C-Bit"},
546   {0, NULL}
547 };
548
549 /* Define storage class for a string handler function
550  * with a const guint8 * argument, and returning a gchar *
551  */
552 typedef gchar *(string_handler_func)(const guint8 *);
553
554 /* Default handler for address to string conversion */
555 static gchar *
556 default_str_handler(const guint8 * bytes _U_)
557 {
558         return "<Support for this Address Family not implemented>";
559 }
560         
561 /* Dissect FEC TLV */
562
563 static void
564 dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
565 {
566         proto_tree *ti=NULL, *val_tree=NULL, *fec_tree=NULL, *vcintparam_tree=NULL;
567         guint16 family, ix=1, ax;
568         guint8  addr_size=0, *addr, implemented, prefix_len_octets, prefix_len, host_len, vc_len;
569         guint8  intparam_len;
570         string_handler_func *str_handler = default_str_handler;
571         char *str;
572
573         if (tree) {
574                 ti=proto_tree_add_text(tree, tvb, offset, rem, "FEC Elements");
575                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
576                 if(val_tree == NULL) return;
577
578                 while (rem > 0){
579                         switch (tvb_get_guint8(tvb, offset)) {
580                         case WILDCARD_FEC:
581                         case CRLSP_FEC:
582                                 ti = proto_tree_add_text(val_tree, tvb, offset, 1, "FEC Element %u", ix);
583                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
584                                 if(fec_tree == NULL) return;
585                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 1, FALSE);
586                                 rem -= 1;
587                                 offset += 1;
588                                 break;
589
590                         case PREFIX_FEC:
591                                 if( rem < 4 ){/*not enough*/
592                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
593                                         return;
594                                 }
595                                 family=tvb_get_ntohs(tvb, offset+1);
596                                 prefix_len=tvb_get_guint8(tvb, offset+3);
597                                 prefix_len_octets=(prefix_len+7)/8;
598
599                                 implemented=1;
600                                 switch(family) {
601                                         case AFNUM_INET: /*IPv4*/
602                                                 addr_size=4;
603                                                 str_handler=ip_to_str;
604                                                 break;
605                                         case AFNUM_INET6: /*IPv6*/
606                                                 addr_size=16;
607                                                 str_handler = (string_handler_func *) ip6_to_str;
608                                                 break;
609                                         default:
610                                                 implemented=0;
611                                                 break;
612                                 }
613
614                                 if( !implemented ) {
615                                         guint16 noctets;
616
617                                         noctets= rem>4+prefix_len_octets?4+prefix_len_octets:rem;
618                                         proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
619                                         offset+=noctets;
620                                         rem-=noctets;
621                                         break;
622                                 }
623
624                                 if( rem < 4+MIN(addr_size, prefix_len_octets) ){
625                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
626                                         return;
627                                 }
628
629                                 /*Add a subtree for this*/
630                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4+MIN(addr_size, prefix_len_octets), "FEC Element %u", ix);
631                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
632                                 if(fec_tree == NULL) return;
633                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
634                                 offset += 1;
635
636                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
637                                 offset += 2;
638
639                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
640                                 offset += 1;
641
642
643                                 if( addr_size < prefix_len_octets) {
644                                         offset+=addr_size;
645                                         rem-=addr_size;
646                                         proto_tree_add_text(fec_tree, tvb, offset-1, 1, "Invalid prefix %u length for family %s", prefix_len, val_to_str(family, afn_vals, "Unknown Family"));
647                                         break;
648                                 }
649
650                                 if( (addr=g_malloc0(addr_size)) == NULL ){
651                                         /*big big trouble, no mem or bad addr_size*/
652                                         fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
653                                         return;
654                                 }
655
656                                 for(ax=0; ax+1 <= prefix_len_octets; ax++)
657                                         addr[ax]=tvb_get_guint8(tvb, offset+ax);
658                                 if( prefix_len % 8 )
659                                         addr[ax-1] = addr[ax-1]&(0xFF<<(8-prefix_len%8));
660
661                                 str = str_handler((const guint8 *)addr);
662                                 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, prefix_len_octets, str, "Prefix: %s", str);
663
664                                 offset += prefix_len_octets;
665                                 rem -= 4+prefix_len_octets;
666                                 g_free(addr);
667                                 break;
668
669                         case HOST_FEC:
670                                 if( rem < 4 ){/*not enough*/
671                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
672                                         return;
673                                 }
674                                 family=tvb_get_ntohs(tvb, offset+1);
675                                 host_len=tvb_get_guint8(tvb, offset+3);
676
677                                 implemented=1;
678                                 switch(family) {
679                                         case AFNUM_INET: /*IPv4*/
680                                                 addr_size=4;
681                                                 str_handler=ip_to_str;
682                                                 break;
683                                         case AFNUM_INET6: /*IPv6*/
684                                                 addr_size=16;
685                                                 str_handler = (string_handler_func *) ip6_to_str;
686                                                 break;
687                                         default:
688                                                 implemented=0;
689                                                 break;
690                                 }
691
692                                 if( !implemented ) {
693                                         guint16 noctets;
694
695                                         noctets= rem>4+host_len?4+host_len:rem;
696                                         proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
697                                         offset+=noctets;
698                                         rem-=noctets;
699                                         break;
700                                 }
701
702                                 if( rem < 4+addr_size ){
703                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
704                                         return;
705                                 }
706
707                                 /*Add a subtree for this*/
708                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4+addr_size, "FEC Element %u", ix);
709                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
710                                 if(fec_tree == NULL) return;
711                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
712                                 offset += 1;
713
714                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
715                                 offset += 2;
716
717                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
718                                 offset += 1;
719
720
721                                 if( addr_size != host_len) {
722                                         offset+=addr_size;
723                                         rem-=addr_size;
724                                         proto_tree_add_text(fec_tree, tvb, offset-1, 1, "Invalid address length %u length for family %s", host_len, val_to_str(family, afn_vals, "Unknown Family"));
725                                         break;
726                                 }
727
728                                 if( (addr=g_malloc0(addr_size)) == NULL ){
729                                         /*big big xtrouble, no mem or bad addr_size*/
730                                         fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
731                                         return;
732                                 }
733
734                                 for(ax=0; ax+1 <= host_len; ax++)
735                                         addr[ax]=tvb_get_guint8(tvb, offset+ax);
736
737                                 str = str_handler((const guint8 *)addr);
738                                 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_hoval, tvb, offset, host_len, str, "Address: %s", str);
739
740                                 offset += host_len;
741                                 rem -= 4+host_len;
742                                 g_free(addr);
743                                 break;
744
745                         case VC_FEC:
746                           if( rem < 8 ){/*not enough bytes for a minimal VC_FEC*/
747                             proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
748                             return;
749                           }
750                           vc_len = tvb_get_guint8 (tvb, offset+3);
751
752
753                           ti = proto_tree_add_text(val_tree, tvb, offset, 8+vc_len, "FEC Element %u", ix);
754                           fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
755                           if(fec_tree == NULL) return;
756                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
757                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_controlword, tvb, offset+1, 1, FALSE);
758                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vctype, tvb, offset+1, 2, FALSE);
759                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_infolength, tvb, offset+3,1,FALSE);
760                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_groupid,tvb, offset +4, 4, FALSE);
761                           rem -=8;
762                           offset +=8;
763
764                           if ( (vc_len > 3) && ( rem > 3 ) ) { /* there is enough room for vcid */
765                             proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vcid,tvb, offset, 4, FALSE);
766                             proto_item_append_text (ti," VCID: %u",tvb_get_ntohl(tvb,offset));
767
768                           } else {
769                             proto_tree_add_text(val_tree,tvb,offset +4, 8 +vc_len, "VC FEC size format error");
770                             return;
771                           }
772                           rem -= 4;
773                           vc_len -= 4;
774                           offset += 4;
775
776                           while ( (vc_len > 1) && (rem > 1) ) { /* enough to include id and length */
777                             intparam_len = tvb_get_guint8(tvb, offset+1);
778                             ti = proto_tree_add_text(fec_tree, tvb, offset, intparam_len, "Interface Paramameter");
779                             vcintparam_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam);
780                             if(vcintparam_tree == NULL) return;
781                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_id,tvb,offset,1,FALSE);
782                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_length,tvb, offset+1, 1, FALSE);
783                             if ( (vc_len -intparam_len) <0 && (rem -intparam_len) <0 ) { /* error condition */
784                               proto_tree_add_text(vcintparam_tree, tvb, offset +2, MIN(vc_len,rem), "malformed data");
785                               return;
786                             }
787                             switch (tvb_get_guint8(tvb, offset)) {
788                             case FEC_VC_INTERFACEPARAM_MTU:
789                               proto_item_append_text(ti,": MTU %u", tvb_get_ntohs(tvb,offset+2));
790                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_mtu,tvb, offset+2, 2, FALSE);
791                               break;
792                             case FEC_VC_INTERFACEPARAM_TDMBPS:
793                               proto_item_append_text(ti,": BPS %u", tvb_get_ntohs(tvb,offset+2));
794                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmbps,tvb, offset+2, 2, FALSE);
795                               break;
796                             case FEC_VC_INTERFACEPARAM_MAXCATMCELLS:
797                               proto_item_append_text(ti,": Max ATM Concat Cells %u", tvb_get_ntohs(tvb,offset+2));
798                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_maxcatmcells,tvb, offset+2, 2, FALSE);
799                               break;
800                             case FEC_VC_INTERFACEPARAM_DESCRIPTION:
801                               proto_item_append_text(ti,": Description");
802                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_desc,tvb, offset+2, (intparam_len -2), FALSE);
803                               break;
804                             case FEC_VC_INTERFACEPARAM_CEMBYTES:
805                               proto_item_append_text(ti,": CEM Payload Bytes %u", tvb_get_ntohs(tvb,offset+2));
806                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_cembytes,tvb, offset+2, 2, FALSE);
807                               break;
808                             case FEC_VC_INTERFACEPARAM_VPNID:
809                               /* draft-lasserre-tls-mpls-00.txt */
810                               proto_item_append_text(ti,": VPN Id");
811                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_vpnid_oui, tvb, offset+2, 3, FALSE);
812                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_vpnid_index, tvb, offset+5, 4, FALSE);
813                               break;
814                             case FEC_VC_INTERFACEPARAM_CEMOPTIONS:
815                                 /* draft-malis-sonet-ces-mpls CEM options still undefined */
816                             default: /* unknown */
817                               proto_item_append_text(ti," unknown");
818                               proto_tree_add_text(vcintparam_tree,tvb, offset+2, (intparam_len -2), "Unknown data");
819
820                               return;
821                             }
822                             rem -= intparam_len;
823                             vc_len -= intparam_len;
824                             offset += intparam_len;
825                           }
826                           break;
827
828                         default:  /* Unknown */
829                         /* XXX - do all FEC's have a length that's a multiple of 4? */
830                         /* Hmmm, don't think so. Will check. RJS. */
831                         /* If we don't know its structure, we have to exit */
832                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4, "FEC Element %u", ix);
833                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
834                                 if(fec_tree == NULL) return;
835                                 proto_tree_add_text(fec_tree, tvb, offset, rem, "Unknown FEC TLV type");
836                                 return;
837                         }
838                         ix++;
839                 }
840         }
841 }
842
843 /* Dissect Address List TLV */
844
845 static void
846 dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
847 {
848         proto_tree *ti = NULL, *val_tree = NULL;
849         guint16 family, ix;
850         guint8  addr_size, *addr;
851         string_handler_func *str_handler = default_str_handler;
852         char *str;
853
854         if (tree) {
855                 if( rem < 2 ) {
856                         proto_tree_add_text(tree, tvb, offset, rem,
857                             "Error processing Address List TLV: length is %d, should be >= 2",
858                             rem);
859                         return;
860                 }
861
862                 family=tvb_get_ntohs(tvb, offset);
863                 proto_tree_add_item(tree, hf_ldp_tlv_addrl_addr_family, tvb,
864                                          offset, 2, FALSE);
865                 switch(family) {
866                         case AFNUM_INET: /*IPv4*/
867                                 addr_size=4;
868                                 str_handler=ip_to_str;
869                                 break;
870                         case AFNUM_INET6: /*IPv6*/
871                                 addr_size=16;
872                                 str_handler = (string_handler_func *) ip6_to_str;
873                                 break;
874                         default:
875                                 proto_tree_add_text(tree, tvb, offset+2, rem-2,
876                                  "Support for Address Family not implemented");
877                                 return;
878                 }
879
880                 offset+=2; rem-=2;
881                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Addresses");
882                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
883
884                 if(val_tree == NULL) return;
885                 if( (addr=g_malloc(addr_size)) == NULL ){
886                         /*big big trouble*/
887                         fprintf(stderr, "packet-ldp: dissect_tlv_address_list() malloc failed\n");
888                         return;
889                 }
890
891                 for(ix=1; rem >= addr_size; ix++, offset += addr_size,
892                                                          rem -= addr_size) {
893                         if( (tvb_memcpy(tvb, addr, offset, addr_size))
894                                                          == NULL)
895                                 break;
896
897                         str = str_handler((const guint8 *)addr);
898                         proto_tree_add_string_format(val_tree,
899                             hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
900                             "Address %u: %s", ix, str);
901                 }
902                 if(rem)
903                         proto_tree_add_text(val_tree, tvb, offset, rem,
904                             "Error processing TLV: Extra data at end of address list");
905                 g_free(addr);
906         }
907 }
908
909 /* Dissect Path Vector TLV */
910
911 static void
912 dissect_tlv_path_vector(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
913 {
914         proto_tree *ti = NULL, *val_tree = NULL;
915         guint8  ix;
916         guint32 addr;
917
918         if (tree) {
919                 ti=proto_tree_add_text(tree, tvb, offset, rem, "LSR IDs");
920                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
921
922                 if(val_tree == NULL) return;
923
924                 for(ix=1; rem >= 4; ix++, offset += 4, rem -= 4) {
925                         tvb_memcpy(tvb, (guint8 *)&addr, offset, 4);
926                         proto_tree_add_ipv4_format(val_tree,
927                             hf_ldp_tlv_pv_lsrid, tvb, offset, 4,
928                             addr, "LSR Id %u: %s", ix,
929                             ip_to_str((guint8 *)&addr));
930                 }
931                 if(rem)
932                         proto_tree_add_text(val_tree, tvb, offset, rem,
933                             "Error processing TLV: Extra data at end of path vector");
934         }
935 }
936
937 /* Dissect ATM Label TLV */
938
939 static void
940 dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
941 {
942         proto_tree *ti = NULL, *val_tree = NULL;
943         guint16 id;
944
945         if(tree) {
946                 if(rem != 4){
947                         proto_tree_add_text(tree, tvb, offset, rem,
948                             "Error processing ATM Label TLV: length is %d, should be 4",
949                             rem);
950                         return;
951                 }
952                 ti=proto_tree_add_text(tree, tvb, offset, rem, "ATM Label");
953                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
954                 if(val_tree == NULL) return;
955
956                 proto_tree_add_item(val_tree, hf_ldp_tlv_atm_label_vbits, tvb, offset, 1, FALSE);
957
958                 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
959                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id);
960
961                 id=tvb_get_ntohs(tvb, offset+2);
962                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id);
963         }
964 }
965
966 /* Dissect FRAME RELAY Label TLV */
967
968 static void
969 dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
970 {
971         proto_tree *ti = NULL, *val_tree = NULL;
972         guint8  len;
973         guint32 id;
974
975         if(tree) {
976                 if(rem != 4){
977                         proto_tree_add_text(tree, tvb, offset, rem,
978                             "Error processing Frame Relay Label TLV: length is %d, should be 4",
979                             rem);
980                         return;
981                 }
982                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Frame Relay Label");
983                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
984                 if(val_tree == NULL) return;
985
986                 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
987                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_fr_label_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len);
988
989                 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
990                 proto_tree_add_uint_format(val_tree,
991                 hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id);
992         }
993 }
994
995 /* Dissect STATUS TLV */
996
997 static void
998 dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
999 {
1000         proto_tree *ti = NULL, *val_tree = NULL;
1001         guint32 data;
1002
1003         if(tree) {
1004                 if(rem != 10){
1005                         proto_tree_add_text(tree, tvb, offset, rem,
1006                             "Error processing Status TLV: length is %d, should be 10",
1007                             rem);
1008                         return;
1009                 }
1010
1011                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Status");
1012                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1013                 if(val_tree == NULL) return;
1014
1015                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE);
1016                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE);
1017
1018                 data=tvb_get_ntohl(tvb, offset)&0x3FFFFFFF;
1019                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_status_data, tvb, offset, 4, data, "Status Data: %s (0x%X)", val_to_str(data, tlv_status_data, "Unknown Status Data"), data);
1020
1021                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE);
1022                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE);
1023         }
1024 }
1025
1026 /* Dissect Returned PDU TLV */
1027
1028 static void
1029 dissect_tlv_returned_pdu(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1030 {
1031         proto_tree *ti = NULL, *val_tree = NULL;
1032
1033         if(tree) {
1034                 if(rem < 10){
1035                         proto_tree_add_text(tree, tvb, offset, rem,
1036                             "Error processing Returned PDU TLV: length is %d, should be >= 10",
1037                             rem);
1038                         return;
1039                 }
1040                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned PDU");
1041                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1042                 if(val_tree == NULL) return;
1043
1044                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE);
1045                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE);
1046                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE);
1047                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE);
1048                 offset += 10;
1049                 rem -= 10;
1050
1051                 if( rem > 0 ) {
1052                 /*XXX - dissect returned pdu data*/
1053                         proto_tree_add_text(val_tree, tvb, offset, rem, "Returned PDU Data");
1054                 }
1055         }
1056 }
1057
1058 /* Dissect Returned MESSAGE TLV */
1059
1060 static void
1061 dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1062 {
1063         proto_tree *ti = NULL, *val_tree = NULL;
1064         guint16 type;
1065
1066         if(tree) {
1067                 if(rem < 4){
1068                         proto_tree_add_text(tree, tvb, offset, rem,
1069                             "Error processing Returned Message TLV: length is %d, should be >= 4",
1070                             rem);
1071                         return;
1072                 }
1073                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned Message");
1074                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1075                 if(val_tree == NULL) return;
1076
1077                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE);
1078
1079                 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
1080                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_returned_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type);
1081
1082                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE);
1083                 offset += 4;
1084                 rem -= 4;
1085
1086                 if( rem >= 4  ) { /*have msg_id*/
1087                         proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE);
1088                         offset += 4;
1089                         rem -= 4;
1090                 }
1091
1092                 if( rem > 0 ) {
1093                 /*XXX - dissect returned msg parameters*/
1094                         proto_tree_add_text(val_tree, tvb, offset, rem, "Returned Message Parameters");
1095                 }
1096         }
1097 }
1098
1099 /* Dissect the common hello params */
1100
1101 static void
1102 #if 0
1103 dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1104 #else
1105 dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree)
1106 #endif
1107 {
1108 #if 0
1109         proto_tree *ti = NULL;
1110 #endif
1111         proto_tree *val_tree = NULL;
1112
1113         if (tree) {
1114 #if 0
1115                 ti = proto_tree_add_item(tree, hf_ldp_tlv_value, tvb, offset, rem, FALSE);
1116                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1117                 if(val_tree == NULL) return;
1118 #else
1119                 val_tree=tree;
1120 #endif
1121                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
1122                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 2, FALSE);
1123                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 2, FALSE);
1124                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_res, tvb, offset + 2, 2, FALSE);
1125         }
1126 }
1127
1128 /* Dissect MAC TLV */
1129
1130 static void
1131 dissect_tlv_mac(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1132 {
1133         proto_tree *ti = NULL, *val_tree = NULL;
1134         guint8  ix;
1135         const guint8 *mac;
1136
1137         if (tree) {
1138                 ti=proto_tree_add_text(tree, tvb, offset, rem, "MAC addresses");
1139                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1140
1141                 if(val_tree == NULL) return;
1142
1143                 for(ix=1; rem >= 6; ix++, offset += 6, rem -= 6) {
1144                         mac = tvb_get_ptr(tvb, offset, 6);
1145                         proto_tree_add_ether(val_tree,
1146                              hf_ldp_tlv_mac, tvb, offset, 6, mac);
1147                 }
1148                 if(rem)
1149                         proto_tree_add_text(val_tree, tvb, offset, rem,
1150                             "Error processing TLV: Extra data at end of path vector");
1151         }
1152 }
1153
1154
1155
1156 /* Dissect the common session params */
1157
1158 static void
1159 dissect_tlv_common_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1160 {
1161         proto_tree *ti = NULL, *val_tree = NULL;
1162
1163         if (tree != NULL) {
1164                 if( rem != 14) { /*length of Comm Sess Parms tlv*/
1165                         proto_tree_add_text(tree, tvb, offset, rem,
1166                             "Error processing Common Session Parameters TLV: length is %d, should be 14",
1167                             rem);
1168                         return;
1169                 }
1170                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
1171                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1172
1173                 if(val_tree != NULL) {
1174                         /*Protocol Version*/
1175                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE);
1176
1177                         /*KeepAlive Time*/
1178                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ka, tvb,offset + 2, 2, FALSE);
1179
1180                         /*A bit*/
1181                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_advbit,tvb, offset + 4, 1, FALSE);
1182
1183                         /*D bit*/
1184                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ldetbit,tvb, offset + 4, 1, FALSE);
1185
1186                         /*Path Vector Limit*/
1187                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_pvlim,tvb, offset + 5, 1, FALSE);
1188
1189                         /*Max PDU Length*/
1190                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_mxpdu,tvb, offset + 6, 2, FALSE);
1191
1192                         /*Rx LSR*/
1193                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxlsr,tvb, offset + 8, 4, FALSE);
1194
1195                         /*Rx LS*/
1196                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxls,tvb, offset + 12, 2, FALSE);
1197                 }
1198         }
1199 }
1200
1201 /* Dissect the atm session params */
1202
1203 static void
1204 dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1205 {
1206         proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1207         guint8 numlr, ix;
1208         guint16 id;
1209
1210         if (tree != NULL) {
1211                 if(rem < 4) {
1212                         proto_tree_add_text(tree, tvb, offset, rem,
1213                             "Error processing ATM Parameters TLV: length is %d, should be >= 4",
1214                             rem);
1215                         return;
1216                 }
1217
1218                 ti = proto_tree_add_text(tree, tvb, offset, rem,"ATM Parameters");
1219                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1220
1221                 if(val_tree != NULL) {
1222                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE);
1223
1224                         /*get the number of label ranges*/
1225                         numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1226                         proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_atm_lr,
1227                         tvb, offset, 1, numlr, "Number of Label Range components: %u",
1228                         numlr);
1229
1230                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE);
1231
1232                         /*move into range components*/
1233                         offset += 4;
1234                         rem -= 4;
1235                         ti = proto_tree_add_text(val_tree, tvb, offset, rem,"ATM Label Range Components");
1236
1237                         if(numlr) {
1238                                 val_tree=proto_item_add_subtree(ti,ett_ldp_tlv_val);
1239                                 if( ! val_tree ) return;
1240                         }
1241                         /*now dissect ranges*/
1242                         for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1243                                 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1244                                  "ATM Label Range Component %u", ix);
1245                                 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1246
1247                                 if( lbl_tree == NULL ) break;
1248
1249                                 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
1250                                 proto_tree_add_uint_format(lbl_tree,
1251                                     hf_ldp_tlv_sess_atm_minvpi,
1252                                     tvb, offset, 2,
1253                                     id, "Minimum VPI: %u", id);
1254                                 id=tvb_get_ntohs(tvb, offset+4)&0x0FFF;
1255                                 proto_tree_add_uint_format(lbl_tree,
1256                                     hf_ldp_tlv_sess_atm_maxvpi,
1257                                     tvb, (offset+4), 2, id,
1258                                     "Maximum VPI: %u", id);
1259
1260                                 id=tvb_get_ntohs(tvb, offset+2);
1261                                 proto_tree_add_uint_format(lbl_tree,
1262                                     hf_ldp_tlv_sess_atm_minvci,
1263                                     tvb, offset+2, 2,
1264                                     id, "Minimum VCI: %u", id);
1265                                 id=tvb_get_ntohs(tvb, offset+6);
1266                                 proto_tree_add_uint_format(lbl_tree,
1267                                     hf_ldp_tlv_sess_atm_maxvci,
1268                                     tvb, offset+6, 2,
1269                                     id, "Maximum VCI: %u", id);
1270
1271                                 offset += 8;
1272                         }
1273                         if( rem || numlr)
1274                                 proto_tree_add_text(val_tree, tvb, offset, rem,
1275                                     "Error processing TLV: Extra data at end of TLV");
1276                 }
1277         }
1278 }
1279
1280 /* Dissect the frame relay session params */
1281
1282 static void
1283 dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
1284 {
1285         proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1286         guint8 numlr, ix, len;
1287         guint32 id;
1288
1289         if (tree != NULL) {
1290                 if(rem < 4) {
1291                         proto_tree_add_text(tree, tvb, offset, rem,
1292                             "Error processing Frame Relay Parameters TLV: length is %d, should be >= 4",
1293                             rem);
1294                         return;
1295                 }
1296
1297                 ti = proto_tree_add_text(tree, tvb, offset, rem,
1298                                                  "Frame Relay Parameters");
1299                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1300
1301                 if(val_tree != NULL) {
1302                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_merge,
1303                                 tvb, offset, 1, FALSE);
1304
1305                         /*get the number of label ranges*/
1306                         numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1307                         proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_fr_lr,
1308                         tvb, offset, 1, numlr, "Number of Label Range components: %u",
1309                         numlr);
1310
1311                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_dir,
1312                                  tvb, offset, 1, FALSE);
1313
1314                         /*move into range components*/
1315                         offset += 4;
1316                         rem -= 4;
1317                         ti = proto_tree_add_text(val_tree, tvb, offset, rem,
1318                                  "Frame Relay Label Range Components");
1319
1320                         if(numlr) {
1321                                 val_tree=proto_item_add_subtree(ti,
1322                                                          ett_ldp_tlv_val);
1323                                 if( ! val_tree ) return;
1324                         }
1325
1326                         /*now dissect ranges*/
1327                         for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1328                                 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1329                                 "Frame Relay Label Range Component %u", ix);
1330                                 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1331
1332                                 if( lbl_tree == NULL ) break;
1333
1334                                 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
1335                                 proto_tree_add_uint_format(lbl_tree, hf_ldp_tlv_sess_fr_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len);
1336
1337                                 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
1338                                 proto_tree_add_uint_format(lbl_tree,
1339                         hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id);
1340                                 id=tvb_get_ntoh24(tvb, offset+5)&0x7FFFFF;
1341                                 proto_tree_add_uint_format(lbl_tree,
1342                         hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id);
1343
1344                                 offset += 8;
1345                         }
1346
1347                         if( rem || numlr)
1348                                 proto_tree_add_text(val_tree, tvb, offset, rem,
1349                                  "Error processing TLV: Extra data at end of TLV");
1350                 }
1351         }
1352 }
1353
1354
1355 static void
1356 dissect_tlv_lspid(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
1357 {
1358         proto_tree *ti = NULL, *val_tree = NULL;
1359
1360         if (tree != NULL) {
1361                 if(rem != 8) {
1362                         proto_tree_add_text(tree, tvb, offset, rem,
1363                             "Error processing LSP ID TLV: length is %d, should be 8",
1364                             rem);
1365                         return;
1366                 }
1367
1368                 ti = proto_tree_add_text(tree, tvb, offset, rem,
1369                                                 "LSP ID");
1370                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1371
1372                 if(val_tree != NULL) {
1373                         proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_act_flg,
1374                                            tvb, offset, 2, FALSE);
1375                         offset += 2;
1376                         proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_cr_lsp,
1377                                            tvb, offset, 2, FALSE);
1378                         offset += 2;
1379                         proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_ldpid,
1380                                            tvb, offset, 4, FALSE);
1381                 }
1382         }
1383 }
1384
1385 static void
1386 dissect_tlv_er_hop_ipv4(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1387 {
1388         proto_tree *ti = NULL, *val_tree = NULL;
1389
1390
1391         if (tree != NULL) {
1392                 if(rem != 8) {
1393                         proto_tree_add_text(tree, tvb, offset, rem,
1394                             "Error processing ER HOP IPv4 TLV: length is %d, should be 8",
1395                             rem);
1396                         return;
1397                 }
1398                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv4");
1399                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1400
1401                 if(val_tree != NULL) {
1402                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1403                                            tvb, offset, 3, FALSE);
1404                         offset += 3;
1405                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
1406                                            tvb, offset, 1, FALSE);
1407                         offset ++;
1408                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix4,
1409                                            tvb, offset, 4, FALSE);
1410                 }
1411         }
1412 }
1413
1414 static void
1415 dissect_tlv_er_hop_ipv6(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1416 {
1417         proto_tree *ti = NULL, *val_tree = NULL;
1418
1419         if (tree != NULL) {
1420                 if(rem != 20) {
1421                         proto_tree_add_text(tree, tvb, offset, rem,
1422                             "Error processing ER HOP IPv6 TLV: length is %d, should be 20",
1423                             rem);
1424                         return;
1425                 }
1426                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv6");
1427                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1428
1429                 if(val_tree != NULL) {
1430                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1431                                            tvb, offset, 3, FALSE);
1432                         offset += 3;
1433                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
1434                                           tvb, offset, 1, FALSE);
1435                         offset ++;
1436                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix6,
1437                                            tvb, offset, 16, FALSE);
1438                 }
1439         }
1440 }
1441
1442 static void
1443 dissect_tlv_er_hop_as(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1444 {
1445         proto_tree *ti = NULL, *val_tree = NULL;
1446
1447         if (tree != NULL) {
1448                 if(rem != 4) {
1449                         proto_tree_add_text(tree, tvb, offset, rem,
1450                             "Error processing ER HOP AS TLV: length is %d, should be 4",
1451                             rem);
1452                         return;
1453                 }
1454                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP AS");
1455                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1456
1457                 if(val_tree != NULL) {
1458                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1459                                            tvb, offset, 2, FALSE);
1460                         offset += 2;
1461                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_as,
1462                                            tvb, offset, 2, FALSE);
1463                 }
1464         }
1465 }
1466
1467 static void
1468 dissect_tlv_er_hop_lspid(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1469 {
1470         proto_tree *ti = NULL, *val_tree = NULL;
1471
1472         if (tree != NULL) {
1473                 if(rem != 8) {
1474                         proto_tree_add_text(tree, tvb, offset, rem,
1475                             "Error processing ER HOP LSPID TLV: length is %d, should be 8",
1476                             rem);
1477                         return;
1478                 }
1479                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP LSPID");
1480                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1481
1482                 if(val_tree != NULL) {
1483                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1484                                            tvb, offset, 2, FALSE);
1485                         offset += 2;
1486                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_cr_lsp,
1487                                            tvb, offset, 2, FALSE);
1488                         offset += 2;
1489                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_ldpid,
1490                                            tvb, offset, 4, FALSE);
1491                 }
1492         }
1493 }
1494
1495 static void
1496 dissect_tlv_traffic(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1497 {
1498         proto_tree *ti = NULL, *val_tree = NULL;
1499         guint8  val_8;
1500         float   val_f;
1501         proto_item *pi;
1502
1503         if (tree != NULL) {
1504                 if(rem != 24) {
1505                         proto_tree_add_text(tree, tvb, offset, rem,
1506                             "Error processing Traffic Parameters TLV: length is %d, should be 24",
1507                             rem);
1508                         return;
1509                 }
1510                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Traffic parameters");
1511                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1512
1513                 if(val_tree != NULL) {
1514                         /* flags */
1515                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_reserv, tvb, offset, 1, FALSE);
1516                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_weight, tvb, offset, 1, FALSE);
1517                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_ebs, tvb, offset, 1, FALSE);
1518                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cbs, tvb, offset, 1, FALSE);
1519                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cdr, tvb, offset, 1, FALSE);
1520                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pbs, tvb, offset, 1, FALSE);
1521                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pdr, tvb, offset, 1, FALSE);
1522
1523                         offset ++;
1524                         /* frequency */
1525                         proto_tree_add_item(val_tree, hf_ldp_tlv_frequency, tvb, offset, 1, FALSE);
1526                         offset ++;
1527
1528                         /* reserver byte */
1529                         offset ++;
1530
1531                         /* weight */
1532                         pi = proto_tree_add_item(val_tree, hf_ldp_tlv_weight, tvb, offset, 1, FALSE);
1533                         val_8 = tvb_get_guint8(tvb, offset);
1534                         if (val_8 == 0)
1535                                 proto_item_set_text(pi, "Weight: Not applicable");
1536                         offset ++;
1537
1538                         /* PDR */
1539                         val_f = tvb_get_ntohieee_float (tvb, offset);
1540                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_pdr, tvb, offset,
1541                                                     4, val_f, "PDR: %.10g Bps", val_f);
1542                         offset += 4;
1543                         /* PBS */
1544                         val_f = tvb_get_ntohieee_float (tvb, offset);
1545                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_pbs, tvb, offset,
1546                                                     4, val_f, "PBS: %.10g Bytes", val_f);
1547                         offset += 4;
1548
1549                         /* CDR */
1550                         val_f = tvb_get_ntohieee_float (tvb, offset);
1551                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_cdr, tvb, offset,
1552                                                     4, val_f, "CDR: %.10g Bps", val_f);
1553                         offset += 4;
1554
1555                         /* CBS */
1556                         val_f = tvb_get_ntohieee_float (tvb, offset);
1557                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_cbs, tvb, offset,
1558                                                     4, val_f, "CBS: %.10g Bytes", val_f);
1559                         offset += 4;
1560
1561                         /* EBS */
1562                         val_f = tvb_get_ntohieee_float (tvb, offset);
1563                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_ebs, tvb, offset,
1564                                                     4, val_f, "EBS: %.10g Bytes", val_f);
1565
1566                 }
1567         }
1568 }
1569
1570 static void
1571 dissect_tlv_route_pinning(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1572 {
1573         proto_tree *ti = NULL, *val_tree = NULL;
1574
1575         if (tree != NULL) {
1576                 if(rem != 4) {
1577                         proto_tree_add_text(tree, tvb, offset, rem,
1578                             "Error processing Route Pinning TLV: length is %d, should be 4",
1579                             rem);
1580                         return;
1581                 }
1582                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Route Pinning");
1583                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1584
1585                 if(val_tree != NULL) {
1586                         proto_tree_add_item(val_tree, hf_ldp_tlv_route_pinning,
1587                                            tvb, offset, 4, FALSE);
1588                 }
1589         }
1590 }
1591
1592
1593 static void
1594 dissect_tlv_resource_class(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1595 {
1596         proto_tree *ti = NULL, *val_tree = NULL;
1597
1598         if (tree != NULL) {
1599                 if(rem != 4) {
1600                         proto_tree_add_text(tree, tvb, offset, rem,
1601                             "Error processing Resource Class TLV: length is %d, should be 4",
1602                             rem);
1603                         return;
1604                 }
1605                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Resource Class");
1606                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1607
1608                 if(val_tree != NULL) {
1609                         proto_tree_add_item(val_tree, hf_ldp_tlv_resource_class,
1610                                            tvb, offset, 4, FALSE);
1611                 }
1612         }
1613 }
1614
1615
1616 static void
1617 dissect_tlv_preemption(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1618 {
1619         proto_tree *ti = NULL, *val_tree = NULL;
1620
1621         if (tree != NULL) {
1622                 if(rem != 4) {
1623                         proto_tree_add_text(tree, tvb, offset, rem,
1624                             "Error processing Preemption TLV: length is %d, should be 4",
1625                             rem);
1626                         return;
1627                 }
1628                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Preemption");
1629                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1630
1631                 if(val_tree != NULL) {
1632                         proto_tree_add_item(val_tree, hf_ldp_tlv_set_prio,
1633                                            tvb, offset, 1, FALSE);
1634                         offset += 1;
1635                         proto_tree_add_item(val_tree, hf_ldp_tlv_hold_prio,
1636                                            tvb, offset, 1, FALSE);
1637                 }
1638         }
1639 }
1640
1641
1642 static void
1643 dissect_tlv_diffserv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1644 {
1645     int type, mapnb, count;
1646     int *hfindexes[] = {
1647         &hf_ldp_tlv_diffserv_map,
1648         &hf_ldp_tlv_diffserv_map_exp,
1649         &hf_ldp_tlv_diffserv_phbid,
1650         &hf_ldp_tlv_diffserv_phbid_dscp,
1651         &hf_ldp_tlv_diffserv_phbid_code,
1652         &hf_ldp_tlv_diffserv_phbid_bit14,
1653         &hf_ldp_tlv_diffserv_phbid_bit15
1654     };
1655     gint *etts[] = {
1656         &ett_ldp_diffserv_map,
1657         &ett_ldp_diffserv_map_phbid
1658     };
1659
1660     if (rem < 4) {
1661         proto_tree_add_text(tree, tvb, offset, rem,
1662             "Error processing Diff-Serv TLV: length is %d, should be >= 4", rem);
1663         return;
1664     }
1665     proto_tree_add_uint(tree, hf_ldp_tlv_diffserv_type, tvb, offset, 1,
1666                         type = tvb_get_guint8(tvb, offset));
1667     type = (type >> 7) + 1;
1668     if (type == 1) {
1669         /* E-LSP */
1670         offset += 3;
1671         proto_tree_add_uint(tree, hf_ldp_tlv_diffserv_mapnb, tvb, offset,
1672                             1, mapnb = tvb_get_guint8(tvb, offset) & 15);
1673         offset += 1;
1674         for (count = 0; count < mapnb; count++) {
1675             dissect_diffserv_mpls_common(tvb, tree, type, offset, hfindexes, etts);
1676             offset += 4;
1677         }
1678     }
1679     else if (type == 2) {
1680         /* L-LSP */
1681         dissect_diffserv_mpls_common(tvb, tree, type, offset + 2, hfindexes, etts);
1682     }
1683 }
1684
1685
1686 static int
1687 dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem);
1688
1689 static void
1690 dissect_tlv_er(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1691 {
1692         proto_tree *ti = NULL, *val_tree = NULL;
1693         int len;
1694
1695         if (tree != NULL) {
1696                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Explicit route");
1697                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1698
1699                 if(val_tree != NULL) {
1700                         len = 0;
1701                         while (rem > 0) {
1702                                 len = dissect_tlv (tvb, offset, val_tree, rem);
1703                                 offset += len;
1704                                 rem -= len;
1705                         }
1706                 }
1707         }
1708 }
1709
1710
1711 /* Dissect a TLV and return the number of bytes consumed ... */
1712
1713 static int
1714 dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1715 {
1716         guint16 type, typebak;
1717         int length;
1718         proto_tree *ti = NULL, *tlv_tree = NULL;
1719
1720         length=tvb_reported_length_remaining(tvb, offset);
1721         rem=MIN(rem, length);
1722
1723         if( rem < 4 ) {/*chk for minimum header*/
1724                 if(tree)
1725                         proto_tree_add_text(tree, tvb, offset, rem,
1726                             "Error processing TLV: length is %d, should be >= 4",
1727                             rem);
1728                 return rem;
1729         }
1730         type = tvb_get_ntohs(tvb, offset) & 0x3FFF;
1731
1732         length = tvb_get_ntohs(tvb, offset + 2),
1733         rem -= 4; /*do not count header*/
1734         length = MIN(length, rem);  /* Don't go haywire if a problem ... */
1735
1736         if (tree != NULL) {
1737                 /*chk for vendor-private*/
1738                 if(type>=TLV_VENDOR_PRIVATE_START && type<=TLV_VENDOR_PRIVATE_END){
1739                         typebak=type;           /*keep type*/
1740                         type=TLV_VENDOR_PRIVATE_START;
1741
1742                 /*chk for experimental*/
1743                 } else if(type>=TLV_EXPERIMENTAL_START && type<=TLV_EXPERIMENTAL_END){
1744                         typebak=type;           /*keep type*/
1745                         type=TLV_EXPERIMENTAL_START;
1746                 }
1747
1748                 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
1749                         val_to_str(type, tlv_type_names, "Unknown TLV type (0x%04X)"));
1750                 tlv_tree = proto_item_add_subtree(ti, ett_ldp_tlv);
1751                 if(tlv_tree == NULL) return length+4;
1752
1753                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_unknown, tvb, offset, 1, FALSE);
1754
1755                 proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_type, tvb, offset, 2, type, "TLV Type: %s (0x%X)", val_to_str(type, tlv_type_names, "Unknown TLV type"), type );
1756
1757                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
1758
1759                 switch (type) {
1760
1761                 case TLV_FEC:
1762                         dissect_tlv_fec(tvb, offset + 4, tlv_tree, length);
1763                         break;
1764
1765                 case TLV_ADDRESS_LIST:
1766                         dissect_tlv_address_list(tvb, offset + 4, tlv_tree, length);
1767                         break;
1768
1769                 case TLV_HOP_COUNT:
1770                         if( length != 1 ) /*error, only one byte*/
1771                                 proto_tree_add_text(tlv_tree, tvb, offset + 4,length,
1772                                     "Error processing Hop Count TLV: length is %d, should be 1",
1773                                     length);
1774                         else
1775                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE);
1776                         break;
1777
1778                 case TLV_PATH_VECTOR:
1779                         dissect_tlv_path_vector(tvb, offset + 4, tlv_tree, length);
1780                         break;
1781
1782                 case TLV_GENERIC_LABEL:
1783                         if( length != 4 ) /*error, need only label*/
1784                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1785                                     "Error processing Generic Label TLV: length is %d, should be 4",
1786                                     length);
1787                         else {
1788                                 guint32 label=tvb_get_ntohl(tvb, offset+4) & 0x000FFFFF;
1789
1790                                 proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_generic_label,
1791                                         tvb, offset+4, length, label, "Generic Label: %u", label);
1792                         }
1793                         break;
1794
1795                 case TLV_ATM_LABEL:
1796                         dissect_tlv_atm_label(tvb, offset + 4, tlv_tree, length);
1797                         break;
1798
1799                 case TLV_FRAME_LABEL:
1800                         dissect_tlv_frame_label(tvb, offset + 4, tlv_tree, length);
1801                         break;
1802
1803                 case TLV_STATUS:
1804                         dissect_tlv_status(tvb, offset + 4, tlv_tree, length);
1805                         break;
1806
1807                 case TLV_EXTENDED_STATUS:
1808                         if( length != 4 ) /*error, need only status_code(guint32)*/
1809                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1810                                     "Error processing Extended Status TLV: length is %d, should be 4",
1811                                     length);
1812                         else {
1813                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE);
1814                         }
1815                         break;
1816
1817                 case TLV_RETURNED_PDU:
1818                         dissect_tlv_returned_pdu(tvb, offset + 4, tlv_tree, length);
1819                         break;
1820
1821                 case TLV_RETURNED_MESSAGE:
1822                         dissect_tlv_returned_message(tvb, offset + 4, tlv_tree, length);
1823                         break;
1824
1825                 case TLV_COMMON_HELLO_PARMS:
1826 #if 0
1827                         dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
1828 #else
1829                         dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree);
1830 #endif
1831                         break;
1832
1833                 case TLV_IPV4_TRANSPORT_ADDRESS:
1834                         if( length != 4 ) /*error, need only ipv4*/
1835                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1836                                     "Error processing IPv4 Transport Address TLV: length is %d, should be 4",
1837                                     length);
1838                         else {
1839                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv4_taddr, tvb, offset + 4, 4, FALSE);
1840                         }
1841                         break;
1842
1843                 case TLV_CONFIGURATION_SEQNO:
1844                         if( length != 4 ) /*error, need only seq_num(guint32)*/
1845                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1846                                     "Error processing Configuration Sequence Number TLV: length is %d, should be 4",
1847                                     length);
1848                         else {
1849                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
1850                         }
1851                         break;
1852
1853                 case TLV_IPV6_TRANSPORT_ADDRESS:
1854                         if( length != 16 ) /*error, need only ipv6*/
1855                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1856                                     "Error processing IPv6 Transport Address TLV: length is %d, should be 16",
1857                                     length);
1858                         else {
1859                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv6_taddr, tvb, offset + 4, 16, FALSE);
1860                         }
1861                         break;
1862
1863                 case TLV_MAC: /* draft-lasserre-vkompella-ppvpn-vpls-02.txt */
1864                         dissect_tlv_mac(tvb, offset + 4, tlv_tree, length);
1865                         break;
1866
1867                 case TLV_COMMON_SESSION_PARMS:
1868                         dissect_tlv_common_session_parms(tvb, offset + 4, tlv_tree, length);
1869                         break;
1870
1871                 case TLV_ATM_SESSION_PARMS:
1872                         dissect_tlv_atm_session_parms(tvb, offset + 4, tlv_tree, length);
1873                         break;
1874
1875                 case TLV_FRAME_RELAY_SESSION_PARMS:
1876                         dissect_tlv_frame_relay_session_parms(tvb, offset + 4, tlv_tree, length);
1877                         break;
1878
1879                 case TLV_LABEL_REQUEST_MESSAGE_ID:
1880                         if( length != 4 ) /*error, need only one msgid*/
1881                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1882                                     "Error processing Label Request Message ID TLV: length is %d, should be 4",
1883                                     length);
1884                         else
1885                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE);
1886                         break;
1887
1888                 case TLV_LSPID:
1889                         dissect_tlv_lspid(tvb, offset + 4, tlv_tree, length);
1890                         break;
1891
1892                 case TLV_ER:
1893                         dissect_tlv_er(tvb, offset + 4, tlv_tree, length);
1894                         break;
1895
1896                 case TLV_ER_HOP_IPV4:
1897                         dissect_tlv_er_hop_ipv4(tvb, offset + 4, tlv_tree, length);
1898                         break;
1899
1900                 case TLV_ER_HOP_IPV6:
1901                         dissect_tlv_er_hop_ipv6(tvb, offset +4, tlv_tree, length);
1902                         break;
1903
1904                 case TLV_ER_HOP_AS:
1905                         dissect_tlv_er_hop_as(tvb, offset + 4, tlv_tree, length);
1906                         break;
1907
1908                 case TLV_ER_HOP_LSPID:
1909                         dissect_tlv_er_hop_lspid(tvb, offset +4, tlv_tree, length);
1910                         break;
1911
1912                 case TLV_TRAFFIC_PARAM:
1913                         dissect_tlv_traffic(tvb, offset +4, tlv_tree, length);
1914                         break;
1915
1916                 case TLV_PREEMPTION:
1917                         dissect_tlv_preemption(tvb, offset +4, tlv_tree, length);
1918                         break;
1919
1920                 case TLV_RESOURCE_CLASS:
1921                         dissect_tlv_resource_class(tvb, offset +4, tlv_tree, length);
1922                         break;
1923
1924                 case TLV_ROUTE_PINNING:
1925                         dissect_tlv_route_pinning(tvb, offset +4, tlv_tree, length);
1926                         break;
1927
1928                 case TLV_DIFFSERV:
1929                         dissect_tlv_diffserv(tvb, offset +4, tlv_tree, length);
1930                         break;
1931
1932                 case TLV_VENDOR_PRIVATE_START:
1933                         if( length < 4 ) /*error, at least Vendor ID*/
1934                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1935                                     "Error processing Vendor Private Start TLV: length is %d, should be >= 4",
1936                                     length);
1937                         else {
1938                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE);
1939                                 if( length > 4 )  /*have data*/
1940                                         proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
1941                         }
1942                         break;
1943
1944                 case TLV_EXPERIMENTAL_START:
1945                         if( length < 4 ) /*error, at least Experiment ID*/
1946                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1947                                     "Error processing Experimental Start TLV: length is %d, should be >= 4",
1948                                     length);
1949                         else {
1950                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE);
1951                                 if( length > 4 )  /*have data*/
1952                                         proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
1953                         }
1954                         break;
1955
1956                 default:
1957                         proto_tree_add_item(tlv_tree, hf_ldp_tlv_value, tvb, offset + 4, length, FALSE);
1958                         break;
1959                 }
1960         }
1961
1962         return length + 4;  /* Length of the value field + header */
1963 }
1964
1965
1966 /* Dissect a Message and return the number of bytes consumed ... */
1967
1968 static int
1969 dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
1970 {
1971         guint16 type, typebak;
1972         guint8  extra=0;
1973         int length, rem, ao=0, co;
1974         proto_tree *ti = NULL, *msg_tree = NULL;
1975
1976         rem=tvb_reported_length_remaining(tvb, offset);
1977
1978         if( rem < 8 ) {/*chk for minimum header = type + length + msg_id*/
1979                 if( check_col(pinfo->cinfo, COL_INFO) )
1980                         col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message");
1981                 if(tree)
1982                         proto_tree_add_text(tree, tvb, offset, rem,
1983                             "Error processing Message: length is %d, should be >= 8",
1984                             rem);
1985                 return rem;
1986         }
1987         type = tvb_get_ntohs(tvb, offset) & 0x7FFF;
1988
1989         /*chk for vendor-private*/
1990         if(type>=LDP_VENDOR_PRIVATE_START && type<=LDP_VENDOR_PRIVATE_END){
1991                 typebak=type;           /*keep type*/
1992                 type=LDP_VENDOR_PRIVATE_START;
1993                 extra=4;
1994         /*chk for experimental*/
1995         } else if(type>=LDP_EXPERIMENTAL_MESSAGE_START && type<=LDP_EXPERIMENTAL_MESSAGE_END){
1996                 typebak=type;           /*keep type*/
1997                 type=LDP_EXPERIMENTAL_MESSAGE_START;
1998                 extra=4;
1999         }
2000
2001         if( (length = tvb_get_ntohs(tvb, offset + 2)) < (4+extra) ) {/*not enough data for type*/
2002                 if( check_col(pinfo->cinfo, COL_INFO) )
2003                         col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message Length ");
2004                 if(tree)
2005                         proto_tree_add_text(tree, tvb, offset, rem,
2006                             "Error processing Message Length: length is %d, should be >= %u",
2007                             length, 4+extra);
2008                 return rem;
2009         }
2010         rem -= 4;
2011         length = MIN(length, rem);  /* Don't go haywire if a problem ... */
2012
2013         if( check_col(pinfo->cinfo, COL_INFO) ){
2014                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, ldp_message_types, "Unknown Message (0x%04X)"));
2015         }
2016
2017         if( tree ){
2018                 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
2019                         val_to_str(type, ldp_message_types, "Unknown Message type (0x%04X)"));
2020                 msg_tree = proto_item_add_subtree(ti, ett_ldp_message);
2021                 if(msg_tree == NULL) return length+4;
2022
2023                 proto_tree_add_item(msg_tree, hf_ldp_msg_ubit, tvb, offset, 1, FALSE);
2024
2025                 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
2026                 proto_tree_add_uint_format(msg_tree, hf_ldp_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type);
2027
2028                 proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset+2, 2, FALSE);
2029                 proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset+4, 4, FALSE);
2030                 if(extra){
2031                         int hf_tmp=0;
2032
2033                         switch(type){
2034                                 case LDP_VENDOR_PRIVATE_START:
2035                                         hf_tmp=hf_ldp_msg_vendor_id;
2036                                         break;
2037                                 case LDP_EXPERIMENTAL_MESSAGE_START:
2038                                         hf_tmp=hf_ldp_msg_experiment_id;
2039                                         break;
2040                         }
2041                         proto_tree_add_item(msg_tree, hf_tmp, tvb, offset+8, extra, FALSE);
2042                 }
2043         }
2044
2045         offset += (8+extra);
2046         length -= (4+extra);
2047
2048         if( tree )
2049                 while( (length-ao) > 0 ) {
2050                         co=dissect_tlv(tvb, offset, msg_tree, length-ao);
2051                         offset += co;
2052                         ao += co;
2053                 }
2054
2055         return length+8+extra;
2056 }
2057
2058 /* Dissect a PDU */
2059 static void
2060 dissect_ldp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2061 {
2062         int offset = 0, co;
2063         int rem, length;
2064         proto_tree *ti=NULL, *pdu_tree = NULL;
2065
2066         if (check_col(pinfo->cinfo, COL_PROTOCOL))
2067                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
2068
2069         if (check_col(pinfo->cinfo, COL_INFO))
2070                 col_clear(pinfo->cinfo, COL_INFO);
2071
2072         if( tree ){
2073                 ti=proto_tree_add_item(tree, proto_ldp, tvb, 0, -1, FALSE);
2074                 pdu_tree = proto_item_add_subtree(ti, ett_ldp);
2075
2076                 proto_tree_add_item(pdu_tree, hf_ldp_version, tvb, offset, 2, FALSE);
2077         }
2078
2079         length = tvb_get_ntohs(tvb, offset+2);
2080         if( tree )
2081                 proto_tree_add_uint(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, length);
2082
2083         length += 4;    /* add the version and type sizes */
2084         rem = tvb_reported_length_remaining(tvb, offset);
2085         if (length < rem)
2086                 tvb_set_reported_length(tvb, length);
2087
2088         if( tree ){
2089                 proto_tree_add_item(pdu_tree, hf_ldp_lsr, tvb, offset+4, 4, FALSE);
2090                 proto_tree_add_item(pdu_tree, hf_ldp_ls_id, tvb, offset+8, 2, FALSE);
2091         }
2092         offset += 10;
2093
2094         while( tvb_reported_length_remaining(tvb, offset) > 0 ) {
2095                 co=dissect_msg(tvb, offset, pinfo, pdu_tree);
2096                 offset += co;
2097         }
2098 }
2099
2100 static int
2101 dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2102 {
2103         /*
2104          * Make sure the first PDU has a version number of 1;
2105          * if not, reject this, so we don't get confused by
2106          * packets that happen to be going to or from the
2107          * LDP port but that aren't LDP packets.
2108          */
2109         if (!tvb_bytes_exist(tvb, 0, 2)) {
2110                 /*
2111                  * Not enough information to tell.
2112                  */
2113                 return 0;
2114         }
2115         if (tvb_get_ntohs(tvb, 0) != 1) {
2116                 /*
2117                  * Not version 1.
2118                  */
2119                 return 0;
2120         }
2121
2122         dissect_ldp_pdu(tvb, pinfo, tree);
2123
2124         /*
2125          * XXX - return minimum of this and the length of the PDU?
2126          */
2127         return tvb_length(tvb);
2128 }
2129
2130 static int
2131 dissect_ldp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2132 {
2133         volatile gboolean first = TRUE;
2134         volatile int offset = 0;
2135         int length_remaining;
2136         guint16 plen;
2137         int length;
2138         tvbuff_t *next_tvb;
2139
2140         while (tvb_reported_length_remaining(tvb, offset) != 0) {
2141                 length_remaining = tvb_length_remaining(tvb, offset);
2142
2143                 /*
2144                  * Make sure the first PDU has a version number of 1;
2145                  * if not, reject this, so we don't get confused by
2146                  * packets that happen to be going to or from the
2147                  * LDP port but that aren't LDP packets.
2148                  *
2149                  * XXX - this means we can't handle an LDP PDU of which
2150                  * only one byte appears in a TCP segment.  If that's
2151                  * a problem, we'll either have to completely punt on
2152                  * rejecting non-LDP packets, or will have to assume
2153                  * that if we have only one byte, it's an LDP packet.
2154                  */
2155                 if (first) {
2156                         if (length_remaining < 2) {
2157                                 /*
2158                                  * Not enough information to tell.
2159                                  */
2160                                 return 0;
2161                         }
2162                         if (tvb_get_ntohs(tvb, offset) != 1) {
2163                                 /*
2164                                  * Not version 1.
2165                                  */
2166                                 return 0;
2167                         }
2168                         first = FALSE;
2169                 }
2170
2171                 /*
2172                  * Can we do reassembly?
2173                  */
2174                 if (ldp_desegment && pinfo->can_desegment) {
2175                         /*
2176                          * Yes - is the LDP header split across segment
2177                          * boundaries?
2178                          */
2179                         if (length_remaining < 4) {
2180                                 /*
2181                                  * Yes.  Tell the TCP dissector where
2182                                  * the data for this message starts in
2183                                  * the data it handed us, and how many
2184                                  * more bytes we need, and return.
2185                                  */
2186                                 pinfo->desegment_offset = offset;
2187                                 pinfo->desegment_len = 4 - length_remaining;
2188                                 return -((gint32) pinfo->desegment_len);
2189                         }
2190                 }
2191
2192                 /*
2193                  * Get the length of the rest of the LDP packet.
2194                  * XXX - check for a version of 1 first?
2195                  */
2196                 plen = tvb_get_ntohs(tvb, offset + 2);
2197
2198                 /*
2199                  * Can we do reassembly?
2200                  */
2201                 if (ldp_desegment && pinfo->can_desegment) {
2202                         /*
2203                          * Yes - is the LDP packet split across segment
2204                          * boundaries?
2205                          */
2206                         if (length_remaining < plen + 4) {
2207                                 /*
2208                                  * Yes.  Tell the TCP dissector where the
2209                                  * data for this message starts in the data
2210                                  * it handed us, and how many more bytes we
2211                                  * need, and return.
2212                                  */
2213                                 pinfo->desegment_offset = offset;
2214                                 pinfo->desegment_len =
2215                                     (plen + 4) - length_remaining;
2216                                 return -((gint32) pinfo->desegment_len);
2217                         }
2218                 }
2219
2220                 /*
2221                  * Construct a tvbuff containing the amount of the payload
2222                  * we have available.  Make its reported length the
2223                  * amount of data in the DNS-over-TCP packet.
2224                  *
2225                  * XXX - if reassembly isn't enabled. the subdissector
2226                  * will throw a BoundsError exception, rather than a
2227                  * ReportedBoundsError exception.  We really want
2228                  * a tvbuff where the length is "length", the reported
2229                  * length is "plen + 4", and the "if the snapshot length
2230                  * were infinite" length is the minimum of the
2231                  * reported length of the tvbuff handed to us and "plen+4",
2232                  * with a new type of exception thrown if the offset is
2233                  * within the reported length but beyond that third length,
2234                  * with that exception getting the "Unreassembled Packet"
2235                  * error.
2236                  */
2237                 length = length_remaining;
2238                 if (length > plen + 4)
2239                         length = plen + 4;
2240                 next_tvb = tvb_new_subset(tvb, offset, length, plen + 4);
2241
2242                 /*
2243                  * Dissect the LDP packet.
2244                  *
2245                  * Catch the ReportedBoundsError exception; if this
2246                  * particular message happens to get a ReportedBoundsError
2247                  * exception, that doesn't mean that we should stop
2248                  * dissecting LDP messages within this frame or chunk of
2249                  * reassembled data.
2250                  *
2251                  * If it gets a BoundsError, we can stop, as there's nothing
2252                  * more to see, so we just re-throw it.
2253                  */
2254                 TRY {
2255                         dissect_ldp_pdu(next_tvb, pinfo, tree);
2256                 }
2257                 CATCH(BoundsError) {
2258                         RETHROW;
2259                 }
2260                 CATCH(ReportedBoundsError) {
2261                         show_reported_bounds_error(tvb, pinfo, tree);
2262                 }
2263                 ENDTRY;
2264
2265                 /*
2266                  * Skip the LDP header and the payload.
2267                  */
2268                 offset += plen + 4;
2269         }
2270         return tvb_length(tvb);
2271 }
2272
2273 /* Register all the bits needed with the filtering engine */
2274
2275 void
2276 proto_register_ldp(void)
2277 {
2278   static hf_register_info hf[] = {
2279     { &hf_ldp_req,
2280       /* Change the following to the type you need */
2281       { "Request", "ldp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
2282
2283     { &hf_ldp_rsp,
2284       { "Response", "ldp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
2285
2286     { &hf_ldp_version,
2287       { "Version", "ldp.hdr.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
2288
2289     { &hf_ldp_pdu_len,
2290       { "PDU Length", "ldp.hdr.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
2291
2292     { &hf_ldp_lsr,
2293       { "LSR ID", "ldp.hdr.ldpid.lsr", FT_IPv4, BASE_HEX, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
2294
2295     { &hf_ldp_ls_id,
2296       { "Label Space ID", "ldp.hdr.ldpid.lsid", FT_UINT16, BASE_DEC, NULL, 0, "LDP Label Space ID", HFILL }},
2297
2298     { &hf_ldp_msg_ubit,
2299       { "U bit", "ldp.msg.ubit", FT_BOOLEAN, 8, TFS(&ldp_message_ubit), 0x80, "Unknown Message Bit", HFILL }},
2300
2301     { &hf_ldp_msg_type,
2302       { "Message Type", "ldp.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
2303
2304     { &hf_ldp_msg_len,
2305       { "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
2306
2307     { &hf_ldp_msg_id,
2308       { "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
2309
2310     { &hf_ldp_msg_vendor_id,
2311       { "Vendor ID", "ldp.msg.vendor.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Vendor-private Message ID", HFILL }},
2312
2313     { &hf_ldp_msg_experiment_id,
2314       { "Experiment ID", "ldp.msg.experiment.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Experimental Message ID", HFILL }},
2315
2316     { &hf_ldp_tlv_unknown,
2317       { "TLV Unknown bits", "ldp.msg.tlv.unknown", FT_UINT8, BASE_HEX, VALS(tlv_unknown_vals), 0xC0, "TLV Unknown bits Field", HFILL }},
2318
2319     { &hf_ldp_tlv_type,
2320       { "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x3FFF, "TLV Type Field", HFILL }},
2321
2322     { &hf_ldp_tlv_len,
2323       {"TLV Length", "ldp.msg.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0, "TLV Length Field", HFILL }},
2324
2325     { &hf_ldp_tlv_value,
2326       { "TLV Value", "ldp.msg.tlv.value", FT_BYTES, BASE_NONE, NULL, 0x0, "TLV Value Bytes", HFILL }},
2327
2328     { &hf_ldp_tlv_val_hold,
2329       { "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time", HFILL }},
2330
2331     { &hf_ldp_tlv_val_target,
2332       { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 16, TFS(&hello_targeted_vals), 0x8000, "Hello Common Parameters Targeted Bit", HFILL }},
2333
2334     { &hf_ldp_tlv_val_request,
2335       { "Hello Requested", "ldp.msg.tlv.hello.requested", FT_BOOLEAN, 16, TFS(&hello_requested_vals), 0x4000, "Hello Common Parameters Hello Requested Bit", HFILL }},
2336
2337     { &hf_ldp_tlv_val_res,
2338       { "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field", HFILL }},
2339
2340     { &hf_ldp_tlv_ipv4_taddr,
2341       { "IPv4 Transport Address", "ldp.msg.tlv.ipv4.taddr", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Transport Address", HFILL }},
2342
2343     { &hf_ldp_tlv_config_seqno,
2344       { "Configuration Sequence Number", "ldp.msg.tlv.hello.cnf_seqno", FT_UINT32, BASE_DEC, NULL, 0x0, "Hello Configuration Sequence Number", HFILL }},
2345
2346     { &hf_ldp_tlv_ipv6_taddr,
2347       { "IPv6 Transport Address", "ldp.msg.tlv.ipv6.taddr", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Transport Address", HFILL }},
2348
2349     { &hf_ldp_tlv_fec_wc,
2350       { "FEC Element Type", "ldp.msg.tlv.fec.type", FT_UINT8, BASE_DEC, VALS(fec_types), 0x0, "Forwarding Equivalence Class Element Types", HFILL }},
2351
2352     { &hf_ldp_tlv_fec_af,
2353       { "FEC Element Address Type", "ldp.msg.tlv.fec.af", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Forwarding Equivalence Class Element Address Family", HFILL }},
2354
2355     { &hf_ldp_tlv_fec_len,
2356       { "FEC Element Length", "ldp.msg.tlv.fec.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Forwarding Equivalence Class Element Length", HFILL }},
2357
2358     { &hf_ldp_tlv_fec_pfval,
2359       { "FEC Element Prefix Value", "ldp.msg.tlv.fec.pfval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Prefix", HFILL }},
2360
2361     { &hf_ldp_tlv_fec_hoval,
2362       { "FEC Element Host Address Value", "ldp.msg.tlv.fec.hoval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Address", HFILL }},
2363
2364     { &hf_ldp_tlv_addrl_addr_family,
2365       { "Address Family", "ldp.msg.tlv.addrl.addr_family", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Address Family List", HFILL }},
2366
2367     { &hf_ldp_tlv_addrl_addr,
2368       { "Address", "ldp.msg.tlv.addrl.addr", FT_STRING, BASE_NONE, NULL, 0x0, "Address", HFILL }},
2369
2370     { &hf_ldp_tlv_hc_value,
2371       { "Hop Count Value", "ldp.msg.tlv.hc.value", FT_UINT8, BASE_DEC, NULL, 0x0, "Hop Count", HFILL }},
2372
2373     { &hf_ldp_tlv_pv_lsrid,
2374       { "LSR Id", "ldp.msg.tlv.pv.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Path Vector LSR Id", HFILL }},
2375
2376     { &hf_ldp_tlv_sess_ver,
2377       { "Session Protocol Version", "ldp.msg.tlv.sess.ver", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Protocol Version", HFILL }},
2378
2379     { &hf_ldp_tlv_sess_ka,
2380       { "Session KeepAlive Time", "ldp.msg.tlv.sess.ka", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters KeepAlive Time", HFILL }},
2381
2382     { &hf_ldp_tlv_sess_advbit,
2383       { "Session Label Advertisement Discipline", "ldp.msg.tlv.sess.advbit",
2384  FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80,
2385         "Common Session Parameters Label Advertisement Discipline", HFILL }},
2386
2387     { &hf_ldp_tlv_sess_ldetbit,
2388       { "Session Loop Detection", "ldp.msg.tlv.sess.ldetbit", FT_BOOLEAN, 8, TFS(&tlv_sess_ldetbit_vals), 0x40, "Common Session Parameters Loop Detection", HFILL }},
2389
2390     { &hf_ldp_tlv_sess_pvlim,
2391       { "Session Path Vector Limit", "ldp.msg.tlv.sess.pvlim", FT_UINT8, BASE_DEC, NULL, 0x0, "Common Session Parameters Path Vector Limit", HFILL }},
2392
2393     { &hf_ldp_tlv_sess_mxpdu,
2394       { "Session Max PDU Length", "ldp.msg.tlv.sess.mxpdu", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Max PDU Length", HFILL }},
2395
2396     { &hf_ldp_tlv_sess_rxlsr,
2397       { "Session Receiver LSR Identifier", "ldp.msg.tlv.sess.rxlsr", FT_IPv4, BASE_DEC, NULL, 0x0, "Common Session Parameters LSR Identifier", HFILL }},
2398
2399     { &hf_ldp_tlv_sess_rxls,
2400       { "Session Receiver Label Space Identifier", "ldp.msg.tlv.sess.rxlsr", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Receiver Label Space Identifier", HFILL }},
2401
2402     { &hf_ldp_tlv_sess_atm_merge,
2403       { "Session ATM Merge Parameter", "ldp.msg.tlv.sess.atm.merge", FT_UINT8, BASE_DEC, VALS(tlv_atm_merge_vals), 0xC0, "Merge ATM Session Parameters", HFILL }},
2404
2405     { &hf_ldp_tlv_sess_atm_lr,
2406       { "Number of ATM Label Ranges", "ldp.msg.tlv.sess.atm.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
2407
2408     { &hf_ldp_tlv_sess_atm_dir,
2409       { "Directionality", "ldp.msg.tlv.sess.atm.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Lablel Directionality", HFILL }},
2410
2411     { &hf_ldp_tlv_sess_atm_minvpi,
2412       { "Minimum VPI", "ldp.msg.tlv.sess.atm.minvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Minimum VPI", HFILL }},
2413
2414     { &hf_ldp_tlv_sess_atm_minvci,
2415       { "Minimum VCI", "ldp.msg.tlv.sess.atm.minvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Minimum VCI", HFILL }},
2416
2417     { &hf_ldp_tlv_sess_atm_maxvpi,
2418       { "Maximum VPI", "ldp.msg.tlv.sess.atm.maxvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Maximum VPI", HFILL }},
2419
2420     { &hf_ldp_tlv_sess_atm_maxvci,
2421       { "Maximum VCI", "ldp.msg.tlv.sess.atm.maxvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Maximum VCI", HFILL }},
2422
2423     { &hf_ldp_tlv_sess_fr_merge,
2424       { "Session Frame Relay Merge Parameter", "ldp.msg.tlv.sess.fr.merge", FT_UINT8, BASE_DEC, VALS(tlv_fr_merge_vals), 0xC0, "Merge Frame Relay Session Parameters", HFILL }},
2425
2426     { &hf_ldp_tlv_sess_fr_lr,
2427       { "Number of Frame Relay Label Ranges", "ldp.msg.tlv.sess.fr.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
2428
2429     { &hf_ldp_tlv_sess_fr_dir,
2430       { "Directionality", "ldp.msg.tlv.sess.fr.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Lablel Directionality", HFILL }},
2431
2432     { &hf_ldp_tlv_sess_fr_len,
2433       { "Number of DLCI bits", "ldp.msg.tlv.sess.fr.len", FT_UINT16, BASE_DEC, VALS(tlv_fr_len_vals), 0x0180, "DLCI Number of bits", HFILL }},
2434
2435     { &hf_ldp_tlv_sess_fr_mindlci,
2436       { "Minimum DLCI", "ldp.msg.tlv.sess.fr.mindlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Minimum DLCI", HFILL }},
2437
2438     { &hf_ldp_tlv_sess_fr_maxdlci,
2439       { "Maximum DLCI", "ldp.msg.tlv.sess.fr.maxdlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Maximum DLCI", HFILL }},
2440
2441     { &hf_ldp_tlv_lbl_req_msg_id,
2442       { "Label Request Message ID", "ldp.tlv.lbl_req_msg_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Label Request Message to be aborted", HFILL }},
2443
2444     { &hf_ldp_tlv_vendor_id,
2445       { "Vendor ID", "ldp.msg.tlv.vendor_id", FT_UINT32, BASE_HEX, NULL, 0, "IEEE 802 Assigned Vendor ID", HFILL }},
2446
2447     { &hf_ldp_tlv_experiment_id,
2448       { "Experiment ID", "ldp.msg.tlv.experiment_id", FT_UINT32, BASE_HEX, NULL, 0, "Experiment ID", HFILL }},
2449
2450     { &hf_ldp_tlv_generic_label,
2451       { "Generic Label", "ldp.msg.tlv.generic.label", FT_UINT32, BASE_HEX, NULL, 0x000FFFFF, "Generic Label", HFILL }},
2452
2453     { &hf_ldp_tlv_atm_label_vbits,
2454       { "V-bits", "ldp.msg.tlv.atm.label.vbits", FT_UINT8, BASE_HEX, VALS(tlv_atm_vbits_vals), 0x30, "ATM Label V Bits", HFILL }},
2455
2456     { &hf_ldp_tlv_atm_label_vpi,
2457       { "VPI", "ldp.msg.tlv.atm.label.vpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "ATM Label VPI", HFILL }},
2458
2459     { &hf_ldp_tlv_atm_label_vci,
2460       { "VCI", "ldp.msg.tlv.atm.label.vci", FT_UINT16, BASE_DEC, NULL, 0, "ATM Label VCI", HFILL }},
2461
2462     { &hf_ldp_tlv_fr_label_len,
2463       { "Number of DLCI bits", "ldp.msg.tlv.fr.label.len", FT_UINT16, BASE_DEC, VALS(tlv_fr_len_vals), 0x0180, "DLCI Number of bits", HFILL }},
2464
2465     { &hf_ldp_tlv_fr_label_dlci,
2466       { "DLCI", "ldp.msg.tlv.fr.label.dlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "FRAME RELAY Label DLCI", HFILL }},
2467
2468     { &hf_ldp_tlv_status_ebit,
2469       { "E Bit", "ldp.msg.tlv.status.ebit", FT_BOOLEAN, 8, TFS(&tlv_status_ebit), 0x80, "Fatal Error Bit", HFILL }},
2470
2471     { &hf_ldp_tlv_status_fbit,
2472       { "F Bit", "ldp.msg.tlv.status.fbit", FT_BOOLEAN, 8, TFS(&tlv_status_fbit), 0x40, "Forward Bit", HFILL }},
2473
2474     { &hf_ldp_tlv_status_data,
2475       { "Status Data", "ldp.msg.tlv.status.data", FT_UINT32, BASE_HEX, VALS(tlv_status_data), 0x3FFFFFFF, "Status Data", HFILL }},
2476
2477     { &hf_ldp_tlv_status_msg_id,
2478       { "Message ID", "ldp.msg.tlv.status.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "Identifies peer message to which Status TLV refers", HFILL }},
2479
2480     { &hf_ldp_tlv_status_msg_type,
2481       { "Message Type", "ldp.msg.tlv.status.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x0, "Type of peer message to which Status TLV refers", HFILL }},
2482
2483     { &hf_ldp_tlv_extstatus_data,
2484       { "Extended Status Data", "ldp.msg.tlv.extstatus.data", FT_UINT32, BASE_HEX, NULL, 0x0, "Extended Status Data", HFILL }},
2485
2486     { &hf_ldp_tlv_returned_version,
2487       { "Returned PDU Version", "ldp.msg.tlv.returned.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
2488
2489     { &hf_ldp_tlv_returned_pdu_len,
2490       { "Returned PDU Length", "ldp.msg.tlv.returned.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
2491
2492     { &hf_ldp_tlv_returned_lsr,
2493       { "Returned PDU LSR ID", "ldp.msg.tlv.returned.ldpid.lsr", FT_IPv4, BASE_DEC, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
2494
2495     { &hf_ldp_tlv_returned_ls_id,
2496       { "Returned PDU Label Space ID", "ldp.msg.tlv.returned.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID", HFILL }},
2497
2498     { &hf_ldp_tlv_returned_msg_ubit,
2499       { "Returned Message Unknown bit", "ldp.msg.tlv.returned.msg.ubit", FT_BOOLEAN, BASE_HEX, TFS(&ldp_message_ubit), 0x80, "Message Unknown bit", HFILL }},
2500
2501     { &hf_ldp_tlv_returned_msg_type,
2502       { "Returned Message Type", "ldp.msg.tlv.returned.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
2503
2504     { &hf_ldp_tlv_returned_msg_len,
2505       { "Returned Message Length", "ldp.msg.tlv.returned.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
2506
2507     { &hf_ldp_tlv_returned_msg_id,
2508       { "Returned Message ID", "ldp.msg.tlv.returned.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
2509
2510     { &hf_ldp_tlv_mac,
2511       { "MAC address", "ldp.msg.tlv.mac", FT_ETHER, BASE_NONE, NULL, 0x0, "MAC address", HFILL}},
2512
2513     {&hf_ldp_tlv_fec_vc_controlword,
2514      {"C-bit", "ldp.msg.tlv.fec.vc.controlword", FT_BOOLEAN, 8, TFS(&fec_vc_cbit), 0x80, "Control Word Present", HFILL }},
2515
2516     {&hf_ldp_tlv_fec_vc_vctype,
2517      {"VC Type", "ldp.msg.tlv.fec.vc.vctype", FT_UINT16, BASE_HEX, VALS(fec_vc_types_vals), 0x7FFF, "Virtual Circuit Type", HFILL }},
2518
2519     {&hf_ldp_tlv_fec_vc_infolength,
2520      {"VC Info Length", "ldp.msg.tlv.fec.vc.infolength", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Info Length", HFILL }},
2521
2522     {&hf_ldp_tlv_fec_vc_groupid,
2523      {"Group ID", "ldp.msg.tlv.fec.vc.groupid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC Group ID", HFILL }},
2524
2525     {&hf_ldp_tlv_fec_vc_vcid,
2526      {"VC ID", "ldp.msg.tlv.fec.vc.vcid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC VCID", HFILL }},
2527
2528     {&hf_ldp_tlv_fec_vc_intparam_length,
2529      {"Length", "ldp.msg.tlv.fec.vc.intparam.length", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater Length", HFILL }},
2530
2531     {&hf_ldp_tlv_fec_vc_intparam_mtu,
2532      {"MTU", "ldp.msg.tlv.fec.vc.intparam.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater MTU", HFILL }},
2533
2534     {&hf_ldp_tlv_fec_vc_intparam_tdmbps,
2535      {"BPS", "ldp.msg.tlv.fec.vc.intparam.tdmbps", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Parameter CEP/TDM bit-rate", HFILL }},
2536
2537     {&hf_ldp_tlv_fec_vc_intparam_id,
2538      {"ID", "ldp.msg.tlv.fec.vc.intparam.id", FT_UINT8, BASE_HEX, VALS(fec_vc_interfaceparm), 0x0, "VC FEC Interface Paramater ID", HFILL }},
2539
2540     {&hf_ldp_tlv_fec_vc_intparam_maxcatmcells,
2541      {"Number of Cells", "ldp.msg.tlv.fec.vc.intparam.maxatm", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param Max ATM Concat Cells", HFILL }},
2542
2543     { &hf_ldp_tlv_fec_vc_intparam_desc,
2544       { "Description", "ldp.msg.tlv.fec.vc.intparam.desc", FT_STRING, BASE_DEC, NULL, 0, "VC FEC Interface Description", HFILL }},
2545
2546     { &hf_ldp_tlv_fec_vc_intparam_cembytes,
2547      {"Payload Bytes", "ldp.msg.tlv.fec.vc.intparam.cembytes", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param CEM Payload Bytes", HFILL }},
2548
2549     { &hf_ldp_tlv_fec_vc_intparam_vpnid_oui,
2550       { "VPN OUI", "ldp.msg.tlv.fec.vc.intparam.vpnid.oui", FT_UINT24, BASE_HEX, NULL, 0x0, "VC FEC Interface Param VPN OUI", HFILL }},
2551
2552     { &hf_ldp_tlv_fec_vc_intparam_vpnid_index,
2553       { "VPN Index", "ldp.msg.tlv.fec.vc.intparam.vpnid.index", FT_UINT32, BASE_HEX, NULL, 0x0, "VC FEC Interface Param VPN Index", HFILL }},
2554
2555     { &hf_ldp_tlv_lspid_act_flg,
2556       { "Action Indicator Flag", "ldp.msg.tlv.lspid.actflg", FT_UINT16, BASE_HEX, VALS(ldp_act_flg_vals), 0x000F, "Action Indicator Flag", HFILL}},
2557
2558     { &hf_ldp_tlv_lspid_cr_lsp,
2559       { "Local CR-LSP ID", "ldp.msg.tlv.lspid.locallspid", FT_UINT16, BASE_HEX, NULL, 0x0, "Local CR-LSP ID", HFILL}},
2560
2561     { &hf_ldp_tlv_lspid_ldpid,
2562       { "Ingress LSR Router ID", "ldp.msg.tlv.lspid.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Ingress LSR Router ID", HFILL}},
2563
2564     { &hf_ldp_tlv_er_hop_loose,
2565       { "Loose route bit", "ldp.msg.tlv.er_hop.loose", FT_UINT24, BASE_HEX, VALS(ldp_loose_vals), 0x800000, "Loose route bit", HFILL}},
2566
2567     { &hf_ldp_tlv_er_hop_prelen,
2568       { "Prefix length", "ldp.msg.tlv.er_hop.prefixlen", FT_UINT8, BASE_DEC, NULL, 0x0, "Prefix len", HFILL}},
2569
2570     { &hf_ldp_tlv_er_hop_prefix4,
2571       { "IPv4 Address", "ldp.msg.tlv.er_hop.prefix4", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Address", HFILL}},
2572    { &hf_ldp_tlv_er_hop_prefix6,
2573      { "IPv6 Address", "ldp.msg.tlv.er_hop.prefix6", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Address", HFILL}},
2574
2575     { &hf_ldp_tlv_er_hop_as,
2576       { "AS Number", "ldp.msg.tlv.er_hop.as", FT_UINT16, BASE_DEC, NULL, 0x0, "AS Number", HFILL}},
2577
2578     { &hf_ldp_tlv_er_hop_cr_lsp,
2579       { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.locallspid", FT_UINT16, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
2580
2581     { &hf_ldp_tlv_er_hop_ldpid,
2582       { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
2583
2584     { &hf_ldp_tlv_flags_reserv,
2585       { "Reserved", "ldp.msg.tlv.flags_reserv", FT_UINT8, BASE_HEX, NULL, 0xC0, "Reserved", HFILL}},
2586
2587     { &hf_ldp_tlv_flags_pdr,
2588       { "PDR", "ldp.msg.tlv.flags_pdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x1, "PDR negotiability flag", HFILL}},
2589
2590     { &hf_ldp_tlv_flags_pbs,
2591       { "PBS", "ldp.msg.tlv.flags_pbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x2, "PBS negotiability flag", HFILL}},
2592
2593     { &hf_ldp_tlv_flags_cdr,
2594       { "CDR", "ldp.msg.tlv.flags_cdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x4, "CDR negotiability flag", HFILL}},
2595
2596     { &hf_ldp_tlv_flags_cbs,
2597       { "CBS", "ldp.msg.tlv.flags_cbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x8, "CBS negotiability flag", HFILL}},
2598
2599     { &hf_ldp_tlv_flags_ebs,
2600       { "EBS", "ldp.msg.tlv.flags_ebs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x10, "EBS negotiability flag", HFILL}},
2601
2602     { &hf_ldp_tlv_flags_weight,
2603       { "Weight", "ldp.msg.tlv.flags_weight", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x20, "Weight negotiability flag", HFILL}},
2604
2605     { &hf_ldp_tlv_frequency,
2606       { "Frequency", "ldp.msg.tlv.frequency", FT_UINT8, BASE_DEC, VALS(freq_values), 0, "Frequency", HFILL}},
2607
2608     { &hf_ldp_tlv_weight,
2609       { "Weight", "ldp.msg.tlv.weight", FT_UINT8, BASE_DEC, NULL, 0, "Weight of the CR-LSP", HFILL}},
2610
2611     { &hf_ldp_tlv_pdr,
2612       { "PDR", "ldp.msg.tlv.pdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Data Rate", HFILL}},
2613
2614     { &hf_ldp_tlv_pbs,
2615       { "PBS", "ldp.msg.tlv.pbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Burst Size", HFILL}},
2616
2617     { &hf_ldp_tlv_cdr,
2618       { "CDR", "ldp.msg.tlv.cdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Data Rate", HFILL}},
2619
2620     { &hf_ldp_tlv_cbs,
2621       { "CBS", "ldp.msg.tlv.cbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Burst Size", HFILL}},
2622
2623     { &hf_ldp_tlv_ebs,
2624       { "EBS", "ldp.msg.tlv.ebs", FT_DOUBLE, BASE_NONE, NULL, 0, "Excess Burst Size", HFILL}},
2625
2626     { &hf_ldp_tlv_set_prio,
2627       { "Set Prio", "ldp.msg.tlv.set_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP setup priority", HFILL}},
2628
2629     { &hf_ldp_tlv_hold_prio,
2630       { "Hold Prio", "ldp.msg.tlv.hold_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP hold priority", HFILL}},
2631
2632     { &hf_ldp_tlv_route_pinning,
2633       { "Route Pinning", "ldp.msg.tlv.route_pinning", FT_UINT32, BASE_DEC, VALS(route_pinning_vals), 0x80000000, "Route Pinning", HFILL}},
2634
2635     { &hf_ldp_tlv_resource_class,
2636       { "Resource Class", "ldp.msg.tlv.resource_class", FT_UINT32, BASE_HEX, NULL, 0, "Resource Class (Color)", HFILL}},
2637
2638     { &hf_ldp_tlv_diffserv,
2639       { "Diff-Serv TLV", "ldp.msg.tlv.diffserv", FT_NONE, BASE_NONE, NULL,
2640         0, "Diffserv TLV", HFILL}},
2641
2642     { &hf_ldp_tlv_diffserv_type,
2643       { "LSP Type", "ldp.msg.tlv.diffserv.type", FT_UINT8, BASE_DEC,
2644         VALS(diffserv_type_vals), 0x80, "LSP Type", HFILL}},
2645
2646     { &hf_ldp_tlv_diffserv_mapnb,
2647       { "MAPnb", "ldp.msg.tlv.diffserv.mapnb", FT_UINT8, BASE_DEC, NULL,
2648         0, MAPNB_DESCRIPTION, HFILL}},
2649
2650     { &hf_ldp_tlv_diffserv_map,
2651       { "MAP", "ldp.msg.tlv.diffserv.map", FT_NONE, BASE_NONE, NULL,
2652         0, MAP_DESCRIPTION, HFILL}},
2653
2654     { &hf_ldp_tlv_diffserv_map_exp,
2655       { "EXP", "ldp.msg.tlv.diffserv.map.exp", FT_UINT8, BASE_DEC, NULL,
2656         0, EXP_DESCRIPTION, HFILL}},
2657
2658     { &hf_ldp_tlv_diffserv_phbid,
2659       { "PHBID", "ldp.msg.tlv.diffserv.phbid", FT_NONE, BASE_NONE, NULL,
2660         0, PHBID_DESCRIPTION, HFILL}},
2661
2662     { &hf_ldp_tlv_diffserv_phbid_dscp,
2663       { "DSCP", "ldp.msg.tlv.diffserv.phbid.dscp", FT_UINT16, BASE_DEC,
2664         NULL, PHBID_DSCP_MASK, PHBID_DSCP_DESCRIPTION, HFILL}},
2665
2666     { &hf_ldp_tlv_diffserv_phbid_code,
2667       { "PHB id code", "ldp.msg.tlv.diffserv.phbid.code", FT_UINT16, BASE_DEC,
2668         NULL, PHBID_CODE_MASK, PHBID_CODE_DESCRIPTION, HFILL}},
2669
2670     { &hf_ldp_tlv_diffserv_phbid_bit14,
2671       { "Bit 14", "ldp.msg.tlv.diffserv.phbid.bit14", FT_UINT16, BASE_DEC,
2672         VALS(phbid_bit14_vals), PHBID_BIT14_MASK, PHBID_BIT14_DESCRIPTION, HFILL}},
2673
2674     { &hf_ldp_tlv_diffserv_phbid_bit15,
2675       { "Bit 15", "ldp.msg.tlv.diffserv.phbid.bit15", FT_UINT16, BASE_DEC,
2676         VALS(phbid_bit15_vals), PHBID_BIT15_MASK, PHBID_BIT15_DESCRIPTION, HFILL}}
2677
2678   };
2679
2680   static gint *ett[] = {
2681     &ett_ldp,
2682     &ett_ldp_header,
2683     &ett_ldp_ldpid,
2684     &ett_ldp_message,
2685     &ett_ldp_tlv,
2686     &ett_ldp_tlv_val,
2687     &ett_ldp_fec,
2688     &ett_ldp_fec_vc_interfaceparam,
2689     &ett_ldp_diffserv_map,
2690     &ett_ldp_diffserv_map_phbid
2691   };
2692   module_t *ldp_module;
2693
2694   proto_ldp = proto_register_protocol("Label Distribution Protocol",
2695                                        "LDP", "ldp");
2696
2697   proto_register_field_array(proto_ldp, hf, array_length(hf));
2698   proto_register_subtree_array(ett, array_length(ett));
2699
2700   /* Register our configuration options for , particularly our port */
2701
2702   ldp_module = prefs_register_protocol(proto_ldp, proto_reg_handoff_ldp);
2703
2704   prefs_register_uint_preference(ldp_module, "tcp.port", "LDP TCP Port",
2705                                  "Set the TCP port for messages (if other"
2706                                  " than the default of 646)",
2707                                  10, &global_ldp_tcp_port);
2708
2709   prefs_register_uint_preference(ldp_module, "udp.port", "LDP UDP Port",
2710                                  "Set the UDP port for messages (if other"
2711                                  " than the default of 646)",
2712                                  10, &global_ldp_udp_port);
2713
2714   prefs_register_bool_preference(ldp_module, "desegment_ldp_messages",
2715     "Desegment all LDP messages\nspanning multiple TCP segments",
2716     "Whether the LDP dissector should desegment all messages spanning multiple TCP segments",
2717     &ldp_desegment);
2718 }
2719
2720 /* The registration hand-off routine */
2721 void
2722 proto_reg_handoff_ldp(void)
2723 {
2724   static gboolean ldp_prefs_initialized = FALSE;
2725   static dissector_handle_t ldp_tcp_handle, ldp_handle;
2726
2727   if (!ldp_prefs_initialized) {
2728
2729     ldp_tcp_handle = new_create_dissector_handle(dissect_ldp_tcp, proto_ldp);
2730     ldp_handle = new_create_dissector_handle(dissect_ldp, proto_ldp);
2731
2732     ldp_prefs_initialized = TRUE;
2733
2734   }
2735   else {
2736
2737     dissector_delete("tcp.port", tcp_port, ldp_tcp_handle);
2738     dissector_delete("udp.port", udp_port, ldp_handle);
2739
2740   }
2741
2742   /* Set our port number for future use */
2743
2744   tcp_port = global_ldp_tcp_port;
2745   udp_port = global_ldp_udp_port;
2746
2747   dissector_add("tcp.port", global_ldp_tcp_port, ldp_tcp_handle);
2748   dissector_add("udp.port", global_ldp_udp_port, ldp_handle);
2749
2750 }