summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHakan Olsson <ho@cvs.openbsd.org>2001-07-10 10:46:30 +0000
committerHakan Olsson <ho@cvs.openbsd.org>2001-07-10 10:46:30 +0000
commit144acf36aacb437ef957bcc997f76c84a13095ad (patch)
treea238f5193356eaefb77b47b73fe5c0942795ed23
parent46b16c0d26d9dd0dee09cfd96907ef2d7bd45a93 (diff)
Rewrite packet capture to handle IPv6 addresses.
-rw-r--r--sbin/isakmpd/log.c239
1 files changed, 148 insertions, 91 deletions
diff --git a/sbin/isakmpd/log.c b/sbin/isakmpd/log.c
index 7a3537c66d0..b4f7e875c02 100644
--- a/sbin/isakmpd/log.c
+++ b/sbin/isakmpd/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.19 2001/07/10 07:55:05 markus Exp $ */
+/* $OpenBSD: log.c,v 1.20 2001/07/10 10:46:29 ho Exp $ */
/* $EOM: log.c,v 1.30 2000/09/29 08:19:23 niklas Exp $ */
/*
@@ -45,6 +45,7 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
@@ -83,11 +84,11 @@ static int log_level[LOG_ENDCLASS];
struct packhdr {
struct pcap_pkthdr pcap; /* pcap file packet header */
- struct {
- u_int32_t null_family; /* NULL encapsulation */
- } null;
- struct ip ip; /* IP header (w/o options) */
- struct udphdr udp; /* UDP header */
+ u_int32_t sa_family; /* address family */
+ union {
+ struct ip ip4; /* IPv4 header (w/o options) */
+ struct ip6_hdr ip6; /* IPv6 header */
+ } ip;
};
struct isakmp_hdr {
@@ -98,11 +99,10 @@ struct isakmp_hdr {
static char *pcaplog_file = NULL;
static FILE *packet_log;
-static u_int8_t pack[SNAPLEN + sizeof (struct packhdr)];
-static struct packhdr *hdr;
+static u_int8_t *packet_buf = NULL;
-static int udp_cksum (const struct ip *, const struct udphdr *, int);
-static u_int16_t in_cksum (const struct ip *, int);
+static int udp_cksum (struct packhdr *, const struct udphdr *, u_int16_t *);
+static u_int16_t in_cksum (const u_int16_t *, int);
#endif /* USE_DEBUG */
void
@@ -364,6 +364,16 @@ log_packet_init (char *newname)
struct pcap_file_header sf_hdr;
mode_t old_umask;
+ /* Allocate packet buffer first time through. */
+ if (!packet_buf)
+ packet_buf = malloc (SNAPLEN);
+
+ if (!packet_buf)
+ {
+ log_error ("log_packet_init: malloc (%d) failed", SNAPLEN);
+ return;
+ }
+
if (pcaplog_file && strcmp (pcaplog_file, PCAP_FILE_DEFAULT) != 0)
free (pcaplog_file);
@@ -398,15 +408,6 @@ log_packet_init (char *newname)
fwrite ((char *)&sf_hdr, sizeof sf_hdr, 1, packet_log);
fflush (packet_log);
-
- /* prep dummy header prepended to each packet */
- hdr = (struct packhdr *)pack;
- hdr->null.null_family = htonl(AF_INET);
- hdr->ip.ip_v = 0x4;
- hdr->ip.ip_hl = 0x5;
- hdr->ip.ip_p = IPPROTO_UDP;
- hdr->udp.uh_sport = htons (500);
- hdr->udp.uh_dport = htons (500);
}
void
@@ -463,111 +464,170 @@ log_packet_iov (struct sockaddr *src, struct sockaddr *dst, struct iovec *iov,
int iovcnt)
{
struct isakmp_hdr *isakmphdr;
- int off, len, i;
-
- len = 0;
- for (i = 0; i < iovcnt; i++)
- len += iov[i].iov_len;
+ struct packhdr hdr;
+ struct udphdr udp;
+ int off, datalen, hdrlen, i;
+
+ for (i = 0, datalen = 0; i < iovcnt; i++)
+ datalen += iov[i].iov_len;
- if (!packet_log || len > SNAPLEN)
+ if (!packet_log || datalen > SNAPLEN)
return;
/* copy packet into buffer */
- off = sizeof *hdr;
- for (i = 0; i < iovcnt; i++)
+ for (i = 0, off = 0; i < iovcnt; i++)
{
- memcpy (pack + off, iov[i].iov_base, iov[i].iov_len);
+ memcpy (packet_buf + off, iov[i].iov_base, iov[i].iov_len);
off += iov[i].iov_len;
}
+
+ memset (&hdr, 0, sizeof hdr);
+ memset (&udp, 0, sizeof udp);
/* isakmp - turn off the encryption bit in the isakmp hdr */
- isakmphdr = (struct isakmp_hdr *)(pack + sizeof *hdr);
+ isakmphdr = (struct isakmp_hdr *)packet_buf;
isakmphdr->flags &= ~(ISAKMP_FLAGS_ENC);
/* udp */
- len += sizeof hdr->udp;
- hdr->udp.uh_ulen = htons (len);
+ udp.uh_sport = udp.uh_dport = htons (500);
+ datalen += sizeof udp;
+ udp.uh_ulen = htons (datalen);
/* ip */
- len += sizeof hdr->ip;
- hdr->ip.ip_len = htons (len);
-
+ hdr.sa_family = htonl (src->sa_family);
switch (src->sa_family)
{
+ default:
+ /* Assume IPv4. XXX Can 'default' ever happen here? */
+ hdr.sa_family = htonl (AF_INET);
+ hdr.ip.ip4.ip_src.s_addr = 0x02020202;
+ hdr.ip.ip4.ip_dst.s_addr = 0x01010101;
+ /* The rest of the setup is common to AF_INET. */
+ goto setup_ip4;
+
case AF_INET:
- hdr->ip.ip_src.s_addr = ((struct sockaddr_in *)src)->sin_addr.s_addr;
- hdr->ip.ip_dst.s_addr = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
+ hdr.ip.ip4.ip_src.s_addr = ((struct sockaddr_in *)src)->sin_addr.s_addr;
+ hdr.ip.ip4.ip_dst.s_addr = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
+
+ setup_ip4:
+ hdrlen = sizeof hdr.ip.ip4;
+ hdr.ip.ip4.ip_v = 0x4;
+ hdr.ip.ip4.ip_hl = 0x5;
+ hdr.ip.ip4.ip_p = IPPROTO_UDP;
+ hdr.ip.ip4.ip_len = htons (datalen + hdrlen);
+ /* Let's use the IP ID as a "packet counter". */
+ i = ntohs (hdr.ip.ip4.ip_id) + 1;
+ hdr.ip.ip4.ip_id = htons (i);
+ /* Calculate IP header checksum. */
+ hdr.ip.ip4.ip_sum = in_cksum ((u_int16_t *)&hdr.ip.ip4,
+ hdr.ip.ip4.ip_hl << 2);
break;
- case AF_INET6:
- /* XXX TBD */
- default:
- hdr->ip.ip_src.s_addr = 0x02020202;
- hdr->ip.ip_dst.s_addr = 0x01010101;
- }
- /* Let's use the IP ID as a "packet counter". */
- i = ntohs (hdr->ip.ip_id) + 1;
- hdr->ip.ip_id = htons (i);
+ case AF_INET6:
+ hdrlen = sizeof (hdr.ip.ip6);
+ hdr.ip.ip6.ip6_vfc = IPV6_VERSION;
+ hdr.ip.ip6.ip6_nxt = IPPROTO_UDP;
+ hdr.ip.ip6.ip6_plen = udp.uh_ulen;
+ memcpy (&hdr.ip.ip6.ip6_src, &((struct sockaddr_in6 *)src)->sin6_addr,
+ sizeof hdr.ip.ip6.ip6_src);
+ memcpy (&hdr.ip.ip6.ip6_dst, &((struct sockaddr_in6 *)dst)->sin6_addr,
+ sizeof hdr.ip.ip6.ip6_dst);
+ break;
+ }
/* Calculate UDP checksum. */
- hdr->udp.uh_sum = 0;
- hdr->udp.uh_sum = udp_cksum (&hdr->ip, &hdr->udp, len);
-
- /* Calculate IP header checksum. */
- hdr->ip.ip_sum = 0;
- hdr->ip.ip_sum = in_cksum (&hdr->ip, hdr->ip.ip_hl << 2);
+ udp.uh_sum = udp_cksum (&hdr, &udp, (u_int16_t *)packet_buf);
+ hdrlen += sizeof hdr.sa_family;
- /* null header */
- len += sizeof hdr->null;
-
/* pcap file packet header */
- gettimeofday (&hdr->pcap.ts, 0);
- hdr->pcap.caplen = len;
- hdr->pcap.len = len;
- len += sizeof hdr->pcap;
-
- fwrite (pack, len, 1, packet_log);
+ gettimeofday (&hdr.pcap.ts, 0);
+ hdr.pcap.caplen = datalen + hdrlen;
+ hdr.pcap.len = datalen + hdrlen;
+
+ hdrlen += sizeof (struct pcap_pkthdr);
+ datalen -= sizeof (struct udphdr);
+
+ /* Write to pcap file. */
+ fwrite (&hdr, hdrlen, 1, packet_log); /* pcap + IP */
+ fwrite (&udp, sizeof (struct udphdr), 1, packet_log); /* UDP */
+ fwrite (packet_buf, datalen, 1, packet_log); /* IKE-data */
fflush (packet_log);
return;
}
-/* Copied from tcpdump/print-udp.c */
+/* Copied from tcpdump/print-udp.c, mostly rewritten. */
static int
-udp_cksum (const struct ip *ip, const struct udphdr *up, int len)
+udp_cksum (struct packhdr *hdr, const struct udphdr *u, u_int16_t *d)
{
- int i, tlen;
+ int i, hdrlen, tlen = ntohs (u->uh_ulen) - sizeof (struct udphdr);
+ struct ip *ip4;
+ struct ip6_hdr *ip6;
+
union phu {
- struct phdr {
- u_int32_t src;
- u_int32_t dst;
- u_char mbz;
- u_char proto;
+ struct ip4pseudo {
+ struct in_addr src;
+ struct in_addr dst;
+ u_int8_t z;
+ u_int8_t proto;
u_int16_t len;
- } ph;
- u_int16_t pa[6];
+ } ip4p;
+ struct ip6pseudo {
+ struct in6_addr src;
+ struct in6_addr dst;
+ u_int32_t plen;
+ u_int16_t z0;
+ u_int8_t z1;
+ u_int8_t nxt;
+ } ip6p;
+ u_int16_t pa[20];
} phu;
const u_int16_t *sp;
u_int32_t sum;
- tlen = ntohs (ip->ip_len) - ((const char *)up-(const char*)ip);
-
- /* pseudo-header.. */
- phu.ph.len = htons (tlen);
- phu.ph.mbz = 0;
- phu.ph.proto = ip->ip_p;
- memcpy (&phu.ph.src, &ip->ip_src.s_addr, sizeof (u_int32_t));
- memcpy (&phu.ph.dst, &ip->ip_dst.s_addr, sizeof (u_int32_t));
-
- sp = &phu.pa[0];
- sum = sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5];
-
- sp = (const u_int16_t *)up;
+
+ /* Setup pseudoheader. */
+ memset (phu.pa, 0, sizeof phu);
+ switch (ntohl (hdr->sa_family))
+ {
+ case AF_INET:
+ ip4 = &hdr->ip.ip4;
+ memcpy (&phu.ip4p.src, &ip4->ip_src, sizeof (struct in_addr));
+ memcpy (&phu.ip4p.dst, &ip4->ip_dst, sizeof (struct in_addr));
+ phu.ip4p.proto = ip4->ip_p;
+ phu.ip4p.len = u->uh_ulen;
+ hdrlen = sizeof phu.ip4p;
+ break;
+
+ case AF_INET6:
+ ip6 = &hdr->ip.ip6;
+ memcpy (&phu.ip6p.src, &ip6->ip6_src, sizeof (phu.ip6p.src));
+ memcpy (&phu.ip6p.dst, &ip6->ip6_dst, sizeof (phu.ip6p.dst));
+ phu.ip6p.plen = u->uh_ulen;
+ phu.ip6p.nxt = ip6->ip6_nxt;
+ hdrlen = sizeof phu.ip6p;
+ break;
+
+ default:
+ return 0;
+ }
+
+ /* IPv6 wants a 0xFFFF checksum "on error", not 0x0. */
+ if (tlen < 0)
+ return (ntohl (hdr->sa_family) == AF_INET ? 0 : 0xFFFF);
+
+ sum = 0;
+ for (i = 0; i < hdrlen; i += 2)
+ sum += phu.pa[i/2];
+
+ sp = (u_int16_t *)u;
+ for (i = 0; i < sizeof (struct udphdr); i += 2)
+ sum += *sp++;
+ sp = d;
for (i = 0; i < (tlen&~1); i += 2)
sum += *sp++;
- if (tlen & 1) {
+ if (tlen & 1)
sum += htons ((*(const char *)sp) << 8);
- }
while (sum > 0xffff)
sum = (sum & 0xffff) + (sum >> 16);
@@ -578,12 +638,10 @@ udp_cksum (const struct ip *ip, const struct udphdr *up, int len)
/* Copied from tcpdump/print-ip.c, modified. */
static u_int16_t
-in_cksum (const struct ip *ip, int len)
+in_cksum (const u_int16_t *w, int len)
{
- int nleft = len;
- const u_short *w = (const u_short *)ip;
- u_short answer;
- int sum = 0;
+ int nleft = len, sum = 0;
+ u_int16_t answer;
while (nleft > 1) {
sum += *w++;
@@ -598,5 +656,4 @@ in_cksum (const struct ip *ip, int len)
return answer;
}
-
#endif /* USE_DEBUG */