Home | History | Annotate | Download | only in tcpdump
      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 (at) gredler.at)
     14  * Support for LMP service discovery extensions (defined by OIF UNI 1.0)
     15  * added by Manu Pathak (mapathak (at) 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 
     46 struct 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 
     57 static const struct tok lmp_header_flag_values[] = {
     58     { 0x01, "Control Channel Down"},
     59     { 0x02, "LMP restart"},
     60     { 0, NULL}
     61 };
     62 
     63 static const struct tok lmp_obj_te_link_flag_values[] = {
     64     { 0x01, "Fault Management Supported"},
     65     { 0x02, "Link Verification Supported"},
     66     { 0, NULL}
     67 };
     68 
     69 static 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 
     76 static 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 
     83 static const struct tok lmp_obj_begin_verify_flag_values[] = {
     84     { 0x0001, "Verify all links"},
     85     { 0x0002, "Data link type"},
     86     { 0, NULL}
     87 };
     88 
     89 static 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 
     98 static 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 */
    109 static 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 */
    116 static 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 */
    124 static 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 */
    130 static 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 */
    137 static 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 */
    143 static 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 
    175 static 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 
    216 struct 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 
    240 static 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 
    264 static 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 
    312 static 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 
    357 static int
    358 lmp_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 
    424 void
    425 lmp_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;
   1131 trunc:
   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