1/*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that: (1) source code
4 * distributions retain the above copyright notice and this paragraph
5 * in its entirety, and (2) distributions including binary code include
6 * the above copyright notice and this paragraph in its entirety in
7 * the documentation or other materials provided with the distribution.
8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11 * FOR A PARTICULAR PURPOSE.
12 *
13 * Original code by Hannes Gredler (hannes@gredler.at)
14 * Support for LMP service discovery extensions (defined by OIF UNI 1.0)
15 * added by Manu Pathak (mapathak@cisco.com), May 2005
16 */
17
18/* \summary: Link Management Protocol (LMP) printer */
19
20/* specification: RFC 4204 */
21/* OIF UNI 1.0: https://web.archive.org/web/20160401194747/http://www.oiforum.com/public/documents/OIF-UNI-01.0.pdf */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include "netdissect-stdinc.h"
28
29#define ND_LONGJMP_FROM_TCHECK
30#include "netdissect.h"
31#include "extract.h"
32#include "addrtoname.h"
33#include "gmpls.h"
34
35
36/*
37 * LMP common header
38 *
39 *  0                   1                   2                   3
40 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 * | Vers  |      (Reserved)       |    Flags      |    Msg Type   |
43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 * |          LMP Length           |          (Reserved)           |
45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 */
47
48struct lmp_common_header {
49    nd_uint16_t version_res;
50    nd_uint8_t  flags;
51    nd_uint8_t  msg_type;
52    nd_uint16_t length;
53    nd_byte     reserved[2];
54};
55
56#define LMP_VERSION            1
57#define	LMP_EXTRACT_VERSION(x) (((x)&0xf000)>>12)
58
59static const struct tok lmp_header_flag_values[] = {
60    { 0x01, "Control Channel Down"},
61    { 0x02, "LMP restart"},
62    { 0, NULL}
63};
64
65static const struct tok lmp_obj_te_link_flag_values[] = {
66    { 0x01, "Fault Management Supported"},
67    { 0x02, "Link Verification Supported"},
68    { 0, NULL}
69};
70
71static const struct tok lmp_obj_data_link_flag_values[] = {
72    { 0x01, "Data Link Port"},
73    { 0x02, "Allocated for user traffic"},
74    { 0x04, "Failed link"},
75    { 0, NULL}
76};
77
78static const struct tok lmp_obj_channel_status_values[] = {
79    { 1, "Signal Okay"},
80    { 2, "Signal Degraded"},
81    { 3, "Signal Fail"},
82    { 0, NULL}
83};
84
85static const struct tok lmp_obj_begin_verify_flag_values[] = {
86    { 0x0001, "Verify all links"},
87    { 0x0002, "Data link type"},
88    { 0, NULL}
89};
90
91static const struct tok lmp_obj_begin_verify_error_values[] = {
92    { 0x01, "Link Verification Procedure Not supported"},
93    { 0x02, "Unwilling to verify"},
94    { 0x04, "Unsupported verification transport mechanism"},
95    { 0x08, "Link-Id configuration error"},
96    { 0x10, "Unknown object c-type"},
97    { 0, NULL}
98};
99
100static const struct tok lmp_obj_link_summary_error_values[] = {
101    { 0x01, "Unacceptable non-negotiable LINK-SUMMARY parameters"},
102    { 0x02, "Renegotiate LINK-SUMMARY parameters"},
103    { 0x04, "Invalid TE-LINK Object"},
104    { 0x08, "Invalid DATA-LINK Object"},
105    { 0x10, "Unknown TE-LINK Object c-type"},
106    { 0x20, "Unknown DATA-LINK Object c-type"},
107    { 0, NULL}
108};
109
110/* Service Config Supported Protocols Flags */
111static const struct tok lmp_obj_service_config_sp_flag_values[] = {
112    { 0x01, "RSVP Supported"},
113    { 0x02, "LDP Supported"},
114    { 0, NULL}
115};
116
117/* Service Config Client Port Service Attribute Transparency Flags */
118static const struct tok lmp_obj_service_config_cpsa_tp_flag_values[] = {
119    { 0x01, "Path/VC Overhead Transparency Supported"},
120    { 0x02, "Line/MS Overhead Transparency Supported"},
121    { 0x04, "Section/RS Overhead Transparency Supported"},
122    { 0, NULL}
123};
124
125/* Service Config Client Port Service Attribute Contiguous Concatenation Types Flags */
126static const struct tok lmp_obj_service_config_cpsa_cct_flag_values[] = {
127    { 0x01, "Contiguous Concatenation Types Supported"},
128    { 0, NULL}
129};
130
131/* Service Config Network Service Attributes Transparency Flags */
132static const struct tok lmp_obj_service_config_nsa_transparency_flag_values[] = {
133    { 0x01, "Standard SOH/RSOH Transparency Supported"},
134    { 0x02, "Standard LOH/MSOH Transparency Supported"},
135    { 0, NULL}
136};
137
138/* Service Config Network Service Attributes TCM Monitoring Flags */
139static const struct tok lmp_obj_service_config_nsa_tcm_flag_values[] = {
140    { 0x01, "Transparent Tandem Connection Monitoring Supported"},
141    { 0, NULL}
142};
143
144/* Network Service Attributes Network Diversity Flags */
145static const struct tok lmp_obj_service_config_nsa_network_diversity_flag_values[] = {
146    { 0x01, "Node Diversity Supported"},
147    { 0x02, "Link Diversity Supported"},
148    { 0x04, "SRLG Diversity Supported"},
149    { 0, NULL}
150};
151
152#define	LMP_MSGTYPE_CONFIG                 1
153#define	LMP_MSGTYPE_CONFIG_ACK             2
154#define	LMP_MSGTYPE_CONFIG_NACK            3
155#define	LMP_MSGTYPE_HELLO                  4
156#define	LMP_MSGTYPE_VERIFY_BEGIN           5
157#define	LMP_MSGTYPE_VERIFY_BEGIN_ACK       6
158#define	LMP_MSGTYPE_VERIFY_BEGIN_NACK      7
159#define LMP_MSGTYPE_VERIFY_END             8
160#define LMP_MSGTYPE_VERIFY_END_ACK         9
161#define LMP_MSGTYPE_TEST                  10
162#define LMP_MSGTYPE_TEST_STATUS_SUCCESS   11
163#define	LMP_MSGTYPE_TEST_STATUS_FAILURE   12
164#define	LMP_MSGTYPE_TEST_STATUS_ACK       13
165#define	LMP_MSGTYPE_LINK_SUMMARY          14
166#define	LMP_MSGTYPE_LINK_SUMMARY_ACK      15
167#define	LMP_MSGTYPE_LINK_SUMMARY_NACK     16
168#define	LMP_MSGTYPE_CHANNEL_STATUS        17
169#define	LMP_MSGTYPE_CHANNEL_STATUS_ACK    18
170#define	LMP_MSGTYPE_CHANNEL_STATUS_REQ    19
171#define	LMP_MSGTYPE_CHANNEL_STATUS_RESP   20
172/* LMP Service Discovery message types defined by UNI 1.0 */
173#define LMP_MSGTYPE_SERVICE_CONFIG        50
174#define LMP_MSGTYPE_SERVICE_CONFIG_ACK    51
175#define LMP_MSGTYPE_SERVICE_CONFIG_NACK   52
176
177static const struct tok lmp_msg_type_values[] = {
178    { LMP_MSGTYPE_CONFIG, "Config"},
179    { LMP_MSGTYPE_CONFIG_ACK, "Config ACK"},
180    { LMP_MSGTYPE_CONFIG_NACK, "Config NACK"},
181    { LMP_MSGTYPE_HELLO, "Hello"},
182    { LMP_MSGTYPE_VERIFY_BEGIN, "Begin Verify"},
183    { LMP_MSGTYPE_VERIFY_BEGIN_ACK, "Begin Verify ACK"},
184    { LMP_MSGTYPE_VERIFY_BEGIN_NACK, "Begin Verify NACK"},
185    { LMP_MSGTYPE_VERIFY_END, "End Verify"},
186    { LMP_MSGTYPE_VERIFY_END_ACK, "End Verify ACK"},
187    { LMP_MSGTYPE_TEST, "Test"},
188    { LMP_MSGTYPE_TEST_STATUS_SUCCESS, "Test Status Success"},
189    { LMP_MSGTYPE_TEST_STATUS_FAILURE, "Test Status Failure"},
190    { LMP_MSGTYPE_TEST_STATUS_ACK, "Test Status ACK"},
191    { LMP_MSGTYPE_LINK_SUMMARY, "Link Summary"},
192    { LMP_MSGTYPE_LINK_SUMMARY_ACK, "Link Summary ACK"},
193    { LMP_MSGTYPE_LINK_SUMMARY_NACK, "Link Summary NACK"},
194    { LMP_MSGTYPE_CHANNEL_STATUS, "Channel Status"},
195    { LMP_MSGTYPE_CHANNEL_STATUS_ACK, "Channel Status ACK"},
196    { LMP_MSGTYPE_CHANNEL_STATUS_REQ, "Channel Status Request"},
197    { LMP_MSGTYPE_CHANNEL_STATUS_RESP, "Channel Status Response"},
198    { LMP_MSGTYPE_SERVICE_CONFIG, "Service Config"},
199    { LMP_MSGTYPE_SERVICE_CONFIG_ACK, "Service Config ACK"},
200    { LMP_MSGTYPE_SERVICE_CONFIG_NACK, "Service Config NACK"},
201    { 0, NULL}
202};
203
204/*
205 * LMP object header
206 *
207 *  0                   1                   2                   3
208 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
209 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210 * |N|   C-Type    |     Class     |            Length             |
211 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
212 * |                                                               |
213 * //                       (object contents)                     //
214 * |                                                               |
215 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
216 */
217
218struct lmp_object_header {
219    nd_uint8_t  ctype;
220    nd_uint8_t  class_num;
221    nd_uint16_t length;
222};
223
224#define	LMP_OBJ_CC_ID                 1
225#define	LMP_OBJ_NODE_ID               2
226#define	LMP_OBJ_LINK_ID               3
227#define	LMP_OBJ_INTERFACE_ID          4
228#define	LMP_OBJ_MESSAGE_ID            5
229#define	LMP_OBJ_CONFIG                6
230#define	LMP_OBJ_HELLO                 7
231#define	LMP_OBJ_VERIFY_BEGIN          8
232#define LMP_OBJ_VERIFY_BEGIN_ACK      9
233#define LMP_OBJ_VERIFY_ID            10
234#define LMP_OBJ_TE_LINK              11
235#define LMP_OBJ_DATA_LINK            12
236#define LMP_OBJ_CHANNEL_STATUS       13
237#define LMP_OBJ_CHANNEL_STATUS_REQ   14
238#define LMP_OBJ_ERROR_CODE           20
239
240#define LMP_OBJ_SERVICE_CONFIG       51 /* defined in UNI 1.0 */
241
242static const struct tok lmp_obj_values[] = {
243    { LMP_OBJ_CC_ID, "Control Channel ID" },
244    { LMP_OBJ_NODE_ID, "Node ID" },
245    { LMP_OBJ_LINK_ID, "Link ID" },
246    { LMP_OBJ_INTERFACE_ID, "Interface ID" },
247    { LMP_OBJ_MESSAGE_ID, "Message ID" },
248    { LMP_OBJ_CONFIG, "Configuration" },
249    { LMP_OBJ_HELLO, "Hello" },
250    { LMP_OBJ_VERIFY_BEGIN, "Verify Begin" },
251    { LMP_OBJ_VERIFY_BEGIN_ACK, "Verify Begin ACK" },
252    { LMP_OBJ_VERIFY_ID, "Verify ID" },
253    { LMP_OBJ_TE_LINK, "TE Link" },
254    { LMP_OBJ_DATA_LINK, "Data Link" },
255    { LMP_OBJ_CHANNEL_STATUS, "Channel Status" },
256    { LMP_OBJ_CHANNEL_STATUS_REQ, "Channel Status Request" },
257    { LMP_OBJ_ERROR_CODE, "Error Code" },
258    { LMP_OBJ_SERVICE_CONFIG, "Service Config" },
259
260    { 0, NULL}
261};
262
263#define INT_SWITCHING_TYPE_SUBOBJ 1
264#define WAVELENGTH_SUBOBJ         2
265
266static const struct tok lmp_data_link_subobj[] = {
267    { INT_SWITCHING_TYPE_SUBOBJ, "Interface Switching Type" },
268    { WAVELENGTH_SUBOBJ        , "Wavelength" },
269    { 0, NULL}
270};
271
272#define	LMP_CTYPE_IPV4       1
273#define	LMP_CTYPE_IPV6       2
274
275#define	LMP_CTYPE_LOC        1
276#define	LMP_CTYPE_RMT        2
277#define	LMP_CTYPE_UNMD       3
278
279#define	LMP_CTYPE_IPV4_LOC   1
280#define	LMP_CTYPE_IPV4_RMT   2
281#define	LMP_CTYPE_IPV6_LOC   3
282#define	LMP_CTYPE_IPV6_RMT   4
283#define	LMP_CTYPE_UNMD_LOC   5
284#define	LMP_CTYPE_UNMD_RMT   6
285
286#define	LMP_CTYPE_1          1
287#define	LMP_CTYPE_2          2
288
289#define LMP_CTYPE_HELLO_CONFIG  1
290#define LMP_CTYPE_HELLO         1
291
292#define LMP_CTYPE_BEGIN_VERIFY_ERROR 1
293#define LMP_CTYPE_LINK_SUMMARY_ERROR 2
294
295/* C-Types for Service Config Object */
296#define LMP_CTYPE_SERVICE_CONFIG_SP                   1
297#define LMP_CTYPE_SERVICE_CONFIG_CPSA                 2
298#define LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM     3
299#define LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY    4
300
301/*
302 * Different link types allowed in the Client Port Service Attributes
303 * subobject defined for LMP Service Discovery in the UNI 1.0 spec
304 */
305#define LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH     5 /* UNI 1.0 Sec 9.4.2 */
306#define LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET   6 /* UNI 1.0 Sec 9.4.2 */
307
308/*
309 * the ctypes are not globally unique so for
310 * translating it to strings we build a table based
311 * on objects offsetted by the ctype
312 */
313
314static const struct tok lmp_ctype_values[] = {
315    { 256*LMP_OBJ_CC_ID+LMP_CTYPE_LOC, "Local" },
316    { 256*LMP_OBJ_CC_ID+LMP_CTYPE_RMT, "Remote" },
317    { 256*LMP_OBJ_NODE_ID+LMP_CTYPE_LOC, "Local" },
318    { 256*LMP_OBJ_NODE_ID+LMP_CTYPE_RMT, "Remote" },
319    { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV4_LOC, "IPv4 Local" },
320    { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV4_RMT, "IPv4 Remote" },
321    { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV6_LOC, "IPv6 Local" },
322    { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV6_RMT, "IPv6 Remote" },
323    { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_UNMD_LOC, "Unnumbered Local" },
324    { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_UNMD_RMT, "Unnumbered Remote" },
325    { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV4_LOC, "IPv4 Local" },
326    { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV4_RMT, "IPv4 Remote" },
327    { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV6_LOC, "IPv6 Local" },
328    { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV6_RMT, "IPv6 Remote" },
329    { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_UNMD_LOC, "Unnumbered Local" },
330    { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_UNMD_RMT, "Unnumbered Remote" },
331    { 256*LMP_OBJ_MESSAGE_ID+LMP_CTYPE_1, "1" },
332    { 256*LMP_OBJ_MESSAGE_ID+LMP_CTYPE_2, "2" },
333    { 256*LMP_OBJ_CONFIG+LMP_CTYPE_1, "1" },
334    { 256*LMP_OBJ_HELLO+LMP_CTYPE_1, "1" },
335    { 256*LMP_OBJ_VERIFY_BEGIN+LMP_CTYPE_1, "1" },
336    { 256*LMP_OBJ_VERIFY_BEGIN_ACK+LMP_CTYPE_1, "1" },
337    { 256*LMP_OBJ_VERIFY_ID+LMP_CTYPE_1, "1" },
338    { 256*LMP_OBJ_TE_LINK+LMP_CTYPE_IPV4, "IPv4" },
339    { 256*LMP_OBJ_TE_LINK+LMP_CTYPE_IPV6, "IPv6" },
340    { 256*LMP_OBJ_TE_LINK+LMP_CTYPE_UNMD, "Unnumbered" },
341    { 256*LMP_OBJ_DATA_LINK+LMP_CTYPE_IPV4, "IPv4" },
342    { 256*LMP_OBJ_DATA_LINK+LMP_CTYPE_IPV6, "IPv6" },
343    { 256*LMP_OBJ_DATA_LINK+LMP_CTYPE_UNMD, "Unnumbered" },
344    { 256*LMP_OBJ_CHANNEL_STATUS+LMP_CTYPE_IPV4, "IPv4" },
345    { 256*LMP_OBJ_CHANNEL_STATUS+LMP_CTYPE_IPV6, "IPv6" },
346    { 256*LMP_OBJ_CHANNEL_STATUS+LMP_CTYPE_UNMD, "Unnumbered" },
347    { 256*LMP_OBJ_CHANNEL_STATUS_REQ+LMP_CTYPE_IPV4, "IPv4" },
348    { 256*LMP_OBJ_CHANNEL_STATUS_REQ+LMP_CTYPE_IPV6, "IPv6" },
349    { 256*LMP_OBJ_CHANNEL_STATUS_REQ+LMP_CTYPE_UNMD, "Unnumbered" },
350    { 256*LMP_OBJ_ERROR_CODE+LMP_CTYPE_1, "1" },
351    { 256*LMP_OBJ_ERROR_CODE+LMP_CTYPE_2, "2" },
352    { 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_SP, "1" },
353    { 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_CPSA, "2" },
354    { 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM, "3" },
355    { 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY, "4" },
356    { 0, NULL}
357};
358
359static int
360lmp_print_data_link_subobjs(netdissect_options *ndo, const u_char *obj_tptr,
361                            int total_subobj_len, int offset)
362{
363    int hexdump = FALSE;
364    int subobj_type, subobj_len;
365
366    union { /* int to float conversion buffer */
367        float f;
368        uint32_t i;
369    } bw;
370
371    while (total_subobj_len > 0 && hexdump == FALSE ) {
372	subobj_type = GET_U_1(obj_tptr + offset);
373	subobj_len  = GET_U_1(obj_tptr + offset + 1);
374	ND_PRINT("\n\t    Subobject, Type: %s (%u), Length: %u",
375		tok2str(lmp_data_link_subobj,
376			"Unknown",
377			subobj_type),
378			subobj_type,
379			subobj_len);
380	if (subobj_len < 4) {
381	    ND_PRINT(" (too short)");
382	    break;
383	}
384	if ((subobj_len % 4) != 0) {
385	    ND_PRINT(" (not a multiple of 4)");
386	    break;
387	}
388	if (total_subobj_len < subobj_len) {
389	    ND_PRINT(" (goes past the end of the object)");
390	    break;
391	}
392	switch(subobj_type) {
393	case INT_SWITCHING_TYPE_SUBOBJ:
394	    ND_PRINT("\n\t      Switching Type: %s (%u)",
395		tok2str(gmpls_switch_cap_values,
396			"Unknown",
397			GET_U_1(obj_tptr + offset + 2)),
398		GET_U_1(obj_tptr + offset + 2));
399	    ND_PRINT("\n\t      Encoding Type: %s (%u)",
400		tok2str(gmpls_encoding_values,
401			"Unknown",
402			GET_U_1(obj_tptr + offset + 3)),
403		GET_U_1(obj_tptr + offset + 3));
404	    bw.i = GET_BE_U_4(obj_tptr + offset + 4);
405	    ND_PRINT("\n\t      Min Reservable Bandwidth: %.3f Mbps",
406                bw.f*8/1000000);
407	    bw.i = GET_BE_U_4(obj_tptr + offset + 8);
408	    ND_PRINT("\n\t      Max Reservable Bandwidth: %.3f Mbps",
409                bw.f*8/1000000);
410	    break;
411	case WAVELENGTH_SUBOBJ:
412	    ND_PRINT("\n\t      Wavelength: %u",
413		GET_BE_U_4(obj_tptr + offset + 4));
414	    break;
415	default:
416	    /* Any Unknown Subobject ==> Exit loop */
417	    hexdump=TRUE;
418	    break;
419	}
420	total_subobj_len-=subobj_len;
421	offset+=subobj_len;
422    }
423    return (hexdump);
424}
425
426void
427lmp_print(netdissect_options *ndo,
428          const u_char *pptr, u_int length)
429{
430    const struct lmp_common_header *lmp_com_header;
431    const u_char *tptr,*obj_tptr;
432    u_int version_res, tlen, lmp_obj_len, lmp_obj_ctype, obj_tlen;
433    int hexdump;
434    u_int offset;
435    u_int link_type;
436
437    union { /* int to float conversion buffer */
438        float f;
439        uint32_t i;
440    } bw;
441
442    ndo->ndo_protocol = "lmp";
443    tptr=pptr;
444    lmp_com_header = (const struct lmp_common_header *)pptr;
445    ND_TCHECK_SIZE(lmp_com_header);
446
447    version_res = GET_BE_U_2(lmp_com_header->version_res);
448
449    /*
450     * Sanity checking of the header.
451     */
452    if (LMP_EXTRACT_VERSION(version_res) != LMP_VERSION) {
453	ND_PRINT("LMP version %u packet not supported",
454               LMP_EXTRACT_VERSION(version_res));
455	return;
456    }
457
458    /* in non-verbose mode just lets print the basic Message Type*/
459    if (ndo->ndo_vflag < 1) {
460        ND_PRINT("LMPv%u %s Message, length: %u",
461               LMP_EXTRACT_VERSION(version_res),
462               tok2str(lmp_msg_type_values, "unknown (%u)",GET_U_1(lmp_com_header->msg_type)),
463               length);
464        return;
465    }
466
467    /* ok they seem to want to know everything - lets fully decode it */
468
469    tlen=GET_BE_U_2(lmp_com_header->length);
470
471    ND_PRINT("\n\tLMPv%u, msg-type: %s, Flags: [%s], length: %u",
472           LMP_EXTRACT_VERSION(version_res),
473           tok2str(lmp_msg_type_values, "unknown, type: %u",GET_U_1(lmp_com_header->msg_type)),
474           bittok2str(lmp_header_flag_values,"none",GET_U_1(lmp_com_header->flags)),
475           tlen);
476    if (tlen < sizeof(struct lmp_common_header)) {
477        ND_PRINT(" (too short)");
478        return;
479    }
480    if (tlen > length) {
481        ND_PRINT(" (too long)");
482        tlen = length;
483    }
484
485    tptr+=sizeof(struct lmp_common_header);
486    tlen-=sizeof(struct lmp_common_header);
487
488    while(tlen>0) {
489        const struct lmp_object_header *lmp_obj_header =
490            (const struct lmp_object_header *)tptr;
491        lmp_obj_len=GET_BE_U_2(lmp_obj_header->length);
492        lmp_obj_ctype=GET_U_1(lmp_obj_header->ctype)&0x7f;
493
494        ND_PRINT("\n\t  %s Object (%u), Class-Type: %s (%u) Flags: [%snegotiable], length: %u",
495               tok2str(lmp_obj_values,
496                       "Unknown",
497                       GET_U_1(lmp_obj_header->class_num)),
498               GET_U_1(lmp_obj_header->class_num),
499               tok2str(lmp_ctype_values,
500                       "Unknown",
501                       (GET_U_1(lmp_obj_header->class_num)<<8)+lmp_obj_ctype),
502               lmp_obj_ctype,
503               GET_U_1(lmp_obj_header->ctype)&0x80 ? "" : "non-",
504               lmp_obj_len);
505
506        if (lmp_obj_len < 4) {
507            ND_PRINT(" (too short)");
508            return;
509        }
510        if ((lmp_obj_len % 4) != 0) {
511            ND_PRINT(" (not a multiple of 4)");
512            return;
513        }
514
515        obj_tptr=tptr+sizeof(struct lmp_object_header);
516        obj_tlen=lmp_obj_len-sizeof(struct lmp_object_header);
517
518        /* did we capture enough for fully decoding the object ? */
519        ND_TCHECK_LEN(tptr, lmp_obj_len);
520        hexdump=FALSE;
521
522        switch(GET_U_1(lmp_obj_header->class_num)) {
523
524        case LMP_OBJ_CC_ID:
525            switch(lmp_obj_ctype) {
526            case LMP_CTYPE_LOC:
527            case LMP_CTYPE_RMT:
528                if (obj_tlen != 4) {
529                    ND_PRINT(" (not correct for object)");
530                    break;
531                }
532                ND_PRINT("\n\t    Control Channel ID: %u (0x%08x)",
533                       GET_BE_U_4(obj_tptr),
534                       GET_BE_U_4(obj_tptr));
535                break;
536
537            default:
538                hexdump=TRUE;
539            }
540            break;
541
542        case LMP_OBJ_LINK_ID:
543        case LMP_OBJ_INTERFACE_ID:
544            switch(lmp_obj_ctype) {
545            case LMP_CTYPE_IPV4_LOC:
546            case LMP_CTYPE_IPV4_RMT:
547                if (obj_tlen != 4) {
548                    ND_PRINT(" (not correct for object)");
549                    break;
550                }
551                ND_PRINT("\n\t    IPv4 Link ID: %s (0x%08x)",
552                       GET_IPADDR_STRING(obj_tptr),
553                       GET_BE_U_4(obj_tptr));
554                break;
555            case LMP_CTYPE_IPV6_LOC:
556            case LMP_CTYPE_IPV6_RMT:
557                if (obj_tlen != 16) {
558                    ND_PRINT(" (not correct for object)");
559                    break;
560                }
561                ND_PRINT("\n\t    IPv6 Link ID: %s (0x%08x)",
562                       GET_IP6ADDR_STRING(obj_tptr),
563                       GET_BE_U_4(obj_tptr));
564                break;
565            case LMP_CTYPE_UNMD_LOC:
566            case LMP_CTYPE_UNMD_RMT:
567                if (obj_tlen != 4) {
568                    ND_PRINT(" (not correct for object)");
569                    break;
570                }
571                ND_PRINT("\n\t    Link ID: %u (0x%08x)",
572                       GET_BE_U_4(obj_tptr),
573                       GET_BE_U_4(obj_tptr));
574                break;
575            default:
576                hexdump=TRUE;
577            }
578            break;
579
580        case LMP_OBJ_MESSAGE_ID:
581            switch(lmp_obj_ctype) {
582            case LMP_CTYPE_1:
583                if (obj_tlen != 4) {
584                    ND_PRINT(" (not correct for object)");
585                    break;
586                }
587                ND_PRINT("\n\t    Message ID: %u (0x%08x)",
588                       GET_BE_U_4(obj_tptr),
589                       GET_BE_U_4(obj_tptr));
590                break;
591            case LMP_CTYPE_2:
592                if (obj_tlen != 4) {
593                    ND_PRINT(" (not correct for object)");
594                    break;
595                }
596                ND_PRINT("\n\t    Message ID Ack: %u (0x%08x)",
597                       GET_BE_U_4(obj_tptr),
598                       GET_BE_U_4(obj_tptr));
599                break;
600            default:
601                hexdump=TRUE;
602            }
603            break;
604
605        case LMP_OBJ_NODE_ID:
606            switch(lmp_obj_ctype) {
607            case LMP_CTYPE_LOC:
608            case LMP_CTYPE_RMT:
609                if (obj_tlen != 4) {
610                    ND_PRINT(" (not correct for object)");
611                    break;
612                }
613                ND_PRINT("\n\t    Node ID: %s (0x%08x)",
614                       GET_IPADDR_STRING(obj_tptr),
615                       GET_BE_U_4(obj_tptr));
616                break;
617
618            default:
619                hexdump=TRUE;
620            }
621            break;
622
623        case LMP_OBJ_CONFIG:
624            switch(lmp_obj_ctype) {
625            case LMP_CTYPE_HELLO_CONFIG:
626                if (obj_tlen != 4) {
627                    ND_PRINT(" (not correct for object)");
628                    break;
629                }
630                ND_PRINT("\n\t    Hello Interval: %u\n\t    Hello Dead Interval: %u",
631                       GET_BE_U_2(obj_tptr),
632                       GET_BE_U_2(obj_tptr + 2));
633                break;
634
635            default:
636                hexdump=TRUE;
637            }
638            break;
639
640        case LMP_OBJ_HELLO:
641            switch(lmp_obj_ctype) {
642	    case LMP_CTYPE_HELLO:
643                if (obj_tlen != 8) {
644                    ND_PRINT(" (not correct for object)");
645                    break;
646                }
647                ND_PRINT("\n\t    Tx Seq: %u, Rx Seq: %u",
648                       GET_BE_U_4(obj_tptr),
649                       GET_BE_U_4(obj_tptr + 4));
650                break;
651
652            default:
653                hexdump=TRUE;
654            }
655            break;
656
657        case LMP_OBJ_TE_LINK:
658	    switch(lmp_obj_ctype) {
659	    case LMP_CTYPE_IPV4:
660                if (obj_tlen != 12) {
661                    ND_PRINT(" (not correct for object)");
662                    break;
663                }
664		ND_PRINT("\n\t    Flags: [%s]",
665		    bittok2str(lmp_obj_te_link_flag_values,
666			"none",
667			GET_U_1(obj_tptr)));
668
669		ND_PRINT("\n\t    Local Link-ID: %s (0x%08x)"
670		       "\n\t    Remote Link-ID: %s (0x%08x)",
671                       GET_IPADDR_STRING(obj_tptr+4),
672                       GET_BE_U_4(obj_tptr + 4),
673                       GET_IPADDR_STRING(obj_tptr+8),
674                       GET_BE_U_4(obj_tptr + 8));
675		break;
676
677	    case LMP_CTYPE_IPV6:
678                if (obj_tlen != 36) {
679                    ND_PRINT(" (not correct for object)");
680                    break;
681                }
682		ND_PRINT("\n\t    Flags: [%s]",
683		    bittok2str(lmp_obj_te_link_flag_values,
684			"none",
685			GET_U_1(obj_tptr)));
686
687		ND_PRINT("\n\t    Local Link-ID: %s (0x%08x)"
688		       "\n\t    Remote Link-ID: %s (0x%08x)",
689                       GET_IP6ADDR_STRING(obj_tptr+4),
690                       GET_BE_U_4(obj_tptr + 4),
691                       GET_IP6ADDR_STRING(obj_tptr+20),
692                       GET_BE_U_4(obj_tptr + 20));
693                break;
694
695	    case LMP_CTYPE_UNMD:
696                if (obj_tlen != 12) {
697                    ND_PRINT(" (not correct for object)");
698                    break;
699                }
700		ND_PRINT("\n\t    Flags: [%s]",
701		    bittok2str(lmp_obj_te_link_flag_values,
702			"none",
703			GET_U_1(obj_tptr)));
704
705		ND_PRINT("\n\t    Local Link-ID: %u (0x%08x)"
706		       "\n\t    Remote Link-ID: %u (0x%08x)",
707                       GET_BE_U_4(obj_tptr + 4),
708                       GET_BE_U_4(obj_tptr + 4),
709                       GET_BE_U_4(obj_tptr + 8),
710                       GET_BE_U_4(obj_tptr + 8));
711		break;
712
713            default:
714                hexdump=TRUE;
715            }
716            break;
717
718        case LMP_OBJ_DATA_LINK:
719	    switch(lmp_obj_ctype) {
720	    case LMP_CTYPE_IPV4:
721                if (obj_tlen < 12) {
722                    ND_PRINT(" (not correct for object)");
723                    break;
724                }
725	        ND_PRINT("\n\t    Flags: [%s]",
726		    bittok2str(lmp_obj_data_link_flag_values,
727			"none",
728			GET_U_1(obj_tptr)));
729                ND_PRINT("\n\t    Local Interface ID: %s (0x%08x)"
730                       "\n\t    Remote Interface ID: %s (0x%08x)",
731                       GET_IPADDR_STRING(obj_tptr+4),
732                       GET_BE_U_4(obj_tptr + 4),
733                       GET_IPADDR_STRING(obj_tptr+8),
734                       GET_BE_U_4(obj_tptr + 8));
735
736		if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12))
737		    hexdump=TRUE;
738		break;
739
740	    case LMP_CTYPE_IPV6:
741                if (obj_tlen < 36) {
742                    ND_PRINT(" (not correct for object)");
743                    break;
744                }
745	        ND_PRINT("\n\t    Flags: [%s]",
746		    bittok2str(lmp_obj_data_link_flag_values,
747			"none",
748			GET_U_1(obj_tptr)));
749                ND_PRINT("\n\t    Local Interface ID: %s (0x%08x)"
750                       "\n\t    Remote Interface ID: %s (0x%08x)",
751                       GET_IP6ADDR_STRING(obj_tptr+4),
752                       GET_BE_U_4(obj_tptr + 4),
753                       GET_IP6ADDR_STRING(obj_tptr+20),
754                       GET_BE_U_4(obj_tptr + 20));
755
756		if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 36, 36))
757		    hexdump=TRUE;
758		break;
759
760	    case LMP_CTYPE_UNMD:
761                if (obj_tlen < 12) {
762                    ND_PRINT(" (not correct for object)");
763                    break;
764                }
765	        ND_PRINT("\n\t    Flags: [%s]",
766		    bittok2str(lmp_obj_data_link_flag_values,
767			"none",
768			GET_U_1(obj_tptr)));
769                ND_PRINT("\n\t    Local Interface ID: %u (0x%08x)"
770                       "\n\t    Remote Interface ID: %u (0x%08x)",
771                       GET_BE_U_4(obj_tptr + 4),
772                       GET_BE_U_4(obj_tptr + 4),
773                       GET_BE_U_4(obj_tptr + 8),
774                       GET_BE_U_4(obj_tptr + 8));
775
776		if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12))
777		    hexdump=TRUE;
778		break;
779
780            default:
781                hexdump=TRUE;
782            }
783            break;
784
785        case LMP_OBJ_VERIFY_BEGIN:
786	    switch(lmp_obj_ctype) {
787            case LMP_CTYPE_1:
788                if (obj_tlen != 20) {
789                    ND_PRINT(" (not correct for object)");
790                    break;
791                }
792		ND_PRINT("\n\t    Flags: %s",
793		bittok2str(lmp_obj_begin_verify_flag_values,
794			"none",
795			GET_BE_U_2(obj_tptr)));
796		ND_PRINT("\n\t    Verify Interval: %u",
797			GET_BE_U_2(obj_tptr + 2));
798		ND_PRINT("\n\t    Data links: %u",
799			GET_BE_U_4(obj_tptr + 4));
800                ND_PRINT("\n\t    Encoding type: %s",
801			tok2str(gmpls_encoding_values, "Unknown", GET_U_1((obj_tptr + 8))));
802                ND_PRINT("\n\t    Verify Transport Mechanism: %u (0x%x)%s",
803			GET_BE_U_2(obj_tptr + 10),
804			GET_BE_U_2(obj_tptr + 10),
805			GET_BE_U_2(obj_tptr + 10)&8000 ? " (Payload test messages capable)" : "");
806                bw.i = GET_BE_U_4(obj_tptr + 12);
807		ND_PRINT("\n\t    Transmission Rate: %.3f Mbps",bw.f*8/1000000);
808		ND_PRINT("\n\t    Wavelength: %u",
809			GET_BE_U_4(obj_tptr + 16));
810		break;
811
812            default:
813                hexdump=TRUE;
814            }
815            break;
816
817        case LMP_OBJ_VERIFY_BEGIN_ACK:
818	    switch(lmp_obj_ctype) {
819            case LMP_CTYPE_1:
820                if (obj_tlen != 4) {
821                    ND_PRINT(" (not correct for object)");
822                    break;
823                }
824                ND_PRINT("\n\t    Verify Dead Interval: %u"
825                       "\n\t    Verify Transport Response: %u",
826                       GET_BE_U_2(obj_tptr),
827                       GET_BE_U_2(obj_tptr + 2));
828                break;
829
830            default:
831                hexdump=TRUE;
832            }
833            break;
834
835	case LMP_OBJ_VERIFY_ID:
836	    switch(lmp_obj_ctype) {
837            case LMP_CTYPE_1:
838                if (obj_tlen != 4) {
839                    ND_PRINT(" (not correct for object)");
840                    break;
841                }
842                ND_PRINT("\n\t    Verify ID: %u",
843                       GET_BE_U_4(obj_tptr));
844                break;
845
846            default:
847                hexdump=TRUE;
848            }
849            break;
850
851	case LMP_OBJ_CHANNEL_STATUS:
852            switch(lmp_obj_ctype) {
853	    case LMP_CTYPE_IPV4:
854		offset = 0;
855		/* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */
856		while (offset+8 <= obj_tlen) {
857			ND_PRINT("\n\t    Interface ID: %s (0x%08x)",
858			GET_IPADDR_STRING(obj_tptr+offset),
859			GET_BE_U_4(obj_tptr + offset));
860
861			ND_PRINT("\n\t\t    Active: %s (%u)",
862				(GET_BE_U_4(obj_tptr + offset + 4)>>31) ?
863				"Allocated" : "Non-allocated",
864				(GET_BE_U_4(obj_tptr + offset + 4)>>31));
865
866			ND_PRINT("\n\t\t    Direction: %s (%u)",
867				(GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1 ?
868				"Transmit" : "Receive",
869				(GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1);
870
871			ND_PRINT("\n\t\t    Channel Status: %s (%u)",
872					tok2str(lmp_obj_channel_status_values,
873					"Unknown",
874					GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF),
875					GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF);
876			offset+=8;
877		}
878                break;
879
880	    case LMP_CTYPE_IPV6:
881		offset = 0;
882		/* Decode pairs: <Interface_ID (16 bytes), Channel_status (4 bytes)> */
883		while (offset+20 <= obj_tlen) {
884			ND_PRINT("\n\t    Interface ID: %s (0x%08x)",
885			GET_IP6ADDR_STRING(obj_tptr+offset),
886			GET_BE_U_4(obj_tptr + offset));
887
888			ND_PRINT("\n\t\t    Active: %s (%u)",
889				(GET_BE_U_4(obj_tptr + offset + 16)>>31) ?
890				"Allocated" : "Non-allocated",
891				(GET_BE_U_4(obj_tptr + offset + 16)>>31));
892
893			ND_PRINT("\n\t\t    Direction: %s (%u)",
894				(GET_BE_U_4(obj_tptr + offset + 16)>>30)&0x1 ?
895				"Transmit" : "Receive",
896				(GET_BE_U_4(obj_tptr + offset + 16)>>30)&0x1);
897
898			ND_PRINT("\n\t\t    Channel Status: %s (%u)",
899					tok2str(lmp_obj_channel_status_values,
900					"Unknown",
901					GET_BE_U_4(obj_tptr + offset + 16)&0x3FFFFFF),
902					GET_BE_U_4(obj_tptr + offset + 16)&0x3FFFFFF);
903			offset+=20;
904		}
905                break;
906
907	    case LMP_CTYPE_UNMD:
908		offset = 0;
909		/* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */
910		while (offset+8 <= obj_tlen) {
911			ND_PRINT("\n\t    Interface ID: %u (0x%08x)",
912			GET_BE_U_4(obj_tptr + offset),
913			GET_BE_U_4(obj_tptr + offset));
914
915			ND_PRINT("\n\t\t    Active: %s (%u)",
916				(GET_BE_U_4(obj_tptr + offset + 4)>>31) ?
917				"Allocated" : "Non-allocated",
918				(GET_BE_U_4(obj_tptr + offset + 4)>>31));
919
920			ND_PRINT("\n\t\t    Direction: %s (%u)",
921				(GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1 ?
922				"Transmit" : "Receive",
923				(GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1);
924
925			ND_PRINT("\n\t\t    Channel Status: %s (%u)",
926					tok2str(lmp_obj_channel_status_values,
927					"Unknown",
928					GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF),
929					GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF);
930			offset+=8;
931		}
932                break;
933
934            default:
935                hexdump=TRUE;
936            }
937            break;
938
939	case LMP_OBJ_CHANNEL_STATUS_REQ:
940            switch(lmp_obj_ctype) {
941	    case LMP_CTYPE_IPV4:
942		offset = 0;
943		while (offset+4 <= obj_tlen) {
944			ND_PRINT("\n\t    Interface ID: %s (0x%08x)",
945			GET_IPADDR_STRING(obj_tptr+offset),
946			GET_BE_U_4(obj_tptr + offset));
947			offset+=4;
948		}
949                break;
950
951	    case LMP_CTYPE_IPV6:
952		offset = 0;
953		while (offset+16 <= obj_tlen) {
954			ND_PRINT("\n\t    Interface ID: %s (0x%08x)",
955			GET_IP6ADDR_STRING(obj_tptr+offset),
956			GET_BE_U_4(obj_tptr + offset));
957			offset+=16;
958		}
959                break;
960
961	    case LMP_CTYPE_UNMD:
962		offset = 0;
963		while (offset+4 <= obj_tlen) {
964			ND_PRINT("\n\t    Interface ID: %u (0x%08x)",
965			GET_BE_U_4(obj_tptr + offset),
966			GET_BE_U_4(obj_tptr + offset));
967			offset+=4;
968		}
969                break;
970
971	    default:
972                hexdump=TRUE;
973            }
974            break;
975
976        case LMP_OBJ_ERROR_CODE:
977	    switch(lmp_obj_ctype) {
978            case LMP_CTYPE_BEGIN_VERIFY_ERROR:
979                if (obj_tlen != 4) {
980                    ND_PRINT(" (not correct for object)");
981                    break;
982                }
983		ND_PRINT("\n\t    Error Code: %s",
984		bittok2str(lmp_obj_begin_verify_error_values,
985			"none",
986			GET_BE_U_4(obj_tptr)));
987                break;
988
989            case LMP_CTYPE_LINK_SUMMARY_ERROR:
990                if (obj_tlen != 4) {
991                    ND_PRINT(" (not correct for object)");
992                    break;
993                }
994		ND_PRINT("\n\t    Error Code: %s",
995		bittok2str(lmp_obj_link_summary_error_values,
996			"none",
997			GET_BE_U_4(obj_tptr)));
998                break;
999            default:
1000                hexdump=TRUE;
1001            }
1002            break;
1003
1004	case LMP_OBJ_SERVICE_CONFIG:
1005	    switch (lmp_obj_ctype) {
1006	    case LMP_CTYPE_SERVICE_CONFIG_SP:
1007                if (obj_tlen != 4) {
1008                    ND_PRINT(" (not correct for object)");
1009                    break;
1010                }
1011		ND_PRINT("\n\t Flags: %s",
1012		       bittok2str(lmp_obj_service_config_sp_flag_values,
1013				  "none",
1014				  GET_U_1(obj_tptr)));
1015
1016		ND_PRINT("\n\t  UNI Version: %u",
1017		       GET_U_1(obj_tptr + 1));
1018
1019		break;
1020
1021            case LMP_CTYPE_SERVICE_CONFIG_CPSA:
1022                if (obj_tlen != 16) {
1023                    ND_PRINT(" (not correct for object)");
1024                    break;
1025                }
1026
1027		link_type = GET_U_1(obj_tptr);
1028
1029		ND_PRINT("\n\t Link Type: %s (%u)",
1030		       tok2str(lmp_sd_service_config_cpsa_link_type_values,
1031			       "Unknown", link_type),
1032		       link_type);
1033
1034		switch (link_type) {
1035		case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH:
1036		    ND_PRINT("\n\t Signal Type: %s (%u)",
1037			   tok2str(lmp_sd_service_config_cpsa_signal_type_sdh_values,
1038				   "Unknown",
1039				   GET_U_1(obj_tptr + 1)),
1040			   GET_U_1(obj_tptr + 1));
1041		    break;
1042
1043		case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET:
1044		    ND_PRINT("\n\t Signal Type: %s (%u)",
1045			   tok2str(lmp_sd_service_config_cpsa_signal_type_sonet_values,
1046				   "Unknown",
1047				   GET_U_1(obj_tptr + 1)),
1048			   GET_U_1(obj_tptr + 1));
1049		    break;
1050		}
1051
1052		ND_PRINT("\n\t Transparency: %s",
1053		       bittok2str(lmp_obj_service_config_cpsa_tp_flag_values,
1054				  "none",
1055				  GET_U_1(obj_tptr + 2)));
1056
1057		ND_PRINT("\n\t Contiguous Concatenation Types: %s",
1058		       bittok2str(lmp_obj_service_config_cpsa_cct_flag_values,
1059				  "none",
1060				  GET_U_1(obj_tptr + 3)));
1061
1062		ND_PRINT("\n\t Minimum NCC: %u",
1063		       GET_BE_U_2(obj_tptr + 4));
1064
1065		ND_PRINT("\n\t Maximum NCC: %u",
1066		       GET_BE_U_2(obj_tptr + 6));
1067
1068		ND_PRINT("\n\t Minimum NVC:%u",
1069		       GET_BE_U_2(obj_tptr + 8));
1070
1071		ND_PRINT("\n\t Maximum NVC:%u",
1072		       GET_BE_U_2(obj_tptr + 10));
1073
1074		ND_PRINT("\n\t    Local Interface ID: %s (0x%08x)",
1075		       GET_IPADDR_STRING(obj_tptr+12),
1076		       GET_BE_U_4(obj_tptr + 12));
1077
1078		break;
1079
1080	    case LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM:
1081                if (obj_tlen != 8) {
1082                    ND_PRINT(" (not correct for object)");
1083                    break;
1084                }
1085
1086		ND_PRINT("\n\t Transparency Flags: %s",
1087		       bittok2str(
1088			   lmp_obj_service_config_nsa_transparency_flag_values,
1089			   "none",
1090			   GET_BE_U_4(obj_tptr)));
1091
1092		ND_PRINT("\n\t TCM Monitoring Flags: %s",
1093		       bittok2str(
1094			   lmp_obj_service_config_nsa_tcm_flag_values,
1095			   "none",
1096			   GET_U_1(obj_tptr + 7)));
1097
1098		break;
1099
1100	    case LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY:
1101                if (obj_tlen != 4) {
1102                    ND_PRINT(" (not correct for object)");
1103                    break;
1104                }
1105
1106		ND_PRINT("\n\t Diversity: Flags: %s",
1107		       bittok2str(
1108			   lmp_obj_service_config_nsa_network_diversity_flag_values,
1109			   "none",
1110			   GET_U_1(obj_tptr + 3)));
1111		break;
1112
1113	    default:
1114		hexdump = TRUE;
1115	    }
1116
1117	break;
1118
1119        default:
1120            if (ndo->ndo_vflag <= 1)
1121                print_unknown_data(ndo,obj_tptr,"\n\t    ",obj_tlen);
1122            break;
1123        }
1124        /* do we want to see an additionally hexdump ? */
1125        if (ndo->ndo_vflag > 1 || hexdump==TRUE)
1126            print_unknown_data(ndo,tptr+sizeof(struct lmp_object_header),"\n\t    ",
1127                               lmp_obj_len-sizeof(struct lmp_object_header));
1128
1129        if (tlen < lmp_obj_len) {
1130            ND_PRINT(" [remaining objects length %u < %u]", tlen, lmp_obj_len);
1131            nd_print_invalid(ndo);
1132            break;
1133        }
1134        tptr+=lmp_obj_len;
1135        tlen-=lmp_obj_len;
1136    }
1137}
1138