xref: /netbsd-src/external/bsd/tcpdump/dist/print-mpls.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (C) 2001 WIDE Project.  All rights reserved.
30f74e101Schristos  *
40f74e101Schristos  * Redistribution and use in source and binary forms, with or without
50f74e101Schristos  * modification, are permitted provided that the following conditions
60f74e101Schristos  * are met:
70f74e101Schristos  * 1. Redistributions of source code must retain the above copyright
80f74e101Schristos  *    notice, this list of conditions and the following disclaimer.
90f74e101Schristos  * 2. Redistributions in binary form must reproduce the above copyright
100f74e101Schristos  *    notice, this list of conditions and the following disclaimer in the
110f74e101Schristos  *    documentation and/or other materials provided with the distribution.
120f74e101Schristos  * 3. Neither the name of the project nor the names of its contributors
130f74e101Schristos  *    may be used to endorse or promote products derived from this software
140f74e101Schristos  *    without specific prior written permission.
150f74e101Schristos  *
160f74e101Schristos  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
170f74e101Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180f74e101Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
190f74e101Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
200f74e101Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210f74e101Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
220f74e101Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
230f74e101Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
240f74e101Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
250f74e101Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260f74e101Schristos  * SUCH DAMAGE.
270f74e101Schristos  */
280f74e101Schristos 
2911b3aaa1Schristos #include <sys/cdefs.h>
300f74e101Schristos #ifndef lint
31*26ba0b50Schristos __RCSID("$NetBSD: print-mpls.c,v 1.10 2024/09/02 16:15:32 christos Exp $");
320f74e101Schristos #endif
330f74e101Schristos 
34dc860a36Sspz /* \summary: Multi-Protocol Label Switching (MPLS) printer */
35dc860a36Sspz 
36c74ad251Schristos #include <config.h>
370f74e101Schristos 
38c74ad251Schristos #include "netdissect-stdinc.h"
390f74e101Schristos 
40c74ad251Schristos #define ND_LONGJMP_FROM_TCHECK
41fdccd7e4Schristos #include "netdissect.h"
42fdccd7e4Schristos #include "extract.h"
430f74e101Schristos #include "mpls.h"
440f74e101Schristos 
450f74e101Schristos static const char *mpls_labelname[] = {
460f74e101Schristos /*0*/	"IPv4 explicit NULL", "router alert", "IPv6 explicit NULL",
470f74e101Schristos 	"implicit NULL", "rsvd",
480f74e101Schristos /*5*/	"rsvd", "rsvd", "rsvd", "rsvd", "rsvd",
490f74e101Schristos /*10*/	"rsvd", "rsvd", "rsvd", "rsvd", "rsvd",
500f74e101Schristos /*15*/	"rsvd",
510f74e101Schristos };
520f74e101Schristos 
530e9868baSchristos enum mpls_packet_type {
540e9868baSchristos 	PT_UNKNOWN,
550e9868baSchristos 	PT_IPV4,
560e9868baSchristos 	PT_IPV6,
570e9868baSchristos 	PT_OSI
580e9868baSchristos };
590e9868baSchristos 
600f74e101Schristos /*
610f74e101Schristos  * RFC3032: MPLS label stack encoding
620f74e101Schristos  */
630f74e101Schristos void
64b3a00663Schristos mpls_print(netdissect_options *ndo, const u_char *bp, u_int length)
650f74e101Schristos {
660f74e101Schristos 	const u_char *p;
67b3a00663Schristos 	uint32_t label_entry;
68b3a00663Schristos 	uint16_t label_stack_depth = 0;
69c74ad251Schristos 	uint8_t first;
700e9868baSchristos 	enum mpls_packet_type pt = PT_UNKNOWN;
710f74e101Schristos 
72c74ad251Schristos 	ndo->ndo_protocol = "mpls";
730f74e101Schristos 	p = bp;
74c74ad251Schristos 	nd_print_protocol_caps(ndo);
750f74e101Schristos 	do {
76c74ad251Schristos 		if (length < sizeof(label_entry))
77c74ad251Schristos 			goto invalid;
78c74ad251Schristos 		label_entry = GET_BE_U_4(p);
79c74ad251Schristos 		ND_PRINT("%s(label %u",
80b3a00663Schristos 		       (label_stack_depth && ndo->ndo_vflag) ? "\n\t" : " ",
81c74ad251Schristos 			MPLS_LABEL(label_entry));
820f74e101Schristos 		label_stack_depth++;
83b3a00663Schristos 		if (ndo->ndo_vflag &&
840f74e101Schristos 		    MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0]))
85c74ad251Schristos 			ND_PRINT(" (%s)", mpls_labelname[MPLS_LABEL(label_entry)]);
86c74ad251Schristos 		ND_PRINT(", tc %u", MPLS_TC(label_entry));
870f74e101Schristos 		if (MPLS_STACK(label_entry))
88c74ad251Schristos 			ND_PRINT(", [S]");
89c74ad251Schristos 		ND_PRINT(", ttl %u)", MPLS_TTL(label_entry));
900f74e101Schristos 
910f74e101Schristos 		p += sizeof(label_entry);
92dc860a36Sspz 		length -= sizeof(label_entry);
930f74e101Schristos 	} while (!MPLS_STACK(label_entry));
940f74e101Schristos 
950e9868baSchristos 	/*
960e9868baSchristos 	 * Try to figure out the packet type.
970e9868baSchristos 	 */
980f74e101Schristos 	switch (MPLS_LABEL(label_entry)) {
990e9868baSchristos 
1000f74e101Schristos 	case 0:	/* IPv4 explicit NULL label */
1010f74e101Schristos 	case 3:	/* IPv4 implicit NULL label */
1020e9868baSchristos 		pt = PT_IPV4;
1030f74e101Schristos 		break;
1040e9868baSchristos 
1050f74e101Schristos 	case 2:	/* IPv6 explicit NULL label */
1060e9868baSchristos 		pt = PT_IPV6;
1070f74e101Schristos 		break;
1080e9868baSchristos 
1090f74e101Schristos 	default:
1100f74e101Schristos 		/*
1110f74e101Schristos 		 * Generally there's no indication of protocol in MPLS label
1120e9868baSchristos 		 * encoding.
1130e9868baSchristos 		 *
1140e9868baSchristos 		 * However, draft-hsmit-isis-aal5mux-00.txt describes a
1150e9868baSchristos 		 * technique for encapsulating IS-IS and IP traffic on the
1160e9868baSchristos 		 * same ATM virtual circuit; you look at the first payload
1170e9868baSchristos 		 * byte to determine the network layer protocol, based on
1180e9868baSchristos 		 * the fact that
1190e9868baSchristos 		 *
1200e9868baSchristos 		 *	1) the first byte of an IP header is 0x45-0x4f
1210e9868baSchristos 		 *	   for IPv4 and 0x60-0x6f for IPv6;
1220e9868baSchristos 		 *
1230e9868baSchristos 		 *	2) the first byte of an OSI CLNP packet is 0x81,
1240e9868baSchristos 		 *	   the first byte of an OSI ES-IS packet is 0x82,
1250e9868baSchristos 		 *	   and the first byte of an OSI IS-IS packet is
1260e9868baSchristos 		 *	   0x83;
1270e9868baSchristos 		 *
1280e9868baSchristos 		 * so the network layer protocol can be inferred from the
1290e9868baSchristos 		 * first byte of the packet, if the protocol is one of the
1300e9868baSchristos 		 * ones listed above.
1310e9868baSchristos 		 *
1320e9868baSchristos 		 * Cisco sends control-plane traffic MPLS-encapsulated in
1330e9868baSchristos 		 * this fashion.
1340f74e101Schristos 		 */
135dc860a36Sspz 		if (length < 1) {
136dc860a36Sspz 			/* nothing to print */
137dc860a36Sspz 			return;
138dc860a36Sspz 		}
139c74ad251Schristos 		first = GET_U_1(p);
140c74ad251Schristos 		pt =
141c74ad251Schristos 			(first >= 0x45 && first <= 0x4f) ? PT_IPV4 :
142c74ad251Schristos 			(first >= 0x60 && first <= 0x6f) ? PT_IPV6 :
143c74ad251Schristos 			(first >= 0x81 && first <= 0x83) ? PT_OSI :
1440f74e101Schristos 			/* ok bail out - we did not figure out what it is*/
145c74ad251Schristos 			PT_UNKNOWN;
1460f74e101Schristos 	}
1470e9868baSchristos 
1480e9868baSchristos 	/*
1490e9868baSchristos 	 * Print the payload.
1500e9868baSchristos 	 */
151c74ad251Schristos 	switch (pt) {
152c74ad251Schristos 	case PT_UNKNOWN:
153b3a00663Schristos 		if (!ndo->ndo_suppress_default_print)
154dc860a36Sspz 			ND_DEFAULTPRINT(p, length);
155c74ad251Schristos 		break;
1560e9868baSchristos 
1570e9868baSchristos 	case PT_IPV4:
158c74ad251Schristos 		ND_PRINT(ndo->ndo_vflag ? "\n\t" : " ");
159dc860a36Sspz 		ip_print(ndo, p, length);
1600e9868baSchristos 		break;
1610e9868baSchristos 
1620e9868baSchristos 	case PT_IPV6:
163c74ad251Schristos 		ND_PRINT(ndo->ndo_vflag ? "\n\t" : " ");
164dc860a36Sspz 		ip6_print(ndo, p, length);
1650e9868baSchristos 		break;
1660e9868baSchristos 
1670e9868baSchristos 	case PT_OSI:
168c74ad251Schristos 		ND_PRINT(ndo->ndo_vflag ? "\n\t" : " ");
16972c96ff3Schristos 		isoclns_print(ndo, p, length);
1700e9868baSchristos 		break;
1710e9868baSchristos 	}
1720e9868baSchristos 	return;
1730f74e101Schristos 
174c74ad251Schristos invalid:
175c74ad251Schristos 	nd_print_invalid(ndo);
176c74ad251Schristos 	ND_TCHECK_LEN(p, length);
1770f74e101Schristos }
178