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