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