summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>2000-09-19 03:19:40 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>2000-09-19 03:19:40 +0000
commitaf73df8e49a73ae51c26612cdf39434cf2ae6a75 (patch)
tree35973a72331245a21b88055374040b9758c65b7f
parent5534a5937914c47ce35c34ef3e6aeba61aa79e11 (diff)
SPD-driven IPsec.
-rw-r--r--sys/net/pfkey.c1
-rw-r--r--sys/net/pfkeyv2.c942
-rw-r--r--sys/net/pfkeyv2.h31
-rw-r--r--sys/net/pfkeyv2_parsemessage.c43
4 files changed, 400 insertions, 617 deletions
diff --git a/sys/net/pfkey.c b/sys/net/pfkey.c
index 4c78bcb2401..8ece8974018 100644
--- a/sys/net/pfkey.c
+++ b/sys/net/pfkey.c
@@ -27,6 +27,7 @@ you didn't get a copy, you may request one from <license@inner.net>.
#include <sys/proc.h>
#include <net/route.h>
#include <netinet/in.h>
+#include <netinet/ip_ipsp.h>
#include <net/pfkeyv2.h>
#include <sys/protosw.h>
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index 76b707eafd7..d89afc980d9 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.38 2000/08/24 22:51:29 fgsch Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.39 2000/09/19 03:19:39 angelos Exp $ */
/*
%%% copyright-nrl-97
This software is Copyright 1997-1998 by Randall Atkinson, Ronald Lee,
@@ -28,8 +28,8 @@ you didn't get a copy, you may request one from <license@inner.net>.
#include <sys/proc.h>
#include <net/route.h>
#include <netinet/in.h>
-#include <net/pfkeyv2.h>
#include <netinet/ip_ipsp.h>
+#include <net/pfkeyv2.h>
#include <netinet/ip_ah.h>
#include <netinet/ip_esp.h>
#include <crypto/blf.h>
@@ -50,9 +50,9 @@ static struct sadb_alg ealgs[] =
{
{ SADB_EALG_DESCBC, 64, 64, 64 },
{ SADB_EALG_3DESCBC, 64, 192, 192 },
- { SADB_X_EALG_BLF, 64, 5, BLF_MAXKEYLEN},
- { SADB_X_EALG_CAST, 64, 5, 16},
- { SADB_X_EALG_SKIPJACK, 64, 10, 10},
+ { SADB_X_EALG_BLF, 64, 40, BLF_MAXKEYLEN * 8},
+ { SADB_X_EALG_CAST, 64, 40, 128},
+ { SADB_X_EALG_SKIPJACK, 64, 80, 80},
};
static struct sadb_alg aalgs[] =
@@ -66,6 +66,7 @@ void export_address(void **, struct sockaddr *);
void export_identity(void **, struct tdb *, int);
void export_lifetime(void **, struct tdb *, int);
void export_sa(void **, struct tdb *);
+void export_key(void **, struct tdb *, int);
void import_address(struct sockaddr *, struct sadb_address *);
void import_identity(struct tdb *, struct sadb_ident *, int);
@@ -492,7 +493,7 @@ import_identity(struct tdb *tdb, struct sadb_ident *sadb_ident, int type)
tdb->tdb_srcid_type = sadb_ident->sadb_ident_type;
MALLOC(tdb->tdb_srcid, u_int8_t *, tdb->tdb_srcid_len, M_XDATA,
M_WAITOK);
- bcopy((void *)sadb_ident + sizeof(struct sadb_ident),
+ bcopy((void *) sadb_ident + sizeof(struct sadb_ident),
tdb->tdb_srcid, tdb->tdb_srcid_len);
}
else
@@ -502,7 +503,7 @@ import_identity(struct tdb *tdb, struct sadb_ident *sadb_ident, int type)
tdb->tdb_dstid_type = sadb_ident->sadb_ident_type;
MALLOC(tdb->tdb_dstid, u_int8_t *, tdb->tdb_dstid_len, M_XDATA,
M_WAITOK);
- bcopy((void *)sadb_ident + sizeof(struct sadb_ident),
+ bcopy((void *) sadb_ident + sizeof(struct sadb_ident),
tdb->tdb_dstid, tdb->tdb_dstid_len);
}
}
@@ -553,6 +554,33 @@ import_key(struct ipsecinit *ii, struct sadb_key *sadb_key, int type)
}
}
+void
+export_key(void **p, struct tdb *tdb, int type)
+{
+ struct sadb_key *sadb_key = (struct sadb_key *) *p;
+
+ if (type == PFKEYV2_ENCRYPTION_KEY)
+ {
+ sadb_key->sadb_key_len = (sizeof(struct sadb_key) +
+ PADUP(tdb->tdb_emxkeylen)) /
+ sizeof(uint64_t);
+ sadb_key->sadb_key_bits = tdb->tdb_emxkeylen * 8;
+ *p += sizeof(struct sadb_key);
+ bcopy(tdb->tdb_emxkey, *p, tdb->tdb_emxkeylen);
+ *p += PADUP(tdb->tdb_emxkeylen);
+ }
+ else
+ {
+ sadb_key->sadb_key_len = (sizeof(struct sadb_key) +
+ PADUP(tdb->tdb_amxkeylen)) /
+ sizeof(uint64_t);
+ sadb_key->sadb_key_bits = tdb->tdb_amxkeylen * 8;
+ *p += sizeof(struct sadb_key);
+ bcopy(tdb->tdb_amxkey, *p, tdb->tdb_amxkeylen);
+ *p += PADUP(tdb->tdb_amxkeylen);
+ }
+}
+
/*
* Send a PFKEYv2 message, possibly to many receivers, based on the
* satype of the socket (which is set by the REGISTER message), and the
@@ -654,11 +682,10 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket,
{
/* Check for specified satype */
if ((1 << satype) & s->registration)
- if (count-- == 0)
- { /* Done */
- pfkey_sendup(s->socket, packet, 1);
- break;
- }
+ { /* Done */
+ pfkey_sendup(s->socket, packet, 1);
+ break;
+ }
}
}
@@ -804,7 +831,19 @@ pfkeyv2_get(struct tdb *sa, void **headers, void **buffer)
export_identity(&p, sa, PFKEYV2_IDENTITY_DST);
}
- /* XXX Export keys ? */
+ /* Export authentication key, if present */
+ if (sa->tdb_amxkey)
+ {
+ headers[SADB_EXT_KEY_AUTH] = p;
+ export_key(&p, sa, PFKEYV2_AUTHENTICATION_KEY);
+ }
+
+ /* Export encryption key, if present */
+ if (sa->tdb_emxkey)
+ {
+ headers[SADB_EXT_KEY_ENCRYPT] = p;
+ export_key(&p, sa, PFKEYV2_ENCRYPTION_KEY);
+ }
rval = 0;
@@ -853,7 +892,7 @@ pfkeyv2_flush_walker(struct tdb *sa, void *satype_vp)
{
if (!(*((u_int8_t *) satype_vp)) ||
sa->tdb_satype == *((u_int8_t *) satype_vp))
- tdb_delete(sa, 0, 0);
+ tdb_delete(sa, 0);
return 0;
}
@@ -874,7 +913,7 @@ pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg)
*sproto = IPPROTO_AH;
- if(alg != NULL)
+ if(alg != NULL)
*alg = satype = XF_AH;
break;
@@ -922,6 +961,8 @@ int
pfkeyv2_send(struct socket *socket, void *message, int len)
{
int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST, delflag = 0, s;
+ struct sockaddr_encap encapdst, encapnetmask, encapgw;
+ struct ipsec_policy *ipo;
struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL;
@@ -931,7 +972,6 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
union sockaddr_union *sunionp;
struct tdb sa, *sa2 = NULL;
- struct flow *flow = NULL;
struct sadb_msg *smsg;
struct sadb_spirange *sprng;
@@ -1109,33 +1149,15 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
if (rval)
{
rval = EINVAL;
- tdb_delete(freeme, 0, TDBEXP_TIMEOUT);
+ tdb_delete(freeme, TDBEXP_TIMEOUT);
freeme = NULL;
goto splxret;
}
newsa->tdb_cur_allocations = sa2->tdb_cur_allocations;
- /* Copy outgoing flows and ACL */
- newsa->tdb_flow = sa2->tdb_flow;
- newsa->tdb_access = sa2->tdb_access;
-
- /* Fix flow backpointers to the TDB */
- for (flow = newsa->tdb_flow;
- flow != NULL;
- flow = flow->flow_next)
- flow->flow_sa = newsa;
-
- for (flow = newsa->tdb_access;
- flow != NULL;
- flow = flow->flow_next)
- flow->flow_sa = newsa;
-
- sa2->tdb_access = NULL;
- sa2->tdb_flow = NULL;
-
/* Delete old version of the SA, insert new one */
- tdb_delete(sa2, 0, TDBEXP_TIMEOUT);
+ tdb_delete(sa2, TDBEXP_TIMEOUT);
puttdb((struct tdb *) freeme);
sa2 = freeme = NULL;
}
@@ -1241,7 +1263,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
if (rval)
{
rval = EINVAL;
- tdb_delete(freeme, 0, TDBEXP_TIMEOUT);
+ tdb_delete(freeme, TDBEXP_TIMEOUT);
freeme = NULL;
goto splxret;
}
@@ -1269,8 +1291,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
goto splxret;
}
- tdb_delete(sa2, ssa->sadb_sa_flags & SADB_X_SAFLAGS_CHAINDEL,
- TDBEXP_TIMEOUT);
+ tdb_delete(sa2, TDBEXP_TIMEOUT);
splx(s);
@@ -1343,28 +1364,14 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
case SADB_FLUSH:
rval = 0;
+ s = spltdb();
+ while ((ipo = TAILQ_FIRST(&ipsec_policy_head)) != NULL)
+ ipsec_delete_policy(ipo);
+ splx(s);
+
switch(smsg->sadb_msg_satype)
{
case SADB_SATYPE_UNSPEC:
- case SADB_X_SATYPE_BYPASS:
- {
- union sockaddr_union dst;
- /* XXX IPv4 dependency -- does it matter though ? */
- dst.sin.sin_family = AF_INET;
- dst.sin.sin_len = sizeof(struct sockaddr_in);
- dst.sin.sin_addr.s_addr = INADDR_ANY;
-
- s = spltdb();
-
- sa2 = gettdb(SPI_LOCAL_USE, &dst, IPPROTO_IP);
- if (sa2 != NULL)
- tdb_delete(sa2, 0, 0);
-
- if (smsg->sadb_msg_satype == SADB_X_SATYPE_BYPASS)
- break;
- /* for SADB_SATYPE_UNSPEC, fall through */
- }
-
case SADB_SATYPE_AH:
case SADB_SATYPE_ESP:
case SADB_X_SATYPE_IPIP:
@@ -1375,15 +1382,14 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
tdb_walk(pfkeyv2_flush_walker,
(u_int8_t *) &(smsg->sadb_msg_satype));
+
+ splx(s);
break;
default:
rval = EINVAL; /* Unknown/unsupported type */
}
- if (rval == 0)
- goto splxret;
-
break;
case SADB_DUMP:
@@ -1407,14 +1413,27 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
case SADB_X_ADDFLOW:
{
- struct sockaddr_encap encapdst, encapgw, encapnetmask;
- struct flow *flow2 = NULL, *old_flow = NULL, *old_flow2 = NULL;
- union sockaddr_union *src, *dst, *srcmask, *dstmask;
- u_int8_t sproto = 0, replace, ingress ;
- struct rtentry *rt;
-
+ union sockaddr_union *src, *dst, *srcmask, *dstmask, *ssrc;
+ struct route_enc re;
+ u_int8_t transproto = 0;
+ u_int8_t direction;
+ int exists = 0;
+ struct tdb *ktdb;
+
+ direction = (((struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE])->sadb_protocol_direction);
+ if ((direction != IPSP_DIRECTION_IN) &&
+ (direction != IPSP_DIRECTION_OUT))
+ {
+ rval = EINVAL;
+ goto ret;
+ }
+
ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
+ /* If the security protocol wasn't specified, pretend it was ESP */
+ if (smsg->sadb_msg_satype == 0)
+ smsg->sadb_msg_satype = SADB_SATYPE_ESP;
+
if (headers[SADB_EXT_ADDRESS_DST])
sunionp = (union sockaddr_union *)
(headers[SADB_EXT_ADDRESS_DST] +
@@ -1422,18 +1441,12 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
else
sunionp = NULL;
- /*
- * SADB_X_SAFLAGS_REPLACEFLOW set means we should remove any
- * potentially conflicting egress flow while we are adding this
- * new one.
- */
- replace = ssa->sadb_sa_flags & SADB_X_SAFLAGS_REPLACEFLOW;
- ingress = ssa->sadb_sa_flags & SADB_X_SAFLAGS_INGRESS_FLOW;
- if ((replace && delflag) || (replace && ingress))
- {
- rval = EINVAL;
- goto ret;
- }
+ if (headers[SADB_EXT_ADDRESS_SRC])
+ ssrc = (union sockaddr_union *)
+ (headers[SADB_EXT_ADDRESS_SRC] +
+ sizeof(struct sadb_address));
+ else
+ ssrc = NULL;
src = (union sockaddr_union *) (headers[SADB_X_EXT_SRC_FLOW] +
sizeof(struct sadb_address));
@@ -1453,415 +1466,250 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
(src->sa.sa_family != dstmask->sa.sa_family))
{
rval = EINVAL;
- goto splxret;
+ goto ret;
}
bzero(&encapdst, sizeof(struct sockaddr_encap));
bzero(&encapnetmask, sizeof(struct sockaddr_encap));
bzero(&encapgw, sizeof(struct sockaddr_encap));
-
+
+ /* Transport protocol specified ? */
if (headers[SADB_X_EXT_PROTOCOL])
- sproto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL])->sadb_protocol_proto;
- else
- sproto = 0;
+ transproto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL])->sadb_protocol_proto;
/* Generic netmask handling, works for IPv4 and IPv6 */
rt_maskedcopy(&src->sa, &src->sa, &srcmask->sa);
rt_maskedcopy(&dst->sa, &dst->sa, &dstmask->sa);
- s = spltdb();
-
- if (!delflag || ingress)
- {
- if ((ssa == NULL) || (sunionp == NULL))
- {
- rval = EINVAL;
- goto splxret;
- }
-
- /* Find the relevant SA */
- sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
- SADB_GETSPROTO(smsg->sadb_msg_satype));
-
- if (sa2 == NULL)
- {
- rval = ESRCH;
- goto splxret;
- }
- }
-
- /* For non-ingress flows... */
- if (!ingress)
- {
- /*
- * ...if the requested flow already exists and we aren't
- * asked to replace or delete it, or if it doesn't exist
- * and we're asked to delete it, fail.
- */
- flow = find_global_flow(src, srcmask, dst, dstmask, sproto);
- if (!replace &&
- ((delflag && (flow == NULL)) ||
- (!delflag && (flow != NULL))))
- {
- rval = delflag ? ESRCH : EEXIST;
- goto splxret;
- }
- }
-
- /* If we're not deleting a flow, add in the TDB */
- if (!delflag)
- {
- if (replace)
- old_flow = flow;
-
- flow = get_flow();
- bcopy(src, &flow->flow_src, src->sa.sa_len);
- bcopy(dst, &flow->flow_dst, dst->sa.sa_len);
- bcopy(srcmask, &flow->flow_srcmask, srcmask->sa.sa_len);
- bcopy(dstmask, &flow->flow_dstmask, dstmask->sa.sa_len);
- flow->flow_proto = sproto;
- put_flow(flow, sa2, ingress);
-
- /* If this is an ACL entry, we're done */
- if (ingress)
- {
- splx(s);
- break;
- }
- }
- else
- if (ingress)
- {
- /* If we're deleting an ingress flow... */
- flow = find_flow(src, srcmask, dst, dstmask, sproto,
- sa2, FLOW_INGRESS);
- if (flow == NULL)
- {
- rval = ESRCH;
- goto splxret;
- }
-
- delete_flow(flow, sa2, FLOW_INGRESS);
- splx(s);
- break;
- }
-
/* Setup the encap fields */
- encapdst.sen_family = PF_KEY;
- switch (flow->flow_src.sa.sa_family)
+ encapdst.sen_family = encapnetmask.sen_family = PF_KEY;
+ encapdst.sen_len = encapnetmask.sen_len = SENT_LEN;
+
+ switch (src->sa.sa_family)
{
#ifdef INET
case AF_INET:
- encapdst.sen_len = SENT_IP4_LEN;
encapdst.sen_type = SENT_IP4;
- encapdst.sen_ip_src = flow->flow_src.sin.sin_addr;
- encapdst.sen_ip_dst = flow->flow_dst.sin.sin_addr;
- encapdst.sen_proto = flow->flow_proto;
- encapdst.sen_sport = flow->flow_src.sin.sin_port;
- encapdst.sen_dport = flow->flow_dst.sin.sin_port;
-
- encapnetmask.sen_len = SENT_IP4_LEN;
- encapnetmask.sen_family = PF_KEY;
- encapnetmask.sen_type = SENT_IP4;
- encapnetmask.sen_ip_src = flow->flow_srcmask.sin.sin_addr;
- encapnetmask.sen_ip_dst = flow->flow_dstmask.sin.sin_addr;
- if (flow->flow_proto)
- {
- encapnetmask.sen_proto = 0xff;
-
- if (flow->flow_src.sin.sin_port)
- encapnetmask.sen_sport = 0xffff;
+ encapdst.sen_direction = direction;
+ encapdst.sen_ip_src = src->sin.sin_addr;
+ encapdst.sen_ip_dst = dst->sin.sin_addr;
+ encapdst.sen_proto = transproto;
+ encapdst.sen_sport = src->sin.sin_port;
+ encapdst.sen_dport = dst->sin.sin_port;
- if (flow->flow_dst.sin.sin_port)
- encapnetmask.sen_dport = 0xffff;
- }
+ encapnetmask.sen_type = SENT_IP4;
+ encapnetmask.sen_direction = 0xff;
+ encapnetmask.sen_ip_src = srcmask->sin.sin_addr;
+ encapnetmask.sen_ip_dst = dstmask->sin.sin_addr;
+ encapnetmask.sen_sport = srcmask->sin.sin_port;
+ encapnetmask.sen_dport = dstmask->sin.sin_port;
+ if (transproto)
+ encapnetmask.sen_proto = 0xff;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- encapdst.sen_len = SENT_IP6_LEN;
encapdst.sen_type = SENT_IP6;
- encapdst.sen_ip6_src = flow->flow_src.sin6.sin6_addr;
- encapdst.sen_ip6_dst = flow->flow_dst.sin6.sin6_addr;
- encapdst.sen_ip6_proto = flow->flow_proto;
- encapdst.sen_ip6_sport = flow->flow_src.sin6.sin6_port;
- encapdst.sen_ip6_dport = flow->flow_dst.sin6.sin6_port;
-
- encapnetmask.sen_len = SENT_IP6_LEN;
- encapnetmask.sen_family = PF_KEY;
- encapnetmask.sen_type = SENT_IP6;
- encapnetmask.sen_ip6_src =
- flow->flow_srcmask.sin6.sin6_addr;
- encapnetmask.sen_ip6_dst =
- flow->flow_dstmask.sin6.sin6_addr;
- if (flow->flow_proto)
- {
- encapnetmask.sen_ip6_proto = 0xff;
+ encapdst.sen_ip6_direction = direction;
+ encapdst.sen_ip6_src = src->sin6.sin6_addr;
+ encapdst.sen_ip6_dst = dst->sin6.sin6_addr;
+ encapdst.sen_ip6_proto = transproto;
+ encapdst.sen_ip6_sport = src->sin6.sin6_port;
+ encapdst.sen_ip6_dport = dst->sin6.sin6_port;
- if (flow->flow_src.sin6.sin6_port)
- encapnetmask.sen_ip6_sport = 0xffff;
-
- if (flow->flow_dst.sin6.sin6_port)
- encapnetmask.sen_ip6_dport = 0xffff;
- }
+ encapnetmask.sen_type = SENT_IP6;
+ encapnetmask.sen_ip6_direction = 0xff;
+ encapnetmask.sen_ip6_src = srcmask->sin6.sin6_addr;
+ encapnetmask.sen_ip6_dst = dstmask->sin6.sin6_addr;
+ encapnetmask.sen_ip6_sport = srcmask->sin6.sin6_port;
+ encapnetmask.sen_ip6_dport = dstmask->sin6.sin6_port;
+ if (transproto)
+ encapnetmask.sen_ip6_proto = 0xff;
break;
#endif /* INET6 */
}
- if (!delflag)
- {
- switch (sa2->tdb_dst.sa.sa_family)
- {
-#ifdef INET
- case AF_INET:
- encapgw.sen_len = SENT_IPSP_LEN;
- encapgw.sen_family = PF_KEY;
- encapgw.sen_type = SENT_IPSP;
- encapgw.sen_ipsp_dst = sa2->tdb_dst.sin.sin_addr;
- encapgw.sen_ipsp_spi = sa2->tdb_spi;
- encapgw.sen_ipsp_sproto = sa2->tdb_sproto;
-
- break;
-#endif /* INET */
+ /* Determine whether the exact same SPD entry already exists. */
+ bzero(&re, sizeof(struct route_enc));
+ bcopy(&encapdst, &re.re_dst, sizeof(struct sockaddr_encap));
+ rtalloc((struct route *) &re);
-#if INET6
- case AF_INET6:
- encapgw.sen_len = SENT_IPSP6_LEN;
- encapgw.sen_family = PF_KEY;
- encapgw.sen_type = SENT_IPSP6;
- encapgw.sen_ipsp6_dst = sa2->tdb_dst.sin6.sin6_addr;
- encapgw.sen_ipsp6_spi = sa2->tdb_spi;
- encapgw.sen_ipsp6_sproto = sa2->tdb_sproto;
-
- break;
-#endif /* INET6 */
-
- default:
- /*
- * This shouldn't ever happen really, as SAs
- * should be checked at establishment time.
- */
- rval = EPFNOSUPPORT;
- delete_flow(flow, flow->flow_sa, FLOW_EGRESS);
- goto splxret;
- }
+ if (re.re_rt != NULL)
+ {
+ ipo = ((struct sockaddr_encap *) re.re_rt->rt_gateway)->sen_ipsp;
+ RTFREE(re.re_rt);
+
+ /* Verify that the entry is identical */
+ if (bcmp(&ipo->ipo_addr, &encapdst,
+ sizeof(struct sockaddr_encap)) ||
+ bcmp(&ipo->ipo_mask, &encapnetmask,
+ sizeof(struct sockaddr_encap)))
+ ipo = NULL; /* Fall through */
+ else
+ exists = 1;
}
+ else
+ ipo = NULL;
- /* Add the entry in the routing table */
+ /* Delete ? */
if (delflag)
{
- rtrequest(RTM_DELETE, (struct sockaddr *) &encapdst,
- (struct sockaddr *) 0,
- (struct sockaddr *) &encapnetmask,
- 0, (struct rtentry **) 0);
-
- delete_flow(flow, flow->flow_sa, FLOW_EGRESS);
- }
- else if (!replace)
- {
- rval = rtrequest(RTM_ADD, (struct sockaddr *) &encapdst,
- (struct sockaddr *) &encapgw,
- (struct sockaddr *) &encapnetmask,
- RTF_UP | RTF_GATEWAY | RTF_STATIC,
- (struct rtentry **) 0);
-
- if (rval)
+ if (exists)
{
- delete_flow(flow, sa2, FLOW_EGRESS);
-
- if (flow2)
- delete_flow(flow2, sa2, FLOW_EGRESS);
-
- goto splxret;
+ s = spltdb();
+ rval = ipsec_delete_policy(ipo);
+ splx(s);
+ goto ret;
}
- sa2->tdb_cur_allocations++;
+ /* If we were asked to delete something non-existant, error */
+ rval = ESRCH;
+ break;
}
- else
- {
- rt = (struct rtentry *) rn_lookup(&encapdst, &encapnetmask,
- rt_tables[PF_KEY]);
- if (rt == NULL)
- {
- rval = rtrequest(RTM_ADD, (struct sockaddr *) &encapdst,
- (struct sockaddr *) &encapgw,
- (struct sockaddr *) &encapnetmask,
- RTF_UP | RTF_GATEWAY | RTF_STATIC,
- (struct rtentry **) 0);
-
- if (rval)
- {
- delete_flow(flow, sa2, FLOW_EGRESS);
- if (flow2)
- delete_flow(flow2, sa2, FLOW_EGRESS);
-
- goto splxret;
- }
- }
- else if (rt_setgate(rt, rt_key(rt),
- (struct sockaddr *) &encapgw))
+ if (!exists)
+ {
+ /* Allocate policy entry */
+ MALLOC(ipo, struct ipsec_policy *, sizeof(struct ipsec_policy),
+ M_TDB, M_NOWAIT);
+ if (ipo == NULL)
{
rval = ENOMEM;
- delete_flow(flow, sa2, FLOW_EGRESS);
-
- if (flow2)
- delete_flow(flow2, sa2, FLOW_EGRESS);
-
- goto splxret;
+ goto ret;
}
- sa2->tdb_cur_allocations++;
- }
+ bzero(ipo, sizeof(struct ipsec_policy));
- if (replace)
- {
- if (old_flow != NULL)
- delete_flow(old_flow, old_flow->flow_sa, FLOW_EGRESS);
+ /* Finish initialization of SPD entry */
+ encapgw.sen_len = SENT_LEN;
+ encapgw.sen_family = PF_KEY;
+ encapgw.sen_type = SENT_IPSP;
+ encapgw.sen_ipsp = ipo;
- if (old_flow2 != NULL)
- delete_flow(old_flow2, old_flow2->flow_sa, FLOW_EGRESS);
+ /* Initialize policy entry */
+ bcopy(&encapdst, &ipo->ipo_addr,
+ sizeof(struct sockaddr_encap));
+ bcopy(&encapnetmask, &ipo->ipo_mask,
+ sizeof(struct sockaddr_encap));
}
- /* If we are adding flows, check for allocation expirations */
- if (!delflag && !(replace && old_flow != NULL))
+ /*
+ * A direct "hint" was provided, try to locate TDB. If we
+ * don't find it, return an error, since it was expected
+ * that we'd be able to find the TDB. Be careful with any
+ * previously pointed to TDB.
+ */
+ if (ssa && ssa->sadb_sa_spi && sunionp)
{
- if ((sa2->tdb_flags & TDBF_ALLOCATIONS) &&
- (sa2->tdb_cur_allocations >= sa2->tdb_exp_allocations))
+ ktdb = ipo->ipo_tdb; /* Hold for now */
+
+ s = spltdb();
+ ipo->ipo_tdb = gettdb(ssa->sadb_sa_spi, sunionp,
+ SADB_GETSPROTO(smsg->sadb_msg_satype));
+ if (ipo->ipo_tdb == NULL)
{
- pfkeyv2_expire(sa2, SADB_EXT_LIFETIME_HARD);
- tdb_delete(sa2, 0, TDBEXP_TIMEOUT);
+ ipo->ipo_tdb = ktdb; /* Reset */
+ rval = ESRCH;
+ goto splxret;
+ }
+ else
+ {
+ if (ktdb)
+ TAILQ_REMOVE(&ktdb->tdb_policy_head, ipo, ipo_tdb_next);
+ TAILQ_INSERT_HEAD(&ipo->ipo_tdb->tdb_policy_head, ipo,
+ ipo_tdb_next);
}
- else
- if ((sa2->tdb_flags & TDBF_SOFT_ALLOCATIONS) &&
- (sa2->tdb_cur_allocations >= sa2->tdb_soft_allocations))
- {
- pfkeyv2_expire(sa2, SADB_EXT_LIFETIME_SOFT);
- sa2->tdb_flags &= ~TDBF_SOFT_ALLOCATIONS;
- }
- }
- }
-
- splx(s);
- break;
-
- case SADB_X_GRPSPIS:
- {
- struct tdb *tdb1, *tdb2, *tdb3;
- struct sadb_protocol *sa_proto;
-
- ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
- sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
- sizeof(struct sadb_address));
-
- s = spltdb();
- tdb1 = gettdb(ssa->sadb_sa_spi, sunionp,
- SADB_GETSPROTO(smsg->sadb_msg_satype));
- if (tdb1 == NULL)
- {
- rval = ESRCH;
- goto splxret;
+ splx(s);
}
- ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA2];
- sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST2] +
- sizeof(struct sadb_address));
- sa_proto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL]);
-
- tdb2 = gettdb(ssa->sadb_sa_spi, sunionp,
- SADB_GETSPROTO(sa_proto->sadb_protocol_proto));
- if (tdb2 == NULL)
+ if (sunionp)
+ bcopy(sunionp, &ipo->ipo_dst, sizeof(union sockaddr_union));
+ else
+ {
+ bzero(&ipo->ipo_dst, sizeof(union sockaddr_union));
+ ipo->ipo_dst.sa.sa_family = src->sa.sa_family;
+ ipo->ipo_dst.sa.sa_len = src->sa.sa_len;
+ }
+
+ if (ssrc)
+ bcopy(ssrc, &ipo->ipo_src, sizeof(union sockaddr_union));
+ else
{
- rval = ESRCH;
- goto splxret;
+ bzero(&ipo->ipo_src, sizeof(union sockaddr_union));
+ ipo->ipo_src.sa.sa_family = src->sa.sa_family;
+ ipo->ipo_src.sa.sa_len = src->sa.sa_len;
}
- /* Detect cycles */
- for (tdb3 = tdb2; tdb3; tdb3 = tdb3->tdb_onext)
- if (tdb3 == tdb1)
- {
- rval = ESRCH;
- goto splxret;
- }
+ ipo->ipo_sproto = SADB_GETSPROTO(smsg->sadb_msg_satype);
- /* Maintenance */
- if ((tdb1->tdb_onext) &&
- (tdb1->tdb_onext->tdb_inext == tdb1))
- tdb1->tdb_onext->tdb_inext = NULL;
-
- if ((tdb2->tdb_inext) &&
- (tdb2->tdb_inext->tdb_onext == tdb2))
- tdb2->tdb_inext->tdb_onext = NULL;
+ /* Flow type */
+ switch (((struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE])->sadb_protocol_proto)
+ {
+ case FLOW_X_TYPE_USE:
+ ipo->ipo_type = IPSP_IPSEC_USE;
+ break;
- /* Link them */
- tdb1->tdb_onext = tdb2;
- tdb2->tdb_inext = tdb1;
+ case FLOW_X_TYPE_ACQUIRE:
+ ipo->ipo_type = IPSP_IPSEC_ACQUIRE;
+ break;
- splx(s);
- }
+ case FLOW_X_TYPE_REQUIRE:
+ ipo->ipo_type = IPSP_IPSEC_REQUIRE;
+ break;
- break;
-
- case SADB_X_BINDSA:
- {
- struct tdb *tdb1, *tdb2;
- struct sadb_protocol *sa_proto;
+ case FLOW_X_TYPE_DENY:
+ ipo->ipo_type = IPSP_DENY;
+ break;
- ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
- sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
- sizeof(struct sadb_address));
+ case FLOW_X_TYPE_BYPASS:
+ ipo->ipo_type = IPSP_PERMIT;
+ break;
- s = spltdb();
+ case FLOW_X_TYPE_DONTACQ:
+ ipo->ipo_type = IPSP_IPSEC_DONTACQ;
+ break;
- tdb1 = gettdb(ssa->sadb_sa_spi, sunionp,
- SADB_GETSPROTO(smsg->sadb_msg_satype));
- if (tdb1 == NULL)
- {
- rval = ESRCH;
- goto splxret;
+ default:
+ FREE(ipo, M_TDB);
+ rval = EINVAL;
+ goto ret;
}
- if (TAILQ_FIRST(&tdb1->tdb_bind_in))
+ if (!exists)
{
- /* Incoming SA has not list of referencing incoming SAs */
- rval = EINVAL;
- goto splxret;
- }
+ /* Add SPD entry */
+ if ((rval = rtrequest(RTM_ADD, (struct sockaddr *) &encapdst,
+ (struct sockaddr *) &encapgw,
+ (struct sockaddr *) &encapnetmask,
+ RTF_UP | RTF_GATEWAY | RTF_STATIC,
+ (struct rtentry **) 0)) != 0)
+ {
+ /* Remove from linked list of policies on TDB */
+ if (ipo->ipo_tdb)
+ {
+ s = spltdb();
+ TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
+ ipo_tdb_next);
+ splx(s);
+ }
- ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA2];
- sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST2] +
- sizeof(struct sadb_address));
- sa_proto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL]);
+ FREE(ipo, M_TDB); /* Free policy entry */
+ goto ret;
+ }
- tdb2 = gettdb(ssa->sadb_sa_spi, sunionp,
- SADB_GETSPROTO(sa_proto->sadb_protocol_proto));
- if (tdb2 == NULL)
- {
- rval = ESRCH;
- goto splxret;
- }
+ s = spltdb();
+ TAILQ_INSERT_HEAD(&ipsec_policy_head, ipo, ipo_list);
+ splx(s);
- if (tdb2->tdb_bind_out)
+ ipsec_in_use++;
+ }
+ else
{
- /* Outgoing SA has no pointer to an outgoing SA */
- rval = EINVAL;
- goto splxret;
+ ipo->ipo_last_searched = ipo->ipo_flags = 0;
}
-
- /* Maintenance */
- if (tdb1->tdb_bind_out)
- TAILQ_REMOVE(&tdb1->tdb_bind_out->tdb_bind_in, tdb1,
- tdb_bind_in_next);
-
- /* Link them */
- tdb1->tdb_bind_out = tdb2;
- TAILQ_INSERT_TAIL(&tdb2->tdb_bind_in, tdb1, tdb_bind_in_next);
-
- splx(s);
- }
-
+ }
break;
case SADB_X_PROMISC:
@@ -1960,14 +1808,14 @@ splxret:
* Send an ACQUIRE message to key management, to get a new SA.
*/
int
-pfkeyv2_acquire(struct tdb *tdb, int rekey)
+pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
+ union sockaddr_union *laddr)
{
- void *p, *headers[SADB_EXT_MAX+1], *buffer = NULL;
+ void *p, *headers[SADB_EXT_MAX + 1], *buffer = NULL;
+ struct sadb_comb *sadb_comb;
struct sadb_address *sadd;
- struct sadb_msg *smsg;
- struct sadb_ident *sa_ident;
struct sadb_prop *sa_prop;
- struct sadb_comb *sadb_comb;
+ struct sadb_msg *smsg;
int rval = 0;
int i, j;
@@ -1978,14 +1826,11 @@ pfkeyv2_acquire(struct tdb *tdb, int rekey)
}
/* How large a buffer do we need... XXX we only do one proposal for now */
- i = sizeof(struct sadb_msg) + sizeof(struct sadb_address) +
- PADUP(SA_LEN(&tdb->tdb_src.sa)) + sizeof(struct sadb_address) +
- PADUP(SA_LEN(&tdb->tdb_dst.sa)) + sizeof(struct sadb_prop) +
- 1 * sizeof(struct sadb_comb) +
- 2 * sizeof(struct sadb_ident);
-
- if (rekey)
- i += PADUP(tdb->tdb_srcid_len) + PADUP(tdb->tdb_dstid_len);
+ i = sizeof(struct sadb_msg) +
+ (laddr == NULL ? 0 : sizeof(struct sadb_address) +
+ PADUP(SA_LEN(&ipo->ipo_src.sa))) +
+ sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa)) +
+ sizeof(struct sadb_prop) + 1 * sizeof(struct sadb_comb);
/* Allocate */
if (!(p = malloc(i, M_PFKEY, M_DONTWAIT)))
@@ -2007,188 +1852,139 @@ pfkeyv2_acquire(struct tdb *tdb, int rekey)
smsg->sadb_msg_type = SADB_ACQUIRE;
smsg->sadb_msg_len = i / sizeof(uint64_t);
smsg->sadb_msg_seq = pfkeyv2_seq++;
- smsg->sadb_msg_satype = tdb->tdb_satype;
- headers[SADB_EXT_ADDRESS_SRC] = p;
- p += sizeof(struct sadb_address) + PADUP(SA_LEN(&tdb->tdb_src.sa));
- sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC];
- sadd->sadb_address_len = (sizeof(struct sadb_address) +
- SA_LEN(&tdb->tdb_src.sa) +
- sizeof(uint64_t) - 1) / sizeof(uint64_t);
- bcopy(&tdb->tdb_src,
- headers[SADB_EXT_ADDRESS_SRC] + sizeof(struct sadb_address),
- SA_LEN(&tdb->tdb_src.sa));
+ if (ipo->ipo_sproto == IPPROTO_ESP)
+ smsg->sadb_msg_satype = SADB_SATYPE_ESP;
+ else
+ smsg->sadb_msg_satype = SADB_SATYPE_AH;
+
+ if (laddr)
+ {
+ headers[SADB_EXT_ADDRESS_SRC] = p;
+ p += sizeof(struct sadb_address) + PADUP(SA_LEN(&laddr->sa));
+ sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC];
+ sadd->sadb_address_len = (sizeof(struct sadb_address) +
+ SA_LEN(&laddr->sa) +
+ sizeof(uint64_t) - 1) / sizeof(uint64_t);
+ bcopy(laddr,
+ headers[SADB_EXT_ADDRESS_SRC] + sizeof(struct sadb_address),
+ SA_LEN(&laddr->sa));
+ }
headers[SADB_EXT_ADDRESS_DST] = p;
- p += sizeof(struct sadb_address) + PADUP(SA_LEN(&tdb->tdb_dst.sa));
+ p += sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa));
sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_DST];
sadd->sadb_address_len = (sizeof(struct sadb_address) +
- SA_LEN(&tdb->tdb_dst.sa) +
+ SA_LEN(&gw->sa) +
sizeof(uint64_t) - 1) / sizeof(uint64_t);
- bcopy(&tdb->tdb_dst,
- headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address),
- SA_LEN(&tdb->tdb_dst.sa));
-
- headers[SADB_EXT_IDENTITY_SRC] = p;
- p += sizeof(struct sadb_ident);
- sa_ident = (struct sadb_ident *) headers[SADB_EXT_IDENTITY_SRC];
- sa_ident->sadb_ident_type = tdb->tdb_srcid_type;
-
- /* XXX some day we'll have to deal with real ident_ids for users */
- sa_ident->sadb_ident_id = 0;
-
- if (rekey)
- {
- sa_ident->sadb_ident_len = (sizeof(struct sadb_ident) +
- PADUP(tdb->tdb_srcid_len)) /
- sizeof(uint64_t);
- bcopy(tdb->tdb_srcid, p, tdb->tdb_srcid_len);
- p += PADUP(tdb->tdb_srcid_len);
- }
- else
- sa_ident->sadb_ident_len = sizeof(struct sadb_ident) / sizeof(uint64_t);
-
- headers[SADB_EXT_IDENTITY_DST] = p;
- p += sizeof(struct sadb_ident);
- sa_ident = (struct sadb_ident *) headers[SADB_EXT_IDENTITY_DST];
- sa_ident->sadb_ident_type = tdb->tdb_dstid_type;
-
- /* XXX some day we'll have to deal with real ident_ids for users */
- sa_ident->sadb_ident_id = 0;
-
- if (rekey)
- {
- sa_ident->sadb_ident_len = (sizeof(struct sadb_ident) +
- PADUP(tdb->tdb_dstid_len)) /
- sizeof(uint64_t);
- bcopy(tdb->tdb_dstid, p, tdb->tdb_dstid_len);
- p += PADUP(tdb->tdb_dstid_len);
- }
- else
- sa_ident->sadb_ident_len = sizeof(struct sadb_ident) / sizeof(uint64_t);
+ bcopy(gw, headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address),
+ SA_LEN(&gw->sa));
headers[SADB_EXT_PROPOSAL] = p;
p += sizeof(struct sadb_prop);
sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL];
- sa_prop->sadb_prop_num = 1; /* XXX Only 1 proposal supported for now */
+ sa_prop->sadb_prop_num = 1; /* XXX One proposal only */
sa_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
(sizeof(struct sadb_comb) *
sa_prop->sadb_prop_num)) / sizeof(uint64_t);
sadb_comb = p;
+ /* XXX Should actually ask the crypto layer what's supported */
for (j = 0; j < sa_prop->sadb_prop_num; j++)
{
sadb_comb->sadb_comb_flags = 0;
- if (tdb->tdb_flags & TDBF_PFS)
+ if (ipsec_require_pfs)
sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS;
- if (tdb->tdb_flags & TDBF_HALFIV)
- sadb_comb->sadb_comb_flags |= SADB_X_SAFLAGS_HALFIV;
-
- if (tdb->tdb_flags & TDBF_TUNNELING)
- sadb_comb->sadb_comb_flags |= SADB_X_SAFLAGS_TUNNEL;
-
- if (tdb->tdb_authalgxform)
+ /* Set the encryption algorithm */
+ if (ipo->ipo_sproto == IPPROTO_ESP)
{
- switch (tdb->tdb_authalgxform->type)
+ if (!strncasecmp(ipsec_def_enc, "3des", sizeof("3des")))
{
- case CRYPTO_MD5_HMAC96:
- sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC96;
- break;
-
- case CRYPTO_SHA1_HMAC96:
- sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC96;
- break;
-
- case CRYPTO_RIPEMD160_HMAC96:
- sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC96;
- break;
-
- case CRYPTO_MD5_KPDK:
- sadb_comb->sadb_comb_auth = SADB_X_AALG_MD5;
- break;
-
- case CRYPTO_SHA1_KPDK:
- sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA1;
- break;
+ sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
+ sadb_comb->sadb_comb_encrypt_minbits = 192;
+ sadb_comb->sadb_comb_encrypt_maxbits = 192;
}
-
- sadb_comb->sadb_comb_auth_minbits =
- tdb->tdb_authalgxform->keysize * 8;
- sadb_comb->sadb_comb_auth_maxbits =
- tdb->tdb_authalgxform->keysize * 8;
- }
- else
- {
- sadb_comb->sadb_comb_auth = 0;
- sadb_comb->sadb_comb_auth_minbits = 0;
- sadb_comb->sadb_comb_auth_maxbits = 0;
+ else
+ if (!strncasecmp(ipsec_def_enc, "des", sizeof("des")))
+ {
+ sadb_comb->sadb_comb_encrypt = SADB_EALG_DESCBC;
+ sadb_comb->sadb_comb_encrypt_minbits = 64;
+ sadb_comb->sadb_comb_encrypt_maxbits = 64;
+ }
+ else
+ if (!strncasecmp(ipsec_def_enc, "blowfish",
+ sizeof("blowfish")))
+ {
+ sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF;
+ sadb_comb->sadb_comb_encrypt_minbits = 40;
+ sadb_comb->sadb_comb_encrypt_maxbits = BLF_MAXKEYLEN * 8;
+ }
+ else
+ if (!strncasecmp(ipsec_def_enc, "skipjack",
+ sizeof("skipjack")))
+ {
+ sadb_comb->sadb_comb_encrypt = SADB_X_EALG_SKIPJACK;
+ sadb_comb->sadb_comb_encrypt_minbits = 80;
+ sadb_comb->sadb_comb_encrypt_maxbits = 80;
+ }
+ else
+ if (!strncasecmp(ipsec_def_enc, "cast128",
+ sizeof("cast128")))
+ {
+ sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST;
+ sadb_comb->sadb_comb_encrypt_minbits = 40;
+ sadb_comb->sadb_comb_encrypt_maxbits = 128;
+ }
}
- if (tdb->tdb_encalgxform)
+ /* Set the authentication algorithm */
+ if (!strncasecmp(ipsec_def_auth, "hmac-sha1", sizeof("hmac-sha1")))
{
- switch (tdb->tdb_encalgxform->type)
- {
- case CRYPTO_DES_CBC:
- sadb_comb->sadb_comb_encrypt = SADB_EALG_DESCBC;
- break;
-
- case CRYPTO_3DES_CBC:
- sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
- break;
-
- case CRYPTO_CAST_CBC:
- sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST;
- break;
-
- case CRYPTO_BLF_CBC:
- sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF;
- break;
-
- case CRYPTO_SKIPJACK_CBC:
- sadb_comb->sadb_comb_encrypt = SADB_X_EALG_SKIPJACK;
- break;
- }
-
- sadb_comb->sadb_comb_encrypt_minbits =
- tdb->tdb_encalgxform->minkey * 8;
- sadb_comb->sadb_comb_encrypt_maxbits =
- tdb->tdb_encalgxform->maxkey * 8;
+ sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC96;
+ sadb_comb->sadb_comb_auth_minbits = 160;
+ sadb_comb->sadb_comb_auth_maxbits = 160;
}
else
- {
- sadb_comb->sadb_comb_encrypt = 0;
- sadb_comb->sadb_comb_encrypt_minbits = 0;
- sadb_comb->sadb_comb_encrypt_maxbits = 0;
- }
-
- sadb_comb->sadb_comb_soft_allocations = tdb->tdb_soft_allocations;
- sadb_comb->sadb_comb_hard_allocations = tdb->tdb_exp_allocations;
+ if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160",
+ sizeof("hmac_ripemd160")))
+ {
+ sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC96;
+ sadb_comb->sadb_comb_auth_minbits = 160;
+ sadb_comb->sadb_comb_auth_maxbits = 160;
+ }
+ else
+ if (!strncasecmp(ipsec_def_auth, "hmac-md5", sizeof("hmac-md5")))
+ {
+ sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC96;
+ sadb_comb->sadb_comb_auth_minbits = 128;
+ sadb_comb->sadb_comb_auth_maxbits = 128;
+ }
+
+ sadb_comb->sadb_comb_soft_allocations = ipsec_soft_allocations;
+ sadb_comb->sadb_comb_hard_allocations = ipsec_exp_allocations;
- sadb_comb->sadb_comb_soft_bytes = tdb->tdb_soft_bytes;
- sadb_comb->sadb_comb_hard_bytes = tdb->tdb_exp_bytes;
+ sadb_comb->sadb_comb_soft_bytes = ipsec_soft_bytes;
+ sadb_comb->sadb_comb_hard_bytes = ipsec_exp_bytes;
- sadb_comb->sadb_comb_soft_addtime = tdb->tdb_soft_timeout;
- sadb_comb->sadb_comb_hard_addtime = tdb->tdb_exp_timeout;
+ sadb_comb->sadb_comb_soft_addtime = ipsec_soft_timeout;
+ sadb_comb->sadb_comb_hard_addtime = ipsec_exp_timeout;
- sadb_comb->sadb_comb_soft_usetime = tdb->tdb_soft_first_use;
- sadb_comb->sadb_comb_hard_usetime = tdb->tdb_exp_first_use;
+ sadb_comb->sadb_comb_soft_usetime = ipsec_soft_first_use;
+ sadb_comb->sadb_comb_hard_usetime = ipsec_exp_first_use;
sadb_comb++;
}
- /*
- * Send the ACQUIRE message to all compliant registered listeners.
- * XXX We only send it to the first compliant registered
- * listener (as specified by the last argument)
- */
+ /* XXX How to externalize the policy itself ? */
+
+ /* Send the ACQUIRE message to all compliant registered listeners. */
if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_REGISTERED,
- NULL, smsg->sadb_msg_satype, 1)) != 0)
+ NULL, smsg->sadb_msg_satype, 0)) != 0)
goto ret;
rval = 0;
-
ret:
if (buffer != NULL)
{
diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
index 1952b82a05b..9a6fcb9a300 100644
--- a/sys/net/pfkeyv2.h
+++ b/sys/net/pfkeyv2.h
@@ -28,9 +28,7 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#define SADB_X_PROMISC 11
#define SADB_X_ADDFLOW 12
#define SADB_X_DELFLOW 13
-#define SADB_X_GRPSPIS 14
-#define SADB_X_BINDSA 15
-#define SADB_MAX 15
+#define SADB_MAX 13
struct sadb_msg {
uint8_t sadb_msg_version;
@@ -155,14 +153,13 @@ struct sadb_protocol {
uint16_t sadb_protocol_len;
uint16_t sadb_protocol_exttype;
uint8_t sadb_protocol_proto;
- uint8_t sadb_protocol_reserved1;
+ uint8_t sadb_protocol_direction;
uint16_t sadb_protocol_reserved2;
};
#define SADB_GETSPROTO(x) ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\
(x) == SADB_SATYPE_ESP ? IPPROTO_ESP :\
- (x) == SADB_X_SATYPE_BYPASS ? IPPROTO_IP :\
- IPPROTO_IPIP )
+ IPPROTO_IPIP )
#define SADB_EXT_RESERVED 0
#define SADB_EXT_SA 1
@@ -183,11 +180,10 @@ struct sadb_protocol {
#define SADB_X_EXT_SRC_MASK 16
#define SADB_X_EXT_DST_MASK 17
#define SADB_X_EXT_PROTOCOL 18
-#define SADB_X_EXT_SA2 19
+#define SADB_X_EXT_FLOW_TYPE 19
#define SADB_X_EXT_SRC_FLOW 20
#define SADB_X_EXT_DST_FLOW 21
-#define SADB_X_EXT_DST2 22
-#define SADB_EXT_MAX 22
+#define SADB_EXT_MAX 21
/* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */
#define SADB_SATYPE_UNSPEC 0
@@ -199,8 +195,7 @@ struct sadb_protocol {
#define SADB_SATYPE_MIP 6
#define SADB_X_SATYPE_IPIP 7
#define SADB_X_SATYPE_TCPSIGNATURE 8
-#define SADB_X_SATYPE_BYPASS 9
-#define SADB_SATYPE_MAX 9
+#define SADB_SATYPE_MAX 8
#define SADB_SASTATE_LARVAL 0
#define SADB_SASTATE_MATURE 1
@@ -230,8 +225,6 @@ struct sadb_protocol {
#define SADB_X_SAFLAGS_HALFIV 0x002 /* Used for ESP-old */
#define SADB_X_SAFLAGS_TUNNEL 0x004 /* Force tunneling */
#define SADB_X_SAFLAGS_CHAINDEL 0x008 /* Delete whole SA chain */
-#define SADB_X_SAFLAGS_REPLACEFLOW 0x020 /* Replace existing flow */
-#define SADB_X_SAFLAGS_INGRESS_FLOW 0x040 /* Ingress ACL entry */
#define SADB_X_SAFLAGS_RANDOMPADDING 0x080 /* Random ESP padding */
#define SADB_X_SAFLAGS_NOREPLAY 0x100 /* No replay counter */
@@ -261,6 +254,15 @@ struct sadb_protocol {
#define PFKEYV2_SENDMESSAGE_REGISTERED 2
#define PFKEYV2_SENDMESSAGE_BROADCAST 3
+#define FLOW_X_TYPE_USE 1
+#define FLOW_X_TYPE_ACQUIRE 2
+#define FLOW_X_TYPE_REQUIRE 3
+#define FLOW_X_TYPE_BYPASS 4
+#define FLOW_X_TYPE_DENY 5
+#define FLOW_X_TYPE_DONTACQ 6
+
+#define OPENBSD_IPSEC_API_VERSION 1
+
#ifdef _KERNEL
struct tdb;
struct socket;
@@ -293,7 +295,8 @@ int pfkeyv2_init(void);
int pfkeyv2_cleanup(void);
int pfkeyv2_parsemessage(void *, int, void **);
int pfkeyv2_expire(struct tdb *, u_int16_t);
-int pfkeyv2_acquire(struct tdb *, int);
+int pfkeyv2_acquire(struct ipsec_policy *, union sockaddr_union *,
+ union sockaddr_union *);
int pfkey_register(struct pfkey_version *version);
int pfkey_unregister(struct pfkey_version *version);
diff --git a/sys/net/pfkeyv2_parsemessage.c b/sys/net/pfkeyv2_parsemessage.c
index abd123d9696..907c26cfb61 100644
--- a/sys/net/pfkeyv2_parsemessage.c
+++ b/sys/net/pfkeyv2_parsemessage.c
@@ -27,6 +27,7 @@ you didn't get a copy, you may request one from <license@inner.net>.
#include <sys/proc.h>
#include <net/route.h>
#include <netinet/in.h>
+#include <netinet/ip_ipsp.h>
#include <net/pfkeyv2.h>
#define BITMAP_SA (1 << SADB_EXT_SA)
@@ -52,10 +53,9 @@ you didn't get a copy, you may request one from <license@inner.net>.
#define BITMAP_X_SRC_MASK (1 << SADB_X_EXT_SRC_MASK)
#define BITMAP_X_DST_MASK (1 << SADB_X_EXT_DST_MASK)
#define BITMAP_X_PROTOCOL (1 << SADB_X_EXT_PROTOCOL)
-#define BITMAP_X_SA2 (1 << SADB_X_EXT_SA2)
#define BITMAP_X_SRC_FLOW (1 << SADB_X_EXT_SRC_FLOW)
#define BITMAP_X_DST_FLOW (1 << SADB_X_EXT_DST_FLOW)
-#define BITMAP_X_DST2 (1 << SADB_X_EXT_DST2)
+#define BITMAP_X_FLOW_TYPE (1 << SADB_X_EXT_FLOW_TYPE)
uint32_t sadb_exts_allowed_in[SADB_MAX+1] =
{
@@ -72,7 +72,7 @@ uint32_t sadb_exts_allowed_in[SADB_MAX+1] =
/* GET */
BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
/* ACQUIRE */
- BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL,
+ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK,
/* REGISTER */
0,
/* EXPIRE */
@@ -84,13 +84,9 @@ uint32_t sadb_exts_allowed_in[SADB_MAX+1] =
/* X_PROMISC */
0,
/* X_ADDFLOW */
- BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW,
+ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
/* X_DELFLOW */
- BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA | BITMAP_ADDRESS_DST,
- /* X_GRPSPIS */
- BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
- /* X_BINDSA */
- BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL
+ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA | BITMAP_ADDRESS_DST | BITMAP_X_FLOW_TYPE,
};
uint32_t sadb_exts_required_in[SADB_MAX+1] =
@@ -120,13 +116,9 @@ uint32_t sadb_exts_required_in[SADB_MAX+1] =
/* X_PROMISC */
0,
/* X_ADDFLOW */
- BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW,
+ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
/* X_DELFLOW */
- BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW,
- /* X_GRPSPIS */
- BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
- /* X_BINDSA */
- BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL
+ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
};
uint32_t sadb_exts_allowed_out[SADB_MAX+1] =
@@ -144,7 +136,7 @@ uint32_t sadb_exts_allowed_out[SADB_MAX+1] =
/* GET */
BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY,
/* ACQUIRE */
- BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL,
+ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK,
/* REGISTER */
BITMAP_SUPPORTED,
/* EXPIRE */
@@ -156,13 +148,9 @@ uint32_t sadb_exts_allowed_out[SADB_MAX+1] =
/* X_PROMISC */
0,
/* X_ADDFLOW */
- BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW,
+ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
/* X_DELFLOW */
- BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA | BITMAP_ADDRESS_DST,
- /* X_GRPSPIS */
- BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
- /* X_BINDSA */
- BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL
+ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_SA | BITMAP_ADDRESS_DST | BITMAP_X_FLOW_TYPE,
};
uint32_t sadb_exts_required_out[SADB_MAX+1] =
@@ -192,13 +180,9 @@ uint32_t sadb_exts_required_out[SADB_MAX+1] =
/* X_PROMISC */
0,
/* X_ADDFLOW */
- BITMAP_ADDRESS_DST | BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW,
+ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
/* X_DELFLOW */
- BITMAP_SA | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW,
- /* X_GRPSPIS */
- BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
- /* X_BINDSA */
- BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL
+ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
};
int pfkeyv2_parsemessage(void *, int, void **);
@@ -274,7 +258,6 @@ pfkeyv2_parsemessage(void *p, int len, void **headers)
seen |= (1 << sadb_ext->sadb_ext_type);
switch (sadb_ext->sadb_ext_type) {
- case SADB_X_EXT_SA2:
case SADB_EXT_SA:
{
struct sadb_sa *sadb_sa = (struct sadb_sa *)p;
@@ -299,6 +282,7 @@ pfkeyv2_parsemessage(void *p, int len, void **headers)
}
break;
case SADB_X_EXT_PROTOCOL:
+ case SADB_X_EXT_FLOW_TYPE:
if (i != sizeof(struct sadb_protocol))
return EINVAL;
break;
@@ -312,7 +296,6 @@ pfkeyv2_parsemessage(void *p, int len, void **headers)
break;
case SADB_EXT_ADDRESS_SRC:
case SADB_EXT_ADDRESS_DST:
- case SADB_X_EXT_DST2:
case SADB_X_EXT_SRC_MASK:
case SADB_X_EXT_DST_MASK:
case SADB_X_EXT_SRC_FLOW: