Print this page
dccp: snoop, build system fixes
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <stdio.h>
27 27 #include <string.h>
28 28 #include <fcntl.h>
29 29 #include <string.h>
30 30 #include <sys/types.h>
31 31 #include <sys/time.h>
32 32
33 33 #include <sys/stropts.h>
34 34 #include <sys/socket.h>
35 35 #include <net/if.h>
36 36 #include <netinet/in_systm.h>
37 37 #include <netinet/in.h>
38 38 #include <netinet/ip.h>
39 39 #include <netinet/ip6.h>
40 40 #include <netinet/ip_icmp.h>
41 41 #include <netinet/icmp6.h>
42 42 #include <netinet/if_ether.h>
43 43 #include <inet/ip.h>
44 44 #include <inet/ip6.h>
45 45 #include <arpa/inet.h>
46 46 #include <netdb.h>
47 47 #include <tsol/label.h>
48 48 #include <sys/tsol/tndb.h>
49 49 #include <sys/tsol/label_macro.h>
50 50
51 51 #include "snoop.h"
52 52
53 53
54 54 /*
55 55 * IPv6 extension header masks. These are used by the print_ipv6_extensions()
56 56 * function to return information to the caller about which extension headers
57 57 * were processed. This can be useful if the caller wants to know if the
58 58 * packet is an IPv6 fragment, for example.
59 59 */
60 60 #define SNOOP_HOPOPTS 0x01U
61 61 #define SNOOP_ROUTING 0x02U
62 62 #define SNOOP_DSTOPTS 0x04U
63 63 #define SNOOP_FRAGMENT 0x08U
64 64 #define SNOOP_AH 0x10U
65 65 #define SNOOP_ESP 0x20U
66 66 #define SNOOP_IPV6 0x40U
67 67
68 68 static void prt_routing_hdr(int, const struct ip6_rthdr *);
69 69 static void prt_fragment_hdr(int, const struct ip6_frag *);
70 70 static void prt_hbh_options(int, const struct ip6_hbh *);
71 71 static void prt_dest_options(int, const struct ip6_dest *);
72 72 static void print_route(const uchar_t *);
73 73 static void print_ipoptions(const uchar_t *, int);
74 74 static void print_ripso(const uchar_t *);
75 75 static void print_cipso(const uchar_t *);
76 76
77 77 /* Keep track of how many nested IP headers we have. */
78 78 unsigned int encap_levels;
79 79 unsigned int total_encap_levels = 1;
80 80
81 81 int
82 82 interpret_ip(int flags, const struct ip *ip, int fraglen)
83 83 {
84 84 uchar_t *data;
85 85 char buff[24];
86 86 boolean_t isfrag = B_FALSE;
87 87 boolean_t morefrag;
88 88 uint16_t fragoffset;
89 89 int hdrlen;
90 90 uint16_t iplen, uitmp;
91 91
92 92 if (ip->ip_v == IPV6_VERSION) {
93 93 iplen = interpret_ipv6(flags, (ip6_t *)ip, fraglen);
94 94 return (iplen);
95 95 }
96 96
97 97 if (encap_levels == 0)
98 98 total_encap_levels = 0;
99 99 encap_levels++;
100 100 total_encap_levels++;
101 101
102 102 hdrlen = ip->ip_hl * 4;
103 103 data = ((uchar_t *)ip) + hdrlen;
104 104 iplen = ntohs(ip->ip_len) - hdrlen;
105 105 fraglen -= hdrlen;
106 106 if (fraglen > iplen)
107 107 fraglen = iplen;
108 108 if (fraglen < 0) {
109 109 (void) snprintf(get_sum_line(), MAXLINE,
110 110 "IP truncated: header missing %d bytes", -fraglen);
111 111 encap_levels--;
112 112 return (fraglen + iplen);
113 113 }
114 114 /*
115 115 * We flag this as a fragment if the more fragments bit is set, or
116 116 * if the fragment offset is non-zero.
117 117 */
118 118 morefrag = (ntohs(ip->ip_off) & IP_MF) == 0 ? B_FALSE : B_TRUE;
119 119 fragoffset = (ntohs(ip->ip_off) & 0x1FFF) * 8;
120 120 if (morefrag || fragoffset != 0)
121 121 isfrag = B_TRUE;
122 122
123 123 src_name = addrtoname(AF_INET, &ip->ip_src);
124 124 dst_name = addrtoname(AF_INET, &ip->ip_dst);
125 125
126 126 if (flags & F_SUM) {
127 127 if (isfrag) {
128 128 (void) snprintf(get_sum_line(), MAXLINE,
129 129 "%s IP fragment ID=%d Offset=%-4d MF=%d TOS=0x%x "
130 130 "TTL=%d",
131 131 getproto(ip->ip_p),
132 132 ntohs(ip->ip_id),
133 133 fragoffset,
134 134 morefrag,
135 135 ip->ip_tos,
136 136 ip->ip_ttl);
137 137 } else {
138 138 (void) strlcpy(buff, inet_ntoa(ip->ip_dst),
139 139 sizeof (buff));
140 140 uitmp = ntohs(ip->ip_len);
141 141 (void) snprintf(get_sum_line(), MAXLINE,
142 142 "IP D=%s S=%s LEN=%u%s, ID=%d, TOS=0x%x, TTL=%d",
143 143 buff,
144 144 inet_ntoa(ip->ip_src),
145 145 uitmp,
146 146 iplen > fraglen ? "?" : "",
147 147 ntohs(ip->ip_id),
148 148 ip->ip_tos,
149 149 ip->ip_ttl);
150 150 }
151 151 }
152 152
153 153 if (flags & F_DTAIL) {
154 154 show_header("IP: ", "IP Header", iplen);
155 155 show_space();
156 156 (void) snprintf(get_line(0, 0), get_line_remain(),
157 157 "Version = %d", ip->ip_v);
158 158 (void) snprintf(get_line(0, 0), get_line_remain(),
159 159 "Header length = %d bytes", hdrlen);
160 160 (void) snprintf(get_line(0, 0), get_line_remain(),
161 161 "Type of service = 0x%02x", ip->ip_tos);
162 162 (void) snprintf(get_line(0, 0), get_line_remain(),
163 163 " xxx. .... = %d (precedence)",
164 164 ip->ip_tos >> 5);
165 165 (void) snprintf(get_line(0, 0), get_line_remain(),
166 166 " %s", getflag(ip->ip_tos, IPTOS_LOWDELAY,
167 167 "low delay", "normal delay"));
168 168 (void) snprintf(get_line(0, 0), get_line_remain(), " %s",
169 169 getflag(ip->ip_tos, IPTOS_THROUGHPUT,
170 170 "high throughput", "normal throughput"));
171 171 (void) snprintf(get_line(0, 0), get_line_remain(), " %s",
172 172 getflag(ip->ip_tos, IPTOS_RELIABILITY,
173 173 "high reliability", "normal reliability"));
174 174 (void) snprintf(get_line(0, 0), get_line_remain(), " %s",
175 175 getflag(ip->ip_tos, IPTOS_ECT,
176 176 "ECN capable transport", "not ECN capable transport"));
177 177 (void) snprintf(get_line(0, 0), get_line_remain(), " %s",
178 178 getflag(ip->ip_tos, IPTOS_CE,
179 179 "ECN congestion experienced",
180 180 "no ECN congestion experienced"));
181 181 /* warning: ip_len is signed in netinet/ip.h */
182 182 uitmp = ntohs(ip->ip_len);
183 183 (void) snprintf(get_line(0, 0), get_line_remain(),
184 184 "Total length = %u bytes%s", uitmp,
185 185 iplen > fraglen ? " -- truncated" : "");
186 186 (void) snprintf(get_line(0, 0), get_line_remain(),
187 187 "Identification = %d", ntohs(ip->ip_id));
188 188 /* warning: ip_off is signed in netinet/ip.h */
189 189 uitmp = ntohs(ip->ip_off);
190 190 (void) snprintf(get_line(0, 0), get_line_remain(),
191 191 "Flags = 0x%x", uitmp >> 12);
192 192 (void) snprintf(get_line(0, 0), get_line_remain(), " %s",
193 193 getflag(uitmp >> 8, IP_DF >> 8,
194 194 "do not fragment", "may fragment"));
195 195 (void) snprintf(get_line(0, 0), get_line_remain(), " %s",
196 196 getflag(uitmp >> 8, IP_MF >> 8,
197 197 "more fragments", "last fragment"));
198 198 (void) snprintf(get_line(0, 0), get_line_remain(),
199 199 "Fragment offset = %u bytes",
200 200 fragoffset);
201 201 (void) snprintf(get_line(0, 0), get_line_remain(),
202 202 "Time to live = %d seconds/hops",
203 203 ip->ip_ttl);
204 204 (void) snprintf(get_line(0, 0), get_line_remain(),
205 205 "Protocol = %d (%s)", ip->ip_p,
206 206 getproto(ip->ip_p));
207 207 /*
208 208 * XXX need to compute checksum and print whether it's correct
209 209 */
210 210 (void) snprintf(get_line(0, 0), get_line_remain(),
211 211 "Header checksum = %04x",
212 212 ntohs(ip->ip_sum));
213 213 (void) snprintf(get_line(0, 0), get_line_remain(),
214 214 "Source address = %s, %s",
215 215 inet_ntoa(ip->ip_src), addrtoname(AF_INET, &ip->ip_src));
216 216 (void) snprintf(get_line(0, 0), get_line_remain(),
217 217 "Destination address = %s, %s",
218 218 inet_ntoa(ip->ip_dst), addrtoname(AF_INET, &ip->ip_dst));
219 219
220 220 /* Print IP options - if any */
221 221
222 222 print_ipoptions((const uchar_t *)(ip + 1),
223 223 hdrlen - sizeof (struct ip));
224 224 show_space();
225 225 }
226 226
227 227 /*
228 228 * If we are in detail mode, and this is not the first fragment of
229 229 * a fragmented packet, print out a little line stating this.
230 230 * Otherwise, go to the next protocol layer only if this is not a
231 231 * fragment, or we are in detail mode and this is the first fragment
232 232 * of a fragmented packet.
233 233 */
234 234 if (flags & F_DTAIL && fragoffset != 0) {
235 235 (void) snprintf(get_detail_line(0, 0), MAXLINE,
236 236 "%s: [%d byte(s) of data, continuation of IP ident=%d]",
237 237 getproto(ip->ip_p),
238 238 iplen,
239 239 ntohs(ip->ip_id));
240 240 } else if (!isfrag || (flags & F_DTAIL) && isfrag && fragoffset == 0) {
241 241 /* go to the next protocol layer */
242 242
243 243 if (fraglen > 0) {
244 244 switch (ip->ip_p) {
245 245 case IPPROTO_IP:
246 246 break;
247 247 case IPPROTO_ENCAP:
248 248 (void) interpret_ip(flags,
249 249 /* LINTED: alignment */
250 250 (const struct ip *)data, fraglen);
251 251 break;
252 252 case IPPROTO_ICMP:
253 253 (void) interpret_icmp(flags,
254 254 /* LINTED: alignment */
255 255 (struct icmp *)data, iplen, fraglen);
256 256 break;
257 257 case IPPROTO_IGMP:
258 258 interpret_igmp(flags, data, iplen, fraglen);
259 259 break;
260 260 case IPPROTO_GGP:
261 261 break;
262 262 case IPPROTO_TCP:
263 263 (void) interpret_tcp(flags,
264 264 (struct tcphdr *)data, iplen, fraglen);
265 265 break;
266 266
267 267 case IPPROTO_ESP:
268 268 (void) interpret_esp(flags, data, iplen,
269 269 fraglen);
270 270 break;
271 271 case IPPROTO_AH:
272 272 (void) interpret_ah(flags, data, iplen,
273 273 fraglen);
274 274 break;
275 275
276 276 case IPPROTO_OSPF:
277 277 interpret_ospf(flags, data, iplen, fraglen);
278 278 break;
279 279
280 280 case IPPROTO_EGP:
281 281 case IPPROTO_PUP:
282 282 break;
283 283 case IPPROTO_UDP:
284 284 (void) interpret_udp(flags,
285 285 (struct udphdr *)data, iplen, fraglen);
286 286 break;
287 287
288 288 case IPPROTO_IDP:
289 289 case IPPROTO_HELLO:
290 290 case IPPROTO_ND:
291 291 case IPPROTO_RAW:
↓ open down ↓ |
291 lines elided |
↑ open up ↑ |
292 292 break;
293 293 case IPPROTO_IPV6: /* IPV6 encap */
294 294 /* LINTED: alignment */
295 295 (void) interpret_ipv6(flags, (ip6_t *)data,
296 296 iplen);
297 297 break;
298 298 case IPPROTO_SCTP:
299 299 (void) interpret_sctp(flags,
300 300 (struct sctp_hdr *)data, iplen, fraglen);
301 301 break;
302 + case IPPROTO_DCCP:
303 + (void) interpret_dccp(flags,
304 + (struct dccphdr *)data, iplen, fraglen);
305 + break;
302 306 }
303 307 }
304 308 }
305 309
306 310 encap_levels--;
307 311 return (iplen);
308 312 }
309 313
310 314 int
311 315 interpret_ipv6(int flags, const ip6_t *ip6h, int fraglen)
312 316 {
313 317 uint8_t *data;
314 318 int hdrlen, iplen;
315 319 int version, flow, class;
316 320 uchar_t proto;
317 321 boolean_t isfrag = B_FALSE;
318 322 uint8_t extmask;
319 323 /*
320 324 * The print_srcname and print_dstname strings are the hostname
321 325 * parts of the verbose IPv6 header output, including the comma
322 326 * and the space after the litteral address strings.
323 327 */
324 328 char print_srcname[MAXHOSTNAMELEN + 2];
325 329 char print_dstname[MAXHOSTNAMELEN + 2];
326 330 char src_addrstr[INET6_ADDRSTRLEN];
327 331 char dst_addrstr[INET6_ADDRSTRLEN];
328 332
329 333 iplen = ntohs(ip6h->ip6_plen);
330 334 hdrlen = IPV6_HDR_LEN;
331 335 fraglen -= hdrlen;
332 336 if (fraglen < 0)
333 337 return (fraglen + hdrlen);
334 338 data = ((uint8_t *)ip6h) + hdrlen;
335 339
336 340 proto = ip6h->ip6_nxt;
337 341
338 342 src_name = addrtoname(AF_INET6, &ip6h->ip6_src);
339 343 dst_name = addrtoname(AF_INET6, &ip6h->ip6_dst);
340 344
341 345 /*
342 346 * Use endian-aware masks to extract traffic class and
343 347 * flowinfo. Also, flowinfo is now 20 bits and class 8
344 348 * rather than 24 and 4.
345 349 */
346 350 class = ntohl((ip6h->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20);
347 351 flow = ntohl(ip6h->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL);
348 352
349 353 /*
350 354 * NOTE: the F_SUM and F_DTAIL flags are mutually exclusive,
351 355 * so the code within the first part of the following if statement
352 356 * will not affect the detailed printing of the packet.
353 357 */
354 358 if (flags & F_SUM) {
355 359 (void) snprintf(get_sum_line(), MAXLINE,
356 360 "IPv6 S=%s D=%s LEN=%d HOPS=%d CLASS=0x%x FLOW=0x%x",
357 361 src_name, dst_name, iplen, ip6h->ip6_hops, class, flow);
358 362 } else if (flags & F_DTAIL) {
359 363
360 364 (void) inet_ntop(AF_INET6, &ip6h->ip6_src, src_addrstr,
361 365 INET6_ADDRSTRLEN);
362 366 (void) inet_ntop(AF_INET6, &ip6h->ip6_dst, dst_addrstr,
363 367 INET6_ADDRSTRLEN);
364 368
365 369 version = ntohl(ip6h->ip6_vcf) >> 28;
366 370
367 371 if (strcmp(src_name, src_addrstr) == 0) {
368 372 print_srcname[0] = '\0';
369 373 } else {
370 374 snprintf(print_srcname, sizeof (print_srcname),
371 375 ", %s", src_name);
372 376 }
373 377
374 378 if (strcmp(dst_name, dst_addrstr) == 0) {
375 379 print_dstname[0] = '\0';
376 380 } else {
377 381 snprintf(print_dstname, sizeof (print_dstname),
378 382 ", %s", dst_name);
379 383 }
380 384
381 385 show_header("IPv6: ", "IPv6 Header", iplen);
382 386 show_space();
383 387
384 388 (void) snprintf(get_line(0, 0), get_line_remain(),
385 389 "Version = %d", version);
386 390 (void) snprintf(get_line(0, 0), get_line_remain(),
387 391 "Traffic Class = %d", class);
388 392 (void) snprintf(get_line(0, 0), get_line_remain(),
389 393 "Flow label = 0x%x", flow);
390 394 (void) snprintf(get_line(0, 0), get_line_remain(),
391 395 "Payload length = %d", iplen);
392 396 (void) snprintf(get_line(0, 0), get_line_remain(),
393 397 "Next Header = %d (%s)", proto,
394 398 getproto(proto));
395 399 (void) snprintf(get_line(0, 0), get_line_remain(),
396 400 "Hop Limit = %d", ip6h->ip6_hops);
397 401 (void) snprintf(get_line(0, 0), get_line_remain(),
398 402 "Source address = %s%s", src_addrstr, print_srcname);
399 403 (void) snprintf(get_line(0, 0), get_line_remain(),
400 404 "Destination address = %s%s", dst_addrstr, print_dstname);
401 405
402 406 show_space();
403 407 }
404 408
405 409 /*
406 410 * Print IPv6 Extension Headers, or skip them in the summary case.
407 411 * Set isfrag to true if one of the extension headers encounterred
408 412 * was a fragment header.
409 413 */
410 414 if (proto == IPPROTO_HOPOPTS || proto == IPPROTO_DSTOPTS ||
411 415 proto == IPPROTO_ROUTING || proto == IPPROTO_FRAGMENT) {
412 416 extmask = print_ipv6_extensions(flags, &data, &proto, &iplen,
413 417 &fraglen);
414 418 if ((extmask & SNOOP_FRAGMENT) != 0) {
415 419 isfrag = B_TRUE;
416 420 }
417 421 }
418 422
419 423 /*
420 424 * We only want to print upper layer information if this is not
421 425 * a fragment, or if we're printing in detail. Note that the
422 426 * proto variable will be set to IPPROTO_NONE if this is a fragment
423 427 * with a non-zero fragment offset.
424 428 */
425 429 if (!isfrag || flags & F_DTAIL) {
426 430 /* go to the next protocol layer */
427 431
428 432 switch (proto) {
429 433 case IPPROTO_IP:
430 434 break;
431 435 case IPPROTO_ENCAP:
432 436 /* LINTED: alignment */
433 437 (void) interpret_ip(flags, (const struct ip *)data,
434 438 fraglen);
435 439 break;
436 440 case IPPROTO_ICMPV6:
437 441 /* LINTED: alignment */
438 442 (void) interpret_icmpv6(flags, (icmp6_t *)data, iplen,
439 443 fraglen);
440 444 break;
441 445 case IPPROTO_IGMP:
442 446 interpret_igmp(flags, data, iplen, fraglen);
443 447 break;
444 448 case IPPROTO_GGP:
445 449 break;
446 450 case IPPROTO_TCP:
447 451 (void) interpret_tcp(flags, (struct tcphdr *)data,
448 452 iplen, fraglen);
449 453 break;
450 454 case IPPROTO_ESP:
451 455 (void) interpret_esp(flags, data, iplen, fraglen);
452 456 break;
453 457 case IPPROTO_AH:
454 458 (void) interpret_ah(flags, data, iplen, fraglen);
455 459 break;
456 460 case IPPROTO_EGP:
457 461 case IPPROTO_PUP:
458 462 break;
459 463 case IPPROTO_UDP:
460 464 (void) interpret_udp(flags, (struct udphdr *)data,
461 465 iplen, fraglen);
462 466 break;
463 467 case IPPROTO_IDP:
464 468 case IPPROTO_HELLO:
465 469 case IPPROTO_ND:
466 470 case IPPROTO_RAW:
467 471 break;
468 472 case IPPROTO_IPV6:
469 473 /* LINTED: alignment */
↓ open down ↓ |
158 lines elided |
↑ open up ↑ |
470 474 (void) interpret_ipv6(flags, (const ip6_t *)data,
471 475 iplen);
472 476 break;
473 477 case IPPROTO_SCTP:
474 478 (void) interpret_sctp(flags, (struct sctp_hdr *)data,
475 479 iplen, fraglen);
476 480 break;
477 481 case IPPROTO_OSPF:
478 482 interpret_ospf6(flags, data, iplen, fraglen);
479 483 break;
484 + case IPPROTO_DCCP:
485 + (void) interpret_dccp(flags, (struct dccphdr *)data,
486 + iplen, fraglen);
487 + break;
480 488 }
481 489 }
482 490
483 491 return (iplen);
484 492 }
485 493
486 494 /*
487 495 * ip_ext: data including the extension header.
488 496 * iplen: length of the data remaining in the packet.
489 497 * Returns a mask of IPv6 extension headers it processed.
490 498 */
491 499 uint8_t
492 500 print_ipv6_extensions(int flags, uint8_t **hdr, uint8_t *next, int *iplen,
493 501 int *fraglen)
494 502 {
495 503 uint8_t *data_ptr;
496 504 uchar_t proto = *next;
497 505 boolean_t is_extension_header;
498 506 struct ip6_hbh *ipv6ext_hbh;
499 507 struct ip6_dest *ipv6ext_dest;
500 508 struct ip6_rthdr *ipv6ext_rthdr;
501 509 struct ip6_frag *ipv6ext_frag;
502 510 uint32_t exthdrlen;
503 511 uint8_t extmask = 0;
504 512
505 513 if ((hdr == NULL) || (*hdr == NULL) || (next == NULL) || (iplen == 0))
506 514 return (0);
507 515
508 516 data_ptr = *hdr;
509 517 is_extension_header = B_TRUE;
510 518 while (is_extension_header) {
511 519
512 520 /*
513 521 * There must be at least enough data left to read the
514 522 * next header and header length fields from the next
515 523 * header.
516 524 */
517 525 if (*fraglen < 2) {
518 526 return (extmask);
519 527 }
520 528
521 529 switch (proto) {
522 530 case IPPROTO_HOPOPTS:
523 531 ipv6ext_hbh = (struct ip6_hbh *)data_ptr;
524 532 exthdrlen = 8 + ipv6ext_hbh->ip6h_len * 8;
525 533 if (*fraglen <= exthdrlen) {
526 534 return (extmask);
527 535 }
528 536 prt_hbh_options(flags, ipv6ext_hbh);
529 537 extmask |= SNOOP_HOPOPTS;
530 538 proto = ipv6ext_hbh->ip6h_nxt;
531 539 break;
532 540 case IPPROTO_DSTOPTS:
533 541 ipv6ext_dest = (struct ip6_dest *)data_ptr;
534 542 exthdrlen = 8 + ipv6ext_dest->ip6d_len * 8;
535 543 if (*fraglen <= exthdrlen) {
536 544 return (extmask);
537 545 }
538 546 prt_dest_options(flags, ipv6ext_dest);
539 547 extmask |= SNOOP_DSTOPTS;
540 548 proto = ipv6ext_dest->ip6d_nxt;
541 549 break;
542 550 case IPPROTO_ROUTING:
543 551 ipv6ext_rthdr = (struct ip6_rthdr *)data_ptr;
544 552 exthdrlen = 8 + ipv6ext_rthdr->ip6r_len * 8;
545 553 if (*fraglen <= exthdrlen) {
546 554 return (extmask);
547 555 }
548 556 prt_routing_hdr(flags, ipv6ext_rthdr);
549 557 extmask |= SNOOP_ROUTING;
550 558 proto = ipv6ext_rthdr->ip6r_nxt;
551 559 break;
552 560 case IPPROTO_FRAGMENT:
553 561 /* LINTED: alignment */
554 562 ipv6ext_frag = (struct ip6_frag *)data_ptr;
555 563 exthdrlen = sizeof (struct ip6_frag);
556 564 if (*fraglen <= exthdrlen) {
557 565 return (extmask);
558 566 }
559 567 prt_fragment_hdr(flags, ipv6ext_frag);
560 568 extmask |= SNOOP_FRAGMENT;
561 569 /*
562 570 * If this is not the first fragment, forget about
563 571 * the rest of the packet, snoop decoding is
564 572 * stateless.
565 573 */
566 574 if ((ipv6ext_frag->ip6f_offlg & IP6F_OFF_MASK) != 0)
567 575 proto = IPPROTO_NONE;
568 576 else
569 577 proto = ipv6ext_frag->ip6f_nxt;
570 578 break;
571 579 default:
572 580 is_extension_header = B_FALSE;
573 581 break;
574 582 }
575 583
576 584 if (is_extension_header) {
577 585 *iplen -= exthdrlen;
578 586 *fraglen -= exthdrlen;
579 587 data_ptr += exthdrlen;
580 588 }
581 589 }
582 590
583 591 *next = proto;
584 592 *hdr = data_ptr;
585 593 return (extmask);
586 594 }
587 595
588 596 static void
589 597 print_ipoptions(const uchar_t *opt, int optlen)
590 598 {
591 599 int len;
592 600 int remain;
593 601 char *line;
594 602 const char *truncstr;
595 603
596 604 if (optlen <= 0) {
597 605 (void) snprintf(get_line(0, 0), get_line_remain(),
598 606 "No options");
599 607 return;
600 608 }
601 609
602 610 (void) snprintf(get_line(0, 0), get_line_remain(),
603 611 "Options: (%d bytes)", optlen);
604 612
605 613 while (optlen > 0) {
606 614 line = get_line(0, 0);
607 615 remain = get_line_remain();
608 616 len = opt[1];
609 617 truncstr = len > optlen ? "?" : "";
610 618 switch (opt[0]) {
611 619 case IPOPT_EOL:
612 620 (void) strlcpy(line, " - End of option list", remain);
613 621 return;
614 622 case IPOPT_NOP:
615 623 (void) strlcpy(line, " - No op", remain);
616 624 len = 1;
617 625 break;
618 626 case IPOPT_RR:
619 627 (void) snprintf(line, remain,
620 628 " - Record route (%d bytes%s)", len, truncstr);
621 629 print_route(opt);
622 630 break;
623 631 case IPOPT_TS:
624 632 (void) snprintf(line, remain,
625 633 " - Time stamp (%d bytes%s)", len, truncstr);
626 634 break;
627 635 case IPOPT_SECURITY:
628 636 (void) snprintf(line, remain, " - RIPSO (%d bytes%s)",
629 637 len, truncstr);
630 638 print_ripso(opt);
631 639 break;
632 640 case IPOPT_COMSEC:
633 641 (void) snprintf(line, remain, " - CIPSO (%d bytes%s)",
634 642 len, truncstr);
635 643 print_cipso(opt);
636 644 break;
637 645 case IPOPT_LSRR:
638 646 (void) snprintf(line, remain,
639 647 " - Loose source route (%d bytes%s)", len,
640 648 truncstr);
641 649 print_route(opt);
642 650 break;
643 651 case IPOPT_SATID:
644 652 (void) snprintf(line, remain,
645 653 " - SATNET Stream id (%d bytes%s)",
646 654 len, truncstr);
647 655 break;
648 656 case IPOPT_SSRR:
649 657 (void) snprintf(line, remain,
650 658 " - Strict source route, (%d bytes%s)", len,
651 659 truncstr);
652 660 print_route(opt);
653 661 break;
654 662 default:
655 663 (void) snprintf(line, remain,
656 664 " - Option %d (unknown - %d bytes%s) %s",
657 665 opt[0], len, truncstr,
658 666 tohex((char *)&opt[2], len - 2));
659 667 break;
660 668 }
661 669 if (len <= 0) {
662 670 (void) snprintf(line, remain,
663 671 " - Incomplete option len %d", len);
664 672 break;
665 673 }
666 674 opt += len;
667 675 optlen -= len;
668 676 }
669 677 }
670 678
671 679 static void
672 680 print_route(const uchar_t *opt)
673 681 {
674 682 int len, pointer, remain;
675 683 struct in_addr addr;
676 684 char *line;
677 685
678 686 len = opt[1];
679 687 pointer = opt[2];
680 688
681 689 (void) snprintf(get_line(0, 0), get_line_remain(),
682 690 " Pointer = %d", pointer);
683 691
684 692 pointer -= IPOPT_MINOFF;
685 693 opt += (IPOPT_OFFSET + 1);
686 694 len -= (IPOPT_OFFSET + 1);
687 695
688 696 while (len > 0) {
689 697 line = get_line(0, 0);
690 698 remain = get_line_remain();
691 699 memcpy((char *)&addr, opt, sizeof (addr));
692 700 if (addr.s_addr == INADDR_ANY)
693 701 (void) strlcpy(line, " -", remain);
694 702 else
695 703 (void) snprintf(line, remain, " %s",
696 704 addrtoname(AF_INET, &addr));
697 705 if (pointer == 0)
698 706 (void) strlcat(line, " <-- (current)", remain);
699 707
700 708 opt += sizeof (addr);
701 709 len -= sizeof (addr);
702 710 pointer -= sizeof (addr);
703 711 }
704 712 }
705 713
706 714 char *
707 715 getproto(int p)
708 716 {
709 717 switch (p) {
710 718 case IPPROTO_HOPOPTS: return ("IPv6-HopOpts");
711 719 case IPPROTO_IPV6: return ("IPv6");
712 720 case IPPROTO_ROUTING: return ("IPv6-Route");
713 721 case IPPROTO_FRAGMENT: return ("IPv6-Frag");
714 722 case IPPROTO_RSVP: return ("RSVP");
715 723 case IPPROTO_ENCAP: return ("IP-in-IP");
716 724 case IPPROTO_AH: return ("AH");
717 725 case IPPROTO_ESP: return ("ESP");
718 726 case IPPROTO_ICMP: return ("ICMP");
719 727 case IPPROTO_ICMPV6: return ("ICMPv6");
720 728 case IPPROTO_DSTOPTS: return ("IPv6-DstOpts");
721 729 case IPPROTO_IGMP: return ("IGMP");
722 730 case IPPROTO_GGP: return ("GGP");
↓ open down ↓ |
233 lines elided |
↑ open up ↑ |
723 731 case IPPROTO_TCP: return ("TCP");
724 732 case IPPROTO_EGP: return ("EGP");
725 733 case IPPROTO_PUP: return ("PUP");
726 734 case IPPROTO_UDP: return ("UDP");
727 735 case IPPROTO_IDP: return ("IDP");
728 736 case IPPROTO_HELLO: return ("HELLO");
729 737 case IPPROTO_ND: return ("ND");
730 738 case IPPROTO_EON: return ("EON");
731 739 case IPPROTO_RAW: return ("RAW");
732 740 case IPPROTO_OSPF: return ("OSPF");
741 + case IPPROTO_DCCP: return ("DCCP");
733 742 default: return ("");
734 743 }
735 744 }
736 745
737 746 static void
738 747 prt_routing_hdr(int flags, const struct ip6_rthdr *ipv6ext_rthdr)
739 748 {
740 749 uint8_t nxt_hdr;
741 750 uint8_t type;
742 751 uint32_t len;
743 752 uint8_t segleft;
744 753 uint32_t numaddrs;
745 754 int i;
746 755 struct ip6_rthdr0 *ipv6ext_rthdr0;
747 756 struct in6_addr *addrs;
748 757 char addr[INET6_ADDRSTRLEN];
749 758
750 759 /* in summary mode, we don't do anything. */
751 760 if (flags & F_SUM) {
752 761 return;
753 762 }
754 763
755 764 nxt_hdr = ipv6ext_rthdr->ip6r_nxt;
756 765 type = ipv6ext_rthdr->ip6r_type;
757 766 len = 8 * (ipv6ext_rthdr->ip6r_len + 1);
758 767 segleft = ipv6ext_rthdr->ip6r_segleft;
759 768
760 769 show_header("IPv6-Route: ", "IPv6 Routing Header", 0);
761 770 show_space();
762 771
763 772 (void) snprintf(get_line(0, 0), get_line_remain(),
764 773 "Next header = %d (%s)", nxt_hdr, getproto(nxt_hdr));
765 774 (void) snprintf(get_line(0, 0), get_line_remain(),
766 775 "Header length = %d", len);
767 776 (void) snprintf(get_line(0, 0), get_line_remain(),
768 777 "Routing type = %d", type);
769 778 (void) snprintf(get_line(0, 0), get_line_remain(),
770 779 "Segments left = %d", segleft);
771 780
772 781 if (type == IPV6_RTHDR_TYPE_0) {
773 782 /*
774 783 * XXX This loop will print all addresses in the routing header,
775 784 * XXX not just the segments left.
776 785 * XXX (The header length field is twice the number of
777 786 * XXX addresses)
778 787 * XXX At some future time, we may want to change this
779 788 * XXX to differentiate between the hops yet to do
780 789 * XXX and the hops already taken.
781 790 */
782 791 /* LINTED: alignment */
783 792 ipv6ext_rthdr0 = (struct ip6_rthdr0 *)ipv6ext_rthdr;
784 793 numaddrs = ipv6ext_rthdr0->ip6r0_len / 2;
785 794 addrs = (struct in6_addr *)(ipv6ext_rthdr0 + 1);
786 795 for (i = 0; i < numaddrs; i++) {
787 796 (void) inet_ntop(AF_INET6, &addrs[i], addr,
788 797 INET6_ADDRSTRLEN);
789 798 (void) snprintf(get_line(0, 0), get_line_remain(),
790 799 "address[%d]=%s", i, addr);
791 800 }
792 801 }
793 802
794 803 show_space();
795 804 }
796 805
797 806 static void
798 807 prt_fragment_hdr(int flags, const struct ip6_frag *ipv6ext_frag)
799 808 {
800 809 boolean_t morefrag;
801 810 uint16_t fragoffset;
802 811 uint8_t nxt_hdr;
803 812 uint32_t fragident;
804 813
805 814 /* extract the various fields from the fragment header */
806 815 nxt_hdr = ipv6ext_frag->ip6f_nxt;
807 816 morefrag = (ipv6ext_frag->ip6f_offlg & IP6F_MORE_FRAG) == 0
808 817 ? B_FALSE : B_TRUE;
809 818 fragoffset = ntohs(ipv6ext_frag->ip6f_offlg & IP6F_OFF_MASK);
810 819 fragident = ntohl(ipv6ext_frag->ip6f_ident);
811 820
812 821 if (flags & F_SUM) {
813 822 (void) snprintf(get_sum_line(), MAXLINE,
814 823 "IPv6 fragment ID=%u Offset=%-4d MF=%d",
815 824 fragident,
816 825 fragoffset,
817 826 morefrag);
818 827 } else { /* F_DTAIL */
819 828 show_header("IPv6-Frag: ", "IPv6 Fragment Header", 0);
820 829 show_space();
821 830
822 831 (void) snprintf(get_line(0, 0), get_line_remain(),
823 832 "Next Header = %d (%s)", nxt_hdr, getproto(nxt_hdr));
824 833 (void) snprintf(get_line(0, 0), get_line_remain(),
825 834 "Fragment Offset = %d", fragoffset);
826 835 (void) snprintf(get_line(0, 0), get_line_remain(),
827 836 "More Fragments Flag = %s", morefrag ? "true" : "false");
828 837 (void) snprintf(get_line(0, 0), get_line_remain(),
829 838 "Identification = %u", fragident);
830 839
831 840 show_space();
832 841 }
833 842 }
834 843
835 844 static void
836 845 print_ip6opt_ls(const uchar_t *data, unsigned int op_len)
837 846 {
838 847 uint32_t doi;
839 848 uint8_t sotype, solen;
840 849 uint16_t value, value2;
841 850 char *cp;
842 851 int remlen;
843 852 boolean_t printed;
844 853
845 854 (void) snprintf(get_line(0, 0), get_line_remain(),
846 855 "Labeled Security Option len = %u bytes%s", op_len,
847 856 op_len < sizeof (uint32_t) || (op_len & 1) != 0 ? "?" : "");
848 857 if (op_len < sizeof (uint32_t))
849 858 return;
850 859 GETINT32(doi, data);
851 860 (void) snprintf(get_line(0, 0), get_line_remain(),
852 861 " DOI = %d (%s)", doi, doi == IP6LS_DOI_V4 ? "IPv4" : "???");
853 862 op_len -= sizeof (uint32_t);
854 863 while (op_len > 0) {
855 864 GETINT8(sotype, data);
856 865 if (op_len < 2) {
857 866 (void) snprintf(get_line(0, 0), get_line_remain(),
858 867 " truncated %u suboption (no len)", sotype);
859 868 break;
860 869 }
861 870 GETINT8(solen, data);
862 871 if (solen < 2 || solen > op_len) {
863 872 (void) snprintf(get_line(0, 0), get_line_remain(),
864 873 " bad %u suboption (len 2 <= %u <= %u)",
865 874 sotype, solen, op_len);
866 875 if (solen < 2)
867 876 solen = 2;
868 877 if (solen > op_len)
869 878 solen = op_len;
870 879 }
871 880 op_len -= solen;
872 881 solen -= 2;
873 882 cp = get_line(0, 0);
874 883 remlen = get_line_remain();
875 884 (void) strlcpy(cp, " ", remlen);
876 885 cp += 4;
877 886 remlen -= 4;
878 887 printed = B_TRUE;
879 888 switch (sotype) {
880 889 case IP6LS_TT_LEVEL:
881 890 if (solen != 2) {
882 891 printed = B_FALSE;
883 892 break;
884 893 }
885 894 GETINT16(value, data);
886 895 (void) snprintf(cp, remlen, "Level %u", value);
887 896 solen = 0;
888 897 break;
889 898 case IP6LS_TT_VECTOR:
890 899 (void) strlcpy(cp, "Bit-Vector: ", remlen);
891 900 remlen -= strlen(cp);
892 901 cp += strlen(cp);
893 902 while (solen > 1) {
894 903 GETINT16(value, data);
895 904 solen -= 2;
896 905 (void) snprintf(cp, remlen, "%04x", value);
897 906 remlen -= strlen(cp);
898 907 cp += strlen(cp);
899 908 }
900 909 break;
901 910 case IP6LS_TT_ENUM:
902 911 (void) strlcpy(cp, "Enumeration:", remlen);
903 912 remlen -= strlen(cp);
904 913 cp += strlen(cp);
905 914 while (solen > 1) {
906 915 GETINT16(value, data);
907 916 solen -= 2;
908 917 (void) snprintf(cp, remlen, " %u", value);
909 918 remlen -= strlen(cp);
910 919 cp += strlen(cp);
911 920 }
912 921 break;
913 922 case IP6LS_TT_RANGES:
914 923 (void) strlcpy(cp, "Ranges:", remlen);
915 924 remlen -= strlen(cp);
916 925 cp += strlen(cp);
917 926 while (solen > 3) {
918 927 GETINT16(value, data);
919 928 GETINT16(value2, data);
920 929 solen -= 4;
921 930 (void) snprintf(cp, remlen, " %u-%u", value,
922 931 value2);
923 932 remlen -= strlen(cp);
924 933 cp += strlen(cp);
925 934 }
926 935 break;
927 936 case IP6LS_TT_V4:
928 937 (void) strlcpy(cp, "IPv4 Option", remlen);
929 938 print_ipoptions(data, solen);
930 939 solen = 0;
931 940 break;
932 941 case IP6LS_TT_DEST:
933 942 (void) snprintf(cp, remlen,
934 943 "Destination-Only Data length %u", solen);
935 944 solen = 0;
936 945 break;
937 946 default:
938 947 (void) snprintf(cp, remlen,
939 948 " unknown %u suboption (len %u)", sotype, solen);
940 949 solen = 0;
941 950 break;
942 951 }
943 952 if (solen != 0) {
944 953 if (printed) {
945 954 cp = get_line(0, 0);
946 955 remlen = get_line_remain();
947 956 }
948 957 (void) snprintf(cp, remlen,
949 958 " malformed %u suboption (remaining %u)",
950 959 sotype, solen);
951 960 data += solen;
952 961 }
953 962 }
954 963 }
955 964
956 965 static void
957 966 prt_hbh_options(int flags, const struct ip6_hbh *ipv6ext_hbh)
958 967 {
959 968 const uint8_t *data, *ndata;
960 969 uint32_t len;
961 970 uint8_t op_type;
962 971 uint8_t op_len;
963 972 uint8_t nxt_hdr;
964 973
965 974 /* in summary mode, we don't do anything. */
966 975 if (flags & F_SUM) {
967 976 return;
968 977 }
969 978
970 979 show_header("IPv6-HopOpts: ", "IPv6 Hop-by-Hop Options Header", 0);
971 980 show_space();
972 981
973 982 /*
974 983 * Store the lengh of this ext hdr in bytes. The caller has
975 984 * ensured that there is at least len bytes of data left.
976 985 */
977 986 len = ipv6ext_hbh->ip6h_len * 8 + 8;
978 987
979 988 ndata = (const uint8_t *)ipv6ext_hbh + 2;
980 989 len -= 2;
981 990
982 991 nxt_hdr = ipv6ext_hbh->ip6h_nxt;
983 992 (void) snprintf(get_line(0, 0), get_line_remain(),
984 993 "Next Header = %u (%s)", nxt_hdr, getproto(nxt_hdr));
985 994
986 995 while (len > 0) {
987 996 data = ndata;
988 997 GETINT8(op_type, data);
989 998 /* This is the only one-octet IPv6 option */
990 999 if (op_type == IP6OPT_PAD1) {
991 1000 (void) snprintf(get_line(0, 0), get_line_remain(),
992 1001 "pad1 option ");
993 1002 len--;
994 1003 ndata = data;
995 1004 continue;
996 1005 }
997 1006 GETINT8(op_len, data);
998 1007 if (len < 2 || op_len + 2 > len) {
999 1008 (void) snprintf(get_line(0, 0), get_line_remain(),
1000 1009 "Error: option %u truncated (%u + 2 > %u)",
1001 1010 op_type, op_len, len);
1002 1011 op_len = len - 2;
1003 1012 /*
1004 1013 * Continue processing the malformed option so that we
1005 1014 * can display as much as possible.
1006 1015 */
1007 1016 }
1008 1017
1009 1018 /* advance pointers to the next option */
1010 1019 len -= op_len + 2;
1011 1020 ndata = data + op_len;
1012 1021
1013 1022 /* process this option */
1014 1023 switch (op_type) {
1015 1024 case IP6OPT_PADN:
1016 1025 (void) snprintf(get_line(0, 0), get_line_remain(),
1017 1026 "padN option len = %u", op_len);
1018 1027 break;
1019 1028 case IP6OPT_JUMBO: {
1020 1029 uint32_t payload_len;
1021 1030
1022 1031 (void) snprintf(get_line(0, 0), get_line_remain(),
1023 1032 "Jumbo Payload Option len = %u bytes%s", op_len,
1024 1033 op_len == sizeof (uint32_t) ? "" : "?");
1025 1034 if (op_len == sizeof (uint32_t)) {
1026 1035 GETINT32(payload_len, data);
1027 1036 (void) snprintf(get_line(0, 0),
1028 1037 get_line_remain(),
1029 1038 "Jumbo Payload Length = %u bytes",
1030 1039 payload_len);
1031 1040 }
1032 1041 break;
1033 1042 }
1034 1043 case IP6OPT_ROUTER_ALERT: {
1035 1044 uint16_t value;
1036 1045 const char *label[] = {"MLD", "RSVP", "AN"};
1037 1046
1038 1047 (void) snprintf(get_line(0, 0), get_line_remain(),
1039 1048 "Router Alert Option len = %u bytes%s", op_len,
1040 1049 op_len == sizeof (uint16_t) ? "" : "?");
1041 1050 if (op_len == sizeof (uint16_t)) {
1042 1051 GETINT16(value, data);
1043 1052 (void) snprintf(get_line(0, 0),
1044 1053 get_line_remain(),
1045 1054 "Alert Type = %d (%s)", value,
1046 1055 value < sizeof (label) / sizeof (label[0]) ?
1047 1056 label[value] : "???");
1048 1057 }
1049 1058 break;
1050 1059 }
1051 1060 case IP6OPT_LS:
1052 1061 print_ip6opt_ls(data, op_len);
1053 1062 break;
1054 1063 default:
1055 1064 (void) snprintf(get_line(0, 0), get_line_remain(),
1056 1065 "Option type = %u, len = %u", op_type, op_len);
1057 1066 break;
1058 1067 }
1059 1068 }
1060 1069
1061 1070 show_space();
1062 1071 }
1063 1072
1064 1073 static void
1065 1074 prt_dest_options(int flags, const struct ip6_dest *ipv6ext_dest)
1066 1075 {
1067 1076 const uint8_t *data, *ndata;
1068 1077 uint32_t len;
1069 1078 uint8_t op_type;
1070 1079 uint32_t op_len;
1071 1080 uint8_t nxt_hdr;
1072 1081 uint8_t value;
1073 1082
1074 1083 /* in summary mode, we don't do anything. */
1075 1084 if (flags & F_SUM) {
1076 1085 return;
1077 1086 }
1078 1087
1079 1088 show_header("IPv6-DstOpts: ", "IPv6 Destination Options Header", 0);
1080 1089 show_space();
1081 1090
1082 1091 /*
1083 1092 * Store the length of this ext hdr in bytes. The caller has
1084 1093 * ensured that there is at least len bytes of data left.
1085 1094 */
1086 1095 len = ipv6ext_dest->ip6d_len * 8 + 8;
1087 1096
1088 1097 ndata = (const uint8_t *)ipv6ext_dest + 2; /* skip hdr/len */
1089 1098 len -= 2;
1090 1099
1091 1100 nxt_hdr = ipv6ext_dest->ip6d_nxt;
1092 1101 (void) snprintf(get_line(0, 0), get_line_remain(),
1093 1102 "Next Header = %u (%s)", nxt_hdr, getproto(nxt_hdr));
1094 1103
1095 1104 while (len > 0) {
1096 1105 data = ndata;
1097 1106 GETINT8(op_type, data);
1098 1107 if (op_type == IP6OPT_PAD1) {
1099 1108 (void) snprintf(get_line(0, 0), get_line_remain(),
1100 1109 "pad1 option ");
1101 1110 len--;
1102 1111 ndata = data;
1103 1112 continue;
1104 1113 }
1105 1114 GETINT8(op_len, data);
1106 1115 if (len < 2 || op_len + 2 > len) {
1107 1116 (void) snprintf(get_line(0, 0), get_line_remain(),
1108 1117 "Error: option %u truncated (%u + 2 > %u)",
1109 1118 op_type, op_len, len);
1110 1119 op_len = len - 2;
1111 1120 /*
1112 1121 * Continue processing the malformed option so that we
1113 1122 * can display as much as possible.
1114 1123 */
1115 1124 }
1116 1125
1117 1126 /* advance pointers to the next option */
1118 1127 len -= op_len + 2;
1119 1128 ndata = data + op_len;
1120 1129
1121 1130 /* process this option */
1122 1131 switch (op_type) {
1123 1132 case IP6OPT_PADN:
1124 1133 (void) snprintf(get_line(0, 0), get_line_remain(),
1125 1134 "padN option len = %u", op_len);
1126 1135 break;
1127 1136 case IP6OPT_TUNNEL_LIMIT:
1128 1137 GETINT8(value, data);
1129 1138 (void) snprintf(get_line(0, 0), get_line_remain(),
1130 1139 "tunnel encapsulation limit len = %d, value = %d",
1131 1140 op_len, value);
1132 1141 break;
1133 1142 case IP6OPT_LS:
1134 1143 print_ip6opt_ls(data, op_len);
1135 1144 break;
1136 1145 default:
1137 1146 (void) snprintf(get_line(0, 0), get_line_remain(),
1138 1147 "Option type = %u, len = %u", op_type, op_len);
1139 1148 break;
1140 1149 }
1141 1150 }
1142 1151
1143 1152 show_space();
1144 1153 }
1145 1154
1146 1155 #define ALABEL_MAXLEN 256
1147 1156
1148 1157 static char ascii_label[ALABEL_MAXLEN];
1149 1158 static char *plabel = ascii_label;
1150 1159
1151 1160 struct snoop_pair {
1152 1161 int val;
1153 1162 const char *name;
1154 1163 };
1155 1164
1156 1165 static struct snoop_pair ripso_class_tbl[] = {
1157 1166 TSOL_CL_TOP_SECRET, "TOP SECRET",
1158 1167 TSOL_CL_SECRET, "SECRET",
1159 1168 TSOL_CL_CONFIDENTIAL, "CONFIDENTIAL",
1160 1169 TSOL_CL_UNCLASSIFIED, "UNCLASSIFIED",
1161 1170 -1, NULL
1162 1171 };
1163 1172
1164 1173 static struct snoop_pair ripso_prot_tbl[] = {
1165 1174 TSOL_PA_GENSER, "GENSER",
1166 1175 TSOL_PA_SIOP_ESI, "SIOP-ESI",
1167 1176 TSOL_PA_SCI, "SCI",
1168 1177 TSOL_PA_NSA, "NSA",
1169 1178 TSOL_PA_DOE, "DOE",
1170 1179 0x04, "UNASSIGNED",
1171 1180 0x02, "UNASSIGNED",
1172 1181 -1, NULL
1173 1182 };
1174 1183
1175 1184 static struct snoop_pair *
1176 1185 get_pair_byval(struct snoop_pair pairlist[], int val)
1177 1186 {
1178 1187 int i;
1179 1188
1180 1189 for (i = 0; pairlist[i].name != NULL; i++)
1181 1190 if (pairlist[i].val == val)
1182 1191 return (&pairlist[i]);
1183 1192 return (NULL);
1184 1193 }
1185 1194
1186 1195 static void
1187 1196 print_ripso(const uchar_t *opt)
1188 1197 {
1189 1198 struct snoop_pair *ripso_class;
1190 1199 int i, index, prot_len;
1191 1200 boolean_t first_prot;
1192 1201 char line[100], *ptr;
1193 1202
1194 1203 prot_len = opt[1] - 3;
1195 1204 if (prot_len < 0)
1196 1205 return;
1197 1206
1198 1207 show_header("RIPSO: ", "Revised IP Security Option", 0);
1199 1208 show_space();
1200 1209
1201 1210 (void) snprintf(get_line(0, 0), get_line_remain(),
1202 1211 "Type = Basic Security Option (%d), Length = %d", opt[0], opt[1]);
1203 1212
1204 1213 /*
1205 1214 * Display Classification Level
1206 1215 */
1207 1216 ripso_class = get_pair_byval(ripso_class_tbl, (int)opt[2]);
1208 1217 if (ripso_class != NULL)
1209 1218 (void) snprintf(get_line(0, 0), get_line_remain(),
1210 1219 "Classification = Unknown (0x%02x)", opt[2]);
1211 1220 else
1212 1221 (void) snprintf(get_line(0, 0), get_line_remain(),
1213 1222 "Classification = %s (0x%02x)",
1214 1223 ripso_class->name, ripso_class->val);
1215 1224
1216 1225 /*
1217 1226 * Display Protection Authority Flags
1218 1227 */
1219 1228 (void) snprintf(line, sizeof (line), "Protection Authority = ");
1220 1229 ptr = line;
1221 1230 first_prot = B_TRUE;
1222 1231 for (i = 0; i < prot_len; i++) {
1223 1232 index = 0;
1224 1233 while (ripso_prot_tbl[index].name != NULL) {
1225 1234 if (opt[3 + i] & ripso_prot_tbl[index].val) {
1226 1235 ptr = strchr(ptr, 0);
1227 1236 if (!first_prot) {
1228 1237 (void) strlcpy(ptr, ", ",
1229 1238 sizeof (line) - (ptr - line));
1230 1239 ptr = strchr(ptr, 0);
1231 1240 }
1232 1241 (void) snprintf(ptr,
1233 1242 sizeof (line) - (ptr - line),
1234 1243 "%s (0x%02x)",
1235 1244 ripso_prot_tbl[index].name,
1236 1245 ripso_prot_tbl[index].val);
1237 1246 }
1238 1247 index++;
1239 1248 }
1240 1249 if ((opt[3 + i] & 1) == 0)
1241 1250 break;
1242 1251 }
1243 1252 if (!first_prot)
1244 1253 (void) snprintf(get_line(0, 0), get_line_remain(), "%s", line);
1245 1254 else
1246 1255 (void) snprintf(get_line(0, 0), get_line_remain(), "%sNone",
1247 1256 line);
1248 1257 }
1249 1258
1250 1259 #define CIPSO_GENERIC_ARRAY_LEN 200
1251 1260
1252 1261 /*
1253 1262 * Return 1 if CIPSO SL and Categories are all 1's; 0 otherwise.
1254 1263 *
1255 1264 * Note: opt starts with "Tag Type":
1256 1265 *
1257 1266 * |tag_type(1)|tag_length(1)|align(1)|sl(1)|categories(variable)|
1258 1267 *
1259 1268 */
1260 1269 static boolean_t
1261 1270 cipso_high(const uchar_t *opt)
1262 1271 {
1263 1272 int i;
1264 1273
1265 1274 if (((int)opt[1] + 6) < IP_MAX_OPT_LENGTH)
1266 1275 return (B_FALSE);
1267 1276 for (i = 0; i < ((int)opt[1] - 3); i++)
1268 1277 if (opt[3 + i] != 0xff)
1269 1278 return (B_FALSE);
1270 1279 return (B_TRUE);
1271 1280 }
1272 1281
1273 1282 /*
1274 1283 * Converts CIPSO label to SL.
1275 1284 *
1276 1285 * Note: opt starts with "Tag Type":
1277 1286 *
1278 1287 * |tag_type(1)|tag_length(1)|align(1)|sl(1)|categories(variable)|
1279 1288 *
1280 1289 */
1281 1290 static void
1282 1291 cipso2sl(const uchar_t *opt, bslabel_t *sl, int *high)
1283 1292 {
1284 1293 int i, taglen;
1285 1294 uchar_t *q = (uchar_t *)&((_bslabel_impl_t *)sl)->compartments;
1286 1295
1287 1296 *high = 0;
1288 1297 taglen = opt[1];
1289 1298 memset((caddr_t)sl, 0, sizeof (bslabel_t));
1290 1299
1291 1300 if (cipso_high(opt)) {
1292 1301 BSLHIGH(sl);
1293 1302 *high = 1;
1294 1303 } else {
1295 1304 LCLASS_SET((_bslabel_impl_t *)sl, opt[3]);
1296 1305 for (i = 0; i < taglen - TSOL_TT1_MIN_LENGTH; i++)
1297 1306 q[i] = opt[TSOL_TT1_MIN_LENGTH + i];
1298 1307 }
1299 1308 SETBLTYPE(sl, SUN_SL_ID);
1300 1309 }
1301 1310
1302 1311 static int
1303 1312 interpret_cipso_tagtype1(const uchar_t *opt)
1304 1313 {
1305 1314 int i, taglen, ishigh;
1306 1315 bslabel_t sl;
1307 1316 char line[CIPSO_GENERIC_ARRAY_LEN], *ptr;
1308 1317
1309 1318 taglen = opt[1];
1310 1319 if (taglen < TSOL_TT1_MIN_LENGTH ||
1311 1320 taglen > TSOL_TT1_MAX_LENGTH)
1312 1321 return (taglen);
1313 1322
1314 1323 (void) snprintf(get_line(0, 0), get_line_remain(),
1315 1324 "Tag Type = %d, Tag Length = %d", opt[0], opt[1]);
1316 1325 (void) snprintf(get_line(0, 0), get_line_remain(),
1317 1326 "Sensitivity Level = 0x%02x", opt[3]);
1318 1327 ptr = line;
1319 1328 for (i = 0; i < taglen - TSOL_TT1_MIN_LENGTH; i++) {
1320 1329 (void) snprintf(ptr, sizeof (line) - (ptr - line), "%02x",
1321 1330 opt[TSOL_TT1_MIN_LENGTH + i]);
1322 1331 ptr = strchr(ptr, 0);
1323 1332 }
1324 1333 if (i != 0) {
1325 1334 (void) snprintf(get_line(0, 0), get_line_remain(),
1326 1335 "Categories = ");
1327 1336 (void) snprintf(get_line(0, 0), get_line_remain(), "\t%s",
1328 1337 line);
1329 1338 } else {
1330 1339 (void) snprintf(get_line(0, 0), get_line_remain(),
1331 1340 "Categories = None");
1332 1341 }
1333 1342 cipso2sl(opt, &sl, &ishigh);
1334 1343 if (is_system_labeled()) {
1335 1344 if (bsltos(&sl, &plabel, ALABEL_MAXLEN,
1336 1345 LONG_CLASSIFICATION|LONG_WORDS|VIEW_INTERNAL) < 0) {
1337 1346 (void) snprintf(get_line(0, 0), get_line_remain(),
1338 1347 "The Sensitivity Level and Categories can't be "
1339 1348 "mapped to a valid SL");
1340 1349 } else {
1341 1350 (void) snprintf(get_line(0, 0), get_line_remain(),
1342 1351 "The Sensitivity Level and Categories are mapped "
1343 1352 "to the SL:");
1344 1353 (void) snprintf(get_line(0, 0), get_line_remain(),
1345 1354 "\t%s", ascii_label);
1346 1355 }
1347 1356 }
1348 1357 return (taglen);
1349 1358 }
1350 1359
1351 1360 /*
1352 1361 * The following struct definition #define's are copied from TS1.x. They are
1353 1362 * not used here (except TTYPE_3_MAX_TOKENS), but included as a reference for
1354 1363 * the tag type 3 packet format.
1355 1364 */
1356 1365 #define TTYPE_3_MAX_TOKENS 7
1357 1366
1358 1367 /*
1359 1368 * Display CIPSO tag type 3 which is defined by MAXSIX.
1360 1369 */
1361 1370 static int
1362 1371 interpret_cipso_tagtype3(const uchar_t *opt)
1363 1372 {
1364 1373 uchar_t tagtype;
1365 1374 int index, numtokens, taglen;
1366 1375 uint16_t mask;
1367 1376 uint32_t token;
1368 1377 static const char *name[] = {
1369 1378 "SL",
1370 1379 "NCAV",
1371 1380 "INTEG",
1372 1381 "SID",
1373 1382 "undefined",
1374 1383 "undefined",
1375 1384 "IL",
1376 1385 "PRIVS",
1377 1386 "LUID",
1378 1387 "PID",
1379 1388 "IDS",
1380 1389 "ACL"
1381 1390 };
1382 1391
1383 1392 tagtype = *opt++;
1384 1393 (void) memcpy(&mask, opt + 3, sizeof (mask));
1385 1394 (void) snprintf(get_line(0, 0), get_line_remain(),
1386 1395 "Tag Type = %d (MAXSIX)", tagtype);
1387 1396 (void) snprintf(get_line(0, 0), get_line_remain(),
1388 1397 "Generation = 0x%02x%02x%02x, Mask = 0x%04x", opt[0], opt[1],
1389 1398 opt[2], mask);
1390 1399 opt += 3 + sizeof (mask);
1391 1400
1392 1401 /*
1393 1402 * Display tokens
1394 1403 */
1395 1404 numtokens = 0;
1396 1405 index = 0;
1397 1406 while (mask != 0 && numtokens < TTYPE_3_MAX_TOKENS) {
1398 1407 if (mask & 0x0001) {
1399 1408 (void) memcpy(&token, opt, sizeof (token));
1400 1409 opt += sizeof (token);
1401 1410 (void) snprintf(get_line(0, 0), get_line_remain(),
1402 1411 "Attribute = %s, Token = 0x%08x",
1403 1412 index < sizeof (name) / sizeof (*name) ?
1404 1413 name[index] : "unknown", token);
1405 1414 numtokens++;
1406 1415 }
1407 1416 mask = mask >> 1;
1408 1417 index++;
1409 1418 }
1410 1419
1411 1420 taglen = 6 + numtokens * 4;
1412 1421 return (taglen);
1413 1422 }
1414 1423
1415 1424 static void
1416 1425 print_cipso(const uchar_t *opt)
1417 1426 {
1418 1427 int optlen, taglen, tagnum;
1419 1428 uint32_t doi;
1420 1429 char line[CIPSO_GENERIC_ARRAY_LEN];
1421 1430 char *oldnest;
1422 1431
1423 1432 optlen = opt[1];
1424 1433 if (optlen < TSOL_CIPSO_MIN_LENGTH || optlen > TSOL_CIPSO_MAX_LENGTH)
1425 1434 return;
1426 1435
1427 1436 oldnest = prot_nest_prefix;
1428 1437 prot_nest_prefix = prot_prefix;
1429 1438 show_header("CIPSO: ", "Common IP Security Option", 0);
1430 1439 show_space();
1431 1440
1432 1441 /*
1433 1442 * Display CIPSO Header
1434 1443 */
1435 1444 (void) snprintf(get_line(0, 0), get_line_remain(),
1436 1445 "Type = CIPSO (%d), Length = %d", opt[0], opt[1]);
1437 1446 (void) memcpy(&doi, opt + 2, sizeof (doi));
1438 1447 (void) snprintf(get_line(0, 0), get_line_remain(),
1439 1448 "Domain of Interpretation = %u", (unsigned)ntohl(doi));
1440 1449
1441 1450 if (opt[1] == TSOL_CIPSO_MIN_LENGTH) { /* no tags */
1442 1451 show_space();
1443 1452 prot_prefix = prot_nest_prefix;
1444 1453 prot_nest_prefix = oldnest;
1445 1454 return;
1446 1455 }
1447 1456 optlen -= TSOL_CIPSO_MIN_LENGTH;
1448 1457 opt += TSOL_CIPSO_MIN_LENGTH;
1449 1458
1450 1459 /*
1451 1460 * Display Each Tag
1452 1461 */
1453 1462 tagnum = 1;
1454 1463 while (optlen >= TSOL_TT1_MIN_LENGTH) {
1455 1464 (void) snprintf(line, sizeof (line), "Tag# %d", tagnum);
1456 1465 show_header("CIPSO: ", line, 0);
1457 1466 /*
1458 1467 * We handle tag type 1 and 3 only. Note, tag type 3
1459 1468 * is MAXSIX defined.
1460 1469 */
1461 1470 switch (opt[0]) {
1462 1471 case 1:
1463 1472 taglen = interpret_cipso_tagtype1(opt);
1464 1473 break;
1465 1474 case 3:
1466 1475 taglen = interpret_cipso_tagtype3(opt);
1467 1476 break;
1468 1477 default:
1469 1478 (void) snprintf(get_line(0, 0), get_line_remain(),
1470 1479 "Unknown Tag Type %d", opt[0]);
1471 1480 show_space();
1472 1481 prot_prefix = prot_nest_prefix;
1473 1482 prot_nest_prefix = oldnest;
1474 1483 return;
1475 1484 }
1476 1485
1477 1486 /*
1478 1487 * Move to the next tag
1479 1488 */
1480 1489 if (taglen <= 0)
1481 1490 break;
1482 1491 optlen -= taglen;
1483 1492 opt += taglen;
1484 1493 tagnum++;
1485 1494 }
1486 1495 show_space();
1487 1496 prot_prefix = prot_nest_prefix;
1488 1497 prot_nest_prefix = oldnest;
1489 1498 }
↓ open down ↓ |
747 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX