summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>2000-10-14 06:23:53 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>2000-10-14 06:23:53 +0000
commit8daaea286dc3be20a9c7897fe10b935d97c6863a (patch)
treeb3c392d2ca74b2c8c3d85325496c132297609de0
parentd6277e1dfdb29065da02107dc01cdcee0968b5d8 (diff)
ASKPOLICY message; used by key management to inquire about policy
triggering an ACQUIRE.
-rw-r--r--sys/net/pfkeyv2.c196
-rw-r--r--sys/net/pfkeyv2.h17
-rw-r--r--sys/net/pfkeyv2_parsemessage.c17
-rw-r--r--sys/netinet/ip_ipsp.h12
-rw-r--r--sys/netinet/ip_spd.c194
5 files changed, 411 insertions, 25 deletions
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index f4a5e3f6a92..c1eb6ab2eea 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.47 2000/10/09 22:18:29 angelos Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.48 2000/10/14 06:23:51 angelos Exp $ */
/*
%%% copyright-nrl-97
This software is Copyright 1997-1998 by Randall Atkinson, Ronald Lee,
@@ -77,6 +77,7 @@ void import_sa(struct tdb *, struct sadb_sa *, struct ipsecinit *);
int pfkeyv2_create(struct socket *);
int pfkeyv2_get(struct tdb *, void **, void **);
+int pfkeyv2_policy(struct ipsec_acquire *, void **, void **);
int pfkeyv2_release(struct socket *);
int pfkeyv2_send(struct socket *, void *, int);
int pfkeyv2_sendmessage(void **, int, struct socket *, u_int8_t, int);
@@ -740,6 +741,174 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket,
}
/*
+ * Get SPD information for an ACQUIRE. We setup the message such that
+ * the SRC/DST payloads are relative to us (regardless of whether the
+ * SPD rule was for incoming or outgoing packets).
+ */
+int
+pfkeyv2_policy(struct ipsec_acquire *ipa, void **headers, void **buffer)
+{
+ union sockaddr_union sunion;
+ struct sadb_protocol *sp;
+ int rval, i, dir;
+ void *p;
+
+ /* Find out how big a buffer we need */
+ i = 4 * sizeof(struct sadb_address) + sizeof(struct sadb_protocol);
+ bzero(&sunion, sizeof(union sockaddr_union));
+
+ switch (ipa->ipa_info.sen_type)
+ {
+#ifdef INET
+ case SENT_IP4:
+ i += 4 * PADUP(sizeof(struct sockaddr_in));
+ sunion.sa.sa_family = AF_INET;
+ sunion.sa.sa_len = sizeof(struct sockaddr_in);
+ dir = ipa->ipa_info.sen_direction;
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case SENT_IP6:
+ i += 4 * PADUP(sizeof(struct sockaddr_in6));
+ sunion.sa.sa_family = AF_INET6;
+ sunion.sa.sa_len = sizeof(struct sockaddr_in6);
+ dir = ipa->ipa_info.sen_ip6_direction;
+ break;
+#endif /* INET6 */
+
+ default:
+ return EINVAL;
+ }
+
+ if (!(p = malloc(i, M_PFKEY, M_DONTWAIT)))
+ {
+ rval = ENOMEM;
+ goto ret;
+ }
+ else
+ {
+ *buffer = p;
+ bzero(p, i);
+ }
+
+ if (dir == IPSP_DIRECTION_OUT)
+ headers[SADB_X_EXT_SRC_FLOW] = p;
+ else
+ headers[SADB_X_EXT_DST_FLOW] = p;
+ switch (sunion.sa.sa_family)
+ {
+#ifdef INET
+ case AF_INET:
+ sunion.sin.sin_addr = ipa->ipa_info.sen_ip_src;
+ sunion.sin.sin_port = ipa->ipa_info.sen_sport;
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case AF_INET6:
+ sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_src;
+ sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_sport;
+ break;
+#endif /* INET6 */
+ }
+ export_address(&p, (struct sockaddr *) &sunion);
+
+ if (dir == IPSP_DIRECTION_OUT)
+ headers[SADB_X_EXT_SRC_MASK] = p;
+ else
+ headers[SADB_X_EXT_DST_MASK] = p;
+ switch (sunion.sa.sa_family)
+ {
+#ifdef INET
+ case AF_INET:
+ sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_src;
+ sunion.sin.sin_port = ipa->ipa_mask.sen_sport;
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case AF_INET6:
+ sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_src;
+ sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_sport;
+ break;
+#endif /* INET6 */
+ }
+ export_address(&p, (struct sockaddr *) &sunion);
+
+ if (dir == IPSP_DIRECTION_OUT)
+ headers[SADB_X_EXT_DST_FLOW] = p;
+ else
+ headers[SADB_X_EXT_SRC_FLOW] = p;
+ switch (sunion.sa.sa_family)
+ {
+#ifdef INET
+ case AF_INET:
+ sunion.sin.sin_addr = ipa->ipa_info.sen_ip_dst;
+ sunion.sin.sin_port = ipa->ipa_info.sen_dport;
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case AF_INET6:
+ sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_dst;
+ sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_dport;
+ break;
+#endif /* INET6 */
+ }
+ export_address(&p, (struct sockaddr *) &sunion);
+
+ if (dir == IPSP_DIRECTION_OUT)
+ headers[SADB_X_EXT_DST_MASK] = p;
+ else
+ headers[SADB_X_EXT_SRC_MASK] = p;
+ switch (sunion.sa.sa_family)
+ {
+#ifdef INET
+ case AF_INET:
+ sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_dst;
+ sunion.sin.sin_port = ipa->ipa_mask.sen_dport;
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case AF_INET6:
+ sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_dst;
+ sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_dport;
+ break;
+#endif /* INET6 */
+ }
+ export_address(&p, (struct sockaddr *) &sunion);
+
+ headers[SADB_X_EXT_FLOW_TYPE] = p;
+ sp = p;
+ sp->sadb_protocol_len = sizeof(struct sadb_protocol) / sizeof(u_int64_t);
+ switch (sunion.sa.sa_family)
+ {
+#ifdef INET
+ case AF_INET:
+ if (ipa->ipa_mask.sen_proto)
+ sp->sadb_protocol_proto = ipa->ipa_info.sen_proto;
+ sp->sadb_protocol_direction = ipa->ipa_info.sen_direction;
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case AF_INET6:
+ if (ipa->ipa_mask.sen_ip6_proto)
+ sp->sadb_protocol_proto = ipa->ipa_info.sen_ip6_proto;
+ sp->sadb_protocol_direction = ipa->ipa_info.sen_ip6_direction;
+ break;
+#endif /* INET6 */
+ }
+
+ rval = 0;
+
+ ret:
+ return rval;
+}
+
+/*
* Get all the information contained in an SA to a PFKEYV2 message.
*/
int
@@ -968,6 +1137,7 @@ 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 ipsec_acquire *ipa;
struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL;
@@ -1304,6 +1474,21 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
sa2 = NULL;
break;
+ case SADB_X_ASKPOLICY:
+ /* Get the relevant policy */
+ ipa = ipsec_get_acquire(((struct sadb_policy *) headers[SADB_X_EXT_POLICY])->sadb_policy_seq);
+ if (ipa == NULL)
+ {
+ rval = ESRCH;
+ goto ret;
+ }
+
+ rval = pfkeyv2_policy(ipa, headers, &freeme);
+ if (rval)
+ mode = PFKEYV2_SENDMESSAGE_UNICAST;
+
+ break;
+
case SADB_GET:
ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
@@ -1915,7 +2100,8 @@ splxret:
*/
int
pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
- union sockaddr_union *laddr)
+ union sockaddr_union *laddr, u_int32_t *seq,
+ struct sockaddr_encap *ddst)
{
void *p, *headers[SADB_EXT_MAX + 1], *buffer = NULL;
struct sadb_ident *srcid, *dstid;
@@ -1926,6 +2112,8 @@ pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
int rval = 0;
int i, j;
+ *seq = pfkeyv2_seq++;
+
if (!nregistered)
{
rval = ESRCH;
@@ -1964,7 +2152,7 @@ pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
smsg->sadb_msg_version = PF_KEY_V2;
smsg->sadb_msg_type = SADB_ACQUIRE;
smsg->sadb_msg_len = i / sizeof(uint64_t);
- smsg->sadb_msg_seq = pfkeyv2_seq++;
+ smsg->sadb_msg_seq = *seq;
if (ipo->ipo_sproto == IPPROTO_ESP)
smsg->sadb_msg_satype = SADB_SATYPE_ESP;
@@ -2123,8 +2311,6 @@ pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
sadb_comb++;
}
- /* 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, 0)) != 0)
diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
index 92b76665be4..9d7073f70b6 100644
--- a/sys/net/pfkeyv2.h
+++ b/sys/net/pfkeyv2.h
@@ -29,7 +29,8 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#define SADB_X_ADDFLOW 12
#define SADB_X_DELFLOW 13
#define SADB_X_GRPSPIS 14
-#define SADB_MAX 14
+#define SADB_X_ASKPOLICY 15
+#define SADB_MAX 15
struct sadb_msg {
uint8_t sadb_msg_version;
@@ -157,7 +158,13 @@ struct sadb_protocol {
uint8_t sadb_protocol_direction;
uint16_t sadb_protocol_reserved2;
};
-
+
+struct sadb_policy {
+ uint16_t sadb_policy_len;
+ uint16_t sadb_policy_exttype;
+ u_int32_t sadb_policy_seq;
+};
+
#define SADB_GETSPROTO(x) ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\
(x) == SADB_SATYPE_ESP ? IPPROTO_ESP :\
IPPROTO_IPIP )
@@ -186,7 +193,8 @@ struct sadb_protocol {
#define SADB_X_EXT_DST_FLOW 21
#define SADB_X_EXT_SA2 22
#define SADB_X_EXT_DST2 23
-#define SADB_EXT_MAX 23
+#define SADB_X_EXT_POLICY 24
+#define SADB_EXT_MAX 24
/* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */
#define SADB_SATYPE_UNSPEC 0
@@ -300,7 +308,8 @@ int pfkeyv2_cleanup(void);
int pfkeyv2_parsemessage(void *, int, void **);
int pfkeyv2_expire(struct tdb *, u_int16_t);
int pfkeyv2_acquire(struct ipsec_policy *, union sockaddr_union *,
- union sockaddr_union *);
+ union sockaddr_union *, u_int32_t *,
+ struct sockaddr_encap *);
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 6977e074b25..9d0acd8d4dd 100644
--- a/sys/net/pfkeyv2_parsemessage.c
+++ b/sys/net/pfkeyv2_parsemessage.c
@@ -58,6 +58,7 @@ you didn't get a copy, you may request one from <license@inner.net>.
#define BITMAP_X_FLOW_TYPE (1 << SADB_X_EXT_FLOW_TYPE)
#define BITMAP_X_SA2 (1 << SADB_X_EXT_SA2)
#define BITMAP_X_DST2 (1 << SADB_X_EXT_DST2)
+#define BITMAP_X_POLICY (1 << SADB_X_EXT_POLICY)
uint32_t sadb_exts_allowed_in[SADB_MAX+1] =
{
@@ -74,7 +75,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_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK,
+ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL,
/* REGISTER */
0,
/* EXPIRE */
@@ -91,6 +92,8 @@ uint32_t sadb_exts_allowed_in[SADB_MAX+1] =
BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
/* X_GRPSPIS */
BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
+ /* X_ASKPOLICY */
+ BITMAP_X_POLICY,
};
uint32_t sadb_exts_required_in[SADB_MAX+1] =
@@ -125,6 +128,8 @@ uint32_t sadb_exts_required_in[SADB_MAX+1] =
BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
/* X_GRPSPIS */
BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
+ /* X_ASKPOLICY */
+ BITMAP_X_POLICY,
};
uint32_t sadb_exts_allowed_out[SADB_MAX+1] =
@@ -142,7 +147,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_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK,
+ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL,
/* REGISTER */
BITMAP_SUPPORTED,
/* EXPIRE */
@@ -159,6 +164,8 @@ uint32_t sadb_exts_allowed_out[SADB_MAX+1] =
BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
/* X_GRPSPIS */
BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
+ /* X_ASKPOLICY */
+ BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE | BITMAP_X_POLICY,
};
uint32_t sadb_exts_required_out[SADB_MAX+1] =
@@ -193,6 +200,8 @@ uint32_t sadb_exts_required_out[SADB_MAX+1] =
BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
/* X_GRPSPIS */
BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
+ /* X_REPPOLICY */
+ BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE,
};
int pfkeyv2_parsemessage(void *, int, void **);
@@ -297,6 +306,10 @@ pfkeyv2_parsemessage(void *p, int len, void **headers)
if (i != sizeof(struct sadb_protocol))
return EINVAL;
break;
+ case SADB_X_EXT_POLICY:
+ if (i != sizeof(struct sadb_policy))
+ return EINVAL;
+ break;
case SADB_EXT_LIFETIME_CURRENT:
case SADB_EXT_LIFETIME_HARD:
case SADB_EXT_LIFETIME_SOFT:
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index c5ff3ac2358..48c15b275bd 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.73 2000/10/09 22:20:41 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.74 2000/10/14 06:23:52 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -155,8 +155,11 @@ struct sockaddr_encap
struct ipsec_acquire
{
- union sockaddr_union ipa_addr;
- u_int64_t ipa_expire;
+ union sockaddr_union ipa_addr;
+ u_int64_t ipa_expire;
+ u_int32_t ipa_seq;
+ struct sockaddr_encap ipa_info;
+ struct sockaddr_encap ipa_mask;
TAILQ_ENTRY(ipsec_acquire) ipa_next;
};
@@ -568,7 +571,7 @@ extern struct tdb *ipsp_spd_lookup(struct mbuf *, int, int, int *, int,
struct tdb *, struct inpcb *);
extern int ipsec_common_input_cb(struct mbuf *, struct tdb *, int, int);
extern int ipsp_acquire_sa(struct ipsec_policy *, union sockaddr_union *,
- union sockaddr_union *);
+ union sockaddr_union *, struct sockaddr_encap *);
extern struct ipsec_policy *ipsec_add_policy(struct sockaddr_encap *,
struct sockaddr_encap *,
union sockaddr_union *, int, int);
@@ -576,5 +579,6 @@ extern int ipsp_match_policy(struct tdb *, struct ipsec_policy *,
struct mbuf *, int);
extern void ipsp_acquire_expirations(void *);
extern int ipsec_delete_policy(struct ipsec_policy *);
+extern struct ipsec_acquire *ipsec_get_acquire(u_int32_t);
#endif /* _KERNEL */
#endif /* _NETINET_IPSP_H_ */
diff --git a/sys/netinet/ip_spd.c b/sys/netinet/ip_spd.c
index 521cd39999b..2ab086b5256 100644
--- a/sys/netinet/ip_spd.c
+++ b/sys/netinet/ip_spd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_spd.c,v 1.4 2000/09/29 19:46:26 angelos Exp $ */
+/* $OpenBSD: ip_spd.c,v 1.5 2000/10/14 06:23:52 angelos Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -84,7 +84,7 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
union sockaddr_union sdst, ssrc;
struct sockaddr_encap *ddst;
struct ipsec_policy *ipo;
- int ignore = 0;
+ int signore = 0, dignore = 0;
/*
* If there are no flows in place, there's no point
@@ -285,6 +285,8 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
else
bcopy(&ipo->ipo_dst, &ssrc, sizeof(union sockaddr_union));
}
+ else
+ dignore = 1;
break;
#endif /* INET */
@@ -297,6 +299,8 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
else
bcopy(&ipo->ipo_dst, &ssrc, sizeof(union sockaddr_union));
}
+ else
+ dignore = 1;
break;
#endif /* INET6 */
}
@@ -313,7 +317,7 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
bcopy(&ipo->ipo_src, &sdst, sizeof(union sockaddr_union));
}
else
- ignore = 1;
+ signore = 1;
break;
#endif /* INET */
@@ -327,7 +331,7 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
bcopy(&ipo->ipo_src, &sdst, sizeof(union sockaddr_union));
}
else
- ignore = 1;
+ signore = 1;
break;
#endif /* INET6 */
}
@@ -423,7 +427,8 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
{
case IPSP_IPSEC_REQUIRE:
/* Acquire SA through key management */
- if (ipsp_acquire_sa(ipo, &sdst, ignore ? NULL : &ssrc) != 0)
+ if (ipsp_acquire_sa(ipo, &sdst, signore ? NULL : &ssrc,
+ ddst) != 0)
{
*error = EACCES;
return NULL;
@@ -437,7 +442,8 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
case IPSP_IPSEC_ACQUIRE:
/* Acquire SA through key management */
- if (ipsp_acquire_sa(ipo, &sdst, ignore ? NULL : &ssrc) != 0)
+ if (ipsp_acquire_sa(ipo, &sdst, signore ? NULL : &ssrc,
+ ddst) != 0)
{
*error = EACCES;
return NULL;
@@ -514,7 +520,8 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
/* Acquire SA through key management */
if ((*error = ipsp_acquire_sa(ipo, &ssrc,
- ignore ? NULL : &sdst)) != 0)
+ dignore ? NULL : &sdst,
+ ddst)) != 0)
return NULL;
*error = -EINVAL;
@@ -568,7 +575,8 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
/* Acquire SA through key management */
if ((*error = ipsp_acquire_sa(ipo, &ssrc,
- ignore ? NULL : &sdst)) != 0)
+ dignore ? NULL : &sdst,
+ ddst)) != 0)
return NULL;
/* Just accept the packet */
@@ -804,9 +812,10 @@ ipsp_acquire_expirations(void *arg)
*/
int
ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw,
- union sockaddr_union *laddr)
+ union sockaddr_union *laddr, struct sockaddr_encap *ddst)
{
struct ipsec_acquire *ipa;
+ int i;
/*
* Check whether request has been made already.
@@ -827,6 +836,157 @@ ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw,
if (ipa == NULL)
return ENOMEM;
bcopy(gw, &ipa->ipa_addr, sizeof(union sockaddr_union));
+
+ ipa->ipa_info.sen_len = ipa->ipa_mask.sen_len = SENT_LEN;
+ ipa->ipa_info.sen_family = ipa->ipa_mask.sen_family = PF_KEY;
+ /* Just copy the right information */
+ switch (ipo->ipo_addr.sen_type)
+ {
+#ifdef INET
+ case SENT_IP4:
+ ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP4;
+ ipa->ipa_info.sen_direction = ipo->ipo_addr.sen_direction;
+ ipa->ipa_mask.sen_direction = ipo->ipo_mask.sen_direction;
+
+ if (ipo->ipo_mask.sen_ip_src.s_addr == INADDR_ANY ||
+ ipo->ipo_addr.sen_ip_src.s_addr == INADDR_ANY)
+ {
+ ipa->ipa_info.sen_ip_src = ddst->sen_ip_src;
+ ipa->ipa_mask.sen_ip_src.s_addr = INADDR_BROADCAST;
+ }
+ else
+ {
+ ipa->ipa_info.sen_ip_src = ipo->ipo_addr.sen_ip_src;
+ ipa->ipa_mask.sen_ip_src = ipo->ipo_mask.sen_ip_src;
+ }
+
+ if (ipo->ipo_mask.sen_ip_dst.s_addr == INADDR_ANY ||
+ ipo->ipo_addr.sen_ip_dst.s_addr == INADDR_ANY)
+ {
+ ipa->ipa_info.sen_ip_dst = ddst->sen_ip_dst;
+ ipa->ipa_mask.sen_ip_dst.s_addr = INADDR_BROADCAST;
+ }
+ else
+ {
+ ipa->ipa_info.sen_ip_dst = ipo->ipo_addr.sen_ip_dst;
+ ipa->ipa_mask.sen_ip_dst = ipo->ipo_mask.sen_ip_dst;
+ }
+
+ if (ipo->ipo_mask.sen_proto)
+ {
+ ipa->ipa_info.sen_proto = ipo->ipo_addr.sen_proto;
+ ipa->ipa_mask.sen_proto = ipo->ipo_mask.sen_proto;
+ }
+ else
+ {
+ ipa->ipa_info.sen_proto = ddst->sen_proto;
+ if (ddst->sen_proto)
+ ipa->ipa_mask.sen_proto = 0xff;
+ }
+
+ if (ipo->ipo_mask.sen_sport)
+ {
+ ipa->ipa_info.sen_sport = ipo->ipo_addr.sen_sport;
+ ipa->ipa_mask.sen_sport = ipo->ipo_mask.sen_sport;
+ }
+ else
+ {
+ ipa->ipa_info.sen_sport = ddst->sen_sport;
+ if (ddst->sen_sport)
+ ipa->ipa_mask.sen_sport = 0xffff;
+ }
+
+ if (ipo->ipo_mask.sen_dport)
+ {
+ ipa->ipa_info.sen_dport = ipo->ipo_addr.sen_dport;
+ ipa->ipa_mask.sen_dport = ipo->ipo_mask.sen_dport;
+ }
+ else
+ {
+ ipa->ipa_info.sen_dport = ddst->sen_dport;
+ if (ddst->sen_dport)
+ ipa->ipa_mask.sen_dport = 0xffff;
+ }
+
+ break;
+#endif /* INET */
+
+#ifdef INET6
+ case SENT_IP6:
+ ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP6;
+ ipa->ipa_info.sen_ip6_direction = ipo->ipo_addr.sen_ip6_direction;
+ ipa->ipa_mask.sen_ip6_direction = ipo->ipo_mask.sen_ip6_direction;
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_mask.sen_ip6_src) ||
+ IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_addr.sen_ip6_src))
+ {
+ ipa->ipa_info.sen_ip6_src = ddst->sen_ip6_src;
+ for (i = 0; i < 16; i++)
+ ipa->ipa_mask.sen_ip6_src.s6_addr8[i] = 0xff;
+ }
+ else
+ {
+ ipa->ipa_info.sen_ip6_src = ipo->ipo_addr.sen_ip6_src;
+ ipa->ipa_mask.sen_ip6_src = ipo->ipo_mask.sen_ip6_src;
+ }
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_mask.sen_ip6_dst) ||
+ IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_addr.sen_ip6_dst))
+ {
+ ipa->ipa_info.sen_ip6_dst = ddst->sen_ip6_dst;
+ for (i = 0; i < 16; i++)
+ ipa->ipa_mask.sen_ip6_dst.s6_addr8[i] = 0xff;
+ }
+ else
+ {
+ ipa->ipa_info.sen_ip6_dst = ipo->ipo_addr.sen_ip6_dst;
+ ipa->ipa_mask.sen_ip6_dst = ipo->ipo_mask.sen_ip6_dst;
+ }
+
+ if (ipo->ipo_mask.sen_ip6_proto)
+ {
+ ipa->ipa_info.sen_ip6_proto = ipo->ipo_addr.sen_ip6_proto;
+ ipa->ipa_mask.sen_ip6_proto = ipo->ipo_mask.sen_ip6_proto;
+ }
+ else
+ {
+ ipa->ipa_info.sen_ip6_proto = ddst->sen_ip6_proto;
+ if (ddst->sen_ip6_proto)
+ ipa->ipa_mask.sen_ip6_proto = 0xff;
+ }
+
+ if (ipo->ipo_mask.sen_ip6_sport)
+ {
+ ipa->ipa_info.sen_ip6_sport = ipo->ipo_addr.sen_ip6_sport;
+ ipa->ipa_mask.sen_ip6_sport = ipo->ipo_mask.sen_ip6_sport;
+ }
+ else
+ {
+ ipa->ipa_info.sen_ip6_sport = ddst->sen_ip6_sport;
+ if (ddst->sen_ip6_sport)
+ ipa->ipa_mask.sen_ip6_sport = 0xffff;
+ }
+
+ if (ipo->ipo_mask.sen_ip6_dport)
+ {
+ ipa->ipa_info.sen_ip6_dport = ipo->ipo_addr.sen_ip6_dport;
+ ipa->ipa_mask.sen_ip6_dport = ipo->ipo_mask.sen_ip6_dport;
+ }
+ else
+ {
+ ipa->ipa_info.sen_ip6_dport = ddst->sen_ip6_dport;
+ if (ddst->sen_ip6_dport)
+ ipa->ipa_mask.sen_ip6_dport = 0xffff;
+ }
+
+ break;
+#endif /* INET6 */
+
+ default:
+ FREE(ipa, M_TDB);
+ return 0;
+ }
+
ipa->ipa_expire = time.tv_sec + ipsec_expire_acquire;
TAILQ_INSERT_TAIL(&ipsec_acquire_head, ipa, ipa_next);
@@ -835,5 +995,19 @@ ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw,
hz * (ipa->ipa_expire - time.tv_sec));
/* PF_KEYv2 notification message */
- return pfkeyv2_acquire(ipo, gw, laddr);
+ return pfkeyv2_acquire(ipo, gw, laddr, &ipa->ipa_seq, ddst);
+}
+
+struct ipsec_acquire *
+ipsec_get_acquire(u_int32_t seq)
+{
+ struct ipsec_acquire *ipa;
+
+ for (ipa = TAILQ_FIRST(&ipsec_acquire_head);
+ ipa;
+ ipa = TAILQ_NEXT(ipa, ipa_next))
+ if (ipa->ipa_seq == seq)
+ return ipa;
+
+ return NULL;
}