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