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