Subject: Re: IPSEC in GENERIC
To: Jason Thorpe <thorpej@shagadelic.org>
From: Christos Zoulas <christos@zoulas.com>
List: tech-kern
Date: 02/21/2006 21:08:43
On Feb 21, 3:50pm, thorpej@shagadelic.org (Jason Thorpe) wrote:
-- Subject: Re: IPSEC in GENERIC
Here's a patch to provide a fast path for both IPSEC and FAST_IPSEC.
The IPSEC code works fine. The FAST_IPSEC prints errors, but the code
has been rotting; i.e. it does not even compile with other IPSEC options
such as IPSEC_NAT_T.
christos
Index: netinet/in_pcb.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/in_pcb.c,v
retrieving revision 1.101
diff -u -r1.101 in_pcb.c
--- netinet/in_pcb.c 15 Nov 2005 18:39:46 -0000 1.101
+++ netinet/in_pcb.c 22 Feb 2006 02:05:56 -0000
@@ -193,10 +193,12 @@
inp->inp_socket = so;
inp->inp_errormtu = -1;
#if defined(IPSEC) || defined(FAST_IPSEC)
- error = ipsec_init_pcbpolicy(so, &inp->inp_sp);
- if (error != 0) {
- pool_put(&inpcb_pool, inp);
- return error;
+ if (ipsec_havespd && inp->inp_sp) {
+ error = ipsec_init_pcbpolicy(so, &inp->inp_sp);
+ if (error != 0) {
+ pool_put(&inpcb_pool, inp);
+ return error;
+ }
}
#endif
so->so_pcb = inp;
@@ -443,7 +445,8 @@
inp->inp_fport = sin->sin_port;
in_pcbstate(inp, INP_CONNECTED);
#if defined(IPSEC) || defined(FAST_IPSEC)
- if (inp->inp_socket->so_type == SOCK_STREAM)
+ if (ipsec_havespd && inp->inp_sp &&
+ inp->inp_socket->so_type == SOCK_STREAM)
ipsec_pcbconn(inp->inp_sp);
#endif
return (0);
@@ -461,7 +464,8 @@
inp->inp_fport = 0;
in_pcbstate(inp, INP_BOUND);
#if defined(IPSEC) || defined(FAST_IPSEC)
- ipsec_pcbdisconn(inp->inp_sp);
+ if (ipsec_havespd && inp->inp_sp)
+ ipsec_pcbdisconn(inp->inp_sp);
#endif
if (inp->inp_socket->so_state & SS_NOFDREF)
in_pcbdetach(inp);
@@ -478,7 +482,8 @@
return;
#if defined(IPSEC) || defined(FAST_IPSEC)
- ipsec4_delete_pcbpolicy(inp);
+ if (ipsec_havespd)
+ ipsec4_delete_pcbpolicy(inp);
#endif /*IPSEC*/
so->so_pcb = 0;
sofree(so);
Index: netinet/ip_icmp.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.97
diff -u -r1.97 ip_icmp.c
--- netinet/ip_icmp.c 10 Nov 2005 13:40:38 -0000 1.97
+++ netinet/ip_icmp.c 22 Feb 2006 02:05:57 -0000
@@ -603,7 +603,8 @@
pfctlinput(PRC_REDIRECT_HOST, sintosa(&icmpsrc));
#if defined(IPSEC) || defined(FAST_IPSEC)
- key_sa_routechange((struct sockaddr *)&icmpsrc);
+ if (ipsec_havespd)
+ key_sa_routechange((struct sockaddr *)&icmpsrc);
#endif
break;
Index: netinet/ip_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_input.c,v
retrieving revision 1.224
diff -u -r1.224 ip_input.c
--- netinet/ip_input.c 18 Feb 2006 17:47:07 -0000 1.224
+++ netinet/ip_input.c 22 Feb 2006 02:05:59 -0000
@@ -616,8 +616,11 @@
}
#if defined(IPSEC)
- /* ipflow (IP fast forwarding) is not compatible with IPsec. */
- m->m_flags &= ~M_CANFASTFWD;
+ if (ipsec_havespd)
+ /* ipflow (IP fast forwarding) is not compatible with IPsec. */
+ m->m_flags &= ~M_CANFASTFWD;
+ else
+ m->m_flags |= M_CANFASTFWD;
#else
/*
* Assume that we can create a fast-forward IP flow entry
@@ -639,9 +642,9 @@
* not the decapsulated packet.
*/
#ifdef IPSEC
- if (!ipsec_getnhist(m))
+ if (!ipsec_havespd || !ipsec_getnhist(m))
#elif defined(FAST_IPSEC)
- if (!ipsec_indone(m))
+ if (!ipsec_havespd || !ipsec_indone(m))
#else
if (1)
#endif
@@ -823,12 +826,13 @@
return;
}
#ifdef IPSEC
- if (ipsec4_in_reject(m, NULL)) {
+ if (ipsec_havespd && ipsec4_in_reject(m, NULL)) {
ipsecstat.in_polvio++;
goto bad;
}
#endif
#ifdef FAST_IPSEC
+ if (ipsec_havespd) {
mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
s = splsoftnet();
if (mtag != NULL) {
@@ -875,6 +879,7 @@
}
splx(s);
}
+ }
#endif /* FAST_IPSEC */
ip_forward(m, srcrt);
@@ -968,7 +973,8 @@
* note that we do not visit this with protocols with pcb layer
* code - like udp/tcp/raw ip.
*/
- if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 &&
+ if (ipsec_havespd &&
+ (inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 &&
ipsec4_in_reject(m, NULL)) {
ipsecstat.in_polvio++;
goto bad;
@@ -980,7 +986,8 @@
* note that we do not visit this with protocols with pcb layer
* code - like udp/tcp/raw ip.
*/
- if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0) {
+ if (ipsec_havespd &&
+ (inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0) {
/*
* Check if the packet has already had IPsec processing
* done. If so, then just pass it along. This tag gets
@@ -1975,6 +1982,13 @@
size_t ipsechdr;
struct route *ro;
+ if (!ipsec_havespd) {
+ destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu;
+ ipstat.ips_cantfrag++;
+ break;
+ }
+
+ destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu;
sp = ipsec4_getpolicybyaddr(mcopy,
IPSEC_DIR_OUTBOUND, IP_FORWARDING,
&ipsecerror);
Index: netinet/ip_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_output.c,v
retrieving revision 1.159
diff -u -r1.159 ip_output.c
--- netinet/ip_output.c 11 Dec 2005 12:24:57 -0000 1.159
+++ netinet/ip_output.c 22 Feb 2006 02:06:03 -0000
@@ -523,6 +523,8 @@
ip_len = ntohs(ip->ip_len);
#ifdef IPSEC
+ if (!ipsec_havespd || sotoinpcb_hdr(so)->inph_sp == NULL)
+ goto skip_ipsec;
/* get SP for this packet */
if (so == NULL)
sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND,
@@ -675,6 +677,8 @@
skip_ipsec:
#endif /*IPSEC*/
#ifdef FAST_IPSEC
+ if (!ipsec_havespd)
+ goto spd_done;
/*
* Check the security policy (SP) for the packet and, if
* required, do IPsec-related processing. There are two
@@ -693,7 +697,7 @@
error = -EINVAL; /* force silent drop */
m_tag_delete(m, mtag);
} else {
- if (inp != NULL &&
+ if (inp != NULL && inp->inp_sp &&
IPSEC_PCB_SKIP_IPSEC(inp->inp_sp, IPSEC_DIR_OUTBOUND))
goto spd_done;
sp = ipsec4_checkpolicy(m, IPSEC_DIR_OUTBOUND, flags,
@@ -872,8 +876,9 @@
}
#ifdef IPSEC
- /* clean ipsec history once it goes out of the node */
- ipsec_delaux(m);
+ if (ipsec_havespd)
+ /* clean ipsec history once it goes out of the node */
+ ipsec_delaux(m);
#endif
if (__predict_true(
@@ -930,6 +935,8 @@
ntohs(ip->ip_len);
#endif
#ifdef IPSEC
+ if (!ipsec_havespd)
+ goto fastout;
/* clean ipsec history once it goes out of the node */
ipsec_delaux(m);
@@ -947,6 +954,9 @@
#endif /* IPSEC_NAT_T */
#endif /* IPSEC */
{
+#ifdef IPSEC
+fastout:
+#endif
KASSERT((m->m_pkthdr.csum_flags &
(M_CSUM_UDPv4 | M_CSUM_TCPv4)) == 0);
error = (*ifp->if_output)(ifp, m, sintosa(dst),
@@ -965,14 +975,14 @@
}
#ifdef IPSEC
- if (sp != NULL) {
+ if (ipsec_havespd && sp != NULL) {
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP ip_output call free SP:%p\n", sp));
key_freesp(sp);
}
#endif /* IPSEC */
#ifdef FAST_IPSEC
- if (sp != NULL)
+ if (ipsec_havespd && sp != NULL)
KEY_FREESP(&sp);
#endif /* FAST_IPSEC */
@@ -1350,6 +1360,10 @@
#if defined(IPSEC) || defined(FAST_IPSEC)
case IP_IPSEC_POLICY:
+ if (!ipsec_havespd) {
+ error = ENOPROTOOPT;
+ break;
+ }
{
caddr_t req = NULL;
size_t len = 0;
Index: netinet/raw_ip.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/raw_ip.c,v
retrieving revision 1.88
diff -u -r1.88 raw_ip.c
--- netinet/raw_ip.c 11 Dec 2005 12:24:57 -0000 1.88
+++ netinet/raw_ip.c 22 Feb 2006 02:06:03 -0000
@@ -183,7 +183,8 @@
#if defined(IPSEC) || defined(FAST_IPSEC)
/* check AH/ESP integrity. */
- if (ipsec4_in_reject_so(m, last->inp_socket)) {
+ if (ipsec_havespd &&
+ ipsec4_in_reject_so(m, last->inp_socket)) {
ipsecstat.in_polvio++;
/* do not inject data to pcb */
} else
@@ -207,7 +208,7 @@
}
#if defined(IPSEC) || defined(FAST_IPSEC)
/* check AH/ESP integrity. */
- if (last && ipsec4_in_reject_so(m, last->inp_socket)) {
+ if (last && ipsec_havespd && ipsec4_in_reject_so(m, last->inp_socket)) {
m_freem(m);
ipsecstat.in_polvio++;
ipstat.ips_delivered--;
Index: netinet/tcp_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_input.c,v
retrieving revision 1.239
diff -u -r1.239 tcp_input.c
--- netinet/tcp_input.c 18 Feb 2006 17:34:49 -0000 1.239
+++ netinet/tcp_input.c 22 Feb 2006 02:06:06 -0000
@@ -1193,6 +1193,8 @@
goto dropwithreset_ratelim;
}
#if defined(IPSEC) || defined(FAST_IPSEC)
+ if (!ipsec_havespd)
+ break;
if (inp && (inp->inp_socket->so_options & SO_ACCEPTCONN) == 0 &&
ipsec4_in_reject(m, inp)) {
ipsecstat.in_polvio++;
@@ -1236,6 +1238,8 @@
goto dropwithreset_ratelim;
}
#if defined(IPSEC) || defined(FAST_IPSEC)
+ if (!ipsec_havespd)
+ break;
if ((in6p->in6p_socket->so_options & SO_ACCEPTCONN) == 0 &&
ipsec6_in_reject(m, in6p)) {
ipsec6stat.in_polvio++;
@@ -1494,6 +1498,8 @@
switch (af) {
#ifdef INET
case AF_INET:
+ if (!ipsec_havespd)
+ break;
if (ipsec4_in_reject_so(m, so)) {
ipsecstat.in_polvio++;
tp = NULL;
@@ -1503,6 +1509,8 @@
#endif
#ifdef INET6
case AF_INET6:
+ if (!ipsec_havespd)
+ break;
if (ipsec6_in_reject_so(m, so)) {
ipsec6stat.in_polvio++;
tp = NULL;
@@ -3701,23 +3709,25 @@
#endif
#if defined(IPSEC) || defined(FAST_IPSEC)
+ if (ipsec_havespd) {
/*
* we make a copy of policy, instead of sharing the policy,
* for better behavior in terms of SA lookup and dead SA removal.
*/
- if (inp) {
+ if (inp && sotoinpcb(oso)->inp_sp) {
/* copy old policy into new socket's */
if (ipsec_copy_pcbpolicy(sotoinpcb(oso)->inp_sp, inp->inp_sp))
printf("tcp_input: could not copy policy\n");
}
#ifdef INET6
- else if (in6p) {
+ else if (in6p && sotoin6pcb(oso)->in6p_sp) {
/* copy old policy into new socket's */
if (ipsec_copy_pcbpolicy(sotoin6pcb(oso)->in6p_sp,
in6p->in6p_sp))
printf("tcp_input: could not copy policy\n");
}
#endif
+ }
#endif
/*
Index: netinet/tcp_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_output.c,v
retrieving revision 1.141
diff -u -r1.141 tcp_output.c
--- netinet/tcp_output.c 24 Dec 2005 20:45:09 -0000 1.141
+++ netinet/tcp_output.c 22 Feb 2006 02:06:07 -0000
@@ -351,7 +351,8 @@
#ifdef INET
if (inp) {
#if defined(IPSEC) || defined(FAST_IPSEC)
- if (! IPSEC_PCB_SKIP_IPSEC(inp->inp_sp, IPSEC_DIR_OUTBOUND))
+ if (ipsec_havespd && inp->inp_sp &&
+ ! IPSEC_PCB_SKIP_IPSEC(inp->inp_sp, IPSEC_DIR_OUTBOUND))
optlen += ipsec4_hdrsiz_tcp(tp);
#endif
optlen += ip_optlen(inp);
@@ -361,7 +362,8 @@
#ifdef INET
if (in6p && tp->t_family == AF_INET) {
#if defined(IPSEC) || defined(FAST_IPSEC)
- if (! IPSEC_PCB_SKIP_IPSEC(in6p->in6p_sp, IPSEC_DIR_OUTBOUND))
+ if (ipsec_havespd && in6p->in6p_sp &&
+ ! IPSEC_PCB_SKIP_IPSEC(in6p->in6p_sp, IPSEC_DIR_OUTBOUND))
optlen += ipsec4_hdrsiz_tcp(tp);
#endif
/* XXX size -= ip_optlen(in6p); */
@@ -369,7 +371,8 @@
#endif
if (in6p && tp->t_family == AF_INET6) {
#ifdef IPSEC
- if (! IPSEC_PCB_SKIP_IPSEC(in6p->in6p_sp, IPSEC_DIR_OUTBOUND))
+ if (ipsec_havespd && in6p->in6p_sp &&
+ ! IPSEC_PCB_SKIP_IPSEC(in6p->in6p_sp, IPSEC_DIR_OUTBOUND))
optlen += ipsec6_hdrsiz_tcp(tp);
#endif
optlen += ip6_optlen(in6p);
@@ -615,10 +618,11 @@
* - If there is not an IPsec policy that prevents it
* - If the interface can do it
*/
- has_tso = tp->t_inpcb != NULL &&
+ has_tso = tp->t_inpcb != NULL &&
#if defined(IPSEC) || defined(FAST_IPSEC)
- IPSEC_PCB_SKIP_IPSEC(tp->t_inpcb->inp_sp,
- IPSEC_DIR_OUTBOUND) &&
+ ipsec_havespd && tp->t_inpcb->inp_sp &&
+ IPSEC_PCB_SKIP_IPSEC(tp->t_inpcb->inp_sp,
+ IPSEC_DIR_OUTBOUND) &&
#endif
tp->t_inpcb->inp_route.ro_rt != NULL &&
(tp->t_inpcb->inp_route.ro_rt->rt_ifp->if_capenable &
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.146
diff -u -r1.146 udp_usrreq.c
--- netinet/udp_usrreq.c 21 Jan 2006 00:15:36 -0000 1.146
+++ netinet/udp_usrreq.c 22 Feb 2006 02:06:08 -0000
@@ -630,7 +630,7 @@
#if defined(IPSEC) || defined(FAST_IPSEC)
/* check AH/ESP integrity. */
- if (so != NULL && ipsec4_in_reject_so(m, so)) {
+ if (so != NULL && ipsec_havespd && ipsec4_in_reject_so(m, so)) {
ipsecstat.in_polvio++;
if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
icmp_error(n, ICMP_UNREACH, ICMP_UNREACH_ADMIN_PROHIBIT,
@@ -677,7 +677,7 @@
#if defined(IPSEC) || defined(FAST_IPSEC)
/* check AH/ESP integrity. */
- if (so != NULL && ipsec6_in_reject_so(m, so)) {
+ if (so != NULL && ipsec_havespd && ipsec6_in_reject_so(m, so)) {
ipsec6stat.in_polvio++;
if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
icmp6_error(n, ICMP6_DST_UNREACH,
Index: netinet6/ipsec.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ipsec.c,v
retrieving revision 1.106
diff -u -r1.106 ipsec.c
--- netinet6/ipsec.c 21 Jan 2006 00:15:36 -0000 1.106
+++ netinet6/ipsec.c 22 Feb 2006 02:06:12 -0000
@@ -119,6 +119,7 @@
#endif /* INET6 */
u_int ipsec_spdgen = 1; /* SPD generation # */
+int ipsec_havespd = 0; /* if we have SPD's */
#ifdef SADB_X_EXT_TAG
static struct pf_tag *ipsec_get_tag __P((struct mbuf *));
@@ -348,6 +349,8 @@
ipsec_spdgen = 1;
else
ipsec_spdgen++;
+ ipsec_havespd = (key_havesp(IPSEC_DIR_INBOUND) ? IPSEC_SPD_INBOUND : 0)
+ | (key_havesp(IPSEC_DIR_OUTBOUND) ? IPSEC_SPD_OUTBOUND : 0);
}
#ifdef SADB_X_EXT_TAG
@@ -409,10 +412,8 @@
panic("ipsec4_getpolicybysock: unsupported address family");
}
-#ifdef DIAGNOSTIC
if (pcbsp == NULL)
- panic("ipsec4_getpolicybysock: pcbsp is NULL.");
-#endif
+ return NULL;
#ifdef SADB_X_EXT_TAG
t = ipsec_get_tag(m);
Index: netinet6/ipsec.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ipsec.h,v
retrieving revision 1.45
diff -u -r1.45 ipsec.h
--- netinet6/ipsec.h 10 Dec 2005 23:39:56 -0000 1.45
+++ netinet6/ipsec.h 22 Feb 2006 02:06:12 -0000
@@ -349,6 +349,9 @@
extern void ipsec_invalpcbcacheall __P((void));
extern u_int ipsec_spdgen;
+extern int ipsec_havespd;
+#define IPSEC_SPD_INBOUND 1
+#define IPSEC_SPD_OUTBOUND 2
extern struct secpolicy *ipsec4_getpolicybysock
__P((struct mbuf *, u_int, struct socket *, int *));
Index: netipsec/ipsec.c
===================================================================
RCS file: /cvsroot/src/sys/netipsec/ipsec.c,v
retrieving revision 1.19
diff -u -r1.19 ipsec.c
--- netipsec/ipsec.c 11 Dec 2005 12:25:05 -0000 1.19
+++ netipsec/ipsec.c 22 Feb 2006 02:06:16 -0000
@@ -107,6 +107,7 @@
#else
int ipsec_debug = 0;
#endif
+int ipsec_havespd = 0; /* if we have SPD's */
/* NB: name changed so netstat doesn't use it */
struct newipsecstat newipsecstat;
@@ -401,6 +402,8 @@
ipsec_spdgen = 1;
else
ipsec_spdgen++;
+ ipsec_havespd = (key_havesp(IPSEC_DIR_INBOUND) ? IPSEC_SPD_INBOUND : 0)
+ | (key_havesp(IPSEC_DIR_OUTBOUND) ? IPSEC_SPD_OUTBOUND : 0);
}
#endif /* __NetBSD__ */
@@ -499,7 +502,10 @@
("ipsec_getpolicybysock: unexpected protocol family %u", af));
#ifdef __NetBSD__
- IPSEC_ASSERT(inp->inph_sp != NULL, ("null PCB policy cache"));
+ if (inp->inph_sp == NULL) {
+ *error = EINVAL;
+ return NULL;
+ }
/* If we have a cached entry, and if it is still valid, use it. */
ipsecstat.ips_spdcache_lookup++;
currsp = ipsec_checkpcbcache(m, /*inpcb_hdr*/inp->inph_sp, dir);
@@ -535,7 +541,9 @@
if (*error)
return NULL;
- IPSEC_ASSERT(pcbsp != NULL, ("ipsec_getpolicybysock: null pcbsp"));
+ if (pcbsp == NULL)
+ return NULL;
+
switch (dir) {
case IPSEC_DIR_INBOUND:
currsp = pcbsp->sp_in;
@@ -714,7 +722,8 @@
int error;
IPSEC_ASSERT(pcb != NULL, ("ipsec4_setspidx_inpcb: null pcb"));
- IPSEC_ASSERT(pcb->inp_sp != NULL, ("ipsec4_setspidx_inpcb: null inp_sp"));
+ if (pcb->inp_sp == NULL)
+ return EINVAL;
IPSEC_ASSERT(pcb->inp_sp->sp_out != NULL && pcb->inp_sp->sp_in != NULL,
("ipsec4_setspidx_inpcb: null sp_in || sp_out"));
@@ -742,7 +751,8 @@
int error;
IPSEC_ASSERT(pcb != NULL, ("ipsec6_setspidx_in6pcb: null pcb"));
- IPSEC_ASSERT(pcb->in6p_sp != NULL, ("ipsec6_setspidx_in6pcb: null inp_sp"));
+ if (pcb->in6p_sp == NULL)
+ return EINVAL;
IPSEC_ASSERT(pcb->in6p_sp->sp_out != NULL && pcb->in6p_sp->sp_in != NULL,
("ipsec6_setspidx_in6pcb: null sp_in || sp_out"));
@@ -1299,11 +1309,10 @@
return EINVAL;
if (len < sizeof(*xpl))
return EINVAL;
+ if (inp->inp_sp == NULL)
+ return EINVAL;
xpl = (struct sadb_x_policy *)request;
- IPSEC_ASSERT(inp->inp_sp != NULL,
- ("ipsec4_set_policy(): null inp->in_sp"));
-
/* select direction */
switch (xpl->sadb_x_policy_dir) {
case IPSEC_DIR_INBOUND:
@@ -1334,7 +1343,8 @@
/* sanity check. */
if (inp == NULL || request == NULL || mp == NULL)
return EINVAL;
- IPSEC_ASSERT(inp->inp_sp != NULL, ("ipsec4_get_policy: null inp_sp"));
+ if (inp->inp_sp != NULL)
+ return EINVAL;
if (len < sizeof(*xpl))
return EINVAL;
xpl = (struct sadb_x_policy *)request;
@@ -1395,6 +1405,8 @@
return EINVAL;
if (len < sizeof(*xpl))
return EINVAL;
+ if (in6p->in6p_sp == NULL)
+ return EINVAL;
xpl = (struct sadb_x_policy *)request;
/* select direction */
@@ -1427,9 +1439,10 @@
/* sanity check. */
if (in6p == NULL || request == NULL || mp == NULL)
return EINVAL;
- IPSEC_ASSERT(in6p->in6p_sp != NULL, ("ipsec6_get_policy: null in6p_sp"));
if (len < sizeof(*xpl))
return EINVAL;
+ if (in6p->in6p_sp == NULL)
+ return EINVAL;
xpl = (struct sadb_x_policy *)request;
/* select direction */
Index: netipsec/ipsec.h
===================================================================
RCS file: /cvsroot/src/sys/netipsec/ipsec.h,v
retrieving revision 1.14
diff -u -r1.14 ipsec.h
--- netipsec/ipsec.h 16 Feb 2006 20:17:20 -0000 1.14
+++ netipsec/ipsec.h 22 Feb 2006 02:06:16 -0000
@@ -219,6 +219,9 @@
};
extern int ipsec_debug;
+extern int ipsec_havespd;
+#define IPSEC_SPD_INBOUND 1
+#define IPSEC_SPD_OUTBOUND 2
extern struct newipsecstat newipsecstat;
extern struct secpolicy ip4_def_policy;
Index: netkey/key.c
===================================================================
RCS file: /cvsroot/src/sys/netkey/key.c,v
retrieving revision 1.139
diff -u -r1.139 key.c
--- netkey/key.c 25 Jan 2006 15:12:05 -0000 1.139
+++ netkey/key.c 22 Feb 2006 02:06:35 -0000
@@ -475,6 +475,18 @@
static struct mbuf *key_alloc_mbuf __P((int));
struct callout key_timehandler_ch;
+/*
+ * Return 0 when there are known to be no SP's for the specified
+ * direction. Otherwise return 1. This is used by IPsec code
+ * to optimize performance.
+ */
+int
+key_havesp(u_int dir)
+{
+ return (dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND ?
+ LIST_FIRST(&sptree[dir]) != NULL : 1);
+}
+
/* %%% IPsec policy management */
/*
* allocating a SP for OUTBOUND or INBOUND packet.
Index: netkey/key.h
===================================================================
RCS file: /cvsroot/src/sys/netkey/key.h,v
retrieving revision 1.20
diff -u -r1.20 key.h
--- netkey/key.h 11 Dec 2005 00:02:28 -0000 1.20
+++ netkey/key.h 22 Feb 2006 02:06:35 -0000
@@ -55,6 +55,7 @@
struct sadb_msg;
struct sadb_x_policy;
+extern int key_havesp __P((u_int));
extern struct secpolicy *key_allocsp __P((u_int16_t, struct secpolicyindex *,
u_int));
extern int key_checkrequest