diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2000-10-14 06:23:53 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2000-10-14 06:23:53 +0000 |
commit | 8daaea286dc3be20a9c7897fe10b935d97c6863a (patch) | |
tree | b3c392d2ca74b2c8c3d85325496c132297609de0 | |
parent | d6277e1dfdb29065da02107dc01cdcee0968b5d8 (diff) |
ASKPOLICY message; used by key management to inquire about policy
triggering an ACQUIRE.
-rw-r--r-- | sys/net/pfkeyv2.c | 196 | ||||
-rw-r--r-- | sys/net/pfkeyv2.h | 17 | ||||
-rw-r--r-- | sys/net/pfkeyv2_parsemessage.c | 17 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 12 | ||||
-rw-r--r-- | sys/netinet/ip_spd.c | 194 |
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; } |