summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/ip_ah.c9
-rw-r--r--sys/netinet/ip_ah_new.c7
-rw-r--r--sys/netinet/ip_ah_old.c7
-rw-r--r--sys/netinet/ip_esp.c19
-rw-r--r--sys/netinet/ip_esp_new.c516
-rw-r--r--sys/netinet/ip_esp_old.c7
-rw-r--r--sys/netinet/ip_ether.c5
-rw-r--r--sys/netinet/ip_ip4.c151
-rw-r--r--sys/netinet/ip_ipsp.c4
-rw-r--r--sys/netinet/ip_ipsp.h31
-rw-r--r--sys/netinet/ip_output.c38
11 files changed, 457 insertions, 337 deletions
diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c
index 2b87e7cae55..1735573970c 100644
--- a/sys/netinet/ip_ah.c
+++ b/sys/netinet/ip_ah.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah.c,v 1.26 1999/11/04 11:23:43 ho Exp $ */
+/* $OpenBSD: ip_ah.c,v 1.27 1999/12/06 07:14:35 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -84,6 +84,10 @@ extern struct enc_softc encif[];
#define DPRINTF(x)
#endif
+#ifndef offsetof
+#define offsetof(s, e) ((int)&((s *)0)->e)
+#endif
+
int ah_enable = 0;
/*
@@ -190,7 +194,8 @@ ah_input(m, va_alist)
ipn = *ipo;
ahn = *ahp;
- m = (*(tdbp->tdb_xform->xf_input))(m, tdbp);
+ m = (*(tdbp->tdb_xform->xf_input))(m, tdbp, ipo->ip_hl << 2,
+ offsetof(struct ip, ip_p));
if (m == NULL)
{
DPRINTF(("ah_input(): authentication failed for AH packet from %s to %s, spi %08x\n", inet_ntoa4(ipn.ip_src), ipsp_address(sunion), ntohl(ahn.ah_spi)));
diff --git a/sys/netinet/ip_ah_new.c b/sys/netinet/ip_ah_new.c
index 73b91396791..639dc7dbff4 100644
--- a/sys/netinet/ip_ah_new.c
+++ b/sys/netinet/ip_ah_new.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah_new.c,v 1.28 1999/10/29 02:10:01 angelos Exp $ */
+/* $OpenBSD: ip_ah_new.c,v 1.29 1999/12/06 07:14:35 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -191,7 +191,7 @@ ah_new_zeroize(struct tdb *tdbp)
*/
struct mbuf *
-ah_new_input(struct mbuf *m, struct tdb *tdb)
+ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
{
struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
struct ip *ip, ipo;
@@ -432,7 +432,8 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
}
int
-ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
+ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
+ int protoff)
{
struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
struct ip *ip, ipo;
diff --git a/sys/netinet/ip_ah_old.c b/sys/netinet/ip_ah_old.c
index c669107f47a..8e2a6f62458 100644
--- a/sys/netinet/ip_ah_old.c
+++ b/sys/netinet/ip_ah_old.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah_old.c,v 1.25 1999/10/29 02:10:01 angelos Exp $ */
+/* $OpenBSD: ip_ah_old.c,v 1.26 1999/12/06 07:14:35 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -173,7 +173,7 @@ ah_old_zeroize(struct tdb *tdbp)
*/
struct mbuf *
-ah_old_input(struct mbuf *m, struct tdb *tdb)
+ah_old_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
{
struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
struct ip *ip, ipo;
@@ -375,7 +375,8 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
}
int
-ah_old_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
+ah_old_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
+ int protoff)
{
struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
struct ip *ip, ipo;
diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c
index 10c16389760..ab3eae18fea 100644
--- a/sys/netinet/ip_esp.c
+++ b/sys/netinet/ip_esp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.c,v 1.26 1999/11/04 11:23:43 ho Exp $ */
+/* $OpenBSD: ip_esp.c,v 1.27 1999/12/06 07:14:35 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -84,6 +84,10 @@ extern struct enc_softc encif[];
#define DPRINTF(x)
#endif
+#ifndef offsetof
+#define offsetof(s, e) ((int)&((s *)0)->e)
+#endif
+
int esp_enable = 0;
/*
@@ -188,7 +192,8 @@ esp_input(m, va_alist)
ipn = *ipo;
- m = (*(tdbp->tdb_xform->xf_input))(m, tdbp);
+ m = (*(tdbp->tdb_xform->xf_input))(m, tdbp, ipo->ip_hl << 2,
+ offsetof(struct ip, ip_p));
if (m == NULL)
{
@@ -197,7 +202,17 @@ esp_input(m, va_alist)
return;
}
+ if ((m = m_pullup(m, ipn.ip_hl << 2)) == 0)
+ {
+ espstat.esps_hdrops++;
+ return;
+ }
+
ipo = mtod(m, struct ip *);
+ ipo->ip_len = htons(m->m_pkthdr.len);
+ ipo->ip_sum = 0;
+ ipo->ip_sum = in_cksum(m, ipo->ip_hl << 2);
+
if (ipo->ip_p == IPPROTO_IPIP) /* IP-in-IP encapsulation */
{
/* ipn will now contain the inner IP header */
diff --git a/sys/netinet/ip_esp_new.c b/sys/netinet/ip_esp_new.c
index 0c5c4e5d8ad..a8b46c0bda4 100644
--- a/sys/netinet/ip_esp_new.c
+++ b/sys/netinet/ip_esp_new.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp_new.c,v 1.48 1999/12/04 23:20:21 angelos Exp $ */
+/* $OpenBSD: ip_esp_new.c,v 1.49 1999/12/06 07:14:35 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -65,6 +65,13 @@
#include <sys/socketvar.h>
#include <net/raw_cb.h>
+#ifdef INET6
+#include <netinet6/ip6.h>
+#include <netinet6/in6_pcb.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/icmp6.h>
+#endif /* INET6 */
+
#include <netinet/ip_icmp.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_esp.h>
@@ -76,6 +83,10 @@
#define DPRINTF(x)
#endif
+#ifndef offsetof
+#define offsetof(s, e) ((int)&((s *)0)->e)
+#endif
+
extern struct auth_hash auth_hash_hmac_md5_96;
extern struct auth_hash auth_hash_hmac_sha1_96;
extern struct auth_hash auth_hash_hmac_ripemd_160_96;
@@ -222,7 +233,7 @@ esp_new_zeroize(struct tdb *tdbp)
{
if (tdbp->tdb_key && tdbp->tdb_encalgxform &&
tdbp->tdb_encalgxform->zerokey)
- tdbp->tdb_encalgxform->zerokey(&tdbp->tdb_key);
+ tdbp->tdb_encalgxform->zerokey(&tdbp->tdb_key);
if (tdbp->tdb_ictx)
{
@@ -243,27 +254,21 @@ esp_new_zeroize(struct tdb *tdbp)
return 0;
}
+#define MAXBUFSIZ (AH_ALEN_MAX > ESP_MAX_IVS ? AH_ALEN_MAX : ESP_MAX_IVS)
struct mbuf *
-esp_new_input(struct mbuf *m, struct tdb *tdb)
+esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
{
- struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
- u_char iv[ESP_MAX_IVS], niv[ESP_MAX_IVS];
- u_char blk[ESP_MAX_BLKS], *lblk, opts[40];
- int ohlen, oplen, plen, alen, ilen, i, blks, rest;
- int count, off, errc;
- struct mbuf *mi, *mo;
+ struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
+ int ohlen, oplen, plen, alen, ilen, i, blks, rest, count, off, roff;
+ u_char iv[MAXBUFSIZ], niv[MAXBUFSIZ], blk[ESP_MAX_BLKS], *lblk;
u_char *idat, *odat, *ivp, *ivn;
- struct esp_new *esp;
- struct ip *ip, ipo;
- u_int32_t btsx;
+ struct mbuf *mi, *mo, *m1;
union authctx ctx;
- u_char buf[AH_ALEN_MAX], buf2[AH_ALEN_MAX];
-#if INET6
- struct ipv6 *ipv6, ipv6o;
-#endif /* INET6 */
+ u_int32_t btsx;
+ ohlen = skip + ESP_NEW_FLENGTH;
blks = espx->blocksize;
if (esph)
@@ -271,35 +276,56 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
else
alen = 0;
- if (m->m_len < sizeof(struct ip))
+ /* Skip the IP header, IP options, SPI, Replay, IV, and any Auth Data */
+ plen = m->m_pkthdr.len - (skip + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen +
+ alen);
+ if ((plen & (blks - 1)) || (plen <= 0))
{
- if ((m = m_pullup(m, sizeof(struct ip))) == NULL)
- {
- DPRINTF(("esp_new_input(): (possibly too short) packet dropped\n"));
- espstat.esps_hdrops++;
- return NULL;
- }
+ DPRINTF(("esp_new_input(): payload not a multiple of %d octets, SA %s/%08x\n", blks, ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_badilen++;
+ m_freem(m);
+ return NULL;
}
- ip = mtod(m, struct ip *);
- ohlen = (ip->ip_hl << 2) + ESP_NEW_FLENGTH;
+ /* Auth covers SPI + SN + IV */
+ oplen = plen + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
- /* Make sure the IP header, any IP options, and the ESP header are here */
- if (m->m_len < ohlen + blks)
+ /* Replay window checking */
+ if (tdb->tdb_wnd > 0)
{
- if ((m = m_pullup(m, ohlen + blks)) == NULL)
+ m_copydata(m, skip + offsetof(struct esp_new, esp_rpl),
+ sizeof(u_int32_t), (unsigned char *) &btsx);
+ btsx = ntohl(btsx);
+
+ switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl), tdb->tdb_wnd,
+ &(tdb->tdb_bitmap)))
{
- DPRINTF(("esp_new_input(): m_pullup() failed\n"));
- espstat.esps_hdrops++;
- return NULL;
- }
+ case 0: /* All's well */
+ break;
+
+ case 1:
+ DPRINTF(("esp_new_input(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_wrap++;
+ m_freem(m);
+ return NULL;
- ip = mtod(m, struct ip *);
+ case 2:
+ case 3:
+ DPRINTF(("esp_new_input(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_replay++;
+ m_freem(m);
+ return NULL;
+
+ default:
+ DPRINTF(("esp_new_input(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ m_freem(m);
+ return NULL;
+ }
}
/* Update the counters */
- tdb->tdb_cur_bytes += ip->ip_len - ohlen - alen;
- espstat.esps_ibytes += ip->ip_len - ohlen - alen;
+ tdb->tdb_cur_bytes += m->m_pkthdr.len - ohlen - alen;
+ espstat.esps_ibytes += m->m_pkthdr.len - ohlen - alen;
/* Hard expiration */
if ((tdb->tdb_flags & TDBF_BYTES) &&
@@ -319,65 +345,34 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
}
- esp = (struct esp_new *) ((u_int8_t *) ip + (ip->ip_hl << 2));
- ipo = *ip;
-
- /* Replay window checking */
- if (tdb->tdb_wnd > 0)
- {
- btsx = ntohl(esp->esp_rpl);
- if ((errc = checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl), tdb->tdb_wnd,
- &(tdb->tdb_bitmap))) != 0)
- {
- switch(errc)
- {
- case 1:
- DPRINTF(("esp_new_input(): replay counter wrapped for packets from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi)));
- espstat.esps_wrap++;
- break;
-
- case 2:
- case 3:
- DPRINTF(("esp_new_input(): duplicate packet received from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi)));
- espstat.esps_replay++;
- break;
- }
-
- m_freem(m);
- return NULL;
- }
- }
-
- /* Skip the IP header, IP options, SPI, SN and IV and minus Auth Data */
- plen = m->m_pkthdr.len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) -
- tdb->tdb_ivlen - alen;
-
- if ((plen & (blks - 1)) || (plen <= 0))
- {
- DPRINTF(("esp_new_input(): payload not a multiple of %d octets for packet from %s to %s, spi %08x\n", blks, inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_badilen++;
- m_freem(m);
- return NULL;
- }
-
+ /* Verify the authenticator */
if (esph)
{
bcopy(tdb->tdb_ictx, &ctx, esph->ctxsize);
- /* Auth covers SPI + SN + IV */
- oplen = plen + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
- off = (ip->ip_hl << 2);
-
/* Copy the authentication data */
- m_copydata(m, m->m_pkthdr.len - alen, alen, buf);
+ m_copydata(m, m->m_pkthdr.len - alen, alen, iv);
+
+ /*
+ * Skip forward to the begining of the ESP header. If we run out
+ * of mbufs in the process, the check inside the following while()
+ * loop will catch it.
+ */
+ for (mo = m, i = 0; mo && i + mo->m_len <= skip; mo = mo->m_next)
+ i += mo->m_len;
- mo = m;
+ off = skip - i;
+
+ /* Preserve these for later processing */
+ roff = off;
+ m1 = mo;
while (oplen > 0)
{
if (mo == 0)
{
- DPRINTF(("esp_new_input(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi)));
+ DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
m_freem(m);
return NULL;
@@ -390,14 +385,14 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
mo = mo->m_next;
}
- esph->Final(buf2, &ctx);
+ esph->Final(niv, &ctx);
bcopy(tdb->tdb_octx, &ctx, esph->ctxsize);
- esph->Update(&ctx, buf2, esph->hashsize);
- esph->Final(buf2, &ctx);
+ esph->Update(&ctx, niv, esph->hashsize);
+ esph->Final(niv, &ctx);
- if (bcmp(buf2, buf, AH_HMAC_HASHLEN))
+ if (bcmp(niv, iv, AH_HMAC_HASHLEN))
{
- DPRINTF(("esp_new_input(): authentication failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi)));
+ DPRINTF(("esp_new_input(): authentication failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_badauth++;
m_freem(m);
return NULL;
@@ -405,14 +400,97 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
}
oplen = plen;
- ilen = m->m_len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t);
- idat = mtod(m, unsigned char *) + (ip->ip_hl << 2) + 2 * sizeof(u_int32_t);
- bcopy(idat, iv, tdb->tdb_ivlen);
+ /* Find beginning of encrypted data (actually, the IV) */
+ mi = m1;
+ ilen = mi->m_len - roff - 2 * sizeof(u_int32_t);
+ while (ilen <= 0)
+ {
+ mi = mi->m_next;
+ if (mi == NULL)
+ {
+ DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_hdrops++;
+ m_freem(m);
+ return NULL;
+ }
+
+ ilen += mi->m_len;
+ }
+
+ idat = mtod(mi, unsigned char *) + (mi->m_len - ilen);
+ m_copydata(mi, mi->m_len - ilen, tdb->tdb_ivlen, iv);
+
+ /* Now skip over the IV */
ilen -= tdb->tdb_ivlen;
- idat += tdb->tdb_ivlen;
+ while (ilen <= 0)
+ {
+ mi = mi->m_next;
+ if (mi == NULL)
+ {
+ DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_hdrops++;
+ m_freem(m);
+ return NULL;
+ }
- mi = m;
+ ilen += mi->m_len;
+ }
+
+ /*
+ * Remove the ESP header and IV from the mbuf.
+ */
+ if (roff == 0)
+ {
+ /* The ESP header was conveniently at the begining of the mbuf */
+ m_adj(m1, 2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
+ if (!(m1->m_flags & M_PKTHDR))
+ m->m_pkthdr.len -= (2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
+ }
+ else
+ if (roff + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen > m1->m_len)
+ {
+ /*
+ * Part of the ESP header is at the end of this mbuf, so first
+ * let's remove the remainder of the ESP header from the
+ * begining of the remainder of the mbuf chain.
+ */
+ m_adj(m1->m_next, roff + 2 * sizeof(u_int32_t) +
+ tdb->tdb_ivlen - m1->m_len);
+ m->m_pkthdr.len -= roff + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen -
+ m1->m_len;
+
+ /* Now, let's unlink the mbuf chain for a second...*/
+ mo = m1->m_next;
+ m1->m_next = NULL;
+
+ /* ...and trim the end of the first part of the chain...sick */
+ m_adj(m1, -(m1->m_len - roff));
+ if (!(m1->m_flags & M_PKTHDR))
+ m->m_pkthdr.len -= (m1->m_len - roff);
+
+ /* Finally, let's relink */
+ m1->m_next = mo;
+ }
+ else
+ {
+ /*
+ * The ESP header lies in the "middle" of the mbuf...do an
+ * overlapping copy of the remainder of the mbuf over the ESP
+ * header.
+ */
+ bcopy(mtod(m1, u_char *) + roff + 2 * sizeof(u_int32_t) +
+ tdb->tdb_ivlen,
+ mtod(m1, u_char *) + roff,
+ m1->m_len - (roff + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen));
+ m1->m_len -= (2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
+ m->m_pkthdr.len -= (2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
+ }
+
+ /* Point to the encrypted data */
+ idat = mtod(mi, unsigned char *) + (mi->m_len - ilen);
/*
* At this point:
@@ -447,7 +525,8 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
mi = (mo = mi)->m_next;
if (mi == NULL)
{
- DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
m_freem(m);
return NULL;
@@ -519,10 +598,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
}
}
- /* Save the options */
- m_copydata(m, sizeof(struct ip), (ipo.ip_hl << 2) - sizeof(struct ip),
- (caddr_t) opts);
-
+ /* Save last block (end of padding), if it was in-place decrypted */
if (lblk != blk)
bcopy(lblk, blk, blks);
@@ -534,9 +610,10 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
* Verify correct decryption by checking the last padding bytes.
*/
- if (blk[blks - 2] + 2 + alen > m->m_pkthdr.len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) - tdb->tdb_ivlen)
+ if (blk[blks - 2] + 2 + alen > m->m_pkthdr.len - skip -
+ 2 * sizeof(u_int32_t) - tdb->tdb_ivlen)
{
- DPRINTF(("esp_new_input(): invalid padding length %d for packet from %s to %s, spi %08x\n", blk[blks - 2], inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_new_input(): invalid padding length %d for packet in SA %s/%08x\n", blk[blks - 2], ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_badilen++;
m_freem(m);
return NULL;
@@ -544,60 +621,39 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
if ((blk[blks - 2] != blk[blks - 3]) && (blk[blks - 2] != 0))
{
- DPRINTF(("esp_new_input(): decryption failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_new_input(): decryption failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_badenc++;
m_freem(m);
return NULL;
}
- m_adj(m, - blk[blks - 2] - 2 - alen); /* Old type padding */
- m_adj(m, 2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
-
- if (m->m_len < (ipo.ip_hl << 2))
- {
- m = m_pullup(m, (ipo.ip_hl << 2));
- if (m == NULL)
- {
- DPRINTF(("esp_new_input(): m_pullup() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- return NULL;
- }
- }
-
- ip = mtod(m, struct ip *);
- ipo.ip_p = blk[blks - 1];
- ipo.ip_id = htons(ipo.ip_id);
- ipo.ip_off = 0;
- ipo.ip_len += (ipo.ip_hl << 2) - 2 * sizeof(u_int32_t) - tdb->tdb_ivlen -
- blk[blks - 2] - 2 - alen;
-
- ipo.ip_len = htons(ipo.ip_len);
- ipo.ip_sum = 0;
- *ip = ipo;
-
- /* Copy the options back */
- m_copyback(m, sizeof(struct ip), (ipo.ip_hl << 2) - sizeof(struct ip),
- (caddr_t) opts);
+ /* Trim the mbuf chain to remove the trailing authenticator */
+ m_adj(m, - blk[blks - 2] - 2 - alen);
- ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));
+ /* Restore the Next Protocol field */
+ m_copyback(m, protoff, 1, &blk[blks - 1]);
return m;
}
int
-esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
+esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
+ int protoff)
{
struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
- struct ip *ip, ipo;
- int i, ilen, ohlen, nh, rlen, plen, padding, rest;
- struct esp_new espo;
+ u_char iv[ESP_MAX_IVS], blk[ESP_MAX_BLKS], auth[AH_ALEN_MAX];
+ int i, ilen, ohlen, rlen, plen, padding, rest, blks, alen;
struct mbuf *mi, *mo = (struct mbuf *) NULL;
u_char *pad, *idat, *odat, *ivp;
- u_char iv[ESP_MAX_IVS], blk[ESP_MAX_BLKS], auth[AH_ALEN_MAX], opts[40];
+ struct esp_new *esp;
union authctx ctx;
- int iphlen, blks, alen;
-
+
blks = espx->blocksize;
+ ohlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
+ rlen = m->m_pkthdr.len - skip; /* Raw payload length */
+ padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
+ plen = rlen + padding; /* Padded payload length */
if (esph)
alen = AH_HMAC_HASHLEN;
@@ -614,7 +670,7 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
while (mi != NULL &&
(!(mi->m_flags & M_EXT) ||
(mi->m_ext.ext_ref == NULL &&
- mclrefcnt[mtocl(mi->m_ext.ext_buf)] <= 1)))
+ mclrefcnt[mtocl(mi->m_ext.ext_buf)] <= 1)))
{
mo = mi;
mi = mi->m_next;
@@ -640,16 +696,8 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
m_freem(mi);
}
- m = m_pullup(m, sizeof (struct ip)); /* Get IP header in one mbuf */
- if (m == NULL)
- {
- DPRINTF(("esp_new_output(): m_pullup() failed, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- return ENOBUFS;
- }
-
- if (tdb->tdb_rpl == 0)
+ /* Check for replay counter wrap-around in automatic (not manual) keying */
+ if ((tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0))
{
DPRINTF(("esp_new_output(): SA %s/%0x8 should have expired\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
@@ -658,17 +706,24 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
return ENOBUFS;
}
- espo.esp_spi = tdb->tdb_spi;
- espo.esp_rpl = htonl(tdb->tdb_rpl++);
+#ifdef INET
+ /* In IPv4, check for max packet size violations. Not needed in IPv6. */
+ if (tdb->tdb_dst.sa.sa_family == AF_INET)
+ if (skip + ohlen + rlen + padding + alen > IP_MAXPACKET)
+ {
+ DPRINTF(("esp_new_output(): packet in SA %s/%0x8 got too big\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ m_freem(m);
+ espstat.esps_toobig++;
+ return EMSGSIZE;
+ }
+#endif /* INET */
- ip = mtod(m, struct ip *);
- iphlen = (ip->ip_hl << 2);
-
/* Update the counters */
- tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
- espstat.esps_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
+ tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
+ espstat.esps_obytes += m->m_pkthdr.len - skip;
- /* Hard expiration */
+ /* Hard byte expiration */
if ((tdb->tdb_flags & TDBF_BYTES) &&
(tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
{
@@ -678,7 +733,7 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
return EINVAL;
}
- /* Notify on expiration */
+ /* Soft byte expiration */
if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
(tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
{
@@ -686,45 +741,30 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
}
- /*
- * If options are present, pullup the IP header, the options.
- */
- if (iphlen != sizeof(struct ip))
+ /* Inject ESP header */
+ mo = m_inject(m, skip, ohlen, M_WAITOK);
+ if (mo == NULL)
{
- m = m_pullup(m, iphlen + 8);
- if (m == NULL)
- {
- DPRINTF(("esp_new_input(): m_pullup() failed for SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- return ENOBUFS;
- }
-
- ip = mtod(m, struct ip *);
-
- /* Keep the options */
- m_copydata(m, sizeof(struct ip), iphlen - sizeof(struct ip),
- (caddr_t) opts);
+ DPRINTF(("esp_new_output(): failed to inject ESP header for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ m_freem(m);
+ espstat.esps_wrap++;
+ return ENOBUFS;
}
- ilen = ntohs(ip->ip_len); /* Size of the packet */
- ohlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
-
- ipo = *ip;
- nh = ipo.ip_p;
+ /* Initialize ESP header */
+ esp = mtod(mo, struct esp_new *);
+ esp->esp_spi = tdb->tdb_spi;
+ esp->esp_rpl = htonl(tdb->tdb_rpl++);
- /* Raw payload length */
- rlen = ilen - iphlen;
- padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
- if (iphlen + ohlen + rlen + padding + alen > IP_MAXPACKET)
- {
- DPRINTF(("esp_new_output(): packet in SA %s/%0x8 got too big\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- espstat.esps_toobig++;
- return EMSGSIZE;
- }
+ /*
+ * We can cheat and use bcopy() instead of m_copyback() for the
+ * second copy below, because m_inject() is guaranteed to fit the
+ * ESP header in one mbuf.
+ */
+ bcopy(tdb->tdb_iv, iv, tdb->tdb_ivlen);
+ bcopy(iv, esp->esp_iv, tdb->tdb_ivlen);
+ /* Add padding */
pad = (u_char *) m_pad(m, padding + alen, 0);
if (pad == NULL)
{
@@ -733,31 +773,42 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
return ENOBUFS;
}
- /* Self describing padding */
- for (i = 0; i < padding - 2; i++)
- pad[i] = i + 1;
+ /* Self-describing padding */
+ for (ilen = 0; ilen < padding - 2; ilen++)
+ pad[ilen] = ilen + 1;
+ /* Fix padding length and Next Protocol in padding itself */
pad[padding - 2] = padding - 2;
- pad[padding - 1] = nh;
+ m_copydata(m, protoff, 1, &pad[padding - 1]);
- mi = m;
- plen = rlen + padding;
- ilen = m->m_len - iphlen;
- idat = mtod(m, u_char *) + iphlen;
+ /* Fix Next Protocol in IPv4/IPv6 header */
+ ilen = IPPROTO_ESP;
+ m_copyback(m, protoff, 1, (u_char *) &ilen);
- bcopy(tdb->tdb_iv, iv, tdb->tdb_ivlen);
- bcopy(tdb->tdb_iv, espo.esp_iv, tdb->tdb_ivlen);
+ mi = mo;
+
+ /* If it's just the ESP header, just skip to the next mbuf */
+ if (mi->m_len == ohlen)
+ {
+ mi = mi->m_next;
+ ilen = mi->m_len;
+ idat = mtod(mi, u_char *);
+ }
+ else
+ { /* There's data at the end of this mbuf, skip over ESP header */
+ ilen = mi->m_len - ohlen;
+ idat = mtod(mi, u_char *) + ohlen;
+ }
- /* Authenticate the esp header */
+ /* Authenticate the ESP header */
if (esph)
{
bcopy(tdb->tdb_ictx, &ctx, esph->ctxsize);
- esph->Update(&ctx, (unsigned char *) &espo,
- 2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
+ esph->Update(&ctx, (unsigned char *) esp,
+ 2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
}
/* Encrypt the payload */
-
ivp = iv;
rest = ilen % blks;
while (plen > 0) /* while not done */
@@ -768,8 +819,8 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
{
if (ivp == blk)
{
- bcopy(blk, iv, blks);
- ivp = iv;
+ bcopy(blk, iv, blks);
+ ivp = iv;
}
bcopy(idat, blk, rest);
@@ -812,12 +863,12 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
bcopy(idat, blk + rest, blks - rest);
for (i = 0; i < blks; i++)
- blk[i] ^= ivp[i];
+ blk[i] ^= ivp[i];
espx->encrypt(tdb, blk);
if (esph)
- esph->Update(&ctx, blk, blks);
+ esph->Update(&ctx, blk, blks);
ivp = blk;
@@ -835,12 +886,12 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
while (ilen >= blks && plen > 0)
{
for (i = 0; i < blks; i++)
- idat[i] ^= ivp[i];
+ idat[i] ^= ivp[i];
espx->encrypt(tdb, idat);
if (esph)
- esph->Update(&ctx, idat, blks);
+ esph->Update(&ctx, idat, blks);
ivp = idat;
idat += blks;
@@ -858,54 +909,17 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
esph->Update(&ctx, auth, esph->hashsize);
esph->Final(auth, &ctx);
- /* Copy the final authenticator */
+ /* Copy the final authenticator -- cheat and use bcopy() again */
bcopy(auth, pad + padding, alen);
}
-
- /*
- * Done with encryption. Let's wedge in the ESP header
- * and send it out.
- */
-
- M_PREPEND(m, ohlen, M_DONTWAIT);
- if (m == NULL)
- {
- DPRINTF(("esp_new_output(): M_PREPEND failed, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- return ENOBUFS;
- }
-
- m = m_pullup(m, iphlen + ohlen);
- if (m == NULL)
- {
- DPRINTF(("esp_new_output(): m_pullup() failed, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- return ENOBUFS;
- }
-
- /* Fix the length and the next protocol, copy back and off we go */
- ipo.ip_len = htons(iphlen + ohlen + rlen + padding + alen);
- ipo.ip_p = IPPROTO_ESP;
-
+
/* Save the last encrypted block, to be used as the next IV */
bcopy(ivp, tdb->tdb_iv, tdb->tdb_ivlen);
- m_copyback(m, 0, sizeof(struct ip), (caddr_t) &ipo);
-
- /* Copy options, if existing */
- if (iphlen != sizeof(struct ip))
- m_copyback(m, sizeof(struct ip), iphlen - sizeof(struct ip),
- (caddr_t) opts);
-
- /* Copy in the esp header */
- m_copyback(m, iphlen, ohlen, (caddr_t) &espo);
-
*mp = m;
return 0;
-}
-
+}
/*
* return 0 on success
diff --git a/sys/netinet/ip_esp_old.c b/sys/netinet/ip_esp_old.c
index dc4ebe2b118..309fddc4118 100644
--- a/sys/netinet/ip_esp_old.c
+++ b/sys/netinet/ip_esp_old.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp_old.c,v 1.37 1999/10/29 02:10:02 angelos Exp $ */
+/* $OpenBSD: ip_esp_old.c,v 1.38 1999/12/06 07:14:35 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -161,7 +161,7 @@ esp_old_zeroize(struct tdb *tdbp)
* esp_old_input() gets called to decrypt an input packet
*/
struct mbuf *
-esp_old_input(struct mbuf *m, struct tdb *tdb)
+esp_old_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
{
struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
struct ip *ip, ipo;
@@ -428,7 +428,8 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
}
int
-esp_old_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
+esp_old_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
+ int protoff)
{
struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
struct ip *ip, ipo;
diff --git a/sys/netinet/ip_ether.c b/sys/netinet/ip_ether.c
index 8167733e054..88be0cbf530 100644
--- a/sys/netinet/ip_ether.c
+++ b/sys/netinet/ip_ether.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ether.c,v 1.3 1999/11/04 05:16:32 jason Exp $ */
+/* $OpenBSD: ip_ether.c,v 1.4 1999/12/06 07:14:35 angelos Exp $ */
/*
* The author of this code is Angelos D. Keromytis (kermit@adk.gr)
@@ -197,7 +197,8 @@ va_dcl
#ifdef IPSEC
int
-etherip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
+etherip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
+ int protoff)
{
struct ip *ipo;
ushort ilen;
diff --git a/sys/netinet/ip_ip4.c b/sys/netinet/ip_ip4.c
index b715b9c508a..0438ec05400 100644
--- a/sys/netinet/ip_ip4.c
+++ b/sys/netinet/ip_ip4.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ip4.c,v 1.33 1999/10/29 02:02:33 angelos Exp $ */
+/* $OpenBSD: ip_ip4.c,v 1.34 1999/12/06 07:14:36 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -69,6 +69,14 @@
#include <netinet/ip_mroute.h>
#endif
+#ifdef INET6
+#include <netinet6/in6.h>
+#include <netinet6/ip6.h>
+#include <netinet6/in6_pcb.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/icmp6.h>
+#endif /* INET6 */
+
#include <sys/socketvar.h>
#include <net/raw_cb.h>
@@ -106,15 +114,19 @@ ip4_input(m, va_alist)
va_dcl
#endif
{
+ register struct sockaddr_in *sin;
register struct ifnet *ifp;
register struct ifaddr *ifa;
- register struct sockaddr_in *sin;
- int iphlen;
- struct ip *ipo, *ipi;
struct ifqueue *ifq = NULL;
- int s;
+ struct ip *ipo, *ipi;
+ int s, iphlen;
va_list ap;
+#ifdef INET6
+ register struct sockaddr_in6 *sin6;
+ struct ip6_hdr *ipv6;
+#endif /* INET6 */
+
va_start(ap, m);
iphlen = va_arg(ap, int);
va_end(ap);
@@ -171,34 +183,56 @@ ip4_input(m, va_alist)
ipo = mtod(m, struct ip *);
}
- ipi = (struct ip *) ((caddr_t) ipo + iphlen);
-
/*
* RFC 1853 specifies that the inner TTL should not be touched on
* decapsulation. There's no reason this comment should be here, but
* this is as good as any a position.
*/
- if (ipi->ip_v != IPVERSION)
+ if (ipo->ip_p == IPPROTO_IPIP)
{
- DPRINTF(("ip4_input(): wrong version %d on packet from %s to %s (%s->%s)\n", ipi->ip_v, inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipi->ip_src), inet_ntoa4(ipi->ip_dst)));
- ip4stat.ip4s_notip4++;
- m_freem(m);
- return;
- }
+ ipi = (struct ip *) ((caddr_t) ipo + iphlen);
- /*
- * If we do not accept IP4 other than part of ESP & AH, we should
- * not accept a packet with double ip4 headers neither.
- */
+ if (ipi->ip_v != IPVERSION)
+ {
+ DPRINTF(("ip4_input(): wrong version %d on packet from %s to %s (%s->%s)\n", ipi->ip_v, inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipi->ip_src), inet_ntoa4(ipi->ip_dst)));
+ ip4stat.ip4s_notip4++;
+ m_freem(m);
+ return;
+ }
+
+ /*
+ * If we do not accept IP4 other than as part of ESP & AH, we should
+ * not accept a packet with double ip4 headers neither.
+ */
- if (!ip4_allow && ipi->ip_p == IPPROTO_IPIP)
+ if (!ip4_allow &&
+ ((ipi->ip_p == IPPROTO_IPIP) ||
+ (ipi->ip_p == IPPROTO_IPV6)))
+ {
+ DPRINTF(("ip4_input(): dropped due to policy\n"));
+ ip4stat.ip4s_pdrops++;
+ m_freem(m);
+ return;
+ }
+ }
+
+#ifdef INET6
+ if (ipo->ip_p == IPPROTO_IPIP)
{
- DPRINTF(("ip4_input(): dropped due to policy\n"));
- ip4stat.ip4s_pdrops++;
- m_freem(m);
- return;
+ ipv6 = (struct ip6_hdr *) ((caddr_t) ipo + iphlen);
+
+ if (ipv6->ip6_vfc != IPV6_VERSION)
+ {
+ DPRINTF(("ip4_input(): wrong version %d on packet from %s to %s (%s->%s)\n", ipi->ip_v, inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet6_ntoa4(ipv6->ip6_src), inet6_ntoa4(ipv6->ip6_dst)));
+ ip4stat.ip4s_notip4++;
+ m_freem(m);
+ return;
+ }
+
+ /* XXX Do we need to check that we don't have double-headers ? */
}
+#endif /* INET6 */
/*
* Check remote packets for local address spoofing.
@@ -212,23 +246,57 @@ ip4_input(m, va_alist)
ifa != 0;
ifa = ifa->ifa_list.tqe_next)
{
- if (ifa->ifa_addr->sa_family != AF_INET)
- continue;
-
- sin = (struct sockaddr_in *) ifa->ifa_addr;
-
- if (sin->sin_addr.s_addr == ipi->ip_src.s_addr)
+ switch (ipo->ip_p)
{
- DPRINTF(("ip_input(): possible local address spoofing detected on packet from %s to %s (%s->%s)\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipi->ip_src), inet_ntoa4(ipi->ip_dst)));
- ip4stat.ip4s_spoof++;
- m_freem(m);
- return;
+ case IPPROTO_IPIP:
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ continue;
+
+ sin = (struct sockaddr_in *) ifa->ifa_addr;
+
+ if (sin->sin_addr.s_addr == ipi->ip_src.s_addr)
+ {
+ DPRINTF(("ip_input(): possible local address spoofing detected on packet from %s to %s (%s->%s)\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipi->ip_src), inet_ntoa4(ipi->ip_dst)));
+ ip4stat.ip4s_spoof++;
+ m_freem(m);
+ return;
+ }
+
+ break;
+
+#ifdef INET6
+ case IPPROTO_IPV6:
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+
+ sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
+
+ if (!bcmp(&sin6->sin6_addr, &ipv6->sin6_addr,
+ sizeof(struct in6_addr)))
+ {
+ DPRINTF(("ip_input(): possible local address spoofing detected on packet from %s to %s (%s->%s)\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet6_ntoa4(ipv6->ip6_src), inet6_ntoa4(ipv6->ip6_dst)));
+ ip4stat.ip4s_spoof++;
+ m_freem(m);
+ return;
+ }
+
+ break;
+#endif /* INET6 */
}
+
}
}
/* Statistics */
- ip4stat.ip4s_ibytes += ntohs(ipi->ip_len);
+ ip4stat.ip4s_ibytes += m->m_pkthdr.len - iphlen;
+
+ /* Determine whether we need to queue in IPv4 or IPv6 input queue */
+ ifq = &ipintrq;
+
+#ifdef INET6
+ if (ipo->ip_p == IPPROTO_IPV6)
+ ifq = &ip6intrq;
+#endif
/*
* Interface pointer is already in first mbuf; chop off the
@@ -239,7 +307,7 @@ ip4_input(m, va_alist)
m->m_pkthdr.len -= iphlen;
m->m_data += iphlen;
- /* tdbi is only set in esp or ah, if next protocol is udp or tcp */
+ /* tdbi is only set in ESP or AH, if the next protocol is UDP or TCP */
if (m->m_flags & (M_CONF|M_AUTH))
m->m_pkthdr.tdbi = NULL;
@@ -251,8 +319,6 @@ ip4_input(m, va_alist)
* untrusted packets.
*/
- ifq = &ipintrq;
-
s = splimp(); /* isn't it already? */
if (IF_QFULL(ifq))
{
@@ -266,14 +332,23 @@ ip4_input(m, va_alist)
}
IF_ENQUEUE(ifq, m);
- schednetisr(NETISR_IP);
+
+ if (ifq == &ipintrq)
+ schednetisr(NETISR_IP);
+
+#ifdef INET6
+ if (ifq == &ip6intrq)
+ schednetisr(NETISR_IP6);
+#endif /* INET6 */
+
splx(s);
return;
}
#ifdef IPSEC
int
-ipe4_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp)
+ipe4_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
+ int protoff)
{
struct ip *ipo, *ipi;
ushort ilen;
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index 4c626c533ba..704203fba1f 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.57 1999/12/05 22:09:18 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.58 1999/12/06 07:14:36 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -133,7 +133,7 @@ u_int8_t hmac_opad_buffer[64] = {
struct xformsw xformsw[] = {
{ XF_IP4, 0, "IPv4 Simple Encapsulation",
ipe4_attach, ipe4_init, ipe4_zeroize,
- (struct mbuf * (*)(struct mbuf *, struct tdb *))ipe4_input,
+ (struct mbuf * (*)(struct mbuf *, struct tdb *, int, int))ipe4_input,
ipe4_output, },
{ XF_OLD_AH, XFT_AUTH, "Keyed Authentication, RFC 1828/1852",
ah_old_attach, ah_old_init, ah_old_zeroize,
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index b3a06d3d7cc..992169c9560 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.47 1999/12/04 23:20:21 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.48 1999/12/06 07:14:36 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -385,8 +385,8 @@ struct xformsw
int (*xf_attach)(void); /* called at config time */
int (*xf_init)(struct tdb *, struct xformsw *, struct ipsecinit *);
int (*xf_zeroize)(struct tdb *); /* termination */
- struct mbuf *(*xf_input)(struct mbuf *, struct tdb *); /* input */
- int (*xf_output)(struct mbuf *, struct tdb *, struct mbuf **); /* output */
+ struct mbuf *(*xf_input)(struct mbuf *, struct tdb *, int, int); /* input */
+ int (*xf_output)(struct mbuf *, struct tdb *, struct mbuf **, int, int); /* output */
};
/* xform IDs */
@@ -505,41 +505,46 @@ extern struct flow *find_global_flow(union sockaddr_union *,
extern int ipe4_attach(void);
extern int ipe4_init(struct tdb *, struct xformsw *, struct ipsecinit *);
extern int ipe4_zeroize(struct tdb *);
-extern int ipe4_output(struct mbuf *, struct tdb *, struct mbuf **);
+extern int ipe4_output(struct mbuf *, struct tdb *, struct mbuf **, int, int);
extern void ipe4_input __P((struct mbuf *, ...));
extern void ip4_input __P((struct mbuf *, ...));
/* XF_ETHERIP */
-extern int etherip_output(struct mbuf *, struct tdb *, struct mbuf **);
+extern int etherip_output(struct mbuf *, struct tdb *, struct mbuf **,
+ int, int);
extern void etherip_input __P((struct mbuf *, ...));
/* XF_OLD_AH */
extern int ah_old_attach(void);
extern int ah_old_init(struct tdb *, struct xformsw *, struct ipsecinit *);
extern int ah_old_zeroize(struct tdb *);
-extern int ah_old_output(struct mbuf *, struct tdb *, struct mbuf **);
-extern struct mbuf *ah_old_input(struct mbuf *, struct tdb *);
+extern int ah_old_output(struct mbuf *, struct tdb *, struct mbuf **,
+ int, int);
+extern struct mbuf *ah_old_input(struct mbuf *, struct tdb *, int, int);
/* XF_NEW_AH */
extern int ah_new_attach(void);
extern int ah_new_init(struct tdb *, struct xformsw *, struct ipsecinit *);
extern int ah_new_zeroize(struct tdb *);
-extern int ah_new_output(struct mbuf *, struct tdb *, struct mbuf **);
-extern struct mbuf *ah_new_input(struct mbuf *, struct tdb *);
+extern int ah_new_output(struct mbuf *, struct tdb *, struct mbuf **,
+ int, int);
+extern struct mbuf *ah_new_input(struct mbuf *, struct tdb *, int, int);
/* XF_OLD_ESP */
extern int esp_old_attach(void);
extern int esp_old_init(struct tdb *, struct xformsw *, struct ipsecinit *);
extern int esp_old_zeroize(struct tdb *);
-extern int esp_old_output(struct mbuf *, struct tdb *, struct mbuf **);
-extern struct mbuf *esp_old_input(struct mbuf *, struct tdb *);
+extern int esp_old_output(struct mbuf *, struct tdb *, struct mbuf **,
+ int, int);
+extern struct mbuf *esp_old_input(struct mbuf *, struct tdb *, int, int);
/* XF_NEW_ESP */
extern int esp_new_attach(void);
extern int esp_new_init(struct tdb *, struct xformsw *, struct ipsecinit *);
extern int esp_new_zeroize(struct tdb *);
-extern int esp_new_output(struct mbuf *, struct tdb *, struct mbuf **);
-extern struct mbuf *esp_new_input(struct mbuf *, struct tdb *);
+extern int esp_new_output(struct mbuf *, struct tdb *, struct mbuf **,
+ int, int);
+extern struct mbuf *esp_new_input(struct mbuf *, struct tdb *, int, int);
/* XF_TCPSIGNATURE */
extern int tcp_signature_tdb_attach __P((void));
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index ea4b083e0db..186433bef12 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.53 1999/12/04 23:20:21 angelos Exp $ */
+/* $OpenBSD: ip_output.c,v 1.54 1999/12/06 07:14:36 angelos Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -76,6 +76,10 @@
#define DPRINTF(x)
#endif
+#ifndef offsetof
+#define offsetof(s, e) ((int)&((s *)0)->e)
+#endif
+
extern u_int8_t get_sa_require __P((struct inpcb *));
#endif
@@ -470,7 +474,7 @@ sendit:
sunion.sin.sin_len = sizeof(struct sockaddr_in);
sunion.sin.sin_addr = gw->sen_ipsp_dst;
}
-#if INET6
+#ifdef INET6
else {
sunion.sin6.sin6_family = AF_INET6;
sunion.sin6.sin6_len = sizeof(struct sockaddr_in6);
@@ -541,7 +545,7 @@ sendit:
DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet_ntoa4(gw->sen_ipsp_dst), ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_sproto));
#if INET6
else
- DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet_ntoa4(gw->sen_ipsp_dst), ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_sproto));
+ DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet6_ntoa4(gw->sen_ipsp_dst), ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_sproto));
#endif /* INET6 */
if (re->re_rt)
@@ -598,12 +602,12 @@ sendit:
ip->ip_dst.s_addr)) ||
((tdb->tdb_flags & TDBF_TUNNELING) &&
(tdb->tdb_xform->xf_type != XF_IP4))) {
- /*
- * Fix checksum here, AH and ESP fix the
- * checksum in their output routines.
- */
- ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
- error = ipe4_output(m, tdb, &mp);
+ /* Fix length and checksum */
+ ip->ip_len = htons(m->m_pkthdr.len);
+ ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
+ error = ipe4_output(m, tdb, &mp,
+ ip->ip_hl << 2,
+ offsetof(struct ip, ip_p));
if (mp == NULL)
error = EFAULT;
if (error) {
@@ -613,20 +617,16 @@ sendit:
return error;
}
m = mp;
+ mp = NULL;
}
if (tdb->tdb_xform->xf_type == XF_IP4) {
- /*
- * Fix checksum if IP-IP; AH and ESP fix the
- * IP header checksum in their
- * output routines.
- */
ip = mtod(m, struct ip *);
+ ip->ip_len = htons(m->m_pkthdr.len);
ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
}
-
- error = (*(tdb->tdb_xform->xf_output))(m, tdb, &mp);
+ error = (*(tdb->tdb_xform->xf_output))(m, tdb, &mp, ip->ip_hl << 2, offsetof(struct ip, ip_p));
if (!error && mp == NULL)
error = EFAULT;
if (error) {
@@ -639,14 +639,16 @@ sendit:
}
m = mp;
+ mp = NULL;
ip = mtod(m, struct ip *);
- if (tdb->tdb_xform->xf_type == XF_IP4)
- ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
+ ip->ip_len = htons(m->m_pkthdr.len);
tdb = tdb->tdb_onext;
}
splx(s);
+ ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
+
/*
* At this point, m is pointing to an mbuf chain with the
* processed packet. Call ourselves recursively, but