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