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 |
|
|
} |