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