xref: /openbsd-src/usr.sbin/tcpdump/print-mpls.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: print-mpls.c,v 1.3 2016/07/11 00:27:50 rzalamena Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 Jason L. Wright (jason@thought.net)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/socket.h>
30 #include <sys/types.h>
31 #include <netmpls/mpls.h>
32 
33 #include <stdio.h>
34 
35 #include "interface.h"
36 #include "extract.h"		    /* must come after interface.h */
37 
38 #define CW_SEQUENCE_MASK       (0x0000ffffU)
39 
40 int controlword_tryprint(const u_char **, u_int *);
41 
42 void
43 mpls_print(const u_char *bp, u_int len)
44 {
45 	u_int32_t tag, label, exp, bottom, ttl;
46 	int has_cw;
47 
48  again:
49 	if (bp + sizeof(tag) > snapend)
50 		goto trunc;
51 
52 	tag = EXTRACT_32BITS(bp);
53 	bp += sizeof(tag);
54 	len -= sizeof(tag);
55 
56 	label = (tag >> 12) & 0xfffff;
57 	exp = (tag >> 9) & 0x7;
58 	bottom = (tag >> 8) & 0x1;
59 	ttl = (tag >> 0) & 0xff;
60 
61 	printf("MPLS(label %u, exp %u, ttl %u) ", label, exp, ttl);
62 
63 	/* XXX decode "Router Alert Label" */
64 
65 	if (!bottom)
66 		goto again;
67 
68 	/* Handle pseudowire control word. */
69 	has_cw = controlword_tryprint(&bp, &len);
70 
71 	/*
72 	 * guessing the underlying protocol is about all we can do if
73 	 * it's not explicitly defined.
74 	 */
75 
76 	switch (label) {
77 	case 0x00000:			/* IPv4 Explicit NULL */
78 		ip_print(bp, len);
79 		break;
80 	case 0x00001:			/* Router Alert */
81 		/* shouldn't happen at stack bottom */
82 		printf("Route-Alert");
83 		break;
84 	case 0x00002:			/* IPv6 Explicit NULL */
85 		ip6_print(bp, len);
86 		break;
87 	case 0x00003:			/* Implicit NULL */
88 		/* shouldn't happen in the tag stack */
89 		printf("Implicit-NULL");
90 		break;
91 
92 	case 0x00004:			/* reserved labels */
93 	case 0x00005:
94 	case 0x00006:
95 	case 0x00007:
96 	case 0x00008:
97 	case 0x00009:
98 	case 0x0000a:
99 	case 0x0000b:
100 	case 0x0000c:
101 	case 0x0000d:
102 	case 0x0000e:
103 	case 0x0000f:
104 		break;
105 
106 	default:			/* dunno, guess? */
107 		if (len == 0)
108 			break;
109 		if (bp >= snapend)
110 			goto trunc;
111 
112 		switch (bp[0] & 0xf0) {
113 		case 0x40:
114 			ip_print(bp, len);
115 			break;
116 		case 0x60:
117 			ip6_print(bp, len);
118 			break;
119 		}
120 	}
121 
122 	if (has_cw)
123 		ether_tryprint(bp, len, 0);
124 
125 	return;
126 trunc:
127 	printf("[|mpls]");
128 }
129 
130 /* Print control word if any and returns 1 on success. */
131 int
132 controlword_tryprint(const u_char **bp, u_int *lenp)
133 {
134 	uint32_t cw, frag, seq;
135 
136 	if (*lenp < 4)
137 		return (0);
138 
139 	cw = EXTRACT_32BITS(*bp);
140 	if (cw & CW_ZERO_MASK)
141 		return (0);
142 
143 	*bp += sizeof(cw);
144 	*lenp += sizeof(cw);
145 
146 	frag = (cw & CW_FRAG_MASK) >> 16;
147 	seq = cw & CW_SEQUENCE_MASK;
148 
149 	printf("CW(frag %u, sequence %u) ", frag, seq);
150 
151 	return (1);
152 }
153