deep-copy pcb policy if it is an ipsec policy. assign ID field to all

SPD entries.  make it possible for racoon to grab SPD entry on pcb
(racoon side needs some changes).  sync w/kame
This commit is contained in:
itojun 2002-06-12 17:56:45 +00:00
parent 9984a8bbcc
commit dc96111483
4 changed files with 98 additions and 94 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipsec.c,v 1.53 2002/06/12 01:47:34 itojun Exp $ */
/* $NetBSD: ipsec.c,v 1.54 2002/06/12 17:56:45 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.53 2002/06/12 01:47:34 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.54 2002/06/12 17:56:45 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -104,7 +104,7 @@ int ip4_esp_trans_deflev = IPSEC_LEVEL_USE;
int ip4_esp_net_deflev = IPSEC_LEVEL_USE;
int ip4_ah_trans_deflev = IPSEC_LEVEL_USE;
int ip4_ah_net_deflev = IPSEC_LEVEL_USE;
struct secpolicy ip4_def_policy;
struct secpolicy *ip4_def_policy;
int ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
static int sp_cachegen = 1; /* cache generation # */
@ -115,7 +115,7 @@ int ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
int ip6_esp_net_deflev = IPSEC_LEVEL_USE;
int ip6_ah_trans_deflev = IPSEC_LEVEL_USE;
int ip6_ah_net_deflev = IPSEC_LEVEL_USE;
struct secpolicy ip6_def_policy;
struct secpolicy *ip6_def_policy;
int ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
#endif /* INET6 */
@ -138,8 +138,8 @@ 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 *));
#endif
static struct secpolicy *ipsec_deepcopy_policy __P((struct secpolicy *));
static int ipsec_set_policy
__P((struct secpolicy **, int, caddr_t, size_t, int));
static int ipsec_get_policy __P((struct secpolicy *, struct mbuf **));
@ -405,10 +405,10 @@ ipsec4_getpolicybysock(m, dir, so, error)
}
/* no SP found */
ip4_def_policy.refcnt++;
ip4_def_policy->refcnt++;
*error = 0;
ipsec_fillpcbcache(pcbsp, m, &ip4_def_policy, dir);
return &ip4_def_policy;
ipsec_fillpcbcache(pcbsp, m, ip4_def_policy, dir);
return ip4_def_policy;
case IPSEC_POLICY_IPSEC:
currsp->refcnt++;
@ -448,10 +448,10 @@ ipsec4_getpolicybysock(m, dir, so, error)
return NULL;
case IPSEC_POLICY_ENTRUST:
ip4_def_policy.refcnt++;
ip4_def_policy->refcnt++;
*error = 0;
ipsec_fillpcbcache(pcbsp, m, &ip4_def_policy, dir);
return &ip4_def_policy;
ipsec_fillpcbcache(pcbsp, m, ip4_def_policy, dir);
return ip4_def_policy;
case IPSEC_POLICY_IPSEC:
currsp->refcnt++;
@ -517,9 +517,9 @@ ipsec4_getpolicybyaddr(m, dir, flag, error)
}
/* no SP found */
ip4_def_policy.refcnt++;
ip4_def_policy->refcnt++;
*error = 0;
return &ip4_def_policy;
return ip4_def_policy;
}
#ifdef INET6
@ -607,10 +607,10 @@ ipsec6_getpolicybysock(m, dir, so, error)
}
/* no SP found */
ip6_def_policy.refcnt++;
ip6_def_policy->refcnt++;
*error = 0;
ipsec_fillpcbcache(pcbsp, m, &ip6_def_policy, dir);
return &ip6_def_policy;
ipsec_fillpcbcache(pcbsp, m, ip6_def_policy, dir);
return ip6_def_policy;
case IPSEC_POLICY_IPSEC:
currsp->refcnt++;
@ -650,10 +650,10 @@ ipsec6_getpolicybysock(m, dir, so, error)
return NULL;
case IPSEC_POLICY_ENTRUST:
ip6_def_policy.refcnt++;
ip6_def_policy->refcnt++;
*error = 0;
ipsec_fillpcbcache(pcbsp, m, &ip6_def_policy, dir);
return &ip6_def_policy;
ipsec_fillpcbcache(pcbsp, m, ip6_def_policy, dir);
return ip6_def_policy;
case IPSEC_POLICY_IPSEC:
currsp->refcnt++;
@ -726,9 +726,9 @@ ipsec6_getpolicybyaddr(m, dir, flag, error)
}
/* no SP found */
ip6_def_policy.refcnt++;
ip6_def_policy->refcnt++;
*error = 0;
return &ip6_def_policy;
return ip6_def_policy;
}
#endif /* INET6 */
@ -1153,12 +1153,22 @@ ipsec_copy_pcbpolicy(old, new)
if (new->sp_in)
key_freesp(new->sp_in);
new->sp_in = old->sp_in;
new->sp_in->refcnt++;
if (old->sp_in->policy == IPSEC_POLICY_IPSEC)
new->sp_in = ipsec_deepcopy_policy(old->sp_in);
else {
new->sp_in = old->sp_in;
new->sp_in->refcnt++;
}
if (new->sp_out)
key_freesp(new->sp_out);
new->sp_out = old->sp_out;
new->sp_out->refcnt++;
if (old->sp_out->policy == IPSEC_POLICY_IPSEC)
new->sp_out = ipsec_deepcopy_policy(old->sp_out);
else {
new->sp_out = old->sp_out;
new->sp_out->refcnt++;
}
new->priv = old->priv;
return 0;
@ -1187,6 +1197,7 @@ ipsec_deepcopy_pcbpolicy(pcb_sp)
return 0;
}
#endif
/* deep-copy a policy in PCB */
static struct secpolicy *
@ -1230,6 +1241,9 @@ ipsec_deepcopy_policy(src)
q = &((*q)->next);
}
if (src->spidx)
keydb_setsecpolicyindex(dst, src->spidx);
dst->req = newchain;
dst->state = src->state;
dst->policy = src->policy;
@ -1243,9 +1257,9 @@ fail:
free(p, M_SECA);
p = NULL;
}
key_freesp(dst);
return NULL;
}
#endif
/* set policy and ipsec request if present. */
static int
@ -3596,7 +3610,7 @@ ipsec_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
&ipsecstat, sizeof(ipsecstat));
case IPSECCTL_DEF_POLICY:
return sysctl_int(oldp, oldlenp, newp, newlen,
&ip4_def_policy.policy);
&ip4_def_policy->policy);
case IPSECCTL_DEF_ESP_TRANSLEV:
if (newp != NULL)
ipsec_invalpcbcacheall();
@ -3698,7 +3712,7 @@ ipsec6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
&ipsec6stat, sizeof(ipsec6stat));
case IPSECCTL_DEF_POLICY:
return sysctl_int(oldp, oldlenp, newp, newlen,
&ip6_def_policy.policy);
&ip6_def_policy->policy);
case IPSECCTL_DEF_ESP_TRANSLEV:
if (newp != NULL)
ipsec_invalpcbcacheall();

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipsec.h,v 1.28 2002/06/12 01:47:35 itojun Exp $ */
/* $NetBSD: ipsec.h,v 1.29 2002/06/12 17:56:45 itojun Exp $ */
/* $KAME: ipsec.h,v 1.51 2001/08/05 04:52:58 itojun Exp $ */
/*
@ -69,7 +69,8 @@ struct secpolicyindex {
/* Security Policy Data Base */
struct secpolicy {
LIST_ENTRY(secpolicy) chain;
TAILQ_ENTRY(secpolicy) tailq; /* all SPD entries, both pcb/table */
LIST_ENTRY(secpolicy) chain; /* SPD entries on table */
u_int8_t dir; /* direction of packet flow */
int readonly; /* write prohibited */
@ -303,7 +304,7 @@ extern int ipsec_debug;
#ifdef INET
extern struct ipsecstat ipsecstat;
extern struct secpolicy ip4_def_policy;
extern struct secpolicy *ip4_def_policy;
extern int ip4_esp_trans_deflev;
extern int ip4_esp_net_deflev;
extern int ip4_ah_trans_deflev;
@ -316,7 +317,7 @@ extern int ip4_ipsec_ecn;
#ifdef INET6
extern struct ipsecstat ipsec6stat;
extern struct secpolicy ip6_def_policy;
extern struct secpolicy *ip6_def_policy;
extern int ip6_esp_trans_deflev;
extern int ip6_esp_net_deflev;
extern int ip6_ah_trans_deflev;

View File

@ -1,4 +1,4 @@
/* $NetBSD: key.c,v 1.69 2002/06/12 03:46:16 itojun Exp $ */
/* $NetBSD: key.c,v 1.70 2002/06/12 17:56:46 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.69 2002/06/12 03:46:16 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.70 2002/06/12 17:56:46 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -124,7 +124,6 @@ u_int32_t key_debug_level = 0;
static u_int key_spi_trycnt = 1000;
static u_int32_t key_spi_minval = 0x100;
static u_int32_t key_spi_maxval = 0x0fffffff; /* XXX */
static u_int32_t policy_id = 0;
static u_int key_int_random = 60; /*interval to initialize randseed,1(m)*/
static u_int key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/
static int key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/
@ -133,7 +132,8 @@ static int key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/
static u_int32_t acq_seq = 0;
static int key_tick_init_random = 0;
static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */
TAILQ_HEAD(_sptailq, secpolicy) sptailq; /* SPD table + pcb */
static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD table */
static LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */
static LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1];
/* registed list */
@ -312,7 +312,6 @@ static struct mbuf *key_gather_mbuf __P((struct mbuf *,
const struct sadb_msghdr *, int, int, ...));
static int key_spdadd __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
static u_int32_t key_getnewspid __P((void));
static int key_spddelete __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
static int key_spddelete2 __P((struct socket *, struct mbuf *,
@ -955,18 +954,7 @@ key_getspbyid(id)
{
struct secpolicy *sp;
LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) {
if (sp->state == IPSEC_SPSTATE_DEAD)
continue;
if (sp->id == id) {
sp->refcnt++;
return sp;
}
}
LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) {
if (sp->state == IPSEC_SPSTATE_DEAD)
continue;
TAILQ_FOREACH(sp, &sptailq, tailq) {
if (sp->id == id) {
sp->refcnt++;
return sp;
@ -1503,11 +1491,6 @@ key_spdadd(so, m, mhp)
return key_senderror(so, m, error);
}
if ((newsp->id = key_getnewspid()) == 0) {
keydb_delsecpolicy(newsp);
return key_senderror(so, m, ENOBUFS);
}
error = keydb_setsecpolicyindex(newsp, &spidx);
if (error) {
keydb_delsecpolicy(newsp);
@ -1612,37 +1595,6 @@ key_spdadd(so, m, mhp)
}
}
/*
* get new policy id.
* OUT:
* 0: failure.
* others: success.
*/
static u_int32_t
key_getnewspid()
{
u_int32_t newid = 0;
int count = key_spi_trycnt; /* XXX */
struct secpolicy *sp;
/* when requesting to allocate spi ranged */
while (count--) {
newid = (policy_id = (policy_id == ~0 ? 1 : policy_id + 1));
if ((sp = key_getspbyid(newid)) == NULL)
break;
key_freesp(sp);
}
if (count == 0 || newid == 0) {
ipseclog((LOG_DEBUG, "key_getnewspid: to allocate policy id is failed.\n"));
return 0;
}
return newid;
}
/*
* SADB_SPDDELETE processing
* receive
@ -2083,6 +2035,9 @@ key_setdumpsp(sp, type, seq, pid)
{
struct mbuf *result = NULL, *m;
if (!sp->spidx)
panic("policy-on-pcb to key_setdumpsp");
m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt);
if (!m)
goto fail;
@ -2193,6 +2148,9 @@ key_spdexpire(sp)
int error = -1;
struct sadb_lifetime *lt;
if (!sp->spidx)
panic("policy-on-pcb to key_spdexpire");
/* XXX: Why do we lock ? */
#ifdef __NetBSD__
s = splsoftnet(); /*called from softclock()*/
@ -7028,16 +6986,22 @@ key_init()
#endif
LIST_INIT(&spacqtree);
TAILQ_INIT(&sptailq);
/* system default */
#ifdef INET
ip4_def_policy.policy = IPSEC_POLICY_NONE;
ip4_def_policy.refcnt++; /*never reclaim this*/
ip4_def_policy.readonly = 1;
ip4_def_policy = key_newsp();
if (!ip4_def_policy)
panic("could not initialize IPv4 default security policy");
ip4_def_policy->policy = IPSEC_POLICY_NONE;
ip4_def_policy->readonly = 1;
#endif
#ifdef INET6
ip6_def_policy.policy = IPSEC_POLICY_NONE;
ip6_def_policy.refcnt++; /*never reclaim this*/
ip6_def_policy.readonly = 1;
ip6_def_policy = key_newsp();
if (!ip6_def_policy)
panic("could not initialize IPv6 default security policy");
ip6_def_policy->policy = IPSEC_POLICY_NONE;
ip6_def_policy->readonly = 1;
#endif
callout_reset(&key_timehandler_ch, hz, key_timehandler, (void *)0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: keydb.c,v 1.7 2002/06/12 01:47:37 itojun Exp $ */
/* $NetBSD: keydb.c,v 1.8 2002/06/12 17:56:46 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.7 2002/06/12 01:47:37 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: keydb.c,v 1.8 2002/06/12 17:56:46 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -55,6 +55,8 @@ __KERNEL_RCSID(0, "$NetBSD: keydb.c,v 1.7 2002/06/12 01:47:37 itojun Exp $");
#include <net/net_osdep.h>
extern TAILQ_HEAD(_sptailq, secpolicy) sptailq;
static void keydb_delsecasvar __P((struct secasvar *));
/*
@ -63,12 +65,34 @@ static void keydb_delsecasvar __P((struct secasvar *));
struct secpolicy *
keydb_newsecpolicy()
{
struct secpolicy *p;
struct secpolicy *p, *np;
p = (struct secpolicy *)malloc(sizeof(*p), M_SECA, M_NOWAIT);
if (!p)
return p;
bzero(p, sizeof(*p));
if (TAILQ_EMPTY(&sptailq)) {
p->id = 1;
TAILQ_INSERT_HEAD(&sptailq, p, tailq);
return p;
} else if (TAILQ_LAST(&sptailq, _sptailq)->id < 0xffffffff) {
p->id = TAILQ_LAST(&sptailq, _sptailq)->id + 1;
TAILQ_INSERT_TAIL(&sptailq, p, tailq);
return p;
} else {
TAILQ_FOREACH(np, &sptailq, tailq) {
if (np->id + 1 != TAILQ_NEXT(np, tailq)->id) {
p->id = np->id + 1;
TAILQ_INSERT_AFTER(&sptailq, np, p, tailq);
break;
}
}
if (!np) {
free(p, M_SECA);
return NULL;
}
}
return p;
}
@ -77,6 +101,7 @@ keydb_delsecpolicy(p)
struct secpolicy *p;
{
TAILQ_REMOVE(&sptailq, p, tailq);
if (p->spidx)
free(p->spidx, M_SECA);
free(p, M_SECA);