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