17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*45916cd2Sjpk * Common Development and Distribution License (the "License"). 6*45916cd2Sjpk * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*45916cd2Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <string.h> 317c478bd9Sstevel@tonic-gate #include <fcntl.h> 327c478bd9Sstevel@tonic-gate #include <string.h> 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <sys/time.h> 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 377c478bd9Sstevel@tonic-gate #include <sys/socket.h> 387c478bd9Sstevel@tonic-gate #include <net/if.h> 397c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h> 407c478bd9Sstevel@tonic-gate #include <netinet/in.h> 417c478bd9Sstevel@tonic-gate #include <netinet/ip.h> 427c478bd9Sstevel@tonic-gate #include <netinet/ip6.h> 437c478bd9Sstevel@tonic-gate #include <netinet/ip_icmp.h> 447c478bd9Sstevel@tonic-gate #include <netinet/icmp6.h> 457c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h> 46*45916cd2Sjpk #include <inet/ip.h> 477c478bd9Sstevel@tonic-gate #include <inet/ip6.h> 487c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 497c478bd9Sstevel@tonic-gate #include <netdb.h> 50*45916cd2Sjpk #include <tsol/label.h> 51*45916cd2Sjpk #include <sys/tsol/tndb.h> 52*45916cd2Sjpk #include <sys/tsol/label_macro.h> 53*45916cd2Sjpk 547c478bd9Sstevel@tonic-gate #include "snoop.h" 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * IPv6 extension header masks. These are used by the print_ipv6_extensions() 597c478bd9Sstevel@tonic-gate * function to return information to the caller about which extension headers 607c478bd9Sstevel@tonic-gate * were processed. This can be useful if the caller wants to know if the 617c478bd9Sstevel@tonic-gate * packet is an IPv6 fragment, for example. 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate #define SNOOP_HOPOPTS 0x01U 647c478bd9Sstevel@tonic-gate #define SNOOP_ROUTING 0x02U 657c478bd9Sstevel@tonic-gate #define SNOOP_DSTOPTS 0x04U 667c478bd9Sstevel@tonic-gate #define SNOOP_FRAGMENT 0x08U 677c478bd9Sstevel@tonic-gate #define SNOOP_AH 0x10U 687c478bd9Sstevel@tonic-gate #define SNOOP_ESP 0x20U 697c478bd9Sstevel@tonic-gate #define SNOOP_IPV6 0x40U 707c478bd9Sstevel@tonic-gate 71*45916cd2Sjpk static void prt_routing_hdr(int, const struct ip6_rthdr *); 72*45916cd2Sjpk static void prt_fragment_hdr(int, const struct ip6_frag *); 73*45916cd2Sjpk static void prt_hbh_options(int, const struct ip6_hbh *); 74*45916cd2Sjpk static void prt_dest_options(int, const struct ip6_dest *); 75*45916cd2Sjpk static void print_route(const uchar_t *); 76*45916cd2Sjpk static void print_ipoptions(const uchar_t *, int); 77*45916cd2Sjpk static void print_ripso(const uchar_t *); 78*45916cd2Sjpk static void print_cipso(const uchar_t *); 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* Keep track of how many nested IP headers we have. */ 817c478bd9Sstevel@tonic-gate unsigned int encap_levels; 827c478bd9Sstevel@tonic-gate unsigned int total_encap_levels = 1; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate int 85*45916cd2Sjpk interpret_ip(int flags, const struct ip *ip, int fraglen) 867c478bd9Sstevel@tonic-gate { 87*45916cd2Sjpk uchar_t *data; 887c478bd9Sstevel@tonic-gate char buff[24]; 897c478bd9Sstevel@tonic-gate boolean_t isfrag = B_FALSE; 907c478bd9Sstevel@tonic-gate boolean_t morefrag; 917c478bd9Sstevel@tonic-gate uint16_t fragoffset; 927c478bd9Sstevel@tonic-gate int hdrlen; 937c478bd9Sstevel@tonic-gate uint16_t iplen, uitmp; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate if (ip->ip_v == IPV6_VERSION) { 967c478bd9Sstevel@tonic-gate iplen = interpret_ipv6(flags, (ip6_t *)ip, fraglen); 977c478bd9Sstevel@tonic-gate return (iplen); 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* XXX Should this count for mix-and-match v4/v6 encapsulations? */ 1017c478bd9Sstevel@tonic-gate if (encap_levels == 0) 1027c478bd9Sstevel@tonic-gate total_encap_levels = 0; 1037c478bd9Sstevel@tonic-gate encap_levels++; 1047c478bd9Sstevel@tonic-gate total_encap_levels++; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate hdrlen = ip->ip_hl * 4; 107*45916cd2Sjpk data = ((uchar_t *)ip) + hdrlen; 1087c478bd9Sstevel@tonic-gate iplen = ntohs(ip->ip_len) - hdrlen; 1097c478bd9Sstevel@tonic-gate fraglen -= hdrlen; 1107c478bd9Sstevel@tonic-gate if (fraglen > iplen) 1117c478bd9Sstevel@tonic-gate fraglen = iplen; 1127c478bd9Sstevel@tonic-gate if (fraglen < 0) { 1137c478bd9Sstevel@tonic-gate (void) snprintf(get_sum_line(), MAXLINE, 1147c478bd9Sstevel@tonic-gate "IP truncated: header missing %d bytes", -fraglen); 1157c478bd9Sstevel@tonic-gate encap_levels--; 1167c478bd9Sstevel@tonic-gate return (fraglen + iplen); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * We flag this as a fragment if the more fragments bit is set, or 1207c478bd9Sstevel@tonic-gate * if the fragment offset is non-zero. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate morefrag = (ntohs(ip->ip_off) & IP_MF) == 0 ? B_FALSE : B_TRUE; 1237c478bd9Sstevel@tonic-gate fragoffset = (ntohs(ip->ip_off) & 0x1FFF) * 8; 1247c478bd9Sstevel@tonic-gate if (morefrag || fragoffset != 0) 1257c478bd9Sstevel@tonic-gate isfrag = B_TRUE; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate if (encap_levels == 1) { 1287c478bd9Sstevel@tonic-gate src_name = addrtoname(AF_INET, &ip->ip_src); 1297c478bd9Sstevel@tonic-gate dst_name = addrtoname(AF_INET, &ip->ip_dst); 1307c478bd9Sstevel@tonic-gate } /* Else we already have the src_name and dst_name we want! */ 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 1337c478bd9Sstevel@tonic-gate if (isfrag) { 1347c478bd9Sstevel@tonic-gate (void) snprintf(get_sum_line(), MAXLINE, 1357c478bd9Sstevel@tonic-gate "%s IP fragment ID=%d Offset=%-4d MF=%d TOS=0x%x " 1367c478bd9Sstevel@tonic-gate "TTL=%d", 1377c478bd9Sstevel@tonic-gate getproto(ip->ip_p), 1387c478bd9Sstevel@tonic-gate ntohs(ip->ip_id), 1397c478bd9Sstevel@tonic-gate fragoffset, 1407c478bd9Sstevel@tonic-gate morefrag, 1417c478bd9Sstevel@tonic-gate ip->ip_tos, 1427c478bd9Sstevel@tonic-gate ip->ip_ttl); 1437c478bd9Sstevel@tonic-gate } else { 1447c478bd9Sstevel@tonic-gate (void) strlcpy(buff, inet_ntoa(ip->ip_dst), 1457c478bd9Sstevel@tonic-gate sizeof (buff)); 1467c478bd9Sstevel@tonic-gate uitmp = ntohs(ip->ip_len); 1477c478bd9Sstevel@tonic-gate (void) snprintf(get_sum_line(), MAXLINE, 1487c478bd9Sstevel@tonic-gate "IP D=%s S=%s LEN=%u%s, ID=%d, TOS=0x%x, TTL=%d", 1497c478bd9Sstevel@tonic-gate buff, 1507c478bd9Sstevel@tonic-gate inet_ntoa(ip->ip_src), 1517c478bd9Sstevel@tonic-gate uitmp, 1527c478bd9Sstevel@tonic-gate iplen > fraglen ? "?" : "", 1537c478bd9Sstevel@tonic-gate ntohs(ip->ip_id), 1547c478bd9Sstevel@tonic-gate ip->ip_tos, 1557c478bd9Sstevel@tonic-gate ip->ip_ttl); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate if (flags & F_DTAIL) { 1607c478bd9Sstevel@tonic-gate show_header("IP: ", "IP Header", iplen); 1617c478bd9Sstevel@tonic-gate show_space(); 162*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 163*45916cd2Sjpk "Version = %d", ip->ip_v); 164*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 165*45916cd2Sjpk "Header length = %d bytes", hdrlen); 166*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 167*45916cd2Sjpk "Type of service = 0x%02x", ip->ip_tos); 168*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 169*45916cd2Sjpk " xxx. .... = %d (precedence)", 1707c478bd9Sstevel@tonic-gate ip->ip_tos >> 5); 171*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 172*45916cd2Sjpk " %s", getflag(ip->ip_tos, IPTOS_LOWDELAY, 1737c478bd9Sstevel@tonic-gate "low delay", "normal delay")); 174*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), " %s", 1757c478bd9Sstevel@tonic-gate getflag(ip->ip_tos, IPTOS_THROUGHPUT, 1767c478bd9Sstevel@tonic-gate "high throughput", "normal throughput")); 177*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), " %s", 1787c478bd9Sstevel@tonic-gate getflag(ip->ip_tos, IPTOS_RELIABILITY, 1797c478bd9Sstevel@tonic-gate "high reliability", "normal reliability")); 180*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), " %s", 1817c478bd9Sstevel@tonic-gate getflag(ip->ip_tos, IPTOS_ECT, 1827c478bd9Sstevel@tonic-gate "ECN capable transport", "not ECN capable transport")); 183*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), " %s", 1847c478bd9Sstevel@tonic-gate getflag(ip->ip_tos, IPTOS_CE, 1857c478bd9Sstevel@tonic-gate "ECN congestion experienced", 1867c478bd9Sstevel@tonic-gate "no ECN congestion experienced")); 1877c478bd9Sstevel@tonic-gate /* warning: ip_len is signed in netinet/ip.h */ 1887c478bd9Sstevel@tonic-gate uitmp = ntohs(ip->ip_len); 189*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 190*45916cd2Sjpk "Total length = %u bytes%s", uitmp, 1917c478bd9Sstevel@tonic-gate iplen > fraglen ? " -- truncated" : ""); 192*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 193*45916cd2Sjpk "Identification = %d", ntohs(ip->ip_id)); 1947c478bd9Sstevel@tonic-gate /* warning: ip_off is signed in netinet/ip.h */ 1957c478bd9Sstevel@tonic-gate uitmp = ntohs(ip->ip_off); 196*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 197*45916cd2Sjpk "Flags = 0x%x", uitmp >> 12); 198*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), " %s", 1997c478bd9Sstevel@tonic-gate getflag(uitmp >> 8, IP_DF >> 8, 2007c478bd9Sstevel@tonic-gate "do not fragment", "may fragment")); 201*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), " %s", 2027c478bd9Sstevel@tonic-gate getflag(uitmp >> 8, IP_MF >> 8, 2037c478bd9Sstevel@tonic-gate "more fragments", "last fragment")); 204*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 205*45916cd2Sjpk "Fragment offset = %u bytes", 2067c478bd9Sstevel@tonic-gate fragoffset); 207*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 208*45916cd2Sjpk "Time to live = %d seconds/hops", 2097c478bd9Sstevel@tonic-gate ip->ip_ttl); 210*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 211*45916cd2Sjpk "Protocol = %d (%s)", ip->ip_p, 2127c478bd9Sstevel@tonic-gate getproto(ip->ip_p)); 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * XXX need to compute checksum and print whether it's correct 2157c478bd9Sstevel@tonic-gate */ 216*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 217*45916cd2Sjpk "Header checksum = %04x", 2187c478bd9Sstevel@tonic-gate ntohs(ip->ip_sum)); 219*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 220*45916cd2Sjpk "Source address = %s, %s", 2217c478bd9Sstevel@tonic-gate inet_ntoa(ip->ip_src), addrtoname(AF_INET, &ip->ip_src)); 222*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 223*45916cd2Sjpk "Destination address = %s, %s", 2247c478bd9Sstevel@tonic-gate inet_ntoa(ip->ip_dst), addrtoname(AF_INET, &ip->ip_dst)); 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* Print IP options - if any */ 2277c478bd9Sstevel@tonic-gate 228*45916cd2Sjpk print_ipoptions((const uchar_t *)(ip + 1), 229*45916cd2Sjpk hdrlen - sizeof (struct ip)); 2307c478bd9Sstevel@tonic-gate show_space(); 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate /* 2347c478bd9Sstevel@tonic-gate * If we are in detail mode, and this is not the first fragment of 2357c478bd9Sstevel@tonic-gate * a fragmented packet, print out a little line stating this. 2367c478bd9Sstevel@tonic-gate * Otherwise, go to the next protocol layer only if this is not a 2377c478bd9Sstevel@tonic-gate * fragment, or we are in detail mode and this is the first fragment 2387c478bd9Sstevel@tonic-gate * of a fragmented packet. 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate if (flags & F_DTAIL && fragoffset != 0) { 241*45916cd2Sjpk (void) snprintf(get_detail_line(0, 0), MAXLINE, 2427c478bd9Sstevel@tonic-gate "%s: [%d byte(s) of data, continuation of IP ident=%d]", 2437c478bd9Sstevel@tonic-gate getproto(ip->ip_p), 2447c478bd9Sstevel@tonic-gate iplen, 2457c478bd9Sstevel@tonic-gate ntohs(ip->ip_id)); 2467c478bd9Sstevel@tonic-gate } else if (!isfrag || (flags & F_DTAIL) && isfrag && fragoffset == 0) { 2477c478bd9Sstevel@tonic-gate /* go to the next protocol layer */ 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if (fraglen > 0) { 2507c478bd9Sstevel@tonic-gate switch (ip->ip_p) { 2517c478bd9Sstevel@tonic-gate case IPPROTO_IP: 2527c478bd9Sstevel@tonic-gate break; 2537c478bd9Sstevel@tonic-gate case IPPROTO_ENCAP: 254*45916cd2Sjpk (void) interpret_ip(flags, 255*45916cd2Sjpk /* LINTED: alignment */ 256*45916cd2Sjpk (const struct ip *)data, fraglen); 2577c478bd9Sstevel@tonic-gate break; 2587c478bd9Sstevel@tonic-gate case IPPROTO_ICMP: 259*45916cd2Sjpk (void) interpret_icmp(flags, 260*45916cd2Sjpk /* LINTED: alignment */ 261*45916cd2Sjpk (struct icmp *)data, iplen, fraglen); 2627c478bd9Sstevel@tonic-gate break; 2637c478bd9Sstevel@tonic-gate case IPPROTO_IGMP: 2647c478bd9Sstevel@tonic-gate interpret_igmp(flags, data, iplen, fraglen); 2657c478bd9Sstevel@tonic-gate break; 2667c478bd9Sstevel@tonic-gate case IPPROTO_GGP: 2677c478bd9Sstevel@tonic-gate break; 2687c478bd9Sstevel@tonic-gate case IPPROTO_TCP: 269*45916cd2Sjpk (void) interpret_tcp(flags, 270*45916cd2Sjpk (struct tcphdr *)data, iplen, fraglen); 2717c478bd9Sstevel@tonic-gate break; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate case IPPROTO_ESP: 274*45916cd2Sjpk (void) interpret_esp(flags, data, iplen, 275*45916cd2Sjpk fraglen); 2767c478bd9Sstevel@tonic-gate break; 2777c478bd9Sstevel@tonic-gate case IPPROTO_AH: 278*45916cd2Sjpk (void) interpret_ah(flags, data, iplen, 279*45916cd2Sjpk fraglen); 2807c478bd9Sstevel@tonic-gate break; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate case IPPROTO_OSPF: 2837c478bd9Sstevel@tonic-gate interpret_ospf(flags, data, iplen, fraglen); 2847c478bd9Sstevel@tonic-gate break; 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate case IPPROTO_EGP: 2877c478bd9Sstevel@tonic-gate case IPPROTO_PUP: 2887c478bd9Sstevel@tonic-gate break; 2897c478bd9Sstevel@tonic-gate case IPPROTO_UDP: 290*45916cd2Sjpk (void) interpret_udp(flags, 291*45916cd2Sjpk (struct udphdr *)data, iplen, fraglen); 2927c478bd9Sstevel@tonic-gate break; 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate case IPPROTO_IDP: 2957c478bd9Sstevel@tonic-gate case IPPROTO_HELLO: 2967c478bd9Sstevel@tonic-gate case IPPROTO_ND: 2977c478bd9Sstevel@tonic-gate case IPPROTO_RAW: 2987c478bd9Sstevel@tonic-gate break; 2997c478bd9Sstevel@tonic-gate case IPPROTO_IPV6: /* IPV6 encap */ 300*45916cd2Sjpk /* LINTED: alignment */ 3017c478bd9Sstevel@tonic-gate (void) interpret_ipv6(flags, (ip6_t *)data, 3027c478bd9Sstevel@tonic-gate iplen); 3037c478bd9Sstevel@tonic-gate break; 3047c478bd9Sstevel@tonic-gate case IPPROTO_SCTP: 305*45916cd2Sjpk (void) interpret_sctp(flags, 306*45916cd2Sjpk (struct sctp_hdr *)data, iplen, fraglen); 3077c478bd9Sstevel@tonic-gate break; 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate encap_levels--; 3137c478bd9Sstevel@tonic-gate return (iplen); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate int 317*45916cd2Sjpk interpret_ipv6(int flags, const ip6_t *ip6h, int fraglen) 3187c478bd9Sstevel@tonic-gate { 3197c478bd9Sstevel@tonic-gate uint8_t *data; 3207c478bd9Sstevel@tonic-gate int hdrlen, iplen; 3217c478bd9Sstevel@tonic-gate int version, flow, class; 3227c478bd9Sstevel@tonic-gate uchar_t proto; 3237c478bd9Sstevel@tonic-gate boolean_t isfrag = B_FALSE; 3247c478bd9Sstevel@tonic-gate uint8_t extmask; 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * The print_srcname and print_dstname strings are the hostname 3277c478bd9Sstevel@tonic-gate * parts of the verbose IPv6 header output, including the comma 3287c478bd9Sstevel@tonic-gate * and the space after the litteral address strings. 3297c478bd9Sstevel@tonic-gate */ 3307c478bd9Sstevel@tonic-gate char print_srcname[MAXHOSTNAMELEN + 2]; 3317c478bd9Sstevel@tonic-gate char print_dstname[MAXHOSTNAMELEN + 2]; 3327c478bd9Sstevel@tonic-gate char src_addrstr[INET6_ADDRSTRLEN]; 3337c478bd9Sstevel@tonic-gate char dst_addrstr[INET6_ADDRSTRLEN]; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate iplen = ntohs(ip6h->ip6_plen); 3367c478bd9Sstevel@tonic-gate hdrlen = IPV6_HDR_LEN; 3377c478bd9Sstevel@tonic-gate fraglen -= hdrlen; 3387c478bd9Sstevel@tonic-gate if (fraglen < 0) 3397c478bd9Sstevel@tonic-gate return (fraglen + hdrlen); 3407c478bd9Sstevel@tonic-gate data = ((uint8_t *)ip6h) + hdrlen; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate proto = ip6h->ip6_nxt; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate src_name = addrtoname(AF_INET6, &ip6h->ip6_src); 3457c478bd9Sstevel@tonic-gate dst_name = addrtoname(AF_INET6, &ip6h->ip6_dst); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * Use endian-aware masks to extract traffic class and 3497c478bd9Sstevel@tonic-gate * flowinfo. Also, flowinfo is now 20 bits and class 8 3507c478bd9Sstevel@tonic-gate * rather than 24 and 4. 3517c478bd9Sstevel@tonic-gate */ 3527c478bd9Sstevel@tonic-gate class = ntohl((ip6h->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20); 3537c478bd9Sstevel@tonic-gate flow = ntohl(ip6h->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate /* 3567c478bd9Sstevel@tonic-gate * NOTE: the F_SUM and F_DTAIL flags are mutually exclusive, 3577c478bd9Sstevel@tonic-gate * so the code within the first part of the following if statement 3587c478bd9Sstevel@tonic-gate * will not affect the detailed printing of the packet. 3597c478bd9Sstevel@tonic-gate */ 3607c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 361*45916cd2Sjpk (void) snprintf(get_sum_line(), MAXLINE, 362*45916cd2Sjpk "IPv6 S=%s D=%s LEN=%d HOPS=%d CLASS=0x%x FLOW=0x%x", 3637c478bd9Sstevel@tonic-gate src_name, dst_name, iplen, ip6h->ip6_hops, class, flow); 3647c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET6, &ip6h->ip6_src, src_addrstr, 3677c478bd9Sstevel@tonic-gate INET6_ADDRSTRLEN); 3687c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET6, &ip6h->ip6_dst, dst_addrstr, 3697c478bd9Sstevel@tonic-gate INET6_ADDRSTRLEN); 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate version = ntohl(ip6h->ip6_vcf) >> 28; 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate if (strcmp(src_name, src_addrstr) == 0) 3747c478bd9Sstevel@tonic-gate print_srcname[0] = '\0'; 3757c478bd9Sstevel@tonic-gate else 3767c478bd9Sstevel@tonic-gate snprintf(print_srcname, sizeof (print_srcname), 3777c478bd9Sstevel@tonic-gate ", %s", src_name); 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate if (strcmp(dst_name, dst_addrstr) == 0) 3807c478bd9Sstevel@tonic-gate print_dstname[0] = '\0'; 3817c478bd9Sstevel@tonic-gate else 3827c478bd9Sstevel@tonic-gate snprintf(print_dstname, sizeof (print_dstname), 3837c478bd9Sstevel@tonic-gate ", %s", dst_name); 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate show_header("IPv6: ", "IPv6 Header", iplen); 3867c478bd9Sstevel@tonic-gate show_space(); 3877c478bd9Sstevel@tonic-gate 388*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 3897c478bd9Sstevel@tonic-gate "Version = %d", version); 390*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 3917c478bd9Sstevel@tonic-gate "Traffic Class = %d", class); 392*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 3937c478bd9Sstevel@tonic-gate "Flow label = 0x%x", flow); 394*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 395*45916cd2Sjpk "Payload length = %d", iplen); 396*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 397*45916cd2Sjpk "Next Header = %d (%s)", proto, 3987c478bd9Sstevel@tonic-gate getproto(proto)); 399*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 400*45916cd2Sjpk "Hop Limit = %d", ip6h->ip6_hops); 401*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 4027c478bd9Sstevel@tonic-gate "Source address = %s%s", src_addrstr, print_srcname); 403*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 4047c478bd9Sstevel@tonic-gate "Destination address = %s%s", dst_addrstr, print_dstname); 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate show_space(); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate /* 4107c478bd9Sstevel@tonic-gate * Print IPv6 Extension Headers, or skip them in the summary case. 4117c478bd9Sstevel@tonic-gate * Set isfrag to true if one of the extension headers encounterred 4127c478bd9Sstevel@tonic-gate * was a fragment header. 4137c478bd9Sstevel@tonic-gate */ 4147c478bd9Sstevel@tonic-gate if (proto == IPPROTO_HOPOPTS || proto == IPPROTO_DSTOPTS || 4157c478bd9Sstevel@tonic-gate proto == IPPROTO_ROUTING || proto == IPPROTO_FRAGMENT) { 4167c478bd9Sstevel@tonic-gate extmask = print_ipv6_extensions(flags, &data, &proto, &iplen, 4177c478bd9Sstevel@tonic-gate &fraglen); 4187c478bd9Sstevel@tonic-gate if ((extmask & SNOOP_FRAGMENT) != 0) { 4197c478bd9Sstevel@tonic-gate isfrag = B_TRUE; 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* 4247c478bd9Sstevel@tonic-gate * We only want to print upper layer information if this is not 4257c478bd9Sstevel@tonic-gate * a fragment, or if we're printing in detail. Note that the 4267c478bd9Sstevel@tonic-gate * proto variable will be set to IPPROTO_NONE if this is a fragment 4277c478bd9Sstevel@tonic-gate * with a non-zero fragment offset. 4287c478bd9Sstevel@tonic-gate */ 4297c478bd9Sstevel@tonic-gate if (!isfrag || flags & F_DTAIL) { 4307c478bd9Sstevel@tonic-gate /* go to the next protocol layer */ 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate switch (proto) { 4337c478bd9Sstevel@tonic-gate case IPPROTO_IP: 4347c478bd9Sstevel@tonic-gate break; 4357c478bd9Sstevel@tonic-gate case IPPROTO_ENCAP: 436*45916cd2Sjpk /* LINTED: alignment */ 437*45916cd2Sjpk (void) interpret_ip(flags, (const struct ip *)data, 438*45916cd2Sjpk fraglen); 4397c478bd9Sstevel@tonic-gate break; 4407c478bd9Sstevel@tonic-gate case IPPROTO_ICMPV6: 441*45916cd2Sjpk /* LINTED: alignment */ 442*45916cd2Sjpk (void) interpret_icmpv6(flags, (icmp6_t *)data, iplen, 4437c478bd9Sstevel@tonic-gate fraglen); 4447c478bd9Sstevel@tonic-gate break; 4457c478bd9Sstevel@tonic-gate case IPPROTO_IGMP: 4467c478bd9Sstevel@tonic-gate interpret_igmp(flags, data, iplen, fraglen); 4477c478bd9Sstevel@tonic-gate break; 4487c478bd9Sstevel@tonic-gate case IPPROTO_GGP: 4497c478bd9Sstevel@tonic-gate break; 4507c478bd9Sstevel@tonic-gate case IPPROTO_TCP: 451*45916cd2Sjpk (void) interpret_tcp(flags, (struct tcphdr *)data, 452*45916cd2Sjpk iplen, fraglen); 4537c478bd9Sstevel@tonic-gate break; 4547c478bd9Sstevel@tonic-gate case IPPROTO_ESP: 455*45916cd2Sjpk (void) interpret_esp(flags, data, iplen, fraglen); 4567c478bd9Sstevel@tonic-gate break; 4577c478bd9Sstevel@tonic-gate case IPPROTO_AH: 458*45916cd2Sjpk (void) interpret_ah(flags, data, iplen, fraglen); 4597c478bd9Sstevel@tonic-gate break; 4607c478bd9Sstevel@tonic-gate case IPPROTO_EGP: 4617c478bd9Sstevel@tonic-gate case IPPROTO_PUP: 4627c478bd9Sstevel@tonic-gate break; 4637c478bd9Sstevel@tonic-gate case IPPROTO_UDP: 464*45916cd2Sjpk (void) interpret_udp(flags, (struct udphdr *)data, 465*45916cd2Sjpk iplen, fraglen); 4667c478bd9Sstevel@tonic-gate break; 4677c478bd9Sstevel@tonic-gate case IPPROTO_IDP: 4687c478bd9Sstevel@tonic-gate case IPPROTO_HELLO: 4697c478bd9Sstevel@tonic-gate case IPPROTO_ND: 4707c478bd9Sstevel@tonic-gate case IPPROTO_RAW: 4717c478bd9Sstevel@tonic-gate break; 4727c478bd9Sstevel@tonic-gate case IPPROTO_IPV6: 473*45916cd2Sjpk /* LINTED: alignment */ 474*45916cd2Sjpk (void) interpret_ipv6(flags, (const ip6_t *)data, 475*45916cd2Sjpk iplen); 4767c478bd9Sstevel@tonic-gate break; 4777c478bd9Sstevel@tonic-gate case IPPROTO_SCTP: 478*45916cd2Sjpk (void) interpret_sctp(flags, (struct sctp_hdr *)data, 479*45916cd2Sjpk iplen, fraglen); 4807c478bd9Sstevel@tonic-gate break; 4817c478bd9Sstevel@tonic-gate case IPPROTO_OSPF: 4827c478bd9Sstevel@tonic-gate interpret_ospf6(flags, data, iplen, fraglen); 4837c478bd9Sstevel@tonic-gate break; 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate return (iplen); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate /* 4917c478bd9Sstevel@tonic-gate * ip_ext: data including the extension header. 4927c478bd9Sstevel@tonic-gate * iplen: length of the data remaining in the packet. 4937c478bd9Sstevel@tonic-gate * Returns a mask of IPv6 extension headers it processed. 4947c478bd9Sstevel@tonic-gate */ 4957c478bd9Sstevel@tonic-gate uint8_t 4967c478bd9Sstevel@tonic-gate print_ipv6_extensions(int flags, uint8_t **hdr, uint8_t *next, int *iplen, 4977c478bd9Sstevel@tonic-gate int *fraglen) 4987c478bd9Sstevel@tonic-gate { 4997c478bd9Sstevel@tonic-gate uint8_t *data_ptr; 5007c478bd9Sstevel@tonic-gate uchar_t proto = *next; 5017c478bd9Sstevel@tonic-gate boolean_t is_extension_header; 5027c478bd9Sstevel@tonic-gate struct ip6_hbh *ipv6ext_hbh; 5037c478bd9Sstevel@tonic-gate struct ip6_dest *ipv6ext_dest; 5047c478bd9Sstevel@tonic-gate struct ip6_rthdr *ipv6ext_rthdr; 5057c478bd9Sstevel@tonic-gate struct ip6_frag *ipv6ext_frag; 5067c478bd9Sstevel@tonic-gate uint32_t exthdrlen; 5077c478bd9Sstevel@tonic-gate uint8_t extmask = 0; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate if ((hdr == NULL) || (*hdr == NULL) || (next == NULL) || (iplen == 0)) 5107c478bd9Sstevel@tonic-gate return (0); 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate data_ptr = *hdr; 5137c478bd9Sstevel@tonic-gate is_extension_header = B_TRUE; 5147c478bd9Sstevel@tonic-gate while (is_extension_header) { 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* 5177c478bd9Sstevel@tonic-gate * There must be at least enough data left to read the 5187c478bd9Sstevel@tonic-gate * next header and header length fields from the next 5197c478bd9Sstevel@tonic-gate * header. 5207c478bd9Sstevel@tonic-gate */ 5217c478bd9Sstevel@tonic-gate if (*fraglen < 2) { 5227c478bd9Sstevel@tonic-gate return (extmask); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate switch (proto) { 5267c478bd9Sstevel@tonic-gate case IPPROTO_HOPOPTS: 5277c478bd9Sstevel@tonic-gate ipv6ext_hbh = (struct ip6_hbh *)data_ptr; 5287c478bd9Sstevel@tonic-gate exthdrlen = 8 + ipv6ext_hbh->ip6h_len * 8; 5297c478bd9Sstevel@tonic-gate if (*fraglen <= exthdrlen) { 5307c478bd9Sstevel@tonic-gate return (extmask); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate prt_hbh_options(flags, ipv6ext_hbh); 5337c478bd9Sstevel@tonic-gate extmask |= SNOOP_HOPOPTS; 5347c478bd9Sstevel@tonic-gate proto = ipv6ext_hbh->ip6h_nxt; 5357c478bd9Sstevel@tonic-gate break; 5367c478bd9Sstevel@tonic-gate case IPPROTO_DSTOPTS: 5377c478bd9Sstevel@tonic-gate ipv6ext_dest = (struct ip6_dest *)data_ptr; 5387c478bd9Sstevel@tonic-gate exthdrlen = 8 + ipv6ext_dest->ip6d_len * 8; 5397c478bd9Sstevel@tonic-gate if (*fraglen <= exthdrlen) { 5407c478bd9Sstevel@tonic-gate return (extmask); 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate prt_dest_options(flags, ipv6ext_dest); 5437c478bd9Sstevel@tonic-gate extmask |= SNOOP_DSTOPTS; 5447c478bd9Sstevel@tonic-gate proto = ipv6ext_dest->ip6d_nxt; 5457c478bd9Sstevel@tonic-gate break; 5467c478bd9Sstevel@tonic-gate case IPPROTO_ROUTING: 5477c478bd9Sstevel@tonic-gate ipv6ext_rthdr = (struct ip6_rthdr *)data_ptr; 5487c478bd9Sstevel@tonic-gate exthdrlen = 8 + ipv6ext_rthdr->ip6r_len * 8; 5497c478bd9Sstevel@tonic-gate if (*fraglen <= exthdrlen) { 5507c478bd9Sstevel@tonic-gate return (extmask); 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate prt_routing_hdr(flags, ipv6ext_rthdr); 5537c478bd9Sstevel@tonic-gate extmask |= SNOOP_ROUTING; 5547c478bd9Sstevel@tonic-gate proto = ipv6ext_rthdr->ip6r_nxt; 5557c478bd9Sstevel@tonic-gate break; 5567c478bd9Sstevel@tonic-gate case IPPROTO_FRAGMENT: 557*45916cd2Sjpk /* LINTED: alignment */ 5587c478bd9Sstevel@tonic-gate ipv6ext_frag = (struct ip6_frag *)data_ptr; 5597c478bd9Sstevel@tonic-gate exthdrlen = sizeof (struct ip6_frag); 5607c478bd9Sstevel@tonic-gate if (*fraglen <= exthdrlen) { 5617c478bd9Sstevel@tonic-gate return (extmask); 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate prt_fragment_hdr(flags, ipv6ext_frag); 5647c478bd9Sstevel@tonic-gate extmask |= SNOOP_FRAGMENT; 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * If this is not the first fragment, forget about 5677c478bd9Sstevel@tonic-gate * the rest of the packet, snoop decoding is 5687c478bd9Sstevel@tonic-gate * stateless. 5697c478bd9Sstevel@tonic-gate */ 5707c478bd9Sstevel@tonic-gate if ((ipv6ext_frag->ip6f_offlg & IP6F_OFF_MASK) != 0) 5717c478bd9Sstevel@tonic-gate proto = IPPROTO_NONE; 5727c478bd9Sstevel@tonic-gate else 5737c478bd9Sstevel@tonic-gate proto = ipv6ext_frag->ip6f_nxt; 5747c478bd9Sstevel@tonic-gate break; 5757c478bd9Sstevel@tonic-gate default: 5767c478bd9Sstevel@tonic-gate is_extension_header = B_FALSE; 5777c478bd9Sstevel@tonic-gate break; 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate if (is_extension_header) { 5817c478bd9Sstevel@tonic-gate *iplen -= exthdrlen; 5827c478bd9Sstevel@tonic-gate *fraglen -= exthdrlen; 5837c478bd9Sstevel@tonic-gate data_ptr += exthdrlen; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate *next = proto; 5887c478bd9Sstevel@tonic-gate *hdr = data_ptr; 5897c478bd9Sstevel@tonic-gate return (extmask); 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate static void 593*45916cd2Sjpk print_ipoptions(const uchar_t *opt, int optlen) 5947c478bd9Sstevel@tonic-gate { 5957c478bd9Sstevel@tonic-gate int len; 596*45916cd2Sjpk int remain; 5977c478bd9Sstevel@tonic-gate char *line; 598*45916cd2Sjpk const char *truncstr; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate if (optlen <= 0) { 601*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 6027c478bd9Sstevel@tonic-gate "No options"); 6037c478bd9Sstevel@tonic-gate return; 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 606*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 6077c478bd9Sstevel@tonic-gate "Options: (%d bytes)", optlen); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate while (optlen > 0) { 610*45916cd2Sjpk line = get_line(0, 0); 611*45916cd2Sjpk remain = get_line_remain(); 6127c478bd9Sstevel@tonic-gate len = opt[1]; 613*45916cd2Sjpk truncstr = len > optlen ? "?" : ""; 6147c478bd9Sstevel@tonic-gate switch (opt[0]) { 6157c478bd9Sstevel@tonic-gate case IPOPT_EOL: 616*45916cd2Sjpk (void) strlcpy(line, " - End of option list", remain); 6177c478bd9Sstevel@tonic-gate return; 6187c478bd9Sstevel@tonic-gate case IPOPT_NOP: 619*45916cd2Sjpk (void) strlcpy(line, " - No op", remain); 6207c478bd9Sstevel@tonic-gate len = 1; 6217c478bd9Sstevel@tonic-gate break; 6227c478bd9Sstevel@tonic-gate case IPOPT_RR: 623*45916cd2Sjpk (void) snprintf(line, remain, 624*45916cd2Sjpk " - Record route (%d bytes%s)", len, truncstr); 6257c478bd9Sstevel@tonic-gate print_route(opt); 6267c478bd9Sstevel@tonic-gate break; 6277c478bd9Sstevel@tonic-gate case IPOPT_TS: 628*45916cd2Sjpk (void) snprintf(line, remain, 629*45916cd2Sjpk " - Time stamp (%d bytes%s)", len, truncstr); 6307c478bd9Sstevel@tonic-gate break; 6317c478bd9Sstevel@tonic-gate case IPOPT_SECURITY: 632*45916cd2Sjpk (void) snprintf(line, remain, " - RIPSO (%d bytes%s)", 633*45916cd2Sjpk len, truncstr); 634*45916cd2Sjpk print_ripso(opt); 635*45916cd2Sjpk break; 636*45916cd2Sjpk case IPOPT_COMSEC: 637*45916cd2Sjpk (void) snprintf(line, remain, " - CIPSO (%d bytes%s)", 638*45916cd2Sjpk len, truncstr); 639*45916cd2Sjpk print_cipso(opt); 6407c478bd9Sstevel@tonic-gate break; 6417c478bd9Sstevel@tonic-gate case IPOPT_LSRR: 642*45916cd2Sjpk (void) snprintf(line, remain, 643*45916cd2Sjpk " - Loose source route (%d bytes%s)", len, 644*45916cd2Sjpk truncstr); 6457c478bd9Sstevel@tonic-gate print_route(opt); 6467c478bd9Sstevel@tonic-gate break; 6477c478bd9Sstevel@tonic-gate case IPOPT_SATID: 648*45916cd2Sjpk (void) snprintf(line, remain, 649*45916cd2Sjpk " - SATNET Stream id (%d bytes%s)", 650*45916cd2Sjpk len, truncstr); 6517c478bd9Sstevel@tonic-gate break; 6527c478bd9Sstevel@tonic-gate case IPOPT_SSRR: 653*45916cd2Sjpk (void) snprintf(line, remain, 654*45916cd2Sjpk " - Strict source route, (%d bytes%s)", len, 655*45916cd2Sjpk truncstr); 6567c478bd9Sstevel@tonic-gate print_route(opt); 6577c478bd9Sstevel@tonic-gate break; 6587c478bd9Sstevel@tonic-gate default: 659*45916cd2Sjpk (void) snprintf(line, remain, 660*45916cd2Sjpk " - Option %d (unknown - %d bytes%s) %s", 661*45916cd2Sjpk opt[0], len, truncstr, 662*45916cd2Sjpk tohex((char *)&opt[2], len - 2)); 6637c478bd9Sstevel@tonic-gate break; 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate if (len <= 0) { 666*45916cd2Sjpk (void) snprintf(line, remain, 667*45916cd2Sjpk " - Incomplete option len %d", len); 6687c478bd9Sstevel@tonic-gate break; 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate opt += len; 6717c478bd9Sstevel@tonic-gate optlen -= len; 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate static void 676*45916cd2Sjpk print_route(const uchar_t *opt) 6777c478bd9Sstevel@tonic-gate { 678*45916cd2Sjpk int len, pointer, remain; 6797c478bd9Sstevel@tonic-gate struct in_addr addr; 6807c478bd9Sstevel@tonic-gate char *line; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate len = opt[1]; 6837c478bd9Sstevel@tonic-gate pointer = opt[2]; 6847c478bd9Sstevel@tonic-gate 685*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 6867c478bd9Sstevel@tonic-gate " Pointer = %d", pointer); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate pointer -= IPOPT_MINOFF; 6897c478bd9Sstevel@tonic-gate opt += (IPOPT_OFFSET + 1); 6907c478bd9Sstevel@tonic-gate len -= (IPOPT_OFFSET + 1); 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate while (len > 0) { 693*45916cd2Sjpk line = get_line(0, 0); 694*45916cd2Sjpk remain = get_line_remain(); 6957c478bd9Sstevel@tonic-gate memcpy((char *)&addr, opt, sizeof (addr)); 6967c478bd9Sstevel@tonic-gate if (addr.s_addr == INADDR_ANY) 697*45916cd2Sjpk (void) strlcpy(line, " -", remain); 6987c478bd9Sstevel@tonic-gate else 699*45916cd2Sjpk (void) snprintf(line, remain, " %s", 7007c478bd9Sstevel@tonic-gate addrtoname(AF_INET, &addr)); 7017c478bd9Sstevel@tonic-gate if (pointer == 0) 702*45916cd2Sjpk (void) strlcat(line, " <-- (current)", remain); 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate opt += sizeof (addr); 7057c478bd9Sstevel@tonic-gate len -= sizeof (addr); 7067c478bd9Sstevel@tonic-gate pointer -= sizeof (addr); 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate char * 711*45916cd2Sjpk getproto(int p) 7127c478bd9Sstevel@tonic-gate { 7137c478bd9Sstevel@tonic-gate switch (p) { 7147c478bd9Sstevel@tonic-gate case IPPROTO_HOPOPTS: return ("IPv6-HopOpts"); 7157c478bd9Sstevel@tonic-gate case IPPROTO_IPV6: return ("IPv6"); 7167c478bd9Sstevel@tonic-gate case IPPROTO_ROUTING: return ("IPv6-Route"); 7177c478bd9Sstevel@tonic-gate case IPPROTO_FRAGMENT: return ("IPv6-Frag"); 7187c478bd9Sstevel@tonic-gate case IPPROTO_RSVP: return ("RSVP"); 7197c478bd9Sstevel@tonic-gate case IPPROTO_ENCAP: return ("IP-in-IP"); 7207c478bd9Sstevel@tonic-gate case IPPROTO_AH: return ("AH"); 7217c478bd9Sstevel@tonic-gate case IPPROTO_ESP: return ("ESP"); 7227c478bd9Sstevel@tonic-gate case IPPROTO_ICMP: return ("ICMP"); 7237c478bd9Sstevel@tonic-gate case IPPROTO_ICMPV6: return ("ICMPv6"); 7247c478bd9Sstevel@tonic-gate case IPPROTO_DSTOPTS: return ("IPv6-DstOpts"); 7257c478bd9Sstevel@tonic-gate case IPPROTO_IGMP: return ("IGMP"); 7267c478bd9Sstevel@tonic-gate case IPPROTO_GGP: return ("GGP"); 7277c478bd9Sstevel@tonic-gate case IPPROTO_TCP: return ("TCP"); 7287c478bd9Sstevel@tonic-gate case IPPROTO_EGP: return ("EGP"); 7297c478bd9Sstevel@tonic-gate case IPPROTO_PUP: return ("PUP"); 7307c478bd9Sstevel@tonic-gate case IPPROTO_UDP: return ("UDP"); 7317c478bd9Sstevel@tonic-gate case IPPROTO_IDP: return ("IDP"); 7327c478bd9Sstevel@tonic-gate case IPPROTO_HELLO: return ("HELLO"); 7337c478bd9Sstevel@tonic-gate case IPPROTO_ND: return ("ND"); 7347c478bd9Sstevel@tonic-gate case IPPROTO_EON: return ("EON"); 7357c478bd9Sstevel@tonic-gate case IPPROTO_RAW: return ("RAW"); 7367c478bd9Sstevel@tonic-gate case IPPROTO_OSPF: return ("OSPF"); 7377c478bd9Sstevel@tonic-gate default: return (""); 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate static void 742*45916cd2Sjpk prt_routing_hdr(int flags, const struct ip6_rthdr *ipv6ext_rthdr) 7437c478bd9Sstevel@tonic-gate { 7447c478bd9Sstevel@tonic-gate uint8_t nxt_hdr; 7457c478bd9Sstevel@tonic-gate uint8_t type; 7467c478bd9Sstevel@tonic-gate uint32_t len; 7477c478bd9Sstevel@tonic-gate uint8_t segleft; 7487c478bd9Sstevel@tonic-gate uint32_t numaddrs; 7497c478bd9Sstevel@tonic-gate int i; 7507c478bd9Sstevel@tonic-gate struct ip6_rthdr0 *ipv6ext_rthdr0; 7517c478bd9Sstevel@tonic-gate struct in6_addr *addrs; 7527c478bd9Sstevel@tonic-gate char addr[INET6_ADDRSTRLEN]; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate /* in summary mode, we don't do anything. */ 7557c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 7567c478bd9Sstevel@tonic-gate return; 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate nxt_hdr = ipv6ext_rthdr->ip6r_nxt; 7607c478bd9Sstevel@tonic-gate type = ipv6ext_rthdr->ip6r_type; 7617c478bd9Sstevel@tonic-gate len = 8 * (ipv6ext_rthdr->ip6r_len + 1); 7627c478bd9Sstevel@tonic-gate segleft = ipv6ext_rthdr->ip6r_segleft; 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate show_header("IPv6-Route: ", "IPv6 Routing Header", 0); 7657c478bd9Sstevel@tonic-gate show_space(); 7667c478bd9Sstevel@tonic-gate 767*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 7687c478bd9Sstevel@tonic-gate "Next header = %d (%s)", nxt_hdr, getproto(nxt_hdr)); 769*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 7707c478bd9Sstevel@tonic-gate "Header length = %d", len); 771*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 7727c478bd9Sstevel@tonic-gate "Routing type = %d", type); 773*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 7747c478bd9Sstevel@tonic-gate "Segments left = %d", segleft); 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate if (type == IPV6_RTHDR_TYPE_0) { 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * XXX This loop will print all addresses in the routing header, 7797c478bd9Sstevel@tonic-gate * XXX not just the segments left. 7807c478bd9Sstevel@tonic-gate * XXX (The header length field is twice the number of 7817c478bd9Sstevel@tonic-gate * XXX addresses) 7827c478bd9Sstevel@tonic-gate * XXX At some future time, we may want to change this 7837c478bd9Sstevel@tonic-gate * XXX to differentiate between the hops yet to do 7847c478bd9Sstevel@tonic-gate * XXX and the hops already taken. 7857c478bd9Sstevel@tonic-gate */ 786*45916cd2Sjpk /* LINTED: alignment */ 7877c478bd9Sstevel@tonic-gate ipv6ext_rthdr0 = (struct ip6_rthdr0 *)ipv6ext_rthdr; 7887c478bd9Sstevel@tonic-gate numaddrs = ipv6ext_rthdr0->ip6r0_len / 2; 7897c478bd9Sstevel@tonic-gate addrs = (struct in6_addr *)(ipv6ext_rthdr0 + 1); 7907c478bd9Sstevel@tonic-gate for (i = 0; i < numaddrs; i++) { 7917c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET6, &addrs[i], addr, 7927c478bd9Sstevel@tonic-gate INET6_ADDRSTRLEN); 793*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 7947c478bd9Sstevel@tonic-gate "address[%d]=%s", i, addr); 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate show_space(); 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate static void 802*45916cd2Sjpk prt_fragment_hdr(int flags, const struct ip6_frag *ipv6ext_frag) 8037c478bd9Sstevel@tonic-gate { 8047c478bd9Sstevel@tonic-gate boolean_t morefrag; 8057c478bd9Sstevel@tonic-gate uint16_t fragoffset; 8067c478bd9Sstevel@tonic-gate uint8_t nxt_hdr; 8077c478bd9Sstevel@tonic-gate uint32_t fragident; 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate /* extract the various fields from the fragment header */ 8107c478bd9Sstevel@tonic-gate nxt_hdr = ipv6ext_frag->ip6f_nxt; 8117c478bd9Sstevel@tonic-gate morefrag = (ipv6ext_frag->ip6f_offlg & IP6F_MORE_FRAG) == 0 8127c478bd9Sstevel@tonic-gate ? B_FALSE : B_TRUE; 8137c478bd9Sstevel@tonic-gate fragoffset = ntohs(ipv6ext_frag->ip6f_offlg & IP6F_OFF_MASK); 8147c478bd9Sstevel@tonic-gate fragident = ntohl(ipv6ext_frag->ip6f_ident); 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 817*45916cd2Sjpk (void) snprintf(get_sum_line(), MAXLINE, 8187c478bd9Sstevel@tonic-gate "IPv6 fragment ID=%d Offset=%-4d MF=%d", 8197c478bd9Sstevel@tonic-gate fragident, 8207c478bd9Sstevel@tonic-gate fragoffset, 8217c478bd9Sstevel@tonic-gate morefrag); 8227c478bd9Sstevel@tonic-gate } else { /* F_DTAIL */ 8237c478bd9Sstevel@tonic-gate show_header("IPv6-Frag: ", "IPv6 Fragment Header", 0); 8247c478bd9Sstevel@tonic-gate show_space(); 8257c478bd9Sstevel@tonic-gate 826*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 8277c478bd9Sstevel@tonic-gate "Next Header = %d (%s)", nxt_hdr, getproto(nxt_hdr)); 828*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 8297c478bd9Sstevel@tonic-gate "Fragment Offset = %d", fragoffset); 830*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 8317c478bd9Sstevel@tonic-gate "More Fragments Flag = %s", morefrag ? "true" : "false"); 832*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 8337c478bd9Sstevel@tonic-gate "Identification = %d", fragident); 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate show_space(); 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate static void 840*45916cd2Sjpk print_ip6opt_ls(const uchar_t *data, unsigned int op_len) 8417c478bd9Sstevel@tonic-gate { 842*45916cd2Sjpk uint32_t doi; 843*45916cd2Sjpk uint8_t sotype, solen; 844*45916cd2Sjpk uint16_t value, value2; 845*45916cd2Sjpk char *cp; 846*45916cd2Sjpk int remlen; 847*45916cd2Sjpk boolean_t printed; 848*45916cd2Sjpk 849*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 850*45916cd2Sjpk "Labeled Security Option len = %u bytes%s", op_len, 851*45916cd2Sjpk op_len < sizeof (uint32_t) || (op_len & 1) != 0 ? "?" : ""); 852*45916cd2Sjpk if (op_len < sizeof (uint32_t)) 853*45916cd2Sjpk return; 854*45916cd2Sjpk GETINT32(doi, data); 855*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 856*45916cd2Sjpk " DOI = %d (%s)", doi, doi == IP6LS_DOI_V4 ? "IPv4" : "???"); 857*45916cd2Sjpk op_len -= sizeof (uint32_t); 858*45916cd2Sjpk while (op_len > 0) { 859*45916cd2Sjpk GETINT8(sotype, data); 860*45916cd2Sjpk if (op_len < 2) { 861*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 862*45916cd2Sjpk " truncated %u suboption (no len)", sotype); 863*45916cd2Sjpk break; 864*45916cd2Sjpk } 865*45916cd2Sjpk GETINT8(solen, data); 866*45916cd2Sjpk if (solen < 2 || solen > op_len) { 867*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 868*45916cd2Sjpk " bad %u suboption (len 2 <= %u <= %u)", 869*45916cd2Sjpk sotype, solen, op_len); 870*45916cd2Sjpk if (solen < 2) 871*45916cd2Sjpk solen = 2; 872*45916cd2Sjpk if (solen > op_len) 873*45916cd2Sjpk solen = op_len; 874*45916cd2Sjpk } 875*45916cd2Sjpk op_len -= solen; 876*45916cd2Sjpk solen -= 2; 877*45916cd2Sjpk cp = get_line(0, 0); 878*45916cd2Sjpk remlen = get_line_remain(); 879*45916cd2Sjpk (void) strlcpy(cp, " ", remlen); 880*45916cd2Sjpk cp += 4; 881*45916cd2Sjpk remlen -= 4; 882*45916cd2Sjpk printed = B_TRUE; 883*45916cd2Sjpk switch (sotype) { 884*45916cd2Sjpk case IP6LS_TT_LEVEL: 885*45916cd2Sjpk if (solen != 2) { 886*45916cd2Sjpk printed = B_FALSE; 887*45916cd2Sjpk break; 888*45916cd2Sjpk } 889*45916cd2Sjpk GETINT16(value, data); 890*45916cd2Sjpk (void) snprintf(cp, remlen, "Level %u", value); 891*45916cd2Sjpk solen = 0; 892*45916cd2Sjpk break; 893*45916cd2Sjpk case IP6LS_TT_VECTOR: 894*45916cd2Sjpk (void) strlcpy(cp, "Bit-Vector: ", remlen); 895*45916cd2Sjpk remlen -= strlen(cp); 896*45916cd2Sjpk cp += strlen(cp); 897*45916cd2Sjpk while (solen > 1) { 898*45916cd2Sjpk GETINT16(value, data); 899*45916cd2Sjpk solen -= 2; 900*45916cd2Sjpk (void) snprintf(cp, remlen, "%04x", value); 901*45916cd2Sjpk remlen -= strlen(cp); 902*45916cd2Sjpk cp += strlen(cp); 903*45916cd2Sjpk } 904*45916cd2Sjpk break; 905*45916cd2Sjpk case IP6LS_TT_ENUM: 906*45916cd2Sjpk (void) strlcpy(cp, "Enumeration:", remlen); 907*45916cd2Sjpk remlen -= strlen(cp); 908*45916cd2Sjpk cp += strlen(cp); 909*45916cd2Sjpk while (solen > 1) { 910*45916cd2Sjpk GETINT16(value, data); 911*45916cd2Sjpk solen -= 2; 912*45916cd2Sjpk (void) snprintf(cp, remlen, " %u", value); 913*45916cd2Sjpk remlen -= strlen(cp); 914*45916cd2Sjpk cp += strlen(cp); 915*45916cd2Sjpk } 916*45916cd2Sjpk break; 917*45916cd2Sjpk case IP6LS_TT_RANGES: 918*45916cd2Sjpk (void) strlcpy(cp, "Ranges:", remlen); 919*45916cd2Sjpk remlen -= strlen(cp); 920*45916cd2Sjpk cp += strlen(cp); 921*45916cd2Sjpk while (solen > 3) { 922*45916cd2Sjpk GETINT16(value, data); 923*45916cd2Sjpk GETINT16(value2, data); 924*45916cd2Sjpk solen -= 4; 925*45916cd2Sjpk (void) snprintf(cp, remlen, " %u-%u", value, 926*45916cd2Sjpk value2); 927*45916cd2Sjpk remlen -= strlen(cp); 928*45916cd2Sjpk cp += strlen(cp); 929*45916cd2Sjpk } 930*45916cd2Sjpk break; 931*45916cd2Sjpk case IP6LS_TT_V4: 932*45916cd2Sjpk (void) strlcpy(cp, "IPv4 Option", remlen); 933*45916cd2Sjpk print_ipoptions(data, solen); 934*45916cd2Sjpk solen = 0; 935*45916cd2Sjpk break; 936*45916cd2Sjpk case IP6LS_TT_DEST: 937*45916cd2Sjpk (void) snprintf(cp, remlen, 938*45916cd2Sjpk "Destination-Only Data length %u", solen); 939*45916cd2Sjpk solen = 0; 940*45916cd2Sjpk break; 941*45916cd2Sjpk default: 942*45916cd2Sjpk (void) snprintf(cp, remlen, 943*45916cd2Sjpk " unknown %u suboption (len %u)", sotype, solen); 944*45916cd2Sjpk solen = 0; 945*45916cd2Sjpk break; 946*45916cd2Sjpk } 947*45916cd2Sjpk if (solen != 0) { 948*45916cd2Sjpk if (printed) { 949*45916cd2Sjpk cp = get_line(0, 0); 950*45916cd2Sjpk remlen = get_line_remain(); 951*45916cd2Sjpk } 952*45916cd2Sjpk (void) snprintf(cp, remlen, 953*45916cd2Sjpk " malformed %u suboption (remaining %u)", 954*45916cd2Sjpk sotype, solen); 955*45916cd2Sjpk data += solen; 956*45916cd2Sjpk } 957*45916cd2Sjpk } 958*45916cd2Sjpk } 959*45916cd2Sjpk 960*45916cd2Sjpk static void 961*45916cd2Sjpk prt_hbh_options(int flags, const struct ip6_hbh *ipv6ext_hbh) 962*45916cd2Sjpk { 963*45916cd2Sjpk const uint8_t *data, *ndata; 964*45916cd2Sjpk uint32_t len; 9657c478bd9Sstevel@tonic-gate uint8_t op_type; 9667c478bd9Sstevel@tonic-gate uint8_t op_len; 9677c478bd9Sstevel@tonic-gate uint8_t nxt_hdr; 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate /* in summary mode, we don't do anything. */ 9707c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 9717c478bd9Sstevel@tonic-gate return; 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate show_header("IPv6-HopOpts: ", "IPv6 Hop-by-Hop Options Header", 0); 9757c478bd9Sstevel@tonic-gate show_space(); 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate /* 9787c478bd9Sstevel@tonic-gate * Store the lengh of this ext hdr in bytes. The caller has 9797c478bd9Sstevel@tonic-gate * ensured that there is at least len bytes of data left. 9807c478bd9Sstevel@tonic-gate */ 9817c478bd9Sstevel@tonic-gate len = ipv6ext_hbh->ip6h_len * 8 + 8; 9827c478bd9Sstevel@tonic-gate 983*45916cd2Sjpk ndata = (const uint8_t *)ipv6ext_hbh + 2; 9847c478bd9Sstevel@tonic-gate len -= 2; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate nxt_hdr = ipv6ext_hbh->ip6h_nxt; 987*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 9887c478bd9Sstevel@tonic-gate "Next Header = %u (%s)", nxt_hdr, getproto(nxt_hdr)); 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate while (len > 0) { 991*45916cd2Sjpk data = ndata; 9927c478bd9Sstevel@tonic-gate GETINT8(op_type, data); 993*45916cd2Sjpk /* This is the only one-octet IPv6 option */ 994*45916cd2Sjpk if (op_type == IP6OPT_PAD1) { 995*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 9967c478bd9Sstevel@tonic-gate "pad1 option "); 9977c478bd9Sstevel@tonic-gate len--; 998*45916cd2Sjpk ndata = data; 999*45916cd2Sjpk continue; 1000*45916cd2Sjpk } 1001*45916cd2Sjpk GETINT8(op_len, data); 1002*45916cd2Sjpk if (len < 2 || op_len + 2 > len) { 1003*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1004*45916cd2Sjpk "Error: option %u truncated (%u + 2 > %u)", 1005*45916cd2Sjpk op_type, op_len, len); 1006*45916cd2Sjpk op_len = len - 2; 1007*45916cd2Sjpk /* 1008*45916cd2Sjpk * Continue processing the malformed option so that we 1009*45916cd2Sjpk * can display as much as possible. 1010*45916cd2Sjpk */ 1011*45916cd2Sjpk } 1012*45916cd2Sjpk 1013*45916cd2Sjpk /* advance pointers to the next option */ 1014*45916cd2Sjpk len -= op_len + 2; 1015*45916cd2Sjpk ndata = data + op_len; 1016*45916cd2Sjpk 1017*45916cd2Sjpk /* process this option */ 1018*45916cd2Sjpk switch (op_type) { 10197c478bd9Sstevel@tonic-gate case IP6OPT_PADN: 1020*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 10217c478bd9Sstevel@tonic-gate "padN option len = %u", op_len); 10227c478bd9Sstevel@tonic-gate break; 10237c478bd9Sstevel@tonic-gate case IP6OPT_JUMBO: { 10247c478bd9Sstevel@tonic-gate uint32_t payload_len; 10257c478bd9Sstevel@tonic-gate 1026*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1027*45916cd2Sjpk "Jumbo Payload Option len = %u bytes%s", op_len, 1028*45916cd2Sjpk op_len == sizeof (uint32_t) ? "" : "?"); 10297c478bd9Sstevel@tonic-gate if (op_len == sizeof (uint32_t)) { 10307c478bd9Sstevel@tonic-gate GETINT32(payload_len, data); 1031*45916cd2Sjpk (void) snprintf(get_line(0, 0), 1032*45916cd2Sjpk get_line_remain(), 10337c478bd9Sstevel@tonic-gate "Jumbo Payload Length = %u bytes", 10347c478bd9Sstevel@tonic-gate payload_len); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate break; 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate case IP6OPT_ROUTER_ALERT: { 10397c478bd9Sstevel@tonic-gate uint16_t value; 10407c478bd9Sstevel@tonic-gate const char *label[] = {"MLD", "RSVP", "AN"}; 10417c478bd9Sstevel@tonic-gate 1042*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1043*45916cd2Sjpk "Router Alert Option len = %u bytes%s", op_len, 1044*45916cd2Sjpk op_len == sizeof (uint16_t) ? "" : "?"); 10457c478bd9Sstevel@tonic-gate if (op_len == sizeof (uint16_t)) { 10467c478bd9Sstevel@tonic-gate GETINT16(value, data); 1047*45916cd2Sjpk (void) snprintf(get_line(0, 0), 1048*45916cd2Sjpk get_line_remain(), 10497c478bd9Sstevel@tonic-gate "Alert Type = %d (%s)", value, 10507c478bd9Sstevel@tonic-gate value < sizeof (label) / sizeof (label[0]) ? 10517c478bd9Sstevel@tonic-gate label[value] : "???"); 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate break; 10547c478bd9Sstevel@tonic-gate } 1055*45916cd2Sjpk case IP6OPT_LS: 1056*45916cd2Sjpk print_ip6opt_ls(data, op_len); 1057*45916cd2Sjpk break; 10587c478bd9Sstevel@tonic-gate default: 1059*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 10607c478bd9Sstevel@tonic-gate "Option type = %u, len = %u", op_type, op_len); 10617c478bd9Sstevel@tonic-gate break; 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate show_space(); 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate static void 1069*45916cd2Sjpk prt_dest_options(int flags, const struct ip6_dest *ipv6ext_dest) 10707c478bd9Sstevel@tonic-gate { 1071*45916cd2Sjpk const uint8_t *data, *ndata; 1072*45916cd2Sjpk uint32_t len; 10737c478bd9Sstevel@tonic-gate uint8_t op_type; 10747c478bd9Sstevel@tonic-gate uint32_t op_len; 10757c478bd9Sstevel@tonic-gate uint8_t nxt_hdr; 10767c478bd9Sstevel@tonic-gate uint8_t value; 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate /* in summary mode, we don't do anything. */ 10797c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 10807c478bd9Sstevel@tonic-gate return; 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate show_header("IPv6-DstOpts: ", "IPv6 Destination Options Header", 0); 10847c478bd9Sstevel@tonic-gate show_space(); 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate /* 10877c478bd9Sstevel@tonic-gate * Store the length of this ext hdr in bytes. The caller has 10887c478bd9Sstevel@tonic-gate * ensured that there is at least len bytes of data left. 10897c478bd9Sstevel@tonic-gate */ 10907c478bd9Sstevel@tonic-gate len = ipv6ext_dest->ip6d_len * 8 + 8; 10917c478bd9Sstevel@tonic-gate 1092*45916cd2Sjpk ndata = (const uint8_t *)ipv6ext_dest + 2; /* skip hdr/len */ 10937c478bd9Sstevel@tonic-gate len -= 2; 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate nxt_hdr = ipv6ext_dest->ip6d_nxt; 1096*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 10977c478bd9Sstevel@tonic-gate "Next Header = %u (%s)", nxt_hdr, getproto(nxt_hdr)); 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate while (len > 0) { 1100*45916cd2Sjpk data = ndata; 11017c478bd9Sstevel@tonic-gate GETINT8(op_type, data); 1102*45916cd2Sjpk if (op_type == IP6OPT_PAD1) { 1103*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 11047c478bd9Sstevel@tonic-gate "pad1 option "); 11057c478bd9Sstevel@tonic-gate len--; 1106*45916cd2Sjpk ndata = data; 1107*45916cd2Sjpk continue; 1108*45916cd2Sjpk } 1109*45916cd2Sjpk GETINT8(op_len, data); 1110*45916cd2Sjpk if (len < 2 || op_len + 2 > len) { 1111*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1112*45916cd2Sjpk "Error: option %u truncated (%u + 2 > %u)", 1113*45916cd2Sjpk op_type, op_len, len); 1114*45916cd2Sjpk op_len = len - 2; 1115*45916cd2Sjpk /* 1116*45916cd2Sjpk * Continue processing the malformed option so that we 1117*45916cd2Sjpk * can display as much as possible. 1118*45916cd2Sjpk */ 1119*45916cd2Sjpk } 1120*45916cd2Sjpk 1121*45916cd2Sjpk /* advance pointers to the next option */ 1122*45916cd2Sjpk len -= op_len + 2; 1123*45916cd2Sjpk ndata = data + op_len; 1124*45916cd2Sjpk 1125*45916cd2Sjpk /* process this option */ 1126*45916cd2Sjpk switch (op_type) { 11277c478bd9Sstevel@tonic-gate case IP6OPT_PADN: 1128*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 11297c478bd9Sstevel@tonic-gate "padN option len = %u", op_len); 11307c478bd9Sstevel@tonic-gate break; 11317c478bd9Sstevel@tonic-gate case IP6OPT_TUNNEL_LIMIT: 11327c478bd9Sstevel@tonic-gate GETINT8(value, data); 1133*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 11347c478bd9Sstevel@tonic-gate "tunnel encapsulation limit len = %d, value = %d", 11357c478bd9Sstevel@tonic-gate op_len, value); 1136*45916cd2Sjpk break; 1137*45916cd2Sjpk case IP6OPT_LS: 1138*45916cd2Sjpk print_ip6opt_ls(data, op_len); 11397c478bd9Sstevel@tonic-gate break; 11407c478bd9Sstevel@tonic-gate default: 1141*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 11427c478bd9Sstevel@tonic-gate "Option type = %u, len = %u", op_type, op_len); 1143*45916cd2Sjpk break; 1144*45916cd2Sjpk } 1145*45916cd2Sjpk } 1146*45916cd2Sjpk 1147*45916cd2Sjpk show_space(); 1148*45916cd2Sjpk } 1149*45916cd2Sjpk 1150*45916cd2Sjpk #define ALABEL_MAXLEN 256 1151*45916cd2Sjpk 1152*45916cd2Sjpk static char ascii_label[ALABEL_MAXLEN]; 1153*45916cd2Sjpk static char *plabel = ascii_label; 1154*45916cd2Sjpk 1155*45916cd2Sjpk struct snoop_pair { 1156*45916cd2Sjpk int val; 1157*45916cd2Sjpk const char *name; 1158*45916cd2Sjpk }; 1159*45916cd2Sjpk 1160*45916cd2Sjpk static struct snoop_pair ripso_class_tbl[] = { 1161*45916cd2Sjpk TSOL_CL_TOP_SECRET, "TOP SECRET", 1162*45916cd2Sjpk TSOL_CL_SECRET, "SECRET", 1163*45916cd2Sjpk TSOL_CL_CONFIDENTIAL, "CONFIDENTIAL", 1164*45916cd2Sjpk TSOL_CL_UNCLASSIFIED, "UNCLASSIFIED", 1165*45916cd2Sjpk -1, NULL 1166*45916cd2Sjpk }; 1167*45916cd2Sjpk 1168*45916cd2Sjpk static struct snoop_pair ripso_prot_tbl[] = { 1169*45916cd2Sjpk TSOL_PA_GENSER, "GENSER", 1170*45916cd2Sjpk TSOL_PA_SIOP_ESI, "SIOP-ESI", 1171*45916cd2Sjpk TSOL_PA_SCI, "SCI", 1172*45916cd2Sjpk TSOL_PA_NSA, "NSA", 1173*45916cd2Sjpk TSOL_PA_DOE, "DOE", 1174*45916cd2Sjpk 0x04, "UNASSIGNED", 1175*45916cd2Sjpk 0x02, "UNASSIGNED", 1176*45916cd2Sjpk -1, NULL 1177*45916cd2Sjpk }; 1178*45916cd2Sjpk 1179*45916cd2Sjpk static struct snoop_pair * 1180*45916cd2Sjpk get_pair_byval(struct snoop_pair pairlist[], int val) 1181*45916cd2Sjpk { 1182*45916cd2Sjpk int i; 1183*45916cd2Sjpk 1184*45916cd2Sjpk for (i = 0; pairlist[i].name != NULL; i++) 1185*45916cd2Sjpk if (pairlist[i].val == val) 1186*45916cd2Sjpk return (&pairlist[i]); 1187*45916cd2Sjpk return (NULL); 1188*45916cd2Sjpk } 1189*45916cd2Sjpk 1190*45916cd2Sjpk static void 1191*45916cd2Sjpk print_ripso(const uchar_t *opt) 1192*45916cd2Sjpk { 1193*45916cd2Sjpk struct snoop_pair *ripso_class; 1194*45916cd2Sjpk int i, index, prot_len; 1195*45916cd2Sjpk boolean_t first_prot; 1196*45916cd2Sjpk char line[100], *ptr; 1197*45916cd2Sjpk 1198*45916cd2Sjpk prot_len = opt[1] - 3; 1199*45916cd2Sjpk if (prot_len < 0) 1200*45916cd2Sjpk return; 1201*45916cd2Sjpk 1202*45916cd2Sjpk show_header("RIPSO: ", "Revised IP Security Option", 0); 1203*45916cd2Sjpk show_space(); 1204*45916cd2Sjpk 1205*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1206*45916cd2Sjpk "Type = Basic Security Option (%d), Length = %d", opt[0], opt[1]); 1207*45916cd2Sjpk 1208*45916cd2Sjpk /* 1209*45916cd2Sjpk * Display Classification Level 1210*45916cd2Sjpk */ 1211*45916cd2Sjpk ripso_class = get_pair_byval(ripso_class_tbl, (int)opt[2]); 1212*45916cd2Sjpk if (ripso_class != NULL) 1213*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1214*45916cd2Sjpk "Classification = Unknown (0x%02x)", opt[2]); 1215*45916cd2Sjpk else 1216*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1217*45916cd2Sjpk "Classification = %s (0x%02x)", 1218*45916cd2Sjpk ripso_class->name, ripso_class->val); 1219*45916cd2Sjpk 1220*45916cd2Sjpk /* 1221*45916cd2Sjpk * Display Protection Authority Flags 1222*45916cd2Sjpk */ 1223*45916cd2Sjpk (void) snprintf(line, sizeof (line), "Protection Authority = "); 1224*45916cd2Sjpk ptr = line; 1225*45916cd2Sjpk first_prot = B_TRUE; 1226*45916cd2Sjpk for (i = 0; i < prot_len; i++) { 1227*45916cd2Sjpk index = 0; 1228*45916cd2Sjpk while (ripso_prot_tbl[index].name != NULL) { 1229*45916cd2Sjpk if (opt[3 + i] & ripso_prot_tbl[index].val) { 1230*45916cd2Sjpk ptr = strchr(ptr, 0); 1231*45916cd2Sjpk if (!first_prot) { 1232*45916cd2Sjpk (void) strlcpy(ptr, ", ", 1233*45916cd2Sjpk sizeof (line) - (ptr - line)); 1234*45916cd2Sjpk ptr = strchr(ptr, 0); 1235*45916cd2Sjpk } 1236*45916cd2Sjpk (void) snprintf(ptr, 1237*45916cd2Sjpk sizeof (line) - (ptr - line), 1238*45916cd2Sjpk "%s (0x%02x)", 1239*45916cd2Sjpk ripso_prot_tbl[index].name, 1240*45916cd2Sjpk ripso_prot_tbl[index].val); 1241*45916cd2Sjpk } 1242*45916cd2Sjpk index++; 12437c478bd9Sstevel@tonic-gate } 1244*45916cd2Sjpk if ((opt[3 + i] & 1) == 0) 12457c478bd9Sstevel@tonic-gate break; 1246*45916cd2Sjpk } 1247*45916cd2Sjpk if (!first_prot) 1248*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), "%s", line); 1249*45916cd2Sjpk else 1250*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), "%sNone", 1251*45916cd2Sjpk line); 1252*45916cd2Sjpk } 1253*45916cd2Sjpk 1254*45916cd2Sjpk #define CIPSO_GENERIC_ARRAY_LEN 200 1255*45916cd2Sjpk 1256*45916cd2Sjpk /* 1257*45916cd2Sjpk * Return 1 if CIPSO SL and Categories are all 1's; 0 otherwise. 1258*45916cd2Sjpk * 1259*45916cd2Sjpk * Note: opt starts with "Tag Type": 1260*45916cd2Sjpk * 1261*45916cd2Sjpk * |tag_type(1)|tag_length(1)|align(1)|sl(1)|categories(variable)| 1262*45916cd2Sjpk * 1263*45916cd2Sjpk */ 1264*45916cd2Sjpk static boolean_t 1265*45916cd2Sjpk cipso_high(const uchar_t *opt) 1266*45916cd2Sjpk { 1267*45916cd2Sjpk int i; 1268*45916cd2Sjpk 1269*45916cd2Sjpk if (((int)opt[1] + 6) < IP_MAX_OPT_LENGTH) 1270*45916cd2Sjpk return (B_FALSE); 1271*45916cd2Sjpk for (i = 0; i < ((int)opt[1] - 3); i++) 1272*45916cd2Sjpk if (opt[3 + i] != 0xff) 1273*45916cd2Sjpk return (B_FALSE); 1274*45916cd2Sjpk return (B_TRUE); 1275*45916cd2Sjpk } 1276*45916cd2Sjpk 1277*45916cd2Sjpk /* 1278*45916cd2Sjpk * Converts CIPSO label to SL. 1279*45916cd2Sjpk * 1280*45916cd2Sjpk * Note: opt starts with "Tag Type": 1281*45916cd2Sjpk * 1282*45916cd2Sjpk * |tag_type(1)|tag_length(1)|align(1)|sl(1)|categories(variable)| 1283*45916cd2Sjpk * 1284*45916cd2Sjpk */ 1285*45916cd2Sjpk static void 1286*45916cd2Sjpk cipso2sl(const uchar_t *opt, bslabel_t *sl, int *high) 1287*45916cd2Sjpk { 1288*45916cd2Sjpk int i, taglen; 1289*45916cd2Sjpk uchar_t *q = (uchar_t *)&((_bslabel_impl_t *)sl)->compartments; 1290*45916cd2Sjpk 1291*45916cd2Sjpk *high = 0; 1292*45916cd2Sjpk taglen = opt[1]; 1293*45916cd2Sjpk memset((caddr_t)sl, 0, sizeof (bslabel_t)); 1294*45916cd2Sjpk 1295*45916cd2Sjpk if (cipso_high(opt)) { 1296*45916cd2Sjpk BSLHIGH(sl); 1297*45916cd2Sjpk *high = 1; 1298*45916cd2Sjpk } else { 1299*45916cd2Sjpk LCLASS_SET((_bslabel_impl_t *)sl, opt[3]); 1300*45916cd2Sjpk for (i = 0; i < taglen - TSOL_TT1_MIN_LENGTH; i++) 1301*45916cd2Sjpk q[i] = opt[TSOL_TT1_MIN_LENGTH + i]; 1302*45916cd2Sjpk } 1303*45916cd2Sjpk SETBLTYPE(sl, SUN_SL_ID); 1304*45916cd2Sjpk } 1305*45916cd2Sjpk 1306*45916cd2Sjpk static int 1307*45916cd2Sjpk interpret_cipso_tagtype1(const uchar_t *opt) 1308*45916cd2Sjpk { 1309*45916cd2Sjpk int i, taglen, ishigh; 1310*45916cd2Sjpk bslabel_t sl; 1311*45916cd2Sjpk char line[CIPSO_GENERIC_ARRAY_LEN], *ptr; 1312*45916cd2Sjpk 1313*45916cd2Sjpk taglen = opt[1]; 1314*45916cd2Sjpk if (taglen < TSOL_TT1_MIN_LENGTH || 1315*45916cd2Sjpk taglen > TSOL_TT1_MAX_LENGTH) 1316*45916cd2Sjpk return (taglen); 1317*45916cd2Sjpk 1318*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1319*45916cd2Sjpk "Tag Type = %d, Tag Length = %d", opt[0], opt[1]); 1320*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1321*45916cd2Sjpk "Sensitivity Level = 0x%02x", opt[3]); 1322*45916cd2Sjpk ptr = line; 1323*45916cd2Sjpk for (i = 0; i < taglen - TSOL_TT1_MIN_LENGTH; i++) { 1324*45916cd2Sjpk (void) snprintf(ptr, sizeof (line) - (ptr - line), "%02x", 1325*45916cd2Sjpk opt[TSOL_TT1_MIN_LENGTH + i]); 1326*45916cd2Sjpk ptr = strchr(ptr, 0); 1327*45916cd2Sjpk } 1328*45916cd2Sjpk if (i != 0) { 1329*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1330*45916cd2Sjpk "Categories = "); 1331*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), "\t%s", 1332*45916cd2Sjpk line); 1333*45916cd2Sjpk } else { 1334*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1335*45916cd2Sjpk "Categories = None"); 1336*45916cd2Sjpk } 1337*45916cd2Sjpk cipso2sl(opt, &sl, &ishigh); 1338*45916cd2Sjpk if (is_system_labeled) { 1339*45916cd2Sjpk if (bsltos(&sl, &plabel, ALABEL_MAXLEN, 1340*45916cd2Sjpk LONG_CLASSIFICATION|LONG_WORDS|VIEW_INTERNAL) < 0) { 1341*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1342*45916cd2Sjpk "The Sensitivity Level and Categories can't be " 1343*45916cd2Sjpk "mapped to a valid SL"); 1344*45916cd2Sjpk } else { 1345*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1346*45916cd2Sjpk "The Sensitivity Level and Categories are mapped " 1347*45916cd2Sjpk "to the SL:"); 1348*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1349*45916cd2Sjpk "\t%s", ascii_label); 1350*45916cd2Sjpk } 1351*45916cd2Sjpk } 1352*45916cd2Sjpk return (taglen); 1353*45916cd2Sjpk } 1354*45916cd2Sjpk 1355*45916cd2Sjpk /* 1356*45916cd2Sjpk * The following struct definition #define's are copied from TS1.x. They are 1357*45916cd2Sjpk * not used here (except TTYPE_3_MAX_TOKENS), but included as a reference for 1358*45916cd2Sjpk * the tag type 3 packet format. 1359*45916cd2Sjpk */ 1360*45916cd2Sjpk #define TTYPE_3_MAX_TOKENS 7 1361*45916cd2Sjpk 1362*45916cd2Sjpk /* 1363*45916cd2Sjpk * Display CIPSO tag type 3 which is defined by MAXSIX. 1364*45916cd2Sjpk */ 1365*45916cd2Sjpk static int 1366*45916cd2Sjpk interpret_cipso_tagtype3(const uchar_t *opt) 1367*45916cd2Sjpk { 1368*45916cd2Sjpk uchar_t tagtype; 1369*45916cd2Sjpk int index, numtokens, taglen; 1370*45916cd2Sjpk uint16_t mask; 1371*45916cd2Sjpk uint32_t token; 1372*45916cd2Sjpk static const char *name[] = { 1373*45916cd2Sjpk "SL", 1374*45916cd2Sjpk "NCAV", 1375*45916cd2Sjpk "INTEG", 1376*45916cd2Sjpk "SID", 1377*45916cd2Sjpk "undefined", 1378*45916cd2Sjpk "undefined", 1379*45916cd2Sjpk "IL", 1380*45916cd2Sjpk "PRIVS", 1381*45916cd2Sjpk "LUID", 1382*45916cd2Sjpk "PID", 1383*45916cd2Sjpk "IDS", 1384*45916cd2Sjpk "ACL" 1385*45916cd2Sjpk }; 1386*45916cd2Sjpk 1387*45916cd2Sjpk tagtype = *opt++; 1388*45916cd2Sjpk (void) memcpy(&mask, opt + 3, sizeof (mask)); 1389*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1390*45916cd2Sjpk "Tag Type = %d (MAXSIX)", tagtype); 1391*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1392*45916cd2Sjpk "Generation = 0x%02x%02x%02x, Mask = 0x%04x", opt[0], opt[1], 1393*45916cd2Sjpk opt[2], mask); 1394*45916cd2Sjpk opt += 3 + sizeof (mask); 1395*45916cd2Sjpk 1396*45916cd2Sjpk /* 1397*45916cd2Sjpk * Display tokens 1398*45916cd2Sjpk */ 1399*45916cd2Sjpk numtokens = 0; 1400*45916cd2Sjpk index = 0; 1401*45916cd2Sjpk while (mask != 0 && numtokens < TTYPE_3_MAX_TOKENS) { 1402*45916cd2Sjpk if (mask & 0x0001) { 1403*45916cd2Sjpk (void) memcpy(&token, opt, sizeof (token)); 1404*45916cd2Sjpk opt += sizeof (token); 1405*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1406*45916cd2Sjpk "Attribute = %s, Token = 0x%08x", 1407*45916cd2Sjpk index < sizeof (name) / sizeof (*name) ? 1408*45916cd2Sjpk name[index] : "unknown", token); 1409*45916cd2Sjpk numtokens++; 14107c478bd9Sstevel@tonic-gate } 1411*45916cd2Sjpk mask = mask >> 1; 1412*45916cd2Sjpk index++; 1413*45916cd2Sjpk } 1414*45916cd2Sjpk 1415*45916cd2Sjpk taglen = 6 + numtokens * 4; 1416*45916cd2Sjpk return (taglen); 1417*45916cd2Sjpk } 1418*45916cd2Sjpk 1419*45916cd2Sjpk static void 1420*45916cd2Sjpk print_cipso(const uchar_t *opt) 1421*45916cd2Sjpk { 1422*45916cd2Sjpk int optlen, taglen, tagnum; 1423*45916cd2Sjpk uint32_t doi; 1424*45916cd2Sjpk char line[CIPSO_GENERIC_ARRAY_LEN]; 1425*45916cd2Sjpk char *oldnest; 1426*45916cd2Sjpk 1427*45916cd2Sjpk optlen = opt[1]; 1428*45916cd2Sjpk if (optlen < TSOL_CIPSO_MIN_LENGTH || optlen > TSOL_CIPSO_MAX_LENGTH) 1429*45916cd2Sjpk return; 1430*45916cd2Sjpk 1431*45916cd2Sjpk oldnest = prot_nest_prefix; 1432*45916cd2Sjpk prot_nest_prefix = prot_prefix; 1433*45916cd2Sjpk show_header("CIPSO: ", "Common IP Security Option", 0); 1434*45916cd2Sjpk show_space(); 1435*45916cd2Sjpk 1436*45916cd2Sjpk /* 1437*45916cd2Sjpk * Display CIPSO Header 1438*45916cd2Sjpk */ 1439*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1440*45916cd2Sjpk "Type = CIPSO (%d), Length = %d", opt[0], opt[1]); 1441*45916cd2Sjpk (void) memcpy(&doi, opt + 2, sizeof (doi)); 1442*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1443*45916cd2Sjpk "Domain of Interpretation = %u", (unsigned)ntohl(doi)); 1444*45916cd2Sjpk 1445*45916cd2Sjpk if (opt[1] == TSOL_CIPSO_MIN_LENGTH) { /* no tags */ 1446*45916cd2Sjpk show_space(); 1447*45916cd2Sjpk prot_prefix = prot_nest_prefix; 1448*45916cd2Sjpk prot_nest_prefix = oldnest; 1449*45916cd2Sjpk return; 14507c478bd9Sstevel@tonic-gate } 1451*45916cd2Sjpk optlen -= TSOL_CIPSO_MIN_LENGTH; 1452*45916cd2Sjpk opt += TSOL_CIPSO_MIN_LENGTH; 14537c478bd9Sstevel@tonic-gate 1454*45916cd2Sjpk /* 1455*45916cd2Sjpk * Display Each Tag 1456*45916cd2Sjpk */ 1457*45916cd2Sjpk tagnum = 1; 1458*45916cd2Sjpk while (optlen >= TSOL_TT1_MIN_LENGTH) { 1459*45916cd2Sjpk (void) snprintf(line, sizeof (line), "Tag# %d", tagnum); 1460*45916cd2Sjpk show_header("CIPSO: ", line, 0); 1461*45916cd2Sjpk /* 1462*45916cd2Sjpk * We handle tag type 1 and 3 only. Note, tag type 3 1463*45916cd2Sjpk * is MAXSIX defined. 1464*45916cd2Sjpk */ 1465*45916cd2Sjpk switch (opt[0]) { 1466*45916cd2Sjpk case 1: 1467*45916cd2Sjpk taglen = interpret_cipso_tagtype1(opt); 1468*45916cd2Sjpk break; 1469*45916cd2Sjpk case 3: 1470*45916cd2Sjpk taglen = interpret_cipso_tagtype3(opt); 1471*45916cd2Sjpk break; 1472*45916cd2Sjpk default: 1473*45916cd2Sjpk (void) snprintf(get_line(0, 0), get_line_remain(), 1474*45916cd2Sjpk "Unknown Tag Type %d", opt[0]); 1475*45916cd2Sjpk show_space(); 1476*45916cd2Sjpk prot_prefix = prot_nest_prefix; 1477*45916cd2Sjpk prot_nest_prefix = oldnest; 1478*45916cd2Sjpk return; 1479*45916cd2Sjpk } 1480*45916cd2Sjpk 1481*45916cd2Sjpk /* 1482*45916cd2Sjpk * Move to the next tag 1483*45916cd2Sjpk */ 1484*45916cd2Sjpk if (taglen <= 0) 1485*45916cd2Sjpk break; 1486*45916cd2Sjpk optlen -= taglen; 1487*45916cd2Sjpk opt += taglen; 1488*45916cd2Sjpk tagnum++; 1489*45916cd2Sjpk } 14907c478bd9Sstevel@tonic-gate show_space(); 1491*45916cd2Sjpk prot_prefix = prot_nest_prefix; 1492*45916cd2Sjpk prot_nest_prefix = oldnest; 14937c478bd9Sstevel@tonic-gate } 1494