Show unknown AFP command codes in decimal in the summary line, as we
[obnox/wireshark/wip.git] / packet-lmp.c
1 /* packet-lmp.c
2  * Routines for LMP packet disassembly
3  *
4  * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
5  *
6  * $Id: packet-lmp.c,v 1.4 2002/04/25 06:34:41 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 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 /*
28  * LMP as a standard has shown a remarkable ability to get completely rewritten
29  * across minor versions of the draft. This file currently implements
30  * the version described in draft-ietf-ccamp-lmp-03.txt
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <stdio.h>
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #include <stdlib.h>
44 #include <string.h>
45
46 #ifdef HAVE_SYS_TYPES_H
47 # include <sys/types.h>
48 #endif
49
50 #ifdef HAVE_NETINET_IN_H
51 # include <netinet/in.h>
52 #endif
53
54 #include <glib.h>
55
56 #ifdef NEED_SNPRINTF_H
57 # include "snprintf.h"
58 #endif
59
60 #include <epan/tvbuff.h>
61 #include <epan/packet.h>
62 #include "in_cksum.h"
63 #include "etypes.h"
64 #include "ipproto.h"
65
66 #include "packet-ip.h"
67 #include "packet-rsvp.h"
68
69 static int proto_lmp = -1;
70
71 /* #define IP_PROTO_LMP 0x6e */
72 #define IP_PROTO_LMP 140
73
74 /*----------------------------------------------------------------------
75  * LMP message types
76  */
77 typedef enum {
78     LMP_MSG_CONFIG=1, 
79     LMP_MSG_CONFIG_ACK, 
80     LMP_MSG_CONFIG_NACK, 
81     LMP_MSG_HELLO,
82     LMP_MSG_BEGIN_VERIFY, 
83     LMP_MSG_BEGIN_VERIFY_ACK, 
84     LMP_MSG_BEGIN_VERIFY_NACK, 
85     LMP_MSG_END_VERIFY,
86     LMP_MSG_END_VERIFY_ACK,
87     LMP_MSG_TEST,
88     LMP_MSG_TEST_STATUS_SUCCESS,
89     LMP_MSG_TEST_STATUS_FAILURE,
90     LMP_MSG_TEST_STATUS_ACK,
91     LMP_MSG_LINK_SUMMARY,
92     LMP_MSG_LINK_SUMMARY_ACK,
93     LMP_MSG_LINK_SUMMARY_NACK,
94     LMP_MSG_CHANNEL_FAIL,
95     LMP_MSG_CHANNEL_FAIL_ACK,
96     LMP_MSG_CHANNEL_FAIL_NACK,
97     LMP_MSG_CHANNEL_STATUS,
98     LMP_MSG_CHANNEL_STATUS_ACK,
99     LMP_MSG_CHANNEL_STATUS_REQ,
100     LMP_MSG_CHANNEL_STATUS_RESP,
101 } lmp_message_types;
102
103 static value_string message_type_vals[] = { 
104     {LMP_MSG_CONFIG,              "Config Message. "},
105     {LMP_MSG_CONFIG_ACK,          "ConfigAck Message. "},
106     {LMP_MSG_CONFIG_NACK,         "ConfigNack Message. "},
107     {LMP_MSG_HELLO,               "Hello Message. "},
108     {LMP_MSG_BEGIN_VERIFY,        "BeginVerify Message. "},
109     {LMP_MSG_BEGIN_VERIFY_ACK,    "BeginVerifyAck Message. "},
110     {LMP_MSG_BEGIN_VERIFY_NACK,   "BeginVerifyNack Message. "},
111     {LMP_MSG_END_VERIFY,          "EndVerifyNack Message. "},
112     {LMP_MSG_TEST,                "Test Message. "},
113     {LMP_MSG_TEST_STATUS_SUCCESS, "TestStatusSuccess Message. "},
114     {LMP_MSG_TEST_STATUS_FAILURE, "TestStatusFailure Message. "},
115     {LMP_MSG_TEST_STATUS_ACK,     "TestStatusAck Message. "},
116     {LMP_MSG_LINK_SUMMARY,        "LinkSummary Message. "},
117     {LMP_MSG_LINK_SUMMARY_ACK,    "LinkSummaryAck Message. "},
118     {LMP_MSG_LINK_SUMMARY_NACK,   "LinkSummaryNack Message. "},
119     {LMP_MSG_CHANNEL_FAIL,        "ChannelFail Message. "},
120     {LMP_MSG_CHANNEL_FAIL_ACK,    "ChannelFailAck Message. "},
121     {LMP_MSG_CHANNEL_FAIL_NACK,   "ChannelFailNack Message. "},
122     {LMP_MSG_CHANNEL_STATUS,      "ChannelStatus Message. "},
123     {LMP_MSG_CHANNEL_STATUS_ACK,  "ChannelStatusAck Message. "},
124     {LMP_MSG_CHANNEL_STATUS_REQ,  "ChannelStatusRequest Message. "},
125     {LMP_MSG_CHANNEL_STATUS_RESP, "ChannelStatusResponse Message. "},
126     {0, NULL}
127 };
128
129 /*------------------------------------------------------------------------------
130  * LMP object classes
131  */
132 typedef enum {
133     LMP_CLASS_NULL = 0,
134
135     LMP_CLASS_LOCAL_CCID,
136     LMP_CLASS_REMOTE_CCID,
137     LMP_CLASS_LOCAL_NODE_ID,
138     LMP_CLASS_REMOTE_NODE_ID,
139     LMP_CLASS_LOCAL_LINK_ID,
140     LMP_CLASS_REMOTE_LINK_ID,
141     LMP_CLASS_LOCAL_INTERFACE_ID,
142     LMP_CLASS_REMOTE_INTERFACE_ID,
143     LMP_CLASS_MESSAGE_ID,
144     LMP_CLASS_MESSAGE_ID_ACK,
145     LMP_CLASS_CONFIG,
146     LMP_CLASS_HELLO,
147     LMP_CLASS_BEGIN_VERIFY,
148     LMP_CLASS_BEGIN_VERIFY_ACK,
149     LMP_CLASS_VERIFY_ID,
150     LMP_CLASS_TE_LINK,
151     LMP_CLASS_DATA_LINK,
152     LMP_CLASS_CHANNEL_STATUS,
153     LMP_CLASS_CHANNEL_STATUS_REQUEST,
154     LMP_CLASS_ERROR,
155
156     LMP_CLASS_MAX
157 } lmp_classes;
158
159 static value_string lmp_class_vals[] = {
160
161     {LMP_CLASS_LOCAL_CCID, "LOCAL_CCID"}, 
162     {LMP_CLASS_REMOTE_CCID, "REMOTE_CCID"}, 
163     {LMP_CLASS_LOCAL_NODE_ID, "LOCAL_NODE_ID"}, 
164     {LMP_CLASS_REMOTE_NODE_ID, "REMOTE_NODE_ID"}, 
165     {LMP_CLASS_LOCAL_LINK_ID, "LOCAL_LINK_ID"}, 
166     {LMP_CLASS_REMOTE_LINK_ID, "REMOTE_LINK_ID"}, 
167     {LMP_CLASS_LOCAL_INTERFACE_ID, "LOCAL_INTERFACE_ID"}, 
168     {LMP_CLASS_REMOTE_INTERFACE_ID, "REMOTE_INTERFACE_ID"}, 
169     {LMP_CLASS_MESSAGE_ID, "MESSAGE_ID"}, 
170     {LMP_CLASS_MESSAGE_ID_ACK, "MESSAGE_ID_ACK"}, 
171     {LMP_CLASS_CONFIG, "CONFIG"}, 
172     {LMP_CLASS_HELLO, "HELLO"}, 
173     {LMP_CLASS_BEGIN_VERIFY, "BEGIN_VERIFY"}, 
174     {LMP_CLASS_BEGIN_VERIFY_ACK, "BEGIN_VERIFY_ACK"}, 
175     {LMP_CLASS_VERIFY_ID, "VERIFY_ID"}, 
176     {LMP_CLASS_TE_LINK, "TE_LINK"}, 
177     {LMP_CLASS_DATA_LINK, "DATA_LINK"}, 
178     {LMP_CLASS_CHANNEL_STATUS, "CHANNEL_STATUS"}, 
179     {LMP_CLASS_CHANNEL_STATUS_REQUEST, "CHANNEL_STATUS_REQUEST"}, 
180     {LMP_CLASS_ERROR, "ERROR"}, 
181 };
182
183 #define VALID_CLASS(class) ((class) > LMP_CLASS_NULL && (class) < LMP_CLASS_MAX)
184
185 /*------------------------------------------------------------------------------
186  * Other constants & stuff
187  */
188
189 /* Channel Status */
190 static const value_string channel_status_str[] = {
191     {1, "Signal Okay (OK)"},
192     {2, "Signal Degraded (SD)"},
193     {3, "Signal Failed (SF)"},
194 };
195 static const value_string channel_status_short_str[] = {
196     {1, "OK"},
197     {2, "SD"},
198     {3, "SF"},
199 };
200
201 /*------------------------------------------------------------------------------
202  * LMP Filter values
203  */
204
205 enum lmp_filter_keys {
206
207   /* Message types ---------------- */
208   LMPF_MSG,
209
210   LMPF_MSG_CONFIG,
211   LMPF_MSG_CONFIG_ACK,
212   LMPF_MSG_CONFIG_NACK, 
213   LMPF_MSG_HELLO,
214   LMPF_MSG_BEGIN_VERIFY, 
215   LMPF_MSG_BEGIN_VERIFY_ACK, 
216   LMPF_MSG_BEGIN_VERIFY_NACK, 
217   LMPF_MSG_END_VERIFY,
218   LMPF_MSG_END_VERIFY_ACK,
219   LMPF_MSG_TEST,
220   LMPF_MSG_TEST_STATUS_SUCCESS,
221   LMPF_MSG_TEST_STATUS_FAILURE,
222   LMPF_MSG_TEST_STATUS_ACK,
223   LMPF_MSG_LINK_SUMMARY,
224   LMPF_MSG_LINK_SUMMARY_ACK,
225   LMPF_MSG_LINK_SUMMARY_NACK,
226   LMPF_MSG_CHANNEL_FAIL,
227   LMPF_MSG_CHANNEL_FAIL_ACK,
228   LMPF_MSG_CHANNEL_FAIL_NACK,
229   LMPF_MSG_CHANNEL_STATUS,
230   LMPF_MSG_CHANNEL_STATUS_ACK,
231   LMPF_MSG_CHANNEL_STATUS_REQ,
232   LMPF_MSG_CHANNEL_STATUS_RESP,
233
234   /* LMP Message Header Fields ------------------ */
235   LMPF_HDR_FLAGS,
236   LMPF_HDR_FLAGS_CC_DOWN,
237   LMPF_HDR_FLAGS_REBOOT,
238   LMPF_HDR_FLAGS_DWDM,
239   LMPF_HDR_FLAGS_AUTHENTICATION,
240
241   /* LMP Object Class Filters -------------------- */
242   LMPF_OBJECT,
243
244   LMPF_CLASS_LOCAL_CCID,
245   LMPF_CLASS_REMOTE_CCID,
246   LMPF_CLASS_LOCAL_NODE_ID,
247   LMPF_CLASS_REMOTE_NODE_ID,
248   LMPF_CLASS_LOCAL_LINK_ID,
249   LMPF_CLASS_REMOTE_LINK_ID,
250   LMPF_CLASS_LOCAL_INTERFACE_ID,
251   LMPF_CLASS_REMOTE_INTERFACE_ID,
252   LMPF_CLASS_MESSAGE_ID,
253   LMPF_CLASS_MESSAGE_ID_ACK,
254   LMPF_CLASS_CONFIG,
255   LMPF_CLASS_HELLO,
256   LMPF_CLASS_BEGIN_VERIFY,
257   LMPF_CLASS_BEGIN_VERIFY_ACK,
258   LMPF_CLASS_VERIFY_ID,
259   LMPF_CLASS_TE_LINK,
260   LMPF_CLASS_DATA_LINK,
261   LMPF_CLASS_CHANNEL_STATUS,
262   LMPF_CLASS_CHANNEL_STATUS_REQUEST,
263   LMPF_CLASS_ERROR,
264
265   LMPF_VAL_CTYPE,
266   LMPF_VAL_LOCAL_CCID,
267   LMPF_VAL_REMOTE_CCID,
268   LMPF_VAL_LOCAL_NODE_ID,
269   LMPF_VAL_REMOTE_NODE_ID,
270   LMPF_VAL_LOCAL_LINK_ID_IPV4,
271   LMPF_VAL_LOCAL_LINK_ID_UNNUM,
272   LMPF_VAL_REMOTE_LINK_ID_IPV4,
273   LMPF_VAL_REMOTE_LINK_ID_UNNUM,
274   LMPF_VAL_LOCAL_INTERFACE_ID_IPV4,
275   LMPF_VAL_LOCAL_INTERFACE_ID_UNNUM,
276   LMPF_VAL_REMOTE_INTERFACE_ID_IPV4,
277   LMPF_VAL_REMOTE_INTERFACE_ID_UNNUM,
278   LMPF_VAL_MESSAGE_ID,
279   LMPF_VAL_MESSAGE_ID_ACK,
280   LMPF_VAL_CONFIG_HELLO,
281   LMPF_VAL_CONFIG_HELLO_DEAD,
282   LMPF_VAL_HELLO_TXSEQ,
283   LMPF_VAL_HELLO_RXSEQ,
284
285   LMPF_VAL_BEGIN_VERIFY_FLAGS,
286   LMPF_VAL_BEGIN_VERIFY_FLAGS_ALL_LINKS,
287   LMPF_VAL_BEGIN_VERIFY_FLAGS_LINK_TYPE,
288   LMPF_VAL_BEGIN_VERIFY_INTERVAL,
289   LMPF_VAL_BEGIN_VERIFY_ENCTYPE,
290   LMPF_VAL_BEGIN_VERIFY_TRANSPORT,
291   LMPF_VAL_BEGIN_VERIFY_TRANSMISSION_RATE,
292   LMPF_VAL_BEGIN_VERIFY_WAVELENGTH,
293   LMPF_VAL_VERIFY_ID,
294
295   LMPF_VAL_TE_LINK_FLAGS,
296   LMPF_VAL_TE_LINK_FLAGS_FAULT_MGMT,
297   LMPF_VAL_TE_LINK_FLAGS_LINK_VERIFY,
298   LMPF_VAL_TE_LINK_LOCAL_IPV4,
299   LMPF_VAL_TE_LINK_LOCAL_UNNUM,
300   LMPF_VAL_TE_LINK_REMOTE_IPV4,
301   LMPF_VAL_TE_LINK_REMOTE_UNNUM,
302
303   LMPF_VAL_DATA_LINK_FLAGS,
304   LMPF_VAL_DATA_LINK_FLAGS_PORT,
305   LMPF_VAL_DATA_LINK_FLAGS_ALLOCATED,
306   LMPF_VAL_DATA_LINK_LOCAL_IPV4,
307   LMPF_VAL_DATA_LINK_LOCAL_UNNUM,
308   LMPF_VAL_DATA_LINK_REMOTE_IPV4,
309   LMPF_VAL_DATA_LINK_REMOTE_UNNUM,
310   LMPF_VAL_DATA_LINK_SUBOBJ,
311   LMPF_VAL_DATA_LINK_SUBOBJ_SWITCHING_TYPE,
312   LMPF_VAL_DATA_LINK_SUBOBJ_LSP_ENCODING,
313
314   LMPF_VAL_ERROR,
315   LMPF_VAL_ERROR_VERIFY_UNSUPPORTED_LINK,
316   LMPF_VAL_ERROR_VERIFY_UNWILLING,
317   LMPF_VAL_ERROR_VERIFY_TRANSPORT,
318   LMPF_VAL_ERROR_VERIFY_TE_LINK_ID,
319   LMPF_VAL_ERROR_SUMMARY_BAD_PARAMETERS,
320   LMPF_VAL_ERROR_SUMMARY_RENEGOTIATE,
321   LMPF_VAL_ERROR_SUMMARY_BAD_REMOTE_LINK_ID,
322   LMPF_VAL_ERROR_SUMMARY_BAD_TE_LINK,
323   LMPF_VAL_ERROR_SUMMARY_BAD_DATA_LINK,
324
325   LMPF_MAX,
326 };
327
328 static int lmp_filter[LMPF_MAX];
329
330 static hf_register_info lmpf_info[] = {
331
332     /* Message type number */
333     {&lmp_filter[LMPF_MSG], 
334      { "Message Type", "lmp.msg", FT_UINT8, BASE_DEC, VALS(message_type_vals), 0x0,
335         "", HFILL }},
336
337     /* Message type shorthands */
338     {&lmp_filter[LMPF_MSG_CONFIG], 
339      { "Config Message", "lmp.msg.config", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
340         "", HFILL }},
341
342     {&lmp_filter[LMPF_MSG_CONFIG_ACK], 
343      { "ConfigAck Message", "lmp.msg.configack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
344         "", HFILL }},
345
346     {&lmp_filter[LMPF_MSG_CONFIG_NACK], 
347      { "ConfigNack Message", "lmp.msg.confignack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
348         "", HFILL }},
349
350     {&lmp_filter[LMPF_MSG_HELLO], 
351      { "HELLO Message", "lmp.msg.hello", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
352         "", HFILL }},
353
354     {&lmp_filter[LMPF_MSG_BEGIN_VERIFY], 
355      { "BeginVerify Message", "lmp.msg.beginverify", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
356         "", HFILL }},
357
358     {&lmp_filter[LMPF_MSG_BEGIN_VERIFY_ACK], 
359      { "BeginVerifyAck Message", "lmp.msg.beginverifyack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
360         "", HFILL }},
361
362     {&lmp_filter[LMPF_MSG_BEGIN_VERIFY_NACK], 
363      { "BeginVerifyNack Message", "lmp.msg.beginverifynack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
364         "", HFILL }},
365
366     {&lmp_filter[LMPF_MSG_END_VERIFY], 
367      { "EndVerify Message", "lmp.msg.endverify", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
368         "", HFILL }},
369
370     {&lmp_filter[LMPF_MSG_TEST], 
371      { "Test Message", "lmp.msg.test", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
372         "", HFILL }},
373
374     {&lmp_filter[LMPF_MSG_TEST_STATUS_SUCCESS], 
375      { "TestStatusSuccess Message", "lmp.msg.teststatussuccess", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
376         "", HFILL }},
377
378     {&lmp_filter[LMPF_MSG_TEST_STATUS_FAILURE], 
379      { "TestStatusFailure Message", "lmp.msg.teststatusfailure", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
380         "", HFILL }},
381
382     {&lmp_filter[LMPF_MSG_TEST_STATUS_ACK], 
383      { "TestStatusAck Message", "lmp.msg.teststatusack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
384         "", HFILL }},
385
386     {&lmp_filter[LMPF_MSG_LINK_SUMMARY], 
387      { "LinkSummary Message", "lmp.msg.linksummary", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
388         "", HFILL }},
389
390     {&lmp_filter[LMPF_MSG_LINK_SUMMARY_ACK], 
391      { "LinkSummaryAck Message", "lmp.msg.linksummaryack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
392         "", HFILL }},
393
394     {&lmp_filter[LMPF_MSG_LINK_SUMMARY_NACK], 
395      { "LinkSummaryNack Message", "lmp.msg.linksummarynack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
396         "", HFILL }},
397
398     {&lmp_filter[LMPF_MSG_CHANNEL_FAIL], 
399      { "ChannelFail Message", "lmp.msg.channelfail", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
400         "", HFILL }},
401
402     {&lmp_filter[LMPF_MSG_CHANNEL_FAIL_ACK], 
403      { "ChannelFailAck Message", "lmp.msg.channelfailack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
404         "", HFILL }},
405
406     {&lmp_filter[LMPF_MSG_CHANNEL_FAIL_NACK], 
407      { "ChannelFailNack Message", "lmp.msg.channelfailnack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
408         "", HFILL }},
409
410     {&lmp_filter[LMPF_MSG_CHANNEL_STATUS], 
411      { "ChannelStatus Message", "lmp.msg.channelstatus", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
412         "", HFILL }},
413
414     {&lmp_filter[LMPF_MSG_CHANNEL_STATUS_ACK], 
415      { "ChannelStatusAck Message", "lmp.msg.channelstatusack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
416         "", HFILL }},
417
418     {&lmp_filter[LMPF_MSG_CHANNEL_STATUS_REQ], 
419      { "ChannelStatusRequest Message", "lmp.msg.channelstatusrequest", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
420         "", HFILL }},
421
422     {&lmp_filter[LMPF_MSG_CHANNEL_STATUS_RESP], 
423      { "ChannelStatusResponse Message", "lmp.msg.channelstatusresponse", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
424         "", HFILL }},
425
426     
427     /* LMP Message Header Fields ------------------- */
428     
429     {&lmp_filter[LMPF_HDR_FLAGS], 
430      { "LMP Header - Flags", "lmp.hdr.flags", FT_UINT8, BASE_DEC, NULL, 0x0,
431         "", HFILL }},
432
433     {&lmp_filter[LMPF_HDR_FLAGS_CC_DOWN], 
434      { "ControlChannelDown", "lmp.hdr.ccdown", FT_BOOLEAN, 8, NULL, 0x01,
435         "", HFILL }},
436
437     {&lmp_filter[LMPF_HDR_FLAGS_REBOOT], 
438      { "Reboot", "lmp.hdr.reboot", FT_BOOLEAN, 8, NULL, 0x02,
439         "", HFILL }},
440
441     {&lmp_filter[LMPF_HDR_FLAGS_DWDM], 
442      { "DWDM Node", "lmp.hdr.dwdm", FT_BOOLEAN, 8, NULL, 0x04,
443         "", HFILL }},
444
445     {&lmp_filter[LMPF_HDR_FLAGS_AUTHENTICATION], 
446      { "Authentication", "lmp.hdr.auth", FT_BOOLEAN, 8, NULL, 0x08,
447         "", HFILL }},
448
449     /* LMP object class filters ------------------------------- */
450
451     {&lmp_filter[LMPF_OBJECT], 
452      { "LOCAL_CCID", "lmp.object", FT_UINT8, BASE_DEC, NULL, 0x0,
453         "", HFILL }},
454
455     {&lmp_filter[LMPF_CLASS_LOCAL_CCID], 
456      { "LOCAL_CCID", "lmp.obj.local_ccid", FT_NONE, BASE_NONE, NULL, 0x0,
457         "", HFILL }},
458     {&lmp_filter[LMPF_CLASS_REMOTE_CCID], 
459      { "REMOTE_CCID", "lmp.obj.remote_ccid", FT_NONE, BASE_NONE, NULL, 0x0,
460         "", HFILL }},
461
462     {&lmp_filter[LMPF_CLASS_LOCAL_NODE_ID], 
463      { "LOCAL_NODE_ID", "lmp.obj.local_nodeid", FT_NONE, BASE_NONE, NULL, 0x0,
464         "", HFILL }},
465     {&lmp_filter[LMPF_CLASS_REMOTE_NODE_ID], 
466      { "REMOTE_NODE_ID", "lmp.obj.remote_nodeid", FT_NONE, BASE_NONE, NULL, 0x0,
467         "", HFILL }},
468
469     {&lmp_filter[LMPF_CLASS_LOCAL_NODE_ID], 
470      { "LOCAL_NODE_ID", "lmp.obj.local_nodeid", FT_NONE, BASE_NONE, NULL, 0x0,
471         "", HFILL }},
472     {&lmp_filter[LMPF_CLASS_REMOTE_NODE_ID], 
473      { "REMOTE_NODE_ID", "lmp.obj.remote_nodeid", FT_NONE, BASE_NONE, NULL, 0x0,
474         "", HFILL }},
475
476     {&lmp_filter[LMPF_CLASS_LOCAL_LINK_ID], 
477      { "LOCAL_LINK_ID", "lmp.obj.local_linkid", FT_NONE, BASE_NONE, NULL, 0x0,
478         "", HFILL }},
479     {&lmp_filter[LMPF_CLASS_REMOTE_LINK_ID], 
480      { "REMOTE_LINK_ID", "lmp.obj.remote_linkid", FT_NONE, BASE_NONE, NULL, 0x0,
481         "", HFILL }},
482
483     {&lmp_filter[LMPF_CLASS_LOCAL_INTERFACE_ID], 
484      { "LOCAL_INTERFACE_ID", "lmp.obj.local_interfaceid", FT_NONE, BASE_NONE, NULL, 0x0,
485         "", HFILL }},
486     {&lmp_filter[LMPF_CLASS_REMOTE_INTERFACE_ID], 
487      { "REMOTE_INTERFACE_ID", "lmp.obj.remote_interfaceid", FT_NONE, BASE_NONE, NULL, 0x0,
488         "", HFILL }},
489
490     {&lmp_filter[LMPF_CLASS_MESSAGE_ID], 
491      { "MESSAGE_ID", "lmp.obj.messageid", FT_NONE, BASE_NONE, NULL, 0x0,
492         "", HFILL }},
493     {&lmp_filter[LMPF_CLASS_MESSAGE_ID_ACK], 
494      { "MESSAGE_ID_ACK", "lmp.obj.messageid_ack", FT_NONE, BASE_NONE, NULL, 0x0,
495         "", HFILL }},
496
497     {&lmp_filter[LMPF_CLASS_CONFIG], 
498      { "CONFIG", "lmp.obj.config", FT_NONE, BASE_NONE, NULL, 0x0,
499         "", HFILL }},
500
501     {&lmp_filter[LMPF_CLASS_HELLO], 
502      { "HELLO", "lmp.obj.hello", FT_NONE, BASE_NONE, NULL, 0x0,
503         "", HFILL }},
504
505     {&lmp_filter[LMPF_CLASS_BEGIN_VERIFY], 
506      { "BEGIN_VERIFY", "lmp.obj.begin_verify", FT_NONE, BASE_NONE, NULL, 0x0,
507         "", HFILL }},
508     {&lmp_filter[LMPF_CLASS_BEGIN_VERIFY_ACK], 
509      { "BEGIN_VERIFY_ACK", "lmp.obj.begin_verify_ack", FT_NONE, BASE_NONE, NULL, 0x0,
510         "", HFILL }},
511     {&lmp_filter[LMPF_CLASS_VERIFY_ID], 
512      { "VERIFY_ID", "lmp.obj.verifyid", FT_NONE, BASE_NONE, NULL, 0x0,
513         "", HFILL }},
514
515     {&lmp_filter[LMPF_CLASS_TE_LINK], 
516      { "TE_LINK", "lmp.obj.te_link", FT_NONE, BASE_NONE, NULL, 0x0,
517         "", HFILL }},
518     {&lmp_filter[LMPF_CLASS_DATA_LINK], 
519      { "DATA_LINK", "lmp.obj.data_link", FT_NONE, BASE_NONE, NULL, 0x0,
520         "", HFILL }},
521
522     {&lmp_filter[LMPF_CLASS_CHANNEL_STATUS], 
523      { "CHANNEL_STATUS", "lmp.obj.channel_status", FT_NONE, BASE_NONE, NULL, 0x0,
524         "", HFILL }},
525     {&lmp_filter[LMPF_CLASS_CHANNEL_STATUS_REQUEST], 
526      { "CHANNEL_STATUS_REQUEST", "lmp.obj.channel_status_request", FT_NONE, BASE_NONE, NULL, 0x0,
527         "", HFILL }},
528
529     {&lmp_filter[LMPF_CLASS_ERROR], 
530      { "ERROR", "lmp.obj.error", FT_NONE, BASE_NONE, NULL, 0x0,
531         "", HFILL }},
532
533     /* Other LMP Value Filters ------------------------------ */
534
535     {&lmp_filter[LMPF_VAL_CTYPE], 
536      { "Object C-Type", "lmp.obj.ctype", FT_UINT8, BASE_DEC, NULL, 0x0,
537         "", HFILL }},
538
539     {&lmp_filter[LMPF_VAL_LOCAL_CCID], 
540      { "Local CCID Value", "lmp.local_ccid", FT_UINT32, BASE_DEC, NULL, 0x0,
541         "", HFILL }},
542     {&lmp_filter[LMPF_VAL_REMOTE_CCID], 
543      { "Remote CCID Value", "lmp.remote_ccid", FT_UINT32, BASE_DEC, NULL, 0x0,
544         "", HFILL }},
545
546     {&lmp_filter[LMPF_VAL_LOCAL_NODE_ID], 
547      { "Local Node ID Value", "lmp.local_nodeid", FT_IPv4, BASE_NONE, NULL, 0x0,
548         "", HFILL }},
549     {&lmp_filter[LMPF_VAL_REMOTE_NODE_ID], 
550      { "Remote Node ID Value", "lmp.remote_nodeid", FT_IPv4, BASE_NONE, NULL, 0x0,
551         "", HFILL }},
552
553     {&lmp_filter[LMPF_VAL_LOCAL_LINK_ID_IPV4], 
554      { "Local Link ID - IPv4", "lmp.local_linkid_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
555         "", HFILL }},
556     {&lmp_filter[LMPF_VAL_LOCAL_LINK_ID_UNNUM], 
557      { "Local Link ID - Unnumbered", "lmp.local_linkid_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
558         "", HFILL }},
559     {&lmp_filter[LMPF_VAL_REMOTE_LINK_ID_IPV4], 
560      { "Remote Link ID - IPv4", "lmp.remote_linkid_ipv4", FT_UINT32, BASE_DEC, NULL, 0x0,
561         "", HFILL }},
562     {&lmp_filter[LMPF_VAL_REMOTE_LINK_ID_UNNUM], 
563      { "Remote Link ID - Unnumbered", "lmp.remote_linkid_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
564         "", HFILL }},
565
566     {&lmp_filter[LMPF_VAL_LOCAL_INTERFACE_ID_IPV4], 
567      { "Local Interface ID - IPv4", "lmp.local_interfaceid_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
568         "", HFILL }},
569     {&lmp_filter[LMPF_VAL_LOCAL_INTERFACE_ID_UNNUM], 
570      { "Local Interface ID - Unnumbered", "lmp.local_interfaceid_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
571         "", HFILL }},
572     {&lmp_filter[LMPF_VAL_REMOTE_INTERFACE_ID_IPV4], 
573      { "Remote Interface ID - IPv4", "lmp.remote_interfaceid_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
574         "", HFILL }},
575     {&lmp_filter[LMPF_VAL_REMOTE_INTERFACE_ID_UNNUM], 
576      { "Remote Interface ID - Unnumbered", "lmp.remote_interfaceid_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
577         "", HFILL }},
578     
579     {&lmp_filter[LMPF_VAL_MESSAGE_ID], 
580      { "Message-ID Value", "lmp.messageid", FT_UINT32, BASE_DEC, NULL, 0x0,
581         "", HFILL }},
582     {&lmp_filter[LMPF_VAL_MESSAGE_ID_ACK], 
583      { "Message-ID Ack Value", "lmp.messageid_ack", FT_UINT32, BASE_DEC, NULL, 0x0,
584         "", HFILL }},
585
586     {&lmp_filter[LMPF_VAL_CONFIG_HELLO], 
587      { "HelloInterval", "lmp.hellointerval", FT_UINT32, BASE_DEC, NULL, 0x0,
588         "", HFILL }},
589     {&lmp_filter[LMPF_VAL_CONFIG_HELLO_DEAD], 
590      { "HelloDeadInterval", "lmp.hellodeadinterval", FT_UINT32, BASE_DEC, NULL, 0x0,
591         "", HFILL }},
592
593     {&lmp_filter[LMPF_VAL_HELLO_TXSEQ], 
594      { "TxSeqNum", "lmp.txseqnum", FT_UINT32, BASE_DEC, NULL, 0x0,
595         "", HFILL }},
596     {&lmp_filter[LMPF_VAL_HELLO_RXSEQ], 
597      { "RxSeqNum", "lmp.rxseqnum", FT_UINT32, BASE_DEC, NULL, 0x0,
598         "", HFILL }},
599
600     {&lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS], 
601      { "Flags", "lmp.begin_verify.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
602         "", HFILL }},
603     {&lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_ALL_LINKS], 
604      { "Verify All Links", "lmp.begin_verify.all_links", 
605        FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
606     {&lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_LINK_TYPE], 
607      { "Data Link Type", "lmp.begin_verify.link_type", 
608        FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
609     {&lmp_filter[LMPF_VAL_BEGIN_VERIFY_ENCTYPE], 
610      { "Encoding Type", "lmp.begin_verify.enctype", FT_UINT8, BASE_DEC, VALS(gmpls_lsp_enc_str), 0x0,
611         "", HFILL }},
612     {&lmp_filter[LMPF_VAL_VERIFY_ID], 
613      { "Verify-ID", "lmp.verifyid", FT_UINT32, BASE_DEC, NULL, 0x0,
614         "", HFILL }},
615
616     {&lmp_filter[LMPF_VAL_TE_LINK_FLAGS], 
617      { "TE-Link Flags", "lmp.te_link_flags", FT_UINT8, BASE_HEX, NULL, 0x0,
618         "", HFILL }},
619     {&lmp_filter[LMPF_VAL_TE_LINK_FLAGS_FAULT_MGMT], 
620      { "Fault Management Supported", "lmp.te_link.fault_mgmt", 
621        FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
622     {&lmp_filter[LMPF_VAL_TE_LINK_FLAGS_LINK_VERIFY], 
623      { "Link Verification Supported", "lmp.te_link.link_verify", 
624        FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
625     {&lmp_filter[LMPF_VAL_TE_LINK_LOCAL_IPV4], 
626      { "TE-Link Local ID - IPv4", "lmp.te_link.local_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
627         "", HFILL }},
628     {&lmp_filter[LMPF_VAL_TE_LINK_LOCAL_UNNUM], 
629      { "TE-Link Local ID - Unnumbered", "lmp.te_link.local_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
630         "", HFILL }},
631     {&lmp_filter[LMPF_VAL_TE_LINK_REMOTE_IPV4], 
632      { "TE-Link Remote ID - IPv4", "lmp.te_link.remote_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
633         "", HFILL }},
634     {&lmp_filter[LMPF_VAL_TE_LINK_REMOTE_UNNUM], 
635      { "TE-Link Remote ID - Unnumbered", "lmp.te_link.remote_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
636         "", HFILL }},
637
638     {&lmp_filter[LMPF_VAL_DATA_LINK_FLAGS], 
639      { "Data-Link Flags", "lmp.data_link_flags", FT_UINT8, BASE_HEX, NULL, 0x0,
640         "", HFILL }},
641     {&lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_PORT], 
642      { "Data-Link is Individual Port", "lmp.data_link.port", 
643        FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
644     {&lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_ALLOCATED], 
645      { "Data-Link is Allocated", "lmp.data_link.link_verify", 
646        FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
647     {&lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_IPV4], 
648      { "Data-Link Local ID - IPv4", "lmp.data_link.local_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
649         "", HFILL }},
650     {&lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_UNNUM], 
651      { "Data-Link Local ID - Unnumbered", "lmp.data_link.local_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
652         "", HFILL }},
653     {&lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_IPV4], 
654      { "Data-Link Remote ID - IPv4", "lmp.data_link.remote_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
655         "", HFILL }},
656     {&lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_UNNUM], 
657      { "Data-Link Remote ID - Unnumbered", "lmp.data_link.remote_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
658         "", HFILL }},
659     {&lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ], 
660      { "Subobject", "lmp.data_link_subobj", FT_NONE, BASE_DEC, NULL, 0x0,
661         "", HFILL }},
662     {&lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_SWITCHING_TYPE], 
663      { "Interface Switching Capability", "lmp.data_link_switching", FT_UINT8, BASE_DEC, 
664        VALS(gmpls_switching_type_str), 0x0, "", HFILL }},
665     {&lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_LSP_ENCODING], 
666      { "LSP Encoding Type", "lmp.data_link_encoding", FT_UINT8, BASE_DEC, 
667        VALS(gmpls_lsp_enc_str), 0x0, "", HFILL }},
668
669     {&lmp_filter[LMPF_VAL_ERROR], 
670      { "Error Code", "lmp.error", FT_UINT32, BASE_HEX, NULL, 0x0,
671         "", HFILL }},
672
673     {&lmp_filter[LMPF_VAL_ERROR_VERIFY_UNSUPPORTED_LINK], 
674      { "Verification - Unsupported for this TE-Link", "lmp.error.verify_unsupported_link", 
675        FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
676     {&lmp_filter[LMPF_VAL_ERROR_VERIFY_UNWILLING], 
677      { "Verification - Unwilling to Verify at this time", "lmp.error.verify_unwilling", 
678        FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
679     {&lmp_filter[LMPF_VAL_ERROR_VERIFY_TRANSPORT], 
680      { "Verification - Transport Unsupported", "lmp.error.verify_unsupported_transport", 
681        FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }},
682     {&lmp_filter[LMPF_VAL_ERROR_VERIFY_TE_LINK_ID], 
683      { "Verification - TE Link ID Configuration Error", "lmp.error.verify_te_link_id", 
684        FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }},
685
686     {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_PARAMETERS], 
687      { "Summary - Unacceptable non-negotiable parameters", "lmp.error.summary_bad_params", 
688        FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
689     {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_RENEGOTIATE], 
690      { "Summary - Renegotiate Parametere", "lmp.error.summary_renegotiate", 
691        FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
692     {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_REMOTE_LINK_ID], 
693      { "Summary - Bad Remote Link ID", "lmp.error.summary_bad_remote_linkid", 
694        FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }},
695     {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_TE_LINK], 
696      { "Summary - Bad TE Link Object", "lmp.error.summary_bad_te_link", 
697        FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }},
698     {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_DATA_LINK], 
699      { "Summary - Bad Data Link Object", "lmp.error.summary_bad_data_link", 
700        FT_BOOLEAN, 8, NULL, 0x10, "", HFILL }},
701 };
702
703 static int
704 lmp_class_to_filter_num(int class)
705 {
706     if (VALID_CLASS(class))
707         return class + LMPF_OBJECT;
708     return -1;
709 }
710
711 /*------------------------------------------------------------------------------
712  * LMP Subtrees
713  *
714  * We have two types of subtrees - a statically defined, constant set and
715  * a class set - one for each class. The static ones are before all the class ones
716  */
717 enum {
718     LMP_TREE_MAIN,
719     LMP_TREE_HEADER,
720     LMP_TREE_HEADER_FLAGS,
721     LMP_TREE_OBJECT_HEADER,
722     LMP_TREE_ERROR_FLAGS,
723     LMP_TREE_BEGIN_VERIFY_FLAGS,
724     LMP_TREE_BEGIN_VERIFY_TRANSPORT_FLAGS,
725     LMP_TREE_TE_LINK_FLAGS,
726     LMP_TREE_DATA_LINK_FLAGS,
727     LMP_TREE_DATA_LINK_SUBOBJ,
728     LMP_TREE_CHANNEL_STATUS_ID,
729
730     LMP_TREE_CLASS_START
731 };
732 #define NUM_LMP_SUBTREES (LMP_TREE_CLASS_START + LMP_CLASS_MAX)
733
734 static gint lmp_subtree[NUM_LMP_SUBTREES];
735
736 static int lmp_class_to_subtree(int class)
737 {
738     if (VALID_CLASS(class)) 
739         return lmp_subtree[LMP_TREE_CLASS_START + class];
740
741     return -1;
742 }
743
744 /*------------------------------------------------------------------------------
745  * Da code 
746  */
747
748 static void 
749 dissect_lmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
750 {
751     int offset = 0;
752     proto_tree *lmp_tree = NULL, *ti, *ti2; 
753     proto_tree *lmp_header_tree;
754     proto_tree *lmp_header_flags_tree;
755     proto_tree *lmp_object_tree;
756     proto_tree *lmp_object_header_tree;
757     proto_tree *lmp_flags_tree;
758     proto_tree *lmp_subobj_tree;
759
760     guint8 version;
761     guint8 flags;
762     guint8 message_type;
763     guint16 cksum, computed_cksum;
764     vec_t cksum_vec[1];
765     int i, j, k, l, len;
766     int msg_length;
767     int obj_length;
768     int mylen;
769     int offset2;
770     char *objtype;
771     int session_off, tempfilt_off;
772
773     if (check_col(pinfo->cinfo, COL_PROTOCOL))
774         col_set_str(pinfo->cinfo, COL_PROTOCOL, "LMP");
775     if (check_col(pinfo->cinfo, COL_INFO))
776         col_clear(pinfo->cinfo, COL_INFO);
777
778     version = (tvb_get_guint8(tvb, offset+0)) >> 4;
779     flags = tvb_get_guint8(tvb, offset+2);
780     message_type = tvb_get_guint8(tvb, offset+3);
781     if (check_col(pinfo->cinfo, COL_INFO)) {
782         col_add_str(pinfo->cinfo, COL_INFO,
783             val_to_str(message_type, message_type_vals, "Unknown (%u). ")); 
784     }
785
786     if (tree) {
787         msg_length = tvb_get_ntohs(tvb, offset+4);
788         ti = proto_tree_add_item(tree, proto_lmp, tvb, offset, msg_length,
789             FALSE);
790         lmp_tree = proto_item_add_subtree(ti, lmp_subtree[LMP_TREE_MAIN]);
791
792         ti = proto_tree_add_text(lmp_tree, tvb, offset, 12, "LMP Header. %s", 
793                                  val_to_str(message_type, message_type_vals, 
794                                             "Unknown Message (%u). ")); 
795         lmp_header_tree = proto_item_add_subtree(ti, lmp_subtree[LMP_TREE_HEADER]);
796
797         proto_tree_add_text(lmp_header_tree, tvb, offset, 1, "LMP Version: %u", 
798                             version);  
799         ti = proto_tree_add_text(lmp_header_tree, tvb, offset+2, 1, "Flags: %02x",
800                                  flags);
801         lmp_header_flags_tree = proto_item_add_subtree(ti, lmp_subtree[LMP_TREE_HEADER_FLAGS]);
802         proto_tree_add_boolean(lmp_header_flags_tree, lmp_filter[LMPF_HDR_FLAGS_CC_DOWN],
803                                tvb, offset+2, 1, flags);
804         proto_tree_add_boolean(lmp_header_flags_tree, lmp_filter[LMPF_HDR_FLAGS_REBOOT],
805                                tvb, offset+2, 1, flags);
806         proto_tree_add_boolean(lmp_header_flags_tree, lmp_filter[LMPF_HDR_FLAGS_DWDM],
807                                tvb, offset+2, 1, flags);
808         proto_tree_add_boolean(lmp_header_flags_tree, lmp_filter[LMPF_HDR_FLAGS_AUTHENTICATION],
809                                tvb, offset+2, 1, flags);
810         proto_tree_add_uint(lmp_header_tree, lmp_filter[LMPF_MSG], tvb, 
811                             offset+3, 1, message_type);
812         proto_tree_add_text(lmp_header_tree, tvb, offset+4, 2, "Length: %d bytes",
813                             msg_length);
814         proto_tree_add_boolean_hidden(lmp_header_tree, lmp_filter[LMPF_MSG + message_type], tvb, 
815                                       offset+3, 1, 1);
816         
817         cksum = tvb_get_ntohs(tvb, offset+6);
818         if (!pinfo->fragmented && (int) tvb_length(tvb) >= msg_length) {
819             /* The packet isn't part of a fragmented datagram and isn't
820                truncated, so we can checksum it. */
821             cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, msg_length);
822             cksum_vec[0].len = msg_length;
823             computed_cksum = in_cksum(&cksum_vec[0], 1);
824             if (computed_cksum == 0) {
825                 proto_tree_add_text(lmp_header_tree, tvb, offset+6, 2,
826                                     "Message Checksum: 0x%04x (correct)",
827                                     cksum);
828             } else {
829                 proto_tree_add_text(lmp_header_tree, tvb, offset+6, 2,
830                                     "Message Checksum: 0x%04x (incorrect, should be 0x%04x)",
831                                     cksum,
832                                     in_cksum_shouldbe(cksum, computed_cksum));
833             }
834         } else {
835             proto_tree_add_text(lmp_header_tree, tvb, offset+6, 2,
836                                 "Message Checksum: 0x%04x",
837                                 cksum);
838         }
839         proto_tree_add_text(lmp_header_tree, tvb, offset+8, 4, 
840                             "Local Control Channel ID: %d (%s)",
841                             tvb_get_ntohl(tvb, offset+8), 
842                             ip_to_str(tvb_get_ptr(tvb, offset+8, 4)));
843
844         offset += 8;
845         len = 8;
846         while (len < msg_length) {
847             guint8 class;       
848             guint8 type;
849             guint8 negotiable;
850             char *object_type;
851
852             obj_length = tvb_get_ntohs(tvb, offset+2);
853             class = tvb_get_guint8(tvb, offset+1);
854             type = tvb_get_guint8(tvb, offset);
855             negotiable = (type >> 7); type &= 0x7f;
856             object_type = val_to_str(class, lmp_class_vals, "Unknown");
857             proto_tree_add_uint_hidden(lmp_tree, lmp_filter[LMPF_OBJECT], tvb, 
858                                             offset, 1, class);
859             ti = proto_tree_add_item(lmp_tree, lmp_filter[lmp_class_to_filter_num(class)],
860                                      tvb, offset, obj_length, FALSE);
861
862             lmp_object_tree = proto_item_add_subtree(ti, lmp_class_to_subtree(class));
863
864             ti2 = proto_tree_add_text(lmp_object_tree, tvb, offset, 4, 
865                                       "Header. Class %d, C-Type %d, Length %d, %s",
866                                       class, type, obj_length, 
867                                       negotiable ? "Negotiable" : "Not Negotiable");
868             lmp_object_header_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_OBJECT_HEADER]);
869             proto_tree_add_text(lmp_object_header_tree, tvb, offset, 1, 
870                                 negotiable ? "Negotiable" : "Not Negotiable");
871             proto_tree_add_text(lmp_object_header_tree, tvb, offset+2, 2,
872                                 "Length: %u", obj_length);
873             proto_tree_add_text(lmp_object_header_tree, tvb, offset+1, 1, 
874                                 "Object Class: %u - %s", 
875                                 class, object_type);
876             proto_tree_add_item(lmp_object_header_tree, lmp_filter[LMPF_VAL_CTYPE], 
877                                 tvb, offset, 1, type);
878             offset2 = offset+4;
879             mylen = obj_length - 4;
880
881             switch(class) {
882                 
883             case LMP_CLASS_NULL:
884                 break;
885                 
886             case LMP_CLASS_LOCAL_CCID:
887             case LMP_CLASS_REMOTE_CCID:
888                 switch(type) {
889                 case 1: 
890                     l = (class == LMP_CLASS_LOCAL_CCID) ? 
891                         LMPF_VAL_LOCAL_CCID : LMPF_VAL_REMOTE_CCID;
892                     proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
893                     proto_tree_add_uint(lmp_object_tree, lmp_filter[l], tvb, offset2, 4, 
894                                         tvb_get_ntohl(tvb, offset2));
895                     break;
896                 default:
897                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
898                                         "Data (%d bytes)", mylen);
899                     break;
900                 }
901                 break;
902                     
903             case LMP_CLASS_LOCAL_NODE_ID:
904             case LMP_CLASS_REMOTE_NODE_ID:
905                 switch(type) {
906                 case 1: 
907                     l = (class == LMP_CLASS_LOCAL_NODE_ID) ? 
908                         LMPF_VAL_LOCAL_NODE_ID : LMPF_VAL_REMOTE_NODE_ID;
909                     proto_item_append_text(ti, ": %s", 
910                                            ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
911                     proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4, 
912                                         FALSE);
913                     break;
914                 default:
915                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
916                                         "Data (%d bytes)", mylen);
917                     break;
918                 }
919                 break;
920
921             case LMP_CLASS_LOCAL_LINK_ID:
922             case LMP_CLASS_REMOTE_LINK_ID:
923                 switch(type) {
924                 case 1: 
925                     l = (class == LMP_CLASS_LOCAL_LINK_ID) ? 
926                         LMPF_VAL_LOCAL_LINK_ID_IPV4 : LMPF_VAL_REMOTE_LINK_ID_IPV4;
927                     proto_item_append_text(ti, ": IPv4 %s", 
928                                            ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
929                     proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4, 
930                                         FALSE);
931                     break;
932                 case 2: 
933                     proto_item_append_text(ti, ": IPv6 %s", 
934                                            ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
935                     proto_tree_add_text(lmp_object_tree, tvb, offset2, 16, "IPv6: %s", 
936                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
937                     break;
938                 case 3: 
939                     l = (class == LMP_CLASS_LOCAL_LINK_ID) ? 
940                         LMPF_VAL_LOCAL_LINK_ID_UNNUM : LMPF_VAL_REMOTE_LINK_ID_UNNUM;
941                     proto_item_append_text(ti, ": Unnumbered %d", tvb_get_ntohl(tvb, offset2));
942                     proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4, 
943                                         FALSE);
944                     break;
945                 default:
946                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
947                                         "Data (%d bytes)", mylen);
948                     break;
949                 }
950                 break;
951
952             case LMP_CLASS_LOCAL_INTERFACE_ID:
953             case LMP_CLASS_REMOTE_INTERFACE_ID:
954                 switch(type) {
955                 case 1: 
956                     l = (class == LMP_CLASS_LOCAL_INTERFACE_ID) ? 
957                         LMPF_VAL_LOCAL_INTERFACE_ID_IPV4 : LMPF_VAL_REMOTE_INTERFACE_ID_IPV4;
958                     proto_item_append_text(ti, ": IPv4 %s", 
959                                            ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
960                     proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4, 
961                                         FALSE);
962                     break;
963                 case 2: 
964                     proto_item_append_text(ti, ": IPv6 %s", 
965                                            ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
966                     proto_tree_add_text(lmp_object_tree, tvb, offset2, 16, "IPv6: %s", 
967                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
968                     break;
969                 case 3: 
970                     l = (class == LMP_CLASS_LOCAL_INTERFACE_ID) ? 
971                         LMPF_VAL_LOCAL_INTERFACE_ID_UNNUM : LMPF_VAL_REMOTE_INTERFACE_ID_UNNUM;
972                     proto_item_append_text(ti, ": Unnumbered %d", tvb_get_ntohl(tvb, offset2));
973                     proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4, 
974                                         FALSE);
975                     break;
976                 default:
977                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
978                                         "Data (%d bytes)", mylen);
979                     break;
980                 }
981                 break;
982
983             case LMP_CLASS_MESSAGE_ID:
984             case LMP_CLASS_MESSAGE_ID_ACK:
985                 switch(type) {
986                 case 1: 
987                     l = (class == LMP_CLASS_MESSAGE_ID) ? 
988                         LMPF_VAL_MESSAGE_ID : LMPF_VAL_MESSAGE_ID_ACK;
989                     proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
990                     proto_tree_add_uint(lmp_object_tree, lmp_filter[l], tvb, offset2, 4, 
991                                         tvb_get_ntohl(tvb, offset2));
992                     break;
993                 default:
994                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
995                                         "Data (%d bytes)", mylen);
996                     break;
997                 }
998                 break;
999                     
1000             case LMP_CLASS_CONFIG:
1001                 switch(type) {
1002                 case 1: 
1003                     proto_item_append_text(ti, ": HelloInterval: %d, HelloDeadInterval: %d", 
1004                                            tvb_get_ntohs(tvb, offset2), tvb_get_ntohs(tvb, offset2+2));
1005                     proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_CONFIG_HELLO], 
1006                                         tvb, offset2, 2, tvb_get_ntohs(tvb, offset2));
1007                     proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_CONFIG_HELLO_DEAD], 
1008                                         tvb, offset2+2, 2, tvb_get_ntohs(tvb, offset2+2));
1009                     break;
1010                 default:
1011                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
1012                                         "Data (%d bytes)", mylen);
1013                     break;
1014                 }
1015                 break;
1016                     
1017             case LMP_CLASS_HELLO:
1018                 switch(type) {
1019                 case 1: 
1020                     proto_item_append_text(ti, ": TxSeq %d, RxSeq: %d", 
1021                                            tvb_get_ntohl(tvb, offset2), 
1022                                            tvb_get_ntohl(tvb, offset2+4));
1023                     proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_HELLO_TXSEQ], 
1024                                         tvb, offset2, 4, tvb_get_ntohl(tvb, offset2));
1025                     proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_HELLO_RXSEQ], 
1026                                         tvb, offset2+4, 4, tvb_get_ntohl(tvb, offset2+4));
1027                     break;
1028                 default:
1029                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
1030                                         "Data (%d bytes)", mylen);
1031                     break;
1032                 }
1033                 break;
1034                 
1035             case LMP_CLASS_BEGIN_VERIFY:
1036                 switch(type) {
1037                 case 1: 
1038                     l = tvb_get_ntohs(tvb, offset2);
1039                     ti2 = proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS],
1040                                               tvb, offset2, 2, FALSE);
1041
1042                     lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_BEGIN_VERIFY_FLAGS]);
1043                     proto_tree_add_boolean(lmp_flags_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_ALL_LINKS],
1044                                            tvb, offset2, 2, l);
1045                     proto_tree_add_boolean(lmp_flags_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_LINK_TYPE],
1046                                            tvb, offset2, 2, l);
1047                     proto_tree_add_text(lmp_object_tree, tvb, offset2+2, 2, 
1048                                         "Verify Interval: %d ms", tvb_get_ntohs(tvb, offset2+2));
1049                     proto_tree_add_text(lmp_object_tree, tvb, offset2+4, 4, 
1050                                         "Number of Data Links: %d", tvb_get_ntohl(tvb, offset2+4));
1051                     proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_ENCTYPE], 
1052                                         tvb, offset2+8, 1, FALSE);
1053                     proto_tree_add_text(lmp_object_tree, tvb, offset2+10, 2, 
1054                                         "Verify Transport Mechanism: 0x%0x", tvb_get_ntohs(tvb, offset2+10));
1055                     proto_tree_add_text(lmp_object_tree, tvb, offset2+12, 4, 
1056                                         "Transmission Rate: %.10g", tvb_get_ntohieee_float(tvb, offset2+12));
1057                     proto_tree_add_text(lmp_object_tree, tvb, offset2+16, 4, 
1058                                         "Wavelength: %d", tvb_get_ntohl(tvb, offset2+4));
1059                     break;
1060                 default:
1061                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
1062                                         "Data (%d bytes)", mylen);
1063                     break;
1064                 }
1065                 break;
1066                     
1067             case LMP_CLASS_BEGIN_VERIFY_ACK:
1068                 switch(type) {
1069                 case 1: 
1070                     proto_item_append_text(ti, ": VerifyDeadInterval: %d, TransportResponse: 0x%0x", 
1071                                            tvb_get_ntohs(tvb, offset2), tvb_get_ntohs(tvb, offset2+2));
1072                     proto_tree_add_text(lmp_object_tree, tvb, offset2, 2, 
1073                                         "VerifyDeadInterval: %d ms", tvb_get_ntohs(tvb, offset2));
1074                     proto_tree_add_text(lmp_object_tree, tvb, offset2+2, 2, 
1075                                         "Verify Transport Response: 0x%0x", tvb_get_ntohs(tvb, offset2+2));
1076                     break;
1077                 default:
1078                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
1079                                         "Data (%d bytes)", mylen);
1080                     break;
1081                 }
1082                 break;
1083                     
1084             case LMP_CLASS_VERIFY_ID:
1085                 switch(type) {
1086                 case 1: 
1087                     proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
1088                     proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_VERIFY_ID], tvb, offset2, 4, 
1089                                         tvb_get_ntohl(tvb, offset2));
1090                     break;
1091                 default:
1092                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
1093                                         "Data (%d bytes)", mylen);
1094                     break;
1095                 }
1096                 break;
1097                     
1098             case LMP_CLASS_TE_LINK:
1099                 l = tvb_get_guint8(tvb, offset2);
1100                 ti2 = proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_FLAGS], 
1101                                           tvb, offset2, 1, l);
1102                 proto_item_append_text(ti2, ": %s%s", 
1103                                        (l&0x01) ? "Fault-Mgmt-Supported " : "",
1104                                        (l&0x02) ? "Link-Verification-Supported " : "");
1105                 lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_TE_LINK_FLAGS]);
1106                 proto_tree_add_boolean(lmp_flags_tree, 
1107                                        lmp_filter[LMPF_VAL_TE_LINK_FLAGS_FAULT_MGMT], 
1108                                        tvb, offset2, 1, l);
1109                 proto_tree_add_boolean(lmp_flags_tree, 
1110                                        lmp_filter[LMPF_VAL_TE_LINK_FLAGS_LINK_VERIFY], 
1111                                        tvb, offset2, 1, l);
1112                 switch(type) {
1113                 case 1: 
1114                     proto_item_append_text(ti, ": IPv4: Local %s, Remote %s", 
1115                                            ip_to_str(tvb_get_ptr(tvb, offset2+4, 4)),
1116                                            ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
1117                     proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_LOCAL_IPV4], 
1118                                         tvb, offset2+4, 4, FALSE);
1119                     proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_REMOTE_IPV4], 
1120                                         tvb, offset2+8, 4, FALSE);
1121                     break;
1122                 case 2: 
1123                     proto_item_append_text(ti, ": IPv6: Local %s, Remote %s", 
1124                                            ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)),
1125                                            ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+8, 16)));
1126                     proto_tree_add_text(lmp_object_tree, tvb, offset2+4, 16, "TE-Link Local ID - IPv6: %s", 
1127                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1128                     proto_tree_add_text(lmp_object_tree, tvb, offset2+20,16, "TE-Link Remote ID - IPv6: %s", 
1129                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)));
1130                     break;
1131                 case 3: 
1132                     proto_item_append_text(ti, ": Unnumbered: Local %d, Remote %d", 
1133                                            tvb_get_ntohl(tvb, offset2+4), tvb_get_ntohl(tvb, offset2+8));
1134                     proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_LOCAL_UNNUM], 
1135                                         tvb, offset2+4, 4, FALSE);
1136                     proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_REMOTE_UNNUM], 
1137                                         tvb, offset2+8, 4, FALSE);
1138                     break;
1139                 default:
1140                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
1141                                         "Data (%d bytes)", mylen);
1142                     break;
1143                 }
1144                 break;
1145
1146             case LMP_CLASS_DATA_LINK:
1147                 l = tvb_get_guint8(tvb, offset2);
1148                 ti2 = proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_FLAGS], 
1149                                           tvb, offset2, 1, l);
1150                 proto_item_append_text(ti2, ": %s%s", 
1151                                        (l&0x01) ? "Interface-Type-Port " : "Interface-Type-Component-Link ",
1152                                        (l&0x02) ? "Allocated " : "Unallocated ");
1153                 lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_DATA_LINK_FLAGS]);
1154                 proto_tree_add_boolean(lmp_flags_tree, 
1155                                        lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_PORT], 
1156                                        tvb, offset2, 1, l);
1157                 proto_tree_add_boolean(lmp_flags_tree, 
1158                                        lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_ALLOCATED], 
1159                                        tvb, offset2, 1, l);
1160                 switch(type) {
1161                 case 1: 
1162                     proto_item_append_text(ti, ": IPv4: Local %s, Remote %s", 
1163                                            ip_to_str(tvb_get_ptr(tvb, offset2+4, 4)),
1164                                            ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
1165                     proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_IPV4], 
1166                                         tvb, offset2+4, 4, FALSE);
1167                     proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_IPV4], 
1168                                         tvb, offset2+8, 4, FALSE);
1169                     l = 12;
1170                     break;
1171                 case 2: 
1172                     proto_item_append_text(ti, ": IPv6: Local %s, Remote %s", 
1173                                            ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)),
1174                                            ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+8, 16)));
1175                     proto_tree_add_text(lmp_object_tree, tvb, offset2+4, 16, 
1176                                         "Data-Link Local ID - IPv6: %s", 
1177                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1178                     proto_tree_add_text(lmp_object_tree, tvb, offset2+20,16, 
1179                                         "Data-Link Remote ID - IPv6: %s", 
1180                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)));
1181                     l = 36;
1182                     break;
1183                 case 3: 
1184                     proto_item_append_text(ti, ": Unnumbered: Local %d, Remote %d", 
1185                                            tvb_get_ntohl(tvb, offset2+4), tvb_get_ntohl(tvb, offset2+8));
1186                     proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_UNNUM], 
1187                                         tvb, offset2+4, 4, FALSE);
1188                     proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_UNNUM], 
1189                                         tvb, offset2+8, 4, FALSE);
1190                     l = 12;
1191                     break;
1192                 default:
1193                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
1194                                         "Data (%d bytes)", mylen);
1195                     break;
1196                 }
1197
1198                 while (l < obj_length - 4) {
1199                     mylen = tvb_get_guint8(tvb, offset2+l+1);
1200                     ti2 = proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ],
1201                                               tvb, offset2+l, mylen, FALSE);
1202                     lmp_subobj_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_DATA_LINK_SUBOBJ]);
1203                     proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 1, 
1204                                         "Subobject Type: %d", tvb_get_guint8(tvb, offset2+l));
1205                     proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+1, 1, 
1206                                         "Subobject Length: %d", mylen);
1207                     switch(tvb_get_guint8(tvb, offset2+l)) {
1208                     case 1: 
1209                         proto_item_set_text(ti2, "Interface Switching Capability: "
1210                                             "Switching Cap: %s, Encoding Type: %s, Min BW: %.10g, Max BW: %.10g", 
1211                                             val_to_str(tvb_get_guint8(tvb, offset2+l+2), 
1212                                                        gmpls_switching_type_str, "Unknown (%d)"),
1213                                             val_to_str(tvb_get_guint8(tvb, offset2+l+3), 
1214                                                        gmpls_lsp_enc_str, "Unknown (%d)"),
1215                                             tvb_get_ntohieee_float(tvb, offset2+l+4), 
1216                                             tvb_get_ntohieee_float(tvb, offset2+l+8));
1217                         proto_tree_add_item(lmp_subobj_tree, 
1218                                             lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_SWITCHING_TYPE],
1219                                             tvb, offset2+l+2, 1, FALSE);
1220                         proto_tree_add_item(lmp_subobj_tree, 
1221                                             lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_LSP_ENCODING],
1222                                             tvb, offset2+l+3, 1, FALSE);
1223                         proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+4, 4, 
1224                                             "Minimum Reservable Bandwidth: %.10g bytes/s", 
1225                                             tvb_get_ntohieee_float(tvb, offset2+l+4));
1226                         proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+8, 4, 
1227                                             "Maximum Reservable Bandwidth: %.10g bytes/s", 
1228                                             tvb_get_ntohieee_float(tvb, offset2+l+8));
1229                         break;
1230
1231                     case 2:
1232                         proto_item_set_text(ti2, "Wavelength: %d", 
1233                                             tvb_get_ntohl(tvb, offset2+l+2));
1234                         proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+4, 4, 
1235                                             "Wavelength: %d", 
1236                                             tvb_get_ntohl(tvb, offset2+l+2));
1237                         break;
1238
1239                     default:
1240                         proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 
1241                                             tvb_get_guint8(tvb, offset2+l+1),
1242                                             "Data (%d bytes)", tvb_get_guint8(tvb, offset2+l+1));
1243                         break;
1244                     }
1245                     l += tvb_get_guint8(tvb, offset2+l+1);
1246                 }
1247                     
1248                 break;
1249
1250             case LMP_CLASS_CHANNEL_STATUS:
1251                 k = 0; j = 0;
1252                 switch(type) {
1253                 case 1:
1254                 case 3:
1255                     k = 8; break;
1256                 case 2:
1257                     k = 20; break;
1258                 }
1259                 if (!k)
1260                     break;
1261                 for (l=0; l<obj_length - 4; ) {
1262                     ti2 = proto_tree_add_text(lmp_object_tree, tvb, offset2+l, k, 
1263                                               "Interface-Id");
1264                     lmp_subobj_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_CHANNEL_STATUS_ID]);
1265                     switch(type) {
1266                     case 1: 
1267                         if (j < 4) 
1268                             proto_item_append_text(ti, ": [IPv4-%s", 
1269                                                    ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
1270                         proto_item_append_text(ti2, ": IPv4 %s", 
1271                                                ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
1272                         proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 4, 
1273                                             "Interface ID: IPv4: %s", 
1274                                             ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
1275                         l += 4;
1276                         break;
1277                     case 2: 
1278                         if (j < 4) 
1279                             proto_item_append_text(ti, ": [IPv6-%s", 
1280                                                    ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l, 16)));
1281                         proto_item_append_text(ti2, ": IPv6 %s", 
1282                                                ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l, 16)));
1283                         proto_tree_add_text(lmp_subobj_tree, tvb, offset2, 16, "Interface ID: IPv6: %s", 
1284                                             ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l, 16)));
1285                         l += 16;
1286                         break;
1287                     case 3: 
1288                         if (j < 4)
1289                             proto_item_append_text(ti, ": [Unnum-%d", tvb_get_ntohl(tvb, offset2+l));
1290                         proto_item_append_text(ti, ": Unnumbered %d", tvb_get_ntohl(tvb, offset2+l));
1291                         proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 4, 
1292                                             "Interface ID: Unnumbered: %d", 
1293                                             tvb_get_ntohl(tvb, offset2+l));
1294                         l += 4;
1295                         break;
1296                     default:
1297                         proto_tree_add_text(lmp_object_tree, tvb, offset2+l, obj_length-4-l,
1298                                             "Data (%d bytes)", obj_length-4-l);
1299                         l = obj_length - 4;
1300                         break;
1301                     }
1302                     if (l == obj_length - 4) break;
1303
1304                     proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 1, 
1305                                         tvb_get_guint8(tvb, offset2+l) & 0x80 ? 
1306                                         "Link Allocated - Active Monitoring" : 
1307                                         "Link Not Allocated");
1308                     if (j < 4) 
1309                         proto_item_append_text(ti, "-%s,%s], ", 
1310                                                tvb_get_guint8(tvb, offset2+l) & 0x80 ? "Act" : "NA",
1311                                                val_to_str(tvb_get_ntohl(tvb, offset2+l) & 0x7fffffff, 
1312                                                            channel_status_short_str, "UNK (%u)."));
1313                     proto_item_append_text(ti2, ": %s, ", 
1314                                            tvb_get_guint8(tvb, offset2+l) & 0x80 ? "Active" : "Not Active");
1315                     proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 4, 
1316                                         "Channel Status: %s", 
1317                                         val_to_str(tvb_get_ntohl(tvb, offset2+l) & 0x7fffffff, 
1318                                                    channel_status_str, "Unknown (%u). "));
1319                     proto_item_append_text(ti2, val_to_str(tvb_get_ntohl(tvb, offset2+l) & 0x7fffffff, 
1320                                                            channel_status_str, "Unknown (%u). "));
1321                     j++;
1322                     l += 4;
1323                     if (j==4 && l < obj_length - 4)
1324                         proto_item_append_text(ti, " ...");
1325                 }
1326                 break;
1327
1328             case LMP_CLASS_CHANNEL_STATUS_REQUEST:
1329                 for (l=0; l<obj_length - 4; ) {
1330                     switch(type) {
1331                     case 1: 
1332                         proto_tree_add_text(lmp_object_tree, tvb, offset2+l, 4, 
1333                                             "Interface ID: IPv4: %s", 
1334                                             ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
1335                         l += 4;
1336                         break;
1337                     case 2: 
1338                         proto_tree_add_text(lmp_object_tree, tvb, offset2+l, 16, "Interface ID: IPv6: %s", 
1339                                             ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l,16)));
1340                         l += 16;
1341                         break;
1342                     case 3: 
1343                         proto_tree_add_text(lmp_object_tree, tvb, offset2+l, 4, 
1344                                             "Interface ID: Unnumbered: %d", 
1345                                             tvb_get_ntohl(tvb, offset2+l));
1346                         l += 4;
1347                         break;
1348                     default:
1349                         proto_tree_add_text(lmp_object_tree, tvb, offset2+l, obj_length-4-l,
1350                                             "Data (%d bytes)", obj_length-4-l);
1351                         l = obj_length - 4;
1352                         break;
1353                     }
1354                 }
1355                 break;
1356
1357             case LMP_CLASS_ERROR:
1358                 l = tvb_get_ntohl(tvb, offset2);
1359                 ti2 = proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_ERROR], 
1360                                           tvb, offset2, 4, l);
1361
1362                 switch(type) {
1363                 case 1: 
1364                     proto_item_append_text(ti, ": BEGIN_VERIFY_ERROR: %s%s%s%s",
1365                                            (l&0x01) ? "Unsupported-Link " : "",
1366                                            (l&0x02) ? "Unwilling" : "",
1367                                            (l&0x04) ? "Unsupported-Transport" : "",
1368                                            (l&0x08) ? "TE-Link-ID" : "");
1369                     lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_ERROR_FLAGS]);
1370                     proto_tree_add_boolean(lmp_flags_tree, 
1371                                            lmp_filter[LMPF_VAL_ERROR_VERIFY_UNSUPPORTED_LINK], 
1372                                            tvb, offset, 4, l);
1373                     proto_tree_add_boolean(lmp_flags_tree, 
1374                                            lmp_filter[LMPF_VAL_ERROR_VERIFY_UNWILLING], 
1375                                            tvb, offset, 4, l);
1376                     proto_tree_add_boolean(lmp_flags_tree, 
1377                                            lmp_filter[LMPF_VAL_ERROR_VERIFY_TRANSPORT], 
1378                                            tvb, offset, 4, l);
1379                     proto_tree_add_boolean(lmp_flags_tree, 
1380                                            lmp_filter[LMPF_VAL_ERROR_VERIFY_TE_LINK_ID], 
1381                                            tvb, offset, 4, l);
1382                     break;
1383                 case 2: 
1384                     proto_item_append_text(ti, ": LINK_SUMMARY_ERROR: %s%s%s%s%s",
1385                                            (l&0x01) ? "Unacceptable-Params " : "",
1386                                            (l&0x02) ? "Renegotiate" : "",
1387                                            (l&0x04) ? "Remote-Link-ID" : "",
1388                                            (l&0x08) ? "TE-Link" : "",
1389                                            (l&0x10) ? "Data-Link" : "");
1390                     lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_ERROR_FLAGS]);
1391                     proto_tree_add_boolean(lmp_flags_tree, 
1392                                            lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_PARAMETERS], 
1393                                            tvb, offset, 4, l);
1394                     proto_tree_add_boolean(lmp_flags_tree, 
1395                                            lmp_filter[LMPF_VAL_ERROR_SUMMARY_RENEGOTIATE], 
1396                                            tvb, offset, 4, l);
1397                     proto_tree_add_boolean(lmp_flags_tree, 
1398                                            lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_REMOTE_LINK_ID], 
1399                                            tvb, offset, 4, l);
1400                     proto_tree_add_boolean(lmp_flags_tree, 
1401                                            lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_TE_LINK], 
1402                                            tvb, offset, 4, l);
1403                     proto_tree_add_boolean(lmp_flags_tree, 
1404                                            lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_DATA_LINK], 
1405                                            tvb, offset, 4, l);
1406                     break;
1407                 default:
1408                     proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
1409                                         "Data (%d bytes)", mylen);
1410                     break;
1411                 }
1412                 break;
1413                     
1414             default :
1415             default_class:
1416                 proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
1417                                     "Data (%d bytes)", mylen);
1418                 break;
1419
1420             }  
1421
1422             offset += obj_length;
1423             len += obj_length;
1424         }
1425     }
1426 }
1427
1428 void
1429 proto_register_lmp(void)
1430 {    
1431     static gint *ett[NUM_LMP_SUBTREES];
1432     int i;
1433     
1434     for (i=0; i<NUM_LMP_SUBTREES; i++) {
1435         lmp_subtree[i] = -1;
1436         ett[i] = &lmp_subtree[i];
1437     }
1438
1439     proto_lmp = proto_register_protocol("Link Management Protocol (LMP)",
1440                                             "LMP", "lmp");
1441     proto_register_field_array(proto_lmp, lmpf_info, array_length(lmpf_info));
1442     proto_register_subtree_array(ett, array_length(ett));
1443 }
1444
1445 void
1446 proto_reg_handoff_lmp(void)
1447 {
1448         dissector_handle_t lmp_handle;
1449
1450         lmp_handle = create_dissector_handle(dissect_lmp, proto_lmp);
1451         dissector_add("ip.proto", IP_PROTO_LMP, lmp_handle);
1452 }