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