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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <ctype.h> 32 #include <string.h> 33 #include <fcntl.h> 34 #include <string.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 extern char *dlc_header; 53 54 int 55 interpret_esp(int flags, uint8_t *hdr, int iplen, int fraglen) 56 { 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 ah_t *ah = (ah_t *)hdr; 108 ah_t *aligned_ah; 109 ah_t storage; /* In case hdr isn't aligned. */ 110 char *line, *buff; 111 uint_t ahlen, auth_data_len; 112 uint8_t *auth_data, *data; 113 int new_iplen; 114 uint8_t proto; 115 116 if (fraglen < sizeof (ah_t)) 117 return (fraglen); /* incomplete header */ 118 119 if (!IS_P2ALIGNED(hdr, 4)) { 120 aligned_ah = (ah_t *)&storage; 121 bcopy(hdr, storage, sizeof (ah_t)); 122 } else { 123 aligned_ah = ah; 124 } 125 126 /* 127 * "+ 8" is for the "constant" part that's not included in the AH 128 * length. 129 * 130 * The AH RFC specifies the length field in "length in 4-byte units, 131 * not counting the first 8 bytes". So if an AH is 24 bytes long, 132 * the length field will contain "4". (4 * 4 + 8 == 24). 133 */ 134 ahlen = (aligned_ah->ah_length << 2) + 8; 135 fraglen -= ahlen; 136 if (fraglen < 0) 137 return (fraglen + ahlen); /* incomplete header */ 138 139 auth_data_len = ahlen - sizeof (ah_t); 140 auth_data = (uint8_t *)(ah + 1); 141 data = auth_data + auth_data_len; 142 143 if (flags & F_SUM) { 144 line = (char *)get_sum_line(); 145 (void) sprintf(line, "AH SPI=0x%x Replay=%u", 146 ntohl(aligned_ah->ah_spi), ntohl(aligned_ah->ah_replay)); 147 line += strlen(line); 148 } 149 150 if (flags & F_DTAIL) { 151 show_header("AH: ", "Authentication Header", ahlen); 152 show_space(); 153 (void) sprintf(get_line((char *)&ah->ah_nexthdr - dlc_header, 154 1), "Next header = %d (%s)", aligned_ah->ah_nexthdr, 155 getproto(aligned_ah->ah_nexthdr)); 156 (void) sprintf(get_line((char *)&ah->ah_length - dlc_header, 1), 157 "AH length = %d (%d bytes)", aligned_ah->ah_length, ahlen); 158 (void) sprintf(get_line((char *)&ah->ah_reserved - dlc_header, 159 2), "<Reserved field = 0x%x>", 160 ntohs(aligned_ah->ah_reserved)); 161 (void) sprintf(get_line((char *)&ah->ah_spi - dlc_header, 4), 162 "SPI = 0x%x", ntohl(aligned_ah->ah_spi)); 163 (void) sprintf(get_line((char *)&ah->ah_replay - dlc_header, 4), 164 "Replay = %u", ntohl(aligned_ah->ah_replay)); 165 166 /* * 2 for two hex digits per auth_data byte. */ 167 buff = malloc(auth_data_len * 2); 168 if (buff != NULL) { 169 int i; 170 171 for (i = 0; i < auth_data_len; i++) 172 sprintf(buff + i * 2, "%02x", auth_data[i]); 173 } 174 175 (void) sprintf(get_line((char *)auth_data - dlc_header, 176 auth_data_len), "ICV = %s", 177 (buff == NULL) ? "<out of memory>" : buff); 178 179 /* malloc(3c) says I can call free even if buff == NULL */ 180 free(buff); 181 182 show_space(); 183 } 184 185 new_iplen = iplen - ahlen; 186 proto = aligned_ah->ah_nexthdr; 187 188 /* 189 * Print IPv6 Extension Headers, or skip them in the summary case. 190 */ 191 if (proto == IPPROTO_HOPOPTS || proto == IPPROTO_DSTOPTS || 192 proto == IPPROTO_ROUTING || proto == IPPROTO_FRAGMENT) { 193 (void) print_ipv6_extensions(flags, &data, &proto, &iplen, 194 &fraglen); 195 } 196 197 if (fraglen > 0) 198 switch (proto) { 199 case IPPROTO_ENCAP: 200 (void) interpret_ip(flags, (struct ip *)data, 201 new_iplen); 202 break; 203 case IPPROTO_IPV6: 204 (void) interpret_ipv6(flags, (ip6_t *)data, 205 new_iplen); 206 break; 207 case IPPROTO_ICMP: 208 interpret_icmp(flags, (struct icmp *)data, 209 new_iplen, fraglen); 210 break; 211 case IPPROTO_ICMPV6: 212 interpret_icmpv6(flags, (icmp6_t *)data, 213 new_iplen, fraglen); 214 break; 215 case IPPROTO_TCP: 216 interpret_tcp(flags, data, new_iplen, fraglen); 217 break; 218 219 case IPPROTO_ESP: 220 interpret_esp(flags, data, new_iplen, fraglen); 221 break; 222 case IPPROTO_AH: 223 interpret_ah(flags, data, new_iplen, fraglen); 224 break; 225 226 227 case IPPROTO_UDP: 228 interpret_udp(flags, data, new_iplen, fraglen); 229 break; 230 /* default case is to not print anything else */ 231 } 232 233 return (ahlen); 234 } 235