xref: /freebsd/contrib/tcpdump/print-ldp.c (revision 55f88dd25e8b4fad6bb2effd3ae55dd687b0903e)
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@juniper.net)
14  *  and Steinar Haug (sthaug@nethelp.no)
15  */
16 
17 #ifndef lint
18 static const char rcsid[] _U_ =
19     "@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.8 2004/06/15 09:42:42 hannes Exp $";
20 #endif
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include <tcpdump-stdinc.h>
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "interface.h"
33 #include "decode_prefix.h"
34 #include "extract.h"
35 #include "addrtoname.h"
36 
37 #include "l2vpn.h"
38 
39 /*
40  * ldp common header
41  *
42  *  0                   1                   2                   3
43  *  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
44  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45  * |  Version                      |         PDU Length            |
46  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47  * |                         LDP Identifier                        |
48  * +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49  * |                               |
50  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51  *
52  */
53 
54 struct ldp_common_header {
55     u_int8_t version[2];
56     u_int8_t pdu_length[2];
57     u_int8_t lsr_id[4];
58     u_int8_t label_space[2];
59 };
60 
61 #define LDP_VERSION 1
62 
63 /*
64  * ldp message header
65  *
66  *  0                   1                   2                   3
67  *  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
68  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69  * |U|   Message Type              |      Message Length           |
70  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71  * |                     Message ID                                |
72  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73  * |                                                               |
74  * +                                                               +
75  * |                     Mandatory Parameters                      |
76  * +                                                               +
77  * |                                                               |
78  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79  * |                                                               |
80  * +                                                               +
81  * |                     Optional Parameters                       |
82  * +                                                               +
83  * |                                                               |
84  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85  */
86 
87 struct ldp_msg_header {
88     u_int8_t type[2];
89     u_int8_t length[2];
90     u_int8_t id[4];
91 };
92 
93 #define	LDP_MASK_MSG_TYPE(x)  ((x)&0x7fff)
94 #define	LDP_MASK_U_BIT(x)     ((x)&0x8000)
95 
96 #define	LDP_MSG_NOTIF                0x0001
97 #define	LDP_MSG_HELLO                0x0100
98 #define	LDP_MSG_INIT                 0x0200
99 #define	LDP_MSG_KEEPALIVE            0x0201
100 #define	LDP_MSG_ADDRESS              0x0300
101 #define	LDP_MSG_ADDRESS_WITHDRAW     0x0301
102 #define	LDP_MSG_LABEL_MAPPING        0x0400
103 #define	LDP_MSG_LABEL_REQUEST        0x0401
104 #define	LDP_MSG_LABEL_WITHDRAW       0x0402
105 #define	LDP_MSG_LABEL_RELEASE        0x0403
106 #define	LDP_MSG_LABEL_ABORT_REQUEST  0x0404
107 
108 #define	LDP_VENDOR_PRIVATE_MIN       0x3e00
109 #define	LDP_VENDOR_PRIVATE_MAX       0x3eff
110 #define	LDP_EXPERIMENTAL_MIN         0x3f00
111 #define	LDP_EXPERIMENTAL_MAX         0x3fff
112 
113 static const struct tok ldp_msg_values[] = {
114     { LDP_MSG_NOTIF,	             "Notification" },
115     { LDP_MSG_HELLO,	             "Hello" },
116     { LDP_MSG_INIT,	             "Initialization" },
117     { LDP_MSG_KEEPALIVE,             "Keepalive" },
118     { LDP_MSG_ADDRESS,	             "Address" },
119     { LDP_MSG_ADDRESS_WITHDRAW,	     "Address Widthdraw" },
120     { LDP_MSG_LABEL_MAPPING,	     "Label Mapping" },
121     { LDP_MSG_LABEL_REQUEST,	     "Label Request" },
122     { LDP_MSG_LABEL_WITHDRAW,	     "Label Withdraw" },
123     { LDP_MSG_LABEL_RELEASE,	     "Label Release" },
124     { LDP_MSG_LABEL_ABORT_REQUEST,   "Label Abort Request" },
125     { 0, NULL}
126 };
127 
128 #define	LDP_MASK_TLV_TYPE(x)  ((x)&0x3fff)
129 #define	LDP_MASK_F_BIT(x) ((x)&0x4000)
130 
131 #define	LDP_TLV_FEC                  0x0100
132 #define	LDP_TLV_ADDRESS_LIST         0x0101
133 #define	LDP_TLV_HOP_COUNT            0x0103
134 #define	LDP_TLV_PATH_VECTOR          0x0104
135 #define	LDP_TLV_GENERIC_LABEL        0x0200
136 #define	LDP_TLV_ATM_LABEL            0x0201
137 #define	LDP_TLV_FR_LABEL             0x0202
138 #define	LDP_TLV_STATUS               0x0300
139 #define	LDP_TLV_EXTD_STATUS          0x0301
140 #define	LDP_TLV_RETURNED_PDU         0x0302
141 #define	LDP_TLV_RETURNED_MSG         0x0303
142 #define	LDP_TLV_COMMON_HELLO         0x0400
143 #define	LDP_TLV_IPV4_TRANSPORT_ADDR  0x0401
144 #define	LDP_TLV_CONFIG_SEQ_NUMBER    0x0402
145 #define	LDP_TLV_IPV6_TRANSPORT_ADDR  0x0403
146 #define	LDP_TLV_COMMON_SESSION       0x0500
147 #define	LDP_TLV_ATM_SESSION_PARM     0x0501
148 #define	LDP_TLV_FR_SESSION_PARM      0x0502
149 #define LDP_TLV_FT_SESSION	     0x0503
150 #define	LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600
151 
152 static const struct tok ldp_tlv_values[] = {
153     { LDP_TLV_FEC,	             "FEC" },
154     { LDP_TLV_ADDRESS_LIST,          "Address List" },
155     { LDP_TLV_HOP_COUNT,             "Hop Count" },
156     { LDP_TLV_PATH_VECTOR,           "Path Vector" },
157     { LDP_TLV_GENERIC_LABEL,         "Generic Label" },
158     { LDP_TLV_ATM_LABEL,             "ATM Label" },
159     { LDP_TLV_FR_LABEL,              "Frame-Relay Label" },
160     { LDP_TLV_STATUS,                "Status" },
161     { LDP_TLV_EXTD_STATUS,           "Extended Status" },
162     { LDP_TLV_RETURNED_PDU,          "Returned PDU" },
163     { LDP_TLV_RETURNED_MSG,          "Returned Message" },
164     { LDP_TLV_COMMON_HELLO,          "Common Hello Parameters" },
165     { LDP_TLV_IPV4_TRANSPORT_ADDR,   "IPv4 Transport Address" },
166     { LDP_TLV_CONFIG_SEQ_NUMBER,     "Configuration Sequence Number" },
167     { LDP_TLV_IPV6_TRANSPORT_ADDR,   "IPv6 Transport Address" },
168     { LDP_TLV_COMMON_SESSION,        "Common Session Parameters" },
169     { LDP_TLV_ATM_SESSION_PARM,      "ATM Session Parameters" },
170     { LDP_TLV_FR_SESSION_PARM,       "Frame-Relay Session Parameters" },
171     { LDP_TLV_FT_SESSION,            "Fault-Tolerant Session Parameters" },
172     { LDP_TLV_LABEL_REQUEST_MSG_ID,  "Label Request Message ID" },
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 draft-martini-l2circuit-trans-mpls-13.txt */
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 /* RFC1700 address family numbers, same definition in print-bgp.c */
191 #define AFNUM_INET	1
192 #define AFNUM_INET6	2
193 
194 #define FALSE 0
195 #define TRUE  1
196 
197 int ldp_tlv_print(register const u_char *);
198 
199 /*
200  * ldp tlv header
201  *
202  *  0                   1                   2                   3
203  *  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
204  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
205  * |U|F|        Type               |            Length             |
206  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
207  * |                                                               |
208  * |                             Value                             |
209  * ~                                                               ~
210  * |                                                               |
211  * |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
212  * |                               |
213  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
214  */
215 
216 int
217 ldp_tlv_print(register const u_char *tptr) {
218 
219     struct ldp_tlv_header {
220         u_int8_t type[2];
221         u_int8_t length[2];
222     };
223 
224     const struct ldp_tlv_header *ldp_tlv_header;
225     u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags;
226     u_char fec_type;
227     u_int ui;
228     char buf[100];
229     int i;
230 
231     ldp_tlv_header = (const struct ldp_tlv_header *)tptr;
232     tlv_len=EXTRACT_16BITS(ldp_tlv_header->length);
233     tlv_tlen=tlv_len;
234     tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type));
235 
236     /* FIXME vendor private / experimental check */
237     printf("\n\t    %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]",
238            tok2str(ldp_tlv_values,
239                    "Unknown",
240                    tlv_type),
241            tlv_type,
242            tlv_len,
243            LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore",
244            LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't");
245 
246     tptr+=sizeof(struct ldp_tlv_header);
247 
248     switch(tlv_type) {
249 
250     case LDP_TLV_COMMON_HELLO:
251         printf("\n\t      Hold Time: %us, Flags: [%s Hello%s]",
252                EXTRACT_16BITS(tptr),
253                (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link",
254                (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : "");
255         break;
256 
257     case LDP_TLV_IPV4_TRANSPORT_ADDR:
258         printf("\n\t      IPv4 Transport Address: %s", ipaddr_string(tptr));
259         break;
260 #ifdef INET6
261     case LDP_TLV_IPV6_TRANSPORT_ADDR:
262         printf("\n\t      IPv6 Transport Address: %s", ip6addr_string(tptr));
263         break;
264 #endif
265     case LDP_TLV_CONFIG_SEQ_NUMBER:
266         printf("\n\t      Sequence Number: %u", EXTRACT_32BITS(tptr));
267         break;
268 
269     case LDP_TLV_ADDRESS_LIST:
270 	af = EXTRACT_16BITS(tptr);
271 	tptr+=2;
272 	printf("\n\t      Adress Family: ");
273 	if (af == AFNUM_INET) {
274 	    printf("IPv4, addresses:");
275 	    for (i=0; i<(tlv_tlen-2)/4; i++) {
276 		printf(" %s",ipaddr_string(tptr));
277 		tptr+=4;
278 	    }
279 	}
280 #ifdef INET6
281 	else if (af == AFNUM_INET6) {
282 	    printf("IPv6, addresses:");
283 	    for (i=0; i<(tlv_tlen-2)/16; i++) {
284 		printf(" %s",ip6addr_string(tptr));
285 		tptr+=16;
286 	    }
287 	}
288 #endif
289 	break;
290 
291     case LDP_TLV_COMMON_SESSION:
292 	printf("\n\t      Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]",
293 	       EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2),
294 	       (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited",
295 	       (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled"
296 	       );
297 	break;
298 
299     case LDP_TLV_FEC:
300         fec_type = *tptr;
301 	printf("\n\t      %s FEC (0x%02x)",
302 	       tok2str(ldp_fec_values, "Unknown", fec_type),
303 	       fec_type);
304 
305 	tptr+=1;
306 	switch(fec_type) {
307 
308 	case LDP_FEC_WILDCARD:
309 	    break;
310 	case LDP_FEC_PREFIX:
311 	    af = EXTRACT_16BITS(tptr);
312 	    tptr+=2;
313 	    if (af == AFNUM_INET) {
314 		i=decode_prefix4(tptr,buf,sizeof(buf));
315 		printf(": IPv4 prefix %s",buf);
316 	    }
317 #ifdef INET6
318 	    else if (af == AFNUM_INET6) {
319 		i=decode_prefix6(tptr,buf,sizeof(buf));
320 		printf(": IPv6 prefix %s",buf);
321 	    }
322 #endif
323 	    break;
324 	case LDP_FEC_HOSTADDRESS:
325 	    break;
326 	case LDP_FEC_MARTINI_VC:
327 	    printf(": %s, %scontrol word, VC %u",
328 		   tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
329 		   EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
330 		   EXTRACT_32BITS(tptr+7));
331 	    break;
332 	}
333 
334 	break;
335 
336     case LDP_TLV_GENERIC_LABEL:
337 	printf("\n\t      Label: %u", EXTRACT_32BITS(tptr) & 0xfffff);
338 	break;
339 
340     case LDP_TLV_STATUS:
341 	ui = EXTRACT_32BITS(tptr);
342 	tptr+=4;
343 	printf("\n\t      Status: 0x%02x, Flags: [%s and %s forward]",
344 	       ui&0x3fffffff,
345 	       ui&0x80000000 ? "Fatal error" : "Advisory Notification",
346 	       ui&0x40000000 ? "do" : "don't");
347 	ui = EXTRACT_32BITS(tptr);
348 	tptr+=4;
349 	if (ui)
350 	    printf(", causing Message ID: 0x%08x", ui);
351 	break;
352 
353     case LDP_TLV_FT_SESSION:
354 	ft_flags = EXTRACT_16BITS(tptr);
355 	printf("\n\t      Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]",
356 	       ft_flags&0x8000 ? "" : "No ",
357 	       ft_flags&0x8 ? "" : "Don't ",
358 	       ft_flags&0x4 ? "" : "No ",
359 	       ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels",
360 	       ft_flags&0x1 ? "" : "Don't ");
361 	tptr+=4;
362 	ui = EXTRACT_32BITS(tptr);
363 	if (ui)
364 	    printf(", Reconnect Timeout: %ums", ui);
365 	tptr+=4;
366 	ui = EXTRACT_32BITS(tptr);
367 	if (ui)
368 	    printf(", Recovery Time: %ums", ui);
369 	break;
370 
371 
372     /*
373      *  FIXME those are the defined TLVs that lack a decoder
374      *  you are welcome to contribute code ;-)
375      */
376 
377     case LDP_TLV_HOP_COUNT:
378     case LDP_TLV_PATH_VECTOR:
379     case LDP_TLV_ATM_LABEL:
380     case LDP_TLV_FR_LABEL:
381     case LDP_TLV_EXTD_STATUS:
382     case LDP_TLV_RETURNED_PDU:
383     case LDP_TLV_RETURNED_MSG:
384     case LDP_TLV_ATM_SESSION_PARM:
385     case LDP_TLV_FR_SESSION_PARM:
386     case LDP_TLV_LABEL_REQUEST_MSG_ID:
387 
388     default:
389         if (vflag <= 1)
390             print_unknown_data(tptr,"\n\t      ",tlv_tlen);
391         break;
392     }
393     return(tlv_len+4); /* Type & Length fields not included */
394 }
395 
396 void
397 ldp_print(register const u_char *pptr, register u_int len) {
398 
399     const struct ldp_common_header *ldp_com_header;
400     const struct ldp_msg_header *ldp_msg_header;
401     const u_char *tptr,*msg_tptr;
402     u_short tlen;
403     u_short msg_len,msg_type,msg_tlen;
404     int hexdump,processed;
405 
406     tptr=pptr;
407     ldp_com_header = (const struct ldp_common_header *)pptr;
408     TCHECK(*ldp_com_header);
409 
410     /*
411      * Sanity checking of the header.
412      */
413     if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) {
414 	printf("LDP version %u packet not supported",
415                EXTRACT_16BITS(&ldp_com_header->version));
416 	return;
417     }
418 
419     /* print the LSR-ID, label-space & length */
420     printf("%sLDP, Label-Space-ID: %s:%u, length: %u",
421            (vflag < 1) ? "" : "\n\t",
422            ipaddr_string(&ldp_com_header->lsr_id),
423            EXTRACT_16BITS(&ldp_com_header->label_space),
424            len);
425 
426     /* bail out if non-verbose */
427     if (vflag < 1)
428         return;
429 
430     /* ok they seem to want to know everything - lets fully decode it */
431     tlen=EXTRACT_16BITS(ldp_com_header->pdu_length);
432 
433     tptr += sizeof(const struct ldp_common_header);
434     tlen -= sizeof(const struct ldp_common_header)-4;	/* Type & Length fields not included */
435 
436     while(tlen>0) {
437         /* did we capture enough for fully decoding the msg header ? */
438         if (!TTEST2(*tptr, sizeof(struct ldp_msg_header)))
439             goto trunc;
440 
441         ldp_msg_header = (const struct ldp_msg_header *)tptr;
442         msg_len=EXTRACT_16BITS(ldp_msg_header->length);
443         msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type));
444 
445         /* FIXME vendor private / experimental check */
446         printf("\n\t  %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]",
447                tok2str(ldp_msg_values,
448                        "Unknown",
449                        msg_type),
450                msg_type,
451                msg_len,
452                EXTRACT_32BITS(&ldp_msg_header->id),
453                LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore");
454 
455         msg_tptr=tptr+sizeof(struct ldp_msg_header);
456         msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */
457 
458         /* did we capture enough for fully decoding the message ? */
459         if (!TTEST2(*tptr, msg_len))
460             goto trunc;
461         hexdump=FALSE;
462 
463         switch(msg_type) {
464 
465         case LDP_MSG_NOTIF:
466         case LDP_MSG_HELLO:
467         case LDP_MSG_INIT:
468         case LDP_MSG_KEEPALIVE:
469         case LDP_MSG_ADDRESS:
470         case LDP_MSG_LABEL_MAPPING:
471             while(msg_tlen >= 4) {
472                 processed = ldp_tlv_print(msg_tptr);
473                 if (processed == 0)
474                     break;
475                 msg_tlen-=processed;
476                 msg_tptr+=processed;
477             }
478             break;
479 
480         /*
481          *  FIXME those are the defined messages that lack a decoder
482          *  you are welcome to contribute code ;-)
483          */
484 
485         case LDP_MSG_ADDRESS_WITHDRAW:
486         case LDP_MSG_LABEL_REQUEST:
487         case LDP_MSG_LABEL_WITHDRAW:
488         case LDP_MSG_LABEL_RELEASE:
489         case LDP_MSG_LABEL_ABORT_REQUEST:
490 
491         default:
492             if (vflag <= 1)
493                 print_unknown_data(msg_tptr,"\n\t  ",msg_tlen);
494             break;
495         }
496         /* do we want to see an additionally hexdump ? */
497         if (vflag > 1 || hexdump==TRUE)
498             print_unknown_data(tptr+sizeof(sizeof(struct ldp_msg_header)),"\n\t  ",
499                                msg_len);
500 
501         tptr += msg_len+4;
502         tlen -= msg_len+4;
503     }
504     return;
505 trunc:
506     printf("\n\t\t packet exceeded snapshot");
507 }
508 
509