• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  #ifndef lint
30  static const char rcsid[] _U_ =
31      "@(#) $Header: /tcpdump/master/tcpdump/print-mpls.c,v 1.14 2005-07-05 09:38:19 hannes Exp $ (LBL)";
32  #endif
33  
34  #ifdef HAVE_CONFIG_H
35  #include "config.h"
36  #endif
37  
38  #include <tcpdump-stdinc.h>
39  
40  #include <stdio.h>
41  #include <stdlib.h>
42  #include <string.h>
43  
44  #include "addrtoname.h"
45  #include "interface.h"
46  #include "extract.h"			/* must come after interface.h */
47  #include "mpls.h"
48  
49  static const char *mpls_labelname[] = {
50  /*0*/	"IPv4 explicit NULL", "router alert", "IPv6 explicit NULL",
51  	"implicit NULL", "rsvd",
52  /*5*/	"rsvd", "rsvd", "rsvd", "rsvd", "rsvd",
53  /*10*/	"rsvd", "rsvd", "rsvd", "rsvd", "rsvd",
54  /*15*/	"rsvd",
55  };
56  
57  enum mpls_packet_type {
58  	PT_UNKNOWN,
59  	PT_IPV4,
60  	PT_IPV6,
61  	PT_OSI
62  };
63  
64  /*
65   * RFC3032: MPLS label stack encoding
66   */
67  void
mpls_print(const u_char * bp,u_int length)68  mpls_print(const u_char *bp, u_int length)
69  {
70  	const u_char *p;
71  	u_int32_t label_entry;
72  	u_int16_t label_stack_depth = 0;
73  	enum mpls_packet_type pt = PT_UNKNOWN;
74  
75  	p = bp;
76  	printf("MPLS");
77  	do {
78  		TCHECK2(*p, sizeof(label_entry));
79  		label_entry = EXTRACT_32BITS(p);
80  		printf("%s(label %u",
81  		       (label_stack_depth && vflag) ? "\n\t" : " ",
82         		       MPLS_LABEL(label_entry));
83  		label_stack_depth++;
84  		if (vflag &&
85  		    MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0]))
86  			printf(" (%s)", mpls_labelname[MPLS_LABEL(label_entry)]);
87  		printf(", exp %u", MPLS_EXP(label_entry));
88  		if (MPLS_STACK(label_entry))
89  			printf(", [S]");
90  		printf(", ttl %u)", MPLS_TTL(label_entry));
91  
92  		p += sizeof(label_entry);
93  	} while (!MPLS_STACK(label_entry));
94  
95  	/*
96  	 * Try to figure out the packet type.
97  	 */
98  	switch (MPLS_LABEL(label_entry)) {
99  
100  	case 0:	/* IPv4 explicit NULL label */
101  	case 3:	/* IPv4 implicit NULL label */
102  		pt = PT_IPV4;
103  		break;
104  
105  	case 2:	/* IPv6 explicit NULL label */
106  		pt = PT_IPV6;
107  		break;
108  
109  	default:
110  		/*
111  		 * Generally there's no indication of protocol in MPLS label
112  		 * encoding.
113  		 *
114  		 * However, draft-hsmit-isis-aal5mux-00.txt describes a
115  		 * technique for encapsulating IS-IS and IP traffic on the
116  		 * same ATM virtual circuit; you look at the first payload
117  		 * byte to determine the network layer protocol, based on
118  		 * the fact that
119  		 *
120  		 *	1) the first byte of an IP header is 0x45-0x4f
121  		 *	   for IPv4 and 0x60-0x6f for IPv6;
122  		 *
123  		 *	2) the first byte of an OSI CLNP packet is 0x81,
124  		 *	   the first byte of an OSI ES-IS packet is 0x82,
125  		 *	   and the first byte of an OSI IS-IS packet is
126  		 *	   0x83;
127  		 *
128  		 * so the network layer protocol can be inferred from the
129  		 * first byte of the packet, if the protocol is one of the
130  		 * ones listed above.
131  		 *
132  		 * Cisco sends control-plane traffic MPLS-encapsulated in
133  		 * this fashion.
134  		 */
135  		switch(*p) {
136  
137  		case 0x45:
138  		case 0x46:
139  		case 0x47:
140  		case 0x48:
141  		case 0x49:
142  		case 0x4a:
143  		case 0x4b:
144  		case 0x4c:
145  		case 0x4d:
146  		case 0x4e:
147  		case 0x4f:
148  			pt = PT_IPV4;
149  			break;
150  
151  		case 0x60:
152  		case 0x61:
153  		case 0x62:
154  		case 0x63:
155  		case 0x64:
156  		case 0x65:
157  		case 0x66:
158  		case 0x67:
159  		case 0x68:
160  		case 0x69:
161  		case 0x6a:
162  		case 0x6b:
163  		case 0x6c:
164  		case 0x6d:
165  		case 0x6e:
166  		case 0x6f:
167  			pt = PT_IPV6;
168  			break;
169  
170  		case 0x81:
171  		case 0x82:
172  		case 0x83:
173  			pt = PT_OSI;
174  			break;
175  
176  		default:
177  			/* ok bail out - we did not figure out what it is*/
178  			break;
179  		}
180  	}
181  
182  	/*
183  	 * Print the payload.
184  	 */
185  	if (pt == PT_UNKNOWN) {
186  		if (!suppress_default_print)
187  			default_print(p, length - (p - bp));
188  		return;
189  	}
190  	if (vflag)
191  		printf("\n\t");
192  	else
193  		printf(" ");
194  	switch (pt) {
195  
196  	case PT_IPV4:
197  		ip_print(gndo, p, length - (p - bp));
198  		break;
199  
200  	case PT_IPV6:
201  #ifdef INET6
202  		ip6_print(gndo, p, length - (p - bp));
203  #else
204  		printf("IPv6, length: %u", length);
205  #endif
206  		break;
207  
208  	case PT_OSI:
209  		isoclns_print(p, length - (p - bp), length - (p - bp));
210  		break;
211  
212  	default:
213  		break;
214  	}
215  	return;
216  
217  trunc:
218  	printf("[|MPLS]");
219  }
220  
221  
222  /*
223   * Local Variables:
224   * c-style: whitesmith
225   * c-basic-offset: 8
226   * End:
227   */
228