File: | src/usr.sbin/tcpdump/print-nsh.c |
Warning: | line 180, column 2 Value stored to 'l' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: print-nsh.c,v 1.1 2019/12/03 01:43:33 dlg Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2019 David Gwynne <dlg@openbsd.org> |
5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above |
8 | * copyright notice and this permission notice appear in all copies. |
9 | * |
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ |
18 | |
19 | /* |
20 | * RFC 8300 Network Service Header (NSH) |
21 | */ |
22 | |
23 | #include <sys/time.h> |
24 | #include <sys/uio.h> |
25 | #include <sys/socket.h> |
26 | |
27 | #include <netinet/in.h> |
28 | #include <netinet/ip.h> |
29 | #include <arpa/inet.h> |
30 | |
31 | #include <stdio.h> |
32 | #include <string.h> |
33 | #include <ctype.h> |
34 | |
35 | #include "interface.h" |
36 | #include "addrtoname.h" |
37 | #include "extract.h" |
38 | |
39 | #ifndef roundup |
40 | #define roundup(x, y)((((x)+((y)-1))/(y))*(y)) ((((x)+((y)-1))/(y))*(y)) |
41 | #endif |
42 | |
43 | #ifndef nitems |
44 | #define nitems(_a)(sizeof((_a)) / sizeof((_a)[0])) (sizeof((_a)) / sizeof((_a)[0])) |
45 | #endif |
46 | |
47 | struct nsh_header { |
48 | uint32_t base; |
49 | #define NSH_VER_SHIFT30 30 |
50 | #define NSH_VER_MASK(0x03 << 30) (0x03 << NSH_VER_SHIFT30) |
51 | #define NSH_VER_00x0 0x0 |
52 | #define NSH_VER_RESERVED(0x01 << 30) (0x01 << NSH_VER_SHIFT30) |
53 | #define NSH_OAM_SHIFT29 29 |
54 | #define NSH_OAM_MASK(0x01 << 29) (0x01 << NSH_OAM_SHIFT29) |
55 | #define NSH_TTL_SHIFT22 22 |
56 | #define NSH_TTL_MASK(0x3f << 22) (0x3f << NSH_TTL_SHIFT22) |
57 | #define NSH_LEN_SHIFT16 16 |
58 | #define NSH_LEN_MASK(0x3f << 16) (0x3f << NSH_LEN_SHIFT16) |
59 | #define NSH_LEN_FACTOR4 4 |
60 | #define NSH_MDTYPE_SHIFT8 8 |
61 | #define NSH_MDTYPE_MASK(0x0f << 8) (0x0f << NSH_MDTYPE_SHIFT8) |
62 | #define NSH_PROTO_SHIFT0 0 |
63 | #define NSH_PROTO_MASK(0xff << 0) (0xff << NSH_PROTO_SHIFT0) |
64 | |
65 | uint32_t sp; |
66 | #define NSH_SPI_SHIFT8 8 |
67 | #define NSH_SPI_MASK(0xffffff << 8) (0xffffff << NSH_SPI_SHIFT8) |
68 | #define NSH_SI_SHIFT0 0 |
69 | #define NSH_SI_MASK(0xff << 0) (0xff << NSH_SI_SHIFT0) |
70 | }; |
71 | |
72 | #define NSH_PROTO_IPV40x01 0x01 |
73 | #define NSH_PROTO_IPV60x02 0x02 |
74 | #define NSH_PROTO_ETHERNET0x03 0x03 |
75 | #define NSH_PROTO_NSH0x04 0x04 |
76 | #define NSH_PROTO_MPLS0x05 0x05 |
77 | #define NSH_PROTO_EXP10xfe 0xfe /* Experiment 1 */ |
78 | #define NSH_PROTO_EXP20xff 0xff /* Experiment 2 */ |
79 | |
80 | #define NSH_MDTYPE_RESERVED0x0 0x0 |
81 | #define NSH_MDTYPE_10x1 0x1 |
82 | #define NSH_MDTYPE_20x2 0x2 |
83 | #define NSH_MDTYPE_EXP0xf 0xf /* Experimentation */ |
84 | |
85 | struct nsh_context_header { |
86 | uint32_t ch[4]; |
87 | }; |
88 | |
89 | struct nsh_md_header { |
90 | uint16_t class; |
91 | uint8_t type; |
92 | uint8_t len; |
93 | #define NSH_MD_LEN_MASK0x7f 0x7f |
94 | }; |
95 | |
96 | static void nsh_print_bytes(const void *, u_int); |
97 | |
98 | static void nsh_print_mdtype1(const u_char *, u_int); |
99 | static void nsh_print_mdtype2(const u_char *, u_int); |
100 | |
101 | void |
102 | nsh_print(const u_char *p, u_int length) |
103 | { |
104 | struct nsh_header nsh; |
105 | uint32_t field, len, proto; |
106 | int l = snapend - p; |
107 | |
108 | printf("NSH"); |
109 | |
110 | if (l < sizeof(nsh)) |
111 | goto trunc; |
112 | if (length < sizeof(nsh)) { |
113 | printf(" encapsulation truncated"); |
114 | return; |
115 | } |
116 | |
117 | nsh.base = EXTRACT_32BITS(p)((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(p) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(p) + 3)); |
118 | nsh.sp = EXTRACT_32BITS(p + sizeof(nsh.base))((u_int32_t)*((const u_int8_t *)(p + sizeof(nsh.base)) + 0) << 24 | (u_int32_t)*((const u_int8_t *)(p + sizeof(nsh.base)) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(p + sizeof( nsh.base)) + 2) << 8 | (u_int32_t)*((const u_int8_t *)( p + sizeof(nsh.base)) + 3)); |
119 | |
120 | field = (nsh.base & NSH_VER_MASK(0x03 << 30)) >> NSH_VER_SHIFT30; |
121 | switch (field) { |
122 | case NSH_VER_00x0: |
123 | break; |
124 | case NSH_VER_RESERVED(0x01 << 30): |
125 | printf(" Reserved version"); |
126 | return; |
127 | default: |
128 | printf(" Unknown version %u", field); |
129 | return; |
130 | } |
131 | |
132 | field = (nsh.sp & NSH_SPI_MASK(0xffffff << 8)) >> NSH_SPI_SHIFT8; |
133 | printf(" spi %u", field); |
134 | field = (nsh.sp & NSH_SI_MASK(0xff << 0)) >> NSH_SI_SHIFT0; |
135 | printf(" si %u", field); |
136 | |
137 | len = ((nsh.base & NSH_LEN_MASK(0x3f << 16)) >> NSH_LEN_SHIFT16) * NSH_LEN_FACTOR4; |
138 | if (vflag > 1) { |
139 | field = (nsh.base & NSH_TTL_MASK(0x3f << 22)) >> NSH_TTL_SHIFT22; |
140 | printf(" (ttl %u, len %u)", field, len); |
141 | } |
142 | |
143 | if (l < len) |
144 | goto trunc; |
145 | if (length < len) { |
146 | printf(" encapsulation truncated"); |
147 | return; |
148 | } |
149 | |
150 | p += sizeof(nsh); |
151 | l -= sizeof(nsh); |
152 | len -= sizeof(nsh); |
153 | |
154 | field = (nsh.base & NSH_MDTYPE_MASK(0x0f << 8)) >> NSH_MDTYPE_SHIFT8; |
155 | switch (field) { |
156 | case NSH_MDTYPE_RESERVED0x0: |
157 | printf(" md-type-reserved"); |
158 | break; |
159 | case NSH_MDTYPE_10x1: |
160 | printf(" md1"); |
161 | if (vflag) |
162 | nsh_print_mdtype1(p, len); |
163 | break; |
164 | case NSH_MDTYPE_20x2: |
165 | printf(" md2"); |
166 | if (vflag) |
167 | nsh_print_mdtype2(p, len); |
168 | break; |
169 | case NSH_MDTYPE_EXP0xf: |
170 | printf(" mdtype-experimentation"); |
171 | break; |
172 | default: |
173 | printf(" mdtype-unknown-0x%02x", field); |
174 | break; |
175 | } |
176 | |
177 | printf("%s", vflag ? "\n " : ": "); |
178 | |
179 | p += len; |
180 | l -= len; |
Value stored to 'l' is never read | |
181 | length -= len; |
182 | |
183 | proto = (nsh.base & NSH_PROTO_MASK(0xff << 0)) >> NSH_PROTO_SHIFT0; |
184 | |
185 | if (nsh.base & NSH_OAM_MASK(0x01 << 29)) |
186 | printf("NSH OAM (proto 0x%0x, len %u)", proto, length); |
187 | else { |
188 | switch (field) { |
189 | case NSH_PROTO_IPV40x01: |
190 | ip_print(p, length); |
191 | return; |
192 | case NSH_PROTO_IPV60x02: |
193 | ip_print(p, length); |
194 | return; |
195 | case NSH_PROTO_ETHERNET0x03: |
196 | ether_tryprint(p, length, 0); |
197 | return; |
198 | case NSH_PROTO_NSH0x04: |
199 | nsh_print(p, length); |
200 | return; |
201 | case NSH_PROTO_MPLS0x05: |
202 | mpls_print(p, length); |
203 | return; |
204 | case NSH_PROTO_EXP10xfe: |
205 | printf("NSH Experiment 1"); |
206 | break; |
207 | case NSH_PROTO_EXP20xff: |
208 | printf("NSH Experiment 2"); |
209 | break; |
210 | default: |
211 | printf("nsh-unknown-proto-0x%02x", field); |
212 | break; |
213 | } |
214 | } |
215 | |
216 | if (vflag) |
217 | default_print_unaligned(p, length); |
218 | |
219 | return; |
220 | trunc: |
221 | printf(" [|nsh]"); |
222 | } |
223 | |
224 | static void |
225 | nsh_print_mdtype1(const u_char *p, u_int len) |
226 | { |
227 | const struct nsh_context_header *ctx; |
228 | size_t i; |
229 | |
230 | if (len != sizeof(*ctx)) |
231 | printf("nsh-mdtype1-length-%u (not %zu)", len, sizeof(*ctx)); |
232 | |
233 | printf("\n\tcontext"); |
234 | |
235 | ctx = (const struct nsh_context_header *)p; |
236 | for (i = 0; i < nitems(ctx->ch)(sizeof((ctx->ch)) / sizeof((ctx->ch)[0])); i++) { |
237 | printf(" "); |
238 | nsh_print_bytes(&ctx->ch[i], sizeof(ctx->ch[i])); |
239 | } |
240 | } |
241 | |
242 | static void |
243 | nsh_print_mdtype2(const u_char *p, u_int l) |
244 | { |
245 | if (l == 0) |
246 | return; |
247 | |
248 | do { |
249 | struct nsh_md_header h; |
250 | uint8_t len; |
251 | |
252 | if (l < sizeof(h)) |
253 | goto trunc; |
254 | |
255 | memcpy(&h, p, sizeof(h)); |
256 | p += sizeof(h); |
257 | l -= sizeof(h); |
258 | |
259 | h.class = ntohs(h.class)(__uint16_t)(__builtin_constant_p(h.class) ? (__uint16_t)(((__uint16_t )(h.class) & 0xffU) << 8 | ((__uint16_t)(h.class) & 0xff00U) >> 8) : __swap16md(h.class)); |
260 | len = h.len & NSH_MD_LEN_MASK0x7f; |
261 | printf("\n\tmd class %u type %u", h.class, h.type); |
262 | if (len > 0) { |
263 | printf(" "); |
264 | nsh_print_bytes(p, len); |
265 | } |
266 | |
267 | len = roundup(len, 4)((((len)+((4)-1))/(4))*(4)); |
268 | if (l < len) |
269 | goto trunc; |
270 | |
271 | p += len; |
272 | l -= len; |
273 | } while (l > 0); |
274 | |
275 | return; |
276 | trunc: |
277 | printf("[|nsh md]"); |
278 | } |
279 | |
280 | static void |
281 | nsh_print_bytes(const void *b, u_int l) |
282 | { |
283 | const uint8_t *p = b; |
284 | u_int i; |
285 | |
286 | for (i = 0; i < l; i++) { |
287 | int ch = p[i]; |
288 | #if 0 |
289 | if (isprint(ch) && !isspace(ch)) |
290 | putchar(ch)(!__isthreaded ? __sputc(ch, (&__sF[1])) : (putc)(ch, (& __sF[1]))); |
291 | else { |
292 | switch (ch) { |
293 | case '\\': |
294 | printf("\\\\"); |
295 | break; |
296 | case '\0': |
297 | printf("\\0"); |
298 | break; |
299 | default: |
300 | printf("\\x%02x", ch); |
301 | break; |
302 | } |
303 | } |
304 | #else |
305 | printf("%02x", ch); |
306 | #endif |
307 | } |
308 | } |