xref: /minix3/external/bsd/tcpdump/dist/print-ldp.c (revision b636d99d91c3d54204248f643c14627405d4afd1)
1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
3*b636d99dSDavid van Moolenbroek  * modification, are permitted provided that: (1) source code
4*b636d99dSDavid van Moolenbroek  * distributions retain the above copyright notice and this paragraph
5*b636d99dSDavid van Moolenbroek  * in its entirety, and (2) distributions including binary code include
6*b636d99dSDavid van Moolenbroek  * the above copyright notice and this paragraph in its entirety in
7*b636d99dSDavid van Moolenbroek  * the documentation or other materials provided with the distribution.
8*b636d99dSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9*b636d99dSDavid van Moolenbroek  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10*b636d99dSDavid van Moolenbroek  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11*b636d99dSDavid van Moolenbroek  * FOR A PARTICULAR PURPOSE.
12*b636d99dSDavid van Moolenbroek  *
13*b636d99dSDavid van Moolenbroek  * Original code by Hannes Gredler (hannes@juniper.net)
14*b636d99dSDavid van Moolenbroek  *  and Steinar Haug (sthaug@nethelp.no)
15*b636d99dSDavid van Moolenbroek  */
16*b636d99dSDavid van Moolenbroek 
17*b636d99dSDavid van Moolenbroek #include <sys/cdefs.h>
18*b636d99dSDavid van Moolenbroek #ifndef lint
19*b636d99dSDavid van Moolenbroek __RCSID("$NetBSD: print-ldp.c,v 1.6 2015/03/31 21:59:35 christos Exp $");
20*b636d99dSDavid van Moolenbroek #endif
21*b636d99dSDavid van Moolenbroek 
22*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
23*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
24*b636d99dSDavid van Moolenbroek #include "config.h"
25*b636d99dSDavid van Moolenbroek #endif
26*b636d99dSDavid van Moolenbroek 
27*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
28*b636d99dSDavid van Moolenbroek 
29*b636d99dSDavid van Moolenbroek #include "interface.h"
30*b636d99dSDavid van Moolenbroek #include "extract.h"
31*b636d99dSDavid van Moolenbroek #include "addrtoname.h"
32*b636d99dSDavid van Moolenbroek 
33*b636d99dSDavid van Moolenbroek #include "l2vpn.h"
34*b636d99dSDavid van Moolenbroek #include "af.h"
35*b636d99dSDavid van Moolenbroek 
36*b636d99dSDavid van Moolenbroek /*
37*b636d99dSDavid van Moolenbroek  * ldp common header
38*b636d99dSDavid van Moolenbroek  *
39*b636d99dSDavid van Moolenbroek  *  0                   1                   2                   3
40*b636d99dSDavid van Moolenbroek  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
41*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42*b636d99dSDavid van Moolenbroek  * |  Version                      |         PDU Length            |
43*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44*b636d99dSDavid van Moolenbroek  * |                         LDP Identifier                        |
45*b636d99dSDavid van Moolenbroek  * +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46*b636d99dSDavid van Moolenbroek  * |                               |
47*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48*b636d99dSDavid van Moolenbroek  *
49*b636d99dSDavid van Moolenbroek  */
50*b636d99dSDavid van Moolenbroek 
51*b636d99dSDavid van Moolenbroek struct ldp_common_header {
52*b636d99dSDavid van Moolenbroek     uint8_t version[2];
53*b636d99dSDavid van Moolenbroek     uint8_t pdu_length[2];
54*b636d99dSDavid van Moolenbroek     uint8_t lsr_id[4];
55*b636d99dSDavid van Moolenbroek     uint8_t label_space[2];
56*b636d99dSDavid van Moolenbroek };
57*b636d99dSDavid van Moolenbroek 
58*b636d99dSDavid van Moolenbroek #define LDP_VERSION 1
59*b636d99dSDavid van Moolenbroek 
60*b636d99dSDavid van Moolenbroek /*
61*b636d99dSDavid van Moolenbroek  * ldp message header
62*b636d99dSDavid van Moolenbroek  *
63*b636d99dSDavid van Moolenbroek  *  0                   1                   2                   3
64*b636d99dSDavid van Moolenbroek  *  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
65*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66*b636d99dSDavid van Moolenbroek  * |U|   Message Type              |      Message Length           |
67*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68*b636d99dSDavid van Moolenbroek  * |                     Message ID                                |
69*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70*b636d99dSDavid van Moolenbroek  * |                                                               |
71*b636d99dSDavid van Moolenbroek  * +                                                               +
72*b636d99dSDavid van Moolenbroek  * |                     Mandatory Parameters                      |
73*b636d99dSDavid van Moolenbroek  * +                                                               +
74*b636d99dSDavid van Moolenbroek  * |                                                               |
75*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76*b636d99dSDavid van Moolenbroek  * |                                                               |
77*b636d99dSDavid van Moolenbroek  * +                                                               +
78*b636d99dSDavid van Moolenbroek  * |                     Optional Parameters                       |
79*b636d99dSDavid van Moolenbroek  * +                                                               +
80*b636d99dSDavid van Moolenbroek  * |                                                               |
81*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82*b636d99dSDavid van Moolenbroek  */
83*b636d99dSDavid van Moolenbroek 
84*b636d99dSDavid van Moolenbroek struct ldp_msg_header {
85*b636d99dSDavid van Moolenbroek     uint8_t type[2];
86*b636d99dSDavid van Moolenbroek     uint8_t length[2];
87*b636d99dSDavid van Moolenbroek     uint8_t id[4];
88*b636d99dSDavid van Moolenbroek };
89*b636d99dSDavid van Moolenbroek 
90*b636d99dSDavid van Moolenbroek #define	LDP_MASK_MSG_TYPE(x)  ((x)&0x7fff)
91*b636d99dSDavid van Moolenbroek #define	LDP_MASK_U_BIT(x)     ((x)&0x8000)
92*b636d99dSDavid van Moolenbroek 
93*b636d99dSDavid van Moolenbroek #define	LDP_MSG_NOTIF                0x0001
94*b636d99dSDavid van Moolenbroek #define	LDP_MSG_HELLO                0x0100
95*b636d99dSDavid van Moolenbroek #define	LDP_MSG_INIT                 0x0200
96*b636d99dSDavid van Moolenbroek #define	LDP_MSG_KEEPALIVE            0x0201
97*b636d99dSDavid van Moolenbroek #define	LDP_MSG_ADDRESS              0x0300
98*b636d99dSDavid van Moolenbroek #define	LDP_MSG_ADDRESS_WITHDRAW     0x0301
99*b636d99dSDavid van Moolenbroek #define	LDP_MSG_LABEL_MAPPING        0x0400
100*b636d99dSDavid van Moolenbroek #define	LDP_MSG_LABEL_REQUEST        0x0401
101*b636d99dSDavid van Moolenbroek #define	LDP_MSG_LABEL_WITHDRAW       0x0402
102*b636d99dSDavid van Moolenbroek #define	LDP_MSG_LABEL_RELEASE        0x0403
103*b636d99dSDavid van Moolenbroek #define	LDP_MSG_LABEL_ABORT_REQUEST  0x0404
104*b636d99dSDavid van Moolenbroek 
105*b636d99dSDavid van Moolenbroek #define	LDP_VENDOR_PRIVATE_MIN       0x3e00
106*b636d99dSDavid van Moolenbroek #define	LDP_VENDOR_PRIVATE_MAX       0x3eff
107*b636d99dSDavid van Moolenbroek #define	LDP_EXPERIMENTAL_MIN         0x3f00
108*b636d99dSDavid van Moolenbroek #define	LDP_EXPERIMENTAL_MAX         0x3fff
109*b636d99dSDavid van Moolenbroek 
110*b636d99dSDavid van Moolenbroek static const struct tok ldp_msg_values[] = {
111*b636d99dSDavid van Moolenbroek     { LDP_MSG_NOTIF,	             "Notification" },
112*b636d99dSDavid van Moolenbroek     { LDP_MSG_HELLO,	             "Hello" },
113*b636d99dSDavid van Moolenbroek     { LDP_MSG_INIT,	             "Initialization" },
114*b636d99dSDavid van Moolenbroek     { LDP_MSG_KEEPALIVE,             "Keepalive" },
115*b636d99dSDavid van Moolenbroek     { LDP_MSG_ADDRESS,	             "Address" },
116*b636d99dSDavid van Moolenbroek     { LDP_MSG_ADDRESS_WITHDRAW,	     "Address Withdraw" },
117*b636d99dSDavid van Moolenbroek     { LDP_MSG_LABEL_MAPPING,	     "Label Mapping" },
118*b636d99dSDavid van Moolenbroek     { LDP_MSG_LABEL_REQUEST,	     "Label Request" },
119*b636d99dSDavid van Moolenbroek     { LDP_MSG_LABEL_WITHDRAW,	     "Label Withdraw" },
120*b636d99dSDavid van Moolenbroek     { LDP_MSG_LABEL_RELEASE,	     "Label Release" },
121*b636d99dSDavid van Moolenbroek     { LDP_MSG_LABEL_ABORT_REQUEST,   "Label Abort Request" },
122*b636d99dSDavid van Moolenbroek     { 0, NULL}
123*b636d99dSDavid van Moolenbroek };
124*b636d99dSDavid van Moolenbroek 
125*b636d99dSDavid van Moolenbroek #define	LDP_MASK_TLV_TYPE(x)  ((x)&0x3fff)
126*b636d99dSDavid van Moolenbroek #define	LDP_MASK_F_BIT(x) ((x)&0x4000)
127*b636d99dSDavid van Moolenbroek 
128*b636d99dSDavid van Moolenbroek #define	LDP_TLV_FEC                  0x0100
129*b636d99dSDavid van Moolenbroek #define	LDP_TLV_ADDRESS_LIST         0x0101
130*b636d99dSDavid van Moolenbroek #define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2
131*b636d99dSDavid van Moolenbroek #define	LDP_TLV_HOP_COUNT            0x0103
132*b636d99dSDavid van Moolenbroek #define	LDP_TLV_PATH_VECTOR          0x0104
133*b636d99dSDavid van Moolenbroek #define	LDP_TLV_GENERIC_LABEL        0x0200
134*b636d99dSDavid van Moolenbroek #define	LDP_TLV_ATM_LABEL            0x0201
135*b636d99dSDavid van Moolenbroek #define	LDP_TLV_FR_LABEL             0x0202
136*b636d99dSDavid van Moolenbroek #define	LDP_TLV_STATUS               0x0300
137*b636d99dSDavid van Moolenbroek #define	LDP_TLV_EXTD_STATUS          0x0301
138*b636d99dSDavid van Moolenbroek #define	LDP_TLV_RETURNED_PDU         0x0302
139*b636d99dSDavid van Moolenbroek #define	LDP_TLV_RETURNED_MSG         0x0303
140*b636d99dSDavid van Moolenbroek #define	LDP_TLV_COMMON_HELLO         0x0400
141*b636d99dSDavid van Moolenbroek #define	LDP_TLV_IPV4_TRANSPORT_ADDR  0x0401
142*b636d99dSDavid van Moolenbroek #define	LDP_TLV_CONFIG_SEQ_NUMBER    0x0402
143*b636d99dSDavid van Moolenbroek #define	LDP_TLV_IPV6_TRANSPORT_ADDR  0x0403
144*b636d99dSDavid van Moolenbroek #define	LDP_TLV_COMMON_SESSION       0x0500
145*b636d99dSDavid van Moolenbroek #define	LDP_TLV_ATM_SESSION_PARM     0x0501
146*b636d99dSDavid van Moolenbroek #define	LDP_TLV_FR_SESSION_PARM      0x0502
147*b636d99dSDavid van Moolenbroek #define LDP_TLV_FT_SESSION	     0x0503
148*b636d99dSDavid van Moolenbroek #define	LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600
149*b636d99dSDavid van Moolenbroek #define LDP_TLV_MTU                  0x0601 /* rfc 3988 */
150*b636d99dSDavid van Moolenbroek 
151*b636d99dSDavid van Moolenbroek static const struct tok ldp_tlv_values[] = {
152*b636d99dSDavid van Moolenbroek     { LDP_TLV_FEC,	             "FEC" },
153*b636d99dSDavid van Moolenbroek     { LDP_TLV_ADDRESS_LIST,          "Address List" },
154*b636d99dSDavid van Moolenbroek     { LDP_TLV_HOP_COUNT,             "Hop Count" },
155*b636d99dSDavid van Moolenbroek     { LDP_TLV_PATH_VECTOR,           "Path Vector" },
156*b636d99dSDavid van Moolenbroek     { LDP_TLV_GENERIC_LABEL,         "Generic Label" },
157*b636d99dSDavid van Moolenbroek     { LDP_TLV_ATM_LABEL,             "ATM Label" },
158*b636d99dSDavid van Moolenbroek     { LDP_TLV_FR_LABEL,              "Frame-Relay Label" },
159*b636d99dSDavid van Moolenbroek     { LDP_TLV_STATUS,                "Status" },
160*b636d99dSDavid van Moolenbroek     { LDP_TLV_EXTD_STATUS,           "Extended Status" },
161*b636d99dSDavid van Moolenbroek     { LDP_TLV_RETURNED_PDU,          "Returned PDU" },
162*b636d99dSDavid van Moolenbroek     { LDP_TLV_RETURNED_MSG,          "Returned Message" },
163*b636d99dSDavid van Moolenbroek     { LDP_TLV_COMMON_HELLO,          "Common Hello Parameters" },
164*b636d99dSDavid van Moolenbroek     { LDP_TLV_IPV4_TRANSPORT_ADDR,   "IPv4 Transport Address" },
165*b636d99dSDavid van Moolenbroek     { LDP_TLV_CONFIG_SEQ_NUMBER,     "Configuration Sequence Number" },
166*b636d99dSDavid van Moolenbroek     { LDP_TLV_IPV6_TRANSPORT_ADDR,   "IPv6 Transport Address" },
167*b636d99dSDavid van Moolenbroek     { LDP_TLV_COMMON_SESSION,        "Common Session Parameters" },
168*b636d99dSDavid van Moolenbroek     { LDP_TLV_ATM_SESSION_PARM,      "ATM Session Parameters" },
169*b636d99dSDavid van Moolenbroek     { LDP_TLV_FR_SESSION_PARM,       "Frame-Relay Session Parameters" },
170*b636d99dSDavid van Moolenbroek     { LDP_TLV_FT_SESSION,            "Fault-Tolerant Session Parameters" },
171*b636d99dSDavid van Moolenbroek     { LDP_TLV_LABEL_REQUEST_MSG_ID,  "Label Request Message ID" },
172*b636d99dSDavid van Moolenbroek     { LDP_TLV_MTU,                   "MTU" },
173*b636d99dSDavid van Moolenbroek     { 0, NULL}
174*b636d99dSDavid van Moolenbroek };
175*b636d99dSDavid van Moolenbroek 
176*b636d99dSDavid van Moolenbroek #define LDP_FEC_WILDCARD	0x01
177*b636d99dSDavid van Moolenbroek #define LDP_FEC_PREFIX		0x02
178*b636d99dSDavid van Moolenbroek #define LDP_FEC_HOSTADDRESS	0x03
179*b636d99dSDavid van Moolenbroek /* From RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */
180*b636d99dSDavid van Moolenbroek #define LDP_FEC_MARTINI_VC	0x80
181*b636d99dSDavid van Moolenbroek 
182*b636d99dSDavid van Moolenbroek static const struct tok ldp_fec_values[] = {
183*b636d99dSDavid van Moolenbroek     { LDP_FEC_WILDCARD,		"Wildcard" },
184*b636d99dSDavid van Moolenbroek     { LDP_FEC_PREFIX,		"Prefix" },
185*b636d99dSDavid van Moolenbroek     { LDP_FEC_HOSTADDRESS,	"Host address" },
186*b636d99dSDavid van Moolenbroek     { LDP_FEC_MARTINI_VC,	"Martini VC" },
187*b636d99dSDavid van Moolenbroek     { 0, NULL}
188*b636d99dSDavid van Moolenbroek };
189*b636d99dSDavid van Moolenbroek 
190*b636d99dSDavid van Moolenbroek #define LDP_FEC_MARTINI_IFPARM_MTU  0x01
191*b636d99dSDavid van Moolenbroek #define LDP_FEC_MARTINI_IFPARM_DESC 0x03
192*b636d99dSDavid van Moolenbroek #define LDP_FEC_MARTINI_IFPARM_VCCV 0x0c
193*b636d99dSDavid van Moolenbroek 
194*b636d99dSDavid van Moolenbroek static const struct tok ldp_fec_martini_ifparm_values[] = {
195*b636d99dSDavid van Moolenbroek     { LDP_FEC_MARTINI_IFPARM_MTU, "MTU" },
196*b636d99dSDavid van Moolenbroek     { LDP_FEC_MARTINI_IFPARM_DESC, "Description" },
197*b636d99dSDavid van Moolenbroek     { LDP_FEC_MARTINI_IFPARM_VCCV, "VCCV" },
198*b636d99dSDavid van Moolenbroek     { 0, NULL}
199*b636d99dSDavid van Moolenbroek };
200*b636d99dSDavid van Moolenbroek 
201*b636d99dSDavid van Moolenbroek /* draft-ietf-pwe3-vccv-04.txt */
202*b636d99dSDavid van Moolenbroek static const struct tok ldp_fec_martini_ifparm_vccv_cc_values[] = {
203*b636d99dSDavid van Moolenbroek     { 0x01, "PWE3 control word" },
204*b636d99dSDavid van Moolenbroek     { 0x02, "MPLS Router Alert Label" },
205*b636d99dSDavid van Moolenbroek     { 0x04, "MPLS inner label TTL = 1" },
206*b636d99dSDavid van Moolenbroek     { 0, NULL}
207*b636d99dSDavid van Moolenbroek };
208*b636d99dSDavid van Moolenbroek 
209*b636d99dSDavid van Moolenbroek /* draft-ietf-pwe3-vccv-04.txt */
210*b636d99dSDavid van Moolenbroek static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = {
211*b636d99dSDavid van Moolenbroek     { 0x01, "ICMP Ping" },
212*b636d99dSDavid van Moolenbroek     { 0x02, "LSP Ping" },
213*b636d99dSDavid van Moolenbroek     { 0x04, "BFD" },
214*b636d99dSDavid van Moolenbroek     { 0, NULL}
215*b636d99dSDavid van Moolenbroek };
216*b636d99dSDavid van Moolenbroek 
217*b636d99dSDavid van Moolenbroek static int ldp_pdu_print(netdissect_options *, register const u_char *);
218*b636d99dSDavid van Moolenbroek 
219*b636d99dSDavid van Moolenbroek /*
220*b636d99dSDavid van Moolenbroek  * ldp tlv header
221*b636d99dSDavid van Moolenbroek  *
222*b636d99dSDavid van Moolenbroek  *  0                   1                   2                   3
223*b636d99dSDavid van Moolenbroek  *  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
224*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
225*b636d99dSDavid van Moolenbroek  * |U|F|        Type               |            Length             |
226*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
227*b636d99dSDavid van Moolenbroek  * |                                                               |
228*b636d99dSDavid van Moolenbroek  * |                             Value                             |
229*b636d99dSDavid van Moolenbroek  * ~                                                               ~
230*b636d99dSDavid van Moolenbroek  * |                                                               |
231*b636d99dSDavid van Moolenbroek  * |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
232*b636d99dSDavid van Moolenbroek  * |                               |
233*b636d99dSDavid van Moolenbroek  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
234*b636d99dSDavid van Moolenbroek  */
235*b636d99dSDavid van Moolenbroek 
236*b636d99dSDavid van Moolenbroek #define TLV_TCHECK(minlen) \
237*b636d99dSDavid van Moolenbroek     ND_TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv;
238*b636d99dSDavid van Moolenbroek 
239*b636d99dSDavid van Moolenbroek static int
ldp_tlv_print(netdissect_options * ndo,register const u_char * tptr,u_short msg_tlen)240*b636d99dSDavid van Moolenbroek ldp_tlv_print(netdissect_options *ndo,
241*b636d99dSDavid van Moolenbroek               register const u_char *tptr,
242*b636d99dSDavid van Moolenbroek               u_short msg_tlen)
243*b636d99dSDavid van Moolenbroek {
244*b636d99dSDavid van Moolenbroek     struct ldp_tlv_header {
245*b636d99dSDavid van Moolenbroek         uint8_t type[2];
246*b636d99dSDavid van Moolenbroek         uint8_t length[2];
247*b636d99dSDavid van Moolenbroek     };
248*b636d99dSDavid van Moolenbroek 
249*b636d99dSDavid van Moolenbroek     const struct ldp_tlv_header *ldp_tlv_header;
250*b636d99dSDavid van Moolenbroek     u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags;
251*b636d99dSDavid van Moolenbroek     u_char fec_type;
252*b636d99dSDavid van Moolenbroek     u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx;
253*b636d99dSDavid van Moolenbroek     char buf[100];
254*b636d99dSDavid van Moolenbroek     int i;
255*b636d99dSDavid van Moolenbroek 
256*b636d99dSDavid van Moolenbroek     ldp_tlv_header = (const struct ldp_tlv_header *)tptr;
257*b636d99dSDavid van Moolenbroek     ND_TCHECK(*ldp_tlv_header);
258*b636d99dSDavid van Moolenbroek     tlv_len=EXTRACT_16BITS(ldp_tlv_header->length);
259*b636d99dSDavid van Moolenbroek     if (tlv_len + 4 > msg_tlen) {
260*b636d99dSDavid van Moolenbroek         ND_PRINT((ndo, "\n\t\t TLV contents go past end of message"));
261*b636d99dSDavid van Moolenbroek         return 0;
262*b636d99dSDavid van Moolenbroek     }
263*b636d99dSDavid van Moolenbroek     tlv_tlen=tlv_len;
264*b636d99dSDavid van Moolenbroek     tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type));
265*b636d99dSDavid van Moolenbroek 
266*b636d99dSDavid van Moolenbroek     /* FIXME vendor private / experimental check */
267*b636d99dSDavid van Moolenbroek     ND_PRINT((ndo, "\n\t    %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]",
268*b636d99dSDavid van Moolenbroek            tok2str(ldp_tlv_values,
269*b636d99dSDavid van Moolenbroek                    "Unknown",
270*b636d99dSDavid van Moolenbroek                    tlv_type),
271*b636d99dSDavid van Moolenbroek            tlv_type,
272*b636d99dSDavid van Moolenbroek            tlv_len,
273*b636d99dSDavid van Moolenbroek            LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore",
274*b636d99dSDavid van Moolenbroek            LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't"));
275*b636d99dSDavid van Moolenbroek 
276*b636d99dSDavid van Moolenbroek     tptr+=sizeof(struct ldp_tlv_header);
277*b636d99dSDavid van Moolenbroek 
278*b636d99dSDavid van Moolenbroek     switch(tlv_type) {
279*b636d99dSDavid van Moolenbroek 
280*b636d99dSDavid van Moolenbroek     case LDP_TLV_COMMON_HELLO:
281*b636d99dSDavid van Moolenbroek         TLV_TCHECK(4);
282*b636d99dSDavid van Moolenbroek         ND_PRINT((ndo, "\n\t      Hold Time: %us, Flags: [%s Hello%s]",
283*b636d99dSDavid van Moolenbroek                EXTRACT_16BITS(tptr),
284*b636d99dSDavid van Moolenbroek                (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link",
285*b636d99dSDavid van Moolenbroek                (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : ""));
286*b636d99dSDavid van Moolenbroek         break;
287*b636d99dSDavid van Moolenbroek 
288*b636d99dSDavid van Moolenbroek     case LDP_TLV_IPV4_TRANSPORT_ADDR:
289*b636d99dSDavid van Moolenbroek         TLV_TCHECK(4);
290*b636d99dSDavid van Moolenbroek         ND_PRINT((ndo, "\n\t      IPv4 Transport Address: %s", ipaddr_string(ndo, tptr)));
291*b636d99dSDavid van Moolenbroek         break;
292*b636d99dSDavid van Moolenbroek #ifdef INET6
293*b636d99dSDavid van Moolenbroek     case LDP_TLV_IPV6_TRANSPORT_ADDR:
294*b636d99dSDavid van Moolenbroek         TLV_TCHECK(16);
295*b636d99dSDavid van Moolenbroek         ND_PRINT((ndo, "\n\t      IPv6 Transport Address: %s", ip6addr_string(ndo, tptr)));
296*b636d99dSDavid van Moolenbroek         break;
297*b636d99dSDavid van Moolenbroek #endif
298*b636d99dSDavid van Moolenbroek     case LDP_TLV_CONFIG_SEQ_NUMBER:
299*b636d99dSDavid van Moolenbroek         TLV_TCHECK(4);
300*b636d99dSDavid van Moolenbroek         ND_PRINT((ndo, "\n\t      Sequence Number: %u", EXTRACT_32BITS(tptr)));
301*b636d99dSDavid van Moolenbroek         break;
302*b636d99dSDavid van Moolenbroek 
303*b636d99dSDavid van Moolenbroek     case LDP_TLV_ADDRESS_LIST:
304*b636d99dSDavid van Moolenbroek         TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN);
305*b636d99dSDavid van Moolenbroek 	af = EXTRACT_16BITS(tptr);
306*b636d99dSDavid van Moolenbroek 	tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
307*b636d99dSDavid van Moolenbroek         tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
308*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\n\t      Address Family: %s, addresses",
309*b636d99dSDavid van Moolenbroek                tok2str(af_values, "Unknown (%u)", af)));
310*b636d99dSDavid van Moolenbroek         switch (af) {
311*b636d99dSDavid van Moolenbroek         case AFNUM_INET:
312*b636d99dSDavid van Moolenbroek 	    while(tlv_tlen >= sizeof(struct in_addr)) {
313*b636d99dSDavid van Moolenbroek 		ND_TCHECK2(*tptr, sizeof(struct in_addr));
314*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " %s", ipaddr_string(ndo, tptr)));
315*b636d99dSDavid van Moolenbroek 		tlv_tlen-=sizeof(struct in_addr);
316*b636d99dSDavid van Moolenbroek 		tptr+=sizeof(struct in_addr);
317*b636d99dSDavid van Moolenbroek 	    }
318*b636d99dSDavid van Moolenbroek             break;
319*b636d99dSDavid van Moolenbroek #ifdef INET6
320*b636d99dSDavid van Moolenbroek         case AFNUM_INET6:
321*b636d99dSDavid van Moolenbroek 	    while(tlv_tlen >= sizeof(struct in6_addr)) {
322*b636d99dSDavid van Moolenbroek 		ND_TCHECK2(*tptr, sizeof(struct in6_addr));
323*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " %s", ip6addr_string(ndo, tptr)));
324*b636d99dSDavid van Moolenbroek 		tlv_tlen-=sizeof(struct in6_addr);
325*b636d99dSDavid van Moolenbroek 		tptr+=sizeof(struct in6_addr);
326*b636d99dSDavid van Moolenbroek 	    }
327*b636d99dSDavid van Moolenbroek             break;
328*b636d99dSDavid van Moolenbroek #endif
329*b636d99dSDavid van Moolenbroek         default:
330*b636d99dSDavid van Moolenbroek             /* unknown AF */
331*b636d99dSDavid van Moolenbroek             break;
332*b636d99dSDavid van Moolenbroek         }
333*b636d99dSDavid van Moolenbroek 	break;
334*b636d99dSDavid van Moolenbroek 
335*b636d99dSDavid van Moolenbroek     case LDP_TLV_COMMON_SESSION:
336*b636d99dSDavid van Moolenbroek 	TLV_TCHECK(8);
337*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\n\t      Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]",
338*b636d99dSDavid van Moolenbroek 	       EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2),
339*b636d99dSDavid van Moolenbroek 	       (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited",
340*b636d99dSDavid van Moolenbroek 	       (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled"
341*b636d99dSDavid van Moolenbroek 	       ));
342*b636d99dSDavid van Moolenbroek 	break;
343*b636d99dSDavid van Moolenbroek 
344*b636d99dSDavid van Moolenbroek     case LDP_TLV_FEC:
345*b636d99dSDavid van Moolenbroek         TLV_TCHECK(1);
346*b636d99dSDavid van Moolenbroek         fec_type = *tptr;
347*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\n\t      %s FEC (0x%02x)",
348*b636d99dSDavid van Moolenbroek 	       tok2str(ldp_fec_values, "Unknown", fec_type),
349*b636d99dSDavid van Moolenbroek 	       fec_type));
350*b636d99dSDavid van Moolenbroek 
351*b636d99dSDavid van Moolenbroek 	tptr+=1;
352*b636d99dSDavid van Moolenbroek 	tlv_tlen-=1;
353*b636d99dSDavid van Moolenbroek 	switch(fec_type) {
354*b636d99dSDavid van Moolenbroek 
355*b636d99dSDavid van Moolenbroek 	case LDP_FEC_WILDCARD:
356*b636d99dSDavid van Moolenbroek 	    break;
357*b636d99dSDavid van Moolenbroek 	case LDP_FEC_PREFIX:
358*b636d99dSDavid van Moolenbroek 	    TLV_TCHECK(2);
359*b636d99dSDavid van Moolenbroek 	    af = EXTRACT_16BITS(tptr);
360*b636d99dSDavid van Moolenbroek 	    tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
361*b636d99dSDavid van Moolenbroek 	    tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
362*b636d99dSDavid van Moolenbroek 	    if (af == AFNUM_INET) {
363*b636d99dSDavid van Moolenbroek 		i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf));
364*b636d99dSDavid van Moolenbroek 		if (i == -2)
365*b636d99dSDavid van Moolenbroek 		    goto trunc;
366*b636d99dSDavid van Moolenbroek 		if (i == -3)
367*b636d99dSDavid van Moolenbroek 		    ND_PRINT((ndo, ": IPv4 prefix (goes past end of TLV)"));
368*b636d99dSDavid van Moolenbroek 		else if (i == -1)
369*b636d99dSDavid van Moolenbroek 		    ND_PRINT((ndo, ": IPv4 prefix (invalid length)"));
370*b636d99dSDavid van Moolenbroek 		else
371*b636d99dSDavid van Moolenbroek 		    ND_PRINT((ndo, ": IPv4 prefix %s", buf));
372*b636d99dSDavid van Moolenbroek 	    }
373*b636d99dSDavid van Moolenbroek #ifdef INET6
374*b636d99dSDavid van Moolenbroek 	    else if (af == AFNUM_INET6) {
375*b636d99dSDavid van Moolenbroek 		i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf));
376*b636d99dSDavid van Moolenbroek 		if (i == -2)
377*b636d99dSDavid van Moolenbroek 		    goto trunc;
378*b636d99dSDavid van Moolenbroek 		if (i == -3)
379*b636d99dSDavid van Moolenbroek 		    ND_PRINT((ndo, ": IPv4 prefix (goes past end of TLV)"));
380*b636d99dSDavid van Moolenbroek 		else if (i == -1)
381*b636d99dSDavid van Moolenbroek 		    ND_PRINT((ndo, ": IPv6 prefix (invalid length)"));
382*b636d99dSDavid van Moolenbroek 		else
383*b636d99dSDavid van Moolenbroek 		    ND_PRINT((ndo, ": IPv6 prefix %s", buf));
384*b636d99dSDavid van Moolenbroek 	    }
385*b636d99dSDavid van Moolenbroek #endif
386*b636d99dSDavid van Moolenbroek 	    else
387*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, ": Address family %u prefix", af));
388*b636d99dSDavid van Moolenbroek 	    break;
389*b636d99dSDavid van Moolenbroek 	case LDP_FEC_HOSTADDRESS:
390*b636d99dSDavid van Moolenbroek 	    break;
391*b636d99dSDavid van Moolenbroek 	case LDP_FEC_MARTINI_VC:
392*b636d99dSDavid van Moolenbroek             /*
393*b636d99dSDavid van Moolenbroek 	     * According to RFC 4908, the VC info Length field can be zero,
394*b636d99dSDavid van Moolenbroek 	     * in which case not only are there no interface parameters,
395*b636d99dSDavid van Moolenbroek 	     * there's no VC ID.
396*b636d99dSDavid van Moolenbroek 	     */
397*b636d99dSDavid van Moolenbroek             TLV_TCHECK(7);
398*b636d99dSDavid van Moolenbroek             vc_info_len = *(tptr+2);
399*b636d99dSDavid van Moolenbroek 
400*b636d99dSDavid van Moolenbroek             if (vc_info_len == 0) {
401*b636d99dSDavid van Moolenbroek                 ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-info-length: %u",
402*b636d99dSDavid van Moolenbroek                        tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
403*b636d99dSDavid van Moolenbroek                        EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
404*b636d99dSDavid van Moolenbroek                        EXTRACT_32BITS(tptr+3),
405*b636d99dSDavid van Moolenbroek                        vc_info_len));
406*b636d99dSDavid van Moolenbroek                 break;
407*b636d99dSDavid van Moolenbroek             }
408*b636d99dSDavid van Moolenbroek 
409*b636d99dSDavid van Moolenbroek             /* Make sure we have the VC ID as well */
410*b636d99dSDavid van Moolenbroek             TLV_TCHECK(11);
411*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u",
412*b636d99dSDavid van Moolenbroek 		   tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
413*b636d99dSDavid van Moolenbroek 		   EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
414*b636d99dSDavid van Moolenbroek                    EXTRACT_32BITS(tptr+3),
415*b636d99dSDavid van Moolenbroek 		   EXTRACT_32BITS(tptr+7),
416*b636d99dSDavid van Moolenbroek                    vc_info_len));
417*b636d99dSDavid van Moolenbroek             if (vc_info_len < 4) {
418*b636d99dSDavid van Moolenbroek                 /* minimum 4, for the VC ID */
419*b636d99dSDavid van Moolenbroek                 ND_PRINT((ndo, " (invalid, < 4"));
420*b636d99dSDavid van Moolenbroek                 return(tlv_len+4); /* Type & Length fields not included */
421*b636d99dSDavid van Moolenbroek 	    }
422*b636d99dSDavid van Moolenbroek             vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */
423*b636d99dSDavid van Moolenbroek 
424*b636d99dSDavid van Moolenbroek             /* Skip past the fixed information and the VC ID */
425*b636d99dSDavid van Moolenbroek             tptr+=11;
426*b636d99dSDavid van Moolenbroek             tlv_tlen-=11;
427*b636d99dSDavid van Moolenbroek             TLV_TCHECK(vc_info_len);
428*b636d99dSDavid van Moolenbroek 
429*b636d99dSDavid van Moolenbroek             while (vc_info_len > 2) {
430*b636d99dSDavid van Moolenbroek                 vc_info_tlv_type = *tptr;
431*b636d99dSDavid van Moolenbroek                 vc_info_tlv_len = *(tptr+1);
432*b636d99dSDavid van Moolenbroek                 if (vc_info_tlv_len < 2)
433*b636d99dSDavid van Moolenbroek                     break;
434*b636d99dSDavid van Moolenbroek                 if (vc_info_len < vc_info_tlv_len)
435*b636d99dSDavid van Moolenbroek                     break;
436*b636d99dSDavid van Moolenbroek 
437*b636d99dSDavid van Moolenbroek                 ND_PRINT((ndo, "\n\t\tInterface Parameter: %s (0x%02x), len %u",
438*b636d99dSDavid van Moolenbroek                        tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type),
439*b636d99dSDavid van Moolenbroek                        vc_info_tlv_type,
440*b636d99dSDavid van Moolenbroek                        vc_info_tlv_len));
441*b636d99dSDavid van Moolenbroek 
442*b636d99dSDavid van Moolenbroek                 switch(vc_info_tlv_type) {
443*b636d99dSDavid van Moolenbroek                 case LDP_FEC_MARTINI_IFPARM_MTU:
444*b636d99dSDavid van Moolenbroek                     ND_PRINT((ndo, ": %u", EXTRACT_16BITS(tptr+2)));
445*b636d99dSDavid van Moolenbroek                     break;
446*b636d99dSDavid van Moolenbroek 
447*b636d99dSDavid van Moolenbroek                 case LDP_FEC_MARTINI_IFPARM_DESC:
448*b636d99dSDavid van Moolenbroek                     ND_PRINT((ndo, ": "));
449*b636d99dSDavid van Moolenbroek                     for (idx = 2; idx < vc_info_tlv_len; idx++)
450*b636d99dSDavid van Moolenbroek                         safeputchar(ndo, *(tptr + idx));
451*b636d99dSDavid van Moolenbroek                     break;
452*b636d99dSDavid van Moolenbroek 
453*b636d99dSDavid van Moolenbroek                 case LDP_FEC_MARTINI_IFPARM_VCCV:
454*b636d99dSDavid van Moolenbroek                     ND_PRINT((ndo, "\n\t\t  Control Channels (0x%02x) = [%s]",
455*b636d99dSDavid van Moolenbroek                            *(tptr+2),
456*b636d99dSDavid van Moolenbroek                            bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", *(tptr+2))));
457*b636d99dSDavid van Moolenbroek                     ND_PRINT((ndo, "\n\t\t  CV Types (0x%02x) = [%s]",
458*b636d99dSDavid van Moolenbroek                            *(tptr+3),
459*b636d99dSDavid van Moolenbroek                            bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", *(tptr+3))));
460*b636d99dSDavid van Moolenbroek                     break;
461*b636d99dSDavid van Moolenbroek 
462*b636d99dSDavid van Moolenbroek                 default:
463*b636d99dSDavid van Moolenbroek                     print_unknown_data(ndo, tptr+2, "\n\t\t  ", vc_info_tlv_len-2);
464*b636d99dSDavid van Moolenbroek                     break;
465*b636d99dSDavid van Moolenbroek                 }
466*b636d99dSDavid van Moolenbroek 
467*b636d99dSDavid van Moolenbroek                 vc_info_len -= vc_info_tlv_len;
468*b636d99dSDavid van Moolenbroek                 tptr += vc_info_tlv_len;
469*b636d99dSDavid van Moolenbroek             }
470*b636d99dSDavid van Moolenbroek 	    break;
471*b636d99dSDavid van Moolenbroek 	}
472*b636d99dSDavid van Moolenbroek 
473*b636d99dSDavid van Moolenbroek 	break;
474*b636d99dSDavid van Moolenbroek 
475*b636d99dSDavid van Moolenbroek     case LDP_TLV_GENERIC_LABEL:
476*b636d99dSDavid van Moolenbroek 	TLV_TCHECK(4);
477*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\n\t      Label: %u", EXTRACT_32BITS(tptr) & 0xfffff));
478*b636d99dSDavid van Moolenbroek 	break;
479*b636d99dSDavid van Moolenbroek 
480*b636d99dSDavid van Moolenbroek     case LDP_TLV_STATUS:
481*b636d99dSDavid van Moolenbroek 	TLV_TCHECK(8);
482*b636d99dSDavid van Moolenbroek 	ui = EXTRACT_32BITS(tptr);
483*b636d99dSDavid van Moolenbroek 	tptr+=4;
484*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\n\t      Status: 0x%02x, Flags: [%s and %s forward]",
485*b636d99dSDavid van Moolenbroek 	       ui&0x3fffffff,
486*b636d99dSDavid van Moolenbroek 	       ui&0x80000000 ? "Fatal error" : "Advisory Notification",
487*b636d99dSDavid van Moolenbroek 	       ui&0x40000000 ? "do" : "don't"));
488*b636d99dSDavid van Moolenbroek 	ui = EXTRACT_32BITS(tptr);
489*b636d99dSDavid van Moolenbroek 	tptr+=4;
490*b636d99dSDavid van Moolenbroek 	if (ui)
491*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, ", causing Message ID: 0x%08x", ui));
492*b636d99dSDavid van Moolenbroek 	break;
493*b636d99dSDavid van Moolenbroek 
494*b636d99dSDavid van Moolenbroek     case LDP_TLV_FT_SESSION:
495*b636d99dSDavid van Moolenbroek 	TLV_TCHECK(8);
496*b636d99dSDavid van Moolenbroek 	ft_flags = EXTRACT_16BITS(tptr);
497*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\n\t      Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]",
498*b636d99dSDavid van Moolenbroek 	       ft_flags&0x8000 ? "" : "No ",
499*b636d99dSDavid van Moolenbroek 	       ft_flags&0x8 ? "" : "Don't ",
500*b636d99dSDavid van Moolenbroek 	       ft_flags&0x4 ? "" : "No ",
501*b636d99dSDavid van Moolenbroek 	       ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels",
502*b636d99dSDavid van Moolenbroek 	       ft_flags&0x1 ? "" : "Don't "));
503*b636d99dSDavid van Moolenbroek 	tptr+=4;
504*b636d99dSDavid van Moolenbroek 	ui = EXTRACT_32BITS(tptr);
505*b636d99dSDavid van Moolenbroek 	if (ui)
506*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, ", Reconnect Timeout: %ums", ui));
507*b636d99dSDavid van Moolenbroek 	tptr+=4;
508*b636d99dSDavid van Moolenbroek 	ui = EXTRACT_32BITS(tptr);
509*b636d99dSDavid van Moolenbroek 	if (ui)
510*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, ", Recovery Time: %ums", ui));
511*b636d99dSDavid van Moolenbroek 	break;
512*b636d99dSDavid van Moolenbroek 
513*b636d99dSDavid van Moolenbroek     case LDP_TLV_MTU:
514*b636d99dSDavid van Moolenbroek 	TLV_TCHECK(2);
515*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\n\t      MTU: %u", EXTRACT_16BITS(tptr)));
516*b636d99dSDavid van Moolenbroek 	break;
517*b636d99dSDavid van Moolenbroek 
518*b636d99dSDavid van Moolenbroek 
519*b636d99dSDavid van Moolenbroek     /*
520*b636d99dSDavid van Moolenbroek      *  FIXME those are the defined TLVs that lack a decoder
521*b636d99dSDavid van Moolenbroek      *  you are welcome to contribute code ;-)
522*b636d99dSDavid van Moolenbroek      */
523*b636d99dSDavid van Moolenbroek 
524*b636d99dSDavid van Moolenbroek     case LDP_TLV_HOP_COUNT:
525*b636d99dSDavid van Moolenbroek     case LDP_TLV_PATH_VECTOR:
526*b636d99dSDavid van Moolenbroek     case LDP_TLV_ATM_LABEL:
527*b636d99dSDavid van Moolenbroek     case LDP_TLV_FR_LABEL:
528*b636d99dSDavid van Moolenbroek     case LDP_TLV_EXTD_STATUS:
529*b636d99dSDavid van Moolenbroek     case LDP_TLV_RETURNED_PDU:
530*b636d99dSDavid van Moolenbroek     case LDP_TLV_RETURNED_MSG:
531*b636d99dSDavid van Moolenbroek     case LDP_TLV_ATM_SESSION_PARM:
532*b636d99dSDavid van Moolenbroek     case LDP_TLV_FR_SESSION_PARM:
533*b636d99dSDavid van Moolenbroek     case LDP_TLV_LABEL_REQUEST_MSG_ID:
534*b636d99dSDavid van Moolenbroek 
535*b636d99dSDavid van Moolenbroek     default:
536*b636d99dSDavid van Moolenbroek         if (ndo->ndo_vflag <= 1)
537*b636d99dSDavid van Moolenbroek             print_unknown_data(ndo, tptr, "\n\t      ", tlv_tlen);
538*b636d99dSDavid van Moolenbroek         break;
539*b636d99dSDavid van Moolenbroek     }
540*b636d99dSDavid van Moolenbroek     return(tlv_len+4); /* Type & Length fields not included */
541*b636d99dSDavid van Moolenbroek 
542*b636d99dSDavid van Moolenbroek trunc:
543*b636d99dSDavid van Moolenbroek     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
544*b636d99dSDavid van Moolenbroek     return 0;
545*b636d99dSDavid van Moolenbroek 
546*b636d99dSDavid van Moolenbroek badtlv:
547*b636d99dSDavid van Moolenbroek     ND_PRINT((ndo, "\n\t\t TLV contents go past end of TLV"));
548*b636d99dSDavid van Moolenbroek     return(tlv_len+4); /* Type & Length fields not included */
549*b636d99dSDavid van Moolenbroek }
550*b636d99dSDavid van Moolenbroek 
551*b636d99dSDavid van Moolenbroek void
ldp_print(netdissect_options * ndo,register const u_char * pptr,register u_int len)552*b636d99dSDavid van Moolenbroek ldp_print(netdissect_options *ndo,
553*b636d99dSDavid van Moolenbroek           register const u_char *pptr, register u_int len)
554*b636d99dSDavid van Moolenbroek {
555*b636d99dSDavid van Moolenbroek     int processed;
556*b636d99dSDavid van Moolenbroek     while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) {
557*b636d99dSDavid van Moolenbroek         processed = ldp_pdu_print(ndo, pptr);
558*b636d99dSDavid van Moolenbroek         if (processed == 0)
559*b636d99dSDavid van Moolenbroek             return;
560*b636d99dSDavid van Moolenbroek         len -= processed;
561*b636d99dSDavid van Moolenbroek         pptr += processed;
562*b636d99dSDavid van Moolenbroek     }
563*b636d99dSDavid van Moolenbroek }
564*b636d99dSDavid van Moolenbroek 
565*b636d99dSDavid van Moolenbroek static int
ldp_pdu_print(netdissect_options * ndo,register const u_char * pptr)566*b636d99dSDavid van Moolenbroek ldp_pdu_print(netdissect_options *ndo,
567*b636d99dSDavid van Moolenbroek               register const u_char *pptr)
568*b636d99dSDavid van Moolenbroek {
569*b636d99dSDavid van Moolenbroek     const struct ldp_common_header *ldp_com_header;
570*b636d99dSDavid van Moolenbroek     const struct ldp_msg_header *ldp_msg_header;
571*b636d99dSDavid van Moolenbroek     const u_char *tptr,*msg_tptr;
572*b636d99dSDavid van Moolenbroek     u_short tlen;
573*b636d99dSDavid van Moolenbroek     u_short pdu_len,msg_len,msg_type,msg_tlen;
574*b636d99dSDavid van Moolenbroek     int hexdump,processed;
575*b636d99dSDavid van Moolenbroek 
576*b636d99dSDavid van Moolenbroek     ldp_com_header = (const struct ldp_common_header *)pptr;
577*b636d99dSDavid van Moolenbroek     ND_TCHECK(*ldp_com_header);
578*b636d99dSDavid van Moolenbroek 
579*b636d99dSDavid van Moolenbroek     /*
580*b636d99dSDavid van Moolenbroek      * Sanity checking of the header.
581*b636d99dSDavid van Moolenbroek      */
582*b636d99dSDavid van Moolenbroek     if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) {
583*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "%sLDP version %u packet not supported",
584*b636d99dSDavid van Moolenbroek                (ndo->ndo_vflag < 1) ? "" : "\n\t",
585*b636d99dSDavid van Moolenbroek                EXTRACT_16BITS(&ldp_com_header->version)));
586*b636d99dSDavid van Moolenbroek 	return 0;
587*b636d99dSDavid van Moolenbroek     }
588*b636d99dSDavid van Moolenbroek 
589*b636d99dSDavid van Moolenbroek     pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length);
590*b636d99dSDavid van Moolenbroek     if (pdu_len < sizeof(const struct ldp_common_header)-4) {
591*b636d99dSDavid van Moolenbroek         /* length too short */
592*b636d99dSDavid van Moolenbroek         ND_PRINT((ndo, "%sLDP, pdu-length: %u (too short, < %u)",
593*b636d99dSDavid van Moolenbroek                (ndo->ndo_vflag < 1) ? "" : "\n\t",
594*b636d99dSDavid van Moolenbroek                pdu_len,
595*b636d99dSDavid van Moolenbroek                (u_int)(sizeof(const struct ldp_common_header)-4)));
596*b636d99dSDavid van Moolenbroek         return 0;
597*b636d99dSDavid van Moolenbroek     }
598*b636d99dSDavid van Moolenbroek 
599*b636d99dSDavid van Moolenbroek     /* print the LSR-ID, label-space & length */
600*b636d99dSDavid van Moolenbroek     ND_PRINT((ndo, "%sLDP, Label-Space-ID: %s:%u, pdu-length: %u",
601*b636d99dSDavid van Moolenbroek            (ndo->ndo_vflag < 1) ? "" : "\n\t",
602*b636d99dSDavid van Moolenbroek            ipaddr_string(ndo, &ldp_com_header->lsr_id),
603*b636d99dSDavid van Moolenbroek            EXTRACT_16BITS(&ldp_com_header->label_space),
604*b636d99dSDavid van Moolenbroek            pdu_len));
605*b636d99dSDavid van Moolenbroek 
606*b636d99dSDavid van Moolenbroek     /* bail out if non-verbose */
607*b636d99dSDavid van Moolenbroek     if (ndo->ndo_vflag < 1)
608*b636d99dSDavid van Moolenbroek         return 0;
609*b636d99dSDavid van Moolenbroek 
610*b636d99dSDavid van Moolenbroek     /* ok they seem to want to know everything - lets fully decode it */
611*b636d99dSDavid van Moolenbroek     tptr = pptr + sizeof(const struct ldp_common_header);
612*b636d99dSDavid van Moolenbroek     tlen = pdu_len - (sizeof(const struct ldp_common_header)-4);	/* Type & Length fields not included */
613*b636d99dSDavid van Moolenbroek 
614*b636d99dSDavid van Moolenbroek     while(tlen>0) {
615*b636d99dSDavid van Moolenbroek         /* did we capture enough for fully decoding the msg header ? */
616*b636d99dSDavid van Moolenbroek         ND_TCHECK2(*tptr, sizeof(struct ldp_msg_header));
617*b636d99dSDavid van Moolenbroek 
618*b636d99dSDavid van Moolenbroek         ldp_msg_header = (const struct ldp_msg_header *)tptr;
619*b636d99dSDavid van Moolenbroek         msg_len=EXTRACT_16BITS(ldp_msg_header->length);
620*b636d99dSDavid van Moolenbroek         msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type));
621*b636d99dSDavid van Moolenbroek 
622*b636d99dSDavid van Moolenbroek         if (msg_len < sizeof(struct ldp_msg_header)-4) {
623*b636d99dSDavid van Moolenbroek             /* length too short */
624*b636d99dSDavid van Moolenbroek             /* FIXME vendor private / experimental check */
625*b636d99dSDavid van Moolenbroek             ND_PRINT((ndo, "\n\t  %s Message (0x%04x), length: %u (too short, < %u)",
626*b636d99dSDavid van Moolenbroek                    tok2str(ldp_msg_values,
627*b636d99dSDavid van Moolenbroek                            "Unknown",
628*b636d99dSDavid van Moolenbroek                            msg_type),
629*b636d99dSDavid van Moolenbroek                    msg_type,
630*b636d99dSDavid van Moolenbroek                    msg_len,
631*b636d99dSDavid van Moolenbroek                    (u_int)(sizeof(struct ldp_msg_header)-4)));
632*b636d99dSDavid van Moolenbroek             return 0;
633*b636d99dSDavid van Moolenbroek         }
634*b636d99dSDavid van Moolenbroek 
635*b636d99dSDavid van Moolenbroek         /* FIXME vendor private / experimental check */
636*b636d99dSDavid van Moolenbroek         ND_PRINT((ndo, "\n\t  %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]",
637*b636d99dSDavid van Moolenbroek                tok2str(ldp_msg_values,
638*b636d99dSDavid van Moolenbroek                        "Unknown",
639*b636d99dSDavid van Moolenbroek                        msg_type),
640*b636d99dSDavid van Moolenbroek                msg_type,
641*b636d99dSDavid van Moolenbroek                msg_len,
642*b636d99dSDavid van Moolenbroek                EXTRACT_32BITS(&ldp_msg_header->id),
643*b636d99dSDavid van Moolenbroek                LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore"));
644*b636d99dSDavid van Moolenbroek 
645*b636d99dSDavid van Moolenbroek         msg_tptr=tptr+sizeof(struct ldp_msg_header);
646*b636d99dSDavid van Moolenbroek         msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */
647*b636d99dSDavid van Moolenbroek 
648*b636d99dSDavid van Moolenbroek         /* did we capture enough for fully decoding the message ? */
649*b636d99dSDavid van Moolenbroek         ND_TCHECK2(*tptr, msg_len);
650*b636d99dSDavid van Moolenbroek         hexdump=FALSE;
651*b636d99dSDavid van Moolenbroek 
652*b636d99dSDavid van Moolenbroek         switch(msg_type) {
653*b636d99dSDavid van Moolenbroek 
654*b636d99dSDavid van Moolenbroek         case LDP_MSG_NOTIF:
655*b636d99dSDavid van Moolenbroek         case LDP_MSG_HELLO:
656*b636d99dSDavid van Moolenbroek         case LDP_MSG_INIT:
657*b636d99dSDavid van Moolenbroek         case LDP_MSG_KEEPALIVE:
658*b636d99dSDavid van Moolenbroek         case LDP_MSG_ADDRESS:
659*b636d99dSDavid van Moolenbroek         case LDP_MSG_LABEL_MAPPING:
660*b636d99dSDavid van Moolenbroek         case LDP_MSG_ADDRESS_WITHDRAW:
661*b636d99dSDavid van Moolenbroek         case LDP_MSG_LABEL_WITHDRAW:
662*b636d99dSDavid van Moolenbroek             while(msg_tlen >= 4) {
663*b636d99dSDavid van Moolenbroek                 processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen);
664*b636d99dSDavid van Moolenbroek                 if (processed == 0)
665*b636d99dSDavid van Moolenbroek                     break;
666*b636d99dSDavid van Moolenbroek                 msg_tlen-=processed;
667*b636d99dSDavid van Moolenbroek                 msg_tptr+=processed;
668*b636d99dSDavid van Moolenbroek             }
669*b636d99dSDavid van Moolenbroek             break;
670*b636d99dSDavid van Moolenbroek 
671*b636d99dSDavid van Moolenbroek         /*
672*b636d99dSDavid van Moolenbroek          *  FIXME those are the defined messages that lack a decoder
673*b636d99dSDavid van Moolenbroek          *  you are welcome to contribute code ;-)
674*b636d99dSDavid van Moolenbroek          */
675*b636d99dSDavid van Moolenbroek 
676*b636d99dSDavid van Moolenbroek         case LDP_MSG_LABEL_REQUEST:
677*b636d99dSDavid van Moolenbroek         case LDP_MSG_LABEL_RELEASE:
678*b636d99dSDavid van Moolenbroek         case LDP_MSG_LABEL_ABORT_REQUEST:
679*b636d99dSDavid van Moolenbroek 
680*b636d99dSDavid van Moolenbroek         default:
681*b636d99dSDavid van Moolenbroek             if (ndo->ndo_vflag <= 1)
682*b636d99dSDavid van Moolenbroek                 print_unknown_data(ndo, msg_tptr, "\n\t  ", msg_tlen);
683*b636d99dSDavid van Moolenbroek             break;
684*b636d99dSDavid van Moolenbroek         }
685*b636d99dSDavid van Moolenbroek         /* do we want to see an additionally hexdump ? */
686*b636d99dSDavid van Moolenbroek         if (ndo->ndo_vflag > 1 || hexdump==TRUE)
687*b636d99dSDavid van Moolenbroek             print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t  ",
688*b636d99dSDavid van Moolenbroek                                msg_len);
689*b636d99dSDavid van Moolenbroek 
690*b636d99dSDavid van Moolenbroek         tptr += msg_len+4;
691*b636d99dSDavid van Moolenbroek         tlen -= msg_len+4;
692*b636d99dSDavid van Moolenbroek     }
693*b636d99dSDavid van Moolenbroek     return pdu_len+4;
694*b636d99dSDavid van Moolenbroek trunc:
695*b636d99dSDavid van Moolenbroek     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
696*b636d99dSDavid van Moolenbroek     return 0;
697*b636d99dSDavid van Moolenbroek }
698*b636d99dSDavid van Moolenbroek 
699*b636d99dSDavid van Moolenbroek /*
700*b636d99dSDavid van Moolenbroek  * Local Variables:
701*b636d99dSDavid van Moolenbroek  * c-style: whitesmith
702*b636d99dSDavid van Moolenbroek  * c-basic-offset: 8
703*b636d99dSDavid van Moolenbroek  * End:
704*b636d99dSDavid van Moolenbroek  */
705