print-mpls.c revision 1.2
1/* 2 * Copyright (C) 2001 WIDE Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the project nor the names of its contributors 13 * may be used to endorse or promote products derived from this software 14 * without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30#ifndef lint 31#if 0 32static const char rcsid[] _U_ = 33 "@(#) Header: /tcpdump/master/tcpdump/print-mpls.c,v 1.14 2005-07-05 09:38:19 hannes Exp (LBL)"; 34#else 35__RCSID("$NetBSD: print-mpls.c,v 1.2 2010/12/05 05:11:30 christos Exp $"); 36#endif 37#endif 38 39#ifdef HAVE_CONFIG_H 40#include "config.h" 41#endif 42 43#include <tcpdump-stdinc.h> 44 45#include <stdio.h> 46#include <stdlib.h> 47#include <string.h> 48 49#include "addrtoname.h" 50#include "interface.h" 51#include "extract.h" /* must come after interface.h */ 52#include "mpls.h" 53 54static const char *mpls_labelname[] = { 55/*0*/ "IPv4 explicit NULL", "router alert", "IPv6 explicit NULL", 56 "implicit NULL", "rsvd", 57/*5*/ "rsvd", "rsvd", "rsvd", "rsvd", "rsvd", 58/*10*/ "rsvd", "rsvd", "rsvd", "rsvd", "rsvd", 59/*15*/ "rsvd", 60}; 61 62/* 63 * RFC3032: MPLS label stack encoding 64 */ 65void 66mpls_print(const u_char *bp, u_int length) 67{ 68 const u_char *p; 69 u_int32_t label_entry; 70 u_int16_t label_stack_depth = 0; 71 72 p = bp; 73 printf("MPLS"); 74 do { 75 TCHECK2(*p, sizeof(label_entry)); 76 label_entry = EXTRACT_32BITS(p); 77 printf("%s(label %u", 78 label_stack_depth ? "\n\t" : " ", 79 MPLS_LABEL(label_entry)); 80 label_stack_depth++; 81 if (vflag && 82 MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0])) 83 printf(" (%s)", mpls_labelname[MPLS_LABEL(label_entry)]); 84 printf(", exp %u", MPLS_EXP(label_entry)); 85 if (MPLS_STACK(label_entry)) 86 printf(", [S]"); 87 printf(", ttl %u)", MPLS_TTL(label_entry)); 88 89 p += sizeof(label_entry); 90 } while (!MPLS_STACK(label_entry)); 91 92 switch (MPLS_LABEL(label_entry)) { 93 case 0: /* IPv4 explicit NULL label */ 94 case 3: /* IPv4 implicit NULL label */ 95 if (vflag>0) { 96 printf("\n\t"); 97 ip_print(gndo, p, length - (p - bp)); 98 } 99 else printf(", IP, length: %u",length); 100 break; 101#ifdef INET6 102 case 2: /* IPv6 explicit NULL label */ 103 if (vflag>0) { 104 printf("\n\t"); 105 ip6_print(p, length - (p - bp)); 106 } 107 else printf(", IPv6, length: %u",length); 108 break; 109#endif 110 default: 111 /* 112 * Generally there's no indication of protocol in MPLS label 113 * encoding, however draft-hsmit-isis-aal5mux-00.txt describes 114 * a technique that looks at the first payload byte if the BOS (bottom of stack) 115 * bit is set and tries to determine the network layer protocol 116 * 0x45-0x4f is IPv4 117 * 0x60-0x6f is IPv6 118 * 0x81-0x83 is OSI (CLNP,ES-IS,IS-IS) 119 * this technique is sometimes known as NULL encapsulation 120 * and decoding is particularly useful for control-plane traffic [BGP] 121 * which cisco by default sends MPLS encapsulated 122 */ 123 124 if (MPLS_STACK(label_entry)) { /* only do this if the stack bit is set */ 125 switch(*p) { 126 case 0x45: 127 case 0x46: 128 case 0x47: 129 case 0x48: 130 case 0x49: 131 case 0x4a: 132 case 0x4b: 133 case 0x4c: 134 case 0x4d: 135 case 0x4e: 136 case 0x4f: 137 if (vflag>0) { 138 printf("\n\t"); 139 ip_print(gndo, p, length - (p - bp)); 140 } 141 else printf(", IP, length: %u",length); 142 break; 143#ifdef INET6 144 case 0x60: 145 case 0x61: 146 case 0x62: 147 case 0x63: 148 case 0x64: 149 case 0x65: 150 case 0x66: 151 case 0x67: 152 case 0x68: 153 case 0x69: 154 case 0x6a: 155 case 0x6b: 156 case 0x6c: 157 case 0x6d: 158 case 0x6e: 159 case 0x6f: 160 if (vflag>0) { 161 printf("\n\t"); 162 ip6_print(p, length - (p - bp)); 163 } 164 else printf(", IPv6, length: %u",length); 165 break; 166#endif 167 case 0x81: 168 case 0x82: 169 case 0x83: 170 if (vflag>0) { 171 printf("\n\t"); 172 isoclns_print(p, length - (p - bp), length - (p - bp)); 173 } 174 else printf(", OSI, length: %u",length); 175 break; 176 default: 177 /* ok bail out - we did not figure out what it is*/ 178 break; 179 } 180 } 181 return; 182 } 183 184trunc: 185 printf("[|MPLS]"); 186} 187 188 189/* 190 * Local Variables: 191 * c-style: whitesmith 192 * c-basic-offset: 8 193 * End: 194 */ 195