Don't loop infinitely if we see a Host Address or unknown Forwarding
[obnox/wireshark/wip.git] / packet-ldp.c
1 /* packet-ldp.c
2  * Routines for ldp packet disassembly
3  *
4  * $Id: packet-ldp.c,v 1.9 2000/12/04 06:05:49 guy Exp $
5  * 
6  * Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs
10  * Copyright 1999 Gerald Combs
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #ifdef HAVE_NETINET_IN_H
35 #include <netinet/in.h>
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <ctype.h>
41 #include <time.h>
42 #include <glib.h>
43 #include <string.h>
44 #include "packet.h"
45 #include "resolv.h"
46 #include "prefs.h"
47
48 #define TCP_PORT_LDP 646
49 #define UDP_PORT_LDP 646
50
51 void proto_reg_handoff_ldp(void);
52
53 static int proto_ldp = -1;
54
55 /* Delete the following if you do not use it, or add to it if you need */
56 static int hf_ldp_req = -1;
57 static int hf_ldp_rsp = -1;
58 static int hf_ldp_version = -1;
59 static int hf_ldp_pdu_len = -1;
60 static int hf_ldp_lsr = -1;
61 static int hf_ldp_ls_id = -1;
62 static int hf_ldp_msg_type = -1;
63 static int hf_ldp_msg_len = -1;
64 static int hf_ldp_msg_id = -1;
65 static int hf_ldp_tlv_value = -1;
66 static int hf_ldp_tlv_type = -1;
67 static int hf_ldp_tlv_len = -1;
68 static int hf_ldp_tlv_val_hold = -1;
69 static int hf_ldp_tlv_val_target = -1;
70 static int hf_ldp_tlv_val_request = -1;
71 static int hf_ldp_tlv_val_res = -1;
72 static int hf_ldp_tlv_config_seqno = -1;
73 static int hf_ldp_tlv_fec_wc = -1;
74 static int hf_ldp_tlv_fec_af = -1;
75 static int hf_ldp_tlv_fec_len = -1;
76 static int hf_ldp_tlv_fec_pfval = -1;
77
78 static int ett_ldp = -1;
79 static int ett_ldp_header = -1;
80 static int ett_ldp_ldpid = -1;
81 static int ett_ldp_message = -1;
82 static int ett_ldp_tlv = -1;
83 static int ett_ldp_tlv_val = -1;
84 static int ett_ldp_fec = -1;
85
86 static int tcp_port = 0;
87 static int udp_port = 0;
88
89 /* Add your functions here */
90
91 static int global_ldp_tcp_port = TCP_PORT_LDP;
92 static int global_ldp_udp_port = UDP_PORT_LDP;
93
94 /*
95  * The following define all the TLV types I know about
96  */
97
98 #define TLV_FEC                    0x0100
99 #define TLV_ADDRESS_LIST           0x0101
100 #define TLV_HOP_COUNT              0x0103
101 #define TLV_PATH_VECTOR            0x0104
102 #define TLV_GENERIC_LABEL          0x0200
103 #define TLV_ATM_LABEL              0x0201
104 #define TLV_FRAME_LABEL            0x0202
105 #define TLV_STATUS                 0x0300
106 #define TLV_EXTENDED_STATUS        0x0301
107 #define TLV_RETURNED_PDU           0x0302
108 #define TLV_RETURNED_MESSAGE       0x0303
109 #define TLV_COMMON_HELLO_PARMS     0x0400
110 #define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
111 #define TLV_CONFIGURATION_SEQNO    0x0402
112 #define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
113 #define TLV_COMMON_SESSION_PARMS   0x0500
114 #define TLV_ATM_SESSION_PARMS      0x0501
115 #define TLV_FRAME_RELAY_SESSION_PARMS 0x0502
116 #define TLV_LABEL_REQUEST_MESSAGE_ID 0x0600
117
118 #define TLV_VENDOR_PRIVATE_START   0x3E00
119 #define TLV_VENDOR_PROVATE_END     0x3EFF
120 #define TLV_EXPERIMENTAL_START     0x3F00
121 #define TLV_EXPERIMENTAL_END       0x3FFF
122
123 static const value_string tlv_type_names[] = { 
124   { TLV_FEC,                       "Forwarding Equivalence Classes" },
125   { TLV_ADDRESS_LIST,              "Address List"},
126   { TLV_HOP_COUNT,                 "Hop Count"},
127   { TLV_PATH_VECTOR,               "Path Vector"},
128   { TLV_GENERIC_LABEL,             "Generic Label"},
129   { TLV_ATM_LABEL,                 "Frame Label"},
130   { TLV_STATUS,                    "Status"},
131   { TLV_EXTENDED_STATUS,           "Extended Status"},
132   { TLV_RETURNED_PDU,              "Returned PDU"},
133   { TLV_RETURNED_MESSAGE,          "Returned Message"},
134   { TLV_COMMON_HELLO_PARMS,        "Common Hello Parameters"},
135   { TLV_IPV4_TRANSPORT_ADDRESS,    "IPv4 Transport Address"},
136   { TLV_CONFIGURATION_SEQNO,       "Configuration Sequence Number"},
137   { TLV_IPV6_TRANSPORT_ADDRESS,    "IPv6 Transport Address"},
138   { TLV_COMMON_SESSION_PARMS,      "Common Session Parameters"},
139   { TLV_ATM_SESSION_PARMS,         "ATM Session Parameters"},
140   { TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters"},
141   { TLV_LABEL_REQUEST_MESSAGE_ID,  "Label Request Message ID"},
142   { 0, NULL}
143 };
144
145 /*
146  * The following define all the message types I know about
147  */
148
149 #define LDP_NOTIFICATION       0x0001
150 #define LDP_HELLO              0x0100
151 #define LDP_INITIALIZATION     0x0200
152 #define LDP_KEEPALIVE          0x0201
153 #define LDP_ADDRESS            0x0300
154 #define LDP_ADDRESS_WITHDRAWAL 0x0301
155 #define LDP_LABEL_MAPPING      0x0400
156 #define LDP_LABEL_REQUEST      0x0401
157 #define LDP_LABEL_WITHDRAWAL   0x0402
158 #define LDP_LABEL_RELEASE      0x0403
159 #define LDP_LABEL_ABORT_REQUEST 0x0404
160 #define LDP_VENDOR_PRIVATE_START 0x3E00
161 #define LDP_VENDOR_PRIVATE_END   0x3EFF
162 #define LDP_EXPERIMENTAL_MESSAGE_START 0x3F00
163 #define LDP_EXPERIMENTAL_MESSAGE_END   0x3FFF
164
165 static const value_string ldp_message_types[] = {
166   {LDP_NOTIFICATION,             "Notification"},
167   {LDP_HELLO,                    "Hello"},
168   {LDP_INITIALIZATION,           "Initialization"},
169   {LDP_KEEPALIVE,                "Keep Alive"},
170   {LDP_ADDRESS,                  "Address"},
171   {LDP_ADDRESS_WITHDRAWAL,       "Address Withdrawal"},
172   {LDP_LABEL_MAPPING,            "Label Mapping"},
173   {LDP_LABEL_REQUEST,            "Label Request"},
174   {LDP_LABEL_WITHDRAWAL,         "Label Withdrawal"},
175   {LDP_LABEL_RELEASE,            "Label Release"},
176   {LDP_LABEL_ABORT_REQUEST,      "Label Abort Request"},
177   {0, NULL}
178 };
179
180 static const true_false_string hello_targeted_vals = {
181   "Targeted Hello",
182   "Link Hello"
183 };
184
185 static const value_string fec_types[] = {
186   {1, "Wildcard FEC"},
187   {2, "Prefix FEC"},
188   {3, "Host Address FEC"},
189   {0, NULL}
190 };
191
192 static const value_string fec_af_types[] = {
193   {1, "UNIX"},
194   {2, "Internet (IPv4)"},
195   {3, "X25"},
196   {4, "IPX"},
197   {5, "Appletalk"},
198   {10, "IPv6"},
199   {0, NULL}
200 };
201
202 static const true_false_string hello_requested_vals = {
203   "Source requests periodic hellos",
204   "Source does not request periodic hellos"
205 };
206
207 /* Dissect the common hello params */
208
209 void dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
210 {
211   proto_tree *ti = NULL, *val_tree = NULL;
212
213   if (tree) {
214
215     ti = proto_tree_add_bytes(tree, hf_ldp_tlv_value, tvb, offset, rem,
216                               tvb_get_ptr(tvb, offset, rem));
217
218     val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
219
220     proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
221
222     proto_tree_add_boolean(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 2, FALSE);
223     proto_tree_add_boolean(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 2, FALSE);
224     proto_tree_add_item(val_tree, hf_ldp_tlv_val_res, tvb, offset + 2, 2, FALSE);
225   }
226
227 }
228
229 /* Dissect a TLV and return the number of bytes consumed ... */
230
231 int dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
232 {
233   guint16 message = tvb_get_ntohs(tvb, offset),
234           length = tvb_get_ntohs(tvb, offset + 2),
235           pad = 0, fec_len = 0;
236   proto_tree *ti = NULL, *tlv_tree = NULL;
237
238   /* Hmmm, check for illegal alignment padding */
239
240   if (message == 0x00) {
241
242     proto_tree_add_text(tree, tvb, offset, 2, "Illegal Padding: %04X", message);
243     offset += 2; pad = 2;
244     message = tvb_get_ntohs(tvb, offset);
245     length = tvb_get_ntohs(tvb, offset + 2);
246
247   }
248
249   length = MIN(length, rem);  /* Don't go haywire if a problem ... */
250
251   if (tree) {
252
253     /* FIXME: Account for vendor and special messages */
254
255     ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
256                              val_to_str(message, tlv_type_names, "Unknown TLV type (0x%04X)"));
257
258     tlv_tree = proto_item_add_subtree(ti, ett_ldp_tlv);
259
260     proto_tree_add_item(tlv_tree, hf_ldp_tlv_type, tvb, offset, 2, FALSE);
261
262     proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
263
264     switch (message) {
265
266     case TLV_FEC:  /* Process an FEC */
267
268       offset += 4;  /* Skip the TLV header */
269
270       fec_len = length;
271
272       while (fec_len > 0) {
273         proto_tree *fec_tree = NULL;
274
275
276         switch (tvb_get_guint8(tvb, offset)) {
277         case 1:   /* Wild Card */
278
279           proto_tree_add_item(tlv_tree, hf_ldp_tlv_fec_wc, tvb, offset, 4, FALSE);
280           fec_len -= 4;
281
282           offset += 4;
283
284           break;
285
286         case 2:   /* Prefix    */
287
288           /* Add a subtree for this ... */
289
290           ti = proto_tree_add_text(tlv_tree, tvb, offset, 8, "Prefix FEC Element");
291
292           fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
293
294           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
295
296           offset += 1;
297
298           /* XXX - the address family length should be extracted and used to
299              dissect the prefix field. */
300           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
301           offset += 2;
302
303
304           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
305
306           offset += 1;
307
308           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, 4, FALSE);
309
310           fec_len -= 8;
311
312           break;
313
314         case 3:   /* Host address */
315
316           /* XXX - write me. */
317
318           fec_len -= 8;
319
320           offset += 8;
321
322           break;
323
324         default:  /* Unknown */
325
326           /* XXX - do all FEC's have a length that's a multiple of 4? */
327
328           fec_len -= 4;
329
330           offset += 4;
331
332           break;
333
334         }
335
336       }
337
338       break;;
339
340     case TLV_COMMON_HELLO_PARMS:
341
342       dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
343       break;
344
345     case TLV_CONFIGURATION_SEQNO:
346
347       proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
348       break;
349
350     default:
351       proto_tree_add_bytes(tlv_tree, hf_ldp_tlv_value, tvb, offset + 4, 
352                            length, tvb_get_ptr(tvb, offset + 4, length));
353
354       break;
355     }
356
357   }
358
359   return length + pad + 4;  /* Length of the value field + header */
360
361 }
362
363 /* 
364  * Each of these routines dissect the relevant messages, but the msg header 
365  * has already been dissected.
366  */
367
368 void
369 dissect_ldp_notification(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
370 {
371   guint rem = length, cc = 0;
372
373   while (rem > 0) {
374
375     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
376     offset += cc;
377
378   }
379
380 }
381
382 /* Dissect a Hello Message ... */
383 void
384 dissect_ldp_hello(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
385 {
386   guint rem = length, cc = 0;
387
388   while (rem > 0) {
389
390     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
391     offset += cc;
392
393   }
394
395 }
396
397 void
398 dissect_ldp_initialization(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
399 {
400   guint rem = length, cc = 0;
401
402   while (rem > 0) {
403
404     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
405     offset += cc;
406
407   }
408
409 }
410
411 void
412 dissect_ldp_keepalive(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
413 {
414   guint rem = length, cc = 0;
415
416   while (rem > 0) {
417
418     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
419     offset += cc;
420
421   }
422
423 }
424
425 void
426 dissect_ldp_address(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
427 {
428   guint rem = length, cc = 0;
429
430   while (rem > 0) {
431
432     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
433     offset += cc;
434
435   }
436
437 }
438
439 void
440 dissect_ldp_address_withdrawal(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
441 {
442   guint rem = length, cc = 0;
443
444   while (rem > 0) {
445
446     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
447     offset += cc;
448
449   }
450
451 }
452
453 void
454 dissect_ldp_label_mapping(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
455 {
456   guint rem = length, cc = 0;
457
458   while (rem > 0) {
459
460     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
461     offset += cc;
462
463   }
464
465 }
466
467 void
468 dissect_ldp_label_request(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
469 {
470   guint rem = length, cc = 0;
471
472   while (rem > 0) {
473
474     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
475     offset += cc;
476
477   }
478
479 }
480
481 void
482 dissect_ldp_label_withdrawal(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
483 {
484   guint rem = length, cc = 0;
485
486   while (rem > 0) {
487
488     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
489     offset += cc;
490
491   }
492
493 }
494
495 void
496 dissect_ldp_label_release(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
497 {
498   guint rem = length, cc = 0;
499
500   while (rem > 0) {
501
502     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
503     offset += cc;
504
505   }
506
507 }
508
509 void
510 dissect_ldp_label_abort_request(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
511 {
512   guint rem = length, cc = 0;
513
514   while (rem > 0) {
515
516     rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
517     offset += cc;
518
519   }
520
521 }
522
523 static void
524 dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
525 {
526   proto_tree     *ldp_tree = NULL, 
527                  *ti = NULL,
528                  *hdr_tree = NULL, *ldpid_tree = NULL;
529   int            offset = 0, msg_cnt = 0;
530   guint16        ldp_message = 0;
531
532   CHECK_DISPLAY_AS_DATA(proto_ldp, tvb, pinfo, tree);
533
534   pinfo->current_proto = "LDP";
535
536   if (check_col(pinfo->fd, COL_PROTOCOL))
537
538     col_add_str(pinfo->fd, COL_PROTOCOL, "LDP");
539
540   if (tree) {  /* Build the tree info ..., this is wrong! FIXME */
541
542     ti = proto_tree_add_item(tree, proto_ldp, tvb, offset,
543                              tvb_length_remaining(tvb, offset), FALSE);
544     ldp_tree = proto_item_add_subtree(ti, ett_ldp);
545
546     ti = proto_tree_add_text(ldp_tree, tvb, 0, 10, "Header");
547
548     hdr_tree = proto_item_add_subtree(ti, ett_ldp_header);
549
550     proto_tree_add_item(hdr_tree, hf_ldp_version, tvb, offset, 2, FALSE);
551
552     offset += 2;
553
554     proto_tree_add_item(hdr_tree, hf_ldp_pdu_len, tvb, offset, 2, FALSE);
555
556     offset += 2;
557
558     ti = proto_tree_add_text(hdr_tree, tvb, offset, 6, "LDP Identifier");
559
560     ldpid_tree = proto_item_add_subtree(ti, ett_ldp_ldpid);
561
562     proto_tree_add_item(ldpid_tree, hf_ldp_lsr, tvb, offset, 4, FALSE);
563
564     offset += 4;
565
566     proto_tree_add_item(ldpid_tree, hf_ldp_ls_id, tvb, offset, 2, FALSE);
567
568     offset += 2;
569
570   }
571
572   offset = 10;
573
574   while (tvb_length_remaining(tvb, offset) > 0) { /* Dissect a message */
575
576     guint msg_len;
577
578     ldp_message = tvb_get_ntohs(tvb, offset) & 0x7FFF; /* Get the message type */
579
580     msg_len = tvb_get_ntohs(tvb, offset + 2);
581
582     if (check_col(pinfo->fd, COL_INFO)) {  /* Check the type ... */
583
584       if (msg_cnt > 0) 
585         col_append_fstr(pinfo->fd, COL_INFO, ", %s",
586                         val_to_str(ldp_message, ldp_message_types, "Unknown Message (0x%04X)"));
587       else
588         col_add_fstr(pinfo->fd, COL_INFO, "%s", 
589                      val_to_str(ldp_message, ldp_message_types, "Unknown Message (0x%04X)"));
590
591     }
592
593     msg_cnt++;
594
595     if (tree) {
596
597       proto_tree *ti = NULL, *msg_tree = NULL;
598
599       /* FIXME: Account for vendor and experimental messages */
600
601       ti = proto_tree_add_text(ldp_tree, tvb, offset, msg_len + 4, "%s",
602                                val_to_str(ldp_message, ldp_message_types, "Unknown Message (0x%04X)"));
603
604       msg_tree = proto_item_add_subtree(ti, ett_ldp_message);
605
606       proto_tree_add_item(msg_tree, hf_ldp_msg_type, tvb, offset, 2, FALSE);
607
608       proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset + 2, 2, FALSE);
609
610       proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset + 4, 4, FALSE);
611
612       switch (ldp_message) {
613
614       case LDP_NOTIFICATION:
615
616         dissect_ldp_notification(tvb, offset + 8, pinfo, msg_tree, msg_len - 4); 
617
618         break;
619
620       case LDP_HELLO:
621
622         dissect_ldp_hello(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
623
624         break;
625
626       case LDP_INITIALIZATION:
627
628         dissect_ldp_initialization(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
629
630         break;
631
632       case LDP_KEEPALIVE:
633
634         dissect_ldp_keepalive(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
635
636         break;
637
638       case LDP_ADDRESS:
639
640         dissect_ldp_address(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
641
642         break;
643
644       case LDP_ADDRESS_WITHDRAWAL:
645
646         dissect_ldp_address_withdrawal(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
647
648         break;
649
650       case LDP_LABEL_MAPPING:
651
652         dissect_ldp_label_mapping(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
653
654         break;
655
656       case LDP_LABEL_REQUEST:
657
658         dissect_ldp_label_request(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
659
660         break;
661
662       case LDP_LABEL_WITHDRAWAL:
663
664         dissect_ldp_label_withdrawal(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
665
666         break;
667
668       case LDP_LABEL_RELEASE:
669
670         dissect_ldp_label_release(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
671
672         break;
673
674       case LDP_LABEL_ABORT_REQUEST:
675
676         dissect_ldp_label_abort_request(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
677
678         break;
679
680       default:
681
682         /* Some sort of unknown message, treat as undissected data */
683
684         break;
685
686       }
687     
688     }
689
690     offset += msg_len + 4;
691
692   }
693 }
694
695 /* Register all the bits needed with the filtering engine */
696
697 void 
698 proto_register_ldp(void)
699 {
700   static hf_register_info hf[] = {
701     { &hf_ldp_req,
702       /* Change the following to the type you need */
703       { "Request", "ldp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "" }},
704
705     { &hf_ldp_rsp,
706       { "Response", "ldp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "" }},
707
708     { &hf_ldp_version,
709       { "Version", "ldp.hdr.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number" }},
710
711     { &hf_ldp_pdu_len,
712       { "PDU Length", "ldp.hdr.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length"}},
713
714     { &hf_ldp_lsr,
715       { "LSR ID", "ldp.hdr.ldpid.lsr", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Label Space Router ID"}},
716
717     { &hf_ldp_ls_id,
718       { "Label Space ID", "ldp.hdr.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID"}},
719
720     { &hf_ldp_msg_type,
721       { "Message Type", "ldp.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x0, "LDP message type"}},
722
723     { &hf_ldp_msg_len,
724       { "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)"}},
725
726     { &hf_ldp_msg_id, 
727       { "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID"}},
728
729     { &hf_ldp_tlv_type, 
730       { "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x0, "TLV Type Field"}},
731
732     { &hf_ldp_tlv_len,
733       {"TLV Length", "ldp.msg.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0, "TLV Length Field"}},
734
735     { &hf_ldp_tlv_value,
736       { "TLV Value", "ldp.msg.tlv.value", FT_BYTES, BASE_NONE, NULL, 0x0, "TLV Value Bytes"}},
737
738     { &hf_ldp_tlv_val_hold,
739       { "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time"}},
740
741     { &hf_ldp_tlv_val_target,
742       { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 8, TFS(&hello_targeted_vals), 0x80, "Hello Common Parameters Targeted Bit"}},
743
744     { &hf_ldp_tlv_val_request,
745       { "Hello Requested", "ldp,msg.tlv.hello.requested", FT_BOOLEAN, 8, TFS(&hello_requested_vals), 0x40, "Hello Common Parameters Hello Requested Bit" }},
746  
747     { &hf_ldp_tlv_val_res,
748       { "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field"}},
749
750     { &hf_ldp_tlv_config_seqno,
751       { "Configuration Sequence Number", "ldp.msg.tlv.hello.cnf_seqno", FT_UINT32, BASE_HEX, NULL, 0x0, "Hello COnfiguration Sequence Number"}},
752
753     { &hf_ldp_tlv_fec_wc,
754       { "FEC Element Type", "ldp.msg.tlv.fec.type", FT_UINT8, BASE_DEC, VALS(fec_types), 0x0, "Forwarding Equivalence Class Element Types"}},
755
756     { &hf_ldp_tlv_fec_af,
757       { "FEC Element Address Type", "ldp.msg.tlv.fec.af", FT_UINT16, BASE_DEC, VALS(fec_af_types), 0x0, "Forwarding Equivalence Class Element Address Family"}},
758
759     { &hf_ldp_tlv_fec_len,
760       { "FEC Element Length", "ldp.msg.tlv.fec.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Forwarding Equivalence Class Element Length"}},
761
762     { &hf_ldp_tlv_fec_pfval,
763       { "FEC Element Prefix Value", "ldp.msg.tlv.fec.pfval", FT_UINT32, BASE_HEX, NULL, 0x0, "Forwarding Equivalence Class Element Prefix"}},
764
765   };
766   static gint *ett[] = {
767     &ett_ldp,
768     &ett_ldp_header,
769     &ett_ldp_ldpid,
770     &ett_ldp_message,
771     &ett_ldp_tlv,
772     &ett_ldp_tlv_val,
773     &ett_ldp_fec,
774   };
775   module_t *ldp_module; 
776
777   /* Register our configuration options for , particularly our port */
778
779   ldp_module = prefs_register_module("ldp", "LDP", proto_reg_handoff_ldp);
780
781   prefs_register_uint_preference(ldp_module, "tcp.port", "LDP TCP Port",
782                                  "Set the port for  messages (if other"
783                                  " than the default of 646)",
784                                  10, &global_ldp_tcp_port);
785
786   prefs_register_uint_preference(ldp_module, "udp.port", "LDP UDP Port",
787                                  "Set the port for  messages (if other"
788                                  " than the default of 646)",
789                                  10, &global_ldp_udp_port);
790
791   proto_ldp = proto_register_protocol("Label Distribution Protocol",
792                                        "ldp");
793
794   proto_register_field_array(proto_ldp, hf, array_length(hf));
795   proto_register_subtree_array(ett, array_length(ett));
796
797 }
798
799 /* The registration hand-off routine */
800 void
801 proto_reg_handoff_ldp(void)
802 {
803   static int ldp_prefs_initialized = FALSE;
804
805   if (ldp_prefs_initialized) {
806
807     dissector_delete("tcp.port", tcp_port, dissect_ldp);
808     dissector_delete("udp.port", udp_port, dissect_ldp);
809
810   }
811   else {
812
813     ldp_prefs_initialized = TRUE;
814
815   }
816
817   /* Set our port number for future use */
818
819   tcp_port = global_ldp_tcp_port;
820   udp_port = global_ldp_udp_port;
821
822   dissector_add("tcp.port", global_ldp_tcp_port, dissect_ldp);
823   dissector_add("udp.port", global_ldp_udp_port, dissect_ldp);
824
825 }