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