summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>2001-06-07 16:19:48 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>2001-06-07 16:19:48 +0000
commit92e01a4632d76bd6b6ac64e57b66cc610d8531c3 (patch)
tree7b712da950290ccbffb06e68a3371c6895f20885 /sys/netinet
parent47643908694ed46da22982d25c33cd6aa716c613 (diff)
Simplify SPD logic (and correct some input cases).
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_ipsp.c78
-rw-r--r--sys/netinet/ip_ipsp.h5
-rw-r--r--sys/netinet/ip_spd.c473
3 files changed, 164 insertions, 392 deletions
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index 87018272ac8..14aa50126b2 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.128 2001/06/05 11:31:31 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.129 2001/06/07 16:19:47 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -315,11 +315,7 @@ gettdbbyaddr(union sockaddr_union *dst, struct ipsec_policy *ipo,
{
if (ipo->ipo_srcid != NULL)
{
- if ((tdbp->tdb_srcid->ref_type !=
- ipo->ipo_srcid->ref_type) ||
- (tdbp->tdb_srcid->ref_len != ipo->ipo_srcid->ref_len) ||
- (bcmp(tdbp->tdb_srcid + 1, ipo->ipo_srcid + 1,
- ipo->ipo_srcid->ref_len)))
+ if (!ipsp_ref_match(ipo->ipo_srcid, tdbp->tdb_srcid))
continue;
}
@@ -333,11 +329,7 @@ gettdbbyaddr(union sockaddr_union *dst, struct ipsec_policy *ipo,
{
if (ipo->ipo_dstid != NULL)
{
- if ((tdbp->tdb_dstid->ref_type !=
- ipo->ipo_dstid->ref_type) ||
- (tdbp->tdb_dstid->ref_len != ipo->ipo_dstid->ref_len) ||
- (bcmp(tdbp->tdb_dstid + 1, ipo->ipo_dstid + 1,
- ipo->ipo_dstid->ref_len)))
+ if (!ipsp_ref_match(ipo->ipo_dstid, tdbp->tdb_dstid))
continue;
}
@@ -352,12 +344,8 @@ gettdbbyaddr(union sockaddr_union *dst, struct ipsec_policy *ipo,
{
if (ipo->ipo_local_cred != NULL)
{
- if ((tdbp->tdb_local_cred->ref_type !=
- ipo->ipo_local_cred->ref_type) ||
- (tdbp->tdb_local_cred->ref_len !=
- ipo->ipo_local_cred->ref_len) ||
- (bcmp(tdbp->tdb_local_cred + 1, ipo->ipo_local_cred + 1,
- ipo->ipo_local_cred->ref_len)))
+ if (!ipsp_ref_match(ipo->ipo_local_cred,
+ tdbp->tdb_local_cred))
continue;
}
}
@@ -404,63 +392,32 @@ gettdbbysrc(union sockaddr_union *src, struct ipsec_policy *ipo,
*/
if (tdbp->tdb_srcid != NULL)
{
- if (ipo->ipo_srcid != NULL)
+ if (ipo->ipo_dstid != NULL)
{
- if ((tdbp->tdb_srcid->ref_type !=
- ipo->ipo_srcid->ref_type) ||
- (tdbp->tdb_srcid->ref_len != ipo->ipo_srcid->ref_len) ||
- (bcmp(tdbp->tdb_srcid + 1, ipo->ipo_srcid + 1,
- ipo->ipo_srcid->ref_len)))
+ if (!ipsp_ref_match(ipo->ipo_dstid, tdbp->tdb_srcid))
continue;
}
/* Otherwise, this is fine */
}
else
- if (ipo->ipo_srcid != NULL)
+ if (ipo->ipo_dstid != NULL)
continue;
if (tdbp->tdb_dstid != NULL)
{
- if (ipo->ipo_dstid != NULL)
+ if (ipo->ipo_srcid != NULL)
{
- if ((tdbp->tdb_dstid->ref_type !=
- ipo->ipo_dstid->ref_type) ||
- (tdbp->tdb_dstid->ref_len != ipo->ipo_dstid->ref_len) ||
- (bcmp(tdbp->tdb_dstid + 1, ipo->ipo_dstid + 1,
- ipo->ipo_dstid->ref_len)))
+ if (!ipsp_ref_match(ipo->ipo_srcid, tdbp->tdb_dstid))
continue;
}
/* Otherwise, this is fine */
}
else
- if (ipo->ipo_dstid != NULL)
+ if (ipo->ipo_srcid != NULL)
continue;
- /* Check for credential matches */
- if (tdbp->tdb_local_cred != NULL)
- {
- if (ipo->ipo_local_cred != NULL)
- {
- if ((tdbp->tdb_local_cred->ref_type !=
- ipo->ipo_local_cred->ref_type) ||
- (tdbp->tdb_local_cred->ref_len !=
- ipo->ipo_local_cred->ref_len) ||
- (bcmp(tdbp->tdb_local_cred, ipo->ipo_local_cred + 1,
- ipo->ipo_local_cred->ref_len)))
- continue;
- }
- }
- else
- if (ipo->ipo_local_cred != NULL)
- continue; /* If no credential was used in the TDB, try
- * to establish a new SA with the given
- * credential, since some type of access control
- * may be done on the other side based on that
- * credential.
- */
-
/* XXX Check for filter matches */
break;
}
@@ -1533,3 +1490,16 @@ ipsp_parse_headers(struct mbuf *m, int off, u_int8_t proto)
}
}
}
+
+/* Return true if the two structures match. */
+int
+ipsp_ref_match(struct ipsec_ref *ref1, struct ipsec_ref *ref2)
+{
+ if (ref1->ref_type != ref2->ref_type ||
+ ref1->ref_len != ref2->ref_len ||
+ bcmp(ref1 + 1, ref2 + 1, ref1->ref_len))
+ return 0;
+
+ return 1;
+}
+
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index 4a284f628f0..988fcdb4244 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.101 2001/06/01 07:56:46 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.102 2001/06/07 16:19:47 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -601,8 +601,6 @@ extern int ipsp_acquire_sa(struct ipsec_policy *, union sockaddr_union *,
extern struct ipsec_policy *ipsec_add_policy(struct sockaddr_encap *,
struct sockaddr_encap *,
union sockaddr_union *, int, int);
-extern int ipsp_match_policy(struct tdb *, struct ipsec_policy *,
- struct mbuf *, int);
extern int ipsec_delete_policy(struct ipsec_policy *);
extern void ipsp_acquire_expirations(void *);
extern struct ipsec_acquire *ipsp_pending_acquire(union sockaddr_union *);
@@ -614,5 +612,6 @@ extern void ipsp_reffree(struct ipsec_ref *);
extern void ipsp_skipcrypto_unmark(struct tdb_ident *);
extern void ipsp_skipcrypto_mark(struct tdb_ident *);
extern struct m_tag *ipsp_parse_headers(struct mbuf *, int, u_int8_t);
+extern int ipsp_ref_match(struct ipsec_ref *, struct ipsec_ref *);
#endif /* _KERNEL */
#endif /* _NETINET_IPSP_H_ */
diff --git a/sys/netinet/ip_spd.c b/sys/netinet/ip_spd.c
index 09bd594d0bb..71e8bd72b41 100644
--- a/sys/netinet/ip_spd.c
+++ b/sys/netinet/ip_spd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_spd.c,v 1.21 2001/05/30 12:22:15 angelos Exp $ */
+/* $OpenBSD: ip_spd.c,v 1.22 2001/06/07 16:19:47 angelos Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -232,7 +232,6 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
(((struct sockaddr_encap *) re->re_rt->rt_gateway)->sen_type !=
SENT_IPSP))
{
- DPRINTF(("ipsp_spd_lookup(): no gw, or gw data not IPSP\n"));
RTFREE(re->re_rt);
*error = EHOSTUNREACH;
return NULL;
@@ -242,7 +241,6 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
RTFREE(re->re_rt);
if (ipo == NULL)
{
- DPRINTF(("ipsp_spd_lookup(): no policy present\n"));
*error = EHOSTUNREACH;
return NULL;
}
@@ -269,72 +267,41 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
return NULL;
}
- /*
- * Check for non-specific destination in the policy. If a specific
- * destination was specified, use that -- otherwise, use the relevant
- * information from the packet.
- */
+ /* Check for non-specific destination in the policy. */
switch (ipo->ipo_dst.sa.sa_family)
{
#ifdef INET
case AF_INET:
- if ((ipo->ipo_dst.sin.sin_addr.s_addr != INADDR_ANY) &&
- (ipo->ipo_dst.sin.sin_addr.s_addr != INADDR_BROADCAST))
- {
- if (direction == IPSP_DIRECTION_OUT)
- bcopy(&ipo->ipo_dst, &sdst, sizeof(union sockaddr_union));
- else
- bcopy(&ipo->ipo_dst, &ssrc, sizeof(union sockaddr_union));
- }
- else
+ if ((ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY) ||
+ (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST))
dignore = 1;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- if ((!IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr)) &&
- (!bcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
+ if ((IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr)) ||
+ (bcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
sizeof(in6mask128))))
- {
- if (direction == IPSP_DIRECTION_OUT)
- bcopy(&ipo->ipo_dst, &sdst, sizeof(union sockaddr_union));
- else
- bcopy(&ipo->ipo_dst, &ssrc, sizeof(union sockaddr_union));
- }
- else
dignore = 1;
break;
#endif /* INET6 */
}
+ /* Likewise for source. */
switch (ipo->ipo_src.sa.sa_family)
{
#ifdef INET
case AF_INET:
- if (ipo->ipo_src.sin.sin_addr.s_addr != INADDR_ANY)
- {
- if (direction == IPSP_DIRECTION_OUT)
- bcopy(&ipo->ipo_src, &ssrc, sizeof(union sockaddr_union));
- else
- bcopy(&ipo->ipo_src, &sdst, sizeof(union sockaddr_union));
- }
- else
- signore = 1;
+ if (ipo->ipo_src.sin.sin_addr.s_addr == INADDR_ANY)
+ signore = 1;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- if (!IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_src.sin6.sin6_addr))
- {
- if (direction == IPSP_DIRECTION_OUT)
- bcopy(&ipo->ipo_src, &ssrc, sizeof(union sockaddr_union));
- else
- bcopy(&ipo->ipo_src, &sdst, sizeof(union sockaddr_union));
- }
- else
- signore = 1;
+ if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_src.sin6.sin6_addr))
+ signore = 1;
break;
#endif /* INET6 */
}
@@ -359,57 +326,54 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
(inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS))
{
/* Direct match */
- if (bcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len) == 0)
+ if (!bcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len) || dignore)
{
*error = 0;
return NULL;
}
-
- /* Same-host */
- switch (ipo->ipo_dst.sa.sa_family)
- {
-#ifdef INET
- case AF_INET:
- if ((ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY) ||
- (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST))
- {
- *error = 0;
- return NULL;
- }
- break;
-#endif /* INET */
-
-#ifdef INET6
- case AF_INET6:
- if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr) ||
- !bcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
- sizeof(in6mask128)))
- {
- *error = 0;
- return NULL;
- }
- break;
-#endif /* INET6 */
- }
}
/* Check that the cached TDB (if present), is appropriate */
if (ipo->ipo_tdb)
{
- if (bcmp(&sdst, &ipo->ipo_tdb->tdb_dst, sdst.sa.sa_len) ||
- (ipo->ipo_last_searched <= ipsec_last_added))
+ if ((ipo->ipo_last_searched <= ipsec_last_added) ||
+ (ipo->ipo_sproto != ipo->ipo_tdb->tdb_sproto) ||
+ bcmp(dignore ? &sdst : &ipo->ipo_dst, &ipo->ipo_tdb->tdb_dst,
+ ipo->ipo_tdb->tdb_dst.sa.sa_len))
+ goto nomatchout;
+
+ /* Match source ID */
+ if (ipo->ipo_srcid)
{
- TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
- ipo_tdb_next);
- ipo->ipo_tdb = NULL;
- ipo->ipo_last_searched = 0;
+ if (ipo->ipo_tdb->tdb_srcid == NULL ||
+ !ipsp_ref_match(ipo->ipo_srcid, ipo->ipo_tdb->tdb_srcid))
+ goto nomatchout;
+ }
- /* Fall through to acquisition of TDB */
+ /* Match destination ID */
+ if (ipo->ipo_dstid)
+ {
+ if (ipo->ipo_tdb->tdb_dstid == NULL ||
+ !ipsp_ref_match(ipo->ipo_dstid, ipo->ipo_tdb->tdb_dstid))
+ goto nomatchout;
}
- else
+
+ /* Match local credentials used */
+ if (ipo->ipo_local_cred)
{
- return ipo->ipo_tdb; /* Cached entry is good, we're done */
+ if (ipo->ipo_tdb->tdb_local_cred == NULL ||
+ !ipsp_ref_match(ipo->ipo_local_cred,
+ ipo->ipo_tdb->tdb_local_cred))
+ goto nomatchout;
}
+
+ return ipo->ipo_tdb; /* Cached entry is good, we're done */
+
+ nomatchout:
+ /* Cached TDB was not good */
+ TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next);
+ ipo->ipo_tdb = NULL;
+ ipo->ipo_last_searched = 0;
}
/*
@@ -421,41 +385,13 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
* destinations exist but are not used, possibly leading to an
* explosion in the number of acquired SAs).
*/
- if (
-#ifdef INET
- ((ipo->ipo_dst.sa.sa_family == AF_INET) &&
- (ipo->ipo_dst.sin.sin_addr.s_addr != INADDR_ANY) &&
- (ipo->ipo_dst.sin.sin_addr.s_addr != INADDR_BROADCAST)) ||
-#endif /* INET */
-#ifdef INET6
- ((ipo->ipo_dst.sa.sa_family == AF_INET6) &&
- !IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr) &&
- bcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
- sizeof(in6mask128))) ||
-#endif /* INET6 */
- 0)
- {
- if (ipo->ipo_last_searched <= ipsec_last_added)
- {
- ipo->ipo_last_searched = time.tv_sec; /* "touch" the entry */
-
- /* Find an appropriate SA from among the existing SAs */
- ipo->ipo_tdb = gettdbbyaddr(&sdst, ipo, m, af);
- if (ipo->ipo_tdb)
- {
- TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head, ipo,
- ipo_tdb_next);
- *error = 0;
- return ipo->ipo_tdb;
- }
- }
- }
- else
+ if (ipo->ipo_last_searched <= ipsec_last_added)
{
ipo->ipo_last_searched = time.tv_sec; /* "touch" the entry */
/* Find an appropriate SA from among the existing SAs */
- ipo->ipo_tdb = gettdbbyaddr(&sdst, ipo, m, af);
+ ipo->ipo_tdb = gettdbbyaddr(dignore ? &sdst : &ipo->ipo_dst,
+ ipo, m, af);
if (ipo->ipo_tdb)
{
TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head, ipo,
@@ -470,7 +406,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, signore ? NULL : &ssrc,
+ if (ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst,
+ signore ? NULL : &ipo->ipo_src,
ddst, m) != 0)
{
*error = EACCES;
@@ -478,14 +415,14 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
}
/* Fall through */
-
case IPSP_IPSEC_DONTACQ:
*error = -EINVAL; /* Silently drop packet */
return NULL;
case IPSP_IPSEC_ACQUIRE:
/* Acquire SA through key management */
- if (ipsp_acquire_sa(ipo, &sdst, signore ? NULL : &ssrc,
+ if (ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst,
+ signore ? NULL : &ipo->ipo_src,
ddst, NULL) != 0)
{
*error = EACCES;
@@ -493,7 +430,6 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
}
/* Fall through */
-
case IPSP_IPSEC_USE:
*error = 0; /* Let packet through */
return NULL;
@@ -501,129 +437,124 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
}
else /* IPSP_DIRECTION_IN */
{
- /* Check the cached entry */
- if ((ipo->ipo_tdb) &&
- (((ipo->ipo_tdb->tdb_src.sa.sa_family != 0) &&
- bcmp(&ssrc, &ipo->ipo_tdb->tdb_src, ssrc.sa.sa_len)) ||
- (ipo->ipo_last_searched <= ipsec_last_added)))
+ if (tdbp != NULL)
{
+ if (ipo->ipo_tdb == tdbp)
+ {
+ *error = 0; /* Accept packet */
+ return NULL;
+ }
+
+ if (bcmp(dignore ? &ssrc : &ipo->ipo_dst, &tdbp->tdb_src,
+ tdbp->tdb_src.sa.sa_len) ||
+ (ipo->ipo_sproto != tdbp->tdb_sproto))
+ goto nomatchin;
+
+ /* Match source ID */
+ if (ipo->ipo_srcid)
+ {
+ if (tdbp->tdb_dstid == NULL ||
+ !ipsp_ref_match(ipo->ipo_srcid, tdbp->tdb_dstid))
+ goto nomatchin;
+ }
+
+ /* Match destination ID */
+ if (ipo->ipo_dstid)
+ {
+ if (tdbp->tdb_srcid == NULL ||
+ !ipsp_ref_match(ipo->ipo_dstid, tdbp->tdb_srcid))
+ goto nomatchin;
+ }
+
+ /* Add it to the cache */
+ if (ipo->ipo_tdb)
+ TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next);
+ ipo->ipo_tdb = tdbp;
+ TAILQ_INSERT_TAIL(&tdbp->tdb_policy_head, ipo, ipo_tdb_next);
+ *error = 0;
+ return NULL;
+
+ nomatchin: /* Nothing needed here, falling through */
+ }
+
+ /* Check whether cached entry applies */
+ if (ipo->ipo_tdb)
+ {
+ /*
+ * We only need to check that the correct security protocol and
+ * security gateway are set; credentials/IDs will be the same,
+ * since the cached entry is linked on this policy.
+ */
+ if (ipo->ipo_sproto == ipo->ipo_tdb->tdb_sproto &&
+ !bcmp(&ipo->ipo_tdb->tdb_src, dignore ? &ssrc : &ipo->ipo_dst,
+ ipo->ipo_tdb->tdb_src.sa.sa_len))
+ goto skipinputsearch;
+
+ /* Not applicable, unlink */
TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next);
ipo->ipo_tdb = NULL;
- ipo->ipo_last_searched = 0;
}
- switch (ipo->ipo_type)
+ /* Find whether there exists an appropriate SA */
+ if (ipo->ipo_last_searched <= ipsec_last_added)
{
- case IPSP_IPSEC_DONTACQ:
- /* Does protection match stated policy ? */
- if (tdbp && ipsp_match_policy(tdbp, ipo, m, af))
- {
- /* Accept packet */
- *error = 0;
- return NULL;
- }
+ ipo->ipo_last_searched = time.tv_sec; /* "touch" */
- /* Silently drop packet */
- *error = EHOSTUNREACH;
- return NULL;
+ ipo->ipo_tdb = gettdbbysrc(dignore ? &ssrc : &ipo->ipo_dst,
+ ipo, m, af);
+ if (ipo->ipo_tdb)
+ TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head, ipo,
+ ipo_tdb_next);
+ }
+ skipinputsearch:
+ switch (ipo->ipo_type)
+ {
case IPSP_IPSEC_REQUIRE:
- if (tdbp && ipsp_match_policy(tdbp, ipo, m, af))
- {
- /* Accept packet */
- *error = 0;
- return NULL;
- }
-
- /* If we have a cached entry, just discard the packet */
+ /* If an appropriate SA exists, don't acquire another */
if (ipo->ipo_tdb)
{
- *error = EHOSTUNREACH;
+ *error = -EINVAL;
return NULL;
}
- /*
- * Find whether there exists an appropriate SA. If so, drop
- * the packet. Otherwise, try to acquire one (from below).
- *
- * If no SA has been added since the last time we did a lookup,
- * there's no point searching for one.
- */
- if (ipo->ipo_last_searched <= ipsec_last_added)
- {
- ipo->ipo_last_searched = time.tv_sec; /* "touch" */
-
- if ((ipo->ipo_tdb = gettdbbysrc(&ssrc, ipo,
- m, af)) != NULL)
- {
- TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head, ipo,
- ipo_tdb_next);
- *error = EHOSTUNREACH;
- return NULL;
- }
- }
-
/* Acquire SA through key management */
- if ((*error = ipsp_acquire_sa(ipo, &ssrc,
- dignore ? NULL : &sdst,
+ if ((*error = ipsp_acquire_sa(ipo,
+ dignore ? &ssrc : &ipo->ipo_dst,
+ signore ? NULL : &ipo->ipo_src,
ddst, m)) != 0)
return NULL;
+ /* Fall through */
+ case IPSP_IPSEC_DONTACQ:
+ /* Drop packet */
*error = -EINVAL;
return NULL;
- case IPSP_IPSEC_USE:
- /*
- * It doesn't matter what protection it had (if any),
- * just accept it -- equivalent to PERMIT for input.
- * This means we can't say that we want in incoming
- * packet to be unprotected -- at least not directly;
- * we can always have a DENY policy for ESP/AH packets.
- */
- *error = 0;
- return NULL;
-
case IPSP_IPSEC_ACQUIRE:
- /*
- * We don't check for policy match, since we would
- * accept clear-text packets as well.
- */
-
- /* If we have a cached entry, just accept the packet */
+ /* If an appropriate SA exists, don't acquire another */
if (ipo->ipo_tdb)
{
*error = 0;
return NULL;
}
- /*
- * Find whether there exists an appropriate SA. If so, accept
- * the packet. Otherwise, try to acquire one (from below).
- *
- * If no SA has been added since the last time we did a lookup,
- * there's no point searching for one.
- */
- if (ipo->ipo_last_searched <= ipsec_last_added)
- {
- ipo->ipo_last_searched = time.tv_sec; /* "touch" */
-
- if ((ipo->ipo_tdb = gettdbbysrc(&ssrc, ipo,
- m, af)) != NULL)
- {
- TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head, ipo,
- ipo_tdb_next);
- *error = 0;
- return NULL;
- }
- }
-
/* Acquire SA through key management */
- if ((*error = ipsp_acquire_sa(ipo, &ssrc,
- dignore ? NULL : &sdst,
+ if ((*error = ipsp_acquire_sa(ipo,
+ dignore ? &ssrc : &ipo->ipo_dst,
+ signore ? NULL : &ipo->ipo_src,
ddst, NULL)) != 0)
return NULL;
- /* Just accept the packet */
+ /* Fall through */
+ case IPSP_IPSEC_USE:
+ /*
+ * It doesn't matter what protection it had (if any),
+ * just accept it -- equivalent to PERMIT for input.
+ * This means we can't say that we want in incoming
+ * packet to be unprotected -- at least not directly;
+ * we can always have a DENY policy for ESP/AH packets.
+ */
*error = 0;
return NULL;
}
@@ -634,134 +565,6 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
return NULL;
}
-
-/*
- * See if a specific SA satisfies stated policy. Return 0 if false, 1 (or
- * non-zero) otherwise.
- */
-int
-ipsp_match_policy(struct tdb *tdb, struct ipsec_policy *ipo,
- struct mbuf *m, int af)
-{
- union sockaddr_union peer;
- int pflag = 0;
-
- switch (ipo->ipo_dst.sa.sa_family)
- {
-#ifdef INET
- case AF_INET:
- if (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY)
- pflag = 1;
- else
- if (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST)
- pflag = 2;
- break;
-#endif /* INET */
-
-#ifdef INET6
- case AF_INET6:
- if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr))
- pflag = 1;
- else
- if (!bcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
- sizeof(in6mask128)))
- pflag = 2;
- break;
-#endif /* INET6 */
-
- case 0: /* Just in case */
- pflag = 1;
- break;
-
- default:
- return 0; /* Unknown/unsupported network protocol */
- }
-
- if (pflag == 0)
- {
- bcopy(&ipo->ipo_dst, &peer, sizeof(union sockaddr_union));
- }
- else
- if (pflag == 1)
- {
- bzero(&peer, sizeof(union sockaddr_union));
-
- /* Need to copy the source address from the packet */
- switch (af)
- {
-#ifdef INET
- case AF_INET:
- peer.sin.sin_family = AF_INET;
- peer.sin.sin_len = sizeof(struct sockaddr_in);
- m_copydata(m, offsetof(struct ip, ip_src),
- sizeof(struct in_addr),
- (caddr_t) &peer.sin.sin_addr);
- break;
-#endif /* INET */
-
-#ifdef INET6
- case AF_INET6:
- peer.sin6.sin6_family = AF_INET6;
- peer.sin6.sin6_len = sizeof(struct sockaddr_in6);
- m_copydata(m, offsetof(struct ip6_hdr, ip6_src),
- sizeof(struct in6_addr),
- (caddr_t) &peer.sin6.sin6_addr);
- break;
-#endif /* INET6 */
-
- default:
- return 0; /* Unknown/unsupported network protocol */
- }
- }
-
- /*
- * Does the packet use the right security protocol and is coming from
- * the right peer ?
- */
- if (tdb->tdb_sproto == ipo->ipo_sproto)
- {
- /*
- * We accept any peer that has a valid SA with us -- this means
- * we depend on the higher-level (key mgmt.) protocol to enforce
- * policy.
- */
- if (pflag == 2)
- return 1;
-
- if (bcmp(&tdb->tdb_src, &peer, tdb->tdb_src.sa.sa_len))
- {
- switch (tdb->tdb_src.sa.sa_family)
- {
-#ifdef INET
- case AF_INET:
- if (tdb->tdb_src.sin.sin_addr.s_addr == INADDR_ANY)
- return 1;
- else
- return 0;
-#endif /* INET */
-
-#ifdef INET6
- case AF_INET6:
- if (IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_src.sin6.sin6_addr))
- return 1;
- else
- return 0;
-#endif /* INET6 */
-
- case 0:
- return 1;
-
- default:
- return 0;
- }
- }
- else
- return 1;
- }
-
- return 0;
-}
-
/*
* Delete a policy from the SPD.
*/