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