do not copy policy-on-socket at all. avoid copying packet header value to

struct spindex.  should reduce memory usage per socket/pcb, and should speedup
ipsec processing.  sync w/kame
This commit is contained in:
itojun 2002-06-12 01:47:34 +00:00
parent c08cac5019
commit 3489976392
6 changed files with 149 additions and 300 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipsec.c,v 1.52 2002/06/11 19:40:00 itojun Exp $ */
/* $NetBSD: ipsec.c,v 1.53 2002/06/12 01:47:34 itojun Exp $ */
/* $KAME: ipsec.c,v 1.136 2002/05/19 00:36:39 itojun Exp $ */
/*
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.52 2002/06/11 19:40:00 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.53 2002/06/12 01:47:34 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -121,30 +121,28 @@ int ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
#endif /* INET6 */
static struct secpolicy *ipsec_checkpcbcache __P((struct mbuf *,
struct inpcbpolicy *pcbsp, int));
struct inpcbpolicy *, int));
static int ipsec_fillpcbcache __P((struct inpcbpolicy *, struct mbuf *,
struct secpolicy *, int));
static int ipsec_invalpcbcache __P((struct inpcbpolicy *, int));
static int ipsec_setspidx_mbuf
__P((struct secpolicyindex *, u_int, u_int, struct mbuf *, int));
static int ipsec4_setspidx_inpcb __P((struct mbuf *, struct inpcb *pcb));
#ifdef INET6
static int ipsec6_setspidx_in6pcb __P((struct mbuf *, struct in6pcb *pcb));
#endif
__P((struct secpolicyindex *, int, struct mbuf *, int));
static int ipsec_setspidx __P((struct mbuf *, struct secpolicyindex *, int));
static void ipsec4_get_ulp __P((struct mbuf *m, struct secpolicyindex *, int));
static void ipsec4_get_ulp __P((struct mbuf *, struct secpolicyindex *, int));
static int ipsec4_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
#ifdef INET6
static void ipsec6_get_ulp __P((struct mbuf *m, struct secpolicyindex *, int));
static void ipsec6_get_ulp __P((struct mbuf *, struct secpolicyindex *, int));
static int ipsec6_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
#endif
static struct inpcbpolicy *ipsec_newpcbpolicy __P((void));
static void ipsec_delpcbpolicy __P((struct inpcbpolicy *));
#if 0
static int ipsec_deepcopy_pcbpolicy __P((struct inpcbpolicy *));
static struct secpolicy *ipsec_deepcopy_policy __P((struct secpolicy *src));
static struct secpolicy *ipsec_deepcopy_policy __P((struct secpolicy *));
#endif
static int ipsec_set_policy
__P((struct secpolicy **, int, caddr_t, size_t, int));
static int ipsec_get_policy __P((struct secpolicy *pcb_sp, struct mbuf **mp));
static int ipsec_get_policy __P((struct secpolicy *, struct mbuf **));
static void vshiftl __P((unsigned char *, int, int));
static int ipsec_in_reject __P((struct secpolicy *, struct mbuf *));
static size_t ipsec_hdrsiz __P((struct secpolicy *));
@ -203,7 +201,8 @@ ipsec_checkpcbcache(m, pcbsp, dir)
if (ipsec_setspidx(m, &spidx, 1) != 0)
return NULL;
if (bcmp(&pcbsp->cacheidx[dir], &spidx, sizeof(spidx))) {
if (!key_cmpspidx_withmask(&pcbsp->cache[dir]->spidx,
if (pcbsp->cache[dir]->spidx &&
!key_cmpspidx_withmask(pcbsp->cache[dir]->spidx,
&spidx))
return NULL;
pcbsp->cacheidx[dir] = spidx;
@ -336,6 +335,7 @@ ipsec4_getpolicybysock(m, dir, so, error)
struct inpcbpolicy *pcbsp = NULL;
struct secpolicy *currsp = NULL; /* policy on socket */
struct secpolicy *kernsp = NULL; /* policy on kernel */
struct secpolicyindex spidx;
/* sanity check */
if (m == NULL || so == NULL || error == NULL)
@ -363,29 +363,6 @@ ipsec4_getpolicybysock(m, dir, so, error)
}
ipsecstat.spdcachemiss++;
/*
* XXX why is it necessary to do this, per-packet?
* we are of course sure that the socket policy do match the packet,
* because policy-on-pcb does not contain selectors, and
* in_pcblookup (inbound) ensures the packet-pcb matching.
*/
switch (so->so_proto->pr_domain->dom_family) {
case AF_INET:
/* set spidx in pcb */
*error = ipsec4_setspidx_inpcb(m, sotoinpcb(so));
break;
#ifdef INET6
case AF_INET6:
/* set spidx in pcb */
*error = ipsec6_setspidx_in6pcb(m, sotoin6pcb(so));
break;
#endif
default:
panic("ipsec4_getpolicybysock: unsupported address family\n");
}
if (*error)
return NULL;
/* sanity check */
if (pcbsp == NULL)
panic("ipsec4_getpolicybysock: pcbsp is NULL.\n");
@ -416,10 +393,9 @@ ipsec4_getpolicybysock(m, dir, so, error)
case IPSEC_POLICY_ENTRUST:
/* look for a policy in SPD */
kernsp = key_allocsp(&currsp->spidx, dir);
/* SP found */
if (kernsp != NULL) {
if (ipsec_setspidx_mbuf(&spidx, AF_INET, m, 0) == 0 &&
(kernsp = key_allocsp(&spidx, dir)) != NULL) {
/* SP found */
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP ipsec4_getpolicybysock called "
"to allocate SP:%p\n", kernsp));
@ -429,13 +405,6 @@ ipsec4_getpolicybysock(m, dir, so, error)
}
/* no SP found */
if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD &&
ip4_def_policy.policy != IPSEC_POLICY_NONE) {
ipseclog((LOG_INFO,
"fixed system default policy: %d->%d\n",
ip4_def_policy.policy, IPSEC_POLICY_NONE));
ip4_def_policy.policy = IPSEC_POLICY_NONE;
}
ip4_def_policy.refcnt++;
*error = 0;
ipsec_fillpcbcache(pcbsp, m, &ip4_def_policy, dir);
@ -458,10 +427,9 @@ ipsec4_getpolicybysock(m, dir, so, error)
/* when non-privilieged socket */
/* look for a policy in SPD */
kernsp = key_allocsp(&currsp->spidx, dir);
/* SP found */
if (kernsp != NULL) {
if (ipsec_setspidx_mbuf(&spidx, AF_INET, m, 0) == 0 &&
(kernsp = key_allocsp(&spidx, dir)) != NULL) {
/* SP found */
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP ipsec4_getpolicybysock called "
"to allocate SP:%p\n", kernsp));
@ -480,13 +448,6 @@ ipsec4_getpolicybysock(m, dir, so, error)
return NULL;
case IPSEC_POLICY_ENTRUST:
if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD &&
ip4_def_policy.policy != IPSEC_POLICY_NONE) {
ipseclog((LOG_INFO,
"fixed system default policy: %d->%d\n",
ip4_def_policy.policy, IPSEC_POLICY_NONE));
ip4_def_policy.policy = IPSEC_POLICY_NONE;
}
ip4_def_policy.refcnt++;
*error = 0;
ipsec_fillpcbcache(pcbsp, m, &ip4_def_policy, dir);
@ -530,13 +491,14 @@ ipsec4_getpolicybyaddr(m, dir, flag, error)
if (m == NULL || error == NULL)
panic("ipsec4_getpolicybyaddr: NULL pointer was passed.\n");
/* get a policy entry matched with the packet */
{
struct secpolicyindex spidx;
bzero(&spidx, sizeof(spidx));
/* make a index to look for a policy */
*error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET, m,
*error = ipsec_setspidx_mbuf(&spidx, AF_INET, m,
(flag & IP_FORWARDING) ? 0 : 1);
if (*error != 0)
@ -555,13 +517,6 @@ ipsec4_getpolicybyaddr(m, dir, flag, error)
}
/* no SP found */
if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD &&
ip4_def_policy.policy != IPSEC_POLICY_NONE) {
ipseclog((LOG_INFO, "fixed system default policy:%d->%d\n",
ip4_def_policy.policy,
IPSEC_POLICY_NONE));
ip4_def_policy.policy = IPSEC_POLICY_NONE;
}
ip4_def_policy.refcnt++;
*error = 0;
return &ip4_def_policy;
@ -588,6 +543,7 @@ ipsec6_getpolicybysock(m, dir, so, error)
struct inpcbpolicy *pcbsp = NULL;
struct secpolicy *currsp = NULL; /* policy on socket */
struct secpolicy *kernsp = NULL; /* policy on kernel */
struct secpolicyindex spidx;
/* sanity check */
if (m == NULL || so == NULL || error == NULL)
@ -609,10 +565,6 @@ ipsec6_getpolicybysock(m, dir, so, error)
}
ipsec6stat.spdcachemiss++;
/* set spidx in pcb */
/* XXX why is it necessary to do this? */
ipsec6_setspidx_in6pcb(m, sotoin6pcb(so));
/* sanity check */
if (pcbsp == NULL)
panic("ipsec6_getpolicybysock: pcbsp is NULL.\n");
@ -643,10 +595,9 @@ ipsec6_getpolicybysock(m, dir, so, error)
case IPSEC_POLICY_ENTRUST:
/* look for a policy in SPD */
kernsp = key_allocsp(&currsp->spidx, dir);
/* SP found */
if (kernsp != NULL) {
if (ipsec_setspidx_mbuf(&spidx, AF_INET6, m, 0) == 0 &&
(kernsp = key_allocsp(&spidx, dir)) != NULL) {
/* SP found */
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP ipsec6_getpolicybysock called "
"to allocate SP:%p\n", kernsp));
@ -656,13 +607,6 @@ ipsec6_getpolicybysock(m, dir, so, error)
}
/* no SP found */
if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD &&
ip6_def_policy.policy != IPSEC_POLICY_NONE) {
ipseclog((LOG_INFO,
"fixed system default policy: %d->%d\n",
ip6_def_policy.policy, IPSEC_POLICY_NONE));
ip6_def_policy.policy = IPSEC_POLICY_NONE;
}
ip6_def_policy.refcnt++;
*error = 0;
ipsec_fillpcbcache(pcbsp, m, &ip6_def_policy, dir);
@ -685,10 +629,9 @@ ipsec6_getpolicybysock(m, dir, so, error)
/* when non-privilieged socket */
/* look for a policy in SPD */
kernsp = key_allocsp(&currsp->spidx, dir);
/* SP found */
if (kernsp != NULL) {
if (ipsec_setspidx_mbuf(&spidx, AF_INET6, m, 0) == 0 &&
(kernsp = key_allocsp(&spidx, dir)) != NULL) {
/* SP found */
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP ipsec6_getpolicybysock called "
"to allocate SP:%p\n", kernsp));
@ -707,13 +650,6 @@ ipsec6_getpolicybysock(m, dir, so, error)
return NULL;
case IPSEC_POLICY_ENTRUST:
if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD &&
ip6_def_policy.policy != IPSEC_POLICY_NONE) {
ipseclog((LOG_INFO,
"fixed system default policy: %d->%d\n",
ip6_def_policy.policy, IPSEC_POLICY_NONE));
ip6_def_policy.policy = IPSEC_POLICY_NONE;
}
ip6_def_policy.refcnt++;
*error = 0;
ipsec_fillpcbcache(pcbsp, m, &ip6_def_policy, dir);
@ -764,13 +700,14 @@ ipsec6_getpolicybyaddr(m, dir, flag, error)
if (m == NULL || error == NULL)
panic("ipsec6_getpolicybyaddr: NULL pointer was passed.\n");
/* get a policy entry matched with the packet */
{
struct secpolicyindex spidx;
bzero(&spidx, sizeof(spidx));
/* make a index to look for a policy */
*error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET6, m,
*error = ipsec_setspidx_mbuf(&spidx, AF_INET6, m,
(flag & IP_FORWARDING) ? 0 : 1);
if (*error != 0)
@ -789,12 +726,6 @@ ipsec6_getpolicybyaddr(m, dir, flag, error)
}
/* no SP found */
if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD &&
ip6_def_policy.policy != IPSEC_POLICY_NONE) {
ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n",
ip6_def_policy.policy, IPSEC_POLICY_NONE));
ip6_def_policy.policy = IPSEC_POLICY_NONE;
}
ip6_def_policy.refcnt++;
*error = 0;
return &ip6_def_policy;
@ -812,9 +743,9 @@ ipsec6_getpolicybyaddr(m, dir, flag, error)
* other: failure, and set errno.
*/
int
ipsec_setspidx_mbuf(spidx, dir, family, m, needport)
ipsec_setspidx_mbuf(spidx, family, m, needport)
struct secpolicyindex *spidx;
u_int dir, family;
int family;
struct mbuf *m;
int needport;
{
@ -829,7 +760,6 @@ ipsec_setspidx_mbuf(spidx, dir, family, m, needport)
error = ipsec_setspidx(m, spidx, needport);
if (error)
goto bad;
spidx->dir = dir;
return 0;
@ -839,98 +769,6 @@ ipsec_setspidx_mbuf(spidx, dir, family, m, needport)
return EINVAL;
}
static int
ipsec4_setspidx_inpcb(m, pcb)
struct mbuf *m;
struct inpcb *pcb;
{
struct secpolicyindex *spidx;
int error;
/* sanity check */
if (pcb == NULL)
panic("ipsec4_setspidx_inpcb: no PCB found.\n");
if (pcb->inp_sp == NULL)
panic("ipsec4_setspidx_inpcb: no inp_sp found.\n");
if (pcb->inp_sp->sp_out == NULL || pcb->inp_sp->sp_in == NULL)
panic("ipsec4_setspidx_inpcb: no sp_in/out found.\n");
if (pcb->inp_sp->sp_in->readonly || pcb->inp_sp->sp_out->readonly) {
error = ipsec_deepcopy_pcbpolicy(pcb->inp_sp);
if (error)
return error;
}
bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));
bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));
spidx = &pcb->inp_sp->sp_in->spidx;
error = ipsec_setspidx(m, spidx, 1);
if (error)
goto bad;
spidx->dir = IPSEC_DIR_INBOUND;
spidx = &pcb->inp_sp->sp_out->spidx;
error = ipsec_setspidx(m, spidx, 1);
if (error)
goto bad;
spidx->dir = IPSEC_DIR_OUTBOUND;
return 0;
bad:
bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));
bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));
return error;
}
#ifdef INET6
static int
ipsec6_setspidx_in6pcb(m, pcb)
struct mbuf *m;
struct in6pcb *pcb;
{
struct secpolicyindex *spidx;
int error;
/* sanity check */
if (pcb == NULL)
panic("ipsec6_setspidx_in6pcb: no PCB found.\n");
if (pcb->in6p_sp == NULL)
panic("ipsec6_setspidx_in6pcb: no in6p_sp found.\n");
if (pcb->in6p_sp->sp_out == NULL || pcb->in6p_sp->sp_in == NULL)
panic("ipsec6_setspidx_in6pcb: no sp_in/out found.\n");
if (pcb->in6p_sp->sp_in->readonly || pcb->in6p_sp->sp_out->readonly) {
error = ipsec_deepcopy_pcbpolicy(pcb->in6p_sp);
if (error)
return error;
}
bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
spidx = &pcb->in6p_sp->sp_in->spidx;
error = ipsec_setspidx(m, spidx, 1);
if (error)
goto bad;
spidx->dir = IPSEC_DIR_INBOUND;
spidx = &pcb->in6p_sp->sp_out->spidx;
error = ipsec_setspidx(m, spidx, 1);
if (error)
goto bad;
spidx->dir = IPSEC_DIR_OUTBOUND;
return 0;
bad:
bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
return error;
}
#endif
/*
* configure security policy index (src/dst/proto/sport/dport)
* by looking at the content of mbuf.
@ -1272,12 +1110,12 @@ ipsec_init_pcbpolicy(so, pcb_sp)
in->state = IPSEC_SPSTATE_ALIVE;
in->policy = IPSEC_POLICY_ENTRUST;
in->spidx.dir = IPSEC_DIR_INBOUND;
in->dir = IPSEC_DIR_INBOUND;
in->readonly = 1;
out->state = IPSEC_SPSTATE_ALIVE;
out->policy = IPSEC_POLICY_ENTRUST;
out->spidx.dir = IPSEC_DIR_OUTBOUND;
out->dir = IPSEC_DIR_OUTBOUND;
out->readonly = 1;
initialized++;
@ -1326,6 +1164,7 @@ ipsec_copy_pcbpolicy(old, new)
return 0;
}
#if 0
static int
ipsec_deepcopy_pcbpolicy(pcb_sp)
struct inpcbpolicy *pcb_sp;
@ -1406,6 +1245,7 @@ fail:
}
return NULL;
}
#endif
/* set policy and ipsec request if present. */
static int
@ -1691,8 +1531,9 @@ ipsec6_delete_pcbpolicy(in6p)
* Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned.
*/
u_int
ipsec_get_reqlevel(isr)
ipsec_get_reqlevel(isr, af)
struct ipsecrequest *isr;
int af;
{
u_int level = 0;
u_int esp_trans_deflev, esp_net_deflev, ah_trans_deflev, ah_net_deflev;
@ -1700,47 +1541,30 @@ ipsec_get_reqlevel(isr)
/* sanity check */
if (isr == NULL || isr->sp == NULL)
panic("ipsec_get_reqlevel: NULL pointer is passed.\n");
if (((struct sockaddr *)&isr->sp->spidx.src)->sa_family
!= ((struct sockaddr *)&isr->sp->spidx.dst)->sa_family)
panic("ipsec_get_reqlevel: family mismatched.\n");
/* XXX note that we have ipseclog() expanded here - code sync issue */
#define IPSEC_CHECK_DEFAULT(lev) \
(((lev) != IPSEC_LEVEL_USE && (lev) != IPSEC_LEVEL_REQUIRE \
&& (lev) != IPSEC_LEVEL_UNIQUE) \
? (ipsec_debug \
? log(LOG_INFO, "fixed system default level " #lev ":%d->%d\n",\
(lev), IPSEC_LEVEL_REQUIRE) \
: 0), \
(lev) = IPSEC_LEVEL_REQUIRE, \
(lev) \
: (lev))
/* set default level */
switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) {
switch (af) {
#ifdef INET
case AF_INET:
esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev);
esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev);
ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev);
ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev);
esp_trans_deflev = ip4_esp_trans_deflev;
esp_net_deflev = ip4_esp_net_deflev;
ah_trans_deflev = ip4_ah_trans_deflev;
ah_net_deflev = ip4_ah_net_deflev;
break;
#endif
#ifdef INET6
case AF_INET6:
esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev);
esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev);
ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev);
ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev);
esp_trans_deflev = ip6_esp_trans_deflev;
esp_net_deflev = ip6_esp_net_deflev;
ah_trans_deflev = ip6_ah_trans_deflev;
ah_net_deflev = ip6_ah_net_deflev;
break;
#endif /* INET6 */
default:
panic("key_get_reqlevel: Unknown family. %d\n",
((struct sockaddr *)&isr->sp->spidx.src)->sa_family);
((struct sockaddr *)&isr->sp->spidx->src)->sa_family);
}
#undef IPSEC_CHECK_DEFAULT
/* set level */
switch (isr->level) {
case IPSEC_LEVEL_DEFAULT:
@ -1828,9 +1652,8 @@ ipsec_in_reject(sp, m)
/* XXX should compare policy against ipsec header history */
for (isr = sp->req; isr != NULL; isr = isr->next) {
/* get current level */
level = ipsec_get_reqlevel(isr);
level = ipsec_get_reqlevel(isr, AF_INET);
switch (isr->saidx.proto) {
case IPPROTO_ESP:
@ -2729,7 +2552,7 @@ ipsec4_output(state, sp, flags)
/* validity check */
if (isr->sav == NULL) {
switch (ipsec_get_reqlevel(isr)) {
switch (ipsec_get_reqlevel(isr, AF_INET)) {
case IPSEC_LEVEL_USE:
continue;
case IPSEC_LEVEL_REQUIRE:
@ -2982,7 +2805,7 @@ ipsec6_output_trans(state, nexthdrp, mprev, sp, flags, tun)
/* validity check */
if (isr->sav == NULL) {
switch (ipsec_get_reqlevel(isr)) {
switch (ipsec_get_reqlevel(isr, AF_INET6)) {
case IPSEC_LEVEL_USE:
continue;
case IPSEC_LEVEL_REQUIRE:
@ -3147,7 +2970,7 @@ ipsec6_output_tunnel(state, sp, flags)
/* validity check */
if (isr->sav == NULL) {
switch (ipsec_get_reqlevel(isr)) {
switch (ipsec_get_reqlevel(isr, AF_INET6)) {
case IPSEC_LEVEL_USE:
continue;
case IPSEC_LEVEL_REQUIRE:
@ -3752,13 +3575,7 @@ ipsec_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
return EINVAL;
}
}
}
switch (name[0]) {
case IPSECCTL_STATS:
return sysctl_struct(oldp, oldlenp, newp, newlen,
&ipsecstat, sizeof(ipsecstat));
break;
case IPSECCTL_DEF_POLICY:
if (newp != NULL && newlen == sizeof(int)) {
switch (*(int *)newp) {
@ -3770,6 +3587,14 @@ ipsec_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
}
ipsec_invalpcbcacheall();
}
break;
}
switch (name[0]) {
case IPSECCTL_STATS:
return sysctl_struct(oldp, oldlenp, newp, newlen,
&ipsecstat, sizeof(ipsecstat));
case IPSECCTL_DEF_POLICY:
return sysctl_int(oldp, oldlenp, newp, newlen,
&ip4_def_policy.policy);
case IPSECCTL_DEF_ESP_TRANSLEV:
@ -3852,13 +3677,7 @@ ipsec6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
return EINVAL;
}
}
}
switch (name[0]) {
case IPSECCTL_STATS:
return sysctl_struct(oldp, oldlenp, newp, newlen,
&ipsec6stat, sizeof(ipsec6stat));
break;
case IPSECCTL_DEF_POLICY:
if (newp != NULL && newlen == sizeof(int)) {
switch (*(int *)newp) {
@ -3870,6 +3689,14 @@ ipsec6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
}
ipsec_invalpcbcacheall();
}
break;
}
switch (name[0]) {
case IPSECCTL_STATS:
return sysctl_struct(oldp, oldlenp, newp, newlen,
&ipsec6stat, sizeof(ipsec6stat));
case IPSECCTL_DEF_POLICY:
return sysctl_int(oldp, oldlenp, newp, newlen,
&ip6_def_policy.policy);
case IPSECCTL_DEF_ESP_TRANSLEV:

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipsec.h,v 1.27 2002/06/11 19:40:00 itojun Exp $ */
/* $NetBSD: ipsec.h,v 1.28 2002/06/12 01:47:35 itojun Exp $ */
/* $KAME: ipsec.h,v 1.51 2001/08/05 04:52:58 itojun Exp $ */
/*
@ -54,7 +54,6 @@
* 0 to (~0 - 1): is one of the number of each value.
*/
struct secpolicyindex {
u_int8_t dir; /* direction of packet flow, see blow */
struct sockaddr_storage src; /* IP src address for SP */
struct sockaddr_storage dst; /* IP dst address for SP */
u_int8_t prefs; /* prefix length in bits for src */
@ -72,9 +71,10 @@ struct secpolicyindex {
struct secpolicy {
LIST_ENTRY(secpolicy) chain;
u_int8_t dir; /* direction of packet flow */
int readonly; /* write prohibited */
int refcnt; /* reference count */
struct secpolicyindex spidx; /* selector */
struct secpolicyindex *spidx; /* selector - NULL if not valid */
u_int32_t id; /* It's unique number on the system. */
u_int state; /* 0: dead, others: alive */
#define IPSEC_SPSTATE_DEAD 0
@ -349,7 +349,7 @@ struct in6pcb;
extern int ipsec_init_pcbpolicy __P((struct socket *so, struct inpcbpolicy **));
extern int ipsec_copy_pcbpolicy
__P((struct inpcbpolicy *, struct inpcbpolicy *));
extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *));
extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *, int));
extern int ipsec4_set_policy __P((struct inpcb *inp, int optname,
caddr_t request, size_t len, int priv));

View File

@ -1,4 +1,4 @@
/* $NetBSD: key.c,v 1.66 2002/06/11 19:40:00 itojun Exp $ */
/* $NetBSD: key.c,v 1.67 2002/06/12 01:47:36 itojun Exp $ */
/* $KAME: key.c,v 1.234 2002/05/13 03:21:17 itojun Exp $ */
/*
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.66 2002/06/11 19:40:00 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.67 2002/06/12 01:47:36 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -266,10 +266,9 @@ do { \
* set parameters into secpolicyindex buffer.
* Must allocate secpolicyindex buffer passed to this function.
*/
#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, idx) \
#define KEY_SETSECSPIDX(s, d, ps, pd, ulp, idx) \
do { \
bzero((idx), sizeof(struct secpolicyindex)); \
(idx)->dir = (_dir); \
(idx)->prefs = (ps); \
(idx)->prefd = (pd); \
(idx)->ul_proto = (ulp); \
@ -307,7 +306,7 @@ static struct secasvar *key_allocsa_policy __P((struct secasindex *));
static void key_freesp_so __P((struct secpolicy **));
static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int));
static void key_delsp __P((struct secpolicy *));
static struct secpolicy *key_getsp __P((struct secpolicyindex *));
static struct secpolicy *key_getsp __P((struct secpolicyindex *, int));
static struct secpolicy *key_getspbyid __P((u_int32_t));
static u_int32_t key_newreqid __P((void));
static struct mbuf *key_gather_mbuf __P((struct mbuf *,
@ -469,11 +468,11 @@ key_allocsp(spidx, dir)
LIST_FOREACH(sp, &sptree[dir], chain) {
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
printf("*** in SPD\n");
kdebug_secpolicyindex(&sp->spidx));
kdebug_secpolicyindex(sp->spidx));
if (sp->state == IPSEC_SPSTATE_DEAD)
continue;
if (key_cmpspidx_withmask(&sp->spidx, spidx))
if (key_cmpspidx_withmask(sp->spidx, spidx))
goto found;
}
@ -482,7 +481,7 @@ key_allocsp(spidx, dir)
found:
/* sanity check */
KEY_CHKSPDIR(sp->spidx.dir, dir, "key_allocsp");
KEY_CHKSPDIR(sp->dir, dir, "key_allocsp");
/* found a SPD entry */
sp->lastused = time.tv_sec;
@ -524,7 +523,7 @@ key_checkrequest(isr, saidx)
}
/* get current level */
level = ipsec_get_reqlevel(isr);
level = ipsec_get_reqlevel(isr, saidx->src.ss_family);
#if 0
/*
@ -995,8 +994,9 @@ key_delsp(sp)
* others : found, pointer to a SP.
*/
static struct secpolicy *
key_getsp(spidx)
key_getsp(spidx, dir)
struct secpolicyindex *spidx;
int dir;
{
struct secpolicy *sp;
@ -1004,10 +1004,10 @@ key_getsp(spidx)
if (spidx == NULL)
panic("key_getsp: NULL pointer is passed.\n");
LIST_FOREACH(sp, &sptree[spidx->dir], chain) {
LIST_FOREACH(sp, &sptree[dir], chain) {
if (sp->state == IPSEC_SPSTATE_DEAD)
continue;
if (key_cmpspidx_exactly(spidx, &sp->spidx)) {
if (key_cmpspidx_exactly(spidx, sp->spidx)) {
sp->refcnt++;
return sp;
}
@ -1092,7 +1092,7 @@ key_msg2sp(xpl0, len, error)
return NULL;
}
newsp->spidx.dir = xpl0->sadb_x_policy_dir;
newsp->dir = xpl0->sadb_x_policy_dir;
newsp->policy = xpl0->sadb_x_policy_type;
/* check policy */
@ -1334,7 +1334,7 @@ key_sp2msg(sp)
xpl->sadb_x_policy_len = PFKEY_UNIT64(tlen);
xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
xpl->sadb_x_policy_type = sp->policy;
xpl->sadb_x_policy_dir = sp->spidx.dir;
xpl->sadb_x_policy_dir = sp->dir;
xpl->sadb_x_policy_id = sp->id;
p = (caddr_t)xpl + sizeof(*xpl);
@ -1514,8 +1514,7 @@ key_spdadd(so, m, mhp)
/* make secindex */
/* XXX boundary check against sa_len */
KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir,
src0 + 1,
KEY_SETSECSPIDX(src0 + 1,
dst0 + 1,
src0->sadb_address_prefixlen,
dst0->sadb_address_prefixlen,
@ -1555,7 +1554,7 @@ key_spdadd(so, m, mhp)
* If the type is either SPDADD or SPDSETIDX AND a SP is found,
* then error.
*/
newsp = key_getsp(&spidx);
newsp = key_getsp(&spidx, xpl0->sadb_x_policy_dir);
if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
if (newsp) {
key_sp_dead(newsp);
@ -1581,14 +1580,11 @@ key_spdadd(so, m, mhp)
return key_senderror(so, m, ENOBUFS);
}
/* XXX boundary check against sa_len */
KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir,
src0 + 1,
dst0 + 1,
src0->sadb_address_prefixlen,
dst0->sadb_address_prefixlen,
src0->sadb_address_proto,
&newsp->spidx);
error = keydb_setsecpolicyindex(newsp, &spidx);
if (error) {
keydb_delsecpolicy(newsp);
return key_senderror(so, m, error);
}
/* sanity check on addr pair */
if (((struct sockaddr *)(src0 + 1))->sa_family !=
@ -1627,7 +1623,7 @@ key_spdadd(so, m, mhp)
newsp->refcnt = 1; /* do not reclaim until I say I do */
newsp->state = IPSEC_SPSTATE_ALIVE;
LIST_INSERT_TAIL(&sptree[newsp->spidx.dir], newsp, secpolicy, chain);
LIST_INSERT_TAIL(&sptree[newsp->dir], newsp, secpolicy, chain);
/* delete the entry in spacqtree */
if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
@ -1765,8 +1761,7 @@ key_spddelete(so, m, mhp)
/* make secindex */
/* XXX boundary check against sa_len */
KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir,
src0 + 1,
KEY_SETSECSPIDX(src0 + 1,
dst0 + 1,
src0->sadb_address_prefixlen,
dst0->sadb_address_prefixlen,
@ -1784,7 +1779,7 @@ key_spddelete(so, m, mhp)
}
/* Is there SP in SPD ? */
if ((sp = key_getsp(&spidx)) == NULL) {
if ((sp = key_getsp(&spidx, xpl0->sadb_x_policy_dir)) == NULL) {
ipseclog((LOG_DEBUG, "key_spddelete: no SP found.\n"));
return key_senderror(so, m, EINVAL);
}
@ -2000,7 +1995,7 @@ key_spdacquire(sp)
panic("key_spdacquire: policy mismathed. IPsec is expected.\n");
/* get a entry to check whether sent message or not. */
if ((newspacq = key_getspacq(&sp->spidx)) != NULL) {
if ((newspacq = key_getspacq(sp->spidx)) != NULL) {
if (key_blockacq_count < newspacq->count) {
/* reset counter and do send message. */
newspacq->count = 0;
@ -2011,7 +2006,7 @@ key_spdacquire(sp)
}
} else {
/* make new entry for blocking to send SADB_ACQUIRE. */
if ((newspacq = key_newspacq(&sp->spidx)) == NULL)
if ((newspacq = key_newspacq(sp->spidx)) == NULL)
return ENOBUFS;
/* add to acqtree */
@ -2166,15 +2161,15 @@ key_setdumpsp(sp, type, seq, pid)
result = m;
m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
(struct sockaddr *)&sp->spidx.src, sp->spidx.prefs,
sp->spidx.ul_proto);
(struct sockaddr *)&sp->spidx->src, sp->spidx->prefs,
sp->spidx->ul_proto);
if (!m)
goto fail;
m_cat(result, m);
m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
(struct sockaddr *)&sp->spidx.dst, sp->spidx.prefd,
sp->spidx.ul_proto);
(struct sockaddr *)&sp->spidx->dst, sp->spidx->prefd,
sp->spidx->ul_proto);
if (!m)
goto fail;
m_cat(result, m);
@ -2317,8 +2312,8 @@ key_spdexpire(sp)
/* set sadb_address for source */
m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
(struct sockaddr *)&sp->spidx.src,
sp->spidx.prefs, sp->spidx.ul_proto);
(struct sockaddr *)&sp->spidx->src,
sp->spidx->prefs, sp->spidx->ul_proto);
if (!m) {
error = ENOBUFS;
goto fail;
@ -2327,8 +2322,8 @@ key_spdexpire(sp)
/* set sadb_address for destination */
m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
(struct sockaddr *)&sp->spidx.dst,
sp->spidx.prefd, sp->spidx.ul_proto);
(struct sockaddr *)&sp->spidx->dst,
sp->spidx->prefd, sp->spidx->ul_proto);
if (!m) {
error = ENOBUFS;
goto fail;
@ -3828,9 +3823,8 @@ key_cmpspidx_exactly(spidx0, spidx1)
if (spidx0 == NULL || spidx1 == NULL)
return 0;
if (spidx0->prefs != spidx1->prefs
|| spidx0->prefd != spidx1->prefd
|| spidx0->ul_proto != spidx1->ul_proto)
if (spidx0->prefs != spidx1->prefs || spidx0->prefd != spidx1->prefd ||
spidx0->ul_proto != spidx1->ul_proto)
return 0;
if (key_sockaddrcmp((struct sockaddr *)&spidx0->src,
@ -5733,7 +5727,7 @@ key_acquire(saidx, sp)
/* set sadb_x_policy */
if (sp) {
m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id);
m = key_setsadbxpolicy(sp->policy, sp->dir, sp->id);
if (!m) {
error = ENOBUFS;
goto fail;
@ -5892,6 +5886,9 @@ key_newspacq(spidx)
{
struct secspacq *acq;
if (!spidx)
return NULL;
/* get new entry */
KMALLOC(acq, struct secspacq *, sizeof(struct secspacq));
if (acq == NULL) {
@ -5914,6 +5911,9 @@ key_getspacq(spidx)
{
struct secspacq *acq;
if (!spidx)
return NULL;
LIST_FOREACH(acq, &spacqtree, chain) {
if (key_cmpspidx_exactly(spidx, &acq->spidx))
return acq;

View File

@ -1,4 +1,4 @@
/* $NetBSD: key_debug.c,v 1.20 2001/11/15 09:48:29 lukem Exp $ */
/* $NetBSD: key_debug.c,v 1.21 2002/06/12 01:47:37 itojun Exp $ */
/* $KAME: key_debug.c,v 1.29 2001/08/16 14:25:41 itojun Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: key_debug.c,v 1.20 2001/11/15 09:48:29 lukem Exp $");
__KERNEL_RCSID(0, "$NetBSD: key_debug.c,v 1.21 2002/06/12 01:47:37 itojun Exp $");
#ifdef _KERNEL
#include "opt_inet.h"
@ -466,10 +466,11 @@ kdebug_secpolicy(sp)
if (sp == NULL)
panic("kdebug_secpolicy: NULL pointer was passed.\n");
printf("secpolicy{ refcnt=%u state=%u policy=%u\n",
sp->refcnt, sp->state, sp->policy);
printf("secpolicy{ refcnt=%u state=%u policy=%u dir=%u\n",
sp->refcnt, sp->state, sp->policy, sp->dir);
kdebug_secpolicyindex(&sp->spidx);
if (sp->spidx)
kdebug_secpolicyindex(sp->spidx);
switch (sp->policy) {
case IPSEC_POLICY_DISCARD:
@ -515,8 +516,8 @@ kdebug_secpolicyindex(spidx)
if (spidx == NULL)
panic("kdebug_secpolicyindex: NULL pointer was passed.\n");
printf("secpolicyindex{ dir=%u prefs=%u prefd=%u ul_proto=%u\n",
spidx->dir, spidx->prefs, spidx->prefd, spidx->ul_proto);
printf("secpolicyindex{ prefs=%u prefd=%u ul_proto=%u\n",
spidx->prefs, spidx->prefd, spidx->ul_proto);
ipsec_hexdump((caddr_t)&spidx->src,
((struct sockaddr *)&spidx->src)->sa_len);

View File

@ -1,4 +1,4 @@
/* $NetBSD: keydb.c,v 1.6 2002/03/01 04:16:38 itojun Exp $ */
/* $NetBSD: keydb.c,v 1.7 2002/06/12 01:47:37 itojun Exp $ */
/* $KAME: keydb.c,v 1.64 2000/05/11 17:02:30 itojun Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: keydb.c,v 1.6 2002/03/01 04:16:38 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: keydb.c,v 1.7 2002/06/12 01:47:37 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -77,9 +77,26 @@ keydb_delsecpolicy(p)
struct secpolicy *p;
{
if (p->spidx)
free(p->spidx, M_SECA);
free(p, M_SECA);
}
int
keydb_setsecpolicyindex(p, idx)
struct secpolicy *p;
struct secpolicyindex *idx;
{
if (!p->spidx)
p->spidx = (struct secpolicyindex *)malloc(sizeof(*p->spidx),
M_SECA, M_NOWAIT);
if (!p->spidx)
return ENOMEM;
memcpy(p->spidx, idx, sizeof(*p->spidx));
return 0;
}
/*
* secashead management
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: keydb.h,v 1.9 2000/09/22 16:55:04 itojun Exp $ */
/* $NetBSD: keydb.h,v 1.10 2002/06/12 01:47:37 itojun Exp $ */
/* $KAME: keydb.h,v 1.14 2000/08/02 17:58:26 sakane Exp $ */
/*
@ -139,8 +139,12 @@ struct key_cb {
};
/* secpolicy */
struct secpolicy;
struct secpolicyindex;
extern struct secpolicy *keydb_newsecpolicy __P((void));
extern void keydb_delsecpolicy __P((struct secpolicy *));
extern int keydb_setsecpolicyindex
__P((struct secpolicy *, struct secpolicyindex *));
/* secashead */
extern struct secashead *keydb_newsecashead __P((void));
extern void keydb_delsecashead __P((struct secashead *));