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