On Windows, include "capture-wpcap.h", to define "has_wpcap".
[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.32 2002/04/08 20:30:52 gram Exp $
5  * 
6  * Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1999 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
37 #endif
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <ctype.h>
42 #include <time.h>
43 #include <glib.h>
44 #include <string.h>
45 #include <epan/packet.h>
46 #include <epan/resolv.h>
47 #include "prefs.h"
48 #include "afn.h"
49
50 #define TCP_PORT_LDP 646
51 #define UDP_PORT_LDP 646
52
53 void proto_reg_handoff_ldp(void);
54
55 static int proto_ldp = -1;
56
57 /* Delete the following if you do not use it, or add to it if you need */
58 static int hf_ldp_req = -1;
59 static int hf_ldp_rsp = -1;
60 static int hf_ldp_version = -1;
61 static int hf_ldp_pdu_len = -1;
62 static int hf_ldp_lsr = -1;
63 static int hf_ldp_ls_id = -1;
64 static int hf_ldp_msg_ubit = -1;
65 static int hf_ldp_msg_type = -1;
66 static int hf_ldp_msg_len = -1;
67 static int hf_ldp_msg_id = -1;
68 static int hf_ldp_msg_vendor_id = -1;
69 static int hf_ldp_msg_experiment_id = -1;
70 static int hf_ldp_tlv_value = -1;
71 static int hf_ldp_tlv_type = -1;
72 static int hf_ldp_tlv_unknown = -1;
73 static int hf_ldp_tlv_len = -1;
74 static int hf_ldp_tlv_val_hold = -1;
75 static int hf_ldp_tlv_val_target = -1;
76 static int hf_ldp_tlv_val_request = -1;
77 static int hf_ldp_tlv_val_res = -1;
78 static int hf_ldp_tlv_ipv4_taddr = -1;
79 static int hf_ldp_tlv_config_seqno = -1;
80 static int hf_ldp_tlv_ipv6_taddr = -1;
81 static int hf_ldp_tlv_fec_wc = -1;
82 static int hf_ldp_tlv_fec_af = -1;
83 static int hf_ldp_tlv_fec_len = -1;
84 static int hf_ldp_tlv_fec_pfval = -1;
85 static int hf_ldp_tlv_fec_hoval = -1;
86 static int hf_ldp_tlv_addrl_addr_family = -1;
87 static int hf_ldp_tlv_addrl_addr = -1;
88 static int hf_ldp_tlv_hc_value = -1;
89 static int hf_ldp_tlv_pv_lsrid = -1;
90 static int hf_ldp_tlv_generic_label = -1;
91 static int hf_ldp_tlv_atm_label_vbits = -1;
92 static int hf_ldp_tlv_atm_label_vpi = -1;
93 static int hf_ldp_tlv_atm_label_vci = -1;
94 static int hf_ldp_tlv_fr_label_len = -1;
95 static int hf_ldp_tlv_fr_label_dlci = -1;
96 static int hf_ldp_tlv_status_ebit = -1;
97 static int hf_ldp_tlv_status_fbit = -1;
98 static int hf_ldp_tlv_status_data = -1;
99 static int hf_ldp_tlv_status_msg_id = -1;
100 static int hf_ldp_tlv_status_msg_type = -1;
101 static int hf_ldp_tlv_extstatus_data = -1;
102 static int hf_ldp_tlv_returned_version = -1;
103 static int hf_ldp_tlv_returned_pdu_len = -1;
104 static int hf_ldp_tlv_returned_lsr = -1;
105 static int hf_ldp_tlv_returned_ls_id = -1;
106 static int hf_ldp_tlv_returned_msg_ubit = -1;
107 static int hf_ldp_tlv_returned_msg_type = -1;
108 static int hf_ldp_tlv_returned_msg_len = -1;
109 static int hf_ldp_tlv_returned_msg_id = -1;
110 static int hf_ldp_tlv_sess_ver = -1;
111 static int hf_ldp_tlv_sess_ka = -1;
112 static int hf_ldp_tlv_sess_advbit = -1;
113 static int hf_ldp_tlv_sess_ldetbit = -1;
114 static int hf_ldp_tlv_sess_pvlim = -1;
115 static int hf_ldp_tlv_sess_mxpdu = -1;
116 static int hf_ldp_tlv_sess_rxlsr = -1;
117 static int hf_ldp_tlv_sess_rxls = -1;
118 static int hf_ldp_tlv_sess_atm_merge = -1;
119 static int hf_ldp_tlv_sess_atm_lr = -1;
120 static int hf_ldp_tlv_sess_atm_dir = -1;
121 static int hf_ldp_tlv_sess_atm_minvpi = -1;
122 static int hf_ldp_tlv_sess_atm_maxvpi = -1;
123 static int hf_ldp_tlv_sess_atm_minvci = -1;
124 static int hf_ldp_tlv_sess_atm_maxvci = -1;
125 static int hf_ldp_tlv_sess_fr_merge = -1;
126 static int hf_ldp_tlv_sess_fr_lr = -1;
127 static int hf_ldp_tlv_sess_fr_dir = -1;
128 static int hf_ldp_tlv_sess_fr_len = -1;
129 static int hf_ldp_tlv_sess_fr_mindlci = -1;
130 static int hf_ldp_tlv_sess_fr_maxdlci = -1;
131 static int hf_ldp_tlv_lbl_req_msg_id = -1;
132 static int hf_ldp_tlv_vendor_id = -1;
133 static int hf_ldp_tlv_experiment_id = -1;
134 static int hf_ldp_tlv_fec_vc_controlword = -1;
135 static int hf_ldp_tlv_fec_vc_vctype = -1;
136 static int hf_ldp_tlv_fec_vc_infolength = -1;
137 static int hf_ldp_tlv_fec_vc_groupid = -1;
138 static int hf_ldp_tlv_fec_vc_vcid = -1; 
139 static int hf_ldp_tlv_fec_vc_intparam_length = -1;
140 static int hf_ldp_tlv_fec_vc_intparam_mtu = -1;
141 static int hf_ldp_tlv_fec_vc_intparam_id = -1;
142 static int hf_ldp_tlv_fec_vc_intparam_maxcatmcells = -1;
143 static int hf_ldp_tlv_fec_vc_intparam_desc = -1;
144 static int hf_ldp_tlv_fec_vc_intparam_cembytes = -1;
145 static int ett_ldp = -1;
146 static int ett_ldp_header = -1;
147 static int ett_ldp_ldpid = -1;
148 static int ett_ldp_message = -1;
149 static int ett_ldp_tlv = -1;
150 static int ett_ldp_tlv_val = -1;
151 static int ett_ldp_fec = -1;
152 static int ett_ldp_fec_vc_interfaceparam = -1;
153
154 static int tcp_port = 0;
155 static int udp_port = 0;
156
157 /* desegmentation of LDP over TCP */
158 static gboolean ldp_desegment = FALSE;
159
160 /* Add your functions here */
161
162 static int global_ldp_tcp_port = TCP_PORT_LDP;
163 static int global_ldp_udp_port = UDP_PORT_LDP;
164
165 /*
166  * The following define all the TLV types I know about
167  */
168
169 #define TLV_FEC                    0x0100
170 #define TLV_ADDRESS_LIST           0x0101
171 #define TLV_HOP_COUNT              0x0103
172 #define TLV_PATH_VECTOR            0x0104
173 #define TLV_GENERIC_LABEL          0x0200
174 #define TLV_ATM_LABEL              0x0201
175 #define TLV_FRAME_LABEL            0x0202
176 #define TLV_STATUS                 0x0300
177 #define TLV_EXTENDED_STATUS        0x0301
178 #define TLV_RETURNED_PDU           0x0302
179 #define TLV_RETURNED_MESSAGE       0x0303
180 #define TLV_COMMON_HELLO_PARMS     0x0400
181 #define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
182 #define TLV_CONFIGURATION_SEQNO    0x0402
183 #define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
184 #define TLV_COMMON_SESSION_PARMS   0x0500
185 #define TLV_ATM_SESSION_PARMS      0x0501
186 #define TLV_FRAME_RELAY_SESSION_PARMS 0x0502
187 #define TLV_LABEL_REQUEST_MESSAGE_ID 0x0600
188
189 #define TLV_VENDOR_PRIVATE_START   0x3E00
190 #define TLV_VENDOR_PRIVATE_END     0x3EFF
191 #define TLV_EXPERIMENTAL_START     0x3F00
192 #define TLV_EXPERIMENTAL_END       0x3FFF
193
194 static const value_string tlv_type_names[] = { 
195   { TLV_FEC,                       "Forwarding Equivalence Classes TLV" },
196   { TLV_ADDRESS_LIST,              "Address List TLV"},
197   { TLV_HOP_COUNT,                 "Hop Count TLV"},
198   { TLV_PATH_VECTOR,               "Path Vector TLV"},
199   { TLV_GENERIC_LABEL,             "Generic Label TLV"},
200   { TLV_ATM_LABEL,                 "ATM Label TLV"},
201   { TLV_FRAME_LABEL,               "Frame Label TLV"},
202   { TLV_STATUS,                    "Status TLV"},
203   { TLV_EXTENDED_STATUS,           "Extended Status TLV"},
204   { TLV_RETURNED_PDU,              "Returned PDU TLV"},
205   { TLV_RETURNED_MESSAGE,          "Returned Message TLV"},
206   { TLV_COMMON_HELLO_PARMS,        "Common Hello Parameters TLV"},
207   { TLV_IPV4_TRANSPORT_ADDRESS,    "IPv4 Transport Address TLV"},
208   { TLV_CONFIGURATION_SEQNO,       "Configuration Sequence Number TLV"},
209   { TLV_IPV6_TRANSPORT_ADDRESS,    "IPv6 Transport Address TLV"},
210   { TLV_COMMON_SESSION_PARMS,      "Common Session Parameters TLV"},
211   { TLV_ATM_SESSION_PARMS,         "ATM Session Parameters TLV"},
212   { TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters TLV"},
213   { TLV_LABEL_REQUEST_MESSAGE_ID,  "Label Request Message ID TLV"},
214   { TLV_VENDOR_PRIVATE_START,   "Vendor Private TLV"},
215   { TLV_EXPERIMENTAL_START,     "Experimental TLV"},
216   { 0, NULL}
217 };
218
219 /*
220  * The following define all the message types I know about
221  */
222
223 #define LDP_NOTIFICATION       0x0001
224 #define LDP_HELLO              0x0100
225 #define LDP_INITIALIZATION     0x0200
226 #define LDP_KEEPALIVE          0x0201
227 #define LDP_ADDRESS            0x0300
228 #define LDP_ADDRESS_WITHDRAWAL 0x0301
229 #define LDP_LABEL_MAPPING      0x0400
230 #define LDP_LABEL_REQUEST      0x0401
231 #define LDP_LABEL_WITHDRAWAL   0x0402
232 #define LDP_LABEL_RELEASE      0x0403
233 #define LDP_LABEL_ABORT_REQUEST 0x0404
234 #define LDP_VENDOR_PRIVATE_START 0x3E00
235 #define LDP_VENDOR_PRIVATE_END   0x3EFF
236 #define LDP_EXPERIMENTAL_MESSAGE_START 0x3F00
237 #define LDP_EXPERIMENTAL_MESSAGE_END   0x3FFF
238
239 static const value_string ldp_message_types[] = {
240   {LDP_NOTIFICATION,             "Notification Message"},
241   {LDP_HELLO,                    "Hello Message"},
242   {LDP_INITIALIZATION,           "Initialization Message"},
243   {LDP_KEEPALIVE,                "Keep Alive Message"},
244   {LDP_ADDRESS,                  "Address Message"},
245   {LDP_ADDRESS_WITHDRAWAL,       "Address Withdrawal Message"},
246   {LDP_LABEL_MAPPING,            "Label Mapping Message"},
247   {LDP_LABEL_REQUEST,            "Label Request Message"},
248   {LDP_LABEL_WITHDRAWAL,         "Label Withdrawal Message"},
249   {LDP_LABEL_RELEASE,            "Label Release Message"},
250   {LDP_LABEL_ABORT_REQUEST,      "Label Abort Request Message"},
251   {LDP_VENDOR_PRIVATE_START,     "Vendor-Private Message"},
252   {LDP_EXPERIMENTAL_MESSAGE_START,     "Experimental Message"},
253   {0, NULL}
254 };
255
256 static const true_false_string ldp_message_ubit = {
257   "Unknown bit set",
258   "Unknown bit not set"
259 };
260
261 static const true_false_string hello_targeted_vals = {
262   "Targeted Hello",
263   "Link Hello"
264 };
265
266 static const value_string tlv_unknown_vals[] = {
267   {0, "Known TLV"},
268   {1, "Known TLV"},
269   {2, "Unknown TLV, do not Forward"},
270   {3, "Unknown TLV, do Forward"},
271   {0, NULL}
272 };
273
274 #define WILDCARD_FEC    1
275 #define PREFIX_FEC      2
276 #define HOST_FEC        3
277 #define VC_FEC          0x80    /* draft-martini-l2circuit-trans-mpls */
278
279 static const value_string fec_types[] = {
280   {WILDCARD_FEC, "Wildcard FEC"},
281   {PREFIX_FEC, "Prefix FEC"},
282   {HOST_FEC, "Host Address FEC"},
283   {VC_FEC, "Virtual Circuit FEC"},
284   {0, NULL}
285 };
286
287
288 static const value_string fec_vc_types_vals[] = {
289   {0x0001, "Frame Relay DLCI"},
290   {0x0002, "ATM VCC transport"},
291   {0x0003, "ATM VPC transport"},
292   {0x0004, "Ethernet VLAN"},
293   {0x0005, "Ethernet"},
294   {0x0006, "HDLC"},
295   {0x0007, "PPP"},
296   {0x0009, "ATM VCC cell transport"},
297   {0x8008, "CEM"},
298   {0x000A, "ATM VPC cell transport"},
299   {0, NULL}
300 };
301
302
303 #define FEC_VC_INTERFACEPARAM_MTU          0x01
304 #define FEC_VC_INTERFACEPARAM_MAXCATMCELLS 0x02
305 #define FEC_VC_INTERFACEPARAM_DESCRIPTION  0x03
306 #define FEC_VC_INTERFACEPARAM_CEMBYTES     0x04
307 #define FEC_VC_INTERFACEPARAM_CEMOPTIONS   0x05
308
309
310 static const value_string fec_vc_interfaceparm[] = {
311   {FEC_VC_INTERFACEPARAM_MTU, "MTU"},
312   {FEC_VC_INTERFACEPARAM_MAXCATMCELLS, "Max Concatenated ATM cells"},
313   {FEC_VC_INTERFACEPARAM_DESCRIPTION, "Interface Description"},
314   {FEC_VC_INTERFACEPARAM_CEMBYTES, "CEM Payload Bytes"},
315   {FEC_VC_INTERFACEPARAM_CEMOPTIONS, "CEM options"}
316 };
317
318 static const true_false_string fec_vc_cbit = {
319   "Contorl Word Present",
320   "Control Word NOT Present"
321 };
322
323
324
325 static const value_string tlv_atm_merge_vals[] = {
326   {0, "Merge not supported"},
327   {1, "VP merge supported"},
328   {2, "VC merge supported"},
329   {3, "VP & VC merge supported"},
330   {0, NULL}
331 };
332
333 static const value_string tlv_atm_vbits_vals[] = {
334   {0, "VPI & VCI Significant"},
335   {1, "Only VPI Significant"},
336   {2, "Only VCI Significant"},
337   {3, "VPI & VCI not Significant, nonsense"},
338   {0, NULL}
339 };
340
341 static const value_string tlv_fr_merge_vals[] = {
342   {0, "Merge not supported"},
343   {1, "Merge supported"},
344   {2, "Unspecified"},
345   {3, "Unspecified"},
346   {0, NULL}
347 };
348
349 static const value_string tlv_fr_len_vals[] = {
350   {0, "10 bits"},
351   {1, "Reserved"},
352   {2, "23 bits"},
353   {3, "Reserved"},
354   {0, NULL}
355 };
356
357 static const true_false_string tlv_atm_dirbit = {
358   "Bidirectional capability",
359   "Unidirectional capability"
360 };
361
362 static const true_false_string hello_requested_vals = {
363   "Source requests periodic hellos",
364   "Source does not request periodic hellos"
365 };
366
367 static const true_false_string tlv_sess_advbit_vals = {
368   "Downstream On Demand proposed",
369   "Downstream Unsolicited proposed"
370 };
371
372 static const true_false_string tlv_sess_ldetbit_vals = {
373   "Loop Detection Enabled",
374   "Loop Detection Disabled"
375 };
376
377 static const true_false_string tlv_status_ebit = {
378   "Fatal Error Notification",
379   "Advisory Notification"
380 };
381
382 static const true_false_string tlv_status_fbit = {
383   "Notification should be Forwarded",
384   "Notification should NOT be Forwarded"
385 };
386
387 static const value_string tlv_status_data[] = {
388   {0, "Success"},
389   {1, "Bad LDP Identifier"},
390   {2, "Bad Protocol Version"},
391   {3, "Bad PDU Length"},
392   {4, "Unknown Message Type"},
393   {5, "Bad Message Length"},
394   {6, "Unknown TLV"},
395   {7, "Bad TLV Length"},
396   {8, "Malformed TLV Value"},
397   {9, "Hold Timer Expired"},
398   {10, "Shutdown"},
399   {11, "Loop Detected"},
400   {12, "Unknown FEC"},
401   {13, "No Route"},
402   {14, "No Label Resources"},
403   {15, "Label Resources / Available"},
404   {16, "Session Rejected / No Hello"},
405   {17, "Session Rejected / Parameters Advertisement Mode"},
406   {18, "Session Rejected / Parameters Max PDU Length"},
407   {19, "Session Rejected / Parameters Label Range"},
408   {20, "KeepAlive Timer Expired"},
409   {21, "Label Request Aborted"},
410   {22, "Missing Message Parameters"},
411   {23, "Unsoported Address Family"},
412   {24, "Session Rejected / Bad KeepAlive Time"},
413   {25, "Internal Error"},
414   {0x01000001,"Unexpected Diff-Serv TLV"},
415   {0x01000002,"Unsupported PHB"},
416   {0x01000003,"Invalid EXP<->PHB Mapping"},
417   {0x01000004,"Unsupported PSC"},
418   {0x01000005,"Per-LSP context allocation failure"},
419   {0x04000001,"Bad Explicit Routing TLV Error"},
420   {0x04000002,"Bad Strict Node Error"},
421   {0x04000003,"Bad Strict Node Error"},
422   {0x04000004,"Bad Initial ER-Hop Error"},
423   {0x04000005,"Resource Unavailable"},
424   {0x04000006,"Traffic Parameters Unavailable"},
425   {0x04000007,"LSP Preempted"},
426   {0x04000008,"Modify Request Not Supported"},
427   {0x20000001,"Illegal C-Bit"},
428   {0x20000002,"Wrong C-Bit"},
429   {0, NULL}
430 };
431
432 /* Dissect FEC TLV */
433
434 static void
435 dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
436 {
437         proto_tree *ti=NULL, *val_tree=NULL, *fec_tree=NULL, *vcintparam_tree=NULL;
438         guint16 family, ix=1, ax;
439         guint8  addr_size=0, *addr, implemented, prefix_len_octets, prefix_len, host_len, vc_len;
440         guint8  intparam_len;
441         void *str_handler=NULL;
442         char *str;
443
444         if (tree) {
445
446                 if( rem < 4 ) {
447                         proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
448                         return;
449                 }
450
451                 ti=proto_tree_add_text(tree, tvb, offset, rem, "FEC Elements");
452                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
453                 if(val_tree == NULL) return;
454
455                 while (rem > 0){
456                         switch (tvb_get_guint8(tvb, offset)) {
457                         case WILDCARD_FEC:
458                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4, "FEC Element %u", ix);
459                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
460                                 if(fec_tree == NULL) return;
461                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 4, FALSE);
462                                 rem -= 1;
463                                 offset += 1;
464                                 break;
465
466                         case PREFIX_FEC:
467                                 if( rem < 4 ){/*not enough*/
468                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
469                                         return;
470                                 }
471                                 family=tvb_get_ntohs(tvb, offset+1);
472                                 prefix_len=tvb_get_guint8(tvb, offset+3);
473                                 prefix_len_octets=(prefix_len+7)/8;
474                                 
475                                 implemented=1;
476                                 switch(family) {
477                                         case AFNUM_INET: /*IPv4*/
478                                                 addr_size=4;
479                                                 str_handler=ip_to_str;
480                                                 break;
481                                         case AFNUM_INET6: /*IPv6*/
482                                                 addr_size=16;
483                                                 str_handler=ip6_to_str;
484                                                 break;
485                                         default:
486                                                 implemented=0;
487                                                 break;
488                                 }
489
490                                 if( !implemented ) {
491                                         guint16 noctets;
492                                         
493                                         noctets= rem>4+prefix_len_octets?4+prefix_len_octets:rem;
494                                         proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
495                                         offset+=noctets;
496                                         rem-=noctets;
497                                         break;
498                                 }
499
500                                 if( rem < 4+MIN(addr_size, prefix_len_octets) ){
501                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
502                                         return;
503                                 }
504
505                                 /*Add a subtree for this*/
506                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4+MIN(addr_size, prefix_len_octets), "FEC Element %u", ix);
507                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
508                                 if(fec_tree == NULL) return;
509                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
510                                 offset += 1;
511
512                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
513                                 offset += 2;
514
515                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
516                                 offset += 1;
517                                 
518                                 
519                                 if( addr_size < prefix_len_octets) {
520                                         offset+=addr_size;
521                                         rem-=addr_size;
522                                         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"));
523                                         break;
524                                 }
525
526                                 if( (addr=g_malloc0(addr_size)) == NULL ){
527                                         /*big big trouble, no mem or bad addr_size*/
528                                         fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
529                                         return;
530                                 }
531                                 
532                                 for(ax=0; ax+1 <= prefix_len_octets; ax++)
533                                         addr[ax]=tvb_get_guint8(tvb, offset+ax);
534                                 if( prefix_len % 8 )
535                                         addr[ax-1] = addr[ax-1]&(0xFF<<(8-prefix_len%8));
536
537                                 str = (* (char* (*)(guint8 *))str_handler)(addr);
538                                 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, prefix_len_octets, str, "Prefix: %s", str);
539                                 
540                                 offset += prefix_len_octets;
541                                 rem -= 4+prefix_len_octets;
542                                 g_free(addr);
543                                 break;
544
545                         case HOST_FEC:
546                                 if( rem < 4 ){/*not enough*/
547                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
548                                         return;
549                                 }
550                                 family=tvb_get_ntohs(tvb, offset+1);
551                                 host_len=tvb_get_guint8(tvb, offset+3);
552
553                                 implemented=1;
554                                 switch(family) {
555                                         case AFNUM_INET: /*IPv4*/
556                                                 addr_size=4;
557                                                 str_handler=ip_to_str;
558                                                 break;
559                                         case AFNUM_INET6: /*IPv6*/
560                                                 addr_size=16;
561                                                 str_handler=ip6_to_str;
562                                                 break;
563                                         default:
564                                                 implemented=0;
565                                                 break;
566                                 }
567
568                                 if( !implemented ) {
569                                         guint16 noctets;
570                                         
571                                         noctets= rem>4+host_len?4+host_len:rem;
572                                         proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
573                                         offset+=noctets;
574                                         rem-=noctets;
575                                         break;
576                                 }
577
578                                 if( rem < 4+addr_size ){
579                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
580                                         return;
581                                 }
582
583                                 /*Add a subtree for this*/
584                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4+addr_size, "FEC Element %u", ix);
585                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
586                                 if(fec_tree == NULL) return;
587                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
588                                 offset += 1;
589
590                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
591                                 offset += 2;
592
593                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
594                                 offset += 1;
595                                 
596                                 
597                                 if( addr_size != host_len) {
598                                         offset+=addr_size;
599                                         rem-=addr_size;
600                                         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"));
601                                         break;
602                                 }
603
604                                 if( (addr=g_malloc0(addr_size)) == NULL ){
605                                         /*big big xtrouble, no mem or bad addr_size*/
606                                         fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
607                                         return;
608                                 }
609                                 
610                                 for(ax=0; ax+1 <= host_len; ax++)
611                                         addr[ax]=tvb_get_guint8(tvb, offset+ax);
612
613                                 str = (* (char* (*)(guint8 *))str_handler)(addr);
614                                 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_hoval, tvb, offset, host_len, str, "Address: %s", str);
615                                 
616                                 offset += host_len;
617                                 rem -= 4+host_len;
618                                 g_free(addr);
619                                 break;
620
621                         case VC_FEC:
622                           if( rem < 8 ){/*not enough bytes for a minimal VC_FEC*/
623                             proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
624                             return;
625                           }
626                           vc_len = tvb_get_guint8 (tvb, offset+3);
627
628
629                           ti = proto_tree_add_text(val_tree, tvb, offset, 8+vc_len, "FEC Element %u", ix);
630                           fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
631                           if(fec_tree == NULL) return;
632                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
633                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_controlword, tvb, offset+1, 1, FALSE);
634                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vctype, tvb, offset+1, 2, FALSE);
635                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_infolength, tvb, offset+3,1,FALSE);
636                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_groupid,tvb, offset +4, 4, FALSE);
637                           rem -=8;
638                           offset +=8;
639                           
640                           if ( (vc_len > 3) && ( rem > 3 ) ) { /* there is enough room for vcid */
641                             proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vcid,tvb, offset, 4, FALSE);
642                             proto_item_append_text (ti," VCID: %u",tvb_get_ntohl(tvb,offset));
643
644                           } else {                 
645                             proto_tree_add_text(val_tree,tvb,offset +4, 8 +vc_len, "VC FEC size format error");
646                             return;
647                           }
648                           rem -= 4;
649                           vc_len -= 4;
650                           offset += 4;
651
652                           while ( (vc_len > 1) && (rem > 1) ) { /* enough to include id and length */
653                             intparam_len = tvb_get_guint8(tvb, offset+1);
654                             ti = proto_tree_add_text(fec_tree, tvb, offset, 4, "Interface Paramameter");
655                             vcintparam_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam);
656                             if(vcintparam_tree == NULL) return;
657                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_id,tvb,offset,1,FALSE);
658                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_length,tvb, offset+1, 1, FALSE);
659                             if ( (vc_len -intparam_len) <0 && (rem -intparam_len) <0 ) { /* error condition */
660                               proto_tree_add_text(vcintparam_tree, tvb, offset +2, MIN(vc_len,rem), "malformed data");
661                               return;
662                             }
663                             switch (tvb_get_guint8(tvb, offset)) {
664                             case FEC_VC_INTERFACEPARAM_MTU:
665                               proto_item_append_text(ti,": MTU %u", tvb_get_ntohs(tvb,offset+2));
666                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_mtu,tvb, offset+2, 2, FALSE);
667                               break;
668                             case FEC_VC_INTERFACEPARAM_MAXCATMCELLS:
669                               proto_item_append_text(ti,": Max ATM Concat Cells %u", tvb_get_ntohs(tvb,offset+2));
670                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_maxcatmcells,tvb, offset+2, 2, FALSE);
671                               break;
672                             case FEC_VC_INTERFACEPARAM_DESCRIPTION:
673                               proto_item_append_text(ti,": Description");
674                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_desc,tvb, offset+2, (intparam_len -2), FALSE);
675                               break;
676                             case FEC_VC_INTERFACEPARAM_CEMBYTES:
677                               proto_item_append_text(ti,": CEM Payload Bytes %u", tvb_get_ntohs(tvb,offset+2));
678                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_cembytes,tvb, offset+2, 2, FALSE);
679                               break;
680                             case FEC_VC_INTERFACEPARAM_CEMOPTIONS:
681                                 /* draft-malis-sonet-ces-mpls CEM options still undefined */
682                             default: /* unknown */
683                               proto_item_append_text(ti," unknown");
684                               proto_tree_add_text(vcintparam_tree,tvb, offset+2, (intparam_len -2), "Unknown data");
685
686                               return;
687                             }
688                             rem -= intparam_len;
689                             vc_len -= intparam_len;
690                             offset += intparam_len;
691                           }
692                           break;
693
694                         default:  /* Unknown */
695                         /* XXX - do all FEC's have a length that's a multiple of 4? */
696                         /* Hmmm, don't think so. Will check. RJS. */
697                         /* If we don't know its structure, we have to exit */
698                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4, "FEC Element %u", ix);
699                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
700                                 if(fec_tree == NULL) return;
701                                 proto_tree_add_text(fec_tree, tvb, offset, rem, "Unknown FEC TLV type");
702                                 return;
703                         }
704                         ix++;
705                 }
706         }
707 }
708
709 /* Dissect Address List TLV */
710
711 void
712 dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
713 {
714         proto_tree *ti = NULL, *val_tree = NULL;
715         guint16 family, ix;
716         guint8  addr_size, *addr;
717         void *str_handler;
718         char *str;
719
720         if (tree) {
721                 if( rem < 2 ) {
722                         proto_tree_add_text(tree, tvb, offset, rem,
723                                          "Error processing TLV");
724                         return;
725                 }
726
727                 family=tvb_get_ntohs(tvb, offset);
728                 proto_tree_add_item(tree, hf_ldp_tlv_addrl_addr_family, tvb,
729                                          offset, 2, FALSE);
730                 switch(family) {
731                         case AFNUM_INET: /*IPv4*/
732                                 addr_size=4;
733                                 str_handler=ip_to_str;
734                                 break;
735                         case AFNUM_INET6: /*IPv6*/
736                                 addr_size=16;
737                                 str_handler=ip6_to_str;
738                                 break;
739                         default:
740                                 proto_tree_add_text(tree, tvb, offset+2, rem-2,
741                                  "Support for Address Family not implemented");
742                                 return;
743                 }
744
745                 offset+=2; rem-=2;
746                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Addresses");
747                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
748
749                 if(val_tree == NULL) return;
750                 if( (addr=g_malloc(addr_size)) == NULL ){
751                         /*big big trouble*/
752                         fprintf(stderr, "packet-ldp: dissect_tlv_address_list() malloc failed\n");
753                         return;
754                 }
755
756                 for(ix=1; rem >= addr_size; ix++, offset += addr_size,
757                                                          rem -= addr_size) {
758                         if( (tvb_memcpy(tvb, addr, offset, addr_size))
759                                                          == NULL)
760                                 break;
761
762                         str = (* (char* (*)(guint8 *))str_handler)(addr);
763                         proto_tree_add_string_format(val_tree,
764                         hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
765                         "Address %u: %s", ix, str);
766                 }
767                 if(rem)
768                         proto_tree_add_text(val_tree, tvb, offset, rem,
769                                          "Error processing TLV");
770                 g_free(addr);
771         }
772 }
773
774 /* Dissect Path Vector TLV */
775
776 void
777 dissect_tlv_path_vector(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
778 {
779         proto_tree *ti = NULL, *val_tree = NULL;
780         guint8  ix;
781         guint32 addr;
782
783         if (tree) {
784                 ti=proto_tree_add_text(tree, tvb, offset, rem, "LSR IDs");
785                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
786
787                 if(val_tree == NULL) return;
788
789                 for(ix=1; rem >= 4; ix++, offset += 4, rem -= 4) {
790                         tvb_memcpy(tvb, (guint8 *)&addr, offset, 4);
791                         proto_tree_add_ipv4_format(val_tree,
792                             hf_ldp_tlv_pv_lsrid, tvb, offset, 4,
793                             addr, "LSR Id %u: %s", ix,
794                             ip_to_str((guint8 *)&addr));
795                 }
796                 if(rem)
797                         proto_tree_add_text(val_tree, tvb, offset, rem,
798                                          "Error processing TLV");
799         }
800 }
801
802 /* Dissect ATM Label TLV */
803
804 void
805 dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
806 {
807         proto_tree *ti = NULL, *val_tree = NULL;
808         guint16 id;
809
810         if(tree) {
811                 if(rem != 4){
812                         proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
813                         return;
814                 }
815                 ti=proto_tree_add_text(tree, tvb, offset, rem, "ATM Label");
816                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
817                 if(val_tree == NULL) return;
818
819                 proto_tree_add_item(val_tree, hf_ldp_tlv_atm_label_vbits, tvb, offset, 1, FALSE);
820
821                 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
822                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id); 
823                         
824                 id=tvb_get_ntohs(tvb, offset+2);
825                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id); 
826         }
827 }
828
829 /* Dissect FRAME RELAY Label TLV */
830
831 void
832 dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
833 {
834         proto_tree *ti = NULL, *val_tree = NULL;
835         guint8  len;
836         guint32 id;
837
838         if(tree) {
839                 if(rem != 4){
840                         proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
841                         return;
842                 }
843                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Frame Relay Label");
844                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
845                 if(val_tree == NULL) return;
846
847                 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
848                 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); 
849
850                 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
851                 proto_tree_add_uint_format(val_tree, 
852                 hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id); 
853         }
854 }
855
856 /* Dissect STATUS TLV */
857
858 void
859 dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
860 {
861         proto_tree *ti = NULL, *val_tree = NULL;
862         guint32 data;
863
864         if(tree) {
865                 if(rem != 10){
866                         proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
867                         return;
868                 }
869
870                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Status");
871                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
872                 if(val_tree == NULL) return;
873
874                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE); 
875                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE); 
876
877                 data=tvb_get_ntohl(tvb, offset)&0x3FFFFFFF;
878                 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); 
879
880                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE); 
881                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE); 
882         }
883 }
884
885 /* Dissect Returned PDU TLV */
886
887 void
888 dissect_tlv_returned_pdu(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
889 {
890         proto_tree *ti = NULL, *val_tree = NULL;
891
892         if(tree) {
893                 if(rem < 10){
894                         proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
895                         return;
896                 }
897                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned PDU");
898                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
899                 if(val_tree == NULL) return;
900
901                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE); 
902                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE); 
903                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE); 
904                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE); 
905                 offset += 10;
906                 rem -= 10;
907
908                 if( rem > 0 ) {
909                 /*XXX - dissect returned pdu data*/
910                         proto_tree_add_text(val_tree, tvb, offset, rem, "Returned PDU Data");
911                 }
912         }
913 }
914
915 /* Dissect Returned MESSAGE TLV */
916
917 void
918 dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
919 {
920         proto_tree *ti = NULL, *val_tree = NULL;
921         guint16 type;
922
923         if(tree) {
924                 if(rem < 4){
925                         proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
926                         return;
927                 }
928                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned Message");
929                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
930                 if(val_tree == NULL) return;
931
932                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE); 
933
934                 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
935                 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); 
936
937                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE); 
938                 offset += 4;
939                 rem -= 4;
940
941                 if( rem >= 4  ) { /*have msg_id*/
942                         proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE); 
943                         offset += 4;
944                         rem -= 4;
945                 }
946
947                 if( rem > 0 ) {
948                 /*XXX - dissect returned msg parameters*/
949                         proto_tree_add_text(val_tree, tvb, offset, rem, "Returned Message Parameters");
950                 }
951         }
952 }
953
954 /* Dissect the common hello params */
955
956 void 
957 dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
958 {
959         proto_tree *ti = NULL, *val_tree = NULL;
960
961         if (tree) {
962 #if 0
963                 ti = proto_tree_add_item(tree, hf_ldp_tlv_value, tvb, offset, rem, FALSE);
964                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
965                 if(val_tree == NULL) return;
966 #else
967                 val_tree=tree;
968 #endif
969                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
970                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 1, FALSE);
971                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 1, FALSE);
972                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_res, tvb, offset + 2, 2, FALSE);
973         }
974 }
975
976 /* Dissect the common session params */
977
978 void 
979 dissect_tlv_common_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
980 {
981         proto_tree *ti = NULL, *val_tree = NULL;
982
983         if (tree != NULL) {
984                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
985                 if( rem != 14) { /*length of Comm Sess Parms tlv*/
986                         proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
987                         return ;
988                 }
989                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
990
991                 if(val_tree != NULL) {
992                         /*Protocol Version*/
993                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE); 
994
995                         /*KeepAlive Time*/
996                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ka, tvb,offset + 2, 2, FALSE);
997
998                         /*A bit*/
999                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_advbit,tvb, offset + 4, 1, FALSE);
1000                                          
1001                         /*D bit*/
1002                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ldetbit,tvb, offset + 4, 1, FALSE);
1003                                          
1004                         /*Path Vector Limit*/
1005                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_pvlim,tvb, offset + 5, 1, FALSE);
1006                                          
1007                         /*Max PDU Length*/
1008                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_mxpdu,tvb, offset + 6, 2, FALSE);
1009                                          
1010                         /*Rx LSR*/
1011                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxlsr,tvb, offset + 8, 4, FALSE);
1012                                          
1013                         /*Rx LS*/
1014                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxls,tvb, offset + 12, 2, FALSE);
1015                 }
1016         }
1017 }
1018
1019 /* Dissect the atm session params */
1020
1021 void 
1022 dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1023 {
1024         proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1025         guint8 numlr, ix;
1026         guint16 id;
1027
1028         if (tree != NULL) {
1029                 if(rem < 4) {
1030                         proto_tree_add_text(tree, tvb, offset, rem,
1031                                                  "Error processing TLV");
1032                         return;
1033                 }
1034
1035                 ti = proto_tree_add_text(tree, tvb, offset, rem,"ATM Parameters");
1036                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1037
1038                 if(val_tree != NULL) {
1039                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE); 
1040
1041                         /*get the number of label ranges*/      
1042                         numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1043                         proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_atm_lr,
1044                         tvb, offset, 1, numlr, "Number of Label Range components: %u",
1045                         numlr); 
1046
1047                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE); 
1048
1049                         /*move into range components*/
1050                         offset += 4;
1051                         rem -= 4;
1052                         ti = proto_tree_add_text(val_tree, tvb, offset, rem,"ATM Label Range Components");
1053                                  
1054                         if(numlr) {
1055                                 val_tree=proto_item_add_subtree(ti,ett_ldp_tlv_val);
1056                                 if( ! val_tree ) return;
1057                         }
1058                         /*now dissect ranges*/
1059                         for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1060                                 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1061                                  "ATM Label Range Component %u", ix);
1062                                 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1063
1064                                 if( lbl_tree == NULL ) break;
1065
1066                                 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
1067                                 proto_tree_add_uint_format(lbl_tree, 
1068                         hf_ldp_tlv_sess_atm_minvpi,tvb, offset, 2, id, "Minimum VPI: %u", id); 
1069                                 id=tvb_get_ntohs(tvb, offset+4)&0x0FFF;
1070                                 proto_tree_add_uint_format(lbl_tree, 
1071                         hf_ldp_tlv_sess_atm_maxvpi,tvb, (offset+4), 2, id, "Maximum VPI: %u", id); 
1072                                  
1073                                 id=tvb_get_ntohs(tvb, offset+2);
1074                                 proto_tree_add_uint_format(lbl_tree, 
1075                         hf_ldp_tlv_sess_atm_minvci,tvb, offset+2, 2, id, "Minimum VCI: %u", id); 
1076                                 id=tvb_get_ntohs(tvb, offset+6);
1077                                 proto_tree_add_uint_format(lbl_tree, 
1078                         hf_ldp_tlv_sess_atm_maxvci,tvb, offset+6, 2, id, "Maximum VCI: %u", id); 
1079
1080                                 offset += 8;
1081                         }
1082                         if( rem || numlr)
1083                                 proto_tree_add_text(val_tree, tvb, offset, rem,"Error processing TLV");
1084                 }
1085         }
1086 }
1087
1088 /* Dissect the frame relay session params */
1089
1090 void 
1091 dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
1092 {
1093         proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1094         guint8 numlr, ix, len;
1095         guint32 id;
1096
1097         if (tree != NULL) {
1098                 if(rem < 4) {
1099                         proto_tree_add_text(tree, tvb, offset, rem,
1100                                                  "Error processing TLV");
1101                         return;
1102                 }
1103
1104                 ti = proto_tree_add_text(tree, tvb, offset, rem,
1105                                                  "Frame Relay Parameters");
1106                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1107
1108                 if(val_tree != NULL) {
1109                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_merge,
1110                                 tvb, offset, 1, FALSE); 
1111
1112                         /*get the number of label ranges*/      
1113                         numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1114                         proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_fr_lr,
1115                         tvb, offset, 1, numlr, "Number of Label Range components: %u",
1116                         numlr); 
1117
1118                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_dir,
1119                                  tvb, offset, 1, FALSE); 
1120
1121                         /*move into range components*/
1122                         offset += 4;
1123                         rem -= 4;
1124                         ti = proto_tree_add_text(val_tree, tvb, offset, rem,
1125                                  "Frame Relay Label Range Components");
1126
1127                         if(numlr) {
1128                                 val_tree=proto_item_add_subtree(ti,
1129                                                          ett_ldp_tlv_val);
1130                                 if( ! val_tree ) return;
1131                         }
1132
1133                         /*now dissect ranges*/
1134                         for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1135                                 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1136                                 "Frame Relay Label Range Component %u", ix);
1137                                 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1138
1139                                 if( lbl_tree == NULL ) break;
1140
1141                                 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
1142                                 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); 
1143
1144                                 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
1145                                 proto_tree_add_uint_format(lbl_tree, 
1146                         hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id); 
1147                                 id=tvb_get_ntoh24(tvb, offset+5)&0x7FFFFF;
1148                                 proto_tree_add_uint_format(lbl_tree, 
1149                         hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id); 
1150
1151                                 offset += 8;
1152                         }
1153
1154                         if( rem || numlr)
1155                                 proto_tree_add_text(val_tree, tvb, offset, rem,
1156                                  "Error processing TLV");
1157                 }
1158         }
1159 }
1160
1161
1162 /* Dissect a TLV and return the number of bytes consumed ... */
1163
1164 int
1165 dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1166 {
1167         guint16 type, typebak;
1168         int length;
1169         proto_tree *ti = NULL, *tlv_tree = NULL;
1170
1171         length=tvb_reported_length_remaining(tvb, offset);
1172         rem=MIN(rem, length);
1173
1174         if( rem < 4 ) {/*chk for minimum header*/
1175                 if(tree)
1176                         proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
1177                 return rem;
1178         }
1179         type = tvb_get_ntohs(tvb, offset) & 0x3FFF;
1180
1181         length = tvb_get_ntohs(tvb, offset + 2),
1182         rem -= 4; /*do not count header*/
1183         length = MIN(length, rem);  /* Don't go haywire if a problem ... */
1184
1185         if (tree != NULL) {
1186                 /*chk for vendor-private*/
1187                 if(type>=TLV_VENDOR_PRIVATE_START && type<=TLV_VENDOR_PRIVATE_END){
1188                         typebak=type;           /*keep type*/   
1189                         type=TLV_VENDOR_PRIVATE_START;
1190
1191                 /*chk for experimental*/
1192                 } else if(type>=TLV_EXPERIMENTAL_START && type<=TLV_EXPERIMENTAL_END){
1193                         typebak=type;           /*keep type*/   
1194                         type=TLV_EXPERIMENTAL_START;
1195                 }
1196
1197                 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
1198                         val_to_str(type, tlv_type_names, "Unknown TLV type (0x%04X)"));
1199                 tlv_tree = proto_item_add_subtree(ti, ett_ldp_tlv);
1200                 if(tlv_tree == NULL) return length+4;
1201
1202                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_unknown, tvb, offset, 1, FALSE);
1203
1204                 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 ); 
1205
1206                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
1207
1208                 switch (type) {
1209
1210                 case TLV_FEC:
1211                         dissect_tlv_fec(tvb, offset + 4, tlv_tree, length);
1212                         break;
1213
1214                 case TLV_ADDRESS_LIST:
1215                         dissect_tlv_address_list(tvb, offset + 4, tlv_tree, length);
1216                         break;
1217
1218                 case TLV_HOP_COUNT:
1219                         if( length != 1 ) /*error, only one byte*/
1220                                 proto_tree_add_text(tlv_tree, tvb, offset + 4,length,"Error processing TLV");
1221                         else
1222                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE); 
1223                         break;
1224
1225                 case TLV_PATH_VECTOR:
1226                         dissect_tlv_path_vector(tvb, offset + 4, tlv_tree, length);
1227                         break;
1228
1229                 case TLV_GENERIC_LABEL:
1230                         if( length != 4 ) /*error, need only label*/
1231                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1232                         else {
1233                                 guint32 label=tvb_get_ntohl(tvb, offset+4) & 0x000FFFFF;
1234
1235                                 proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_generic_label,
1236                                         tvb, offset+4, length, label, "Generic Label: %u", label); 
1237                         }
1238                         break;
1239
1240                 case TLV_ATM_LABEL:
1241                         dissect_tlv_atm_label(tvb, offset + 4, tlv_tree, length);
1242                         break;
1243
1244                 case TLV_FRAME_LABEL:
1245                         dissect_tlv_frame_label(tvb, offset + 4, tlv_tree, length);
1246                         break;
1247
1248                 case TLV_STATUS:
1249                         dissect_tlv_status(tvb, offset + 4, tlv_tree, length);
1250                         break;
1251
1252                 case TLV_EXTENDED_STATUS:
1253                         if( length != 4 ) /*error, need only status_code(guint32)*/
1254                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1255                         else {
1256                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE); 
1257                         }
1258                         break;
1259
1260                 case TLV_RETURNED_PDU:
1261                         dissect_tlv_returned_pdu(tvb, offset + 4, tlv_tree, length);
1262                         break;
1263
1264                 case TLV_RETURNED_MESSAGE:
1265                         dissect_tlv_returned_message(tvb, offset + 4, tlv_tree, length);
1266                         break;
1267
1268                 case TLV_COMMON_HELLO_PARMS:
1269                         dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
1270                         break;
1271
1272                 case TLV_IPV4_TRANSPORT_ADDRESS:
1273                         if( length != 4 ) /*error, need only ipv4*/
1274                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1275                         else {
1276                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv4_taddr, tvb, offset + 4, 4, FALSE);
1277                         }
1278                         break;
1279
1280                 case TLV_CONFIGURATION_SEQNO:
1281                         if( length != 4 ) /*error, need only seq_num(guint32)*/
1282                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1283                         else {
1284                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
1285                         }
1286                         break;
1287
1288                 case TLV_IPV6_TRANSPORT_ADDRESS:
1289                         if( length != 16 ) /*error, need only ipv6*/
1290                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1291                         else {
1292                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv6_taddr, tvb, offset + 4, 16, FALSE);
1293                         }
1294                         break;
1295
1296                 case TLV_COMMON_SESSION_PARMS:
1297                         dissect_tlv_common_session_parms(tvb, offset + 4, tlv_tree, length);
1298                         break;
1299
1300                 case TLV_ATM_SESSION_PARMS:
1301                         dissect_tlv_atm_session_parms(tvb, offset + 4, tlv_tree, length);
1302                         break;
1303
1304                 case TLV_FRAME_RELAY_SESSION_PARMS:
1305                         dissect_tlv_frame_relay_session_parms(tvb, offset + 4, tlv_tree, length);
1306                         break;
1307
1308                 case TLV_LABEL_REQUEST_MESSAGE_ID:
1309                         if( length != 4 ) /*error, need only one msgid*/
1310                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1311                         else
1312                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE); 
1313                         break;
1314
1315                 case TLV_VENDOR_PRIVATE_START:
1316                         if( length < 4 ) /*error, at least Vendor ID*/
1317                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1318                         else {
1319                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE); 
1320                                 if( length > 4 )  /*have data*/ 
1321                                         proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
1322                         }
1323                         break;
1324
1325                 case TLV_EXPERIMENTAL_START:
1326                         if( length < 4 ) /*error, at least Experiment ID*/
1327                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1328                         else {
1329                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE); 
1330                                 if( length > 4 )  /*have data*/ 
1331                                         proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
1332                         }
1333                         break;
1334
1335                 default:
1336                         proto_tree_add_item(tlv_tree, hf_ldp_tlv_value, tvb, offset + 4, length, FALSE);
1337                         break;
1338                 }
1339         }
1340
1341         return length + 4;  /* Length of the value field + header */
1342 }
1343
1344
1345 /* Dissect a Message and return the number of bytes consumed ... */
1346
1347 int
1348 dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, int rem)
1349 {
1350         guint16 type, typebak;
1351         guint8  extra=0;
1352         int length, ao=0, co;
1353         proto_tree *ti = NULL, *msg_tree = NULL;
1354
1355         length=tvb_reported_length_remaining(tvb, offset);
1356         rem=MIN(rem, length);
1357
1358         if( rem < 8 ) {/*chk for minimum header = type + length + msg_id*/
1359                 if( check_col(pinfo->cinfo, COL_INFO) )
1360                         col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message");
1361                 if(tree)
1362                         proto_tree_add_text(tree, tvb, offset, rem,"Error processing Message");
1363                 return rem;
1364         }
1365         type = tvb_get_ntohs(tvb, offset) & 0x7FFF;
1366
1367         /*chk for vendor-private*/
1368         if(type>=LDP_VENDOR_PRIVATE_START && type<=LDP_VENDOR_PRIVATE_END){
1369                 typebak=type;           /*keep type*/   
1370                 type=LDP_VENDOR_PRIVATE_START;
1371                 extra=4;
1372         /*chk for experimental*/
1373         } else if(type>=LDP_EXPERIMENTAL_MESSAGE_START && type<=LDP_EXPERIMENTAL_MESSAGE_END){
1374                 typebak=type;           /*keep type*/   
1375                 type=LDP_EXPERIMENTAL_MESSAGE_START;
1376                 extra=4;
1377         }
1378
1379         if( (length = tvb_get_ntohs(tvb, offset + 2)) < (4+extra) ) {/*not enough data for type*/
1380                 if( check_col(pinfo->cinfo, COL_INFO) )
1381                         col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message Length ");
1382                 if(tree)
1383                         proto_tree_add_text(tree, tvb, offset, rem,"Error processing Message Length");
1384                 return rem;
1385         }
1386         rem -= 4; 
1387         length = MIN(length, rem);  /* Don't go haywire if a problem ... */
1388
1389         if( check_col(pinfo->cinfo, COL_INFO) ){
1390                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, ldp_message_types, "Unknown Message (0x%04X)"));
1391         }
1392
1393         if( tree ){
1394                 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
1395                         val_to_str(type, ldp_message_types, "Unknown Message type (0x%04X)"));
1396                 msg_tree = proto_item_add_subtree(ti, ett_ldp_message);
1397                 if(msg_tree == NULL) return length+4;
1398
1399                 proto_tree_add_item(msg_tree, hf_ldp_msg_ubit, tvb, offset, 1, FALSE);
1400
1401                 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
1402                 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); 
1403
1404                 proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset+2, 2, FALSE);
1405                 proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset+4, 4, FALSE);
1406                 if(extra){
1407                         int hf_tmp=0;
1408
1409                         switch(type){
1410                                 case LDP_VENDOR_PRIVATE_START:
1411                                         hf_tmp=hf_ldp_msg_vendor_id;
1412                                         break;
1413                                 case LDP_EXPERIMENTAL_MESSAGE_START:
1414                                         hf_tmp=hf_ldp_msg_experiment_id;
1415                                         break;
1416                         }
1417                         proto_tree_add_item(msg_tree, hf_tmp, tvb, offset+8, extra, FALSE);
1418                 }
1419         }
1420                 
1421         offset += (8+extra);
1422         length -= (4+extra);
1423         
1424         if( tree )      
1425                 while( (length-ao) > 0 ) {
1426                         co=dissect_tlv(tvb, offset, msg_tree, length-ao);
1427                         offset += co;
1428                         ao += co;
1429                 }
1430         
1431         return length+8+extra;
1432 }
1433
1434 /* Dissect a PDU and return the number of bytes consumed ... */
1435
1436 int
1437 dissect_ldp_pdu(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, int rem, guint ix)
1438 {
1439         int length, ao=0, co;
1440         proto_tree *ti=NULL, *pdu_tree = NULL;
1441         
1442         length=tvb_reported_length_remaining(tvb, offset);
1443         rem=MIN(rem, length);
1444         
1445         if( rem < 10 ){/*don't even have a PDU header*/
1446 /*XXX Need changes in desegment_tcp to handle multiple requests*/
1447 #if 0
1448                 if( pinfo->can_desegment && (pinfo->ptype==PT_TCP) && ldp_desegment ){
1449                         pinfo->desegment_offset=offset;
1450                         pinfo->desegment_len=10-rem;
1451                 }
1452 #else
1453                 if(tree)
1454                         proto_tree_add_text(tree, tvb, offset, rem,"Not enough bytes for PDU Hdr in TCP segment");
1455 #endif
1456                 return rem;
1457         }
1458
1459         if( (length = tvb_get_ntohs(tvb, offset + 2)) < 6 ) {/*not enough*/
1460                 if( check_col(pinfo->cinfo, COL_INFO) && ix )
1461                         col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
1462                 if( check_col(pinfo->cinfo, COL_INFO) ){
1463                         col_append_fstr(pinfo->cinfo, COL_INFO, "Bad PDU Length ");
1464                 }
1465                 if(tree)
1466                         proto_tree_add_text(tree, tvb, offset, rem,"Error processing PDU Length");
1467                 return rem;
1468         }
1469
1470         rem -=4;
1471         if( length>rem ){
1472                 if( pinfo->can_desegment && (pinfo->ptype==PT_TCP) && ldp_desegment ){/*ask for more*/
1473                         pinfo->desegment_offset=offset;
1474                         pinfo->desegment_len=length-rem;
1475                 }else {
1476                         if( check_col(pinfo->cinfo, COL_INFO) && ix )
1477                                 col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
1478                         if( check_col(pinfo->cinfo, COL_INFO) )
1479                                 col_append_fstr(pinfo->cinfo, COL_INFO, "Bad PDU Length ");
1480                         if(tree)
1481                                 proto_tree_add_text(tree, tvb, offset, rem+4,"Error processing PDU Length");
1482                 }
1483                 return rem+4;
1484         }
1485         
1486         if( check_col(pinfo->cinfo, COL_INFO) && ix )
1487                 col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
1488
1489         if( tree ){
1490                 ti=proto_tree_add_protocol_format(tree, proto_ldp, tvb, offset,
1491                     length+4, ix?"LDP PDU %u":"LDP PDU", ix);
1492                 pdu_tree = proto_item_add_subtree(ti, ett_ldp);
1493         }
1494
1495         if(pdu_tree){
1496                 proto_tree_add_item(pdu_tree, hf_ldp_version, tvb, offset, 2, FALSE);
1497                 proto_tree_add_item(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, FALSE);
1498                 proto_tree_add_item(pdu_tree, hf_ldp_lsr, tvb, offset+4, 4, FALSE);
1499                 proto_tree_add_item(pdu_tree, hf_ldp_ls_id, tvb, offset+8, 2, FALSE);
1500         }
1501         offset += 10;
1502         length -= 6;
1503
1504         while( (length-ao) > 0 ) {
1505                 co=dissect_msg(tvb, offset, pinfo, pdu_tree, length-ao);
1506                 offset += co;
1507                 ao += co;
1508         }
1509         
1510         return length+10;
1511 }
1512
1513 static void
1514 dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1515 {
1516         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1517                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
1518
1519         if (check_col(pinfo->cinfo, COL_INFO))
1520                 col_clear(pinfo->cinfo, COL_INFO);
1521
1522         dissect_ldp_pdu(tvb, 0, pinfo, tree, tvb_reported_length(tvb), 0);
1523 }
1524
1525 static void
1526 dissect_ldp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1527
1528         int offset=0, length, rtn;
1529         guint ix=1;
1530   
1531
1532         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1533                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
1534
1535         if (check_col(pinfo->cinfo, COL_INFO))
1536                 col_clear(pinfo->cinfo, COL_INFO);
1537
1538         length=tvb_reported_length(tvb);
1539         while (length > 0){
1540                 rtn = dissect_ldp_pdu(tvb, offset, pinfo, tree, length, ix++);
1541                 offset += rtn;
1542                 length -= rtn;
1543         }
1544 }
1545
1546 /* Register all the bits needed with the filtering engine */
1547
1548 void 
1549 proto_register_ldp(void)
1550 {
1551   static hf_register_info hf[] = {
1552     { &hf_ldp_req,
1553       /* Change the following to the type you need */
1554       { "Request", "ldp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
1555
1556     { &hf_ldp_rsp,
1557       { "Response", "ldp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
1558
1559     { &hf_ldp_version,
1560       { "Version", "ldp.hdr.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
1561
1562     { &hf_ldp_pdu_len,
1563       { "PDU Length", "ldp.hdr.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
1564
1565     { &hf_ldp_lsr,
1566       { "LSR ID", "ldp.hdr.ldpid.lsr", FT_IPv4, BASE_HEX, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
1567
1568     { &hf_ldp_ls_id,
1569       { "Label Space ID", "ldp.hdr.ldpid.lsid", FT_UINT16, BASE_DEC, NULL, 0, "LDP Label Space ID", HFILL }},
1570
1571     { &hf_ldp_msg_ubit,
1572       { "U bit", "ldp.msg.ubit", FT_BOOLEAN, 8, TFS(&ldp_message_ubit), 0x80, "Unknown Message Bit", HFILL }},
1573
1574     { &hf_ldp_msg_type,
1575       { "Message Type", "ldp.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
1576
1577     { &hf_ldp_msg_len,
1578       { "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
1579
1580     { &hf_ldp_msg_id, 
1581       { "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
1582
1583     { &hf_ldp_msg_vendor_id, 
1584       { "Vendor ID", "ldp.msg.vendor.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Vendor-private Message ID", HFILL }},
1585
1586     { &hf_ldp_msg_experiment_id, 
1587       { "Experiment ID", "ldp.msg.experiment.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Experimental Message ID", HFILL }},
1588
1589     { &hf_ldp_tlv_unknown, 
1590       { "TLV Unknown bits", "ldp.msg.tlv.unknown", FT_UINT8, BASE_HEX, VALS(tlv_unknown_vals), 0xC0, "TLV Unknown bits Field", HFILL }},
1591
1592     { &hf_ldp_tlv_type, 
1593       { "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x3FFF, "TLV Type Field", HFILL }},
1594
1595     { &hf_ldp_tlv_len,
1596       {"TLV Length", "ldp.msg.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0, "TLV Length Field", HFILL }},
1597
1598     { &hf_ldp_tlv_value,
1599       { "TLV Value", "ldp.msg.tlv.value", FT_BYTES, BASE_NONE, NULL, 0x0, "TLV Value Bytes", HFILL }},
1600
1601     { &hf_ldp_tlv_val_hold,
1602       { "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time", HFILL }},
1603
1604     { &hf_ldp_tlv_val_target,
1605       { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 8, TFS(&hello_targeted_vals), 0x80, "Hello Common Parameters Targeted Bit", HFILL }},
1606
1607     { &hf_ldp_tlv_val_request,
1608       { "Hello Requested", "ldp,msg.tlv.hello.requested", FT_BOOLEAN, 8, TFS(&hello_requested_vals), 0x40, "Hello Common Parameters Hello Requested Bit", HFILL }},
1609  
1610     { &hf_ldp_tlv_val_res,
1611       { "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field", HFILL }},
1612
1613     { &hf_ldp_tlv_ipv4_taddr,
1614       { "IPv4 Transport Address", "ldp.msg.tlv.ipv4.taddr", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Transport Address", HFILL }},
1615
1616     { &hf_ldp_tlv_config_seqno,
1617       { "Configuration Sequence Number", "ldp.msg.tlv.hello.cnf_seqno", FT_UINT32, BASE_DEC, NULL, 0x0, "Hello Configuration Sequence Number", HFILL }},
1618
1619     { &hf_ldp_tlv_ipv6_taddr,
1620       { "IPv6 Transport Address", "ldp.msg.tlv.ipv6.taddr", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Transport Address", HFILL }},
1621
1622     { &hf_ldp_tlv_fec_wc,
1623       { "FEC Element Type", "ldp.msg.tlv.fec.type", FT_UINT8, BASE_DEC, VALS(fec_types), 0x0, "Forwarding Equivalence Class Element Types", HFILL }},
1624
1625     { &hf_ldp_tlv_fec_af,
1626       { "FEC Element Address Type", "ldp.msg.tlv.fec.af", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Forwarding Equivalence Class Element Address Family", HFILL }},
1627
1628     { &hf_ldp_tlv_fec_len,
1629       { "FEC Element Length", "ldp.msg.tlv.fec.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Forwarding Equivalence Class Element Length", HFILL }},
1630
1631     { &hf_ldp_tlv_fec_pfval,
1632       { "FEC Element Prefix Value", "ldp.msg.tlv.fec.pfval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Prefix", HFILL }},
1633
1634     { &hf_ldp_tlv_fec_hoval,
1635       { "FEC Element Host Address Value", "ldp.msg.tlv.fec.hoval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Address", HFILL }},
1636
1637     { &hf_ldp_tlv_addrl_addr_family,
1638       { "Address Family", "ldp.msg.tlv.addrl.addr_family", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Address Family List", HFILL }},
1639
1640     { &hf_ldp_tlv_addrl_addr,
1641       { "Address", "ldp.msg.tlv.addrl.addr", FT_STRING, BASE_NONE, NULL, 0x0, "Address", HFILL }},
1642
1643     { &hf_ldp_tlv_hc_value,
1644       { "Hop Count Value", "ldp.msg.tlv.hc.value", FT_UINT8, BASE_DEC, NULL, 0x0, "Hop Count", HFILL }},
1645
1646     { &hf_ldp_tlv_pv_lsrid,
1647       { "LSR Id", "ldp.msg.tlv.pv.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Path Vector LSR Id", HFILL }},
1648
1649     { &hf_ldp_tlv_sess_ver,
1650       { "Session Protocol Version", "ldp.msg.tlv.sess.ver", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Protocol Version", HFILL }},
1651
1652     { &hf_ldp_tlv_sess_ka,
1653       { "Session KeepAlive Time", "ldp.msg.tlv.sess.ka", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters KeepAlive Time", HFILL }},
1654
1655     { &hf_ldp_tlv_sess_advbit,
1656       { "Session Label Advertisement Discipline", "ldp.msg.tlv.sess.advbit",
1657  FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80, 
1658         "Common Session Parameters Label Advertisement Discipline", HFILL }},
1659
1660     { &hf_ldp_tlv_sess_ldetbit,
1661       { "Session Loop Detection", "ldp.msg.tlv.sess.ldetbit", FT_BOOLEAN, 8, TFS(&tlv_sess_ldetbit_vals), 0x40, "Common Session Parameters Loop Detection", HFILL }},
1662
1663     { &hf_ldp_tlv_sess_pvlim,
1664       { "Session Path Vector Limit", "ldp.msg.tlv.sess.pvlim", FT_UINT8, BASE_DEC, NULL, 0x0, "Common Session Parameters Path Vector Limit", HFILL }},
1665
1666     { &hf_ldp_tlv_sess_mxpdu,
1667       { "Session Max PDU Length", "ldp.msg.tlv.sess.mxpdu", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Max PDU Length", HFILL }},
1668
1669     { &hf_ldp_tlv_sess_rxlsr,
1670       { "Session Receiver LSR Identifier", "ldp.msg.tlv.sess.rxlsr", FT_IPv4, BASE_DEC, NULL, 0x0, "Common Session Parameters LSR Identifier", HFILL }},
1671
1672     { &hf_ldp_tlv_sess_rxls,
1673       { "Session Receiver Label Space Identifier", "ldp.msg.tlv.sess.rxlsr", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Receiver Label Space Identifier", HFILL }},
1674
1675     { &hf_ldp_tlv_sess_atm_merge,
1676       { "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 }},
1677
1678     { &hf_ldp_tlv_sess_atm_lr,
1679       { "Number of ATM Label Ranges", "ldp.msg.tlv.sess.atm.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
1680
1681     { &hf_ldp_tlv_sess_atm_dir,
1682       { "Directionality", "ldp.msg.tlv.sess.atm.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Lablel Directionality", HFILL }},
1683
1684     { &hf_ldp_tlv_sess_atm_minvpi,
1685       { "Minimum VPI", "ldp.msg.tlv.sess.atm.minvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Minimum VPI", HFILL }},
1686
1687     { &hf_ldp_tlv_sess_atm_minvci,
1688       { "Minimum VCI", "ldp.msg.tlv.sess.atm.minvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Minimum VCI", HFILL }},
1689
1690     { &hf_ldp_tlv_sess_atm_maxvpi,
1691       { "Maximum VPI", "ldp.msg.tlv.sess.atm.maxvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Maximum VPI", HFILL }},
1692
1693     { &hf_ldp_tlv_sess_atm_maxvci,
1694       { "Maximum VCI", "ldp.msg.tlv.sess.atm.maxvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Maximum VCI", HFILL }},
1695
1696     { &hf_ldp_tlv_sess_fr_merge,
1697       { "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 }},
1698
1699     { &hf_ldp_tlv_sess_fr_lr,
1700       { "Number of Frame Relay Label Ranges", "ldp.msg.tlv.sess.fr.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
1701
1702     { &hf_ldp_tlv_sess_fr_dir,
1703       { "Directionality", "ldp.msg.tlv.sess.fr.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Lablel Directionality", HFILL }},
1704
1705     { &hf_ldp_tlv_sess_fr_len,
1706       { "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 }},
1707
1708     { &hf_ldp_tlv_sess_fr_mindlci,
1709       { "Minimum DLCI", "ldp.msg.tlv.sess.fr.mindlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Minimum DLCI", HFILL }},
1710
1711     { &hf_ldp_tlv_sess_fr_maxdlci,
1712       { "Maximum DLCI", "ldp.msg.tlv.sess.fr.maxdlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Maximum DLCI", HFILL }},
1713
1714     { &hf_ldp_tlv_lbl_req_msg_id, 
1715       { "Label Request Message ID", "ldp.tlv.lbl_req_msg_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Label Request Message to be aborted", HFILL }},
1716
1717     { &hf_ldp_tlv_vendor_id,
1718       { "Vendor ID", "ldp.msg.tlv.vendor_id", FT_UINT32, BASE_HEX, NULL, 0, "IEEE 802 Assigned Vendor ID", HFILL }},
1719
1720     { &hf_ldp_tlv_experiment_id,
1721       { "Experiment ID", "ldp.msg.tlv.experiment_id", FT_UINT32, BASE_HEX, NULL, 0, "Experiment ID", HFILL }},
1722
1723     { &hf_ldp_tlv_generic_label,
1724       { "Generic Label", "ldp.msg.tlv.generic.label", FT_UINT32, BASE_HEX, NULL, 0x000FFFFF, "Generic Label", HFILL }},
1725
1726     { &hf_ldp_tlv_atm_label_vbits,
1727       { "V-bits", "ldp.msg.tlv.atm.label.vbits", FT_UINT8, BASE_HEX, VALS(tlv_atm_vbits_vals), 0x30, "ATM Label V Bits", HFILL }},
1728
1729     { &hf_ldp_tlv_atm_label_vpi,
1730       { "VPI", "ldp.msg.tlv.atm.label.vpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "ATM Label VPI", HFILL }},
1731
1732     { &hf_ldp_tlv_atm_label_vci,
1733       { "VCI", "ldp.msg.tlv.atm.label.vci", FT_UINT16, BASE_DEC, NULL, 0, "ATM Label VCI", HFILL }},
1734
1735     { &hf_ldp_tlv_fr_label_len,
1736       { "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 }},
1737
1738     { &hf_ldp_tlv_fr_label_dlci,
1739       { "DLCI", "ldp.msg.tlv.fr.label.dlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "FRAME RELAY Label DLCI", HFILL }},
1740
1741     { &hf_ldp_tlv_status_ebit,
1742       { "E Bit", "ldp.msg.tlv.status.ebit", FT_BOOLEAN, 8, TFS(&tlv_status_ebit), 0x80, "Fatal Error Bit", HFILL }},
1743
1744     { &hf_ldp_tlv_status_fbit,
1745       { "F Bit", "ldp.msg.tlv.status.fbit", FT_BOOLEAN, 8, TFS(&tlv_status_fbit), 0x40, "Forward Bit", HFILL }},
1746
1747     { &hf_ldp_tlv_status_data,
1748       { "Status Data", "ldp.msg.tlv.status.data", FT_UINT32, BASE_HEX, VALS(tlv_status_data), 0x3FFFFFFF, "Status Data", HFILL }},
1749
1750     { &hf_ldp_tlv_status_msg_id, 
1751       { "Message ID", "ldp.msg.tlv.status.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "Identifies peer message to which Status TLV refers", HFILL }},
1752
1753     { &hf_ldp_tlv_status_msg_type,
1754       { "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 }},
1755
1756     { &hf_ldp_tlv_extstatus_data,
1757       { "Extended Status Data", "ldp.msg.tlv.extstatus.data", FT_UINT32, BASE_HEX, NULL, 0x0, "Extended Status Data", HFILL }},
1758
1759     { &hf_ldp_tlv_returned_version,
1760       { "Returned PDU Version", "ldp.msg.tlv.returned.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
1761
1762     { &hf_ldp_tlv_returned_pdu_len,
1763       { "Returned PDU Length", "ldp.msg.tlv.returned.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
1764
1765     { &hf_ldp_tlv_returned_lsr,
1766       { "Returned PDU LSR ID", "ldp.msg.tlv.returned.ldpid.lsr", FT_IPv4, BASE_DEC, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
1767
1768     { &hf_ldp_tlv_returned_ls_id,
1769       { "Returned PDU Label Space ID", "ldp.msg.tlv.returned.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID", HFILL }},
1770
1771     { &hf_ldp_tlv_returned_msg_ubit, 
1772       { "Returned Message Unknown bit", "ldp.msg.tlv.returned.msg.ubit", FT_UINT8, BASE_HEX, TFS(&ldp_message_ubit), 0x80, "Message Unknown bit", HFILL }},
1773
1774     { &hf_ldp_tlv_returned_msg_type,
1775       { "Returned Message Type", "ldp.msg.tlv.returned.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
1776
1777     { &hf_ldp_tlv_returned_msg_len,
1778       { "Returned Message Length", "ldp.msg.tlv.returned.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
1779
1780     { &hf_ldp_tlv_returned_msg_id, 
1781       { "Returned Message ID", "ldp.msg.tlv.returned.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
1782
1783     {&hf_ldp_tlv_fec_vc_controlword,
1784      {"C-bit", "ldp.msg.tlv.fec.vc.controlword", FT_BOOLEAN, 8, TFS(&fec_vc_cbit), 0x80, "Control Word Present", HFILL }},
1785
1786     {&hf_ldp_tlv_fec_vc_vctype,
1787      {"VC Type", "ldp.msg.tlv.fec.vc.vctype", FT_UINT16, BASE_HEX, VALS(fec_vc_types_vals), 0x7FFF, "Virtual Circuit Type", HFILL }},
1788
1789     {&hf_ldp_tlv_fec_vc_infolength,
1790      {"VC Info Length", "ldp.msg.tlv.fec.vc.infolength", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Info Length", HFILL }},
1791
1792     {&hf_ldp_tlv_fec_vc_groupid,
1793      {"Group ID", "ldp.msg.tlv.fec.vc.groupid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC Group ID", HFILL }},
1794
1795     {&hf_ldp_tlv_fec_vc_vcid,
1796      {"VC ID", "ldp.msg.tlv.fec.vc.vcid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC VCID", HFILL }},
1797
1798     {&hf_ldp_tlv_fec_vc_intparam_length,
1799      {"Length", "ldp.msg.tlv.fec.vc.intparam.length", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater Length", HFILL }},
1800
1801     {&hf_ldp_tlv_fec_vc_intparam_mtu,
1802      {"MTU", "ldp.msg.tlv.fec.vc.intparam.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater MTU", HFILL }},
1803
1804     {&hf_ldp_tlv_fec_vc_intparam_id,
1805      {"ID", "ldp.msg.tlv.fec.vc.intparam.id", FT_UINT8, BASE_HEX, VALS(fec_vc_interfaceparm), 0x0, "VC FEC Interface Paramater ID", HFILL }},
1806
1807     {&hf_ldp_tlv_fec_vc_intparam_maxcatmcells,
1808      {"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 }},
1809
1810     { &hf_ldp_tlv_fec_vc_intparam_desc,
1811       { "Description", "ldp.msg.tlv.fec.vc.intparam.desc", FT_STRING, BASE_DEC, NULL, 0, "VC FEC Interface Description", HFILL }},
1812
1813     {&hf_ldp_tlv_fec_vc_intparam_cembytes,
1814      {"Payload Bytes", "ldp.msg.tlv.fec.vc.intparam.cembytes", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param CEM Payload Bytes", HFILL }},
1815
1816   };
1817
1818   static gint *ett[] = {
1819     &ett_ldp,
1820     &ett_ldp_header,
1821     &ett_ldp_ldpid,
1822     &ett_ldp_message,
1823     &ett_ldp_tlv,
1824     &ett_ldp_tlv_val,
1825     &ett_ldp_fec,
1826     &ett_ldp_fec_vc_interfaceparam
1827   };
1828   module_t *ldp_module; 
1829
1830   proto_ldp = proto_register_protocol("Label Distribution Protocol",
1831                                        "LDP", "ldp");
1832
1833   proto_register_field_array(proto_ldp, hf, array_length(hf));
1834   proto_register_subtree_array(ett, array_length(ett));
1835
1836   /* Register our configuration options for , particularly our port */
1837
1838   ldp_module = prefs_register_protocol(proto_ldp, proto_reg_handoff_ldp);
1839
1840   prefs_register_uint_preference(ldp_module, "tcp.port", "LDP TCP Port",
1841                                  "Set the TCP port for messages (if other"
1842                                  " than the default of 646)",
1843                                  10, &global_ldp_tcp_port);
1844
1845   prefs_register_uint_preference(ldp_module, "udp.port", "LDP UDP Port",
1846                                  "Set the UDP port for messages (if other"
1847                                  " than the default of 646)",
1848                                  10, &global_ldp_udp_port);
1849
1850   prefs_register_bool_preference(ldp_module, "desegment_ldp_messages",
1851     "Desegment all LDP messages spanning multiple TCP segments",
1852     "Whether the LDP dissector should desegment all messages spanning multiple TCP segments",
1853     &ldp_desegment);
1854 }
1855
1856 /* The registration hand-off routine */
1857 void
1858 proto_reg_handoff_ldp(void)
1859 {
1860   static int ldp_prefs_initialized = FALSE;
1861   static dissector_handle_t ldp_tcp_handle, ldp_handle;
1862
1863   if (!ldp_prefs_initialized) {
1864
1865     ldp_tcp_handle = create_dissector_handle(dissect_ldp_tcp, proto_ldp);
1866     ldp_handle = create_dissector_handle(dissect_ldp, proto_ldp);
1867
1868     ldp_prefs_initialized = TRUE;
1869
1870   }
1871   else {
1872
1873     dissector_delete("tcp.port", tcp_port, ldp_tcp_handle);
1874     dissector_delete("udp.port", udp_port, ldp_handle);
1875
1876   }
1877
1878   /* Set our port number for future use */
1879
1880   tcp_port = global_ldp_tcp_port;
1881   udp_port = global_ldp_udp_port;
1882
1883   dissector_add("tcp.port", global_ldp_tcp_port, ldp_tcp_handle);
1884   dissector_add("udp.port", global_ldp_udp_port, ldp_handle);
1885
1886 }