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