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