xref: /netbsd-src/crypto/dist/ipsec-tools/src/racoon/dump.c (revision 81e0d2b0af8485d94ed5da487d4253841a2e6e45)
1 /*	$KAME: dump.c,v 1.3 2000/09/23 15:31:05 itojun Exp $	*/
2 
3 /*
4  * Copyright (C) 2000 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include "config.h"
33 
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/queue.h>
38 
39 #include <netinet/in.h>
40 #include <netinet/in_systm.h>
41 #include <netinet/ip.h>
42 #include <netinet/ip6.h>
43 #include <netinet/udp.h>
44 
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <errno.h>
49 #if TIME_WITH_SYS_TIME
50 # include <sys/time.h>
51 # include <time.h>
52 #else
53 # if HAVE_SYS_TIME_H
54 #  include <sys/time.h>
55 # else
56 #  include <time.h>
57 # endif
58 #endif
59 #include <netdb.h>
60 #ifdef HAVE_UNISTD_H
61 #include <unistd.h>
62 #endif
63 #include <pcap.h>
64 #include <fcntl.h>
65 
66 #include "vmbuf.h"
67 
68 /* copied from pcap-int.h */
69 struct pcap_timeval {
70 	u_int32_t tv_sec;	/* seconds */
71 	u_int32_t tv_usec;	/* microseconds */
72 };
73 
74 struct pcap_sf_pkthdr {
75 	struct pcap_timeval ts;	/* time stamp */
76 	u_int32_t caplen;	/* length of portion present */
77 	u_int32_t len;		/* length this packet (off wire) */
78 };
79 
80 #define TCPDUMP_MAGIC	0xa1b2c3d4
81 
82 static int fd = -1;
83 
84 int
85 isakmp_dump_open(path)
86 	char *path;
87 {
88 	struct pcap_file_header hdr;
89 
90 	path = "isakmp.dump";
91 
92 	if (fd >= 0)
93 		return EBUSY;
94 
95 	fd = open(path, O_WRONLY|O_CREAT|O_APPEND, 0600);
96 	if (fd < 0)
97 		return errno;
98 
99 	memset(&hdr, 0, sizeof(hdr));
100 	hdr.magic = TCPDUMP_MAGIC;
101 	hdr.version_major = PCAP_VERSION_MAJOR;
102 	hdr.version_minor = PCAP_VERSION_MINOR;
103 
104 	hdr.thiszone = 0;
105 	hdr.snaplen = 60000;	/* should be enough */
106 	hdr.sigfigs = 0;
107 	hdr.linktype = DLT_NULL;
108 
109 	if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
110 		return errno;
111 
112 	return 0;
113 }
114 
115 int
116 isakmp_dump_close()
117 {
118 	close(fd);
119 	fd = -1;
120 	return 0;
121 }
122 
123 int
124 isakmp_dump(msg, from, my)
125 	vchar_t *msg;
126 	struct sockaddr *from;
127 	struct sockaddr *my;
128 {
129 	struct ip ip;
130 #ifdef INET6
131 	struct ip6_hdr ip6;
132 #endif
133 	struct udphdr uh;
134 	int32_t af;	/*llhdr for DLT_NULL*/
135 	struct pcap_sf_pkthdr sf_hdr;
136 	struct timeval tv;
137 
138 	/* af validation */
139 	if (from && my) {
140 		if (from->sa_family == my->sa_family)
141 			af = from->sa_family;
142 		else
143 			return EAFNOSUPPORT;
144 	} else if (from)
145 		af = from->sa_family;
146 	else if (my)
147 		af = my->sa_family;
148 	else
149 		af = AF_INET;	/*assume it*/
150 	switch (af) {
151 	case AF_INET:
152 #ifdef INET6
153 	case AF_INET6:
154 #endif
155 		break;
156 	default:
157 		return EAFNOSUPPORT;
158 	}
159 
160 	memset(&sf_hdr, 0, sizeof(sf_hdr));
161 	gettimeofday(&tv, NULL);
162 	sf_hdr.ts.tv_sec = tv.tv_sec;
163 	sf_hdr.ts.tv_usec = tv.tv_usec;
164 
165 	/* write out timestamp and llhdr */
166 	switch (af == AF_INET) {
167 	case AF_INET:
168 		sf_hdr.caplen = sf_hdr.len = sizeof(ip);
169 		break;
170 	case AF_INET6:
171 		sf_hdr.caplen = sf_hdr.len = sizeof(ip6);
172 		break;
173 	}
174 	sf_hdr.caplen += sizeof(af) + sizeof(uh) + msg->l;
175 	sf_hdr.len += sizeof(af) + sizeof(uh) + msg->l;
176 	if (write(fd, &sf_hdr, sizeof(sf_hdr)) < sizeof(sf_hdr))
177 		return errno;
178 	if (write(fd, &af, sizeof(af)) < sizeof(af))
179 		return errno;
180 
181 	/* write out llhdr and ip header */
182 	if (af == AF_INET) {
183 		memset(&ip, 0, sizeof(ip));
184 		ip.ip_v = IPVERSION;
185 		ip.ip_hl = sizeof(ip) >> 2;
186 		if (from)
187 			ip.ip_src = ((struct sockaddr_in *)from)->sin_addr;
188 		if (my)
189 			ip.ip_dst = ((struct sockaddr_in *)my)->sin_addr;
190 		ip.ip_p = IPPROTO_UDP;
191 		ip.ip_ttl = 1;
192 		ip.ip_len = htons(sizeof(ip) + sizeof(uh) + msg->l);
193 		if (write(fd, &ip, sizeof(ip)) < sizeof(ip))
194 			return errno;
195 	} else if (af == AF_INET6) {
196 		memset(&ip6, 0, sizeof(ip6));
197 		ip6.ip6_vfc = IPV6_VERSION;
198 		if (from)
199 			ip6.ip6_src = ((struct sockaddr_in6 *)from)->sin6_addr;
200 		if (my)
201 			ip6.ip6_dst = ((struct sockaddr_in6 *)my)->sin6_addr;
202 		ip6.ip6_nxt = IPPROTO_UDP;
203 		ip6.ip6_plen = htons(sizeof(uh) + msg->l);
204 		ip6.ip6_hlim = 1;
205 		if (write(fd, &ip6, sizeof(ip6)) < sizeof(ip6))
206 			return errno;
207 	}
208 
209 	/* write out udp header */
210 	memset(&uh, 0, sizeof(uh));
211 	uh.uh_sport = htons(500);
212 	uh.uh_dport = htons(500);
213 	uh.uh_ulen = htons(msg->l & 0xffff);
214 	uh.uh_sum = htons(0x0000);	/*no checksum - invalid for IPv6*/
215 	if (write(fd, &uh, sizeof(uh)) < sizeof(uh))
216 		return errno;
217 
218 	/* write out payload */
219 	if (write(fd, msg->v, msg->l) != msg->l)
220 		return errno;
221 
222 	return 0;
223 }
224