xref: /openbsd-src/usr.sbin/tcpdump/print-mpls.c (revision 868399f9388362410093d7eeaff21dc76ce83a78)
1 /*	$OpenBSD: print-mpls.c,v 1.4 2018/07/06 07:00:49 dlg 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
mpls_print(const u_char * bp,u_int len)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 	do {
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 	} while (!bottom);
65 
66 	/* Handle pseudowire control word. */
67 	has_cw = controlword_tryprint(&bp, &len);
68 
69 	/*
70 	 * guessing the underlying protocol is about all we can do if
71 	 * it's not explicitly defined.
72 	 */
73 
74 	switch (label) {
75 	case 0x00000:			/* IPv4 Explicit NULL */
76 		ip_print(bp, len);
77 		break;
78 	case 0x00001:			/* Router Alert */
79 		/* shouldn't happen at stack bottom */
80 		printf("Route-Alert");
81 		break;
82 	case 0x00002:			/* IPv6 Explicit NULL */
83 		ip6_print(bp, len);
84 		break;
85 	case 0x00003:			/* Implicit NULL */
86 		/* shouldn't happen in the tag stack */
87 		printf("Implicit-NULL");
88 		break;
89 
90 	case 0x00004:			/* reserved labels */
91 	case 0x00005:
92 	case 0x00006:
93 	case 0x00007:
94 	case 0x00008:
95 	case 0x00009:
96 	case 0x0000a:
97 	case 0x0000b:
98 	case 0x0000c:
99 	case 0x0000d:
100 	case 0x0000e:
101 	case 0x0000f:
102 		break;
103 
104 	default:			/* dunno, guess? */
105 		if (len == 0)
106 			break;
107 		if (bp >= snapend)
108 			goto trunc;
109 
110 		switch (bp[0] & 0xf0) {
111 		case 0x40:
112 			ip_print(bp, len);
113 			break;
114 		case 0x60:
115 			ip6_print(bp, len);
116 			break;
117 		}
118 	}
119 
120 	if (has_cw)
121 		ether_tryprint(bp, len, 0);
122 
123 	return;
124 trunc:
125 	printf("[|mpls]");
126 }
127 
128 /* Print control word if any and returns 1 on success. */
129 int
controlword_tryprint(const u_char ** bp,u_int * lenp)130 controlword_tryprint(const u_char **bp, u_int *lenp)
131 {
132 	uint32_t cw, frag, seq;
133 
134 	if (*lenp < 4)
135 		return (0);
136 
137 	cw = EXTRACT_32BITS(*bp);
138 	if (cw & CW_ZERO_MASK)
139 		return (0);
140 
141 	*bp += sizeof(cw);
142 	*lenp += sizeof(cw);
143 
144 	frag = (cw & CW_FRAG_MASK) >> 16;
145 	seq = cw & CW_SEQUENCE_MASK;
146 
147 	printf("CW(frag %u, sequence %u) ", frag, seq);
148 
149 	return (1);
150 }
151