summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>1999-02-24 22:33:08 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>1999-02-24 22:33:08 +0000
commitbc6ad109752ee01f946571f9488d7335d751b7fe (patch)
tree51a5f44fa5bf81542dfc5c8ad510f1f8cf4a6691
parent689ba6c5dcae1e6d1086d01cfc27fd19a8e11b03 (diff)
Remove encap.h include; saner debugging printfs; fix buglets; work with
pfkeyv2.
-rw-r--r--sys/netinet/in_pcb.c3
-rw-r--r--sys/netinet/in_proto.c3
-rw-r--r--sys/netinet/ip_ah.c134
-rw-r--r--sys/netinet/ip_ah.h99
-rw-r--r--sys/netinet/ip_ah_new.c455
-rw-r--r--sys/netinet/ip_ah_old.c328
-rw-r--r--sys/netinet/ip_esp.c128
-rw-r--r--sys/netinet/ip_esp.h197
-rw-r--r--sys/netinet/ip_esp_new.c787
-rw-r--r--sys/netinet/ip_esp_old.c442
-rw-r--r--sys/netinet/ip_ip4.c103
-rw-r--r--sys/netinet/ip_ip4.h21
-rw-r--r--sys/netinet/ip_ipsp.c747
-rw-r--r--sys/netinet/ip_ipsp.h444
-rw-r--r--sys/netinet/ip_output.c117
15 files changed, 1772 insertions, 2236 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index b36fe6b55d3..24ec420bdd2 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.c,v 1.29 1999/01/11 02:01:34 deraadt Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.30 1999/02/24 22:32:57 angelos Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@@ -77,7 +77,6 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#endif /* INET6 */
#ifdef IPSEC
-#include <net/encap.h>
#include <netinet/ip_ipsp.h>
extern int check_ipsec_policy __P((struct inpcb *, u_int32_t));
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 8da44bb90ed..3a1b928d7f8 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_proto.c,v 1.10 1999/01/08 01:00:34 deraadt Exp $ */
+/* $OpenBSD: in_proto.c,v 1.11 1999/02/24 22:32:58 angelos Exp $ */
/* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $ */
/*
@@ -111,7 +111,6 @@ void iplinit __P((void));
#endif /* INET6 */
#ifdef IPSEC
-#include <net/encap.h>
#include <netinet/ip_ipsp.h>
extern void ah_input __P((struct mbuf *, ...));
diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c
index 682f4fe3d75..4ae7499c04b 100644
--- a/sys/netinet/ip_ah.c
+++ b/sys/netinet/ip_ah.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah.c,v 1.16 1998/06/10 23:57:13 provos Exp $ */
+/* $OpenBSD: ip_ah.c,v 1.17 1999/02/24 22:32:59 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -66,16 +66,21 @@
#include <sys/socketvar.h>
#include <net/raw_cb.h>
-#include <net/encap.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_ah.h>
-#include <sys/syslog.h>
-
#include "bpfilter.h"
-void ah_input __P((struct mbuf *, int));
+extern struct ifnet enc_softc;
+
+#ifdef ENCDEBUG
+#define DPRINTF(x) if (encdebug) printf x
+#else
+#define DPRINTF(x)
+#endif
+
+void ah_input __P((struct mbuf *, int));
/*
* ah_input gets called when we receive an packet with an AH.
@@ -84,6 +89,7 @@ void ah_input __P((struct mbuf *, int));
void
ah_input(register struct mbuf *m, int iphlen)
{
+ union sockaddr_union sunion;
struct ifqueue *ifq = NULL;
struct ah_old *ahp, ahn;
struct expiration *exp;
@@ -103,13 +109,10 @@ ah_input(register struct mbuf *m, int iphlen)
{
if ((m = m_pullup(m, iphlen + AH_OLD_FLENGTH)) == 0)
{
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ah_input(): (possibly too short) packet from %x to %x dropped\n", ipo->ip_src, ipo->ip_dst);
-#endif /* ENCDEBUG */
ahstat.ahs_hdrops++;
return;
}
+
ipo = mtod(m, struct ip *);
}
@@ -121,11 +124,14 @@ ah_input(register struct mbuf *m, int iphlen)
* IP packet ready to go through input processing.
*/
- tdbp = gettdb(ahp->ah_spi, ipo->ip_dst, IPPROTO_AH);
+ bzero(&sunion, sizeof(sunion));
+ sunion.sin.sin_family = AF_INET;
+ sunion.sin.sin_len = sizeof(struct sockaddr_in);
+ sunion.sin.sin_addr = ipo->ip_dst;
+ tdbp = gettdb(ahp->ah_spi, &sunion, IPPROTO_AH);
if (tdbp == NULL)
{
- if (encdebug)
- log(LOG_ERR, "ah_input(): could not find SA for AH packet from %x to %x, spi %08x\n", ipo->ip_src, ipo->ip_dst, ntohl(ahp->ah_spi));
+ DPRINTF(("ah_input(): could not find SA for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(sunion), ntohl(ahp->ah_spi)));
m_freem(m);
ahstat.ahs_notdb++;
return;
@@ -133,8 +139,7 @@ ah_input(register struct mbuf *m, int iphlen)
if (tdbp->tdb_flags & TDBF_INVALID)
{
- if (encdebug)
- log(LOG_ALERT, "ah_input(): attempted to use invalid AH SA %08x, packet %x->%x\n", ntohl(ahp->ah_spi), ipo->ip_src, ipo->ip_dst);
+ DPRINTF(("ah_input(): attempted to use invalid SA %08x, packet from %s to %s\n", ntohl(ahp->ah_spi), inet_ntoa4(ipo->ip_src), ipsp_address(sunion)));
m_freem(m);
ahstat.ahs_invalid++;
return;
@@ -142,8 +147,7 @@ ah_input(register struct mbuf *m, int iphlen)
if (tdbp->tdb_xform == NULL)
{
- if (encdebug)
- log(LOG_ALERT, "ah_input(): attempted to use uninitialized AH SA %08x, packet from %x to %x\n", ntohl(ahp->ah_spi), ipo->ip_src, ipo->ip_dst);
+ DPRINTF(("ah_input(): attempted to use uninitialized SA %08x, packet from %s to %s\n", ntohl(ahp->ah_spi), inet_ntoa4(ipo->ip_src), ipsp_address(sunion)));
m_freem(m);
ahstat.ahs_noxform++;
return;
@@ -159,21 +163,10 @@ ah_input(register struct mbuf *m, int iphlen)
if (tdbp->tdb_flags & TDBF_FIRSTUSE)
{
exp = get_expiration();
- if (exp == (struct expiration *) NULL)
- {
- if (encdebug)
- log(LOG_WARNING,
- "ah_input(): out of memory for expiration timer\n");
- ahstat.ahs_hdrops++;
- m_freem(m);
- return;
- }
-
- exp->exp_dst.s_addr = tdbp->tdb_dst.s_addr;
+ bcopy(&tdbp->tdb_dst, &exp->exp_dst, SA_LEN(&tdbp->tdb_dst.sa));
exp->exp_spi = tdbp->tdb_spi;
exp->exp_sproto = tdbp->tdb_sproto;
exp->exp_timeout = tdbp->tdb_first_use + tdbp->tdb_exp_first_use;
-
put_expiration(exp);
}
@@ -181,21 +174,10 @@ ah_input(register struct mbuf *m, int iphlen)
(tdbp->tdb_soft_first_use <= tdbp->tdb_exp_first_use))
{
exp = get_expiration();
- if (exp == (struct expiration *) NULL)
- {
- if (encdebug)
- log(LOG_WARNING,
- "ah_input(): out of memory for expiration timer\n");
- ahstat.ahs_hdrops++;
- m_freem(m);
- return;
- }
-
- exp->exp_dst.s_addr = tdbp->tdb_dst.s_addr;
+ bcopy(&tdbp->tdb_dst, &exp->exp_dst, SA_LEN(&tdbp->tdb_dst.sa));
exp->exp_spi = tdbp->tdb_spi;
exp->exp_sproto = tdbp->tdb_sproto;
exp->exp_timeout = tdbp->tdb_first_use + tdbp->tdb_soft_first_use;
-
put_expiration(exp);
}
}
@@ -206,8 +188,7 @@ ah_input(register struct mbuf *m, int iphlen)
m = (*(tdbp->tdb_xform->xf_input))(m, tdbp);
if (m == NULL)
{
- if (encdebug)
- log(LOG_ALERT, "ah_input(): authentication failed for AH packet from %x to %x, spi %08x\n", ipn.ip_src, ipn.ip_dst, ntohl(ahn.ah_spi));
+ 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)));
ahstat.ahs_badkcr++;
return;
}
@@ -218,48 +199,42 @@ ah_input(register struct mbuf *m, int iphlen)
/* ipn will now contain the inner IP header */
m_copydata(m, ipo->ip_hl << 2, sizeof(struct ip), (caddr_t) &ipn);
- /* Encapsulating SPI */
- if (tdbp->tdb_osrc.s_addr && tdbp->tdb_odst.s_addr)
- {
- if (tdbp->tdb_flags & TDBF_UNIQUE)
- if ((ipn.ip_src.s_addr != ipo->ip_src.s_addr) ||
- (ipn.ip_dst.s_addr != ipo->ip_dst.s_addr))
- {
- if (encdebug)
- log(LOG_ALERT, "ah_input(): AH-tunnel with different internal addresses %x/%x, SA %08x/%x\n", ipo->ip_src, ipo->ip_dst, tdbp->tdb_spi, tdbp->tdb_dst);
- m_freem(m);
- ahstat.ahs_hdrops++;
- return;
- }
-
- /*
- * XXX Here we should be checking that the inner IP addresses
- * XXX are acceptable/authorized.
- */
- }
- else /* So we're paranoid */
+ if (tdbp->tdb_flags & TDBF_UNIQUE)
+ if ((ipn.ip_src.s_addr != ipo->ip_src.s_addr) ||
+ (ipn.ip_dst.s_addr != ipo->ip_dst.s_addr))
+ {
+ DPRINTF(("ah_input(): AH-tunnel with different internal addresses %s->%s (%s->%s), SA %s/%08x\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipn.ip_src), ipsp_address(sunion), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi)));
+ m_freem(m);
+ ahstat.ahs_hdrops++;
+ return;
+ }
+
+ /*
+ * Check that the inner source address is the same as
+ * the proxy address, if available.
+ */
+ if ((tdbp->tdb_proxy.sin.sin_addr.s_addr != INADDR_ANY) &&
+ (ipn.ip_src.s_addr != tdbp->tdb_proxy.sin.sin_addr.s_addr))
{
- if (encdebug)
- log(LOG_ALERT, "ah_input(): AH-tunnel used when expecting AH-transport, SA %08x/%x\n", tdbp->tdb_spi, tdbp->tdb_dst);
- m_freem(m);
+ DPRINTF(("ah_input(): inner source address %s doesn't correspond to expected proxy source %s, SA %s/%08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(tdbp->tdb_proxy), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi)));
+ m_free(m);
ahstat.ahs_hdrops++;
return;
}
}
/*
- * Check that the source address is an expected one, if we know what
- * it's supposed to be. This avoids source address spoofing.
+ * Check that the outter source address is an expected one, if we know
+ * what it's supposed to be. This avoids source address spoofing.
*/
- if (tdbp->tdb_src.s_addr != INADDR_ANY)
- if (ipo->ip_src.s_addr != tdbp->tdb_src.s_addr)
- {
- if (encdebug)
- log(LOG_ALERT, "esp_input(): source address %x doesn't correspond to expected source %x, SA %08x/%x\n", ipo->ip_src, tdbp->tdb_src, tdbp->tdb_dst, tdbp->tdb_spi);
- m_free(m);
- ahstat.ahs_hdrops++;
- return;
- }
+ if ((tdbp->tdb_src.sin.sin_addr.s_addr != INADDR_ANY) &&
+ (ipo->ip_src.s_addr != tdbp->tdb_src.sin.sin_addr.s_addr))
+ {
+ DPRINTF(("ah_input(): source address %s doesn't correspond to expected source %s, SA %s/%08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(tdbp->tdb_src), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi)));
+ m_free(m);
+ ahstat.ahs_hdrops++;
+ return;
+ }
/* Packet is authentic */
m->m_flags |= M_AUTH;
@@ -279,7 +254,7 @@ ah_input(register struct mbuf *m, int iphlen)
hdr.af = AF_INET;
hdr.spi = tdbp->tdb_spi;
- hdr.flags = m->m_flags & (M_AUTH|M_CONF|M_TUNNEL);
+ hdr.flags = m->m_flags & (M_AUTH|M_CONF);
m0.m_next = m;
m0.m_len = ENC_HDRLEN;
@@ -303,10 +278,7 @@ ah_input(register struct mbuf *m, int iphlen)
m_freem(m);
ahstat.ahs_qfull++;
splx(s);
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ah_input(): dropped packet because of full IP queue\n");
-#endif /* ENCDEBUG */
+ DPRINTF(("ah_input(): dropped packet because of full IP queue\n"));
return;
}
diff --git a/sys/netinet/ip_ah.h b/sys/netinet/ip_ah.h
index 1df84dbb1b5..817f4eee5ad 100644
--- a/sys/netinet/ip_ah.h
+++ b/sys/netinet/ip_ah.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah.h,v 1.13 1998/11/25 02:01:28 niklas Exp $ */
+/* $OpenBSD: ip_ah.h,v 1.14 1999/02/24 22:32:59 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -38,20 +38,6 @@
* Per RFC1826 (Atkinson, 1995)
*/
-#include <sys/md5k.h>
-#include <netinet/ip_sha1.h>
-#include <netinet/ip_rmd160.h>
-
-struct ah_hash {
- int type;
- char *name;
- u_int16_t hashsize;
- u_int16_t ctxsize;
- void (*Init)(void *);
- void (*Update)(void *, u_int8_t *, u_int16_t);
- void (*Final)(u_int8_t *, void *);
-};
-
struct ah_old
{
u_int8_t ah_nh; /* Next header (protocol) */
@@ -63,13 +49,6 @@ struct ah_old
#define AH_OLD_FLENGTH 8 /* size of fixed part */
-/* Authenticator lengths */
-#define AH_MD5_ALEN 16
-#define AH_SHA1_ALEN 20
-#define AH_RMD160_ALEN 20
-
-#define AH_ALEN_MAX AH_SHA1_ALEN /* Keep this updated */
-
struct ahstat
{
u_int32_t ahs_hdrops; /* packet shorter than header shows */
@@ -89,14 +68,6 @@ struct ahstat
u_int32_t ahs_toobig; /* packet got larger than IP_MAXPACKET */
};
-#define AH_HMAC_HASHLEN 12 /* 96 bits of authenticator */
-#define AH_HMAC_RPLENGTH 4 /* 32 bits of replay counter */
-#define AH_HMAC_INITIAL_RPL 1 /* Replay counter initial value */
-
-#define HMAC_IPAD_VAL 0x36
-#define HMAC_OPAD_VAL 0x5C
-#define HMAC_BLOCK_LEN 64
-
struct ah_new
{
u_int8_t ah_nh; /* Next header (protocol) */
@@ -109,72 +80,6 @@ struct ah_new
#define AH_NEW_FLENGTH (sizeof(struct ah_new))
-struct ah_new_xencap
-{
- u_int32_t amx_hash_algorithm;
- int32_t amx_wnd;
- u_int32_t amx_keylen;
- u_int8_t amx_key[1];
-};
-
-#define AH_NEW_XENCAP_LEN (3 * sizeof(u_int32_t))
-
-struct ah_new_xdata
-{
- u_int32_t amx_hash_algorithm;
- int32_t amx_wnd;
- u_int32_t amx_rpl; /* Replay counter */
- u_int32_t amx_bitmap;
- struct ah_hash *amx_hash;
- union
- {
- MD5_CTX amx_MD5_ictx; /* Internal key+padding */
- SHA1_CTX amx_SHA1_ictx;
- RMD160_CTX amx_RMD160_ictx;
- } amx_ictx;
- union
- {
- MD5_CTX amx_MD5_octx; /* External key+padding */
- SHA1_CTX amx_SHA1_octx;
- RMD160_CTX amx_RMD160_octx;
- } amx_octx;
-};
-
-#define amx_md5_ictx amx_ictx.amx_MD5_ictx
-#define amx_md5_octx amx_octx.amx_MD5_octx
-#define amx_sha1_ictx amx_ictx.amx_SHA1_ictx
-#define amx_sha1_octx amx_octx.amx_SHA1_octx
-#define amx_rmd160_ictx amx_ictx.amx_RMD160_ictx
-#define amx_rmd160_octx amx_octx.amx_RMD160_octx
-
-struct ah_old_xdata
-{
- u_int32_t amx_hash_algorithm;
- u_int32_t amx_keylen; /* Key material length */
- struct ah_hash *amx_hash;
- union
- {
- MD5_CTX amx_MD5_ctx;
- SHA1_CTX amx_SHA1_ctx;
- } amx_ctx;
- u_int8_t amx_key[1]; /* Key material */
-};
-
-#define amx_md5_ctx amx_ctx.amx_MD5_ctx
-#define amx_sha1_ctx amx_ctx.amx_SHA1_ctx
-
-struct ah_old_xencap
-{
- u_int32_t amx_hash_algorithm;
- u_int32_t amx_keylen;
- u_int8_t amx_key[1];
-};
-
-#define AH_OLD_XENCAP_LEN (2 * sizeof(u_int32_t))
-
-#define AH_HMAC_IPAD_VAL 0x36
-#define AH_HMAC_OPAD_VAL 0x5C
-
#ifdef _KERNEL
struct ahstat ahstat;
-#endif
+#endif /* _KERNEL */
diff --git a/sys/netinet/ip_ah_new.c b/sys/netinet/ip_ah_new.c
index a6061bfc4d7..ad6cfc3463e 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.21 1999/01/11 22:52:09 deraadt Exp $ */
+/* $OpenBSD: ip_ah_new.c,v 1.22 1999/02/24 22:32:59 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -65,10 +65,9 @@
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
-#include <net/encap.h>
-
#include <netinet/ip_ipsp.h>
#include <netinet/ip_ah.h>
+#include <net/pfkeyv2.h>
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
@@ -76,25 +75,23 @@
#define DPRINTF(x)
#endif
-extern void encap_sendnotify(int, struct tdb *, void *);
-
-struct ah_hash ah_new_hash[] = {
- { ALG_AUTH_MD5, "HMAC-MD5-96",
- AH_MD5_ALEN,
+struct auth_hash ah_new_hash[] = {
+ { SADB_AALG_MD5HMAC96, "HMAC-MD5-96",
+ MD5HMAC96_KEYSIZE, AH_MD5_ALEN,
sizeof(MD5_CTX),
(void (*)(void *)) MD5Init,
(void (*)(void *, u_int8_t *, u_int16_t)) MD5Update,
(void (*)(u_int8_t *, void *)) MD5Final
},
- { ALG_AUTH_SHA1, "HMAC-SHA1-96",
- AH_SHA1_ALEN,
+ { SADB_AALG_SHA1HMAC96, "HMAC-SHA1-96",
+ SHA1HMAC96_KEYSIZE, AH_SHA1_ALEN,
sizeof(SHA1_CTX),
(void (*)(void *)) SHA1Init,
(void (*)(void *, u_int8_t *, u_int16_t)) SHA1Update,
(void (*)(u_int8_t *, void *)) SHA1Final
},
- { ALG_AUTH_RMD160, "HMAC-RIPEMD-160-96",
- AH_RMD160_ALEN,
+ { SADB_AALG_X_RIPEMD160HMAC96, "HMAC-RIPEMD-160-96",
+ RIPEMD160HMAC96_KEYSIZE, AH_RMD160_ALEN,
sizeof(RMD160_CTX),
(void (*)(void *)) RMD160Init,
(void (*)(void *, u_int8_t *, u_int16_t)) RMD160Update,
@@ -110,127 +107,66 @@ struct ah_hash ah_new_hash[] = {
int
ah_new_attach()
{
- DPRINTF(("ah_new_attach(): setting up\n"));
return 0;
}
/*
- * ah_new_init() is called when an SPI is being set up. It interprets the
- * encap_msghdr present in m, and sets up the transformation data.
+ * ah_new_init() is called when an SPI is being set up.
*/
int
-ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
+ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
- struct ah_new_xdata *xd;
- struct ah_new_xencap txd;
- struct encap_msghdr *em;
- struct ah_hash *thash;
- caddr_t buffer = NULL;
- int blocklen, i;
-
- if (m->m_len < ENCAP_MSG_FIXED_LEN)
- {
- if ((m = m_pullup(m, ENCAP_MSG_FIXED_LEN)) == NULL)
- {
- DPRINTF(("ah_new_init(): m_pullup failed\n"));
- return ENOBUFS;
- }
- }
+ struct auth_hash *thash = NULL;
+ int i;
- em = mtod(m, struct encap_msghdr *);
- if (em->em_msglen - EMT_SETSPI_FLEN <= AH_NEW_XENCAP_LEN)
- {
- DPRINTF(("ah_new_init() initialization failed\n"));
- return EINVAL;
- }
-
- /* Just copy the standard fields */
- m_copydata(m, EMT_SETSPI_FLEN, AH_NEW_XENCAP_LEN, (caddr_t) &txd);
+ for (i = sizeof(ah_new_hash) / sizeof(struct auth_hash) - 1;
+ i >= 0; i--)
+ if (ii->ii_authalg == ah_new_hash[i].type)
+ break;
- /* Check whether the hash algorithm is supported */
- for (i = sizeof(ah_new_hash) / sizeof(struct ah_hash) - 1; i >= 0; i--)
- if (txd.amx_hash_algorithm == ah_new_hash[i].type)
- break;
if (i < 0)
{
- DPRINTF(("ah_new_init(): unsupported authentication algorithm %d specified\n", txd.amx_hash_algorithm));
+ DPRINTF(("ah_new_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
return EINVAL;
}
- DPRINTF(("ah_new_init(): initalized TDB with hash algorithm %d: %s\n",
- txd.amx_hash_algorithm, ah_new_hash[i].name));
+
thash = &ah_new_hash[i];
- blocklen = HMAC_BLOCK_LEN;
- if (txd.amx_keylen + EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN != em->em_msglen)
+ if (ii->ii_authkeylen != thash->keysize)
{
- DPRINTF(("ah_new_init(): message length (%d) doesn't match\n",
- em->em_msglen));
+ DPRINTF(("ah_new_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
return EINVAL;
}
- MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct ah_new_xdata),
- M_XDATA, M_WAITOK);
- if (tdbp->tdb_xdata == NULL)
- {
- DPRINTF(("ah_new_init(): MALLOC failed\n"));
- return ENOBUFS;
- }
-
- MALLOC(buffer, caddr_t,
- (txd.amx_keylen < blocklen ? blocklen : txd.amx_keylen),
- M_TEMP, M_WAITOK);
- if (buffer == NULL)
- {
- DPRINTF(("ah_new_init(): MALLOC failed\n"));
- free(tdbp->tdb_xdata, M_XDATA);
- return ENOBUFS;
- }
-
- bzero(buffer, (txd.amx_keylen < blocklen ? blocklen : txd.amx_keylen));
- bzero(tdbp->tdb_xdata, sizeof(struct ah_new_xdata));
- xd = (struct ah_new_xdata *) tdbp->tdb_xdata;
-
- /* Copy the key to the buffer */
- m_copydata(m, EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN, txd.amx_keylen, buffer);
-
- xd->amx_hash = thash;
- /* Shorten the key if necessary */
- if (txd.amx_keylen > blocklen)
- {
- xd->amx_hash->Init(&(xd->amx_ictx));
- xd->amx_hash->Update(&(xd->amx_ictx), buffer, txd.amx_keylen);
- bzero(buffer,
- (txd.amx_keylen < blocklen ? blocklen : txd.amx_keylen));
- xd->amx_hash->Final(buffer, &(xd->amx_ictx));
- }
-
- /* Pointer to the transform */
tdbp->tdb_xform = xsp;
+ tdbp->tdb_authalgxform = thash;
+ tdbp->tdb_bitmap = 0;
+ tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
- /* Pass name of auth algorithm for kernfs */
- tdbp->tdb_authname = xd->amx_hash->name;
-
- xd->amx_hash_algorithm = txd.amx_hash_algorithm;
- xd->amx_rpl = AH_HMAC_INITIAL_RPL;
- xd->amx_wnd = txd.amx_wnd;
- xd->amx_bitmap = 0;
+ DPRINTF(("ah_new_init(): initialized TDB with hash algorithm %s\n",
+ thash->name));
/* Precompute the I and O pads of the HMAC */
- for (i = 0; i < blocklen; i++)
- buffer[i] ^= HMAC_IPAD_VAL;
-
- xd->amx_hash->Init(&(xd->amx_ictx));
- xd->amx_hash->Update(&(xd->amx_ictx), buffer, blocklen);
-
- for (i = 0; i < blocklen; i++)
- buffer[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
-
- xd->amx_hash->Init(&(xd->amx_octx));
- xd->amx_hash->Update(&(xd->amx_octx), buffer, blocklen);
-
- bzero(buffer, blocklen); /* paranoid */
- free(buffer, M_TEMP);
+ for (i = 0; i < ii->ii_authkeylen; i++)
+ ii->ii_authkey[i] ^= HMAC_IPAD_VAL;
+
+ MALLOC(tdbp->tdb_ictx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_ictx, thash->ctxsize);
+ thash->Init(tdbp->tdb_ictx);
+ thash->Update(tdbp->tdb_ictx, ii->ii_authkey, ii->ii_authkeylen);
+ thash->Update(tdbp->tdb_ictx, hmac_ipad_buffer,
+ HMAC_BLOCK_LEN - ii->ii_authkeylen);
+
+ for (i = 0; i < ii->ii_authkeylen; i++)
+ ii->ii_authkey[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
+
+ MALLOC(tdbp->tdb_octx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_octx, thash->ctxsize);
+ thash->Init(tdbp->tdb_octx);
+ thash->Update(tdbp->tdb_octx, ii->ii_authkey, ii->ii_authkeylen);
+ thash->Update(tdbp->tdb_octx, hmac_opad_buffer,
+ HMAC_BLOCK_LEN - ii->ii_authkeylen);
bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */
@@ -241,12 +177,18 @@ ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
int
ah_new_zeroize(struct tdb *tdbp)
{
- DPRINTF(("ah_new_zeroize(): freeing memory\n"));
- if (tdbp->tdb_xdata)
+ if (tdbp->tdb_ictx)
{
- FREE(tdbp->tdb_xdata, M_XDATA);
- tdbp->tdb_xdata = NULL;
+ FREE(tdbp->tdb_ictx, M_XDATA);
+ tdbp->tdb_ictx = NULL;
}
+
+ if (tdbp->tdb_octx)
+ {
+ FREE(tdbp->tdb_octx, M_XDATA);
+ tdbp->tdb_octx = NULL;
+ }
+
return 0;
}
@@ -258,7 +200,7 @@ ah_new_zeroize(struct tdb *tdbp)
struct mbuf *
ah_new_input(struct mbuf *m, struct tdb *tdb)
{
- struct ah_new_xdata *xd;
+ struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
struct ip *ip, ipo;
struct ah_new *aho, *ah;
int ohlen, len, count, off, errc;
@@ -273,9 +215,6 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
u_char buffer[40];
aho = (struct ah_new *) buffer;
-
- xd = (struct ah_new_xdata *) tdb->tdb_xdata;
-
ohlen = sizeof(struct ip) + AH_NEW_FLENGTH;
if (m->m_len < ohlen)
@@ -310,29 +249,57 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
if (ah->ah_hl * sizeof(u_int32_t) != AH_HMAC_HASHLEN + AH_HMAC_RPLENGTH)
{
- DPRINTF(("ah_new_input(): bad authenticator length for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi)));
+ DPRINTF(("ah_new_input(): bad authenticator length for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi)));
ahstat.ahs_badauthl++;
m_freem(m);
return NULL;
}
+ /* Update the counters */
+ tdb->tdb_cur_bytes += ip->ip_len - (ip->ip_hl << 2) -
+ ah->ah_hl * sizeof(u_int32_t);
+ ahstat.ahs_ibytes += ip->ip_len - (ip->ip_hl << 2) -
+ ah->ah_hl * sizeof(u_int32_t);
+
+ /* Hard expiration */
+ if ((tdb->tdb_flags & TDBF_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ tdb_delete(tdb, 0);
+ m_freem(m);
+ return NULL;
+ }
+
+ /* Notify on expiration */
+ if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
+ }
+
/* Replay window checking */
- if (xd->amx_wnd >= 0)
+ if (tdb->tdb_wnd > 0)
{
btsx = ntohl(ah->ah_rpl);
- if ((errc = checkreplaywindow32(btsx, 0, &(xd->amx_rpl), xd->amx_wnd,
- &(xd->amx_bitmap))) != 0)
+ if ((errc = checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl), tdb->tdb_wnd,
+ &(tdb->tdb_bitmap))) != 0)
{
switch(errc)
{
case 1:
- DPRINTF(("ah_new_input(): replay counter wrapped for packets from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi)));
+ DPRINTF(("ah_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(ah->ah_spi)));
ahstat.ahs_wrap++;
break;
case 2:
case 3:
- DPRINTF(("ah_new_input(): duplicate packet received, %x->%x spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi)));
+ DPRINTF(("ah_new_input(): duplicate packet received from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi)));
ahstat.ahs_replay++;
break;
}
@@ -351,8 +318,8 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
ipo.ip_ttl = 0;
ipo.ip_sum = 0;
- bcopy(&(xd->amx_ictx), &ctx, xd->amx_hash->ctxsize);
- xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
+ bcopy(tdb->tdb_ictx, &ctx, ahx->ctxsize);
+ ahx->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
/* Options */
if ((ip->ip_hl << 2) > sizeof(struct ip))
@@ -362,13 +329,13 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
switch (optval)
{
case IPOPT_EOL:
- xd->amx_hash->Update(&ctx, ipseczeroes, 1);
+ ahx->Update(&ctx, ipseczeroes, 1);
off = ip->ip_hl << 2;
break;
case IPOPT_NOP:
- xd->amx_hash->Update(&ctx, ipseczeroes, 1);
+ ahx->Update(&ctx, ipseczeroes, 1);
off++;
break;
@@ -378,7 +345,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
case 134:
optval = ((u_int8_t *) ip)[off + 1];
- xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval);
+ ahx->Update(&ctx, (u_int8_t *) ip + off, optval);
off += optval;
break;
@@ -386,16 +353,15 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
default:
optval = ((u_int8_t *) ip)[off + 1];
- xd->amx_hash->Update(&ctx, ipseczeroes, optval);
+ ahx->Update(&ctx, ipseczeroes, optval);
off += optval;
break;
}
}
- xd->amx_hash->Update(&ctx, (unsigned char *) ah, AH_NEW_FLENGTH -
- AH_HMAC_HASHLEN);
- xd->amx_hash->Update(&ctx, ipseczeroes, AH_HMAC_HASHLEN);
+ ahx->Update(&ctx, (unsigned char *) ah, AH_NEW_FLENGTH - AH_HMAC_HASHLEN);
+ ahx->Update(&ctx, ipseczeroes, AH_HMAC_HASHLEN);
/*
* Code shamelessly stolen from m_copydata
@@ -408,7 +374,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
{
if (m0 == 0)
{
- DPRINTF(("ah_new_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi)));
+ DPRINTF(("ah_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(ah->ah_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
@@ -425,7 +391,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
{
if (m0 == 0)
{
- DPRINTF(("ah_new_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi)));
+ DPRINTF(("ah_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(ah->ah_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
@@ -433,36 +399,21 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
count = min(m0->m_len - off, len);
- xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count);
+ ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count);
len -= count;
off = 0;
m0 = m0->m_next;
}
- xd->amx_hash->Final((unsigned char *) (aho->ah_data), &ctx);
- bcopy(&(xd->amx_octx), &ctx, xd->amx_hash->ctxsize);
- xd->amx_hash->Update(&ctx, (unsigned char *) (aho->ah_data),
- xd->amx_hash->hashsize);
- xd->amx_hash->Final((unsigned char *) (aho->ah_data), &ctx);
+ ahx->Final((unsigned char *) (aho->ah_data), &ctx);
+ bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize);
+ ahx->Update(&ctx, (unsigned char *) (aho->ah_data), ahx->hashsize);
+ ahx->Final((unsigned char *) (aho->ah_data), &ctx);
if (bcmp(aho->ah_data, ah->ah_data, AH_HMAC_HASHLEN))
{
- DPRINTF(("ah_new_input(): authentication failed for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi)));
-#ifdef ENCDEBUG
- if (encdebug)
- {
- printf("Received authenticator: ");
- for (off = 0; off < AH_HMAC_HASHLEN; off++)
- printf("%02x ", ah->ah_data[off]);
- printf("\n");
-
- printf("Computed authenticator: ");
- for (off = 0; off < AH_HMAC_HASHLEN; off++)
- printf("%02x ", aho->ah_data[off]);
- printf("\n");
- }
-#endif
+ DPRINTF(("ah_new_input(): authentication failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi)));
ahstat.ahs_badauth++;
m_freem(m);
return NULL;
@@ -492,44 +443,6 @@ ah_new_input(struct mbuf *m, struct tdb *tdb)
ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));
- /* Update the counters */
- tdb->tdb_cur_packets++;
- tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
- ahstat.ahs_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
-
- /* Notify on expiration */
- if (tdb->tdb_flags & TDBF_SOFT_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_PACKETS;
- }
- else
- if (tdb->tdb_flags & TDBF_SOFT_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
- }
- }
-
- if (tdb->tdb_flags & TDBF_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- else
- if (tdb->tdb_flags & TDBF_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- }
-
return m;
}
@@ -537,40 +450,37 @@ int
ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
struct mbuf **mp)
{
- struct ah_new_xdata *xd;
+ struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
struct ip *ip, ipo;
struct ah_new aho, *ah;
- register int len, off, count;
- register struct mbuf *m0;
+ register int len, off, count, ilen;
union {
MD5_CTX md5ctx;
SHA1_CTX sha1ctx;
RMD160_CTX rmd160ctx;
} ctx;
- int ilen, ohlen;
u_int8_t optval;
- u_char buffer[AH_ALEN_MAX], opts[40];
+ u_char opts[40];
ahstat.ahs_output++;
m = m_pullup(m, sizeof(struct ip));
if (m == NULL)
{
- DPRINTF(("ah_new_output(): m_pullup() failed, SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_new_output(): m_pullup() failed, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
return ENOBUFS;
}
ip = mtod(m, struct ip *);
- xd = (struct ah_new_xdata *) tdb->tdb_xdata;
-
if ((ip->ip_hl << 2) > sizeof(struct ip))
{
if ((m = m_pullup(m, ip->ip_hl << 2)) == NULL)
{
- DPRINTF(("ah_new_output(): m_pullup() failed, SA &x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_new_output(): m_pullup() failed, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst),
+ ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
return ENOBUFS;
}
@@ -578,18 +488,44 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
ip = mtod(m, struct ip *);
}
+ /* Update the counters */
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
+ ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
+
+ /* Hard expiration */
+ if ((tdb->tdb_flags & TDBF_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ tdb_delete(tdb, 0);
+ m_freem(m);
+ return EINVAL;
+ }
+
+ /* Notify on expiration */
+ if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
+ }
+
/* Save options */
m_copydata(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),
(caddr_t) opts);
- DPRINTF(("ah_new_output(): using hash algorithm %s\n", xd->amx_hash->name));
+ DPRINTF(("ah_new_output(): using hash algorithm %s\n", ahx->name));
ilen = ntohs(ip->ip_len);
- ohlen = AH_NEW_FLENGTH;
- if (ohlen + ilen > IP_MAXPACKET) {
- DPRINTF(("ah_new_output(): packet in SA %x/%0x8 got too big\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ if (AH_NEW_FLENGTH + ilen > IP_MAXPACKET)
+ {
+ DPRINTF(("ah_new_output(): packet in SA %s/%08x got too big\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
ahstat.ahs_toobig++;
return EMSGSIZE;
@@ -598,7 +534,7 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
ipo.ip_v = IPVERSION;
ipo.ip_hl = ip->ip_hl;
ipo.ip_tos = 0;
- ipo.ip_len = htons(ohlen + ilen);
+ ipo.ip_len = htons(AH_NEW_FLENGTH + ilen);
ipo.ip_id = ip->ip_id;
ipo.ip_off = 0;
ipo.ip_ttl = 0;
@@ -614,19 +550,19 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
aho.ah_rv = 0;
aho.ah_spi = tdb->tdb_spi;
- if (xd->amx_rpl == 0)
+ if (tdb->tdb_rpl == 0)
{
- DPRINTF(("ah_new_output(): SA %x/%0x8 should have expired\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_new_output(): SA %s/%08x should have expired\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
ahstat.ahs_wrap++;
return NULL;
}
- aho.ah_rpl = htonl(xd->amx_rpl++);
+ aho.ah_rpl = htonl(tdb->tdb_rpl++);
- bcopy((caddr_t)&(xd->amx_ictx), (caddr_t)&ctx, xd->amx_hash->ctxsize);
- xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
+ bcopy(tdb->tdb_ictx, (caddr_t)&ctx, ahx->ctxsize);
+ ahx->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
/* Options */
if ((ip->ip_hl << 2) > sizeof(struct ip))
@@ -636,13 +572,13 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
switch (optval)
{
case IPOPT_EOL:
- xd->amx_hash->Update(&ctx, ipseczeroes, 1);
+ ahx->Update(&ctx, ipseczeroes, 1);
off = ip->ip_hl << 2;
break;
case IPOPT_NOP:
- xd->amx_hash->Update(&ctx, ipseczeroes, 1);
+ ahx->Update(&ctx, ipseczeroes, 1);
off++;
break;
@@ -652,7 +588,7 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
case 134:
optval = ((u_int8_t *) ip)[off + 1];
- xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval);
+ ahx->Update(&ctx, (u_int8_t *) ip + off, optval);
off += optval;
break;
@@ -660,14 +596,14 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
default:
optval = ((u_int8_t *) ip)[off + 1];
- xd->amx_hash->Update(&ctx, ipseczeroes, optval);
+ ahx->Update(&ctx, ipseczeroes, optval);
off += optval;
break;
}
}
- xd->amx_hash->Update(&ctx, (unsigned char *) &aho, AH_NEW_FLENGTH);
+ ahx->Update(&ctx, (unsigned char *) &aho, AH_NEW_FLENGTH);
off = ip->ip_hl << 2;
@@ -676,44 +612,46 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
*/
len = m->m_pkthdr.len - off;
- m0 = m;
+ *mp = m;
while (len > 0)
{
- if (m0 == 0)
+ if ((*mp) == 0)
{
- DPRINTF(("ah_new_output(): bad mbuf chain for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_new_output(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return EMSGSIZE;
}
- count = min(m0->m_len - off, len);
+ count = min((*mp)->m_len - off, len);
- xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count);
+ ahx->Update(&ctx, mtod(*mp, unsigned char *) + off, count);
len -= count;
off = 0;
- m0 = m0->m_next;
+ *mp = (*mp)->m_next;
}
+ *mp = NULL;
+
ipo.ip_tos = ip->ip_tos;
ipo.ip_id = ip->ip_id;
ipo.ip_off = ip->ip_off;
ipo.ip_ttl = ip->ip_ttl;
/* ipo.ip_len = ntohs(ipo.ip_len); */
- M_PREPEND(m, ohlen, M_DONTWAIT);
+ M_PREPEND(m, AH_NEW_FLENGTH, M_DONTWAIT);
if (m == NULL)
{
- DPRINTF(("ah_new_output(): M_PREPEND() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_new_output(): M_PREPEND() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
return ENOBUFS;
}
- m = m_pullup(m, ohlen + (ipo.ip_hl << 2));
+ m = m_pullup(m, AH_NEW_FLENGTH + (ipo.ip_hl << 2));
if (m == NULL)
{
- DPRINTF(("ah_new_output(): m_pullup() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_new_output(): 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)));
ahstat.ahs_hdrops++;
return ENOBUFS;
}
@@ -727,58 +665,19 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
ah->ah_spi = aho.ah_spi;
ah->ah_rpl = aho.ah_rpl;
- xd->amx_hash->Final(buffer, &ctx);
- bcopy(&(xd->amx_octx), &ctx, xd->amx_hash->ctxsize);
- xd->amx_hash->Update(&ctx, buffer, xd->amx_hash->hashsize);
- xd->amx_hash->Final(buffer, &ctx);
-
/* Restore the options */
- m_copyback(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),
- (caddr_t) opts);
+ bcopy(opts, (caddr_t) (ip + 1), (ip->ip_hl << 2) - sizeof(struct ip));
+
+ /* Finish computing the authenticator */
+ ahx->Final(opts, &ctx);
+ bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize);
+ ahx->Update(&ctx, opts, ahx->hashsize);
+ ahx->Final(opts, &ctx);
/* Copy the authenticator */
- bcopy(buffer, ah->ah_data, AH_HMAC_HASHLEN);
+ bcopy(opts, ah->ah_data, AH_HMAC_HASHLEN);
*mp = m;
- /* Update the counters */
- tdb->tdb_cur_packets++;
- tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) -
- AH_NEW_FLENGTH;
- ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) - AH_NEW_FLENGTH;
-
- /* Notify on expiration */
- if (tdb->tdb_flags & TDBF_SOFT_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_PACKETS;
- }
- else
- if (tdb->tdb_flags & TDBF_SOFT_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
- }
- }
-
- if (tdb->tdb_flags & TDBF_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- else
- if (tdb->tdb_flags & TDBF_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- }
-
return 0;
}
diff --git a/sys/netinet/ip_ah_old.c b/sys/netinet/ip_ah_old.c
index 23ea072b899..4102de90b94 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.18 1999/01/11 22:52:09 deraadt Exp $ */
+/* $OpenBSD: ip_ah_old.c,v 1.19 1999/02/24 22:33:00 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -64,10 +64,10 @@
#include <sys/socketvar.h>
#include <net/raw_cb.h>
-#include <net/encap.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_ah.h>
+#include <net/pfkeyv2.h>
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
@@ -75,18 +75,16 @@
#define DPRINTF(x)
#endif
-extern void encap_sendnotify(int, struct tdb *, void *);
-
-struct ah_hash ah_old_hash[] = {
- { ALG_AUTH_MD5, "Keyed MD5",
- AH_MD5_ALEN,
+struct auth_hash ah_old_hash[] = {
+ { SADB_AALG_X_MD5, "Keyed MD5",
+ 0, AH_MD5_ALEN,
sizeof(MD5_CTX),
(void (*)(void *))MD5Init,
(void (*)(void *, u_int8_t *, u_int16_t))MD5Update,
(void (*)(u_int8_t *, void *))MD5Final
},
- { ALG_AUTH_SHA1, "Keyed SHA1",
- AH_SHA1_ALEN,
+ { SADB_AALG_X_SHA1, "Keyed SHA1",
+ 0, AH_SHA1_ALEN,
sizeof(SHA1_CTX),
(void (*)(void *))SHA1Init,
(void (*)(void *, u_int8_t *, u_int16_t))SHA1Update,
@@ -101,93 +99,49 @@ struct ah_hash ah_old_hash[] = {
int
ah_old_attach()
{
- DPRINTF(("ah_old_attach(): setting up\n"));
return 0;
}
/*
- * ah_old_init() is called when an SPI is being set up. It interprets the
- * encap_msghdr present in m, and sets up the transformation data.
+ * ah_old_init() is called when an SPI is being set up.
*/
int
-ah_old_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
+ah_old_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
- struct ah_old_xencap xenc;
- struct ah_old_xdata *xd;
- struct encap_msghdr *em;
- struct ah_hash *thash;
+ struct auth_hash *thash = NULL;
int i;
- if (m->m_len < ENCAP_MSG_FIXED_LEN)
- {
- if ((m = m_pullup(m, ENCAP_MSG_FIXED_LEN)) == NULL)
- {
- DPRINTF(("ah_old_init(): m_pullup failed\n"));
- return ENOBUFS;
- }
- }
-
- em = mtod(m, struct encap_msghdr *);
- if (em->em_msglen - EMT_SETSPI_FLEN <= AH_OLD_XENCAP_LEN)
- {
- DPRINTF(("ah_old_init(): initialization failed\n"));
- return EINVAL;
- }
-
- /* Just copy the standard fields */
- m_copydata(m, EMT_SETSPI_FLEN, AH_OLD_XENCAP_LEN, (caddr_t) &xenc);
-
/* Check whether the hash algorithm is supported */
- for (i=sizeof(ah_old_hash)/sizeof(struct ah_hash)-1; i >= 0; i--)
- if (xenc.amx_hash_algorithm == ah_old_hash[i].type)
+ for (i = sizeof(ah_old_hash) / sizeof(struct auth_hash) - 1; i >= 0; i--)
+ if (ii->ii_authalg == ah_old_hash[i].type)
break;
+
if (i < 0)
{
- DPRINTF(("ah_old_init(): unsupported authentication algorithm %d specified\n", xenc.amx_hash_algorithm));
- m_freem(m);
+ DPRINTF(("ah_old_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
return EINVAL;
}
- DPRINTF(("ah_old_init(): initalized TDB with hash algorithm %d: %s\n",
- xenc.amx_hash_algorithm, ah_old_hash[i].name));
thash = &ah_old_hash[i];
- if (xenc.amx_keylen + EMT_SETSPI_FLEN + AH_OLD_XENCAP_LEN != em->em_msglen)
- {
- DPRINTF(("ah_old_init(): message length (%d) doesn't match\n",
- em->em_msglen));
- return EINVAL;
- }
-
- MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct ah_old_xdata) +
- xenc.amx_keylen, M_XDATA, M_WAITOK);
- if (tdbp->tdb_xdata == NULL)
- {
- DPRINTF(("ah_old_init(): MALLOC() failed\n"));
- return ENOBUFS;
- }
-
- bzero(tdbp->tdb_xdata, sizeof(struct ah_old_xdata) + xenc.amx_keylen);
- xd = (struct ah_old_xdata *) tdbp->tdb_xdata;
+ DPRINTF(("ah_old_init(): initalized TDB with hash algorithm %s\n",
+ thash->name));
- /* Pointer to the transform */
tdbp->tdb_xform = xsp;
+ tdbp->tdb_authalgxform = thash;
- xd->amx_keylen = xenc.amx_keylen;
- xd->amx_hash_algorithm = xenc.amx_hash_algorithm;
- xd->amx_hash = thash;
-
- /* Pass name of auth algorithm for kernfs */
- tdbp->tdb_authname = xd->amx_hash->name;
+ tdbp->tdb_amxkeylen = ii->ii_authkeylen;
+ MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen,
+ M_XDATA, M_WAITOK);
- /* Copy the key material */
- m_copydata(m, EMT_SETSPI_FLEN + AH_OLD_XENCAP_LEN, xd->amx_keylen,
- (caddr_t) xd->amx_key);
+ bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
- xd->amx_hash->Init(&(xd->amx_ctx));
- xd->amx_hash->Update(&(xd->amx_ctx), xd->amx_key, xd->amx_keylen);
- xd->amx_hash->Final(NULL, &(xd->amx_ctx));
+ MALLOC(tdbp->tdb_ictx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_ictx, thash->ctxsize);
+ thash->Init(tdbp->tdb_ictx);
+ thash->Update(tdbp->tdb_ictx, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+ thash->Final(NULL, tdbp->tdb_ictx);
bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */
@@ -201,12 +155,18 @@ ah_old_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
int
ah_old_zeroize(struct tdb *tdbp)
{
- DPRINTF(("ah_old_zeroize(): freeing memory\n"));
- if (tdbp->tdb_xdata)
+ if (tdbp->tdb_amxkey)
+ {
+ FREE(tdbp->tdb_amxkey, M_XDATA);
+ tdbp->tdb_amxkey = NULL;
+ }
+
+ if (tdbp->tdb_ictx)
{
- FREE(tdbp->tdb_xdata, M_XDATA);
- tdbp->tdb_xdata = NULL;
+ FREE(tdbp->tdb_ictx, M_XDATA);
+ tdbp->tdb_ictx = NULL;
}
+
return 0;
}
@@ -218,7 +178,7 @@ ah_old_zeroize(struct tdb *tdbp)
struct mbuf *
ah_old_input(struct mbuf *m, struct tdb *tdb)
{
- struct ah_old_xdata *xd;
+ struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
struct ip *ip, ipo;
struct ah_old *ah, *aho;
int ohlen, len, count, off, alen;
@@ -231,11 +191,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
u_char buffer[40];
aho = (struct ah_old *) buffer;
-
- xd = (struct ah_old_xdata *) tdb->tdb_xdata;
-
- alen = xd->amx_hash->hashsize;
-
+ alen = ahx->hashsize;
ohlen = sizeof(struct ip) + AH_OLD_FLENGTH + alen;
if (m->m_len < ohlen)
@@ -267,6 +223,32 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
else
ah = (struct ah_old *) (ip + 1);
+ /* Update the counters */
+ tdb->tdb_cur_bytes += ip->ip_len - (ip->ip_hl << 2);
+ ahstat.ahs_ibytes += ip->ip_len - (ip->ip_hl << 2);
+
+ /* Hard expiration */
+ if ((tdb->tdb_flags & TDBF_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ m_freem(m);
+ tdb_delete(tdb, 0);
+ return NULL;
+ }
+
+ /* Notify on expiration */
+ if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
+ }
+
ipo = *ip;
ipo.ip_tos = 0;
ipo.ip_len += (ip->ip_hl << 2); /* adjusted in ip_intr() */
@@ -276,8 +258,8 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
ipo.ip_ttl = 0;
ipo.ip_sum = 0;
- bcopy(&(xd->amx_ctx), &ctx, xd->amx_hash->ctxsize);
- xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
+ bcopy(tdb->tdb_ictx, &ctx, ahx->ctxsize);
+ ahx->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
/* Options */
if ((ip->ip_hl << 2) > sizeof(struct ip))
@@ -287,13 +269,13 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
switch (optval)
{
case IPOPT_EOL:
- xd->amx_hash->Update(&ctx, ipseczeroes, 1);
+ ahx->Update(&ctx, ipseczeroes, 1);
off = ip->ip_hl << 2;
break;
case IPOPT_NOP:
- xd->amx_hash->Update(&ctx, ipseczeroes, 1);
+ ahx->Update(&ctx, ipseczeroes, 1);
off++;
break;
@@ -303,7 +285,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
case 134:
optval = ((u_int8_t *) ip)[off + 1];
- xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval);
+ ahx->Update(&ctx, (u_int8_t *) ip + off, optval);
off += optval;
break;
@@ -311,7 +293,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
default:
optval = ((u_int8_t *) ip)[off + 1];
- xd->amx_hash->Update(&ctx, ipseczeroes, optval);
+ ahx->Update(&ctx, ipseczeroes, optval);
off += optval;
break;
@@ -319,8 +301,8 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
}
- xd->amx_hash->Update(&ctx, (unsigned char *) ah, AH_OLD_FLENGTH);
- xd->amx_hash->Update(&ctx, ipseczeroes, alen);
+ ahx->Update(&ctx, (unsigned char *) ah, AH_OLD_FLENGTH);
+ ahx->Update(&ctx, ipseczeroes, alen);
/*
* Code shamelessly stolen from m_copydata
@@ -333,7 +315,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
{
if (m0 == 0)
{
- DPRINTF(("ah_old_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_old_input(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
@@ -350,7 +332,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
{
if (m0 == 0)
{
- DPRINTF(("ah_old_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_old_input(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
@@ -358,15 +340,15 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
count = min(m0->m_len - off, len);
- xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count);
+ ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count);
len -= count;
off = 0;
m0 = m0->m_next;
}
- xd->amx_hash->Update(&ctx, (unsigned char *) xd->amx_key, xd->amx_keylen);
- xd->amx_hash->Final((unsigned char *) (aho->ah_data), &ctx);
+ ahx->Update(&ctx, (unsigned char *) tdb->tdb_amxkey, tdb->tdb_amxkeylen);
+ ahx->Final((unsigned char *) (aho->ah_data), &ctx);
if (bcmp(aho->ah_data, ah->ah_data, alen))
{
@@ -399,44 +381,6 @@ ah_old_input(struct mbuf *m, struct tdb *tdb)
ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));
- /* Update the counters */
- tdb->tdb_cur_packets++;
- tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
- ahstat.ahs_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
-
- /* Notify on expiration */
- if (tdb->tdb_flags & TDBF_SOFT_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_PACKETS;
- }
- else
- if (tdb->tdb_flags & TDBF_SOFT_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
- }
- }
-
- if (tdb->tdb_flags & TDBF_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- else
- if (tdb->tdb_flags & TDBF_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- }
-
return m;
}
@@ -444,7 +388,7 @@ int
ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
struct mbuf **mp)
{
- struct ah_old_xdata *xd;
+ struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
struct ip *ip, ipo;
struct ah_old *ah, aho;
register int len, off, count;
@@ -457,26 +401,55 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
u_int8_t optval;
u_char opts[40];
+ alen = ahx->hashsize;
+
ahstat.ahs_output++;
m = m_pullup(m, sizeof(struct ip));
if (m == NULL)
{
- DPRINTF(("ah_old_output(): m_pullup() failed, SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_old_output(): m_pullup() failed, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
return ENOBUFS;
}
ip = mtod(m, struct ip *);
- xd = (struct ah_old_xdata *) tdb->tdb_xdata;
+ /* Update the counters */
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) -
+ AH_OLD_FLENGTH - alen;
+ ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) -
+ AH_OLD_FLENGTH - alen;
+
+ /* Hard expiration */
+ if ((tdb->tdb_flags & TDBF_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ tdb_delete(tdb, 0);
+ m_freem(m);
+ return EINVAL;
+ }
+
+ /* Notify on expiration */
+ if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
+ }
if ((ip->ip_hl << 2) > sizeof(struct ip))
{
if ((m = m_pullup(m, ip->ip_hl << 2)) == NULL)
{
- DPRINTF(("ah_old_output(): m_pullup() failed, SA &x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_old_output(): m_pullup() failed, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst),
+ ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
return ENOBUFS;
}
@@ -484,8 +457,6 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
ip = mtod(m, struct ip *);
}
- alen = xd->amx_hash->hashsize;
-
/* Save the options */
m_copydata(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),
(caddr_t) opts);
@@ -493,9 +464,10 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
ilen = ntohs(ip->ip_len);
ohlen = AH_OLD_FLENGTH + alen;
- if (ohlen + ilen > IP_MAXPACKET) {
- DPRINTF(("ah_old_output(): packet in SA %x/%0x8 got too big\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ if (ohlen + ilen > IP_MAXPACKET)
+ {
+ DPRINTF(("ah_old_output(): packet in SA %s/%0x8 got too big\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
ahstat.ahs_toobig++;
return EMSGSIZE;
@@ -518,8 +490,8 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
aho.ah_rv = 0;
aho.ah_spi = tdb->tdb_spi;
- bcopy(&(xd->amx_ctx), &ctx, xd->amx_hash->ctxsize);
- xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
+ bcopy(tdb->tdb_ictx, &ctx, ahx->ctxsize);
+ ahx->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
/* Options */
if ((ip->ip_hl << 2) > sizeof(struct ip))
@@ -529,13 +501,13 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
switch (optval)
{
case IPOPT_EOL:
- xd->amx_hash->Update(&ctx, ipseczeroes, 1);
+ ahx->Update(&ctx, ipseczeroes, 1);
off = ip->ip_hl << 2;
break;
case IPOPT_NOP:
- xd->amx_hash->Update(&ctx, ipseczeroes, 1);
+ ahx->Update(&ctx, ipseczeroes, 1);
off++;
break;
@@ -545,7 +517,7 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
case 134:
optval = ((u_int8_t *) ip)[off + 1];
- xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval);
+ ahx->Update(&ctx, (u_int8_t *) ip + off, optval);
off += optval;
break;
@@ -553,15 +525,15 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
default:
optval = ((u_int8_t *) ip)[off + 1];
- xd->amx_hash->Update(&ctx, ipseczeroes, optval);
+ ahx->Update(&ctx, ipseczeroes, optval);
off += optval;
break;
}
}
- xd->amx_hash->Update(&ctx, (unsigned char *) &aho, AH_OLD_FLENGTH);
- xd->amx_hash->Update(&ctx, ipseczeroes, alen);
+ ahx->Update(&ctx, (unsigned char *) &aho, AH_OLD_FLENGTH);
+ ahx->Update(&ctx, ipseczeroes, alen);
/* Skip the IP header and any options */
off = ip->ip_hl << 2;
@@ -577,21 +549,21 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
{
if (m0 == 0)
{
- DPRINTF(("ah_old_output(): M_PREPEND() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_old_output(): M_PREPEND() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
return NULL;
}
count = min(m0->m_len - off, len);
- xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count);
+ ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count);
len -= count;
off = 0;
m0 = m0->m_next;
}
- xd->amx_hash->Update(&ctx, (unsigned char *) xd->amx_key, xd->amx_keylen);
+ ahx->Update(&ctx, (unsigned char *) tdb->tdb_amxkey, tdb->tdb_amxkeylen);
ipo.ip_tos = ip->ip_tos;
ipo.ip_id = ip->ip_id;
@@ -602,14 +574,14 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
M_PREPEND(m, ohlen, M_DONTWAIT);
if (m == NULL)
{
- DPRINTF(("ah_old_output(): M_PREPEND() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_old_output(): M_PREPEND() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
return ENOBUFS;
}
m = m_pullup(m, ohlen + (ipo.ip_hl << 2));
if (m == NULL)
{
- DPRINTF(("ah_old_output(): m_pullup() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_old_output(): 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)));
ahstat.ahs_hdrops++;
return ENOBUFS;
}
@@ -626,49 +598,9 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
m_copyback(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),
(caddr_t) opts);
- xd->amx_hash->Final(ah->ah_data, &ctx);
+ ahx->Final(ah->ah_data, &ctx);
*mp = m;
- /* Update the counters */
- tdb->tdb_cur_packets++;
- tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) -
- AH_OLD_FLENGTH - alen;
- ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) -
- AH_OLD_FLENGTH - alen;
-
- /* Notify on expiration */
- if (tdb->tdb_flags & TDBF_SOFT_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_PACKETS;
- }
- else
- if (tdb->tdb_flags & TDBF_SOFT_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
- }
- }
-
- if (tdb->tdb_flags & TDBF_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- else
- if (tdb->tdb_flags & TDBF_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- }
-
return 0;
}
diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c
index dcc6d0c9ad5..66189caa2bb 100644
--- a/sys/netinet/ip_esp.c
+++ b/sys/netinet/ip_esp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.c,v 1.16 1998/06/10 23:57:14 provos Exp $ */
+/* $OpenBSD: ip_esp.c,v 1.17 1999/02/24 22:33:01 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -65,16 +65,22 @@
#include <sys/socketvar.h>
#include <net/raw_cb.h>
-#include <net/encap.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_esp.h>
-#include <sys/syslog.h>
#include "bpfilter.h"
-void esp_input __P((struct mbuf *, int));
+extern struct ifnet enc_softc;
+
+#ifdef ENCDEBUG
+#define DPRINTF(x) if (encdebug) printf x
+#else
+#define DPRINTF(x)
+#endif
+
+void esp_input __P((struct mbuf *, int));
/*
* esp_input gets called when we receive an packet with an ESP.
@@ -83,6 +89,7 @@ void esp_input __P((struct mbuf *, int));
void
esp_input(register struct mbuf *m, int iphlen)
{
+ union sockaddr_union sunion;
struct ifqueue *ifq = NULL;
struct expiration *exp;
struct ip *ipo, ipn;
@@ -101,10 +108,6 @@ esp_input(register struct mbuf *m, int iphlen)
{
if ((m = m_pullup(m, iphlen + sizeof(u_int32_t))) == 0)
{
-#ifdef ENCDEBUG
- if (encdebug)
- printf("esp_input(): (possibly too short) packet from %x to %x dropped\n", ipo->ip_src, ipo->ip_dst);
-#endif /* ENCDEBUG */
espstat.esps_hdrops++;
return;
}
@@ -120,11 +123,14 @@ esp_input(register struct mbuf *m, int iphlen)
* IP packet ready to go through input processing.
*/
- tdbp = gettdb(spi, ipo->ip_dst, IPPROTO_ESP);
+ bzero(&sunion, sizeof(sunion));
+ sunion.sin.sin_family = AF_INET;
+ sunion.sin.sin_len = sizeof(struct sockaddr_in);
+ sunion.sin.sin_addr = ipo->ip_dst;
+ tdbp = gettdb(spi, &sunion, IPPROTO_ESP);
if (tdbp == NULL)
{
- if (encdebug)
- log(LOG_ERR, "esp_input(): could not find SA for ESP packet from %x to %x, spi %08x\n", ipo->ip_src, ipo->ip_dst, ntohl(spi));
+ DPRINTF(("esp_input(): could not find SA for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(sunion), ntohl(spi)));
m_freem(m);
espstat.esps_notdb++;
return;
@@ -132,8 +138,7 @@ esp_input(register struct mbuf *m, int iphlen)
if (tdbp->tdb_flags & TDBF_INVALID)
{
- if (encdebug)
- log(LOG_ALERT, "esp_input(): attempted to use invalid ESP SA %08x, packet %x->%x\n", ntohl(spi), ipo->ip_src, ipo->ip_dst);
+ DPRINTF(("esp_input(): attempted to use invalid SA %08x, packet from %s to %s\n", ntohl(spi), inet_ntoa4(ipo->ip_src), ipsp_address(sunion)));
m_freem(m);
espstat.esps_invalid++;
return;
@@ -141,8 +146,7 @@ esp_input(register struct mbuf *m, int iphlen)
if (tdbp->tdb_xform == NULL)
{
- if (encdebug)
- log(LOG_ALERT, "esp_input(): attempted to use uninitialized ESP SA %08x, packet from %x to %x\n", ntohl(spi), ipo->ip_src, ipo->ip_dst);
+ DPRINTF(("esp_input(): attempted to use uninitialized SA %08x, packet from %s to %s\n", ntohl(spi), inet_ntoa4(ipo->ip_src), ipsp_address(sunion)));
m_freem(m);
espstat.esps_noxform++;
return;
@@ -158,21 +162,10 @@ esp_input(register struct mbuf *m, int iphlen)
if (tdbp->tdb_flags & TDBF_FIRSTUSE)
{
exp = get_expiration();
- if (exp == (struct expiration *) NULL)
- {
- if (encdebug)
- log(LOG_WARNING,
- "esp_input(): out of memory for expiration timer\n");
- espstat.esps_hdrops++;
- m_freem(m);
- return;
- }
-
- exp->exp_dst.s_addr = tdbp->tdb_dst.s_addr;
+ bcopy(&tdbp->tdb_dst, &exp->exp_dst, SA_LEN(&tdbp->tdb_dst.sa));
exp->exp_spi = tdbp->tdb_spi;
exp->exp_sproto = tdbp->tdb_sproto;
exp->exp_timeout = tdbp->tdb_first_use + tdbp->tdb_exp_first_use;
-
put_expiration(exp);
}
@@ -180,21 +173,10 @@ esp_input(register struct mbuf *m, int iphlen)
(tdbp->tdb_soft_first_use <= tdbp->tdb_exp_first_use))
{
exp = get_expiration();
- if (exp == (struct expiration *) NULL)
- {
- if (encdebug)
- log(LOG_WARNING,
- "esp_input(): out of memory for expiration timer\n");
- espstat.esps_hdrops++;
- m_freem(m);
- return;
- }
-
- exp->exp_dst.s_addr = tdbp->tdb_dst.s_addr;
+ bcopy(&tdbp->tdb_dst, &exp->exp_dst, SA_LEN(&tdbp->tdb_dst.sa));
exp->exp_spi = tdbp->tdb_spi;
exp->exp_sproto = tdbp->tdb_sproto;
exp->exp_timeout = tdbp->tdb_first_use + tdbp->tdb_soft_first_use;
-
put_expiration(exp);
}
}
@@ -205,8 +187,7 @@ esp_input(register struct mbuf *m, int iphlen)
if (m == NULL)
{
- if (encdebug)
- log(LOG_ALERT, "esp_input(): processing failed for ESP packet from %x to %x, spi %08x\n", ipn.ip_src, ipn.ip_dst, ntohl(spi));
+ DPRINTF(("esp_input(): processing failed for ESP packet from %s to %s, spi %08x\n", inet_ntoa4(ipn.ip_src), ipsp_address(sunion), ntohl(spi)));
espstat.esps_badkcr++;
return;
}
@@ -217,30 +198,25 @@ esp_input(register struct mbuf *m, int iphlen)
/* ipn will now contain the inner IP header */
m_copydata(m, ipo->ip_hl << 2, sizeof(struct ip), (caddr_t) &ipn);
- /* Encapsulating SPI */
- if (tdbp->tdb_osrc.s_addr && tdbp->tdb_odst.s_addr)
+ if (tdbp->tdb_flags & TDBF_UNIQUE)
+ if ((ipn.ip_src.s_addr != ipo->ip_src.s_addr) ||
+ (ipn.ip_dst.s_addr != ipo->ip_dst.s_addr))
+ {
+ DPRINTF(("esp_input(): ESP-tunnel with different internal addresses %s->%s (%s->%s), SA %s/%08x\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipn.ip_src), ipsp_address(sunion), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi)));
+ m_freem(m);
+ espstat.esps_hdrops++;
+ return;
+ }
+
+ /*
+ * Check that the inner source address is the same as
+ * the proxy address, if available.
+ */
+ if ((tdbp->tdb_proxy.sin.sin_addr.s_addr != INADDR_ANY) &&
+ (ipn.ip_src.s_addr != tdbp->tdb_proxy.sin.sin_addr.s_addr))
{
- if (tdbp->tdb_flags & TDBF_UNIQUE)
- if ((ipn.ip_src.s_addr != ipo->ip_src.s_addr) ||
- (ipn.ip_dst.s_addr != ipo->ip_dst.s_addr))
- {
- if (encdebug)
- log(LOG_ALERT, "esp_input(): ESP-tunnel with different internal addresses %x/%x, SA %08x/%x\n", ipo->ip_src, ipo->ip_dst, tdbp->tdb_spi, tdbp->tdb_dst);
- m_freem(m);
- espstat.esps_hdrops++;
- return;
- }
-
- /*
- * XXX Here we should be checking that the inner IP addresses
- * XXX are acceptable/authorized.
- */
- }
- else /* So we're paranoid */
- {
- if (encdebug)
- log(LOG_ALERT, "esp_input(): ESP-tunnel used when expecting ESP-transport, SA %08x/%x\n", tdbp->tdb_spi, tdbp->tdb_dst);
- m_freem(m);
+ DPRINTF(("esp_input(): inner source address %s doesn't correspond to expected proxy source %s, SA %s/%08x\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(tdbp->tdb_proxy.sin.sin_addr), inet_ntoa4(tdbp->tdb_dst.sin.sin_addr), ntohl(tdbp->tdb_spi)));
+ m_free(m);
espstat.esps_hdrops++;
return;
}
@@ -250,15 +226,14 @@ esp_input(register struct mbuf *m, int iphlen)
* Check that the source address is an expected one, if we know what
* it's supposed to be. This avoids source address spoofing.
*/
- if (tdbp->tdb_src.s_addr != INADDR_ANY)
- if (ipo->ip_src.s_addr != tdbp->tdb_src.s_addr)
- {
- if (encdebug)
- log(LOG_ALERT, "esp_input(): source address %x doesn't correspond to expected source %x, SA %08x/%x\n", ipo->ip_src, tdbp->tdb_src, tdbp->tdb_dst, tdbp->tdb_spi);
- m_free(m);
- espstat.esps_hdrops++;
- return;
- }
+ if ((tdbp->tdb_src.sin.sin_addr.s_addr != INADDR_ANY) &&
+ (ipo->ip_src.s_addr != tdbp->tdb_src.sin.sin_addr.s_addr))
+ {
+ DPRINTF(("esp_input(): source address %s doesn't correspond to expected source %s, SA %s/%08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(tdbp->tdb_src), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi)));
+ m_free(m);
+ espstat.esps_hdrops++;
+ return;
+ }
/* Packet is confidental */
m->m_flags |= M_CONF;
@@ -278,7 +253,7 @@ esp_input(register struct mbuf *m, int iphlen)
hdr.af = AF_INET;
hdr.spi = tdbp->tdb_spi;
- hdr.flags = m->m_flags & (M_AUTH|M_CONF|M_TUNNEL);
+ hdr.flags = m->m_flags & (M_AUTH|M_CONF);
m0.m_next = m;
m0.m_len = ENC_HDRLEN;
@@ -302,10 +277,7 @@ esp_input(register struct mbuf *m, int iphlen)
m_freem(m);
espstat.esps_qfull++;
splx(s);
-#ifdef ENCDEBUG
- if (encdebug)
- printf("esp_input(): dropped packet because of full IP queue\n");
-#endif /* ENCDEBUG */
+ DPRINTF(("esp_input(): dropped packet because of full IP queue\n"));
return;
}
diff --git a/sys/netinet/ip_esp.h b/sys/netinet/ip_esp.h
index ccbc83cb730..b1f7af1a8d7 100644
--- a/sys/netinet/ip_esp.h
+++ b/sys/netinet/ip_esp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.h,v 1.20 1999/02/17 20:39:17 deraadt Exp $ */
+/* $OpenBSD: ip_esp.h,v 1.21 1999/02/24 22:33:01 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -38,181 +38,44 @@
* Per RFC1827 (Atkinson, 1995)
*/
-#ifndef _MD5_H_
-#include <sys/md5k.h>
-#endif
-
-#include <netinet/ip_sha1.h>
-#include <netinet/ip_rmd160.h>
-#include <netinet/ip_blf.h>
-#include <netinet/ip_cast.h>
-#include <netinet/ip_skipjack.h>
-
-/* IV lengths */
-#define ESP_DES_IVS 8
-#define ESP_3DES_IVS 8
-#define ESP_BLF_IVS 8
-#define ESP_CAST_IVS 8
-#define ESP_SKIPJACK_IVS 8
-
-#define ESP_MAX_IVS ESP_3DES_IVS
-
-/* Block sizes -- it is assumed that they're powers of 2 */
-#define ESP_DES_BLKS 8
-#define ESP_3DES_BLKS 8
-#define ESP_BLF_BLKS 8
-#define ESP_CAST_BLKS 8
-#define ESP_SKIPJACK_BLKS 8
-
-#define ESP_MAX_BLKS ESP_3DES_BLKS
-
/* Various defines for the "new" ESP */
#define ESP_NEW_ALEN 12 /* 96bits authenticator */
-#define ESP_NEW_IPAD_VAL 0x36
-#define ESP_NEW_OPAD_VAL 0x5C
-
-struct esp_hash {
- int type;
- char *name;
- u_int16_t hashsize;
- u_int16_t ctxsize;
- void (*Init) __P((void *));
- void (*Update) __P((void *, u_int8_t *, u_int16_t));
- void (*Final) __P((u_int8_t *, void *));
-};
-
-struct esp_xform {
- int type;
- char *name;
- u_int16_t blocksize, ivsize;
- u_int16_t minkey, maxkey;
- u_int32_t ivmask; /* Or all possible modes, zero iv = 1 */
- void (*encrypt) __P((void *, u_int8_t *));
- void (*decrypt) __P((void *, u_int8_t *));
-};
-
-struct esp_old {
- u_int32_t esp_spi; /* Security Parameters Index */
- u_int8_t esp_iv[8]; /* iv[4] may actually be data! */
-};
-
-struct esp_new {
- u_int32_t esp_spi; /* Security Parameter Index */
- u_int32_t esp_rpl; /* Sequence Number, Replay Counter */
- u_int8_t esp_iv[8]; /* Data may start already at iv[0]! */
-};
-struct espstat {
- u_int32_t esps_hdrops; /* packet shorter than header shows */
- u_int32_t esps_notdb;
- u_int32_t esps_badkcr;
- u_int32_t esps_qfull;
- u_int32_t esps_noxform;
- u_int32_t esps_badilen;
- u_int32_t esps_wrap; /* Replay counter wrapped around */
- u_int32_t esps_badauth; /* Only valid for transforms with auth */
- u_int32_t esps_replay; /* Possible packet replay detected */
- u_int32_t esps_input; /* Input ESP packets */
- u_int32_t esps_output; /* Output ESP packets */
- u_int32_t esps_invalid; /* Trying to use an invalid TDB */
- u_int64_t esps_ibytes; /* input bytes */
- u_int64_t esps_obytes; /* output bytes */
- u_int32_t esps_toobig; /* packet got larger than IP_MAXPACKET */
+struct esp_old
+{
+ u_int32_t esp_spi; /* Security Parameters Index */
+ u_int8_t esp_iv[8]; /* iv[4] may actually be data! */
};
-struct esp_old_xdata {
- u_int32_t edx_enc_algorithm;
- int32_t edx_ivlen; /* 4 or 8 */
- struct esp_xform *edx_xform;
- union {
- u_int8_t Iv[ESP_3DES_IVS]; /* that's enough space */
- u_int32_t Ivl; /* make sure this is 4 bytes */
- u_int64_t Ivq; /* make sure this is 8 bytes! */
- } Iu;
-#define edx_iv Iu.Iv
-#define edx_ivl Iu.Ivl
-#define edx_ivq Iu.Ivq
- union {
- u_int8_t Rk[3][8];
- u_int32_t Eks[3][16][2];
- } Xu;
-#define edx_rk Xu.Rk
-#define edx_eks Xu.Eks
-};
+#define ESP_OLD_FLENGTH 12
+#define ESP_NEW_FLENGTH 16
-struct esp_old_xencap {
- u_int32_t edx_enc_algorithm;
- u_int32_t edx_ivlen;
- u_int32_t edx_keylen;
- u_int8_t edx_data[1]; /* IV + key material */
+struct esp_new
+{
+ u_int32_t esp_spi; /* Security Parameter Index */
+ u_int32_t esp_rpl; /* Sequence Number, Replay Counter */
+ u_int8_t esp_iv[8]; /* Data may start already at iv[0]! */
};
-#define ESP_OLD_XENCAP_LEN (3 * sizeof(u_int32_t))
-
-struct esp_new_xencap {
- u_int32_t edx_enc_algorithm;
- u_int32_t edx_hash_algorithm;
- u_int32_t edx_ivlen; /* 0 or 8 */
- u_int16_t edx_confkeylen;
- u_int16_t edx_authkeylen;
- int32_t edx_wnd;
- u_int32_t edx_flags;
- u_int8_t edx_data[1]; /* IV + key material */
+struct espstat
+{
+ u_int32_t esps_hdrops; /* packet shorter than header shows */
+ u_int32_t esps_notdb;
+ u_int32_t esps_badkcr;
+ u_int32_t esps_qfull;
+ u_int32_t esps_noxform;
+ u_int32_t esps_badilen;
+ u_int32_t esps_wrap; /* Replay counter wrapped around */
+ u_int32_t esps_badauth; /* Only valid for transforms with auth */
+ u_int32_t esps_replay; /* Possible packet replay detected */
+ u_int32_t esps_input; /* Input ESP packets */
+ u_int32_t esps_output; /* Output ESP packets */
+ u_int32_t esps_invalid; /* Trying to use an invalid TDB */
+ u_int64_t esps_ibytes; /* input bytes */
+ u_int64_t esps_obytes; /* output bytes */
+ u_int32_t esps_toobig; /* packet got larger than IP_MAXPACKET */
};
-#define ESP_NEW_XENCAP_LEN (6 * sizeof(u_int32_t))
-
-#define ESP_NEW_FLAG_AUTH 0x00000001 /* Doing authentication too */
-#define ESP_NEW_FLAG_NPADDING 0x00000002 /* New style padding */
-
-struct esp_new_xdata {
- u_int32_t edx_enc_algorithm;
- u_int32_t edx_hash_algorithm;
- u_int32_t edx_ivlen; /* 0 or 8 */
- u_int32_t edx_rpl; /* Replay counter */
- int32_t edx_wnd; /* Replay window */
- u_int32_t edx_bitmap;
- u_int32_t edx_flags;
- u_int32_t edx_initial; /* initial replay value */
- struct esp_hash *edx_hash;
- struct esp_xform *edx_xform;
- union {
- u_int8_t Iv[ESP_MAX_IVS]; /* that's enough space */
- u_int32_t Ivl; /* make sure this is 4 bytes */
- u_int64_t Ivq; /* make sure this is 8 bytes! */
- } Iu;
- union {
- u_int8_t Rk[3][8];
- u_int32_t Eks[3][16][2];
- blf_ctx Bks;
- cast_key Cks;
- u_int8_t *Sks[10];
- } Xu;
- union {
- MD5_CTX edx_MD5_ictx;
- SHA1_CTX edx_SHA1_ictx;
- RMD160_CTX edx_RMD160_ictx;
- } edx_ictx;
- union {
- MD5_CTX edx_MD5_octx;
- SHA1_CTX edx_SHA1_octx;
- RMD160_CTX edx_RMD160_octx;
- } edx_octx;
-};
-
-#define edx_bks Xu.Bks
-#define edx_cks Xu.Cks
-#define edx_sks Xu.Sks
-#define edx_md5_ictx edx_ictx.edx_MD5_ictx
-#define edx_md5_octx edx_octx.edx_MD5_octx
-#define edx_sha1_ictx edx_ictx.edx_SHA1_ictx
-#define edx_sha1_octx edx_octx.edx_SHA1_octx
-#define edx_rmd160_ictx edx_ictx.edx_RMD160_ictx
-#define edx_rmd160_octx edx_octx.edx_RMD160_octx
-
-#define ESP_OLD_FLENGTH 12
-#define ESP_NEW_FLENGTH 16
-
#ifdef _KERNEL
struct espstat espstat;
-#endif
+#endif /* _Kernel */
diff --git a/sys/netinet/ip_esp_new.c b/sys/netinet/ip_esp_new.c
index 5a45bd97e76..26026302756 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.33 1999/02/17 20:39:17 deraadt Exp $ */
+/* $OpenBSD: ip_esp_new.c,v 1.34 1999/02/24 22:33:02 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -63,12 +63,11 @@
#include <sys/socketvar.h>
#include <net/raw_cb.h>
-#include <net/encap.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_esp.h>
-#include <netinet/ip_ah.h>
+#include <net/pfkeyv2.h>
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
@@ -76,39 +75,36 @@
#define DPRINTF(x)
#endif
-extern void encap_sendnotify(int, struct tdb *, void *);
extern void des_ecb3_encrypt(caddr_t, caddr_t, caddr_t, caddr_t, caddr_t, int);
extern void des_ecb_encrypt(caddr_t, caddr_t, caddr_t, int);
extern void des_set_key(caddr_t, caddr_t);
-static void des1_encrypt(void *, u_int8_t *);
-static void des3_encrypt(void *, u_int8_t *);
-static void blf_encrypt(void *, u_int8_t *);
-static void cast5_encrypt(void *, u_int8_t *);
-static void skipjack_encrypt(void *, u_int8_t *);
-static void des1_decrypt(void *, u_int8_t *);
-static void des3_decrypt(void *, u_int8_t *);
-static void blf_decrypt(void *, u_int8_t *);
-static void cast5_decrypt(void *, u_int8_t *);
-static void skipjack_decrypt(void *, u_int8_t *);
-
-struct esp_hash esp_new_hash[] = {
- { ALG_AUTH_MD5, "HMAC-MD5-96",
- AH_MD5_ALEN,
+static void des1_encrypt(struct tdb *, u_int8_t *);
+static void des3_encrypt(struct tdb *, u_int8_t *);
+static void blf_encrypt(struct tdb *, u_int8_t *);
+static void cast5_encrypt(struct tdb *, u_int8_t *);
+static void des1_decrypt(struct tdb *, u_int8_t *);
+static void des3_decrypt(struct tdb *, u_int8_t *);
+static void blf_decrypt(struct tdb *, u_int8_t *);
+static void cast5_decrypt(struct tdb *, u_int8_t *);
+
+struct auth_hash esp_new_hash[] = {
+ { SADB_AALG_MD5HMAC96, "HMAC-MD5-96",
+ MD5HMAC96_KEYSIZE, AH_MD5_ALEN,
sizeof(MD5_CTX),
(void (*) (void *)) MD5Init,
(void (*) (void *, u_int8_t *, u_int16_t)) MD5Update,
(void (*) (u_int8_t *, void *)) MD5Final
},
- { ALG_AUTH_SHA1, "HMAC-SHA1-96",
- AH_SHA1_ALEN,
+ { SADB_AALG_SHA1HMAC96, "HMAC-SHA1-96",
+ SHA1HMAC96_KEYSIZE, AH_SHA1_ALEN,
sizeof(SHA1_CTX),
(void (*) (void *)) SHA1Init,
(void (*) (void *, u_int8_t *, u_int16_t)) SHA1Update,
(void (*) (u_int8_t *, void *)) SHA1Final
},
- { ALG_AUTH_RMD160, "HMAC-RIPEMD-160-96",
- AH_RMD160_ALEN,
+ { SADB_AALG_X_RIPEMD160HMAC96, "HMAC-RIPEMD-160-96",
+ RIPEMD160HMAC96_KEYSIZE, AH_RMD160_ALEN,
sizeof(RMD160_CTX),
(void (*)(void *)) RMD160Init,
(void (*)(void *, u_int8_t *, u_int16_t)) RMD160Update,
@@ -116,358 +112,251 @@ struct esp_hash esp_new_hash[] = {
}
};
-struct esp_xform esp_new_xform[] = {
- { ALG_ENC_DES, "Data Encryption Standard (DES)",
+struct enc_xform esp_new_xform[] = {
+ { SADB_EALG_DESCBC, "Data Encryption Standard (DES)",
ESP_DES_BLKS, ESP_DES_IVS,
- 8, 8, 8 | 1,
+ 8, 8, 8,
des1_encrypt,
des1_decrypt
},
- { ALG_ENC_3DES, "Triple DES (3DES)",
+ { SADB_EALG_3DESCBC, "Triple DES (3DES)",
ESP_3DES_BLKS, ESP_3DES_IVS,
- 24, 24, 8 | 1,
+ 24, 24, 8,
des3_encrypt,
des3_decrypt
},
- { ALG_ENC_BLF, "Blowfish",
+ { SADB_EALG_X_BLF, "Blowfish",
ESP_BLF_BLKS, ESP_BLF_IVS,
- 5, BLF_MAXKEYLEN, 8 | 1,
+ 5, BLF_MAXKEYLEN, 8,
blf_encrypt,
blf_decrypt
},
- { ALG_ENC_CAST, "CAST",
+ { SADB_EALG_X_CAST, "CAST",
ESP_CAST_BLKS, ESP_CAST_IVS,
- 5, 16, 8 | 1,
+ 5, 16, 8,
cast5_encrypt,
cast5_decrypt
- },
- { ALG_ENC_CAST, "Skipjack",
- ESP_SKIPJACK_BLKS, ESP_SKIPJACK_IVS,
- 10, 10, 8 | 1,
- skipjack_encrypt,
- skipjack_decrypt
}
};
static void
-des1_encrypt(void *pxd, u_int8_t *blk)
-{
- struct esp_new_xdata *xd = pxd;
- des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 1);
-}
-
-static void
-des1_decrypt(void *pxd, u_int8_t *blk)
+des1_encrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_new_xdata *xd = pxd;
- des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 0);
+ des_ecb_encrypt(blk, blk, tdb->tdb_key, 1);
}
static void
-des3_encrypt(void *pxd, u_int8_t *blk)
+des1_decrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_new_xdata *xd = pxd;
- des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]),
- (caddr_t) (xd->edx_eks[1]),
- (caddr_t) (xd->edx_eks[2]), 1);
+ des_ecb_encrypt(blk, blk, tdb->tdb_key, 0);
}
static void
-des3_decrypt(void *pxd, u_int8_t *blk)
+des3_encrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_new_xdata *xd = pxd;
- des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]),
- (caddr_t) (xd->edx_eks[1]),
- (caddr_t) (xd->edx_eks[0]), 0);
+ des_ecb3_encrypt(blk, blk, tdb->tdb_key, tdb->tdb_key + 128,
+ tdb->tdb_key + 256, 1);
}
static void
-blf_encrypt(void *pxd, u_int8_t *blk)
+des3_decrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_new_xdata *xd = pxd;
- Blowfish_encipher(&xd->edx_bks, (u_int32_t *) blk,
- (u_int32_t *) (blk + 4));
+ des_ecb3_encrypt(blk, blk, tdb->tdb_key + 256, tdb->tdb_key + 128,
+ tdb->tdb_key, 0);
}
static void
-blf_decrypt(void *pxd, u_int8_t *blk)
+blf_encrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_new_xdata *xd = pxd;
- Blowfish_decipher(&xd->edx_bks, (u_int32_t *) blk,
- (u_int32_t *) (blk + 4));
+ blf_ecb_encrypt((blf_ctx *) tdb->tdb_key, blk, 8);
}
static void
-cast5_encrypt(void *pxd, u_int8_t *blk)
+blf_decrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_new_xdata *xd = pxd;
- cast_encrypt(&xd->edx_cks, blk, blk);
+ blf_ecb_decrypt((blf_ctx *) tdb->tdb_key, blk, 8);
}
static void
-cast5_decrypt(void *pxd, u_int8_t *blk)
+cast5_encrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_new_xdata *xd = pxd;
- cast_decrypt(&xd->edx_cks, blk, blk);
+ cast_encrypt((cast_key *) tdb->tdb_key, blk, blk);
}
static void
-skipjack_encrypt(void *pxd, u_int8_t *blk)
+cast5_decrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_new_xdata *xd = pxd;
- skipjack_forwards(blk, blk, xd->edx_sks);
-}
-
-static void
-skipjack_decrypt(void *pxd, u_int8_t *blk)
-{
- struct esp_new_xdata *xd = pxd;
- skipjack_backwards(blk, blk, xd->edx_sks);
+ cast_decrypt((cast_key *) tdb->tdb_key, blk, blk);
}
/*
* esp_new_attach() is called from the transformation initialization code.
- * It just returns.
*/
int
esp_new_attach()
{
- DPRINTF(("esp_new_attach(): setting up\n"));
return 0;
}
/*
- * esp_new_init() is called when an SPI is being set up. It interprets the
- * encap_msghdr present in m, and sets up the transformation data, in
- * this case, the encryption and decryption key schedules
+ * esp_new_init() is called when an SPI is being set up.
*/
int
-esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
+esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
- struct esp_new_xdata *xd;
- struct esp_new_xencap txd;
- struct encap_msghdr *em;
- struct esp_xform *txform;
- struct esp_hash *thash;
- caddr_t buffer = NULL;
- u_int32_t rk[14];
- int blocklen, i;
-
- if (m->m_len < ENCAP_MSG_FIXED_LEN)
- {
- if ((m = m_pullup(m, ENCAP_MSG_FIXED_LEN)) == NULL)
- {
- DPRINTF(("esp_new_init(): m_pullup failed\n"));
- return ENOBUFS;
- }
- }
-
- em = mtod(m, struct encap_msghdr *);
- if (em->em_msglen - EMT_SETSPI_FLEN <= ESP_NEW_XENCAP_LEN)
- {
- DPRINTF(("esp_new_init(): initialization failed\n"));
- return EINVAL;
- }
-
- /* Just copy the standard fields */
- m_copydata(m, EMT_SETSPI_FLEN, ESP_NEW_XENCAP_LEN, (caddr_t) &txd);
+ struct enc_xform *txform = NULL;
+ struct auth_hash *thash = NULL;
+ int i;
/* Check whether the encryption algorithm is supported */
- for (i = sizeof(esp_new_xform) / sizeof(struct esp_xform) - 1; i >= 0; i--)
- if (txd.edx_enc_algorithm == esp_new_xform[i].type)
- break;
+ for (i = sizeof(esp_new_xform) / sizeof(struct enc_xform) - 1;
+ i >= 0; i--)
+ if (ii->ii_encalg == esp_new_xform[i].type)
+ break;
+
if (i < 0)
{
- DPRINTF(("esp_new_init(): unsupported encryption algorithm %d specified\n", txd.edx_enc_algorithm));
+ DPRINTF(("esp_new_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg));
return EINVAL;
}
txform = &esp_new_xform[i];
- DPRINTF(("esp_new_init(): initialized TDB with enc algorithm %d: %s\n",
- txd.edx_enc_algorithm, esp_new_xform[i].name));
- /* Check whether the authentication algorithm is supported */
- if (txd.edx_flags & ESP_NEW_FLAG_AUTH)
+ if (ii->ii_enckeylen < txform->minkey)
{
- for (i = sizeof(esp_new_hash) / sizeof(struct esp_hash) - 1; i >= 0;
- i--)
- if (txd.edx_hash_algorithm == esp_new_hash[i].type)
- break;
- if (i < 0)
- {
- DPRINTF(("esp_new_init(): unsupported authentication algorithm %d specified\n", txd.edx_hash_algorithm));
- return EINVAL;
- }
-
- DPRINTF(("esp_new_init(): initialized TDB with hash algorithm %d: %s\n",
- txd.edx_hash_algorithm, esp_new_hash[i].name));
- blocklen = HMAC_BLOCK_LEN;
- thash = &esp_new_hash[i];
- }
-
- if (txd.edx_ivlen + txd.edx_confkeylen + txd.edx_authkeylen +
- EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN != em->em_msglen)
- {
- if (encdebug)
- DPRINTF(("esp_new_init(): message length (%d) doesn't match\n", em->em_msglen));
+ DPRINTF(("esp_new_init(): keylength %d too small (min length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->minkey, txform->name));
return EINVAL;
}
-
- /* Check the IV length */
- if (((txd.edx_ivlen == 0) && !(txform->ivmask&1)) ||
- ((txd.edx_ivlen != 0) && (
- !(txd.edx_ivlen & txform->ivmask) ||
- (txd.edx_ivlen & (txd.edx_ivlen - 1)))))
+
+ if (ii->ii_enckeylen > txform->maxkey)
{
- DPRINTF(("esp_new_init(): unsupported IV length %d\n", txd.edx_ivlen));
+ DPRINTF(("esp_new_init(): keylength %d too large (max length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->maxkey, txform->name));
return EINVAL;
}
- /* Check the key length */
- if (txd.edx_confkeylen < txform->minkey ||
- txd.edx_confkeylen > txform->maxkey)
+ if (ii->ii_authalg)
{
- DPRINTF(("esp_new_init(): bad key length %d\n", txd.edx_confkeylen));
- return EINVAL;
- }
+ for (i = sizeof(esp_new_hash) / sizeof(struct auth_hash) - 1;
+ i >= 0; i--)
+ if (ii->ii_authalg == esp_new_hash[i].type)
+ break;
- MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct esp_new_xdata),
- M_XDATA, M_WAITOK);
- if (tdbp->tdb_xdata == NULL)
- {
- DPRINTF(("esp_new_init(): MALLOC() failed\n"));
- return ENOBUFS;
- }
+ if (i < 0)
+ {
+ DPRINTF(("esp_new_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
+ return EINVAL;
+ }
- bzero(tdbp->tdb_xdata, sizeof(struct esp_new_xdata));
- xd = (struct esp_new_xdata *) tdbp->tdb_xdata;
+ thash = &esp_new_hash[i];
- /* Pointer to the transform */
- tdbp->tdb_xform = xsp;
+ if (ii->ii_authkeylen != thash->keysize)
+ {
+ DPRINTF(("esp_new_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
+ return EINVAL;
+ }
+
+ tdbp->tdb_authalgxform = thash;
- xd->edx_ivlen = txd.edx_ivlen;
- xd->edx_enc_algorithm = txd.edx_enc_algorithm;
- xd->edx_wnd = txd.edx_wnd;
- xd->edx_flags = txd.edx_flags;
- xd->edx_hash_algorithm = txd.edx_hash_algorithm;
- xd->edx_bitmap = 0;
- xd->edx_xform = txform;
+ DPRINTF(("esp_new_init(): initialized TDB with hash algorithm %s\n",
+ thash->name));
+ }
+
+ tdbp->tdb_xform = xsp;
+ tdbp->tdb_encalgxform = txform;
+ tdbp->tdb_bitmap = 0;
+ tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
- /* Pass name of enc algorithm for kernfs */
- tdbp->tdb_confname = xd->edx_xform->name;
+ DPRINTF(("esp_new_init(): initialized TDB with enc algorithm %s\n",
+ txform->name));
- /* Replay counters are mandatory, even without auth */
- xd->edx_rpl = AH_HMAC_INITIAL_RPL;
+ tdbp->tdb_ivlen = txform->ivmask;
- /* Copy the IV */
- m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN, xd->edx_ivlen,
- (caddr_t) xd->edx_iv);
+ /* Initialize the IV */
+ get_random_bytes(tdbp->tdb_iv, tdbp->tdb_ivlen);
- /* Copy the key material */
- m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + xd->edx_ivlen,
- txd.edx_confkeylen, (caddr_t) rk);
- switch (xd->edx_enc_algorithm)
+ switch (ii->ii_encalg)
{
- case ALG_ENC_DES:
- des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0]));
+ case SADB_EALG_DESCBC:
+ MALLOC(tdbp->tdb_key, u_int8_t *, 128, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_key, 128);
+ des_set_key(ii->ii_enckey, tdbp->tdb_key);
break;
- case ALG_ENC_3DES:
- des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0]));
- des_set_key((caddr_t) (rk + 2), (caddr_t) (xd->edx_eks[1]));
- des_set_key((caddr_t) (rk + 4), (caddr_t) (xd->edx_eks[2]));
- break;
- case ALG_ENC_BLF:
- blf_key(&xd->edx_bks, (caddr_t) rk, txd.edx_confkeylen);
+ case SADB_EALG_3DESCBC:
+ MALLOC(tdbp->tdb_key, u_int8_t *, 384, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_key, 384);
+ des_set_key(ii->ii_enckey, tdbp->tdb_key);
+ des_set_key(ii->ii_enckey + 8, tdbp->tdb_key + 128);
+ des_set_key(ii->ii_enckey + 16, tdbp->tdb_key + 256);
break;
- case ALG_ENC_CAST:
- cast_setkey(&xd->edx_cks, (caddr_t) rk, txd.edx_confkeylen);
+
+ case SADB_EALG_X_BLF:
+ MALLOC(tdbp->tdb_key, u_int8_t *, sizeof(blf_ctx),
+ M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_key, sizeof(blf_ctx));
+ blf_key((blf_ctx *) tdbp->tdb_key, ii->ii_enckey,
+ ii->ii_enckeylen);
break;
- case ALG_ENC_SKIPJACK:
- subkey_table_gen((caddr_t) rk, xd->edx_sks);
+
+ case SADB_EALG_X_CAST:
+ MALLOC(tdbp->tdb_key, u_int8_t *, sizeof(cast_key),
+ M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_key, sizeof(cast_key));
+ cast_setkey((cast_key *) tdbp->tdb_key, ii->ii_enckey,
+ ii->ii_enckeylen);
break;
}
- if (txd.edx_flags & ESP_NEW_FLAG_AUTH)
+ if (thash)
{
- xd->edx_hash = thash;
-
- /* Pass name of auth algorithm for kernfs */
- tdbp->tdb_authname = xd->edx_hash->name;
-
- DPRINTF(("esp_new_init(): using %d bytes of authentication key\n",
- txd.edx_authkeylen));
-
- MALLOC(buffer, caddr_t,
- txd.edx_authkeylen < blocklen ? blocklen : txd.edx_authkeylen,
- M_TEMP, M_WAITOK);
- if (buffer == NULL)
- {
- DPRINTF(("esp_new_init(): MALLOC() failed\n"));
- free(tdbp->tdb_xdata, M_XDATA);
- return ENOBUFS;
- }
-
- bzero(buffer, txd.edx_authkeylen < blocklen ?
- blocklen : txd.edx_authkeylen);
-
- /* Copy the key to the buffer */
- m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + xd->edx_ivlen +
- txd.edx_confkeylen, txd.edx_authkeylen, buffer);
-
- /* Shorten the key if necessary */
- if (txd.edx_authkeylen > blocklen)
- {
- xd->edx_hash->Init(&(xd->edx_ictx));
- xd->edx_hash->Update(&(xd->edx_ictx), buffer, txd.edx_authkeylen);
- bzero(buffer, txd.edx_authkeylen < blocklen ?
- blocklen : txd.edx_authkeylen);
- xd->edx_hash->Final(buffer, &(xd->edx_ictx));
- }
-
/* Precompute the I and O pads of the HMAC */
- for (i = 0; i < blocklen; i++)
- buffer[i] ^= HMAC_IPAD_VAL;
-
- xd->edx_hash->Init(&(xd->edx_ictx));
- xd->edx_hash->Update(&(xd->edx_ictx), buffer, blocklen);
+ for (i = 0; i < ii->ii_authkeylen; i++)
+ ii->ii_authkey[i] ^= HMAC_IPAD_VAL;
+
+ MALLOC(tdbp->tdb_ictx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_ictx, thash->ctxsize);
+ thash->Init(tdbp->tdb_ictx);
+ thash->Update(tdbp->tdb_ictx, ii->ii_authkey, ii->ii_authkeylen);
+ thash->Update(tdbp->tdb_ictx, hmac_ipad_buffer,
+ HMAC_BLOCK_LEN - ii->ii_authkeylen);
- for (i = 0; i < blocklen; i++)
- buffer[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
-
- xd->edx_hash->Init(&(xd->edx_octx));
- xd->edx_hash->Update(&(xd->edx_octx), buffer, blocklen);
-
- bzero(buffer, blocklen);
- free(buffer, M_TEMP);
+ for (i = 0; i < ii->ii_authkeylen; i++)
+ ii->ii_authkey[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
+
+ MALLOC(tdbp->tdb_octx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_octx, thash->ctxsize);
+ thash->Init(tdbp->tdb_octx);
+ thash->Update(tdbp->tdb_octx, ii->ii_authkey, ii->ii_authkeylen);
+ thash->Update(tdbp->tdb_octx, hmac_opad_buffer,
+ HMAC_BLOCK_LEN - ii->ii_authkeylen);
}
- bzero(rk, 14 * sizeof(u_int32_t)); /* paranoid */
- bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */
-
return 0;
}
int
esp_new_zeroize(struct tdb *tdbp)
{
- struct esp_new_xdata *xd = (struct esp_new_xdata *) tdbp->tdb_xdata;
-
- DPRINTF(("esp_new_zeroize(): freeing memory\n"));
- if (xd->edx_enc_algorithm == ALG_ENC_SKIPJACK) {
- int k;
+ if (tdbp->tdb_key)
+ {
+ FREE(tdbp->tdb_key, M_XDATA);
+ tdbp->tdb_key = NULL;
+ }
- for (k = 0; k < 10; k++)
- free(xd->edx_sks[k], M_TEMP);
+ if (tdbp->tdb_ictx)
+ {
+ FREE(tdbp->tdb_ictx, M_XDATA);
+ tdbp->tdb_ictx = NULL;
}
- if (tdbp->tdb_xdata)
+ if (tdbp->tdb_octx)
{
- FREE(tdbp->tdb_xdata, M_XDATA);
- tdbp->tdb_xdata = NULL;
+ FREE(tdbp->tdb_octx, M_XDATA);
+ tdbp->tdb_octx = NULL;
}
+
return 0;
}
@@ -475,10 +364,11 @@ esp_new_zeroize(struct tdb *tdbp)
struct mbuf *
esp_new_input(struct mbuf *m, struct tdb *tdb)
{
+ 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;
- struct esp_new_xdata *xd;
int count, off, errc;
struct mbuf *mi, *mo;
u_char *idat, *odat, *ivp, *ivn;
@@ -492,11 +382,9 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
} ctx;
u_char buf[AH_ALEN_MAX], buf2[AH_ALEN_MAX];
- xd = (struct esp_new_xdata *) tdb->tdb_xdata;
+ blks = espx->blocksize;
- blks = xd->edx_xform->blocksize;
-
- if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
+ if (esph)
alen = AH_HMAC_HASHLEN;
else
alen = 0;
@@ -527,26 +415,52 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
ip = mtod(m, struct ip *);
}
+ /* Update the counters */
+ tdb->tdb_cur_bytes += ip->ip_len - ohlen - alen;
+ espstat.esps_ibytes += ip->ip_len - ohlen - alen;
+
+ /* Hard expiration */
+ if ((tdb->tdb_flags & TDBF_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ tdb_delete(tdb, 0);
+ m_freem(m);
+ return NULL;
+ }
+
+ /* Notify on expiration */
+ if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ 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 (xd->edx_wnd >= 0)
+ if (tdb->tdb_wnd > 0)
{
btsx = ntohl(esp->esp_rpl);
- if ((errc = checkreplaywindow32(btsx, 0, &(xd->edx_rpl), xd->edx_wnd,
- &(xd->edx_bitmap))) != 0)
+ 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 %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(esp->esp_spi)));
+ 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, %x->%x spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(esp->esp_spi)));
+ 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;
}
@@ -558,22 +472,22 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
/* 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) -
- xd->edx_ivlen - alen;
+ tdb->tdb_ivlen - alen;
if ((plen & (blks - 1)) || (plen <= 0))
{
- DPRINTF(("esp_new_input(): payload not a multiple of %d octets for packet from %x to %x, spi %08x\n", blks, ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ 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;
}
- if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
+ if (esph)
{
- bcopy(&(xd->edx_ictx), &ctx, xd->edx_hash->ctxsize);
+ bcopy(tdb->tdb_ictx, &ctx, esph->ctxsize);
/* Auth covers SPI + SN + IV */
- oplen = plen + 2 * sizeof(u_int32_t) + xd->edx_ivlen;
+ oplen = plen + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
off = (ip->ip_hl << 2);
/* Copy the authentication data */
@@ -585,27 +499,27 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
{
if (mo == 0)
{
- DPRINTF(("esp_new_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(esp->esp_spi)));
+ 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)));
espstat.esps_hdrops++;
m_freem(m);
return NULL;
}
count = min(mo->m_len - off, oplen);
- xd->edx_hash->Update(&ctx, mtod(mo, unsigned char *) + off, count);
+ esph->Update(&ctx, mtod(mo, unsigned char *) + off, count);
oplen -= count;
off = 0;
mo = mo->m_next;
}
- xd->edx_hash->Final(buf2, &ctx);
- bcopy(&(xd->edx_octx), &ctx, xd->edx_hash->ctxsize);
- xd->edx_hash->Update(&ctx, buf2, xd->edx_hash->hashsize);
- xd->edx_hash->Final(buf2, &ctx);
+ esph->Final(buf2, &ctx);
+ bcopy(tdb->tdb_octx, &ctx, esph->ctxsize);
+ esph->Update(&ctx, buf2, esph->hashsize);
+ esph->Final(buf2, &ctx);
if (bcmp(buf2, buf, AH_HMAC_HASHLEN))
{
- DPRINTF(("esp_new_input(): authentication failed for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(esp->esp_spi)));
+ 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)));
espstat.esps_badauth++;
m_freem(m);
return NULL;
@@ -616,21 +530,10 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
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);
- if (xd->edx_ivlen == 0) /* Derived IV in use */
- {
- bcopy((u_char *) &esp->esp_rpl, iv, sizeof(esp->esp_rpl));
- iv[4] = ~iv[0];
- iv[5] = ~iv[1];
- iv[6] = ~iv[2];
- iv[7] = ~iv[3];
- }
- else
- {
- bcopy(idat, iv, xd->edx_ivlen);
- ilen -= xd->edx_ivlen;
- idat += xd->edx_ivlen;
- }
-
+ bcopy(idat, iv, tdb->tdb_ivlen);
+ ilen -= tdb->tdb_ivlen;
+ idat += tdb->tdb_ivlen;
+
mi = m;
/*
@@ -666,7 +569,7 @@ 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 %x/%08x\n", 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;
@@ -677,7 +580,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
{
if ((mi = m_pullup(mi, blks - rest)) == NULL)
{
- DPRINTF(("esp_new_input(): m_pullup() failed, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_new_input(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_hdrops++;
return NULL;
@@ -697,7 +600,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
bcopy(idat, blk + rest, blks - rest);
bcopy(blk, ivn, blks);
- xd->edx_xform->decrypt(xd, blk);
+ espx->decrypt(tdb, blk);
for (i = 0; i < blks; i++)
blk[i] ^= ivp[i];
@@ -722,7 +625,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
{
bcopy(idat, ivn, blks);
- xd->edx_xform->decrypt(xd, idat);
+ espx->decrypt(tdb, idat);
for (i = 0; i < blks; i++)
idat[i] ^= ivp[i];
@@ -743,7 +646,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
(caddr_t) opts);
if (lblk != blk)
- bcopy(lblk, blk, blks);
+ bcopy(lblk, blk, blks);
/*
* Now, the entire chain has been decrypted. As a side effect,
@@ -753,58 +656,30 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
* Verify correct decryption by checking the last padding bytes.
*/
- if ((xd->edx_flags & ESP_NEW_FLAG_NPADDING) == 0)
+ 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 - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) - xd->edx_ivlen)
- {
- DPRINTF(("esp_new_input(): invalid padding length %d for packet from %x to %x, SA %x/%08x\n", blk[blks - 2], ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi)));
- espstat.esps_badilen++;
- m_freem(m);
- return NULL;
- }
- if ((blk[blks - 2] != blk[blks - 3]) && (blk[blks - 2] != 0))
- {
- DPRINTF(("esp_new_input(): decryption failed for packet from %x to %x, SA %x/%08x\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi)));
- m_freem(m);
- return NULL;
- }
-
- m_adj(m, - blk[blks - 2] - 2 - alen); /* Old type padding */
+ 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)));
+ espstat.esps_badilen++;
+ m_freem(m);
+ return NULL;
}
- else
+
+ if ((blk[blks - 2] != blk[blks - 3]) && (blk[blks - 2] != 0))
{
- if (blk[blks - 2] + 1 + alen > m->m_pkthdr.len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) - xd->edx_ivlen)
- {
- DPRINTF(("esp_new_input(): invalid padding length %d for packet from %x to %x, SA %x/%08x\n", blk[blks - 2], ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi)));
- espstat.esps_badilen++;
- m_freem(m);
- return NULL;
- }
- if (blk[blks - 2] == 0)
- {
- DPRINTF(("esp_new_input(): decryption failed for packet from %x to %x, SA %x/%08x -- peer is probably using old style padding\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi)));
- m_freem(m);
- return NULL;
- }
- else
- if ((blk[blks - 2] != 1) && (blk[blks - 2] != blk[blks - 3] + 1))
- {
- DPRINTF(("esp_new_input(): decryption failed for packet from %x to %x, SA %x/%08x\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi)));
- m_freem(m);
- return NULL;
- }
-
- m_adj(m, - blk[blks - 2] - 1 - alen);
- }
+ 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)));
+ m_freem(m);
+ return NULL;
+ }
- m_adj(m, 2 * sizeof(u_int32_t) + xd->edx_ivlen);
+ 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 %x to %x, SA %x/%08x\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ 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;
}
@@ -814,11 +689,8 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
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) - xd->edx_ivlen -
- blk[blks - 2] - 1 - alen;
-
- if ((xd->edx_flags & ESP_NEW_FLAG_NPADDING) == 0)
- ipo.ip_len -= 1;
+ 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;
@@ -830,52 +702,6 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));
- /* Update the counters */
- tdb->tdb_cur_packets++;
- tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) +
- blk[blks - 2] + 1 + alen;
- espstat.esps_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) +
- blk[blks - 2] + 1 + alen;
-
- if ((xd->edx_flags & ESP_NEW_FLAG_NPADDING) == 0)
- {
- tdb->tdb_cur_bytes++;
- espstat.esps_ibytes++;
- }
-
- /* Notify on expiration */
- if (tdb->tdb_flags & TDBF_SOFT_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_PACKETS;
- }
- else
- if (tdb->tdb_flags & TDBF_SOFT_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
- }
- }
-
- if (tdb->tdb_flags & TDBF_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- else
- if (tdb->tdb_flags & TDBF_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- }
-
return m;
}
@@ -883,7 +709,8 @@ int
esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
struct mbuf **mp)
{
- struct esp_new_xdata *xd;
+ 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;
@@ -897,14 +724,12 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
} ctx;
int iphlen, blks, alen;
- xd = (struct esp_new_xdata *) tdb->tdb_xdata;
+ blks = espx->blocksize;
- blks = xd->edx_xform->blocksize;
-
- if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
+ if (esph)
{
alen = AH_HMAC_HASHLEN;
- DPRINTF(("esp_new_output(): using hash algorithm: %s\n", xd->edx_hash->name));
+ DPRINTF(("esp_new_output(): using hash algorithm: %s\n", esph->name));
}
else
alen = 0;
@@ -914,27 +739,53 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
m = m_pullup(m, sizeof (struct ip)); /* Get IP header in one mbuf */
if (m == NULL)
{
- DPRINTF(("esp_new_output(): m_pullup() failed, SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ 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 (xd->edx_rpl == 0)
+ if (tdb->tdb_rpl == 0)
{
- DPRINTF(("esp_new_output(): SA %x/%0x8 should have expired\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_new_output(): SA %s/%0x8 should have expired\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_wrap++;
return ENOBUFS;
}
espo.esp_spi = tdb->tdb_spi;
- espo.esp_rpl = htonl(xd->edx_rpl++);
+ espo.esp_rpl = htonl(tdb->tdb_rpl++);
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);
+
+ /* Hard expiration */
+ if ((tdb->tdb_flags & TDBF_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ tdb_delete(tdb, 0);
+ m_freem(m);
+ return EINVAL;
+ }
+
+ /* Notify on expiration */
+ if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
+ }
+
/*
* If options are present, pullup the IP header, the options.
*/
@@ -943,8 +794,8 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
m = m_pullup(m, iphlen + 8);
if (m == NULL)
{
- DPRINTF(("esp_new_input(): m_pullup() failed for SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ 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;
}
@@ -957,7 +808,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
}
ilen = ntohs(ip->ip_len); /* Size of the packet */
- ohlen = 2 * sizeof(u_int32_t) + xd->edx_ivlen;
+ ohlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
ipo = *ip;
nh = ipo.ip_p;
@@ -965,9 +816,10 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
/* 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 %x/%0x8 got too big\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ 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;
@@ -976,8 +828,8 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
pad = (u_char *) m_pad(m, padding + alen, 0);
if (pad == NULL)
{
- DPRINTF(("esp_new_output(): m_pad() failed for SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_new_output(): m_pad() failed for SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
return ENOBUFS;
}
@@ -985,11 +837,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
for (i = 0; i < padding - 2; i++)
pad[i] = i + 1;
- if (xd->edx_flags & ESP_NEW_FLAG_NPADDING)
- pad[padding - 2] = padding - 1;
- else
- pad[padding - 2] = padding - 2;
-
+ pad[padding - 2] = padding - 2;
pad[padding - 1] = nh;
mi = m;
@@ -997,26 +845,15 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
ilen = m->m_len - iphlen;
idat = mtod(m, u_char *) + iphlen;
- if (xd->edx_ivlen == 0)
- {
- bcopy((u_char *) &espo.esp_rpl, iv, 4);
- iv[4] = ~iv[0];
- iv[5] = ~iv[1];
- iv[6] = ~iv[2];
- iv[7] = ~iv[3];
- }
- else
- {
- bcopy(xd->edx_iv, iv, xd->edx_ivlen);
- bcopy(xd->edx_iv, espo.esp_iv, xd->edx_ivlen);
- }
+ bcopy(tdb->tdb_iv, iv, tdb->tdb_ivlen);
+ bcopy(tdb->tdb_iv, espo.esp_iv, tdb->tdb_ivlen);
/* Authenticate the esp header */
- if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
+ if (esph)
{
- bcopy(&(xd->edx_ictx), &ctx, xd->edx_hash->ctxsize);
- xd->edx_hash->Update(&ctx, (unsigned char *) &espo,
- 2 * sizeof(u_int32_t) + xd->edx_ivlen);
+ bcopy(tdb->tdb_ictx, &ctx, esph->ctxsize);
+ esph->Update(&ctx, (unsigned char *) &espo,
+ 2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
}
/* Encrypt the payload */
@@ -1043,7 +880,8 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
mi = (mo = mi)->m_next;
if (mi == NULL)
{
- DPRINTF(("esp_new_output(): bad mbuf chain, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_new_output(): bad mbuf chain, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
m_freem(m);
return EINVAL;
@@ -1054,7 +892,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
{
if ((mi = m_pullup(mi, blks - rest)) == NULL)
{
- DPRINTF(("esp_new_output(): m_pullup() failed, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_new_output(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_hdrops++;
return ENOBUFS;
@@ -1076,10 +914,10 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
for (i = 0; i < blks; i++)
blk[i] ^= ivp[i];
- xd->edx_xform->encrypt(xd, blk);
+ espx->encrypt(tdb, blk);
- if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
- xd->edx_hash->Update(&ctx, blk, blks);
+ if (esph)
+ esph->Update(&ctx, blk, blks);
ivp = blk;
@@ -1099,10 +937,10 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
for (i = 0; i < blks; i++)
idat[i] ^= ivp[i];
- xd->edx_xform->encrypt(xd, idat);
+ espx->encrypt(tdb, idat);
- if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
- xd->edx_hash->Update(&ctx, idat, blks);
+ if (esph)
+ esph->Update(&ctx, idat, blks);
ivp = idat;
idat += blks;
@@ -1113,12 +951,12 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
}
/* Put in authentication data */
- if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
+ if (esph)
{
- xd->edx_hash->Final(auth, &ctx);
- bcopy(&(xd->edx_octx), &ctx, xd->edx_hash->ctxsize);
- xd->edx_hash->Update(&ctx, auth, xd->edx_hash->hashsize);
- xd->edx_hash->Final(auth, &ctx);
+ esph->Final(auth, &ctx);
+ bcopy(tdb->tdb_octx, &ctx, esph->ctxsize);
+ esph->Update(&ctx, auth, esph->hashsize);
+ esph->Final(auth, &ctx);
/* Copy the final authenticator */
bcopy(auth, pad + padding, alen);
@@ -1132,16 +970,16 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
M_PREPEND(m, ohlen, M_DONTWAIT);
if (m == NULL)
{
- DPRINTF(("esp_new_output(): M_PREPEND failed, SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ 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 %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ 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;
}
@@ -1151,7 +989,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
ipo.ip_p = IPPROTO_ESP;
/* Save the last encrypted block, to be used as the next IV */
- bcopy(ivp, xd->edx_iv, xd->edx_ivlen);
+ bcopy(ivp, tdb->tdb_iv, tdb->tdb_ivlen);
m_copyback(m, 0, sizeof(struct ip), (caddr_t) &ipo);
@@ -1165,44 +1003,6 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
*mp = m;
- /* Update the counters */
- tdb->tdb_cur_packets++;
- tdb->tdb_cur_bytes += rlen + padding;
- espstat.esps_obytes += rlen + padding;
-
- /* Notify on expiration */
- if (tdb->tdb_flags & TDBF_SOFT_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_PACKETS;
- }
- else
- if (tdb->tdb_flags & TDBF_SOFT_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
- }
- }
-
- if (tdb->tdb_flags & TDBF_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- else
- if (tdb->tdb_flags & TDBF_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- }
-
return 0;
}
@@ -1250,3 +1050,4 @@ checkreplaywindow32(u_int32_t seq, u_int32_t initial, u_int32_t *lastseq,
*bitmap |= (((u_int32_t) 1) << diff);
return 0;
}
+
diff --git a/sys/netinet/ip_esp_old.c b/sys/netinet/ip_esp_old.c
index 37e6a63f908..d8089df6866 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.27 1999/02/12 00:46:11 deraadt Exp $ */
+/* $OpenBSD: ip_esp_old.c,v 1.28 1999/02/24 22:33:03 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -63,11 +63,11 @@
#include <sys/socketvar.h>
#include <net/raw_cb.h>
-#include <net/encap.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_esp.h>
+#include <net/pfkeyv2.h>
#include <dev/rndvar.h>
#ifdef ENCDEBUG
@@ -80,188 +80,123 @@ extern void des_ecb3_encrypt(caddr_t, caddr_t, caddr_t, caddr_t, caddr_t, int);
extern void des_ecb_encrypt(caddr_t, caddr_t, caddr_t, int);
extern void des_set_key(caddr_t, caddr_t);
-extern int encap_sendnotify(int, struct tdb *, void *);
+static void des1_encrypt(struct tdb *, u_int8_t *);
+static void des3_encrypt(struct tdb *, u_int8_t *);
+static void des1_decrypt(struct tdb *, u_int8_t *);
+static void des3_decrypt(struct tdb *, u_int8_t *);
-static void des1_encrypt(void *, u_int8_t *);
-static void des3_encrypt(void *, u_int8_t *);
-static void des1_decrypt(void *, u_int8_t *);
-static void des3_decrypt(void *, u_int8_t *);
-
-struct esp_xform esp_old_xform[] = {
- { ALG_ENC_DES, "Data Encryption Standard (DES)",
+struct enc_xform esp_old_xform[] = {
+ { SADB_EALG_DESCBC, "Data Encryption Standard (DES)",
ESP_DES_BLKS, ESP_DES_IVS,
- 8, 8, 8 | 4,
+ 8, 8, 8,
des1_encrypt,
des1_decrypt
},
- { ALG_ENC_3DES, "Triple DES (3DES)",
+ { SADB_EALG_3DESCBC, "Triple DES (3DES)",
ESP_3DES_BLKS, ESP_3DES_IVS,
- 24, 24, 8 | 4,
+ 24, 24, 8,
des3_encrypt,
des3_decrypt
}
};
static void
-des1_encrypt(void *pxd, u_int8_t *blk)
+des1_encrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_old_xdata *xd = pxd;
- des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 1);
+ des_ecb_encrypt(blk, blk, tdb->tdb_key, 1);
}
static void
-des1_decrypt(void *pxd, u_int8_t *blk)
+des1_decrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_old_xdata *xd = pxd;
- des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 0);
+ des_ecb_encrypt(blk, blk, tdb->tdb_key, 0);
}
static void
-des3_encrypt(void *pxd, u_int8_t *blk)
+des3_encrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_old_xdata *xd = pxd;
- des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]),
- (caddr_t) (xd->edx_eks[1]),
- (caddr_t) (xd->edx_eks[0]), 1);
+ des_ecb3_encrypt(blk, blk, tdb->tdb_key, tdb->tdb_key + 128,
+ tdb->tdb_key + 256, 1);
}
static void
-des3_decrypt(void *pxd, u_int8_t *blk)
+des3_decrypt(struct tdb *tdb, u_int8_t *blk)
{
- struct esp_old_xdata *xd = pxd;
- des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]),
- (caddr_t) (xd->edx_eks[1]),
- (caddr_t) (xd->edx_eks[0]), 0);
+ des_ecb3_encrypt(blk, blk, tdb->tdb_key + 256, tdb->tdb_key + 128,
+ tdb->tdb_key, 0);
}
int
esp_old_attach()
{
- DPRINTF(("esp_old_attach(): setting up\n"));
return 0;
}
/*
- * esp_old_init() is called when an SPI is being set up. It interprets the
- * encap_msghdr present in m, and sets up the transformation data, in
- * this case, the encryption and decryption key schedules
+ * esp_old_init() is called when an SPI is being set up.
*/
int
-esp_old_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
+esp_old_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
- struct esp_old_xdata *xd;
- struct esp_old_xencap xenc;
- struct encap_msghdr *em;
- struct esp_xform *txform;
- u_int32_t rk[6];
+ struct enc_xform *txform = NULL;
int i;
- if (m->m_len < ENCAP_MSG_FIXED_LEN)
- {
- if ((m = m_pullup(m, ENCAP_MSG_FIXED_LEN)) == NULL)
- {
- DPRINTF(("esp_old_init(): m_pullup failed\n"));
- return ENOBUFS;
- }
- }
-
- em = mtod(m, struct encap_msghdr *);
- if (em->em_msglen - EMT_SETSPI_FLEN <= ESP_OLD_XENCAP_LEN)
- {
- DPRINTF(("esp_old_init(): initialization failed\n"));
- return EINVAL;
- }
-
- /* Just copy the standard fields */
- m_copydata(m, EMT_SETSPI_FLEN, ESP_OLD_XENCAP_LEN, (caddr_t) &xenc);
-
/* Check whether the encryption algorithm is supported */
- for (i=sizeof(esp_old_xform)/sizeof(struct esp_xform)-1; i >= 0; i--)
- if (xenc.edx_enc_algorithm == esp_old_xform[i].type)
- break;
+ for (i = sizeof(esp_old_xform) / sizeof(struct enc_xform) - 1;
+ i >= 0; i--)
+ if (ii->ii_encalg == esp_old_xform[i].type)
+ break;
+
if (i < 0)
{
- DPRINTF(("esp_old_init(): unsupported encryption algorithm %d specified\n", xenc.edx_enc_algorithm));
+ DPRINTF(("esp_old_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg));
return EINVAL;
}
txform = &esp_old_xform[i];
- DPRINTF(("esp_old_init(): initialized TDB with enc algorithm %d: %s\n",
- xenc.edx_enc_algorithm, esp_old_xform[i].name));
-
- if (xenc.edx_ivlen + xenc.edx_keylen + EMT_SETSPI_FLEN +
- ESP_OLD_XENCAP_LEN != em->em_msglen)
- {
- DPRINTF(("esp_old_init(): message length (%d) doesn't match\n",
- em->em_msglen));
- return EINVAL;
- }
- /* Check the IV length */
- if (((xenc.edx_ivlen == 0) && !(txform->ivmask&1)) ||
- ((xenc.edx_ivlen != 0) && (
- !(xenc.edx_ivlen & txform->ivmask) ||
- (xenc.edx_ivlen & (xenc.edx_ivlen-1)))))
+ if (ii->ii_enckeylen < txform->minkey)
{
- DPRINTF(("esp_old_init(): unsupported IV length %d\n",
- xenc.edx_ivlen));
+ DPRINTF(("esp_old_init(): keylength %d too small (min length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->minkey, txform->name));
return EINVAL;
}
-
- /* Check the key length */
- if (xenc.edx_keylen < txform->minkey || xenc.edx_keylen > txform->maxkey)
+
+ if (ii->ii_enckeylen > txform->maxkey)
{
- DPRINTF(("esp_old_init(): bad key length %d\n", xenc.edx_keylen));
+ DPRINTF(("esp_old_init(): keylength %d too large (max length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->maxkey, txform->name));
return EINVAL;
}
- MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct esp_old_xdata),
- M_XDATA, M_WAITOK);
- if (tdbp->tdb_xdata == NULL)
- {
- DPRINTF(("esp_old_init(): MALLOC() failed\n"));
- return ENOBUFS;
- }
-
- bzero(tdbp->tdb_xdata, sizeof(struct esp_old_xdata));
- xd = (struct esp_old_xdata *) tdbp->tdb_xdata;
-
- /* Pointer to the transform */
tdbp->tdb_xform = xsp;
+ tdbp->tdb_encalgxform = txform;
- xd->edx_ivlen = xenc.edx_ivlen;
- xd->edx_xform = txform;
- xd->edx_enc_algorithm = xenc.edx_enc_algorithm;
+ DPRINTF(("esp_old_init(): initialized TDB with enc algorithm %s\n",
+ txform->name));
- /* Pass name of enc algorithm for kernfs */
- tdbp->tdb_confname = xd->edx_xform->name;
+ tdbp->tdb_ivlen = txform->ivmask;
+ if (tdbp->tdb_flags & TDBF_HALFIV)
+ tdbp->tdb_ivlen /= 2;
- /* Copy the IV */
- m_copydata(m, EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN, xd->edx_ivlen,
- (caddr_t) xd->edx_iv);
+ get_random_bytes(tdbp->tdb_iv, tdbp->tdb_ivlen);
- /* Copy the key material */
- m_copydata(m, EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN + xd->edx_ivlen,
- xenc.edx_keylen, (caddr_t) rk);
-
- switch (xd->edx_enc_algorithm)
+ switch (ii->ii_encalg)
{
- case ALG_ENC_DES:
- des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0]));
+ case SADB_EALG_DESCBC:
+ MALLOC(tdbp->tdb_key, u_int8_t *, 128, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_key, 128);
+ des_set_key(ii->ii_enckey, tdbp->tdb_key);
break;
- case ALG_ENC_3DES:
- des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0]));
- des_set_key((caddr_t) (rk + 2), (caddr_t) (xd->edx_eks[1]));
- des_set_key((caddr_t) (rk + 4), (caddr_t) (xd->edx_eks[2]));
+ case SADB_EALG_3DESCBC:
+ MALLOC(tdbp->tdb_key, u_int8_t *, 384, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_key, 384);
+ des_set_key(ii->ii_enckey, tdbp->tdb_key);
+ des_set_key(ii->ii_enckey + 8, tdbp->tdb_key + 128);
+ des_set_key(ii->ii_enckey + 16, tdbp->tdb_key + 256);
break;
}
- bzero(rk, 6 * sizeof(u_int32_t)); /* paranoid */
-
- bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */
-
return 0;
}
@@ -269,12 +204,12 @@ esp_old_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
int
esp_old_zeroize(struct tdb *tdbp)
{
- DPRINTF(("esp_old_zeroize(): freeing memory\n"));
- if (tdbp->tdb_xdata)
+ if (tdbp->tdb_key)
{
- FREE(tdbp->tdb_xdata, M_XDATA);
- tdbp->tdb_xdata = NULL;
+ FREE(tdbp->tdb_key, M_XDATA);
+ tdbp->tdb_key = NULL;
}
+
return 0;
}
@@ -284,7 +219,7 @@ esp_old_zeroize(struct tdb *tdbp)
struct mbuf *
esp_old_input(struct mbuf *m, struct tdb *tdb)
{
- struct esp_old_xdata *xd;
+ struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
struct ip *ip, ipo;
u_char iv[ESP_3DES_IVS], niv[ESP_3DES_IVS], blk[ESP_3DES_BLKS], opts[40];
u_char *idat, *odat, *ivp, *ivn, *lblk;
@@ -292,9 +227,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
int ohlen, plen, ilen, i, blks, rest;
struct mbuf *mi, *mo;
- xd = (struct esp_old_xdata *) tdb->tdb_xdata;
-
- blks = xd->edx_xform->blocksize;
+ blks = espx->blocksize;
if (m->m_len < sizeof(struct ip))
{
@@ -323,20 +256,45 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
}
esp = (struct esp_old *) ((u_int8_t *) ip + (ip->ip_hl << 2));
-
ipo = *ip;
/* Skip the IP header, IP options, SPI and IV */
plen = m->m_pkthdr.len - (ip->ip_hl << 2) - sizeof(u_int32_t) -
- xd->edx_ivlen;
+ tdb->tdb_ivlen;
if ((plen & (blks - 1)) || (plen <= 0))
{
- DPRINTF(("esp_old_input(): payload not a multiple of %d octets for packet from %x to %x, spi %08x\n", blks, ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_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;
}
+ /* Update the counters */
+ tdb->tdb_cur_bytes += plen;
+ espstat.esps_ibytes += plen;
+
+ /* Hard expiration */
+ if ((tdb->tdb_flags & TDBF_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ tdb_delete(tdb, 0);
+ m_freem(m);
+ return NULL;
+ }
+
+ /* Notify on expiration */
+ if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
+ }
+
ilen = m->m_len - (ip->ip_hl << 2) - sizeof(u_int32_t) - 4;
idat = mtod(m, unsigned char *) + (ip->ip_hl << 2) + sizeof(u_int32_t) + 4;
@@ -345,7 +303,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
iv[1] = esp->esp_iv[1];
iv[2] = esp->esp_iv[2];
iv[3] = esp->esp_iv[3];
- if (xd->edx_ivlen == 4) /* Half-IV */
+ if (tdb->tdb_ivlen == 4) /* Half-IV */
{
iv[4] = ~esp->esp_iv[0];
iv[5] = ~esp->esp_iv[1];
@@ -399,8 +357,8 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
mi = (mo = mi)->m_next;
if (mi == NULL)
{
- DPRINTF(("esp_old_input(): bad mbuf chain, SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_input(): bad mbuf chain, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_hdrops++;
return NULL;
@@ -411,7 +369,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
{
if ((mi = m_pullup(mi, blks - rest)) == NULL)
{
- DPRINTF(("esp_old_input(): m_pullup() failed, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_input(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
return NULL;
}
@@ -430,9 +388,9 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
bcopy(idat, blk + rest, blks - rest);
bcopy(blk, ivn, blks);
- xd->edx_xform->decrypt(xd, blk);
+ espx->decrypt(tdb, blk);
- for (i=0; i<blks; i++)
+ for (i=0; i < blks; i++)
blk[i] ^= ivp[i];
ivp = ivn;
@@ -455,7 +413,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
{
bcopy(idat, ivn, blks);
- xd->edx_xform->decrypt(xd, idat);
+ espx->decrypt(tdb, idat);
for (i = 0; i < blks; i++)
idat[i] ^= ivp[i];
@@ -476,7 +434,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
(caddr_t) opts);
if (lblk != blk)
- bcopy(lblk, blk, blks);
+ bcopy(lblk, blk, blks);
/*
* Now, the entire chain has been decrypted. As a side effect,
@@ -487,24 +445,24 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
* the padding may be random.
*/
- if (blk[blks - 2] + 2 > m->m_pkthdr.len - (ip->ip_hl << 2) - sizeof(u_int32_t) -
- xd->edx_ivlen)
+ if (blk[blks - 2] + 2 > m->m_pkthdr.len - (ip->ip_hl << 2) -
+ sizeof(u_int32_t) - tdb->tdb_ivlen)
{
- DPRINTF(("esp_old_input(): invalid padding length %d for packet from %x to %x, SA %x/%08x\n", blk[blks - 2], ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_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)));
espstat.esps_badilen++;
m_freem(m);
return NULL;
}
m_adj(m, - blk[blks - 2] - 2);
- m_adj(m, 4 + xd->edx_ivlen);
+ m_adj(m, 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_old_input(): m_pullup() failed for packet from %x to %x, SA %x/%08x\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_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;
}
@@ -514,7 +472,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
ipo.ip_p = blk[blks - 1];
ipo.ip_id = htons(ipo.ip_id);
ipo.ip_off = 0;
- ipo.ip_len += (ipo.ip_hl << 2) - sizeof(u_int32_t) - xd->edx_ivlen -
+ ipo.ip_len += (ipo.ip_hl << 2) - sizeof(u_int32_t) - tdb->tdb_ivlen -
blk[blks - 2] - 2;
ipo.ip_len = htons(ipo.ip_len);
ipo.ip_sum = 0;
@@ -526,46 +484,6 @@ esp_old_input(struct mbuf *m, struct tdb *tdb)
ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));
- /* Update the counters */
- tdb->tdb_cur_packets++;
- tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) +
- blk[blks - 2] + 2;
- espstat.esps_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) +
- blk[blks - 2] + 2;
-
- /* Notify on expiration */
- if (tdb->tdb_flags & TDBF_SOFT_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_PACKETS;
- }
- else
- if (tdb->tdb_flags & TDBF_SOFT_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
- }
- }
-
- if (tdb->tdb_flags & TDBF_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- else
- if (tdb->tdb_flags & TDBF_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- }
-
return m;
}
@@ -573,7 +491,7 @@ int
esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
struct mbuf **mp)
{
- struct esp_old_xdata *xd;
+ struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
struct ip *ip, ipo;
int i, ilen, ohlen, nh, rlen, plen, padding, rest;
u_int32_t spi;
@@ -582,17 +500,15 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
u_char iv[ESP_3DES_IVS], blk[ESP_3DES_IVS], opts[40];
int iphlen, blks;
- xd = (struct esp_old_xdata *) tdb->tdb_xdata;
-
- blks = xd->edx_xform->blocksize;
+ blks = espx->blocksize;
espstat.esps_output++;
m = m_pullup(m, sizeof(struct ip));
if (m == NULL)
{
- DPRINTF(("esp_old_output(): m_pullup() failed for SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_output(): m_pullup() failed for SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
return ENOBUFS;
}
@@ -609,8 +525,8 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
m = m_pullup(m, iphlen);
if (m == NULL)
{
- DPRINTF(("esp_old_output(): m_pullup() failed for SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_output(): m_pullup() failed for SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
return ENOBUFS;
}
@@ -623,7 +539,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
}
ilen = ntohs(ip->ip_len);
- ohlen = sizeof(u_int32_t) + xd->edx_ivlen;
+ ohlen = sizeof(u_int32_t) + tdb->tdb_ivlen;
ipo = *ip;
nh = ipo.ip_p;
@@ -631,19 +547,46 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
/* Raw payload length */
rlen = ilen - iphlen;
padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
- if (iphlen + ohlen + rlen + padding > IP_MAXPACKET) {
- DPRINTF(("esp_old_output(): packet in SA %x/%0x8 got too big\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ if (iphlen + ohlen + rlen + padding > IP_MAXPACKET)
+ {
+ DPRINTF(("esp_old_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;
}
+ /* Update the counters */
+ tdb->tdb_cur_bytes += rlen;
+ espstat.esps_obytes += rlen;
+
+ /* Hard expiration */
+ if ((tdb->tdb_flags & TDBF_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ tdb_delete(tdb, 0);
+ m_freem(m);
+ return EINVAL;
+ }
+
+ /* Notify on expiration */
+ if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
+ (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
+ {
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
+ }
+
pad = (u_char *) m_pad(m, padding, 1);
if (pad == NULL)
{
- DPRINTF(("esp_old_output(): m_pad() failed for SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_output(): m_pad() failed for SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
return ENOBUFS;
}
@@ -659,24 +602,24 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
* We are now ready to encrypt the payload.
*/
- iv[0] = xd->edx_iv[0];
- iv[1] = xd->edx_iv[1];
- iv[2] = xd->edx_iv[2];
- iv[3] = xd->edx_iv[3];
+ iv[0] = tdb->tdb_iv[0];
+ iv[1] = tdb->tdb_iv[1];
+ iv[2] = tdb->tdb_iv[2];
+ iv[3] = tdb->tdb_iv[3];
- if (xd->edx_ivlen == 4) /* Half-IV */
+ if (tdb->tdb_ivlen == 4) /* Half-IV */
{
- iv[4] = ~xd->edx_iv[0];
- iv[5] = ~xd->edx_iv[1];
- iv[6] = ~xd->edx_iv[2];
- iv[7] = ~xd->edx_iv[3];
+ iv[4] = ~tdb->tdb_iv[0];
+ iv[5] = ~tdb->tdb_iv[1];
+ iv[6] = ~tdb->tdb_iv[2];
+ iv[7] = ~tdb->tdb_iv[3];
}
else
{
- iv[4] = xd->edx_iv[4];
- iv[5] = xd->edx_iv[5];
- iv[6] = xd->edx_iv[6];
- iv[7] = xd->edx_iv[7];
+ iv[4] = tdb->tdb_iv[4];
+ iv[5] = tdb->tdb_iv[5];
+ iv[6] = tdb->tdb_iv[6];
+ iv[7] = tdb->tdb_iv[7];
}
ivp = iv;
@@ -701,8 +644,9 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
mi = (mo = mi)->m_next;
if (mi == NULL)
{
- DPRINTF(("esp_old_output(): bad mbuf chain, SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_output(): bad mbuf chain, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst),
+ ntohl(tdb->tdb_spi)));
m_freem(m);
return EINVAL;
}
@@ -712,7 +656,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
{
if ((mi = m_pullup(mi, blks - rest)) == NULL)
{
- DPRINTF(("esp_old_output(): m_pullup() failed, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_output(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_hdrops++;
return ENOBUFS;
@@ -733,7 +677,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
for (i=0; i<blks; i++)
blk[i] ^= ivp[i];
- xd->edx_xform->encrypt(xd, blk);
+ espx->encrypt(tdb, blk);
ivp = blk;
@@ -753,7 +697,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
for (i = 0; i < blks; i++)
idat[i] ^= ivp[i];
- xd->edx_xform->encrypt(xd, idat);
+ espx->encrypt(tdb, idat);
ivp = idat;
idat += blks;
@@ -771,16 +715,16 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
M_PREPEND(m, ohlen, M_DONTWAIT);
if (m == NULL)
{
- DPRINTF(("esp_old_output(): M_PREPEND failed, SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_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_old_output(): m_pullup() failed, SA %x/%08x\n",
- tdb->tdb_dst, ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_old_output(): m_pullup() failed, SA %s/%08x\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
return ENOBUFS;
}
@@ -788,21 +732,21 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
ipo.ip_len = htons(iphlen + ohlen + rlen + padding);
ipo.ip_p = IPPROTO_ESP;
- iv[0] = xd->edx_iv[0];
- iv[1] = xd->edx_iv[1];
- iv[2] = xd->edx_iv[2];
- iv[3] = xd->edx_iv[3];
+ iv[0] = tdb->tdb_iv[0];
+ iv[1] = tdb->tdb_iv[1];
+ iv[2] = tdb->tdb_iv[2];
+ iv[3] = tdb->tdb_iv[3];
- if (xd->edx_ivlen == 8)
+ if (tdb->tdb_ivlen == 8)
{
- iv[4] = xd->edx_iv[4];
- iv[5] = xd->edx_iv[5];
- iv[6] = xd->edx_iv[6];
- iv[7] = xd->edx_iv[7];
+ iv[4] = tdb->tdb_iv[4];
+ iv[5] = tdb->tdb_iv[5];
+ iv[6] = tdb->tdb_iv[6];
+ iv[7] = tdb->tdb_iv[7];
}
/* Save the last encrypted block, to be used as the next IV */
- bcopy(ivp, xd->edx_iv, xd->edx_ivlen);
+ bcopy(ivp, tdb->tdb_iv, tdb->tdb_ivlen);
m_copyback(m, 0, sizeof(struct ip), (caddr_t) &ipo);
@@ -812,48 +756,10 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
(caddr_t) opts);
m_copyback(m, iphlen, sizeof(u_int32_t), (caddr_t) &spi);
- m_copyback(m, iphlen + sizeof(u_int32_t), xd->edx_ivlen, (caddr_t) iv);
+ m_copyback(m, iphlen + sizeof(u_int32_t), tdb->tdb_ivlen, (caddr_t) iv);
*mp = m;
- /* Update the counters */
- tdb->tdb_cur_packets++;
- tdb->tdb_cur_bytes += rlen + padding;
- espstat.esps_obytes += rlen + padding;
-
- /* Notify on expiration */
- if (tdb->tdb_flags & TDBF_SOFT_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_PACKETS;
- }
- else
- if (tdb->tdb_flags & TDBF_SOFT_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES;
- }
- }
-
- if (tdb->tdb_flags & TDBF_PACKETS)
- {
- if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- else
- if (tdb->tdb_flags & TDBF_BYTES)
- if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- }
-
return 0;
}
diff --git a/sys/netinet/ip_ip4.c b/sys/netinet/ip_ip4.c
index 0315ea03494..46406781679 100644
--- a/sys/netinet/ip_ip4.c
+++ b/sys/netinet/ip_ip4.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ip4.c,v 1.22 1999/01/08 21:51:21 provos Exp $ */
+/* $OpenBSD: ip_ip4.c,v 1.23 1999/02/24 22:33:04 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -64,13 +64,16 @@
#include <sys/socketvar.h>
#include <net/raw_cb.h>
-#include <net/encap.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_ip4.h>
#include <dev/rndvar.h>
-#include <sys/syslog.h>
+#ifdef ENCDEBUG
+#define DPRINTF(x) if (encdebug) printf x
+#else
+#define DPRINTF(x)
+#endif
/*
* ip4_input gets called when we receive an encapsulated packet,
@@ -105,11 +108,7 @@ ip4_input(m, va_alist)
*/
if (iphlen > sizeof(struct ip))
{
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ip4_input(): stripping options\n");
-#endif /* ENCDEBUG */
-
+ DPRINTF(("ip4_input(): stripping options\n"));
ip_stripoptions(m, (struct mbuf *) 0);
iphlen = sizeof(struct ip);
}
@@ -128,11 +127,7 @@ ip4_input(m, va_alist)
{
if ((m = m_pullup(m, iphlen + sizeof(struct ip))) == 0)
{
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ip4_input(): m_pullup() failed\n");
-#endif /* ENCDEBUG */
-
+ DPRINTF(("ip4_input(): m_pullup() failed\n"));
ip4stat.ip4s_hdrops++;
return;
}
@@ -151,8 +146,7 @@ ip4_input(m, va_alist)
if (ipi->ip_v != IPVERSION)
{
- if (encdebug)
- log(LOG_WARNING, "ip4_input(): wrong version %d on IP packet from %x to %x (%x->%x)\n", ipi->ip_v, ipo->ip_src, ipo->ip_dst, ipi->ip_src, ipi->ip_dst);
+ 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++;
return;
}
@@ -165,7 +159,6 @@ ip4_input(m, va_alist)
m->m_len -= iphlen;
m->m_pkthdr.len -= iphlen;
m->m_data += iphlen;
- m->m_flags |= M_TUNNEL;
/*
* Interface pointer stays the same; if no IPsec processing has
@@ -184,10 +177,8 @@ ip4_input(m, va_alist)
m_freem(m);
ip4stat.ip4s_qfull++;
splx(s);
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ip4_input(): packet dropped because of full queue\n");
-#endif /* ENCDEBUG */
+
+ DPRINTF(("ip4_input(): packet dropped because of full queue\n"));
return;
}
@@ -204,6 +195,23 @@ ipe4_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
struct ip *ipo, *ipi;
ushort ilen;
+ /* Check that the source address, if present, is from AF_INET */
+ if ((tdb->tdb_src.sa.sa_family != 0) &&
+ (tdb->tdb_src.sa.sa_family != AF_INET))
+ {
+ DPRINTF(("ipe4_output(): IP in protocol-family <%d> attempted, aborting", tdb->tdb_src.sa.sa_family));
+ m_freem(m);
+ return EINVAL;
+ }
+
+ /* Check that the destination address is AF_INET */
+ if (tdb->tdb_src.sa.sa_family != AF_INET)
+ {
+ DPRINTF(("ipe4_output(): IP in protocol-family <%d> attempted, aborting", tdb->tdb_dst.sa.sa_family));
+ m_freem(m);
+ return EINVAL;
+ }
+
ip4stat.ip4s_opackets++;
ipi = mtod(m, struct ip *);
ilen = ntohs(ipi->ip_len);
@@ -211,10 +219,7 @@ ipe4_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
if (m == 0)
{
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ipe4_output(): M_PREPEND failed\n");
-#endif /* ENCDEBUG */
+ DPRINTF(("ipe4_output(): M_PREPEND failed\n"));
return ENOBUFS;
}
@@ -226,63 +231,33 @@ ipe4_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
ipo->ip_len = htons(ilen + sizeof(struct ip));
ipo->ip_id = ip_randomid();
HTONS(ipo->ip_id);
- ipo->ip_off = ipi->ip_off & ~(IP_MF | IP_OFFMASK); /* keep C and DF */
-
- if (tdb->tdb_flags & TDBF_SAME_TTL)
- ipo->ip_ttl = ipi->ip_ttl;
- else
- if (tdb->tdb_ttl == 0)
- ipo->ip_ttl = ip_defttl;
- else
- ipo->ip_ttl = tdb->tdb_ttl;
-
+ ipo->ip_off = ipi->ip_off & ~(IP_MF | IP_OFFMASK); /* XXX keep C and DF */
+ ipo->ip_ttl = ip_defttl;
ipo->ip_p = IPPROTO_IPIP;
ipo->ip_sum = 0;
- ipo->ip_src = tdb->tdb_osrc;
- ipo->ip_dst = tdb->tdb_odst;
-
-/*
- * printf("ip4_output: [%x->%x](l=%d, p=%d)",
- * ntohl(ipi->ip_src.s_addr), ntohl(ipi->ip_dst.s_addr),
- * ilen, ipi->ip_p);
- * printf(" through [%x->%x](l=%d, p=%d)\n",
- * ntohl(ipo->ip_src.s_addr), ntohl(ipo->ip_dst.s_addr),
- * ipo->ip_len, ipo->ip_p);
- */
+
+ ipo->ip_src = tdb->tdb_src.sin.sin_addr;
+ ipo->ip_dst = tdb->tdb_dst.sin.sin_addr;
*mp = m;
/* Update the counters */
if (tdb->tdb_xform->xf_type == XF_IP4)
- {
- tdb->tdb_cur_packets++;
- tdb->tdb_cur_bytes += ntohs(ipo->ip_len) - (ipo->ip_hl << 2);
- }
+ tdb->tdb_cur_bytes += ntohs(ipo->ip_len) - (ipo->ip_hl << 2);
ip4stat.ip4s_obytes += ntohs(ipo->ip_len) - (ipo->ip_hl << 2);
-
return 0;
-
-/* return ip_output(m, NULL, NULL, IP_ENCAPSULATED, NULL); */
}
int
ipe4_attach()
{
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ipe4_attach(): setting up\n");
-#endif /* ENCDEBUG */
return 0;
}
int
-ipe4_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
+ipe4_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ipe4_init(): setting up\n");
-#endif /* ENCDEBUG */
tdbp->tdb_xform = xsp;
return 0;
}
@@ -290,10 +265,6 @@ ipe4_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
int
ipe4_zeroize(struct tdb *tdbp)
{
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ipe4_zeroize(): nothing to do really...\n");
-#endif /* ENCDEBUG */
return 0;
}
@@ -301,7 +272,7 @@ void
ipe4_input(struct mbuf *m, ...)
{
/* This is a rather serious mistake, so no conditional printing */
- log(LOG_ALERT, "ipe4_input(): should never be called\n");
+ printf("ipe4_input(): should never be called\n");
if (m)
m_freem(m);
}
diff --git a/sys/netinet/ip_ip4.h b/sys/netinet/ip_ip4.h
index 96df0bab5de..ead2d231566 100644
--- a/sys/netinet/ip_ip4.h
+++ b/sys/netinet/ip_ip4.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ip4.h,v 1.11 1999/02/17 18:10:38 deraadt Exp $ */
+/* $OpenBSD: ip_ip4.h,v 1.12 1999/02/24 22:33:04 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -38,15 +38,16 @@
* Not quite all the functionality of RFC-1853, but the main idea is there.
*/
-struct ip4stat {
- u_int32_t ip4s_ipackets; /* total input packets */
- u_int32_t ip4s_opackets; /* total output packets */
- u_int32_t ip4s_hdrops; /* packet shorter than header shows */
- u_int32_t ip4s_badlen;
- u_int32_t ip4s_notip4;
- u_int32_t ip4s_qfull;
- u_int64_t ip4s_ibytes;
- u_int64_t ip4s_obytes;
+struct ip4stat
+{
+ u_int32_t ip4s_ipackets; /* total input packets */
+ u_int32_t ip4s_opackets; /* total output packets */
+ u_int32_t ip4s_hdrops; /* packet shorter than header shows */
+ u_int32_t ip4s_badlen;
+ u_int32_t ip4s_notip4;
+ u_int32_t ip4s_qfull;
+ u_int64_t ip4s_ibytes;
+ u_int64_t ip4s_obytes;
};
#define IP4_DEFAULT_TTL 0
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index 76f1397020d..139e21e6721 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.31 1999/01/11 22:52:10 deraadt Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.32 1999/02/24 22:33:05 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -62,14 +62,13 @@
#include <netinet/ip_icmp.h>
#include <net/raw_cb.h>
-#include <net/encap.h>
+#include <net/pfkeyv2.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_ah.h>
#include <netinet/ip_esp.h>
#include <dev/rndvar.h>
-#include <sys/syslog.h>
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
@@ -77,19 +76,37 @@
#define DPRINTF(x)
#endif
-int tdb_init __P((struct tdb *, struct mbuf *));
int ipsp_kern __P((int, char **, int));
u_int8_t get_sa_require __P((struct inpcb *));
int check_ipsec_policy __P((struct inpcb *, u_int32_t));
-extern void encap_sendnotify __P((int, struct tdb *, void *));
extern int ipsec_auth_default_level;
extern int ipsec_esp_trans_default_level;
extern int ipsec_esp_network_default_level;
int encdebug = 0;
+int ipsec_in_use = 0;
u_int32_t kernfs_epoch = 0;
+u_int8_t hmac_ipad_buffer[64] = {
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 };
+
+u_int8_t hmac_opad_buffer[64] = {
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C };
/*
* This is the proper place to define the various encapsulation transforms.
@@ -100,7 +117,7 @@ struct xformsw xformsw[] = {
ipe4_attach, ipe4_init, ipe4_zeroize,
(struct mbuf * (*)(struct mbuf *, struct tdb *))ipe4_input,
ipe4_output, },
- { XF_OLD_AH, XFT_AUTH, "Keyed Authentication, RFC 1828/1852",
+ { XF_OLD_AH, XFT_AUTH, "Keyed Authentication, RFC 1828/1852",
ah_old_attach, ah_old_init, ah_old_zeroize,
ah_old_input, ah_old_output, },
{ XF_OLD_ESP, XFT_CONF, "Simple Encryption, RFC 1829/1851",
@@ -126,25 +143,28 @@ unsigned char ipseczeroes[IPSEC_ZEROES_SIZE]; /* zeroes! */
u_int8_t
get_sa_require(struct inpcb *inp)
{
- u_int8_t sareq = 0;
+ u_int8_t sareq = 0;
- if (inp != NULL) {
- sareq |= inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_USE ?
- NOTIFY_SATYPE_AUTH : 0;
- sareq |= inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_USE ?
- NOTIFY_SATYPE_CONF : 0;
- sareq |= inp->inp_seclevel[SL_ESP_NETWORK] >= IPSEC_LEVEL_USE ?
- NOTIFY_SATYPE_TUNNEL : 0;
- } else {
- sareq |= ipsec_auth_default_level >= IPSEC_LEVEL_USE ?
- NOTIFY_SATYPE_AUTH : 0;
- sareq |= ipsec_esp_trans_default_level >= IPSEC_LEVEL_USE ?
- NOTIFY_SATYPE_CONF : 0;
- sareq |= ipsec_esp_network_default_level >= IPSEC_LEVEL_USE ?
- NOTIFY_SATYPE_TUNNEL : 0;
- }
-
- return (sareq);
+ if (inp != NULL)
+ {
+ sareq |= inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_USE ?
+ NOTIFY_SATYPE_AUTH : 0;
+ sareq |= inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_USE ?
+ NOTIFY_SATYPE_CONF : 0;
+ sareq |= inp->inp_seclevel[SL_ESP_NETWORK] >= IPSEC_LEVEL_USE ?
+ NOTIFY_SATYPE_TUNNEL : 0;
+ }
+ else
+ {
+ sareq |= ipsec_auth_default_level >= IPSEC_LEVEL_USE ?
+ NOTIFY_SATYPE_AUTH : 0;
+ sareq |= ipsec_esp_trans_default_level >= IPSEC_LEVEL_USE ?
+ NOTIFY_SATYPE_CONF : 0;
+ sareq |= ipsec_esp_network_default_level >= IPSEC_LEVEL_USE ?
+ NOTIFY_SATYPE_TUNNEL : 0;
+ }
+
+ return (sareq);
}
/*
@@ -156,167 +176,185 @@ get_sa_require(struct inpcb *inp)
int
check_ipsec_policy(struct inpcb *inp, u_int32_t daddr)
{
- struct socket *so;
- struct route_enc re0, *re = &re0;
- struct sockaddr_encap *dst;
- struct tdb tmptdb;
- u_int8_t sa_require, sa_have;
- int error, i;
-
- if (inp == NULL || ((so=inp->inp_socket) == 0))
- return (EINVAL);
-
- /* If IPSEC is not required just use what we got */
- if (!(sa_require = inp->inp_secrequire))
- return 0;
-
- bzero((caddr_t) re, sizeof(*re));
- dst = (struct sockaddr_encap *) &re->re_dst;
- dst->sen_family = AF_ENCAP;
- dst->sen_len = SENT_IP4_LEN;
- dst->sen_type = SENT_IP4;
- dst->sen_ip_src = inp->inp_laddr;
- dst->sen_ip_dst.s_addr = inp->inp_faddr.s_addr ?
- inp->inp_faddr.s_addr : daddr;
- dst->sen_proto = so->so_proto->pr_protocol;
- switch (dst->sen_proto) {
+ union sockaddr_union sunion;
+ struct socket *so;
+ struct route_enc re0, *re = &re0;
+ struct sockaddr_encap *dst;
+ u_int8_t sa_require, sa_have;
+ int error, i;
+
+ if (inp == NULL || ((so = inp->inp_socket) == 0))
+ return (EINVAL);
+
+ /* If IPSEC is not required just use what we got */
+ if (!(sa_require = inp->inp_secrequire))
+ return 0;
+
+ bzero((caddr_t) re, sizeof(*re));
+ dst = (struct sockaddr_encap *) &re->re_dst;
+ dst->sen_family = PF_KEY;
+ dst->sen_len = SENT_IP4_LEN;
+ dst->sen_type = SENT_IP4;
+ dst->sen_ip_src = inp->inp_laddr;
+ dst->sen_ip_dst.s_addr = inp->inp_faddr.s_addr ?
+ inp->inp_faddr.s_addr : daddr;
+ dst->sen_proto = so->so_proto->pr_protocol;
+ switch (dst->sen_proto)
+ {
case IPPROTO_UDP:
case IPPROTO_TCP:
- dst->sen_sport = inp->inp_lport;
- dst->sen_dport = inp->inp_fport;
- break;
+ dst->sen_sport = inp->inp_lport;
+ dst->sen_dport = inp->inp_fport;
+ break;
default:
- dst->sen_sport = 0;
- dst->sen_dport = 0;
+ dst->sen_sport = 0;
+ dst->sen_dport = 0;
+ }
+
+ /* Try to find a flow */
+ rtalloc((struct route *) re);
+
+ if (re->re_rt != NULL)
+ {
+ struct tdb *tdb;
+ struct sockaddr_encap *gw;
+
+ gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway);
+
+ if (gw->sen_type == SENT_IPSP) {
+ sunion.sin.sin_family = AF_INET;
+ sunion.sin.sin_len = sizeof(struct sockaddr_in);
+ sunion.sin.sin_addr = gw->sen_ipsp_dst;
+
+ tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion,
+ gw->sen_ipsp_sproto);
+
+ SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb);
}
+ else
+ sa_have = 0;
+
+ RTFREE(re->re_rt);
+
+ /* Check if our requirements are met */
+ if (!(sa_require & ~sa_have))
+ return 0;
+ }
+ else
+ sa_have = 0;
- /* Try to find a flow */
- rtalloc((struct route *) re);
+ error = i = 0;
- if (re->re_rt != NULL) {
- struct tdb *tdb;
- struct sockaddr_encap *gw;
-
- gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway);
-
- if (gw->sen_type == SENT_IPSP) {
- tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi,
- gw->sen_ipsp_dst,
- gw->sen_ipsp_sproto);
-
- SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb);
- } else
- sa_have = 0;
-
- RTFREE(re->re_rt);
-
- /* Check if our requirements are met */
- if (!(sa_require & ~sa_have))
- return 0;
- } else
- sa_have = 0;
-
- error = i = 0;
-
- inp->inp_secresult = SR_WAIT;
-
- /* If necessary try to notify keymanagement three times */
- while (i < 3) {
- DPRINTF(("ipsec: send SA request (%d), remote ip: %0x, SA type: %d\n", i+1, dst->sen_ip_dst, sa_require));
-
- /* Send notify */
- bzero((caddr_t) &tmptdb, sizeof(tmptdb));
- tmptdb.tdb_src = dst->sen_ip_src;
- tmptdb.tdb_dst = dst->sen_ip_dst;
- /*
- * When we already have an insufficient SA, we need to
- * establish a new SA which combines the required
- * attributes and the already existant. This can go
- * once we can do socket specific keying.
- */
- tmptdb.tdb_satype = sa_require | sa_have;
- encap_sendnotify(NOTIFY_REQUEST_SA, &tmptdb, inp);
+ inp->inp_secresult = SR_WAIT;
+
+ /* If necessary try to notify keymanagement three times */
+ while (i < 3)
+ {
+ /* XXX address */
+ DPRINTF(("ipsec: send SA request (%d), remote ip: %s, SA type: %d\n",
+ i + 1, inet_ntoa4(dst->sen_ip_dst), sa_require));
+
+ /* Send notify */
+ /* XXX PF_KEYv2 Notify */
- /*
- * Wait for the keymanagement daemon to establich a new SA,
- * even on error check again, perhaps some other process
- * already established the necessary SA.
- */
- error = tsleep((caddr_t)inp, PSOCK|PCATCH, "ipsecnotify", 30*hz);
-
- DPRINTF(("check_ipsec: sleep %d\n", error));
-
- if (error && error != EWOULDBLOCK)
- break;
- /*
- * A Key Management daemon returned an apropriate SA back
- * to the kernel, the kernel noted that state in the waiting
- * socket.
- */
- if (inp->inp_secresult == SR_SUCCESS)
- return (0);
- /*
- * Key Management returned a permanent failure, we do not
- * need to retry again. XXX - when more than one key
- * management daemon is available we can not do that.
- */
- if (inp->inp_secresult == SR_FAILED)
- break;
- i++;
- }
+ /*
+ * Wait for the keymanagement daemon to establich a new SA,
+ * even on error check again, perhaps some other process
+ * already established the necessary SA.
+ */
+ error = tsleep((caddr_t)inp, PSOCK|PCATCH, "ipsecnotify", 30*hz);
+ DPRINTF(("check_ipsec: sleep %d\n", error));
+
+ if (error && error != EWOULDBLOCK)
+ break;
+ /*
+ * A Key Management daemon returned an apropriate SA back
+ * to the kernel, the kernel noted that state in the waiting
+ * socket.
+ */
+ if (inp->inp_secresult == SR_SUCCESS)
+ return (0);
+ /*
+ * Key Management returned a permanent failure, we do not
+ * need to retry again. XXX - when more than one key
+ * management daemon is available we can not do that.
+ */
+ if (inp->inp_secresult == SR_FAILED)
+ break;
+ i++;
+ }
- return (error ? error : EWOULDBLOCK);
+ return (error ? error : EWOULDBLOCK);
}
/*
* Reserve an SPI; the SA is not valid yet though. Zero is reserved as
* an error return value. If tspi is not zero, we try to allocate that
- * SPI. SPIs less than 255 are reserved, so we check for those too.
+ * SPI.
*/
u_int32_t
-reserve_spi(u_int32_t tspi, struct in_addr src, u_int8_t proto, int *errval)
+reserve_spi(u_int32_t sspi, u_int32_t tspi, union sockaddr_union *src,
+ union sockaddr_union *dst, u_int8_t sproto, int *errval)
{
struct tdb *tdbp;
- u_int32_t spi = tspi; /* Don't change */
+ u_int32_t spi;
+ int nums;
+
+ if (tspi <= 255) /* We don't reserve 0 < SPI <= 255 */
+ {
+ (*errval) = EEXIST;
+ return 0;
+ }
- while (1)
+ if ((sspi == tspi) && (sspi != 0)) /* Asking for a specific SPI */
+ nums = 1;
+ else
+ nums = 50; /* XXX figure out some good value */
+
+ while (nums--)
{
- while (ntohl(spi) <= 255) /* Get a new SPI */
- get_random_bytes((void *) &spi, sizeof(spi));
-
- /* Check whether we're using this SPI already */
- if (gettdb(spi, src, proto) != (struct tdb *) NULL)
+ if (tspi != 0) /* SPIRANGE was defined */
{
- if (tspi != 0) /* If one was proposed, report error */
+ if (sspi == tspi) /* Specific SPI asked */
+ spi = tspi;
+ else /* Range specified */
{
- (*errval) = EEXIST;
- return 0;
+ get_random_bytes((void *) &spi, sizeof(spi));
+ spi = sspi + (spi % (tspi - sspi));
}
-
- spi = 0;
- continue;
}
-
- MALLOC(tdbp, struct tdb *, sizeof(*tdbp), M_TDB, M_WAITOK);
- if (tdbp == NULL)
- {
- (*errval) = ENOBUFS;
- return 0;
- }
+ else /* Some SPI */
+ get_random_bytes((void *) &spi, sizeof(spi));
+
+ if (spi <= 255) /* Don't allocate SPI <= 255, they're reserved */
+ continue;
+ else
+ spi = htonl(spi);
- bzero((caddr_t) tdbp, sizeof(*tdbp));
+ /* Check whether we're using this SPI already */
+ if (gettdb(spi, dst, sproto) != (struct tdb *) NULL)
+ continue;
+
+ MALLOC(tdbp, struct tdb *, sizeof(struct tdb), M_TDB, M_WAITOK);
+ bzero((caddr_t) tdbp, sizeof(struct tdb));
tdbp->tdb_spi = spi;
- tdbp->tdb_dst = src;
- tdbp->tdb_sproto = proto;
- tdbp->tdb_flags |= TDBF_INVALID;
+ bcopy(&dst->sa, &tdbp->tdb_dst.sa, SA_LEN(&dst->sa));
+ bcopy(&src->sa, &tdbp->tdb_src.sa, SA_LEN(&src->sa));
+ tdbp->tdb_sproto = sproto;
+ tdbp->tdb_flags |= TDBF_INVALID; /* Mark SA as invalid for now */
+ tdbp->tdb_established = time.tv_sec;
tdbp->tdb_epoch = kernfs_epoch - 1;
-
puttdb(tdbp);
+
+ /* XXX Should set up a silent expiration for this */
return spi;
}
+
+ (*errval) = EEXIST;
+ return 0;
}
/*
@@ -328,16 +366,22 @@ reserve_spi(u_int32_t tspi, struct in_addr src, u_int8_t proto, int *errval)
*/
struct tdb *
-gettdb(u_int32_t spi, struct in_addr dst, u_int8_t proto)
+gettdb(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto)
{
- int hashval;
+ u_int8_t *ptr = (u_int8_t *) dst;
+ u_int32_t hashval = proto + spi;
struct tdb *tdbp;
-
- hashval = (spi + dst.s_addr + proto) % TDB_HASHMOD;
-
+ int i;
+
+ for (i = 0; i < SA_LEN(&dst->sa); i++)
+ hashval += ptr[i];
+
+ hashval %= TDB_HASHMOD;
+
for (tdbp = tdbh[hashval]; tdbp; tdbp = tdbp->tdb_hnext)
- if ((tdbp->tdb_spi == spi) && (tdbp->tdb_dst.s_addr == dst.s_addr)
- && (tdbp->tdb_sproto == proto))
+ if ((tdbp->tdb_spi == spi) &&
+ !bcmp(&tdbp->tdb_dst, dst, SA_LEN(&dst->sa)) &&
+ (tdbp->tdb_sproto == proto))
break;
return tdbp;
@@ -349,9 +393,6 @@ get_flow(void)
struct flow *flow;
MALLOC(flow, struct flow *, sizeof(struct flow), M_TDB, M_WAITOK);
- if (flow == (struct flow *) NULL)
- return (struct flow *) NULL;
-
bzero(flow, sizeof(struct flow));
return flow;
@@ -364,8 +405,6 @@ get_expiration(void)
MALLOC(exp, struct expiration *, sizeof(struct expiration), M_TDB,
M_WAITOK);
- if (exp == (struct expiration *) NULL)
- return (struct expiration *) NULL;
bzero(exp, sizeof(struct expiration));
@@ -373,12 +412,12 @@ get_expiration(void)
}
void
-cleanup_expirations(struct in_addr dst, u_int32_t spi, u_int8_t sproto)
+cleanup_expirations(union sockaddr_union *dst, u_int32_t spi, u_int8_t sproto)
{
struct expiration *exp, *nexp;
-
- for (exp = explist; exp; exp = exp ? exp->exp_next : explist)
- if ((exp->exp_dst.s_addr == dst.s_addr) &&
+
+ for (exp = explist; exp; exp = (exp ? exp->exp_next : explist))
+ if (!bcmp(&exp->exp_dst, dst, SA_LEN(&dst->sa)) &&
(exp->exp_spi == spi) && (exp->exp_sproto == sproto))
{
/* Link previous to next */
@@ -390,10 +429,10 @@ cleanup_expirations(struct in_addr dst, u_int32_t spi, u_int8_t sproto)
/* Link next (if it exists) to previous */
if (exp->exp_next != (struct expiration *) NULL)
exp->exp_next->exp_prev = exp->exp_prev;
-
+
nexp = exp;
exp = exp->exp_prev;
- free(nexp, M_TDB);
+ FREE(nexp, M_TDB);
}
}
@@ -421,48 +460,51 @@ handle_expirations(void *arg)
if (explist)
explist->exp_prev = NULL;
- tdb = gettdb(exp->exp_spi, exp->exp_dst, exp->exp_sproto);
+ tdb = gettdb(exp->exp_spi, &exp->exp_dst, exp->exp_sproto);
if (tdb == (struct tdb *) NULL)
{
free(exp, M_TDB);
continue; /* TDB is gone, ignore this */
}
- /* Soft expirations */
- if (tdb->tdb_flags & TDBF_SOFT_TIMER)
+ /* Hard expirations first */
+ if ((tdb->tdb_flags & TDBF_TIMER) &&
+ (tdb->tdb_exp_timeout <= time.tv_sec))
{
- if (tdb->tdb_soft_timeout <= time.tv_sec)
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ tdb_delete(tdb, 0);
+ }
+ else
+ if ((tdb->tdb_flags & TDBF_FIRSTUSE) &&
+ (tdb->tdb_first_use + tdb->tdb_exp_first_use <= time.tv_sec))
{
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_TIMER;
+/* XXX
+ encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
+*/
+ tdb_delete(tdb, 0);
}
- else
- if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE)
- if (tdb->tdb_first_use + tdb->tdb_soft_first_use <=
- time.tv_sec)
- {
- encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
- tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE;
- }
- }
- /* Hard expirations */
- if (tdb->tdb_flags & TDBF_TIMER)
+ /* Soft expirations */
+ if ((tdb->tdb_flags & TDBF_SOFT_TIMER) &&
+ (tdb->tdb_soft_timeout <= time.tv_sec))
{
- if (tdb->tdb_exp_timeout <= time.tv_sec)
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ tdb->tdb_flags &= ~TDBF_SOFT_TIMER;
+ }
+ else
+ if ((tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) &&
+ (tdb->tdb_first_use + tdb->tdb_soft_first_use <=
+ time.tv_sec))
{
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
+/* XXX
+ encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL);
+*/
+ tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE;
}
- else
- if (tdb->tdb_flags & TDBF_FIRSTUSE)
- if (tdb->tdb_first_use + tdb->tdb_exp_first_use <=
- time.tv_sec)
- {
- encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL);
- tdb_delete(tdb, 0);
- }
- }
free(exp, M_TDB);
}
@@ -535,28 +577,27 @@ put_expiration(struct expiration *exp)
}
struct flow *
-find_flow(struct in_addr src, struct in_addr srcmask, struct in_addr dst,
- struct in_addr dstmask, u_int8_t proto, u_int16_t sport,
- u_int16_t dport, struct tdb *tdb)
+find_flow(union sockaddr_union *src, union sockaddr_union *srcmask,
+ union sockaddr_union * dst, union sockaddr_union *dstmask,
+ u_int8_t proto, struct tdb *tdb)
{
struct flow *flow;
for (flow = tdb->tdb_flow; flow; flow = flow->flow_next)
- if ((src.s_addr == flow->flow_src.s_addr) &&
- (dst.s_addr == flow->flow_dst.s_addr) &&
- (srcmask.s_addr == flow->flow_srcmask.s_addr) &&
- (dstmask.s_addr == flow->flow_dstmask.s_addr) &&
- (proto == flow->flow_proto) &&
- (sport == flow->flow_sport) && (dport == flow->flow_dport))
+ if (!bcmp(&src->sa, &flow->flow_src.sa, SA_LEN(&src->sa)) &&
+ !bcmp(&dst->sa, &flow->flow_dst.sa, SA_LEN(&dst->sa)) &&
+ !bcmp(&srcmask->sa, &flow->flow_srcmask.sa, SA_LEN(&srcmask->sa)) &&
+ !bcmp(&dstmask->sa, &flow->flow_dstmask.sa, SA_LEN(&dstmask->sa)) &&
+ (proto == flow->flow_proto))
return flow;
return (struct flow *) NULL;
}
struct flow *
-find_global_flow(struct in_addr src, struct in_addr srcmask,
- struct in_addr dst, struct in_addr dstmask,
- u_int8_t proto, u_int16_t sport, u_int16_t dport)
+find_global_flow(union sockaddr_union *src, union sockaddr_union *srcmask,
+ union sockaddr_union *dst, union sockaddr_union *dstmask,
+ u_int8_t proto)
{
struct flow *flow;
struct tdb *tdb;
@@ -564,8 +605,8 @@ find_global_flow(struct in_addr src, struct in_addr srcmask,
for (i = 0; i < TDB_HASHMOD; i++)
for (tdb = tdbh[i]; tdb; tdb = tdb->tdb_hnext)
- if ((flow = find_flow(src, srcmask, dst, dstmask, proto, sport,
- dport, tdb)) != (struct flow *) NULL)
+ if ((flow = find_flow(src, srcmask, dst, dstmask, proto, tdb)) !=
+ (struct flow *) NULL)
return flow;
return (struct flow *) NULL;
@@ -574,10 +615,13 @@ find_global_flow(struct in_addr src, struct in_addr srcmask,
void
puttdb(struct tdb *tdbp)
{
- int hashval;
+ u_int8_t *ptr = (u_int8_t *) &tdbp->tdb_dst;
+ u_int32_t hashval = tdbp->tdb_sproto + tdbp->tdb_spi, i;
- hashval = ((tdbp->tdb_sproto + tdbp->tdb_spi + tdbp->tdb_dst.s_addr)
- % TDB_HASHMOD);
+ for (i = 0; i < SA_LEN(&tdbp->tdb_dst.sa); i++)
+ hashval += ptr[i];
+
+ hashval %= TDB_HASHMOD;
tdbp->tdb_hnext = tdbh[hashval];
tdbh[hashval] = tdbp;
}
@@ -599,17 +643,20 @@ put_flow(struct flow *flow, struct tdb *tdb)
void
delete_flow(struct flow *flow, struct tdb *tdb)
{
- if (tdb->tdb_flow == flow)
+ if (tdb)
{
- tdb->tdb_flow = flow->flow_next;
- if (tdb->tdb_flow)
- tdb->tdb_flow->flow_prev = (struct flow *) NULL;
- }
- else
- {
- flow->flow_prev->flow_next = flow->flow_next;
- if (flow->flow_next)
- flow->flow_next->flow_prev = flow->flow_prev;
+ if (tdb->tdb_flow == flow)
+ {
+ tdb->tdb_flow = flow->flow_next;
+ if (tdb->tdb_flow)
+ tdb->tdb_flow->flow_prev = (struct flow *) NULL;
+ }
+ else
+ {
+ flow->flow_prev->flow_next = flow->flow_next;
+ if (flow->flow_next)
+ flow->flow_next->flow_prev = flow->flow_prev;
+ }
}
FREE(flow, M_TDB);
@@ -618,12 +665,15 @@ delete_flow(struct flow *flow, struct tdb *tdb)
int
tdb_delete(struct tdb *tdbp, int delchain)
{
+ u_int8_t *ptr = (u_int8_t *) &tdbp->tdb_dst;
struct tdb *tdbpp;
struct flow *flow;
- int hashval;
+ u_int32_t hashval = tdbp->tdb_sproto + tdbp->tdb_spi, i;
- hashval = ((tdbp->tdb_sproto + tdbp->tdb_spi + tdbp->tdb_dst.s_addr)
- % TDB_HASHMOD);
+ for (i = 0; i < SA_LEN(&tdbp->tdb_dst.sa); i++)
+ hashval += ptr[i];
+
+ hashval %= TDB_HASHMOD;
if (tdbh[hashval] == tdbp)
{
@@ -638,27 +688,41 @@ tdb_delete(struct tdb *tdbp, int delchain)
tdbpp = tdbp;
}
- if (tdbp != tdbpp)
- return EINVAL; /* Should never happen */
-
- /* If there was something before us in the chain, make it point nowhere */
- if (tdbp->tdb_inext)
+ /*
+ * If there was something before us in the chain pointing to us,
+ * make it point nowhere
+ */
+ if ((tdbp->tdb_inext) &&
+ (tdbp->tdb_inext->tdb_onext == tdbp))
tdbp->tdb_inext->tdb_onext = NULL;
- /* If there was something after us in the chain, make it point nowhere */
- if (tdbp->tdb_onext)
+ /*
+ * If there was something after us in the chain pointing to us,
+ * make it point nowhere
+ */
+ if ((tdbp->tdb_onext) &&
+ (tdbp->tdb_onext->tdb_inext == tdbp))
tdbp->tdb_onext->tdb_inext = NULL;
-
+
tdbpp = tdbp->tdb_onext;
-
+
if (tdbp->tdb_xform)
(*(tdbp->tdb_xform->xf_zeroize))(tdbp);
for (flow = tdbp->tdb_flow; flow; flow = tdbp->tdb_flow)
- delete_flow(flow, tdbp);
+ {
+ delete_flow(flow, tdbp);
+ ipsec_in_use--;
+ }
+
+ cleanup_expirations(&tdbp->tdb_dst, tdbp->tdb_spi, tdbp->tdb_sproto);
+
+ if (tdbp->tdb_srcid)
+ FREE(tdbp->tdb_srcid, M_XDATA);
+
+ if (tdbp->tdb_dstid)
+ FREE(tdbp->tdb_dstid, M_XDATA);
- cleanup_expirations(tdbp->tdb_dst, tdbp->tdb_spi, tdbp->tdb_sproto);
-
FREE(tdbp, M_TDB);
if (delchain && tdbpp)
@@ -668,26 +732,21 @@ tdb_delete(struct tdb *tdbp, int delchain)
}
int
-tdb_init(struct tdb *tdbp, struct mbuf *m)
+tdb_init(struct tdb *tdbp, u_int16_t alg, struct ipsecinit *ii)
{
- int alg;
- struct encap_msghdr *em;
struct xformsw *xsp;
-
- em = mtod(m, struct encap_msghdr *);
- alg = em->em_alg;
/* Record establishment time */
tdbp->tdb_established = time.tv_sec;
-
tdbp->tdb_epoch = kernfs_epoch - 1;
for (xsp = xformsw; xsp < xformswNXFORMSW; xsp++)
if (xsp->xf_type == alg)
- return (*(xsp->xf_init))(tdbp, xsp, m);
+ return (*(xsp->xf_init))(tdbp, xsp, ii);
- DPRINTF(("tdb_init(): no alg %d for spi %08x, addr %x, proto %d\n",
- alg, ntohl(tdbp->tdb_spi), tdbp->tdb_dst.s_addr, tdbp->tdb_sproto));
+ DPRINTF(("tdb_init(): no alg %d for spi %08x, addr %s, proto %d\n",
+ alg, ntohl(tdbp->tdb_spi), ipsp_address(tdbp->tdb_dst),
+ tdbp->tdb_sproto));
return EINVAL;
}
@@ -700,7 +759,6 @@ ipsp_kern(int off, char **bufp, int len)
{
static char buffer[IPSEC_KERNFS_BUFSIZE];
struct tdb *tdb;
- struct flow *fl;
int l, i;
if (off == 0)
@@ -720,59 +778,119 @@ ipsp_kern(int off, char **bufp, int len)
tdb->tdb_epoch = kernfs_epoch;
l = sprintf(buffer, "SPI = %08x, Destination = %s, Sproto = %u\n",
- ntohl(tdb->tdb_spi), inet_ntoa(tdb->tdb_dst),
- tdb->tdb_sproto);
-
- l += sprintf(buffer + l, "\testablished %d seconds ago\n",
+ ntohl(tdb->tdb_spi),
+ ipsp_address(tdb->tdb_dst), tdb->tdb_sproto);
+
+ l += sprintf(buffer + l, "\tEstablished %d seconds ago\n",
time.tv_sec - tdb->tdb_established);
-
- l += sprintf(buffer + l, "\tsrc = %s, flags = %08x, SAtype = %u\n",
- inet_ntoa(tdb->tdb_src), tdb->tdb_flags,
- tdb->tdb_satype);
+
+ l += sprintf(buffer + l, "\tSource = %s",
+ ipsp_address(tdb->tdb_src));
+
+ if (tdb->tdb_proxy.sa.sa_family)
+ l += sprintf(buffer + l, ", Proxy = %s\n",
+ ipsp_address(tdb->tdb_proxy));
+ else
+ l += sprintf(buffer + l, "\n");
+
+ l += sprintf(buffer + l, "\tFlags (%08x) = <", tdb->tdb_flags);
+
+ if ((tdb->tdb_flags & ~(TDBF_TIMER | TDBF_BYTES |
+ TDBF_ALLOCATIONS | TDBF_FIRSTUSE |
+ TDBF_SOFT_TIMER | TDBF_SOFT_BYTES |
+ TDBF_SOFT_FIRSTUSE |
+ TDBF_SOFT_ALLOCATIONS)) == 0)
+ l += sprintf(buffer + l, "none>\n");
+ else
+ {
+ /* We can reuse variable 'i' here, since we're not looping */
+ i = 0;
+
+ if (tdb->tdb_flags & TDBF_UNIQUE)
+ {
+ if (i)
+ l += sprintf(buffer + l, ", ");
+ else
+ i = 1;
+
+ l += sprintf(buffer + l, "unique");
+ i = 1;
+ }
+
+ if (tdb->tdb_flags & TDBF_INVALID)
+ {
+ if (i)
+ l += sprintf(buffer + l, ", ");
+ else
+ i = 1;
+
+ l += sprintf(buffer + l, "invalid");
+ }
+
+ if (tdb->tdb_flags & TDBF_HALFIV)
+ {
+ if (i)
+ l += sprintf(buffer + l, ", ");
+ else
+ i = 1;
+
+ l += sprintf(buffer + l, "halviv");
+ }
+
+ if (tdb->tdb_flags & TDBF_PFS)
+ {
+ if (i)
+ l += sprintf(buffer + l, ", ");
+ else
+ i = 1;
+
+ l += sprintf(buffer + l, "pfs");
+ }
+
+ if (tdb->tdb_flags & TDBF_TUNNELING)
+ {
+ if (i)
+ l += sprintf(buffer + l, ", ");
+ else
+ i = 1;
+
+ l += sprintf(buffer + l, "tunneling");
+ }
+
+ l += sprintf(buffer + l, ">\n");
+ }
if (tdb->tdb_xform)
l += sprintf(buffer + l, "\txform = <%s>\n",
tdb->tdb_xform->xf_name);
- else
- l += sprintf(buffer + l, "\txform = <(null)>\n");
- if (tdb->tdb_confname)
- l += sprintf(buffer + l, "\t\tencryption = <%s>\n",
- tdb->tdb_confname);
- if (tdb->tdb_authname)
- l += sprintf(buffer + l, "\t\tauthentication = <%s>\n",
- tdb->tdb_authname);
+ if (tdb->tdb_encalgxform)
+ l += sprintf(buffer + l, "\t\tEncryption = <%s>\n",
+ tdb->tdb_encalgxform->name);
- l += sprintf(buffer + l, "\tOSrc = %s", inet_ntoa(tdb->tdb_osrc));
-
- l += sprintf(buffer + l, " ODst = %s, TTL = %u\n",
- inet_ntoa(tdb->tdb_odst), tdb->tdb_ttl);
+ if (tdb->tdb_authalgxform)
+ l += sprintf(buffer + l, "\t\tAuthentication = <%s>\n",
+ tdb->tdb_authalgxform->name);
if (tdb->tdb_onext)
l += sprintf(buffer + l,
- "\tNext (on output) SA: SPI = %08x, "
+ "\tNext SA: SPI = %08x, "
"Destination = %s, Sproto = %u\n",
ntohl(tdb->tdb_onext->tdb_spi),
- inet_ntoa(tdb->tdb_onext->tdb_dst),
+ ipsp_address(tdb->tdb_onext->tdb_dst),
tdb->tdb_onext->tdb_sproto);
if (tdb->tdb_inext)
l += sprintf(buffer + l,
- "\tNext (on input) SA: SPI = %08x, "
+ "\tPrevious SA: SPI = %08x, "
"Destination = %s, Sproto = %u\n",
ntohl(tdb->tdb_inext->tdb_spi),
- inet_ntoa(tdb->tdb_inext->tdb_dst),
+ ipsp_address(tdb->tdb_inext->tdb_dst),
tdb->tdb_inext->tdb_sproto);
- /* XXX We can reuse variable i, we're not going to loop again */
- for (i = 0, fl = tdb->tdb_flow; fl; fl = fl->flow_next)
- i++;
+ if (tdb->tdb_flow)
+ l+= sprintf(buffer + l, "\tUsed by at least one flow\n");
- l += sprintf(buffer + l,
- "\t%u flows counted "
- "(use netstat -r for more information)\n",
- i);
-
l += sprintf(buffer + l, "\tExpirations:\n");
if (tdb->tdb_flags & TDBF_TIMER)
@@ -793,29 +911,34 @@ ipsp_kern(int off, char **bufp, int len)
l += sprintf(buffer + l, "\t\tSoft expiration after %qu bytes\n",
tdb->tdb_soft_bytes);
+ if ((tdb->tdb_flags & TDBF_BYTES) ||
+ (tdb->tdb_flags & TDBF_SOFT_BYTES))
l += sprintf(buffer + l, "\t\tCurrently %qu bytes processed\n",
tdb->tdb_cur_bytes);
- if (tdb->tdb_flags & TDBF_PACKETS)
+ if (tdb->tdb_flags & TDBF_ALLOCATIONS)
l += sprintf(buffer + l,
- "\t\tHard expiration after %qu packets\n",
- tdb->tdb_exp_packets);
+ "\t\tHard expiration after %u flows\n",
+ tdb->tdb_exp_allocations);
- if (tdb->tdb_flags & TDBF_SOFT_PACKETS)
+ if (tdb->tdb_flags & TDBF_SOFT_ALLOCATIONS)
l += sprintf(buffer + l,
- "\t\tSoft expiration after %qu packets\n",
- tdb->tdb_soft_packets);
+ "\t\tSoft expiration after %u flows\n",
+ tdb->tdb_soft_allocations);
- l += sprintf(buffer + l, "\t\tCurrently %qu packets processed\n",
- tdb->tdb_cur_packets);
+ if ((tdb->tdb_flags & TDBF_ALLOCATIONS) ||
+ (tdb->tdb_flags & TDBF_SOFT_ALLOCATIONS))
+ l += sprintf(buffer + l, "\t\tCurrently %u flows processed\n",
+ tdb->tdb_cur_allocations);
- if (tdb->tdb_flags & TDBF_FIRSTUSE) {
- if (tdb->tdb_first_use)
+ if (tdb->tdb_flags & TDBF_FIRSTUSE)
+ {
+ if (tdb->tdb_first_use)
l += sprintf(buffer + l,
"\t\tHard expiration(2) in %qu seconds\n",
(tdb->tdb_first_use + tdb->tdb_exp_first_use) -
time.tv_sec);
- else
+ else
l += sprintf(buffer + l,
"\t\tHard expiration in %qu seconds after first "
"use\n", tdb->tdb_exp_first_use);
@@ -834,7 +957,7 @@ ipsp_kern(int off, char **bufp, int len)
}
if (!(tdb->tdb_flags & (TDBF_TIMER | TDBF_SOFT_TIMER | TDBF_BYTES |
- TDBF_SOFT_PACKETS | TDBF_PACKETS |
+ TDBF_SOFT_ALLOCATIONS | TDBF_ALLOCATIONS |
TDBF_SOFT_BYTES | TDBF_FIRSTUSE |
TDBF_SOFT_FIRSTUSE)))
l += sprintf(buffer + l, "\t\t(none)\n");
@@ -846,3 +969,33 @@ ipsp_kern(int off, char **bufp, int len)
return 0;
}
+
+char *
+inet_ntoa4(struct in_addr ina)
+{
+ static char buf[4][4 * sizeof "123"];
+ unsigned char *ucp = (unsigned char *) &ina;
+ static int i = 1;
+
+ i = (i + 1) % 2;
+ sprintf(buf[i], "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff,
+ ucp[2] & 0xff, ucp[3] & 0xff);
+ return (buf[i]);
+}
+
+char *
+ipsp_address(union sockaddr_union sa)
+{
+ switch (sa.sa.sa_family)
+ {
+ case AF_INET:
+ return inet_ntoa4(sa.sin.sin_addr);
+
+#if INET6
+ /* XXX Add AF_INET6 support here */
+#endif /* INET6 */
+
+ default:
+ return "(unknown address family)";
+ }
+}
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index 34f306f4a92..ab34c6c6796 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.23 1999/02/17 20:39:17 deraadt Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.24 1999/02/24 22:33:06 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -37,119 +37,291 @@
* IPSP global definitions.
*/
-struct expiration {
- u_int32_t exp_timeout;
- struct in_addr exp_dst;
- u_int32_t exp_spi;
- u_int8_t exp_sproto;
- struct expiration *exp_next;
- struct expiration *exp_prev;
+#include <sys/md5k.h>
+#include <netinet/ip_sha1.h>
+#include <netinet/ip_rmd160.h>
+#include <netinet/ip_blf.h>
+#include <netinet/ip_cast.h>
+#include <sys/socket.h>
+
+/* HMAC key sizes */
+#define MD5HMAC96_KEYSIZE 16
+#define SHA1HMAC96_KEYSIZE 20
+#define RIPEMD160HMAC96_KEYSIZE 20
+
+/* IV lengths */
+#define ESP_DES_IVS 8
+#define ESP_3DES_IVS 8
+#define ESP_BLF_IVS 8
+#define ESP_CAST_IVS 8
+#define ESP_MAX_IVS 8 /* Keep updated */
+
+/* Block sizes -- it is assumed that they're powers of 2 */
+#define ESP_DES_BLKS 8
+#define ESP_3DES_BLKS 8
+#define ESP_BLF_BLKS 8
+#define ESP_CAST_BLKS 8
+#define ESP_MAX_BLKS 8 /* Keep updated */
+
+#define HMAC_BLOCK_LEN 64
+
+#define AH_HMAC_HASHLEN 12 /* 96 bits of authenticator */
+#define AH_HMAC_RPLENGTH 4 /* 32 bits of replay counter */
+#define AH_HMAC_INITIAL_RPL 1 /* Replay counter initial value */
+
+/* HMAC definitions */
+#define HMAC_IPAD_VAL 0x36
+#define HMAC_OPAD_VAL 0x5C
+#define HMAC_BLOCK_LEN 64
+
+/* Authenticator lengths */
+#define AH_MD5_ALEN 16
+#define AH_SHA1_ALEN 20
+#define AH_RMD160_ALEN 20
+#define AH_ALEN_MAX 20 /* Keep updated */
+
+struct sockaddr_encap
+{
+ u_int8_t sen_len; /* length */
+ u_int8_t sen_family; /* PF_KEY */
+ u_int16_t sen_type; /* see SENT_* */
+ union
+ {
+ u_int8_t Data[16]; /* other stuff mapped here */
+
+ struct /* SENT_IP4 */
+ {
+ struct in_addr Src;
+ struct in_addr Dst;
+ u_int16_t Sport;
+ u_int16_t Dport;
+ u_int8_t Proto;
+ u_int8_t Filler[3];
+ } Sip4;
+
+ struct /* SENT_IPSP */
+ {
+ struct in_addr Dst;
+ u_int32_t Spi;
+ u_int8_t Sproto;
+ u_int8_t Filler[7];
+ } Sipsp;
+ } Sen;
};
-struct flow {
- struct flow *flow_next; /* Next in flow chain */
- struct flow *flow_prev; /* Previous in flow chain */
- struct tdb *flow_sa; /* Pointer to the SA */
- struct in_addr flow_src; /* Source address */
- struct in_addr flow_srcmask; /* Source netmask */
- struct in_addr flow_dst; /* Destination address */
- struct in_addr flow_dstmask; /* Destination netmask */
- u_int16_t flow_sport; /* Source port, if applicable */
- u_int16_t flow_dport; /* Destination port, if applicable */
- u_int8_t flow_proto; /* Transport protocol, if applicable */
- u_int8_t foo[3]; /* Alignment */
-};
+#define sen_data Sen.Data
+#define sen_ip_src Sen.Sip4.Src
+#define sen_ip_dst Sen.Sip4.Dst
+#define sen_proto Sen.Sip4.Proto
+#define sen_sport Sen.Sip4.Sport
+#define sen_dport Sen.Sip4.Dport
+#define sen_ipsp_dst Sen.Sipsp.Dst
+#define sen_ipsp_spi Sen.Sipsp.Spi
+#define sen_ipsp_sproto Sen.Sipsp.Sproto
-struct tdb { /* tunnel descriptor block */
- struct tdb *tdb_hnext; /* next in hash chain */
- struct tdb *tdb_onext; /* next in output */
- struct tdb *tdb_inext; /* next in input (prev!) */
- struct xformsw *tdb_xform; /* transformation to use */
- u_int32_t tdb_spi; /* SPI to use */
- u_int32_t tdb_flags; /* Flags related to this TDB */
-#define TDBF_UNIQUE 0x00001 /* This should not be used by others */
-#define TDBF_TIMER 0x00002 /* Absolute expiration timer in use */
-#define TDBF_BYTES 0x00004 /* Check the byte counters */
-#define TDBF_PACKETS 0x00008 /* Check the packet counters */
-#define TDBF_INVALID 0x00010 /* This SPI is not valid yet/anymore */
-#define TDBF_FIRSTUSE 0x00020 /* Expire after first use */
-#define TDBF_TUNNELING 0x00040 /* Do IP-in-IP encapsulation */
-#define TDBF_SOFT_TIMER 0x00080 /* Soft expiration */
-#define TDBF_SOFT_BYTES 0x00100 /* Soft expiration */
-#define TDBF_SOFT_PACKETS 0x00200 /* Soft expiration */
-#define TDBF_SOFT_FIRSTUSE 0x00400 /* Soft expiration */
-#define TDBF_SAME_TTL 0x00800 /* Keep the packet TTL, in tunneling */
- u_int64_t tdb_exp_packets; /* Expire after so many packets s|r */
- u_int64_t tdb_soft_packets; /* Expiration warning */
- u_int64_t tdb_cur_packets; /* Current number of packets s|r'ed */
- u_int64_t tdb_exp_bytes; /* Expire after so many bytes passed */
- u_int64_t tdb_soft_bytes; /* Expiration warning */
- u_int64_t tdb_cur_bytes; /* Current count of bytes */
- u_int64_t tdb_exp_timeout; /* When does the SPI expire */
- u_int64_t tdb_soft_timeout; /* Send a soft-expire warning */
- u_int64_t tdb_established; /* When was the SPI established */
- u_int64_t tdb_first_use; /* When was it first used */
- u_int64_t tdb_soft_first_use; /* Soft warning */
- u_int64_t tdb_exp_first_use; /* Expire if tdb_first_use +
- tdb_exp_first_use <= curtime */
- struct in_addr tdb_dst; /* dest address for this SPI */
- struct in_addr tdb_src; /* source address for this SPI,
- * used when tunneling */
- struct in_addr tdb_osrc;
- struct in_addr tdb_odst; /* Source and destination addresses
- * of outer IP header if we're doing
- * tunneling */
- caddr_t tdb_xdata; /* transformation data (opaque) */
- struct flow *tdb_flow; /* Which flows use this SA */
-
- u_int8_t tdb_ttl; /* TTL used in tunneling */
- u_int8_t tdb_sproto; /* IPsec protocol */
- u_int16_t tdb_satype; /* Alignment */
- u_int32_t tdb_epoch; /* Used by the kernfs interface */
- u_int8_t *tdb_confname; /* Used by the kernfs interface */
- u_int8_t *tdb_authname; /* Used by the kernfs interface */
-};
+/*
+ * The "type" is really part of the address as far as the routing
+ * system is concerned. By using only one bit in the type field
+ * for each type, we sort-of make sure that different types of
+ * encapsulation addresses won't be matched against the wrong type.
+ *
+ */
-#define TDB_HASHMOD 257
+#define SENT_IP4 0x0001 /* data is two struct in_addr */
+#define SENT_IPSP 0x0002 /* data as in IP4 plus SPI */
-struct xformsw
+/*
+ * SENT_HDRLEN is the length of the "header"
+ * SENT_*_LEN are the lengths of various forms of sen_data
+ * SENT_*_OFF are the offsets in the sen_data array of various fields
+ */
+
+#define SENT_HDRLEN (2 * sizeof(u_int8_t) + sizeof(u_int16_t))
+
+#define SENT_IP4_SRCOFF (0)
+#define SENT_IP4_DSTOFF (sizeof (struct in_addr))
+
+#define SENT_IP4_LEN 20
+#define SENT_IPSP_LEN 20
+
+#define NOTIFY_SOFT_EXPIRE 0 /* Soft expiration of SA */
+#define NOTIFY_HARD_EXPIRE 1 /* Hard expiration of SA */
+#define NOTIFY_REQUEST_SA 2 /* Establish an SA */
+
+#define NOTIFY_SATYPE_CONF 1 /* SA should do encryption */
+#define NOTIFY_SATYPE_AUTH 2 /* SA should do authentication */
+#define NOTIFY_SATYPE_TUNNEL 4 /* SA should use tunneling */
+
+/*
+ * For encapsulation routes are possible not only for the destination
+ * address but also for the protocol, source and destination ports
+ * if available
+ */
+
+struct route_enc {
+ struct rtentry *re_rt;
+ struct sockaddr_encap re_dst;
+};
+
+struct expiration
{
- u_short xf_type; /* Unique ID of xform */
- u_short xf_flags; /* flags (see below) */
- char *xf_name; /* human-readable name */
- int (*xf_attach) __P((void)); /* called at config time */
+ u_int32_t exp_timeout;
+ union sockaddr_union exp_dst;
+ u_int32_t exp_spi;
+ u_int8_t exp_sproto;
+ struct expiration *exp_next;
+ struct expiration *exp_prev;
+};
- /* xform initialization */
- int (*xf_init) __P((struct tdb *, struct xformsw *, struct mbuf *));
+struct flow
+{
+ struct flow *flow_next; /* Next in flow chain */
+ struct flow *flow_prev; /* Previous in flow chain */
+ struct tdb *flow_sa; /* Pointer to the SA */
+ union sockaddr_union flow_src; /* Source address */
+ union sockaddr_union flow_srcmask; /* Source netmask */
+ union sockaddr_union flow_dst; /* Destination address */
+ union sockaddr_union flow_dstmask; /* Destination netmask */
+ u_int8_t flow_proto; /* Transport protocol, if applicable */
+ u_int8_t foo[3]; /* Alignment */
+};
- int (*xf_zeroize) __P((struct tdb *)); /* termination */
+struct tdb /* tunnel descriptor block */
+{
+ struct tdb *tdb_hnext; /* Next in hash chain */
+ struct tdb *tdb_onext; /* Next in output */
+ struct tdb *tdb_inext; /* Previous in output */
+
+ struct xformsw *tdb_xform; /* Transformation to use */
+ struct enc_xform *tdb_encalgxform; /* Encryption algorithm xform */
+ struct auth_hash *tdb_authalgxform; /* Authentication algorithm xform */
+
+#define TDBF_UNIQUE 0x00001 /* This should not be used by others */
+#define TDBF_TIMER 0x00002 /* Absolute expiration timer in use */
+#define TDBF_BYTES 0x00004 /* Check the byte counters */
+#define TDBF_ALLOCATIONS 0x00008 /* Check the flows counters */
+#define TDBF_INVALID 0x00010 /* This SPI is not valid yet/anymore */
+#define TDBF_FIRSTUSE 0x00020 /* Expire after first use */
+#define TDBF_HALFIV 0x00040 /* Use half-length IV (ESP old only) */
+#define TDBF_SOFT_TIMER 0x00080 /* Soft expiration */
+#define TDBF_SOFT_BYTES 0x00100 /* Soft expiration */
+#define TDBF_SOFT_ALLOCATIONS 0x00200 /* Soft expiration */
+#define TDBF_SOFT_FIRSTUSE 0x00400 /* Soft expiration */
+#define TDBF_PFS 0x00800 /* Ask for PFS from Key Mgmt. */
+#define TDBF_TUNNELING 0x01000 /* Force IP-IP encapsulation */
+ u_int32_t tdb_flags; /* Flags related to this TDB */
+
+ u_int32_t tdb_exp_allocations; /* Expire after so many flows */
+ u_int32_t tdb_soft_allocations; /* Expiration warning */
+ u_int32_t tdb_cur_allocations; /* Total number of allocations */
+
+ u_int64_t tdb_exp_bytes; /* Expire after so many bytes passed */
+ u_int64_t tdb_soft_bytes; /* Expiration warning */
+ u_int64_t tdb_cur_bytes; /* Current count of bytes */
+
+ u_int64_t tdb_exp_timeout; /* When does the SPI expire */
+ u_int64_t tdb_soft_timeout; /* Send a soft-expire warning */
+ u_int64_t tdb_established; /* When was the SPI established */
+
+ u_int64_t tdb_first_use; /* When was it first used */
+ u_int64_t tdb_soft_first_use; /* Soft warning */
+ u_int64_t tdb_exp_first_use; /* Expire if tdb_first_use +
+ * tdb_exp_first_use <= curtime */
+ u_int32_t tdb_spi; /* SPI */
+ u_int16_t tdb_amxkeylen; /* AH-old only */
+ u_int16_t tdb_ivlen; /* IV length */
+ u_int8_t tdb_sproto; /* IPsec protocol */
+ u_int8_t tdb_wnd; /* Replay window */
+ u_int16_t tdb_FILLER; /* Padding */
+
+ union sockaddr_union tdb_dst; /* Destination address for this SA */
+ union sockaddr_union tdb_src; /* Source address for this SA */
+ union sockaddr_union tdb_proxy;
+
+ u_int8_t *tdb_key; /* Key material (schedules) */
+ u_int8_t *tdb_ictx; /* Authentication contexts */
+ u_int8_t *tdb_octx;
+ u_int8_t *tdb_srcid; /* Source ID for this SA */
+ u_int8_t *tdb_dstid; /* Destination ID for this SA */
+ u_int8_t *tdb_amxkey; /* AH-old only */
+
+ union
+ {
+ u_int8_t Iv[ESP_3DES_IVS]; /* That's enough space */
+ u_int32_t Ivl; /* Make sure this is 4 bytes */
+ u_int64_t Ivq; /* Make sure this is 8 bytes! */
+ }IV;
+#define tdb_iv IV.Iv
+#define tdb_ivl IV.Ivl
+#define tdb_ivq IV.Ivq
+
+ u_int32_t tdb_rpl; /* Replay counter */
+ u_int32_t tdb_bitmap; /* Used for replay sliding window */
+ u_int32_t tdb_initial; /* Initial replay value */
+
+ u_int32_t tdb_epoch; /* Used by the kernfs interface */
+ u_int16_t tdb_srcid_len;
+ u_int16_t tdb_dstid_len;
+ u_int16_t tdb_srcid_type;
+ u_int16_t tdb_dstid_type;
+
+ struct flow *tdb_flow; /* Which flows use this SA */
+};
- /* called when packet received */
- struct mbuf *(*xf_input) __P((struct mbuf *, struct tdb *));
+#define TDB_HASHMOD 257
- /* called when packet sent */
- int (*xf_output) __P((struct mbuf *, struct sockaddr_encap *,
- struct tdb *, struct mbuf **));
+struct auth_hash {
+ int type;
+ char *name;
+ u_int16_t keysize;
+ u_int16_t hashsize;
+ u_int16_t ctxsize;
+ void (*Init)(void *);
+ void (*Update)(void *, u_int8_t *, u_int16_t);
+ void (*Final)(u_int8_t *, void *);
};
-#define XF_IP4 1 /* IP inside IP */
-#define XF_OLD_AH 2 /* RFCs 1828 & 1852 */
-#define XF_OLD_ESP 3 /* RFCs 1829 & 1851 */
-#define XF_NEW_AH 4 /* AH HMAC 96bits */
-#define XF_NEW_ESP 5 /* ESP + auth 96bits + replay counter */
+struct enc_xform {
+ int type;
+ char *name;
+ u_int16_t blocksize, ivsize;
+ u_int16_t minkey, maxkey;
+ u_int32_t ivmask; /* Or all possible modes, zero iv = 1 */
+ void (*encrypt)(struct tdb *, u_int8_t *);
+ void (*decrypt)(struct tdb *, u_int8_t *);
+};
-/* Supported key hash algorithms */
-#define ALG_AUTH_MD5 1
-#define ALG_AUTH_SHA1 2
-#define ALG_AUTH_RMD160 3
+struct ipsecinit
+{
+ u_int8_t *ii_enckey;
+ u_int8_t *ii_authkey;
+ u_int16_t ii_enckeylen;
+ u_int16_t ii_authkeylen;
+ u_int8_t ii_encalg;
+ u_int8_t ii_authalg;
+};
+
+struct xformsw
+{
+ u_short xf_type; /* Unique ID of xform */
+ u_short xf_flags; /* flags (see below) */
+ char *xf_name; /* human-readable name */
+ 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 sockaddr_encap *,
+ struct tdb *, struct mbuf **); /* output */
+};
-/* Supported encryption algorithms */
-#define ALG_ENC_DES 1
-#define ALG_ENC_3DES 2
-#define ALG_ENC_BLF 3
-#define ALG_ENC_CAST 4
-#define ALG_ENC_SKIPJACK 5
+/* xform IDs */
+#define XF_IP4 1 /* IP inside IP */
+#define XF_OLD_AH 2 /* RFCs 1828 & 1852 */
+#define XF_OLD_ESP 3 /* RFCs 1829 & 1851 */
+#define XF_NEW_AH 4 /* AH HMAC 96bits */
+#define XF_NEW_ESP 5 /* ESP + auth 96bits + replay counter */
+/* xform attributes */
#define XFT_AUTH 0x0001
#define XFT_CONF 0x0100
@@ -160,11 +332,11 @@ struct xformsw
static __inline u_int64_t
htonq(u_int64_t q)
{
- register u_int32_t u, l;
- u = q >> 32;
- l = (u_int32_t) q;
+ register u_int32_t u, l;
+ u = q >> 32;
+ l = (u_int32_t) q;
- return htonl(u) | ((u_int64_t)htonl(l) << 32);
+ return htonl(u) | ((u_int64_t)htonl(l) << 32);
}
#define ntohq(_x) htonq(_x)
@@ -178,36 +350,41 @@ htonq(u_int64_t q)
#error "Please fix <machine/endian.h>"
#endif
-extern unsigned char ipseczeroes[];
-
/*
* Names for IPsec sysctl objects
*/
-#define IPSECCTL_ENCAP 0
+#define IPSECCTL_PFKEY 0
#define IPSECCTL_MAXID 1
#define CTL_IPSEC_NAMES {\
- { "encap", CTLTYPE_NODE }, \
+ { "pfkey", CTLTYPE_NODE }, \
+}
+
+#define PFKEYCTL_ENCDEBUG 1
+#define PFKEYCTL_MAXID 2
+
+#define PFKEYCTL_NAMES {\
+ { 0, 0 }, \
+ { "encdebug", CTLTYPE_INT }, \
}
#ifdef _KERNEL
extern int encdebug;
+extern int ipsec_in_use;
+extern u_int8_t hmac_ipad_buffer[64];
+extern u_int8_t hmac_opad_buffer[64];
struct tdb *tdbh[TDB_HASHMOD];
struct expiration *explist;
extern struct xformsw xformsw[], *xformswNXFORMSW;
-u_int32_t notify_msgids;
/* Check if a given tdb has encryption, authentication and/or tunneling */
-#define TDB_ATTRIB(x) \
- (((x)->tdb_confname != NULL ? NOTIFY_SATYPE_CONF : 0)| \
- ((x)->tdb_authname != NULL ? NOTIFY_SATYPE_AUTH : 0)| \
- ((x)->tdb_confname != NULL && \
- ((x)->tdb_flags & TDBF_TUNNELING) ? NOTIFY_SATYPE_TUNNEL : 0))
+#define TDB_ATTRIB(x) (((x)->tdb_encalgxform ? NOTIFY_SATYPE_CONF : 0)| \
+ ((x)->tdb_authalgxform ? NOTIFY_SATYPE_AUTH : 0))
/* Traverse spi chain and get attributes */
-#define SPI_CHAIN_ATTRIB(have, TDB_DIR, TDBP) { \
+#define SPI_CHAIN_ATTRIB(have, TDB_DIR, TDBP) {\
struct tdb *tmptdb = (TDBP); \
(have) = 0; \
\
@@ -219,32 +396,39 @@ u_int32_t notify_msgids;
} \
}
+/* Misc. */
+extern char *inet_ntoa4(struct in_addr);
+extern char *ipsp_address(union sockaddr_union);
+
/* TDB management routines */
-extern u_int32_t reserve_spi(u_int32_t, struct in_addr, u_int8_t, int *);
-extern struct tdb *gettdb(u_int32_t, struct in_addr, u_int8_t);
+extern u_int32_t reserve_spi(u_int32_t, u_int32_t, union sockaddr_union *,
+ union sockaddr_union *, u_int8_t, int *);
+extern struct tdb *gettdb(u_int32_t, union sockaddr_union *, u_int8_t);
extern void puttdb(struct tdb *);
extern int tdb_delete(struct tdb *, int);
+extern int tdb_init (struct tdb *, u_int16_t, struct ipsecinit *);
/* Expiration management routines */
extern struct expiration *get_expiration(void);
extern void put_expiration(struct expiration *);
extern void handle_expirations(void *);
-extern void cleanup_expirations(struct in_addr, u_int32_t, u_int8_t);
+extern void cleanup_expirations(union sockaddr_union *, u_int32_t, u_int8_t);
/* Flow management routines */
extern struct flow *get_flow(void);
extern void put_flow(struct flow *, struct tdb *);
extern void delete_flow(struct flow *, struct tdb *);
-extern struct flow *find_flow(struct in_addr, struct in_addr, struct in_addr,
- struct in_addr, u_int8_t, u_int16_t, u_int16_t,
- struct tdb *);
-extern struct flow *find_global_flow(struct in_addr, struct in_addr,
- struct in_addr, struct in_addr, u_int8_t,
- u_int16_t, u_int16_t);
+extern struct flow *find_flow(union sockaddr_union *, union sockaddr_union *,
+ union sockaddr_union *, union sockaddr_union *,
+ u_int8_t, struct tdb *);
+extern struct flow *find_global_flow(union sockaddr_union *,
+ union sockaddr_union *,
+ union sockaddr_union *,
+ union sockaddr_union *, u_int8_t);
/* XF_IP4 */
extern int ipe4_attach(void);
-extern int ipe4_init(struct tdb *, struct xformsw *, struct mbuf *);
+extern int ipe4_init(struct tdb *, struct xformsw *, struct ipsecinit *);
extern int ipe4_zeroize(struct tdb *);
extern int ipe4_output(struct mbuf *, struct sockaddr_encap *, struct tdb *,
struct mbuf **);
@@ -253,7 +437,7 @@ extern void ip4_input __P((struct mbuf *, ...));
/* XF_OLD_AH */
extern int ah_old_attach(void);
-extern int ah_old_init(struct tdb *, struct xformsw *, struct mbuf *);
+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 sockaddr_encap *, struct tdb *,
struct mbuf **);
@@ -261,7 +445,7 @@ extern struct mbuf *ah_old_input(struct mbuf *, struct tdb *);
/* XF_NEW_AH */
extern int ah_new_attach(void);
-extern int ah_new_init(struct tdb *, struct xformsw *, struct mbuf *);
+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 sockaddr_encap *, struct tdb *,
struct mbuf **);
@@ -269,7 +453,7 @@ extern struct mbuf *ah_new_input(struct mbuf *, struct tdb *);
/* XF_OLD_ESP */
extern int esp_old_attach(void);
-extern int esp_old_init(struct tdb *, struct xformsw *, struct mbuf *);
+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 sockaddr_encap *, struct tdb *,
struct mbuf **);
@@ -277,7 +461,7 @@ extern struct mbuf *esp_old_input(struct mbuf *, struct tdb *);
/* XF_NEW_ESP */
extern int esp_new_attach(void);
-extern int esp_new_init(struct tdb *, struct xformsw *, struct mbuf *);
+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 sockaddr_encap *, struct tdb *,
struct mbuf **);
@@ -288,5 +472,7 @@ extern caddr_t m_pad(struct mbuf *, int, int);
/* Replay window */
extern int checkreplaywindow32(u_int32_t, u_int32_t, u_int32_t *, u_int32_t,
- u_int32_t *);
+ u_int32_t *);
+
+extern unsigned char ipseczeroes[];
#endif
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 5ccf119abe8..f3976ded930 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.39 1999/01/11 00:42:53 angelos Exp $ */
+/* $OpenBSD: ip_output.c,v 1.40 1999/02/24 22:33:07 angelos Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -64,11 +64,15 @@
#include <machine/stdarg.h>
#ifdef IPSEC
-#include <net/encap.h>
#include <netinet/ip_ipsp.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
-#include <sys/syslog.h>
+
+#ifdef ENCDEBUG
+#define DPRINTF(x) if (encdebug) printf x
+#else
+#define DPRINTF(x)
+#endif
extern u_int8_t get_sa_require __P((struct inpcb *));
@@ -117,6 +121,7 @@ ip_output(m0, va_alist)
struct ip_moptions *imo;
va_list ap;
#ifdef IPSEC
+ union sockaddr_union sunion;
struct mbuf *mp;
struct udphdr *udp;
struct tcphdr *tcp;
@@ -163,7 +168,8 @@ ip_output(m0, va_alist)
/*
* Check if the packet needs encapsulation
*/
- if (!(flags & IP_ENCAPSULATED) &&
+ if ((ipsec_in_use != 0) &&
+ !(flags & IP_ENCAPSULATED) &&
(inp == NULL ||
(inp->inp_seclevel[SL_AUTH] != IPSEC_LEVEL_BYPASS ||
inp->inp_seclevel[SL_ESP_TRANS] != IPSEC_LEVEL_BYPASS ||
@@ -180,7 +186,7 @@ ip_output(m0, va_alist)
bzero((caddr_t) re, sizeof(*re));
ddst = (struct sockaddr_encap *) &re->re_dst;
- ddst->sen_family = AF_ENCAP;
+ ddst->sen_family = PF_KEY;
ddst->sen_len = SENT_IP4_LEN;
ddst->sen_type = SENT_IP4;
ddst->sen_ip_src = ip->ip_src;
@@ -234,10 +240,8 @@ ip_output(m0, va_alist)
goto no_encap;
if (gw == NULL || gw->sen_type != SENT_IPSP) {
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ip_output(): no gw or gw data not IPSP\n");
-#endif /* ENCDEBUG */
+ DPRINTF(("ip_output(): no gw or gw data not IPSP\n"));
+
if (re->re_rt)
RTFREE(re->re_rt);
error = EHOSTUNREACH;
@@ -250,17 +254,11 @@ ip_output(m0, va_alist)
* indicate the need for an SA when none is established.
*/
if (ntohl(gw->sen_ipsp_spi) == 0x1) {
- struct tdb tmptdb;
-
sa_require = NOTIFY_SATYPE_AUTH | NOTIFY_SATYPE_TUNNEL;
if (gw->sen_ipsp_sproto == IPPROTO_ESP)
sa_require |= NOTIFY_SATYPE_CONF;
- tmptdb.tdb_dst.s_addr = gw->sen_ipsp_dst.s_addr;
- tmptdb.tdb_satype = sa_require;
-
- /* Request SA with key management */
- encap_sendnotify(NOTIFY_REQUEST_SA, &tmptdb, NULL);
+ /* XXX PF_KEYv2 notification message */
/*
* When sa_require is set, the packet will be dropped
@@ -280,8 +278,12 @@ ip_output(m0, va_alist)
* and then pass it, along with the packet and the gw,
* to the appropriate transformation.
*/
- tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, gw->sen_ipsp_dst,
- gw->sen_ipsp_sproto);
+ bzero(&sunion, sizeof(sunion));
+ sunion.sin.sin_family = AF_INET;
+ sunion.sin.sin_len = sizeof(struct sockaddr_in);
+ sunion.sin.sin_addr = gw->sen_ipsp_dst;
+ tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion,
+ gw->sen_ipsp_sproto);
/*
* Now we check if this tdb has all the transforms which
@@ -293,10 +295,8 @@ ip_output(m0, va_alist)
goto no_encap;
if (tdb == NULL) {
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ip_output(): non-existant TDB for SA %08x/%x/%d\n", ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_dst, gw->sen_ipsp_sproto);
-#endif
+ 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 (re->re_rt)
RTFREE(re->re_rt);
error = EHOSTUNREACH;
@@ -306,8 +306,9 @@ ip_output(m0, va_alist)
/* Fix the ip_src field if necessary */
if (ip->ip_src.s_addr == INADDR_ANY) {
- if (tdb && tdb->tdb_src.s_addr != 0) /* Provided */
- ip->ip_src = tdb->tdb_src;
+ if (tdb && tdb->tdb_src.sin.sin_addr.s_addr != 0 &&
+ tdb->tdb_src.sa.sa_family == AF_INET)
+ ip->ip_src = tdb->tdb_src.sin.sin_addr;
else
{
if (ro == 0) {
@@ -349,63 +350,39 @@ ip_output(m0, va_alist)
}
}
-#ifdef ENCDEBUG
- if (encdebug) {
- printf("ip_output(): tdb=%08x, tdb->tdb_xform=0x%x,",
- tdb, tdb->tdb_xform);
- printf(" tdb->tdb_xform->xf_output=%x, sproto=%x\n",
- tdb->tdb_xform->xf_output, tdb->tdb_sproto);
- }
-#endif /* ENCDEBUG */
-
while (tdb && tdb->tdb_xform) {
/* Check if the SPI is invalid */
if (tdb->tdb_flags & TDBF_INVALID) {
- if (encdebug)
- log(LOG_ALERT, "ip_output(): attempt to use invalid SA %08x/%x/%x\n", ntohl(tdb->tdb_spi), tdb->tdb_dst,
- tdb->tdb_sproto);
+ DPRINTF(("ip_output(): attempt to use invalid SA %s/%08x/%u\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi), tdb->tdb_sproto));
m_freem(m);
RTFREE(re->re_rt);
return ENXIO;
}
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ip_output(): calling %s\n",
- tdb->tdb_xform->xf_name);
-#endif /* ENCDEBUG */
+ DPRINTF(("ip_output(): calling %s\n",
+ tdb->tdb_xform->xf_name));
/* Register first use, setup expiration timer */
if (tdb->tdb_first_use == 0) {
- tdb->tdb_first_use = time.tv_sec;
-
- if (tdb->tdb_flags & TDBF_FIRSTUSE) {
- exp = get_expiration();
- if (exp == NULL)
- goto expbail;
- exp->exp_dst.s_addr =
- tdb->tdb_dst.s_addr;
- exp->exp_spi = tdb->tdb_spi;
- exp->exp_sproto = tdb->tdb_sproto;
- exp->exp_timeout = tdb->tdb_first_use +
- tdb->tdb_exp_first_use;
- put_expiration(exp);
+ tdb->tdb_first_use = time.tv_sec;
+
+ if (tdb->tdb_flags & TDBF_FIRSTUSE) {
+ exp = get_expiration();
+ bcopy(&tdb->tdb_dst, &exp->exp_dst,
+ SA_LEN(&tdb->tdb_dst.sa));
+ exp->exp_spi = tdb->tdb_spi;
+ exp->exp_sproto = tdb->tdb_sproto;
+ exp->exp_timeout = tdb->tdb_first_use +
+ tdb->tdb_exp_first_use;
+ put_expiration(exp);
}
if ((tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) &&
(tdb->tdb_soft_first_use <=
tdb->tdb_exp_first_use)) {
exp = get_expiration();
- if (exp == NULL) {
-expbail:
- if (encdebug)
- log(LOG_WARNING, "ip_output(): no memory for exp timer\n");
- m_freem(m);
- RTFREE(re->re_rt);
- return ENOBUFS;
- }
- exp->exp_dst.s_addr =
- tdb->tdb_dst.s_addr;
+ bcopy(&tdb->tdb_dst, &exp->exp_dst,
+ SA_LEN(&tdb->tdb_dst.sa));
exp->exp_spi = tdb->tdb_spi;
exp->exp_sproto = tdb->tdb_sproto;
exp->exp_timeout = tdb->tdb_first_use +
@@ -415,12 +392,12 @@ expbail:
}
/* Check for tunneling */
- if ((tdb->tdb_flags & TDBF_TUNNELING) &&
- (tdb->tdb_xform->xf_type != XF_IP4)){
-#ifdef ENCDEBUG
- if (encdebug)
- printf("ip_output(): tunneling\n");
-#endif /* ENCDEBUG */
+ if (((tdb->tdb_dst.sin.sin_addr.s_addr !=
+ ip->ip_dst.s_addr) ||
+ (tdb->tdb_flags & TDBF_TUNNELING)) &&
+ (tdb->tdb_xform->xf_type != XF_IP4))
+ {
+ DPRINTF(("ip_output(): tunneling\n"));
/*
* Fix checksum here, AH and ESP fix the