1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <ctype.h> 31 #include <string.h> 32 #include <fcntl.h> 33 #include <string.h> 34 #include <strings.h> 35 #include <sys/types.h> 36 #include <sys/sysmacros.h> 37 #include <sys/time.h> 38 39 #include <sys/socket.h> 40 #include <sys/sockio.h> 41 #include <net/if.h> 42 #include <netinet/in_systm.h> 43 #include <netinet/in.h> 44 #include <netinet/ip.h> 45 #include <netinet/ip_icmp.h> 46 #include <netinet/icmp6.h> 47 #include <netinet/if_ether.h> 48 #include <inet/ipsecesp.h> 49 #include <inet/ipsecah.h> 50 #include "snoop.h" 51 52 /* ARGSUSED */ 53 int 54 interpret_esp(int flags, uint8_t *hdr, int iplen, int fraglen) 55 { 56 /* LINTED: alignment */ 57 esph_t *esph = (esph_t *)hdr; 58 esph_t *aligned_esph; 59 esph_t storage; /* In case hdr isn't aligned. */ 60 char *line; 61 62 if (fraglen < sizeof (esph_t)) 63 return (fraglen); /* incomplete header */ 64 65 if (!IS_P2ALIGNED(hdr, 4)) { 66 aligned_esph = &storage; 67 bcopy(hdr, aligned_esph, sizeof (esph_t)); 68 } else { 69 aligned_esph = esph; 70 } 71 72 if (flags & F_SUM) { 73 line = (char *)get_sum_line(); 74 /* 75 * sprintf() is safe because line guarantees us 80 columns, 76 * and SPI and replay certainly won't exceed that. 77 */ 78 (void) sprintf(line, "ESP SPI=0x%x Replay=%u", 79 ntohl(aligned_esph->esph_spi), 80 ntohl(aligned_esph->esph_replay)); 81 line += strlen(line); 82 } 83 84 if (flags & F_DTAIL) { 85 show_header("ESP: ", "Encapsulating Security Payload", 86 sizeof (esph_t)); 87 show_space(); 88 /* 89 * sprintf() is safe because get_line guarantees us 80 columns, 90 * and SPI and replay certainly won't exceed that. 91 */ 92 (void) sprintf(get_line((char *)&esph->esph_spi - dlc_header, 93 4), "SPI = 0x%x", ntohl(aligned_esph->esph_spi)); 94 (void) sprintf(get_line((char *)&esph->esph_replay - 95 dlc_header, 4), "Replay = %u", 96 ntohl(aligned_esph->esph_replay)); 97 (void) sprintf(get_line((char *)(esph + 1) - dlc_header, 98 4), " ....ENCRYPTED DATA...."); 99 } 100 101 return (sizeof (esph_t)); 102 } 103 104 int 105 interpret_ah(int flags, uint8_t *hdr, int iplen, int fraglen) 106 { 107 /* LINTED: alignment */ 108 ah_t *ah = (ah_t *)hdr; 109 ah_t *aligned_ah; 110 ah_t storage; /* In case hdr isn't aligned. */ 111 char *line, *buff; 112 uint_t ahlen, auth_data_len; 113 uint8_t *auth_data, *data; 114 int new_iplen; 115 uint8_t proto; 116 117 if (fraglen < sizeof (ah_t)) 118 return (fraglen); /* incomplete header */ 119 120 if (!IS_P2ALIGNED(hdr, 4)) { 121 aligned_ah = (ah_t *)&storage; 122 bcopy(hdr, &storage, sizeof (ah_t)); 123 } else { 124 aligned_ah = ah; 125 } 126 127 /* 128 * "+ 8" is for the "constant" part that's not included in the AH 129 * length. 130 * 131 * The AH RFC specifies the length field in "length in 4-byte units, 132 * not counting the first 8 bytes". So if an AH is 24 bytes long, 133 * the length field will contain "4". (4 * 4 + 8 == 24). 134 */ 135 ahlen = (aligned_ah->ah_length << 2) + 8; 136 fraglen -= ahlen; 137 if (fraglen < 0) 138 return (fraglen + ahlen); /* incomplete header */ 139 140 auth_data_len = ahlen - sizeof (ah_t); 141 auth_data = (uint8_t *)(ah + 1); 142 data = auth_data + auth_data_len; 143 144 if (flags & F_SUM) { 145 line = (char *)get_sum_line(); 146 (void) sprintf(line, "AH SPI=0x%x Replay=%u", 147 ntohl(aligned_ah->ah_spi), ntohl(aligned_ah->ah_replay)); 148 line += strlen(line); 149 } 150 151 if (flags & F_DTAIL) { 152 show_header("AH: ", "Authentication Header", ahlen); 153 show_space(); 154 (void) sprintf(get_line((char *)&ah->ah_nexthdr - dlc_header, 155 1), "Next header = %d (%s)", aligned_ah->ah_nexthdr, 156 getproto(aligned_ah->ah_nexthdr)); 157 (void) sprintf(get_line((char *)&ah->ah_length - dlc_header, 1), 158 "AH length = %d (%d bytes)", aligned_ah->ah_length, ahlen); 159 (void) sprintf(get_line((char *)&ah->ah_reserved - dlc_header, 160 2), "<Reserved field = 0x%x>", 161 ntohs(aligned_ah->ah_reserved)); 162 (void) sprintf(get_line((char *)&ah->ah_spi - dlc_header, 4), 163 "SPI = 0x%x", ntohl(aligned_ah->ah_spi)); 164 (void) sprintf(get_line((char *)&ah->ah_replay - dlc_header, 4), 165 "Replay = %u", ntohl(aligned_ah->ah_replay)); 166 167 /* * 2 for two hex digits per auth_data byte. */ 168 buff = malloc(auth_data_len * 2); 169 if (buff != NULL) { 170 int i; 171 172 for (i = 0; i < auth_data_len; i++) 173 sprintf(buff + i * 2, "%02x", auth_data[i]); 174 } 175 176 (void) sprintf(get_line((char *)auth_data - dlc_header, 177 auth_data_len), "ICV = %s", 178 (buff == NULL) ? "<out of memory>" : buff); 179 180 /* malloc(3c) says I can call free even if buff == NULL */ 181 free(buff); 182 183 show_space(); 184 } 185 186 new_iplen = iplen - ahlen; 187 proto = aligned_ah->ah_nexthdr; 188 189 /* 190 * Print IPv6 Extension Headers, or skip them in the summary case. 191 */ 192 if (proto == IPPROTO_HOPOPTS || proto == IPPROTO_DSTOPTS || 193 proto == IPPROTO_ROUTING || proto == IPPROTO_FRAGMENT) { 194 (void) print_ipv6_extensions(flags, &data, &proto, &iplen, 195 &fraglen); 196 } 197 198 if (fraglen > 0) 199 switch (proto) { 200 case IPPROTO_ENCAP: 201 /* LINTED: alignment */ 202 (void) interpret_ip(flags, (struct ip *)data, 203 new_iplen); 204 break; 205 case IPPROTO_IPV6: 206 (void) interpret_ipv6(flags, (ip6_t *)data, 207 new_iplen); 208 break; 209 case IPPROTO_ICMP: 210 (void) interpret_icmp(flags, 211 /* LINTED: alignment */ 212 (struct icmp *)data, new_iplen, fraglen); 213 break; 214 case IPPROTO_ICMPV6: 215 /* LINTED: alignment */ 216 (void) interpret_icmpv6(flags, (icmp6_t *)data, 217 new_iplen, fraglen); 218 break; 219 case IPPROTO_TCP: 220 (void) interpret_tcp(flags, 221 (struct tcphdr *)data, new_iplen, fraglen); 222 break; 223 224 case IPPROTO_ESP: 225 (void) interpret_esp(flags, data, new_iplen, 226 fraglen); 227 break; 228 229 case IPPROTO_AH: 230 (void) interpret_ah(flags, data, new_iplen, 231 fraglen); 232 break; 233 234 case IPPROTO_UDP: 235 (void) interpret_udp(flags, 236 (struct udphdr *)data, new_iplen, fraglen); 237 break; 238 /* default case is to not print anything else */ 239 } 240 241 return (ahlen); 242 } 243