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