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
interpret_esp(int flags,uint8_t * hdr,int iplen,int fraglen)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
interpret_ah(int flags,uint8_t * hdr,int iplen,int fraglen)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 }
244