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