198524Sfenner/* 298524Sfenner * Copyright (C) 2001 WIDE Project. All rights reserved. 398524Sfenner * 498524Sfenner * Redistribution and use in source and binary forms, with or without 598524Sfenner * modification, are permitted provided that the following conditions 698524Sfenner * are met: 798524Sfenner * 1. Redistributions of source code must retain the above copyright 898524Sfenner * notice, this list of conditions and the following disclaimer. 998524Sfenner * 2. Redistributions in binary form must reproduce the above copyright 1098524Sfenner * notice, this list of conditions and the following disclaimer in the 1198524Sfenner * documentation and/or other materials provided with the distribution. 1298524Sfenner * 3. Neither the name of the project nor the names of its contributors 1398524Sfenner * may be used to endorse or promote products derived from this software 1498524Sfenner * without specific prior written permission. 1598524Sfenner * 1698524Sfenner * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1798524Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1898524Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1998524Sfenner * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2098524Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2198524Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2298524Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2398524Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2498524Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2598524Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2698524Sfenner * SUCH DAMAGE. 2798524Sfenner */ 2898524Sfenner 2998524Sfenner#ifndef lint 30127668Sbmsstatic const char rcsid[] _U_ = 31190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-mpls.c,v 1.14 2005-07-05 09:38:19 hannes Exp $ (LBL)"; 3298524Sfenner#endif 3398524Sfenner 3498524Sfenner#ifdef HAVE_CONFIG_H 3598524Sfenner#include "config.h" 3698524Sfenner#endif 3798524Sfenner 38127668Sbms#include <tcpdump-stdinc.h> 3998524Sfenner 4098524Sfenner#include <stdio.h> 4198524Sfenner#include <stdlib.h> 4298524Sfenner#include <string.h> 4398524Sfenner 4498524Sfenner#include "addrtoname.h" 4598524Sfenner#include "interface.h" 4698524Sfenner#include "extract.h" /* must come after interface.h */ 47146773Ssam#include "mpls.h" 4898524Sfenner 4998524Sfennerstatic const char *mpls_labelname[] = { 5098524Sfenner/*0*/ "IPv4 explicit NULL", "router alert", "IPv6 explicit NULL", 5198524Sfenner "implicit NULL", "rsvd", 5298524Sfenner/*5*/ "rsvd", "rsvd", "rsvd", "rsvd", "rsvd", 5398524Sfenner/*10*/ "rsvd", "rsvd", "rsvd", "rsvd", "rsvd", 5498524Sfenner/*15*/ "rsvd", 5598524Sfenner}; 5698524Sfenner 57235530Sdelphijenum mpls_packet_type { 58235530Sdelphij PT_UNKNOWN, 59235530Sdelphij PT_IPV4, 60235530Sdelphij PT_IPV6, 61235530Sdelphij PT_OSI 62235530Sdelphij}; 63235530Sdelphij 6498524Sfenner/* 6598524Sfenner * RFC3032: MPLS label stack encoding 6698524Sfenner */ 6798524Sfennervoid 6898524Sfennermpls_print(const u_char *bp, u_int length) 6998524Sfenner{ 7098524Sfenner const u_char *p; 71147899Ssam u_int32_t label_entry; 72235530Sdelphij u_int16_t label_stack_depth = 0; 73235530Sdelphij enum mpls_packet_type pt = PT_UNKNOWN; 7498524Sfenner 7598524Sfenner p = bp; 7698524Sfenner printf("MPLS"); 77111726Sfenner do { 78147899Ssam TCHECK2(*p, sizeof(label_entry)); 79147899Ssam label_entry = EXTRACT_32BITS(p); 80147899Ssam printf("%s(label %u", 81235530Sdelphij (label_stack_depth && vflag) ? "\n\t" : " ", 82235530Sdelphij MPLS_LABEL(label_entry)); 83235530Sdelphij label_stack_depth++; 84111726Sfenner if (vflag && 85147899Ssam MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0])) 86147899Ssam printf(" (%s)", mpls_labelname[MPLS_LABEL(label_entry)]); 87147899Ssam printf(", exp %u", MPLS_EXP(label_entry)); 88147899Ssam if (MPLS_STACK(label_entry)) 89127668Sbms printf(", [S]"); 90147899Ssam printf(", ttl %u)", MPLS_TTL(label_entry)); 9198524Sfenner 92147899Ssam p += sizeof(label_entry); 93147899Ssam } while (!MPLS_STACK(label_entry)); 9498524Sfenner 95235530Sdelphij /* 96235530Sdelphij * Try to figure out the packet type. 97235530Sdelphij */ 98147899Ssam switch (MPLS_LABEL(label_entry)) { 99235530Sdelphij 10098524Sfenner case 0: /* IPv4 explicit NULL label */ 101235530Sdelphij case 3: /* IPv4 implicit NULL label */ 102235530Sdelphij pt = PT_IPV4; 10398524Sfenner break; 104235530Sdelphij 10598524Sfenner case 2: /* IPv6 explicit NULL label */ 106235530Sdelphij pt = PT_IPV6; 10798524Sfenner break; 108235530Sdelphij 10998524Sfenner default: 11098524Sfenner /* 111127668Sbms * Generally there's no indication of protocol in MPLS label 112235530Sdelphij * encoding. 113235530Sdelphij * 114235530Sdelphij * However, draft-hsmit-isis-aal5mux-00.txt describes a 115235530Sdelphij * technique for encapsulating IS-IS and IP traffic on the 116235530Sdelphij * same ATM virtual circuit; you look at the first payload 117235530Sdelphij * byte to determine the network layer protocol, based on 118235530Sdelphij * the fact that 119235530Sdelphij * 120235530Sdelphij * 1) the first byte of an IP header is 0x45-0x4f 121235530Sdelphij * for IPv4 and 0x60-0x6f for IPv6; 122235530Sdelphij * 123235530Sdelphij * 2) the first byte of an OSI CLNP packet is 0x81, 124235530Sdelphij * the first byte of an OSI ES-IS packet is 0x82, 125235530Sdelphij * and the first byte of an OSI IS-IS packet is 126235530Sdelphij * 0x83; 127235530Sdelphij * 128235530Sdelphij * so the network layer protocol can be inferred from the 129235530Sdelphij * first byte of the packet, if the protocol is one of the 130235530Sdelphij * ones listed above. 131235530Sdelphij * 132235530Sdelphij * Cisco sends control-plane traffic MPLS-encapsulated in 133235530Sdelphij * this fashion. 13498524Sfenner */ 135235530Sdelphij switch(*p) { 136127668Sbms 137235530Sdelphij case 0x45: 138235530Sdelphij case 0x46: 139235530Sdelphij case 0x47: 140235530Sdelphij case 0x48: 141235530Sdelphij case 0x49: 142235530Sdelphij case 0x4a: 143235530Sdelphij case 0x4b: 144235530Sdelphij case 0x4c: 145235530Sdelphij case 0x4d: 146235530Sdelphij case 0x4e: 147235530Sdelphij case 0x4f: 148235530Sdelphij pt = PT_IPV4; 149235530Sdelphij break; 150235530Sdelphij 151235530Sdelphij case 0x60: 152235530Sdelphij case 0x61: 153235530Sdelphij case 0x62: 154235530Sdelphij case 0x63: 155235530Sdelphij case 0x64: 156235530Sdelphij case 0x65: 157235530Sdelphij case 0x66: 158235530Sdelphij case 0x67: 159235530Sdelphij case 0x68: 160235530Sdelphij case 0x69: 161235530Sdelphij case 0x6a: 162235530Sdelphij case 0x6b: 163235530Sdelphij case 0x6c: 164235530Sdelphij case 0x6d: 165235530Sdelphij case 0x6e: 166235530Sdelphij case 0x6f: 167235530Sdelphij pt = PT_IPV6; 168235530Sdelphij break; 169235530Sdelphij 170235530Sdelphij case 0x81: 171235530Sdelphij case 0x82: 172235530Sdelphij case 0x83: 173235530Sdelphij pt = PT_OSI; 174235530Sdelphij break; 175235530Sdelphij 176235530Sdelphij default: 177235530Sdelphij /* ok bail out - we did not figure out what it is*/ 178235530Sdelphij break; 179235530Sdelphij } 180235530Sdelphij } 181235530Sdelphij 182235530Sdelphij /* 183235530Sdelphij * Print the payload. 184235530Sdelphij */ 185235530Sdelphij if (pt == PT_UNKNOWN) { 186235530Sdelphij if (!suppress_default_print) 187235530Sdelphij default_print(p, length - (p - bp)); 188235530Sdelphij return; 189235530Sdelphij } 190235530Sdelphij if (vflag) 191235530Sdelphij printf("\n\t"); 192235530Sdelphij else 193235530Sdelphij printf(" "); 194235530Sdelphij switch (pt) { 195235530Sdelphij 196235530Sdelphij case PT_IPV4: 197235530Sdelphij ip_print(gndo, p, length - (p - bp)); 198235530Sdelphij break; 199235530Sdelphij 200235530Sdelphij case PT_IPV6: 201127668Sbms#ifdef INET6 202235530Sdelphij ip6_print(gndo, p, length - (p - bp)); 203235530Sdelphij#else 204235530Sdelphij printf("IPv6, length: %u", length); 205127668Sbms#endif 206235530Sdelphij break; 207235530Sdelphij 208235530Sdelphij case PT_OSI: 209235530Sdelphij isoclns_print(p, length - (p - bp), length - (p - bp)); 210235530Sdelphij break; 211235530Sdelphij 212235530Sdelphij default: 213235530Sdelphij break; 21498524Sfenner } 215235530Sdelphij return; 21698524Sfenner 21798524Sfennertrunc: 21898524Sfenner printf("[|MPLS]"); 21998524Sfenner} 220127668Sbms 221146773Ssam 222127668Sbms/* 223146773Ssam * Local Variables: 224146773Ssam * c-style: whitesmith 225146773Ssam * c-basic-offset: 8 226146773Ssam * End: 227127668Sbms */ 228