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