Convert IP_IPSECFLOWINFO to use tdb flow id instead of an SPI.
Tested with npppd and Windows NAT-T clients. OK?
---
sys/netinet/ip_spd.c | 49 +++++++++++++++++++++++++++---------------------
sys/netinet/udp_usrreq.c | 2 +-
2 files changed, 29 insertions(+), 22 deletions(-)
diff --git sys/netinet/ip_spd.c sys/netinet/ip_spd.c
index e4b858c..e451ad0 100644
--- sys/netinet/ip_spd.c
+++ sys/netinet/ip_spd.c
@@ -78,22 +78,21 @@ int ipsec_acquire_pool_initialized = 0;
* returned.
*/
struct tdb *
ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
struct tdb *tdbp, struct inpcb *inp, u_int32_t ipsecflowinfo)
{
struct rtentry *rt;
union sockaddr_union sdst, ssrc;
struct sockaddr_encap *ddst, dst;
struct ipsec_policy *ipo;
- struct ipsec_ref *dstid = NULL, *srcid = NULL;
- struct tdb *tdbin = NULL;
+ struct tdb *tdbpp = NULL;
int signore = 0, dignore = 0;
u_int rdomain = rtable_l2(m->m_pkthdr.ph_rtableid);
/*
* If there are no flows in place, there's no point
* continuing with the SPD lookup.
*/
if (!ipsec_in_use && inp == NULL) {
*error = 0;
return NULL;
@@ -337,84 +336,92 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int
*error, int direction,
IPSEC_LEVEL_BYPASS) &&
(inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
/* Direct match. */
if (dignore ||
!memcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len)) {
*error = 0;
return NULL;
}
}
- /*
- * Fetch the incoming TDB based on the SPI passed
- * in ipsecflow and use it's dstid when looking
- * up the outgoing TDB.
- */
- if (ipsecflowinfo &&
- (tdbin = gettdb(rdomain, ipsecflowinfo, &ssrc,
- ipo->ipo_sproto)) != NULL) {
- srcid = tdbin->tdb_dstid;
- dstid = tdbin->tdb_srcid;
- }
+ /* Fetch the TDB based on the flow ID in ipsecflow. */
+ if (ipsecflowinfo)
+ tdbpp = gettdbbyflow(rdomain, ipsecflowinfo,
+ dignore ? &sdst : &ipo->ipo_dst, ipo->ipo_sproto);
/* Check that the cached TDB (if present), is appropriate. */
if (ipo->ipo_tdb) {
if ((ipo->ipo_last_searched <= ipsec_last_added) ||
(ipo->ipo_sproto != ipo->ipo_tdb->tdb_sproto) ||
memcmp(dignore ? &sdst : &ipo->ipo_dst,
&ipo->ipo_tdb->tdb_dst,
ipo->ipo_tdb->tdb_dst.sa.sa_len))
goto nomatchout;
- if (!ipsp_aux_match(ipo->ipo_tdb,
- srcid ? srcid : ipo->ipo_srcid,
- dstid ? dstid : ipo->ipo_dstid,
+ if (tdbpp && ipo->ipo_tdb != tdbpp)
+ goto nomatchout;
+ else if (!ipsp_aux_match(ipo->ipo_tdb,
+ ipo->ipo_srcid, ipo->ipo_dstid,
ipo->ipo_local_cred, NULL,
&ipo->ipo_addr, &ipo->ipo_mask))
goto nomatchout;
/* Cached entry is good. */
*error = 0;
return ipsp_spd_inp(m, af, hlen, error, direction,
tdbp, inp, ipo);
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;
}
+ /* Use the SA we have found via the ipsecflowinfo */
+ if (tdbpp) {
+ if (ipo->ipo_last_searched <= ipsec_last_added) {
+ /* "Touch" the entry. */
+ if (dignore == 0)
+ ipo->ipo_last_searched = time_second;
+ }
+
+ ipo->ipo_tdb = tdbpp;
+ TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head, ipo,
+ ipo_tdb_next);
+ *error = 0;
+ return ipsp_spd_inp(m, af, hlen, error, direction, tdbp,
+ inp, ipo);
+ }
+
/*
* If no SA has been added since the last time we did a
* lookup, there's no point searching for one. However, if the
* destination gateway is left unspecified (or is all-1's),
* always lookup since this is a generic-match rule
* (otherwise, we can have situations where SAs to some
* destinations exist but are not used, possibly leading to an
* explosion in the number of acquired SAs).
*/
if (ipo->ipo_last_searched <= ipsec_last_added) {
/* "Touch" the entry. */
if (dignore == 0)
ipo->ipo_last_searched = time_second;
/* Find an appropriate SA from the existing ones. */
ipo->ipo_tdb =
gettdbbydst(rdomain,
dignore ? &sdst : &ipo->ipo_dst,
- ipo->ipo_sproto,
- srcid ? srcid : ipo->ipo_srcid,
- dstid ? dstid : ipo->ipo_dstid,
- ipo->ipo_local_cred, &ipo->ipo_addr,
- &ipo->ipo_mask);
+ ipo->ipo_sproto, ipo->ipo_srcid,
+ ipo->ipo_dstid, ipo->ipo_local_cred,
+ &ipo->ipo_addr, &ipo->ipo_mask);
if (ipo->ipo_tdb) {
TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
ipo, ipo_tdb_next);
*error = 0;
return ipsp_spd_inp(m, af, hlen, error,
direction, tdbp, inp, ipo);
}
}
/* So, we don't have an SA -- just a policy. */
diff --git sys/netinet/udp_usrreq.c sys/netinet/udp_usrreq.c
index a9b0f6b..810d151 100644
--- sys/netinet/udp_usrreq.c
+++ sys/netinet/udp_usrreq.c
@@ -645,21 +645,21 @@ udp_input(struct mbuf *m, ...)
tdb->tdb_remote_auth->ref_count++;
}
} else { /* Just reset */
TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in, inp,
inp_tdb_in_next);
inp->inp_tdb_in = NULL;
}
}
/* create ipsec options while we know that tdb cannot be modified */
if (tdb)
- ipsecflowinfo = tdb->tdb_spi;
+ ipsecflowinfo = tdb->tdb_flow;
#endif /*IPSEC */
opts = NULL;
#ifdef INET6
if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS ||
inp->inp_socket->so_options & SO_TIMESTAMP))
ip6_savecontrol(inp, m, &opts);
#endif /* INET6 */
if (ip && (inp->inp_flags & INP_CONTROLOPTS ||
--
2.3.4