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
29276788Sdelphij#define NETDISSECT_REWORKED
3098524Sfenner#ifdef HAVE_CONFIG_H
3198524Sfenner#include "config.h"
3298524Sfenner#endif
3398524Sfenner
34127668Sbms#include <tcpdump-stdinc.h>
3598524Sfenner
3698524Sfenner#include "interface.h"
3798524Sfenner#include "extract.h"			/* must come after interface.h */
38146773Ssam#include "mpls.h"
3998524Sfenner
4098524Sfennerstatic const char *mpls_labelname[] = {
4198524Sfenner/*0*/	"IPv4 explicit NULL", "router alert", "IPv6 explicit NULL",
4298524Sfenner	"implicit NULL", "rsvd",
4398524Sfenner/*5*/	"rsvd", "rsvd", "rsvd", "rsvd", "rsvd",
4498524Sfenner/*10*/	"rsvd", "rsvd", "rsvd", "rsvd", "rsvd",
4598524Sfenner/*15*/	"rsvd",
4698524Sfenner};
4798524Sfenner
48235530Sdelphijenum mpls_packet_type {
49235530Sdelphij	PT_UNKNOWN,
50235530Sdelphij	PT_IPV4,
51235530Sdelphij	PT_IPV6,
52235530Sdelphij	PT_OSI
53235530Sdelphij};
54235530Sdelphij
5598524Sfenner/*
5698524Sfenner * RFC3032: MPLS label stack encoding
5798524Sfenner */
5898524Sfennervoid
59276788Sdelphijmpls_print(netdissect_options *ndo, const u_char *bp, u_int length)
6098524Sfenner{
6198524Sfenner	const u_char *p;
62276788Sdelphij	uint32_t label_entry;
63276788Sdelphij	uint16_t label_stack_depth = 0;
64235530Sdelphij	enum mpls_packet_type pt = PT_UNKNOWN;
6598524Sfenner
6698524Sfenner	p = bp;
67276788Sdelphij	ND_PRINT((ndo, "MPLS"));
68111726Sfenner	do {
69276788Sdelphij		ND_TCHECK2(*p, sizeof(label_entry));
70147899Ssam		label_entry = EXTRACT_32BITS(p);
71276788Sdelphij		ND_PRINT((ndo, "%s(label %u",
72276788Sdelphij		       (label_stack_depth && ndo->ndo_vflag) ? "\n\t" : " ",
73276788Sdelphij       		       MPLS_LABEL(label_entry)));
74235530Sdelphij		label_stack_depth++;
75276788Sdelphij		if (ndo->ndo_vflag &&
76147899Ssam		    MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0]))
77276788Sdelphij			ND_PRINT((ndo, " (%s)", mpls_labelname[MPLS_LABEL(label_entry)]));
78276788Sdelphij		ND_PRINT((ndo, ", exp %u", MPLS_EXP(label_entry)));
79147899Ssam		if (MPLS_STACK(label_entry))
80276788Sdelphij			ND_PRINT((ndo, ", [S]"));
81276788Sdelphij		ND_PRINT((ndo, ", ttl %u)", MPLS_TTL(label_entry)));
8298524Sfenner
83147899Ssam		p += sizeof(label_entry);
84147899Ssam	} while (!MPLS_STACK(label_entry));
8598524Sfenner
86235530Sdelphij	/*
87235530Sdelphij	 * Try to figure out the packet type.
88235530Sdelphij	 */
89147899Ssam	switch (MPLS_LABEL(label_entry)) {
90235530Sdelphij
9198524Sfenner	case 0:	/* IPv4 explicit NULL label */
92235530Sdelphij	case 3:	/* IPv4 implicit NULL label */
93235530Sdelphij		pt = PT_IPV4;
9498524Sfenner		break;
95235530Sdelphij
9698524Sfenner	case 2:	/* IPv6 explicit NULL label */
97235530Sdelphij		pt = PT_IPV6;
9898524Sfenner		break;
99235530Sdelphij
10098524Sfenner	default:
10198524Sfenner		/*
102127668Sbms		 * Generally there's no indication of protocol in MPLS label
103235530Sdelphij		 * encoding.
104235530Sdelphij		 *
105235530Sdelphij		 * However, draft-hsmit-isis-aal5mux-00.txt describes a
106235530Sdelphij		 * technique for encapsulating IS-IS and IP traffic on the
107235530Sdelphij		 * same ATM virtual circuit; you look at the first payload
108235530Sdelphij		 * byte to determine the network layer protocol, based on
109235530Sdelphij		 * the fact that
110235530Sdelphij		 *
111235530Sdelphij		 *	1) the first byte of an IP header is 0x45-0x4f
112235530Sdelphij		 *	   for IPv4 and 0x60-0x6f for IPv6;
113235530Sdelphij		 *
114235530Sdelphij		 *	2) the first byte of an OSI CLNP packet is 0x81,
115235530Sdelphij		 *	   the first byte of an OSI ES-IS packet is 0x82,
116235530Sdelphij		 *	   and the first byte of an OSI IS-IS packet is
117235530Sdelphij		 *	   0x83;
118235530Sdelphij		 *
119235530Sdelphij		 * so the network layer protocol can be inferred from the
120235530Sdelphij		 * first byte of the packet, if the protocol is one of the
121235530Sdelphij		 * ones listed above.
122235530Sdelphij		 *
123235530Sdelphij		 * Cisco sends control-plane traffic MPLS-encapsulated in
124235530Sdelphij		 * this fashion.
12598524Sfenner		 */
126235530Sdelphij		switch(*p) {
127127668Sbms
128235530Sdelphij		case 0x45:
129235530Sdelphij		case 0x46:
130235530Sdelphij		case 0x47:
131235530Sdelphij		case 0x48:
132235530Sdelphij		case 0x49:
133235530Sdelphij		case 0x4a:
134235530Sdelphij		case 0x4b:
135235530Sdelphij		case 0x4c:
136235530Sdelphij		case 0x4d:
137235530Sdelphij		case 0x4e:
138235530Sdelphij		case 0x4f:
139235530Sdelphij			pt = PT_IPV4;
140235530Sdelphij			break;
141276788Sdelphij
142235530Sdelphij		case 0x60:
143235530Sdelphij		case 0x61:
144235530Sdelphij		case 0x62:
145235530Sdelphij		case 0x63:
146235530Sdelphij		case 0x64:
147235530Sdelphij		case 0x65:
148235530Sdelphij		case 0x66:
149235530Sdelphij		case 0x67:
150235530Sdelphij		case 0x68:
151235530Sdelphij		case 0x69:
152235530Sdelphij		case 0x6a:
153235530Sdelphij		case 0x6b:
154235530Sdelphij		case 0x6c:
155235530Sdelphij		case 0x6d:
156235530Sdelphij		case 0x6e:
157235530Sdelphij		case 0x6f:
158235530Sdelphij			pt = PT_IPV6;
159235530Sdelphij			break;
160235530Sdelphij
161235530Sdelphij		case 0x81:
162235530Sdelphij		case 0x82:
163235530Sdelphij		case 0x83:
164235530Sdelphij			pt = PT_OSI;
165235530Sdelphij			break;
166235530Sdelphij
167235530Sdelphij		default:
168235530Sdelphij			/* ok bail out - we did not figure out what it is*/
169235530Sdelphij			break;
170235530Sdelphij		}
171235530Sdelphij	}
172235530Sdelphij
173235530Sdelphij	/*
174235530Sdelphij	 * Print the payload.
175235530Sdelphij	 */
176235530Sdelphij	if (pt == PT_UNKNOWN) {
177276788Sdelphij		if (!ndo->ndo_suppress_default_print)
178276788Sdelphij			ND_DEFAULTPRINT(p, length - (p - bp));
179235530Sdelphij		return;
180235530Sdelphij	}
181276788Sdelphij	ND_PRINT((ndo, ndo->ndo_vflag ? "\n\t" : " "));
182235530Sdelphij	switch (pt) {
183235530Sdelphij
184235530Sdelphij	case PT_IPV4:
185276788Sdelphij		ip_print(ndo, p, length - (p - bp));
186235530Sdelphij		break;
187235530Sdelphij
188235530Sdelphij	case PT_IPV6:
189276788Sdelphij		ip6_print(ndo, p, length - (p - bp));
190235530Sdelphij		break;
191235530Sdelphij
192235530Sdelphij	case PT_OSI:
193276788Sdelphij		isoclns_print(ndo, p, length - (p - bp), length - (p - bp));
194235530Sdelphij		break;
195235530Sdelphij
196235530Sdelphij	default:
197235530Sdelphij		break;
19898524Sfenner	}
199235530Sdelphij	return;
20098524Sfenner
20198524Sfennertrunc:
202276788Sdelphij	ND_PRINT((ndo, "[|MPLS]"));
20398524Sfenner}
204127668Sbms
205146773Ssam
206127668Sbms/*
207146773Ssam * Local Variables:
208146773Ssam * c-style: whitesmith
209146773Ssam * c-basic-offset: 8
210146773Ssam * End:
211127668Sbms */
212