xref: /freebsd/contrib/tcpdump/print-ldp.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
15b0fe478SBruce M Simpson /*
25b0fe478SBruce M Simpson  * Redistribution and use in source and binary forms, with or without
35b0fe478SBruce M Simpson  * modification, are permitted provided that: (1) source code
45b0fe478SBruce M Simpson  * distributions retain the above copyright notice and this paragraph
55b0fe478SBruce M Simpson  * in its entirety, and (2) distributions including binary code include
65b0fe478SBruce M Simpson  * the above copyright notice and this paragraph in its entirety in
75b0fe478SBruce M Simpson  * the documentation or other materials provided with the distribution.
85b0fe478SBruce M Simpson  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
95b0fe478SBruce M Simpson  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
105b0fe478SBruce M Simpson  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
115b0fe478SBruce M Simpson  * FOR A PARTICULAR PURPOSE.
125b0fe478SBruce M Simpson  *
130bff6a5aSEd Maste  * Original code by Hannes Gredler (hannes@gredler.at)
141de50e9fSSam Leffler  *  and Steinar Haug (sthaug@nethelp.no)
155b0fe478SBruce M Simpson  */
165b0fe478SBruce M Simpson 
173340d773SGleb Smirnoff /* \summary: Label Distribution Protocol (LDP) printer */
183340d773SGleb Smirnoff 
19ee67461eSJoseph Mingrone #include <config.h>
205b0fe478SBruce M Simpson 
21ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
225b0fe478SBruce M Simpson 
233340d773SGleb Smirnoff #include "netdissect.h"
245b0fe478SBruce M Simpson #include "extract.h"
255b0fe478SBruce M Simpson #include "addrtoname.h"
265b0fe478SBruce M Simpson 
271de50e9fSSam Leffler #include "l2vpn.h"
28a5779b6eSRui Paulo #include "af.h"
291de50e9fSSam Leffler 
3039e421e8SCy Schubert 
315b0fe478SBruce M Simpson /*
325b0fe478SBruce M Simpson  * ldp common header
335b0fe478SBruce M Simpson  *
345b0fe478SBruce M Simpson  *  0                   1                   2                   3
355b0fe478SBruce M Simpson  *  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
365b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
375b0fe478SBruce M Simpson  * |  Version                      |         PDU Length            |
385b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
395b0fe478SBruce M Simpson  * |                         LDP Identifier                        |
405b0fe478SBruce M Simpson  * +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
415b0fe478SBruce M Simpson  * |                               |
425b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
435b0fe478SBruce M Simpson  *
445b0fe478SBruce M Simpson  */
455b0fe478SBruce M Simpson 
465b0fe478SBruce M Simpson struct ldp_common_header {
47ee67461eSJoseph Mingrone     nd_uint16_t version;
48ee67461eSJoseph Mingrone     nd_uint16_t pdu_length;
49ee67461eSJoseph Mingrone     nd_ipv4     lsr_id;
50ee67461eSJoseph Mingrone     nd_uint16_t label_space;
515b0fe478SBruce M Simpson };
525b0fe478SBruce M Simpson 
535b0fe478SBruce M Simpson #define LDP_VERSION 1
545b0fe478SBruce M Simpson 
555b0fe478SBruce M Simpson /*
565b0fe478SBruce M Simpson  * ldp message header
575b0fe478SBruce M Simpson  *
585b0fe478SBruce M Simpson  *  0                   1                   2                   3
595b0fe478SBruce M Simpson  *  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
605b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
615b0fe478SBruce M Simpson  * |U|   Message Type              |      Message Length           |
625b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
635b0fe478SBruce M Simpson  * |                     Message ID                                |
645b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
655b0fe478SBruce M Simpson  * |                                                               |
665b0fe478SBruce M Simpson  * +                                                               +
675b0fe478SBruce M Simpson  * |                     Mandatory Parameters                      |
685b0fe478SBruce M Simpson  * +                                                               +
695b0fe478SBruce M Simpson  * |                                                               |
705b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
715b0fe478SBruce M Simpson  * |                                                               |
725b0fe478SBruce M Simpson  * +                                                               +
735b0fe478SBruce M Simpson  * |                     Optional Parameters                       |
745b0fe478SBruce M Simpson  * +                                                               +
755b0fe478SBruce M Simpson  * |                                                               |
765b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
775b0fe478SBruce M Simpson  */
785b0fe478SBruce M Simpson 
795b0fe478SBruce M Simpson struct ldp_msg_header {
80ee67461eSJoseph Mingrone     nd_uint16_t type;
81ee67461eSJoseph Mingrone     nd_uint16_t length;
82ee67461eSJoseph Mingrone     nd_uint32_t id;
835b0fe478SBruce M Simpson };
845b0fe478SBruce M Simpson 
855b0fe478SBruce M Simpson #define	LDP_MASK_MSG_TYPE(x)  ((x)&0x7fff)
865b0fe478SBruce M Simpson #define	LDP_MASK_U_BIT(x)     ((x)&0x8000)
875b0fe478SBruce M Simpson 
885b0fe478SBruce M Simpson #define	LDP_MSG_NOTIF                0x0001
895b0fe478SBruce M Simpson #define	LDP_MSG_HELLO                0x0100
905b0fe478SBruce M Simpson #define	LDP_MSG_INIT                 0x0200
915b0fe478SBruce M Simpson #define	LDP_MSG_KEEPALIVE            0x0201
925b0fe478SBruce M Simpson #define	LDP_MSG_ADDRESS              0x0300
935b0fe478SBruce M Simpson #define	LDP_MSG_ADDRESS_WITHDRAW     0x0301
945b0fe478SBruce M Simpson #define	LDP_MSG_LABEL_MAPPING        0x0400
955b0fe478SBruce M Simpson #define	LDP_MSG_LABEL_REQUEST        0x0401
965b0fe478SBruce M Simpson #define	LDP_MSG_LABEL_WITHDRAW       0x0402
975b0fe478SBruce M Simpson #define	LDP_MSG_LABEL_RELEASE        0x0403
985b0fe478SBruce M Simpson #define	LDP_MSG_LABEL_ABORT_REQUEST  0x0404
995b0fe478SBruce M Simpson 
1005b0fe478SBruce M Simpson #define	LDP_VENDOR_PRIVATE_MIN       0x3e00
1015b0fe478SBruce M Simpson #define	LDP_VENDOR_PRIVATE_MAX       0x3eff
1025b0fe478SBruce M Simpson #define	LDP_EXPERIMENTAL_MIN         0x3f00
1035b0fe478SBruce M Simpson #define	LDP_EXPERIMENTAL_MAX         0x3fff
1045b0fe478SBruce M Simpson 
1055b0fe478SBruce M Simpson static const struct tok ldp_msg_values[] = {
1065b0fe478SBruce M Simpson     { LDP_MSG_NOTIF,	             "Notification" },
1075b0fe478SBruce M Simpson     { LDP_MSG_HELLO,	             "Hello" },
1085b0fe478SBruce M Simpson     { LDP_MSG_INIT,	             "Initialization" },
1095b0fe478SBruce M Simpson     { LDP_MSG_KEEPALIVE,             "Keepalive" },
1105b0fe478SBruce M Simpson     { LDP_MSG_ADDRESS,	             "Address" },
111b5bfcb5dSMax Laier     { LDP_MSG_ADDRESS_WITHDRAW,	     "Address Withdraw" },
1125b0fe478SBruce M Simpson     { LDP_MSG_LABEL_MAPPING,	     "Label Mapping" },
1135b0fe478SBruce M Simpson     { LDP_MSG_LABEL_REQUEST,	     "Label Request" },
1145b0fe478SBruce M Simpson     { LDP_MSG_LABEL_WITHDRAW,	     "Label Withdraw" },
1155b0fe478SBruce M Simpson     { LDP_MSG_LABEL_RELEASE,	     "Label Release" },
1165b0fe478SBruce M Simpson     { LDP_MSG_LABEL_ABORT_REQUEST,   "Label Abort Request" },
1175b0fe478SBruce M Simpson     { 0, NULL}
1185b0fe478SBruce M Simpson };
1195b0fe478SBruce M Simpson 
1205b0fe478SBruce M Simpson #define	LDP_MASK_TLV_TYPE(x)  ((x)&0x3fff)
1215b0fe478SBruce M Simpson #define	LDP_MASK_F_BIT(x) ((x)&0x4000)
1225b0fe478SBruce M Simpson 
1235b0fe478SBruce M Simpson #define	LDP_TLV_FEC                  0x0100
1245b0fe478SBruce M Simpson #define	LDP_TLV_ADDRESS_LIST         0x0101
125a5779b6eSRui Paulo #define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2
1265b0fe478SBruce M Simpson #define	LDP_TLV_HOP_COUNT            0x0103
1275b0fe478SBruce M Simpson #define	LDP_TLV_PATH_VECTOR          0x0104
1285b0fe478SBruce M Simpson #define	LDP_TLV_GENERIC_LABEL        0x0200
1295b0fe478SBruce M Simpson #define	LDP_TLV_ATM_LABEL            0x0201
1305b0fe478SBruce M Simpson #define	LDP_TLV_FR_LABEL             0x0202
1315b0fe478SBruce M Simpson #define	LDP_TLV_STATUS               0x0300
1325b0fe478SBruce M Simpson #define	LDP_TLV_EXTD_STATUS          0x0301
1335b0fe478SBruce M Simpson #define	LDP_TLV_RETURNED_PDU         0x0302
1345b0fe478SBruce M Simpson #define	LDP_TLV_RETURNED_MSG         0x0303
1355b0fe478SBruce M Simpson #define	LDP_TLV_COMMON_HELLO         0x0400
1365b0fe478SBruce M Simpson #define	LDP_TLV_IPV4_TRANSPORT_ADDR  0x0401
1375b0fe478SBruce M Simpson #define	LDP_TLV_CONFIG_SEQ_NUMBER    0x0402
1385b0fe478SBruce M Simpson #define	LDP_TLV_IPV6_TRANSPORT_ADDR  0x0403
1395b0fe478SBruce M Simpson #define	LDP_TLV_COMMON_SESSION       0x0500
1405b0fe478SBruce M Simpson #define	LDP_TLV_ATM_SESSION_PARM     0x0501
1415b0fe478SBruce M Simpson #define	LDP_TLV_FR_SESSION_PARM      0x0502
1421de50e9fSSam Leffler #define LDP_TLV_FT_SESSION	     0x0503
1435b0fe478SBruce M Simpson #define	LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600
144a5779b6eSRui Paulo #define LDP_TLV_MTU                  0x0601 /* rfc 3988 */
1455b0fe478SBruce M Simpson 
1465b0fe478SBruce M Simpson static const struct tok ldp_tlv_values[] = {
1475b0fe478SBruce M Simpson     { LDP_TLV_FEC,	             "FEC" },
1485b0fe478SBruce M Simpson     { LDP_TLV_ADDRESS_LIST,          "Address List" },
1495b0fe478SBruce M Simpson     { LDP_TLV_HOP_COUNT,             "Hop Count" },
1505b0fe478SBruce M Simpson     { LDP_TLV_PATH_VECTOR,           "Path Vector" },
1515b0fe478SBruce M Simpson     { LDP_TLV_GENERIC_LABEL,         "Generic Label" },
1525b0fe478SBruce M Simpson     { LDP_TLV_ATM_LABEL,             "ATM Label" },
1535b0fe478SBruce M Simpson     { LDP_TLV_FR_LABEL,              "Frame-Relay Label" },
1545b0fe478SBruce M Simpson     { LDP_TLV_STATUS,                "Status" },
1555b0fe478SBruce M Simpson     { LDP_TLV_EXTD_STATUS,           "Extended Status" },
1565b0fe478SBruce M Simpson     { LDP_TLV_RETURNED_PDU,          "Returned PDU" },
1575b0fe478SBruce M Simpson     { LDP_TLV_RETURNED_MSG,          "Returned Message" },
1585b0fe478SBruce M Simpson     { LDP_TLV_COMMON_HELLO,          "Common Hello Parameters" },
1595b0fe478SBruce M Simpson     { LDP_TLV_IPV4_TRANSPORT_ADDR,   "IPv4 Transport Address" },
1605b0fe478SBruce M Simpson     { LDP_TLV_CONFIG_SEQ_NUMBER,     "Configuration Sequence Number" },
1615b0fe478SBruce M Simpson     { LDP_TLV_IPV6_TRANSPORT_ADDR,   "IPv6 Transport Address" },
1625b0fe478SBruce M Simpson     { LDP_TLV_COMMON_SESSION,        "Common Session Parameters" },
1635b0fe478SBruce M Simpson     { LDP_TLV_ATM_SESSION_PARM,      "ATM Session Parameters" },
1645b0fe478SBruce M Simpson     { LDP_TLV_FR_SESSION_PARM,       "Frame-Relay Session Parameters" },
1651de50e9fSSam Leffler     { LDP_TLV_FT_SESSION,            "Fault-Tolerant Session Parameters" },
1665b0fe478SBruce M Simpson     { LDP_TLV_LABEL_REQUEST_MSG_ID,  "Label Request Message ID" },
167a5779b6eSRui Paulo     { LDP_TLV_MTU,                   "MTU" },
1685b0fe478SBruce M Simpson     { 0, NULL}
1695b0fe478SBruce M Simpson };
1705b0fe478SBruce M Simpson 
1711de50e9fSSam Leffler #define LDP_FEC_WILDCARD	0x01
1721de50e9fSSam Leffler #define LDP_FEC_PREFIX		0x02
1731de50e9fSSam Leffler #define LDP_FEC_HOSTADDRESS	0x03
174d09a7e67SXin LI /* From RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */
1751de50e9fSSam Leffler #define LDP_FEC_MARTINI_VC	0x80
1761de50e9fSSam Leffler 
1771de50e9fSSam Leffler static const struct tok ldp_fec_values[] = {
1781de50e9fSSam Leffler     { LDP_FEC_WILDCARD,		"Wildcard" },
1791de50e9fSSam Leffler     { LDP_FEC_PREFIX,		"Prefix" },
1801de50e9fSSam Leffler     { LDP_FEC_HOSTADDRESS,	"Host address" },
1811de50e9fSSam Leffler     { LDP_FEC_MARTINI_VC,	"Martini VC" },
1821de50e9fSSam Leffler     { 0, NULL}
1831de50e9fSSam Leffler };
1841de50e9fSSam Leffler 
185f4d0c64aSSam Leffler #define LDP_FEC_MARTINI_IFPARM_MTU  0x01
186f4d0c64aSSam Leffler #define LDP_FEC_MARTINI_IFPARM_DESC 0x03
187f4d0c64aSSam Leffler #define LDP_FEC_MARTINI_IFPARM_VCCV 0x0c
188f4d0c64aSSam Leffler 
189f4d0c64aSSam Leffler static const struct tok ldp_fec_martini_ifparm_values[] = {
190f4d0c64aSSam Leffler     { LDP_FEC_MARTINI_IFPARM_MTU, "MTU" },
191f4d0c64aSSam Leffler     { LDP_FEC_MARTINI_IFPARM_DESC, "Description" },
192f4d0c64aSSam Leffler     { LDP_FEC_MARTINI_IFPARM_VCCV, "VCCV" },
193f4d0c64aSSam Leffler     { 0, NULL}
194f4d0c64aSSam Leffler };
195f4d0c64aSSam Leffler 
196f4d0c64aSSam Leffler /* draft-ietf-pwe3-vccv-04.txt */
197f4d0c64aSSam Leffler static const struct tok ldp_fec_martini_ifparm_vccv_cc_values[] = {
198f4d0c64aSSam Leffler     { 0x01, "PWE3 control word" },
199f4d0c64aSSam Leffler     { 0x02, "MPLS Router Alert Label" },
200f4d0c64aSSam Leffler     { 0x04, "MPLS inner label TTL = 1" },
201f4d0c64aSSam Leffler     { 0, NULL}
202f4d0c64aSSam Leffler };
203f4d0c64aSSam Leffler 
204f4d0c64aSSam Leffler /* draft-ietf-pwe3-vccv-04.txt */
205f4d0c64aSSam Leffler static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = {
206f4d0c64aSSam Leffler     { 0x01, "ICMP Ping" },
207f4d0c64aSSam Leffler     { 0x02, "LSP Ping" },
208f4d0c64aSSam Leffler     { 0x04, "BFD" },
209f4d0c64aSSam Leffler     { 0, NULL}
210f4d0c64aSSam Leffler };
211f4d0c64aSSam Leffler 
212ee67461eSJoseph Mingrone static u_int ldp_pdu_print(netdissect_options *, const u_char *);
2135b0fe478SBruce M Simpson 
2145b0fe478SBruce M Simpson /*
2155b0fe478SBruce M Simpson  * ldp tlv header
2165b0fe478SBruce M Simpson  *
2175b0fe478SBruce M Simpson  *  0                   1                   2                   3
2185b0fe478SBruce M Simpson  *  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
2195b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2205b0fe478SBruce M Simpson  * |U|F|        Type               |            Length             |
2215b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2225b0fe478SBruce M Simpson  * |                                                               |
2235b0fe478SBruce M Simpson  * |                             Value                             |
2245b0fe478SBruce M Simpson  * ~                                                               ~
2255b0fe478SBruce M Simpson  * |                                                               |
2265b0fe478SBruce M Simpson  * |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2275b0fe478SBruce M Simpson  * |                               |
2285b0fe478SBruce M Simpson  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2295b0fe478SBruce M Simpson  */
2305b0fe478SBruce M Simpson 
231d09a7e67SXin LI #define TLV_TCHECK(minlen) \
232ee67461eSJoseph Mingrone     if (tlv_tlen < minlen) { \
233ee67461eSJoseph Mingrone         ND_PRINT(" [tlv length %u < %u]", tlv_tlen, minlen); \
234ee67461eSJoseph Mingrone         nd_print_invalid(ndo); \
235ee67461eSJoseph Mingrone         goto invalid; \
236ee67461eSJoseph Mingrone     }
237d09a7e67SXin LI 
238ee67461eSJoseph Mingrone static u_int
ldp_tlv_print(netdissect_options * ndo,const u_char * tptr,u_int msg_tlen)2393c602fabSXin LI ldp_tlv_print(netdissect_options *ndo,
240ee67461eSJoseph Mingrone               const u_char *tptr,
241ee67461eSJoseph Mingrone               u_int msg_tlen)
2428bdc5a62SPatrick Kelsey {
2435b0fe478SBruce M Simpson     struct ldp_tlv_header {
244ee67461eSJoseph Mingrone         nd_uint16_t type;
245ee67461eSJoseph Mingrone         nd_uint16_t length;
2465b0fe478SBruce M Simpson     };
2475b0fe478SBruce M Simpson 
2485b0fe478SBruce M Simpson     const struct ldp_tlv_header *ldp_tlv_header;
2491de50e9fSSam Leffler     u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags;
2501de50e9fSSam Leffler     u_char fec_type;
251f4d0c64aSSam Leffler     u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx;
2521de50e9fSSam Leffler     char buf[100];
2531de50e9fSSam Leffler     int i;
2545b0fe478SBruce M Simpson 
2555b0fe478SBruce M Simpson     ldp_tlv_header = (const struct ldp_tlv_header *)tptr;
256ee67461eSJoseph Mingrone     ND_TCHECK_SIZE(ldp_tlv_header);
257ee67461eSJoseph Mingrone     tlv_len=GET_BE_U_2(ldp_tlv_header->length);
258ee67461eSJoseph Mingrone     if (tlv_len + 4U > msg_tlen) {
259ee67461eSJoseph Mingrone         ND_PRINT("\n\t\t TLV contents go past end of message");
2608bdc5a62SPatrick Kelsey         return 0;
2618bdc5a62SPatrick Kelsey     }
2625b0fe478SBruce M Simpson     tlv_tlen=tlv_len;
263ee67461eSJoseph Mingrone     tlv_type=LDP_MASK_TLV_TYPE(GET_BE_U_2(ldp_tlv_header->type));
2645b0fe478SBruce M Simpson 
2655b0fe478SBruce M Simpson     /* FIXME vendor private / experimental check */
266ee67461eSJoseph Mingrone     ND_PRINT("\n\t    %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]",
2675b0fe478SBruce M Simpson            tok2str(ldp_tlv_values,
2685b0fe478SBruce M Simpson                    "Unknown",
2695b0fe478SBruce M Simpson                    tlv_type),
2705b0fe478SBruce M Simpson            tlv_type,
2715b0fe478SBruce M Simpson            tlv_len,
272ee67461eSJoseph Mingrone            LDP_MASK_U_BIT(GET_BE_U_2(ldp_tlv_header->type)) ? "continue processing" : "ignore",
273ee67461eSJoseph Mingrone            LDP_MASK_F_BIT(GET_BE_U_2(ldp_tlv_header->type)) ? "do" : "don't");
2745b0fe478SBruce M Simpson 
2755b0fe478SBruce M Simpson     tptr+=sizeof(struct ldp_tlv_header);
2765b0fe478SBruce M Simpson 
2775b0fe478SBruce M Simpson     switch(tlv_type) {
2785b0fe478SBruce M Simpson 
2795b0fe478SBruce M Simpson     case LDP_TLV_COMMON_HELLO:
280d09a7e67SXin LI         TLV_TCHECK(4);
281ee67461eSJoseph Mingrone         ND_PRINT("\n\t      Hold Time: %us, Flags: [%s Hello%s]",
282ee67461eSJoseph Mingrone                GET_BE_U_2(tptr),
283ee67461eSJoseph Mingrone                (GET_BE_U_2(tptr + 2)&0x8000) ? "Targeted" : "Link",
284ee67461eSJoseph Mingrone                (GET_BE_U_2(tptr + 2)&0x4000) ? ", Request for targeted Hellos" : "");
2855b0fe478SBruce M Simpson         break;
2865b0fe478SBruce M Simpson 
2875b0fe478SBruce M Simpson     case LDP_TLV_IPV4_TRANSPORT_ADDR:
288d09a7e67SXin LI         TLV_TCHECK(4);
289ee67461eSJoseph Mingrone         ND_PRINT("\n\t      IPv4 Transport Address: %s", GET_IPADDR_STRING(tptr));
2905b0fe478SBruce M Simpson         break;
2915b0fe478SBruce M Simpson     case LDP_TLV_IPV6_TRANSPORT_ADDR:
292d09a7e67SXin LI         TLV_TCHECK(16);
293ee67461eSJoseph Mingrone         ND_PRINT("\n\t      IPv6 Transport Address: %s", GET_IP6ADDR_STRING(tptr));
2945b0fe478SBruce M Simpson         break;
2955b0fe478SBruce M Simpson     case LDP_TLV_CONFIG_SEQ_NUMBER:
296d09a7e67SXin LI         TLV_TCHECK(4);
297ee67461eSJoseph Mingrone         ND_PRINT("\n\t      Sequence Number: %u", GET_BE_U_4(tptr));
2985b0fe478SBruce M Simpson         break;
2995b0fe478SBruce M Simpson 
3001de50e9fSSam Leffler     case LDP_TLV_ADDRESS_LIST:
301d09a7e67SXin LI         TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN);
302ee67461eSJoseph Mingrone 	af = GET_BE_U_2(tptr);
303a5779b6eSRui Paulo 	tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
304a5779b6eSRui Paulo         tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
305ee67461eSJoseph Mingrone 	ND_PRINT("\n\t      Address Family: %s, addresses",
306ee67461eSJoseph Mingrone                tok2str(af_values, "Unknown (%u)", af));
307a5779b6eSRui Paulo         switch (af) {
308a5779b6eSRui Paulo         case AFNUM_INET:
309ee67461eSJoseph Mingrone 	    while(tlv_tlen >= sizeof(nd_ipv4)) {
310ee67461eSJoseph Mingrone 		ND_PRINT(" %s", GET_IPADDR_STRING(tptr));
311ee67461eSJoseph Mingrone 		tlv_tlen-=sizeof(nd_ipv4);
312ee67461eSJoseph Mingrone 		tptr+=sizeof(nd_ipv4);
3131de50e9fSSam Leffler 	    }
314a5779b6eSRui Paulo             break;
315a5779b6eSRui Paulo         case AFNUM_INET6:
316ee67461eSJoseph Mingrone 	    while(tlv_tlen >= sizeof(nd_ipv6)) {
317ee67461eSJoseph Mingrone 		ND_PRINT(" %s", GET_IP6ADDR_STRING(tptr));
318ee67461eSJoseph Mingrone 		tlv_tlen-=sizeof(nd_ipv6);
319ee67461eSJoseph Mingrone 		tptr+=sizeof(nd_ipv6);
3201de50e9fSSam Leffler 	    }
321a5779b6eSRui Paulo             break;
322a5779b6eSRui Paulo         default:
323a5779b6eSRui Paulo             /* unknown AF */
324a5779b6eSRui Paulo             break;
325a5779b6eSRui Paulo         }
3261de50e9fSSam Leffler 	break;
3271de50e9fSSam Leffler 
3281de50e9fSSam Leffler     case LDP_TLV_COMMON_SESSION:
329*0a7e5f1fSJoseph Mingrone 	TLV_TCHECK(14);
330ee67461eSJoseph Mingrone 	ND_PRINT("\n\t      Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]",
331ee67461eSJoseph Mingrone 	       GET_BE_U_2(tptr), GET_BE_U_2(tptr + 2),
332*0a7e5f1fSJoseph Mingrone 	       (GET_BE_U_2(tptr + 4)&0x8000) ? "On Demand" : "Unsolicited",
333*0a7e5f1fSJoseph Mingrone 	       (GET_BE_U_2(tptr + 4)&0x4000) ? "Enabled" : "Disabled"
334*0a7e5f1fSJoseph Mingrone 	       );
335*0a7e5f1fSJoseph Mingrone 	ND_PRINT("\n\t      Path Vector Limit %u, Max-PDU length: %u, Receiver Label-Space-ID %s:%u",
336*0a7e5f1fSJoseph Mingrone 	       GET_U_1(tptr+5),
337*0a7e5f1fSJoseph Mingrone 	       GET_BE_U_2(tptr+6),
338*0a7e5f1fSJoseph Mingrone 	       GET_IPADDR_STRING(tptr+8),
339*0a7e5f1fSJoseph Mingrone 	       GET_BE_U_2(tptr+12)
340ee67461eSJoseph Mingrone 	       );
3411de50e9fSSam Leffler 	break;
3421de50e9fSSam Leffler 
3431de50e9fSSam Leffler     case LDP_TLV_FEC:
344d09a7e67SXin LI         TLV_TCHECK(1);
345ee67461eSJoseph Mingrone         fec_type = GET_U_1(tptr);
346ee67461eSJoseph Mingrone 	ND_PRINT("\n\t      %s FEC (0x%02x)",
3471de50e9fSSam Leffler 	       tok2str(ldp_fec_values, "Unknown", fec_type),
348ee67461eSJoseph Mingrone 	       fec_type);
3491de50e9fSSam Leffler 
3501de50e9fSSam Leffler 	tptr+=1;
351d09a7e67SXin LI 	tlv_tlen-=1;
3521de50e9fSSam Leffler 	switch(fec_type) {
3531de50e9fSSam Leffler 
3541de50e9fSSam Leffler 	case LDP_FEC_WILDCARD:
3551de50e9fSSam Leffler 	    break;
3561de50e9fSSam Leffler 	case LDP_FEC_PREFIX:
357d09a7e67SXin LI 	    TLV_TCHECK(2);
358ee67461eSJoseph Mingrone 	    af = GET_BE_U_2(tptr);
359ee67461eSJoseph Mingrone 	    tptr+=2;
360ee67461eSJoseph Mingrone 	    tlv_tlen-=2;
3611de50e9fSSam Leffler 	    if (af == AFNUM_INET) {
3623c602fabSXin LI 		i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf));
363d09a7e67SXin LI 		if (i == -2)
364d09a7e67SXin LI 		    goto trunc;
365d09a7e67SXin LI 		if (i == -3)
366ee67461eSJoseph Mingrone 		    ND_PRINT(": IPv4 prefix (goes past end of TLV)");
367d09a7e67SXin LI 		else if (i == -1)
368ee67461eSJoseph Mingrone 		    ND_PRINT(": IPv4 prefix (invalid length)");
369d09a7e67SXin LI 		else
370ee67461eSJoseph Mingrone 		    ND_PRINT(": IPv4 prefix %s", buf);
371*0a7e5f1fSJoseph Mingrone 	    } else if (af == AFNUM_INET6) {
3723c602fabSXin LI 		i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf));
373d09a7e67SXin LI 		if (i == -2)
374d09a7e67SXin LI 		    goto trunc;
375d09a7e67SXin LI 		if (i == -3)
376ee67461eSJoseph Mingrone 		    ND_PRINT(": IPv4 prefix (goes past end of TLV)");
377d09a7e67SXin LI 		else if (i == -1)
378ee67461eSJoseph Mingrone 		    ND_PRINT(": IPv6 prefix (invalid length)");
379d09a7e67SXin LI 		else
380ee67461eSJoseph Mingrone 		    ND_PRINT(": IPv6 prefix %s", buf);
381*0a7e5f1fSJoseph Mingrone 	    } else
382ee67461eSJoseph Mingrone 		ND_PRINT(": Address family %u prefix", af);
3831de50e9fSSam Leffler 	    break;
3841de50e9fSSam Leffler 	case LDP_FEC_HOSTADDRESS:
3851de50e9fSSam Leffler 	    break;
3861de50e9fSSam Leffler 	case LDP_FEC_MARTINI_VC:
387d09a7e67SXin LI             /*
3883340d773SGleb Smirnoff              * We assume the type was supposed to be one of the MPLS
3893340d773SGleb Smirnoff              * Pseudowire Types.
390d09a7e67SXin LI              */
391d09a7e67SXin LI             TLV_TCHECK(7);
392ee67461eSJoseph Mingrone             vc_info_len = GET_U_1(tptr + 2);
393f4d0c64aSSam Leffler 
3943340d773SGleb Smirnoff             /*
3953340d773SGleb Smirnoff 	     * According to RFC 4908, the VC info Length field can be zero,
3963340d773SGleb Smirnoff 	     * in which case not only are there no interface parameters,
3973340d773SGleb Smirnoff 	     * there's no VC ID.
3983340d773SGleb Smirnoff 	     */
399d09a7e67SXin LI             if (vc_info_len == 0) {
400ee67461eSJoseph Mingrone                 ND_PRINT(": %s, %scontrol word, group-ID %u, VC-info-length: %u",
401ee67461eSJoseph Mingrone                        tok2str(mpls_pw_types_values, "Unknown", GET_BE_U_2(tptr)&0x7fff),
402ee67461eSJoseph Mingrone                        GET_BE_U_2(tptr)&0x8000 ? "" : "no ",
403ee67461eSJoseph Mingrone                        GET_BE_U_4(tptr + 3),
404ee67461eSJoseph Mingrone                        vc_info_len);
405d09a7e67SXin LI                 break;
406d09a7e67SXin LI             }
407d09a7e67SXin LI 
408d09a7e67SXin LI             /* Make sure we have the VC ID as well */
409d09a7e67SXin LI             TLV_TCHECK(11);
410ee67461eSJoseph Mingrone 	    ND_PRINT(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u",
411ee67461eSJoseph Mingrone 		   tok2str(mpls_pw_types_values, "Unknown", GET_BE_U_2(tptr)&0x7fff),
412ee67461eSJoseph Mingrone 		   GET_BE_U_2(tptr)&0x8000 ? "" : "no ",
413ee67461eSJoseph Mingrone 		   GET_BE_U_4(tptr + 3),
414ee67461eSJoseph Mingrone 		   GET_BE_U_4(tptr + 7),
415ee67461eSJoseph Mingrone 		   vc_info_len);
4168bdc5a62SPatrick Kelsey             if (vc_info_len < 4) {
4178bdc5a62SPatrick Kelsey                 /* minimum 4, for the VC ID */
418ee67461eSJoseph Mingrone                 ND_PRINT(" (invalid, < 4");
4198bdc5a62SPatrick Kelsey                 return(tlv_len+4); /* Type & Length fields not included */
4208bdc5a62SPatrick Kelsey 	    }
421d09a7e67SXin LI             vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */
422f4d0c64aSSam Leffler 
423d09a7e67SXin LI             /* Skip past the fixed information and the VC ID */
424f4d0c64aSSam Leffler             tptr+=11;
425d09a7e67SXin LI             tlv_tlen-=11;
426d09a7e67SXin LI             TLV_TCHECK(vc_info_len);
427f4d0c64aSSam Leffler 
428f4d0c64aSSam Leffler             while (vc_info_len > 2) {
429ee67461eSJoseph Mingrone                 vc_info_tlv_type = GET_U_1(tptr);
430ee67461eSJoseph Mingrone                 vc_info_tlv_len = GET_U_1(tptr + 1);
431f4d0c64aSSam Leffler                 if (vc_info_tlv_len < 2)
432f4d0c64aSSam Leffler                     break;
433f4d0c64aSSam Leffler                 if (vc_info_len < vc_info_tlv_len)
434f4d0c64aSSam Leffler                     break;
435f4d0c64aSSam Leffler 
436ee67461eSJoseph Mingrone                 ND_PRINT("\n\t\tInterface Parameter: %s (0x%02x), len %u",
437f4d0c64aSSam Leffler                        tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type),
438f4d0c64aSSam Leffler                        vc_info_tlv_type,
439ee67461eSJoseph Mingrone                        vc_info_tlv_len);
440f4d0c64aSSam Leffler 
441f4d0c64aSSam Leffler                 switch(vc_info_tlv_type) {
442f4d0c64aSSam Leffler                 case LDP_FEC_MARTINI_IFPARM_MTU:
443ee67461eSJoseph Mingrone                     ND_PRINT(": %u", GET_BE_U_2(tptr + 2));
444f4d0c64aSSam Leffler                     break;
445f4d0c64aSSam Leffler 
446f4d0c64aSSam Leffler                 case LDP_FEC_MARTINI_IFPARM_DESC:
447ee67461eSJoseph Mingrone                     ND_PRINT(": ");
448ee67461eSJoseph Mingrone                     for (idx = 2; idx < vc_info_tlv_len; idx++)
449ee67461eSJoseph Mingrone                         fn_print_char(ndo, GET_U_1(tptr + idx));
450f4d0c64aSSam Leffler                     break;
451f4d0c64aSSam Leffler 
452f4d0c64aSSam Leffler                 case LDP_FEC_MARTINI_IFPARM_VCCV:
453ee67461eSJoseph Mingrone                     ND_PRINT("\n\t\t  Control Channels (0x%02x) = [%s]",
454ee67461eSJoseph Mingrone                            GET_U_1((tptr + 2)),
455ee67461eSJoseph Mingrone                            bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", GET_U_1((tptr + 2))));
456ee67461eSJoseph Mingrone                     ND_PRINT("\n\t\t  CV Types (0x%02x) = [%s]",
457ee67461eSJoseph Mingrone                            GET_U_1((tptr + 3)),
458ee67461eSJoseph Mingrone                            bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", GET_U_1((tptr + 3))));
459f4d0c64aSSam Leffler                     break;
460f4d0c64aSSam Leffler 
461f4d0c64aSSam Leffler                 default:
4623c602fabSXin LI                     print_unknown_data(ndo, tptr+2, "\n\t\t  ", vc_info_tlv_len-2);
463f4d0c64aSSam Leffler                     break;
464f4d0c64aSSam Leffler                 }
465f4d0c64aSSam Leffler 
466f4d0c64aSSam Leffler                 vc_info_len -= vc_info_tlv_len;
467f4d0c64aSSam Leffler                 tptr += vc_info_tlv_len;
468f4d0c64aSSam Leffler             }
4691de50e9fSSam Leffler 	    break;
4701de50e9fSSam Leffler 	}
4711de50e9fSSam Leffler 
4721de50e9fSSam Leffler 	break;
4731de50e9fSSam Leffler 
4741de50e9fSSam Leffler     case LDP_TLV_GENERIC_LABEL:
475d09a7e67SXin LI 	TLV_TCHECK(4);
476ee67461eSJoseph Mingrone 	ND_PRINT("\n\t      Label: %u", GET_BE_U_4(tptr) & 0xfffff);
4771de50e9fSSam Leffler 	break;
4781de50e9fSSam Leffler 
4791de50e9fSSam Leffler     case LDP_TLV_STATUS:
480d09a7e67SXin LI 	TLV_TCHECK(8);
481ee67461eSJoseph Mingrone 	ui = GET_BE_U_4(tptr);
4821de50e9fSSam Leffler 	tptr+=4;
483ee67461eSJoseph Mingrone 	ND_PRINT("\n\t      Status: 0x%02x, Flags: [%s and %s forward]",
4841de50e9fSSam Leffler 	       ui&0x3fffffff,
4851de50e9fSSam Leffler 	       ui&0x80000000 ? "Fatal error" : "Advisory Notification",
486ee67461eSJoseph Mingrone 	       ui&0x40000000 ? "do" : "don't");
487ee67461eSJoseph Mingrone 	ui = GET_BE_U_4(tptr);
4881de50e9fSSam Leffler 	tptr+=4;
4891de50e9fSSam Leffler 	if (ui)
490ee67461eSJoseph Mingrone 	    ND_PRINT(", causing Message ID: 0x%08x", ui);
4911de50e9fSSam Leffler 	break;
4921de50e9fSSam Leffler 
4931de50e9fSSam Leffler     case LDP_TLV_FT_SESSION:
49439e421e8SCy Schubert 	TLV_TCHECK(12);
495ee67461eSJoseph Mingrone 	ft_flags = GET_BE_U_2(tptr);
496ee67461eSJoseph Mingrone 	ND_PRINT("\n\t      Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]",
4971de50e9fSSam Leffler 	       ft_flags&0x8000 ? "" : "No ",
4981de50e9fSSam Leffler 	       ft_flags&0x8 ? "" : "Don't ",
4991de50e9fSSam Leffler 	       ft_flags&0x4 ? "" : "No ",
5001de50e9fSSam Leffler 	       ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels",
501ee67461eSJoseph Mingrone 	       ft_flags&0x1 ? "" : "Don't ");
50239e421e8SCy Schubert 	/* 16 bits (FT Flags) + 16 bits (Reserved) */
5031de50e9fSSam Leffler 	tptr+=4;
504ee67461eSJoseph Mingrone 	ui = GET_BE_U_4(tptr);
5051de50e9fSSam Leffler 	if (ui)
506ee67461eSJoseph Mingrone 	    ND_PRINT(", Reconnect Timeout: %ums", ui);
5071de50e9fSSam Leffler 	tptr+=4;
508ee67461eSJoseph Mingrone 	ui = GET_BE_U_4(tptr);
5091de50e9fSSam Leffler 	if (ui)
510ee67461eSJoseph Mingrone 	    ND_PRINT(", Recovery Time: %ums", ui);
5111de50e9fSSam Leffler 	break;
5121de50e9fSSam Leffler 
513a5779b6eSRui Paulo     case LDP_TLV_MTU:
514d09a7e67SXin LI 	TLV_TCHECK(2);
515ee67461eSJoseph Mingrone 	ND_PRINT("\n\t      MTU: %u", GET_BE_U_2(tptr));
516a5779b6eSRui Paulo 	break;
517a5779b6eSRui Paulo 
5181de50e9fSSam Leffler 
5195b0fe478SBruce M Simpson     /*
5205b0fe478SBruce M Simpson      *  FIXME those are the defined TLVs that lack a decoder
5215b0fe478SBruce M Simpson      *  you are welcome to contribute code ;-)
5225b0fe478SBruce M Simpson      */
5235b0fe478SBruce M Simpson 
5245b0fe478SBruce M Simpson     case LDP_TLV_HOP_COUNT:
5255b0fe478SBruce M Simpson     case LDP_TLV_PATH_VECTOR:
5265b0fe478SBruce M Simpson     case LDP_TLV_ATM_LABEL:
5275b0fe478SBruce M Simpson     case LDP_TLV_FR_LABEL:
5285b0fe478SBruce M Simpson     case LDP_TLV_EXTD_STATUS:
5295b0fe478SBruce M Simpson     case LDP_TLV_RETURNED_PDU:
5305b0fe478SBruce M Simpson     case LDP_TLV_RETURNED_MSG:
5315b0fe478SBruce M Simpson     case LDP_TLV_ATM_SESSION_PARM:
5325b0fe478SBruce M Simpson     case LDP_TLV_FR_SESSION_PARM:
5335b0fe478SBruce M Simpson     case LDP_TLV_LABEL_REQUEST_MSG_ID:
5345b0fe478SBruce M Simpson 
5355b0fe478SBruce M Simpson     default:
5363c602fabSXin LI         if (ndo->ndo_vflag <= 1)
5373c602fabSXin LI             print_unknown_data(ndo, tptr, "\n\t      ", tlv_tlen);
5385b0fe478SBruce M Simpson         break;
5395b0fe478SBruce M Simpson     }
5405b0fe478SBruce M Simpson     return(tlv_len+4); /* Type & Length fields not included */
541f4d0c64aSSam Leffler 
542f4d0c64aSSam Leffler trunc:
543ee67461eSJoseph Mingrone     nd_trunc_longjmp(ndo);
544d09a7e67SXin LI 
545ee67461eSJoseph Mingrone invalid:
546d09a7e67SXin LI     return(tlv_len+4); /* Type & Length fields not included */
5475b0fe478SBruce M Simpson }
5485b0fe478SBruce M Simpson 
5495b0fe478SBruce M Simpson void
ldp_print(netdissect_options * ndo,const u_char * pptr,u_int len)5503c602fabSXin LI ldp_print(netdissect_options *ndo,
551ee67461eSJoseph Mingrone           const u_char *pptr, u_int len)
5528bdc5a62SPatrick Kelsey {
55339e421e8SCy Schubert     u_int processed;
554ee67461eSJoseph Mingrone 
555ee67461eSJoseph Mingrone     ndo->ndo_protocol = "ldp";
556f4d0c64aSSam Leffler     while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) {
5578bdc5a62SPatrick Kelsey         processed = ldp_pdu_print(ndo, pptr);
558f4d0c64aSSam Leffler         if (processed == 0)
559f4d0c64aSSam Leffler             return;
56039e421e8SCy Schubert         if (len < processed) {
561ee67461eSJoseph Mingrone             ND_PRINT(" [remaining length %u < %u]", len, processed);
562ee67461eSJoseph Mingrone             nd_print_invalid(ndo);
56339e421e8SCy Schubert             break;
56439e421e8SCy Schubert         }
565f4d0c64aSSam Leffler         len -= processed;
566f4d0c64aSSam Leffler         pptr += processed;
567f4d0c64aSSam Leffler     }
568f4d0c64aSSam Leffler }
569f4d0c64aSSam Leffler 
57039e421e8SCy Schubert static u_int
ldp_pdu_print(netdissect_options * ndo,const u_char * pptr)5718bdc5a62SPatrick Kelsey ldp_pdu_print(netdissect_options *ndo,
572ee67461eSJoseph Mingrone               const u_char *pptr)
5738bdc5a62SPatrick Kelsey {
5745b0fe478SBruce M Simpson     const struct ldp_common_header *ldp_com_header;
5755b0fe478SBruce M Simpson     const struct ldp_msg_header *ldp_msg_header;
5765b0fe478SBruce M Simpson     const u_char *tptr,*msg_tptr;
5775b0fe478SBruce M Simpson     u_short tlen;
578ee67461eSJoseph Mingrone     u_short pdu_len,msg_len,msg_type;
579ee67461eSJoseph Mingrone     u_int msg_tlen;
5805b0fe478SBruce M Simpson     int hexdump,processed;
5815b0fe478SBruce M Simpson 
5825b0fe478SBruce M Simpson     ldp_com_header = (const struct ldp_common_header *)pptr;
583ee67461eSJoseph Mingrone     ND_TCHECK_SIZE(ldp_com_header);
5845b0fe478SBruce M Simpson 
5855b0fe478SBruce M Simpson     /*
5865b0fe478SBruce M Simpson      * Sanity checking of the header.
5875b0fe478SBruce M Simpson      */
588ee67461eSJoseph Mingrone     if (GET_BE_U_2(ldp_com_header->version) != LDP_VERSION) {
589ee67461eSJoseph Mingrone 	ND_PRINT("%sLDP version %u packet not supported",
5903c602fabSXin LI                (ndo->ndo_vflag < 1) ? "" : "\n\t",
591ee67461eSJoseph Mingrone                GET_BE_U_2(ldp_com_header->version));
592f4d0c64aSSam Leffler 	return 0;
5935b0fe478SBruce M Simpson     }
5945b0fe478SBruce M Simpson 
595ee67461eSJoseph Mingrone     pdu_len = GET_BE_U_2(ldp_com_header->pdu_length);
596ee67461eSJoseph Mingrone     if (pdu_len < sizeof(struct ldp_common_header)-4) {
5978bdc5a62SPatrick Kelsey         /* length too short */
598ee67461eSJoseph Mingrone         ND_PRINT("%sLDP, pdu-length: %u (too short, < %zu)",
5998bdc5a62SPatrick Kelsey                  (ndo->ndo_vflag < 1) ? "" : "\n\t",
6008bdc5a62SPatrick Kelsey                  pdu_len,
601ee67461eSJoseph Mingrone                  sizeof(struct ldp_common_header)-4);
6028bdc5a62SPatrick Kelsey         return 0;
6038bdc5a62SPatrick Kelsey     }
6048bdc5a62SPatrick Kelsey 
6058bdc5a62SPatrick Kelsey     /* print the LSR-ID, label-space & length */
606ee67461eSJoseph Mingrone     ND_PRINT("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u",
6073c602fabSXin LI            (ndo->ndo_vflag < 1) ? "" : "\n\t",
608ee67461eSJoseph Mingrone            GET_IPADDR_STRING(ldp_com_header->lsr_id),
609ee67461eSJoseph Mingrone            GET_BE_U_2(ldp_com_header->label_space),
610ee67461eSJoseph Mingrone            pdu_len);
6115b0fe478SBruce M Simpson 
6125b0fe478SBruce M Simpson     /* bail out if non-verbose */
6133c602fabSXin LI     if (ndo->ndo_vflag < 1)
614f4d0c64aSSam Leffler         return 0;
6155b0fe478SBruce M Simpson 
6165b0fe478SBruce M Simpson     /* ok they seem to want to know everything - lets fully decode it */
617ee67461eSJoseph Mingrone     tptr = pptr + sizeof(struct ldp_common_header);
618ee67461eSJoseph Mingrone     tlen = pdu_len - (sizeof(struct ldp_common_header)-4);	/* Type & Length fields not included */
6195b0fe478SBruce M Simpson 
6205b0fe478SBruce M Simpson     while(tlen>0) {
6215b0fe478SBruce M Simpson         /* did we capture enough for fully decoding the msg header ? */
622ee67461eSJoseph Mingrone         ND_TCHECK_LEN(tptr, sizeof(struct ldp_msg_header));
6235b0fe478SBruce M Simpson 
6245b0fe478SBruce M Simpson         ldp_msg_header = (const struct ldp_msg_header *)tptr;
625ee67461eSJoseph Mingrone         msg_len=GET_BE_U_2(ldp_msg_header->length);
626ee67461eSJoseph Mingrone         msg_type=LDP_MASK_MSG_TYPE(GET_BE_U_2(ldp_msg_header->type));
6275b0fe478SBruce M Simpson 
6288bdc5a62SPatrick Kelsey         if (msg_len < sizeof(struct ldp_msg_header)-4) {
6298bdc5a62SPatrick Kelsey             /* length too short */
6308bdc5a62SPatrick Kelsey             /* FIXME vendor private / experimental check */
631ee67461eSJoseph Mingrone             ND_PRINT("\n\t  %s Message (0x%04x), length: %u (too short, < %zu)",
6328bdc5a62SPatrick Kelsey                      tok2str(ldp_msg_values,
6338bdc5a62SPatrick Kelsey                              "Unknown",
6348bdc5a62SPatrick Kelsey                              msg_type),
6358bdc5a62SPatrick Kelsey                      msg_type,
6368bdc5a62SPatrick Kelsey                      msg_len,
637ee67461eSJoseph Mingrone                      sizeof(struct ldp_msg_header)-4);
6388bdc5a62SPatrick Kelsey             return 0;
6398bdc5a62SPatrick Kelsey         }
6408bdc5a62SPatrick Kelsey 
6415b0fe478SBruce M Simpson         /* FIXME vendor private / experimental check */
642ee67461eSJoseph Mingrone         ND_PRINT("\n\t  %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]",
6435b0fe478SBruce M Simpson                tok2str(ldp_msg_values,
6445b0fe478SBruce M Simpson                        "Unknown",
6455b0fe478SBruce M Simpson                        msg_type),
6465b0fe478SBruce M Simpson                msg_type,
6475b0fe478SBruce M Simpson                msg_len,
648ee67461eSJoseph Mingrone                GET_BE_U_4(ldp_msg_header->id),
649ee67461eSJoseph Mingrone                LDP_MASK_U_BIT(GET_BE_U_2(ldp_msg_header->type)) ? "continue processing" : "ignore");
6505b0fe478SBruce M Simpson 
6515b0fe478SBruce M Simpson         msg_tptr=tptr+sizeof(struct ldp_msg_header);
6528bdc5a62SPatrick Kelsey         msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */
6535b0fe478SBruce M Simpson 
6545b0fe478SBruce M Simpson         /* did we capture enough for fully decoding the message ? */
655ee67461eSJoseph Mingrone         ND_TCHECK_LEN(tptr, msg_len);
6565b0fe478SBruce M Simpson         hexdump=FALSE;
6575b0fe478SBruce M Simpson 
6585b0fe478SBruce M Simpson         switch(msg_type) {
6595b0fe478SBruce M Simpson 
6601de50e9fSSam Leffler         case LDP_MSG_NOTIF:
6615b0fe478SBruce M Simpson         case LDP_MSG_HELLO:
6621de50e9fSSam Leffler         case LDP_MSG_INIT:
6631de50e9fSSam Leffler         case LDP_MSG_KEEPALIVE:
6641de50e9fSSam Leffler         case LDP_MSG_ADDRESS:
6651de50e9fSSam Leffler         case LDP_MSG_LABEL_MAPPING:
666b5bfcb5dSMax Laier         case LDP_MSG_ADDRESS_WITHDRAW:
667b5bfcb5dSMax Laier         case LDP_MSG_LABEL_WITHDRAW:
6685b0fe478SBruce M Simpson             while(msg_tlen >= 4) {
6698bdc5a62SPatrick Kelsey                 processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen);
6705b0fe478SBruce M Simpson                 if (processed == 0)
6715b0fe478SBruce M Simpson                     break;
6725b0fe478SBruce M Simpson                 msg_tlen-=processed;
6735b0fe478SBruce M Simpson                 msg_tptr+=processed;
6745b0fe478SBruce M Simpson             }
6755b0fe478SBruce M Simpson             break;
6765b0fe478SBruce M Simpson 
6775b0fe478SBruce M Simpson         /*
6785b0fe478SBruce M Simpson          *  FIXME those are the defined messages that lack a decoder
6795b0fe478SBruce M Simpson          *  you are welcome to contribute code ;-)
6805b0fe478SBruce M Simpson          */
6815b0fe478SBruce M Simpson 
6825b0fe478SBruce M Simpson         case LDP_MSG_LABEL_REQUEST:
6835b0fe478SBruce M Simpson         case LDP_MSG_LABEL_RELEASE:
6845b0fe478SBruce M Simpson         case LDP_MSG_LABEL_ABORT_REQUEST:
6855b0fe478SBruce M Simpson 
6865b0fe478SBruce M Simpson         default:
6873c602fabSXin LI             if (ndo->ndo_vflag <= 1)
6883c602fabSXin LI                 print_unknown_data(ndo, msg_tptr, "\n\t  ", msg_tlen);
6895b0fe478SBruce M Simpson             break;
6905b0fe478SBruce M Simpson         }
6915b0fe478SBruce M Simpson         /* do we want to see an additionally hexdump ? */
6923c602fabSXin LI         if (ndo->ndo_vflag > 1 || hexdump==TRUE)
6933c602fabSXin LI             print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t  ",
6945b0fe478SBruce M Simpson                                msg_len);
6955b0fe478SBruce M Simpson 
6961de50e9fSSam Leffler         tptr += msg_len+4;
6971de50e9fSSam Leffler         tlen -= msg_len+4;
6985b0fe478SBruce M Simpson     }
699f4d0c64aSSam Leffler     return pdu_len+4;
7005b0fe478SBruce M Simpson trunc:
701ee67461eSJoseph Mingrone     nd_trunc_longjmp(ndo);
7025b0fe478SBruce M Simpson }
703