- cleanup SP refcnt issue.

- share policy-on-socket for listening socket.
- don't copy policy-on-socket at all.  secpolicy no longer contain
  spidx, which saves a lot of memory.
- 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.
- fixed the order of searching SA table for packets.
- fixed to get a security association header.  a mode is always needed
  to compare them.
- fixed that the incorrect time was set to
  sadb_comb_{hard|soft}_usetime.
- disallow port spec for tunnel mode policy (as we don't reassemble).
- an user can define a policy-id.
- clear enc/auth key before freeing.
- fixed that the kernel crashed when key_spdacquire() was called
  because key_spdacquire() had been implemented imcopletely.
- preparation for 64bit sequence number.
- maintain ordered list of SA, based on SA id.
- cleanup secasvar management; refcnt is key.c responsibility;
  alloc/free is keydb.c responsibility.
- cleanup, avoid double-loop.
- use hash for spi-based lookup.
- mark persistent SP "persistent".
  XXX in theory refcnt should do the right thing, however, we have
  "spdflush" which would touch all SPs.  another solution would be to
  de-register persistent SPs from sptree.
- u_short -> u_int16_t
- reduce kernel stack usage by auto variable secasindex.
- clarify function name confusion.  ipsec_*_policy ->
  ipsec_*_pcbpolicy.
- avoid variable name confusion.
  (struct inpcbpolicy *)pcb_sp, spp (struct secpolicy **), sp (struct
  secpolicy *)
- count number of ipsec encapsulations on ipsec4_output, so that we
  can tell ip_output() how to handle the packet further.
- When the value of the ul_proto is ICMP or ICMPV6, the port field in
  "src" of the spidx specifies ICMP type, and the port field in "dst"
  of the spidx specifies ICMP code.
- avoid from applying IPsec transport mode to the packets when the
  kernel forwards the packets.

Tested by:	nork
Obtained from:	KAME
This commit is contained in:
Hajimu UMEMOTO 2003-11-04 16:02:05 +00:00
parent 7430623f55
commit 0f9ade718d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=122062
21 changed files with 1671 additions and 1097 deletions

View file

@ -79,7 +79,6 @@
#include <netipsec/ipsec.h>
#include <netipsec/key.h>
#define IPSEC
#endif /* FAST_IPSEC */
struct in_addr zeroin_addr;
@ -162,7 +161,7 @@ in_pcballoc(so, pcbinfo, td)
struct thread *td;
{
register struct inpcb *inp;
#ifdef IPSEC
#if defined(IPSEC) || defined(FAST_IPSEC)
int error;
#endif
inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT | M_ZERO);
@ -171,8 +170,12 @@ in_pcballoc(so, pcbinfo, td)
inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
inp->inp_pcbinfo = pcbinfo;
inp->inp_socket = so;
#ifdef IPSEC
#if defined(IPSEC) || defined(FAST_IPSEC)
#ifdef FAST_IPSEC
error = ipsec_init_policy(so, &inp->inp_sp);
#else
error = ipsec_init_pcbpolicy(so, &inp->inp_sp);
#endif
if (error != 0) {
uma_zfree(pcbinfo->ipi_zone, inp);
return error;
@ -473,6 +476,10 @@ in_pcbconnect(inp, nam, td)
inp->inp_faddr.s_addr = faddr;
inp->inp_fport = fport;
in_pcbrehash(inp);
#ifdef IPSEC
if (inp->inp_socket->so_type == SOCK_STREAM)
ipsec_pcbconn(inp->inp_sp);
#endif
if (anonport)
inp->inp_flags |= INP_ANONPORT;
return (0);
@ -655,6 +662,9 @@ in_pcbdisconnect(inp)
in_pcbrehash(inp);
if (inp->inp_socket->so_state & SS_NOFDREF)
in_pcbdetach(inp);
#ifdef IPSEC
ipsec_pcbdisconn(inp->inp_sp);
#endif
}
void
@ -664,7 +674,7 @@ in_pcbdetach(inp)
struct socket *so = inp->inp_socket;
struct inpcbinfo *ipi = inp->inp_pcbinfo;
#ifdef IPSEC
#if defined(IPSEC) || defined(FAST_IPSEC)
ipsec4_delete_pcbpolicy(inp);
#endif /*IPSEC*/
inp->inp_gencnt = ++ipi->ipi_gencnt;

View file

@ -492,7 +492,7 @@ ip_input(struct mbuf *m)
/*
* Bypass packet filtering for packets from a tunnel (gif).
*/
if (ipsec_gethist(m, NULL))
if (ipsec_getnhist(m))
goto pass;
#endif
#if defined(FAST_IPSEC) && !defined(IPSEC_FILTERGIF)

View file

@ -144,6 +144,7 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
struct in_addr pkt_dst;
#ifdef IPSEC
struct route iproute;
struct socket *so;
struct secpolicy *sp = NULL;
#endif
#ifdef FAST_IPSEC
@ -195,6 +196,11 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
}
m = m0;
#ifdef IPSEC
so = ipsec_getsocket(m);
(void)ipsec_setsocket(m, NULL);
#endif /*IPSEC*/
M_ASSERTPKTHDR(m);
#ifndef FAST_IPSEC
KASSERT(ro != NULL, ("ip_output: no route, proto %d",
@ -488,10 +494,11 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
sendit:
#ifdef IPSEC
/* get SP for this packet */
if (inp == NULL)
sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error);
if (so == NULL)
sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND,
flags, &error);
else
sp = ipsec4_getpolicybypcb(m, IPSEC_DIR_OUTBOUND, inp, &error);
sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
if (sp == NULL) {
ipsecstat.out_inval++;

View file

@ -880,6 +880,13 @@ tcp_output(struct tcpcb *tp)
: NULL);
/* TODO: IPv6 IP6TOS_ECT bit on */
#ifdef IPSEC
if (ipsec_setsocket(m, so) != 0) {
m_freem(m);
error = ENOBUFS;
goto out;
}
#endif /*IPSEC*/
error = ip6_output(m,
tp->t_inpcb->in6p_outputopts,
&tp->t_inpcb->in6p_route,

View file

@ -96,7 +96,6 @@
#include <netipsec/ipsec6.h>
#endif
#include <netipsec/key.h>
#define IPSEC
#endif /*FAST_IPSEC*/
#include <machine/in_cksum.h>
@ -620,6 +619,11 @@ syncache_socket(sc, lso, m)
goto abort;
}
#ifdef IPSEC
/* copy old policy into new socket's */
if (ipsec_copy_pcbpolicy(sotoinpcb(lso)->inp_sp, inp->inp_sp))
printf("syncache_expand: could not copy policy\n");
#endif
#ifdef FAST_IPSEC
/* copy old policy into new socket's */
if (ipsec_copy_policy(sotoinpcb(lso)->inp_sp, inp->inp_sp))
printf("syncache_expand: could not copy policy\n");

View file

@ -109,7 +109,6 @@
#ifdef FAST_IPSEC
#include <netipsec/ipsec.h>
#include <netipsec/key.h>
#define IPSEC
#endif
#include <net/net_osdep.h>
@ -2218,6 +2217,10 @@ icmp6_reflect(m, off)
*/
m->m_flags &= ~(M_BCAST|M_MCAST);
#ifdef IPSEC
/* Don't lookup socket */
(void)ipsec_setsocket(m, NULL);
#endif /* IPSEC */
#ifdef COMPAT_RFC1885
ip6_output(m, NULL, &icmp6_reflect_rt, 0, NULL, &outif, NULL);
@ -2441,7 +2444,7 @@ icmp6_redirect_input(m, off)
sdst.sin6_len = sizeof(struct sockaddr_in6);
bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
#ifdef IPSEC
#if defined(IPSEC) || defined(FAST_IPSEC)
key_sa_routechange((struct sockaddr *)&sdst);
#endif
}
@ -2725,6 +2728,10 @@ noredhdropt:;
sizeof(*ip6), ntohs(ip6->ip6_plen));
/* send the packet to outside... */
#ifdef IPSEC
/* Don't lookup socket */
(void)ipsec_setsocket(m, NULL);
#endif /* IPSEC */
ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
if (outif) {
icmp6_ifstat_inc(outif, ifs6_out_msg);

View file

@ -109,14 +109,15 @@ ip6_forward(m, srcrt)
int srcrt;
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct sockaddr_in6 *dst;
struct rtentry *rt;
struct sockaddr_in6 *dst = NULL;
struct rtentry *rt = NULL;
int error, type = 0, code = 0;
struct mbuf *mcopy = NULL;
struct ifnet *origifp; /* maybe unnecessary */
u_int32_t srczone, dstzone;
#ifdef IPSEC
struct secpolicy *sp = NULL;
int ipsecrt = 0;
#endif
#ifdef IPSEC
@ -253,8 +254,23 @@ ip6_forward(m, srcrt)
}
{
struct ipsecrequest *isr = NULL;
struct ipsec_output_state state;
/*
* when the kernel forwards a packet, it is not proper to apply
* IPsec transport mode to the packet is not proper. this check
* avoid from this.
* at present, if there is even a transport mode SA request in the
* security policy, the kernel does not apply IPsec to the packet.
* this check is not enough because the following case is valid.
* ipsec esp/tunnel/xxx-xxx/require esp/transport//require;
*/
for (isr = sp->req; isr; isr = isr->next) {
if (isr->saidx.mode == IPSEC_MODE_TRANSPORT)
goto skip_ipsec;
}
/*
* All the extension headers will become inaccessible
* (since they can be encrypted).
@ -300,10 +316,22 @@ ip6_forward(m, srcrt)
m_freem(m);
return;
}
/* adjust pointer */
ip6 = mtod(m, struct ip6_hdr *);
dst = (struct sockaddr_in6 *)state.dst;
rt = state.ro ? state.ro->ro_rt : NULL;
if (dst != NULL && rt != NULL)
ipsecrt = 1;
}
skip_ipsec:
#endif /* IPSEC */
#ifdef IPSEC
if (ipsecrt)
goto skip_routing;
#endif
dst = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
if (!srcrt) {
/* ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst */
@ -353,6 +381,9 @@ ip6_forward(m, srcrt)
}
}
rt = ip6_forward_rt.ro_rt;
#ifdef IPSEC
skip_routing:;
#endif
/*
* Scope check: if a packet can't be delivered to its destination
@ -362,8 +393,18 @@ ip6_forward(m, srcrt)
* [draft-ietf-ipngwg-icmp-v3-02.txt, Section 3.1]
*/
if (in6_addr2zoneid(m->m_pkthdr.rcvif, &ip6->ip6_src, &srczone) ||
in6_addr2zoneid(rt->rt_ifp, &ip6->ip6_src, &dstzone) ||
srczone != dstzone) {
in6_addr2zoneid(rt->rt_ifp, &ip6->ip6_src, &dstzone)) {
/* XXX: this should not happen */
ip6stat.ip6s_cantforward++;
ip6stat.ip6s_badscope++;
m_freem(m);
return;
}
if (srczone != dstzone
#ifdef IPSEC
&& !ipsecrt
#endif
) {
ip6stat.ip6s_cantforward++;
ip6stat.ip6s_badscope++;
in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);
@ -399,7 +440,7 @@ ip6_forward(m, srcrt)
#ifdef IPSEC
/*
* When we do IPsec tunnel ingress, we need to play
* with if_mtu value (decrement IPsec header size
* with the link value (decrement IPsec header size
* from mtu value). The code is much simpler than v4
* case, as we have the outgoing interface for
* encapsulated packet as "rt->rt_ifp".
@ -439,6 +480,9 @@ ip6_forward(m, srcrt)
* modified by a redirect.
*/
if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&
#ifdef IPSEC
!ipsecrt &&
#endif
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) != 0) {
/*

View file

@ -184,18 +184,21 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp, inp)
struct route_in6 *ro_pmtu = NULL;
int hdrsplit = 0;
int needipsec = 0;
#ifdef IPSEC
int needipsectun = 0;
struct secpolicy *sp = NULL;
ip6 = mtod(m, struct ip6_hdr *);
#endif /* IPSEC */
#ifdef FAST_IPSEC
int needipsectun = 0;
struct secpolicy *sp = NULL;
#endif /* FAST_IPSEC */
#ifdef IPSEC
int needipsectun = 0;
struct socket *so;
struct secpolicy *sp = NULL;
/* for AH processing. stupid to have "socket" variable in IP layer... */
so = ipsec_getsocket(m);
(void)ipsec_setsocket(m, NULL);
#endif /* IPSEC */
ip6 = mtod(m, struct ip6_hdr *);
#endif /* FAST_IPSEC */
#define MAKE_EXTHDR(hp, mp) \
do { \
@ -235,10 +238,10 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp, inp)
#ifdef IPSEC
/* get a security policy for this packet */
if (inp == NULL)
if (so == NULL)
sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
else
sp = ipsec6_getpolicybypcb(m, IPSEC_DIR_OUTBOUND, inp, &error);
sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
if (sp == NULL) {
ipsec6stat.out_inval++;

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* $FreeBSD$ */
/* $KAME: ipsec.h,v 1.53 2001/11/20 08:32:38 itojun Exp $ */
/* $KAME: ipsec.h,v 1.69 2003/09/10 23:49:11 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -54,7 +54,6 @@
* specifies ICMPv6 type, and the port field in "dst" specifies ICMPv6 code.
*/
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 */
@ -70,16 +69,26 @@ 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 */
int persist; /* will never be removed */
int refcnt; /* reference count */
struct secpolicyindex spidx; /* selector */
u_int32_t id; /* It's unique number on the system. */
struct secpolicyindex *spidx; /* selector - NULL if not valid */
u_int32_t id; /* it identifies a policy in the SPD. */
#define IPSEC_MANUAL_POLICYID_MAX 0x3fff
/*
* 1 - 0x3fff are reserved for user operation.
* 0 are reserved. Others are for kernel use.
*/
struct socket *so; /* backpointer to per-socket policy */
u_int state; /* 0: dead, others: alive */
#define IPSEC_SPSTATE_DEAD 0
#define IPSEC_SPSTATE_ALIVE 1
u_int policy; /* DISCARD, NONE or IPSEC, see keyv2.h */
int policy; /* DISCARD, NONE or IPSEC, see below */
struct ipsecrequest *req;
/* pointer to the ipsec request tree, */
/* if policy == IPSEC else this value == NULL.*/
@ -98,6 +107,7 @@ struct secpolicy {
};
/* Request for IPsec */
struct ifnet;
struct ipsecrequest {
struct ipsecrequest *next;
/* pointer to next structure */
@ -108,6 +118,8 @@ struct ipsecrequest {
struct secasvar *sav; /* place holder of SA for use */
struct secpolicy *sp; /* back pointer to SP */
struct ifnet *tunifp; /* interface for tunnelling */
};
/* security policy in PCB */
@ -115,6 +127,14 @@ struct inpcbpolicy {
struct secpolicy *sp_in;
struct secpolicy *sp_out;
int priv; /* privileged socket ? */
/* cached policy */
/* XXX 3 == IPSEC_DIR_MAX */
struct secpolicy *cache[3];
struct secpolicyindex cacheidx[3];
int cachegen[3]; /* cache generation #, the time we filled it */
int cacheflags;
#define IPSEC_PCBSP_CONNECTED 1
};
/* SP acquiring list table. */
@ -127,6 +147,14 @@ struct secspacq {
int count; /* for lifetime */
/* XXX: here is mbuf place holder to be sent ? */
};
struct ipsecaux {
struct socket *so;
int hdrs; /* # of ipsec headers */
struct secpolicy *sp;
struct ipsecrequest *req;
};
#endif /* _KERNEL */
/* according to IANA assignment, port 0x0000 and proto 0xff are reserved. */
@ -210,6 +238,9 @@ struct ipsecstat {
u_quad_t out_esphist[256];
u_quad_t out_ahhist[256];
u_quad_t out_comphist[256];
u_quad_t spdcachelookup;
u_quad_t spdcachemiss;
};
/*
@ -274,6 +305,7 @@ struct ipsec_output_state {
struct mbuf *m;
struct route *ro;
struct sockaddr *dst;
int encap;
};
struct ipsec_history {
@ -283,8 +315,9 @@ struct ipsec_history {
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;
@ -294,21 +327,26 @@ extern int ip4_ah_offsetmask;
extern int ip4_ipsec_dfbit;
extern int ip4_ipsec_ecn;
extern int ip4_esp_randpad;
#endif
#define ipseclog(x) do { if (ipsec_debug) log x; } while (/*CONSTCOND*/ 0)
struct inpcb;
extern struct secpolicy *ipsec4_getpolicybypcb
__P((struct mbuf *, u_int, struct inpcb *, int *));
extern int ipsec_pcbconn __P((struct inpcbpolicy *));
extern int ipsec_pcbdisconn __P((struct inpcbpolicy *));
extern int ipsec_invalpcbcacheall __P((void));
extern struct secpolicy *ipsec4_getpolicybysock
__P((struct mbuf *, u_int, struct socket *, int *));
extern struct secpolicy *ipsec4_getpolicybyaddr
__P((struct mbuf *, u_int, int, int *));
extern struct secpolicy *ipsec4_getpolicybytag
__P((struct mbuf *, u_int, int *));
extern int ipsec_init_policy __P((struct socket *, struct inpcbpolicy **));
extern int ipsec_copy_policy
struct inpcb;
extern int ipsec_init_pcbpolicy __P((struct socket *, 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 *, int, caddr_t, size_t, int));
extern int ipsec4_get_policy __P((struct inpcb *, caddr_t, size_t,
@ -319,6 +357,7 @@ extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *));
struct secas;
struct tcpcb;
struct tcp6cb;
extern int ipsec_chkreplay __P((u_int32_t, struct secasvar *));
extern int ipsec_updatereplay __P((u_int32_t, struct secasvar *));
@ -337,8 +376,13 @@ extern int ipsec4_tunnel_validate __P((struct mbuf *, int, u_int,
struct secasvar *));
extern struct mbuf *ipsec_copypkt __P((struct mbuf *));
extern void ipsec_delaux __P((struct mbuf *));
extern int ipsec_setsocket __P((struct mbuf *, struct socket *));
extern struct socket *ipsec_getsocket __P((struct mbuf *));
extern int ipsec_addhist __P((struct mbuf *, int, u_int32_t));
extern int ipsec_getnhist __P((struct mbuf *));
extern struct ipsec_history *ipsec_gethist __P((struct mbuf *, int *));
extern void ipsec_clearhist __P((struct mbuf *));
#endif /* _KERNEL */
#ifndef _KERNEL

View file

@ -42,7 +42,7 @@
#ifdef _KERNEL
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;
@ -51,8 +51,6 @@ extern int ip6_ipsec_ecn;
extern int ip6_esp_randpad;
struct inpcb;
extern struct secpolicy *ipsec6_getpolicybypcb
__P((struct mbuf *, u_int, struct inpcb *, int *));
extern struct secpolicy *ipsec6_getpolicybysock
__P((struct mbuf *, u_int, struct socket *, int *));
extern struct secpolicy *ipsec6_getpolicybyaddr
@ -60,10 +58,9 @@ extern struct secpolicy *ipsec6_getpolicybyaddr
extern int ipsec6_in_reject_so __P((struct mbuf *, struct socket *));
extern int ipsec6_delete_pcbpolicy __P((struct inpcb *));
extern int ipsec6_set_policy __P((struct inpcb *inp, int optname,
caddr_t request, size_t len, int priv));
extern int ipsec6_get_policy
__P((struct inpcb *inp, caddr_t request, size_t len, struct mbuf **mp));
extern int ipsec6_set_policy __P((struct inpcb *, int, caddr_t, size_t, int));
extern int ipsec6_get_policy __P((struct inpcb *, caddr_t, size_t,
struct mbuf **));
extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *));
struct tcp6cb;

View file

@ -1970,6 +1970,10 @@ nd6_output(ifp, origifp, m0, dst, rt0)
return (0);
sendpkt:
#ifdef IPSEC
/* clean ipsec history once it goes out of the node */
ipsec_delaux(m);
#endif
#ifdef MAC
mac_create_mbuf_linklayer(ifp, m);

View file

@ -487,6 +487,10 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
nd_ns->nd_ns_cksum =
in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
#ifdef IPSEC
/* Don't lookup socket */
(void)ipsec_setsocket(m, NULL);
#endif
ip6_output(m, NULL, NULL, dad ? IPV6_DADOUTPUT : 0, &im6o, &outif, NULL);
if (outif) {
icmp6_ifstat_inc(outif, ifs6_out_msg);
@ -928,6 +932,10 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
nd_na->nd_na_cksum =
in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
#ifdef IPSEC
/* Don't lookup socket */
(void)ipsec_setsocket(m, NULL);
#endif
ip6_output(m, NULL, NULL, 0, &im6o, &outif, NULL);
if (outif) {
icmp6_ifstat_inc(outif, ifs6_out_msg);

View file

@ -180,7 +180,7 @@ rip6_input(mp, offp, proto)
/*
* Check AH/ESP integrity.
*/
if (n && ipsec6_in_reject(n, last)) {
if (n && ipsec6_in_reject_so(n, last->inp_socket)) {
m_freem(n);
ipsec6stat.in_polvio++;
/* do not inject data into pcb */
@ -219,7 +219,7 @@ rip6_input(mp, offp, proto)
/*
* Check AH/ESP integrity.
*/
if (last && ipsec6_in_reject(m, last)) {
if (last && ipsec6_in_reject_so(m, last->inp_socket)) {
m_freem(m);
ipsec6stat.in_polvio++;
ip6stat.ip6s_delivered--;
@ -470,6 +470,13 @@ rip6_output(m, va_alist)
*p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen);
}
#ifdef IPSEC
if (ipsec_setsocket(m, so) != 0) {
error = ENOBUFS;
goto bad;
}
#endif /*IPSEC*/
error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route, 0,
in6p->in6p_moptions, &oifp, in6p);
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {

View file

@ -291,6 +291,12 @@ udp6_output(in6p, m, addr6, control, td)
flags = 0;
udp6stat.udp6s_opackets++;
#ifdef IPSEC
if (ipsec_setsocket(m, in6p->in6p_socket) != 0) {
error = ENOBUFS;
goto release;
}
#endif /* IPSEC */
error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route,
flags, in6p->in6p_moptions, NULL, in6p);
break;

View file

@ -261,7 +261,7 @@ udp6_input(mp, offp, proto)
/*
* Check AH/ESP integrity.
*/
if (ipsec6_in_reject(m, last))
if (ipsec6_in_reject_so(m, last->inp_socket))
ipsec6stat.in_polvio++;
/* do not inject data into pcb */
else
@ -327,7 +327,7 @@ udp6_input(mp, offp, proto)
/*
* Check AH/ESP integrity.
*/
if (ipsec6_in_reject(m, last)) {
if (ipsec6_in_reject_so(m, last->inp_socket)) {
ipsec6stat.in_polvio++;
goto bad;
}
@ -383,7 +383,7 @@ udp6_input(mp, offp, proto)
/*
* Check AH/ESP integrity.
*/
if (ipsec6_in_reject(m, in6p)) {
if (ipsec6_in_reject_so(m, in6p->inp_socket)) {
ipsec6stat.in_polvio++;
goto bad;
}

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* $FreeBSD$ */
/* $KAME: key.h,v 1.21 2001/07/27 03:51:30 itojun Exp $ */
/* $KAME: key.h,v 1.32 2003/09/07 05:25:20 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -35,8 +35,13 @@
#ifdef _KERNEL
#include <sys/queue.h>
extern struct key_cb key_cb;
extern TAILQ_HEAD(_satailq, secasvar) satailq;
extern TAILQ_HEAD(_sptailq, secpolicy) sptailq;
struct secpolicy;
struct secpolicyindex;
struct ipsecrequest;
@ -46,22 +51,24 @@ struct socket;
struct sadb_msg;
struct sadb_x_policy;
extern struct secpolicy *key_allocsp(struct secpolicyindex *, u_int);
extern struct secpolicy *key_allocsp(u_int16_t, struct secpolicyindex *,
u_int);
extern struct secpolicy *key_gettunnel(struct sockaddr *,
struct sockaddr *, struct sockaddr *, struct sockaddr *);
extern int key_checkrequest
(struct ipsecrequest *isr, struct secasindex *);
extern struct secasvar *key_allocsa(u_int, caddr_t, caddr_t, u_int, u_int32_t);
extern void key_freesp(struct secpolicy *);
extern void key_freeso(struct socket *);
extern void key_freesav(struct secasvar *);
extern struct secpolicy *key_newsp(void);
extern struct secpolicy *key_newsp(u_int32_t);
extern struct secpolicy *key_msg2sp(struct sadb_x_policy *, size_t, int *);
extern struct mbuf *key_sp2msg(struct secpolicy *);
extern int key_ismyaddr(struct sockaddr *);
extern int key_cmpspidx_exactly
(struct secpolicyindex *, struct secpolicyindex *);
extern int key_cmpspidx_withmask
(struct secpolicyindex *, struct secpolicyindex *);
extern int key_spdacquire(struct secpolicy *);
extern void key_timehandler(void);
extern u_long key_random(void);
extern void key_timehandler(void *);
extern void key_randomfill(void *, size_t);
extern void key_freereg(struct socket *);
extern int key_parse(struct mbuf *, struct socket *);

View file

@ -1,4 +1,4 @@
/* $KAME: key_debug.c,v 1.26 2001/06/27 10:46:50 sakane Exp $ */
/* $KAME: key_debug.c,v 1.38 2003/09/06 05:15:44 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -562,10 +562,11 @@ kdebug_secpolicy(sp)
if (sp == NULL)
panic("kdebug_secpolicy: NULL pointer was passed.");
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:
@ -611,8 +612,8 @@ kdebug_secpolicyindex(spidx)
if (spidx == NULL)
panic("kdebug_secpolicyindex: NULL pointer was passed.");
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);
@ -632,8 +633,7 @@ kdebug_secasindex(saidx)
if (saidx == NULL)
panic("kdebug_secpolicyindex: NULL pointer was passed.");
printf("secasindex{ mode=%u proto=%u\n",
saidx->mode, saidx->proto);
printf("secasindex{ mode=%u proto=%u\n", saidx->mode, saidx->proto);
ipsec_hexdump((caddr_t)&saidx->src,
((struct sockaddr *)&saidx->src)->sa_len);
@ -697,8 +697,9 @@ kdebug_secreplay(rpl)
if (rpl == NULL)
panic("kdebug_secreplay: NULL pointer was passed.");
printf(" secreplay{ count=%u wsize=%u seq=%u lastseq=%u",
rpl->count, rpl->wsize, rpl->seq, rpl->lastseq);
printf(" secreplay{ count=%llu wsize=%u seq=%llu lastseq=%llu",
(unsigned long long)rpl->count, rpl->wsize,
(unsigned long long)rpl->seq, (unsigned long long)rpl->lastseq);
if (rpl->bitmap == NULL) {
printf(" }\n");
@ -736,9 +737,9 @@ kdebug_mbufhdr(m)
if (m->m_flags & M_EXT) {
printf(" m_ext{ ext_buf:%p ext_free:%p "
"ext_size:%u ref_cnt:%p }\n",
"ext_size:%u }\n",
m->m_ext.ext_buf, m->m_ext.ext_free,
m->m_ext.ext_size, m->m_ext.ref_cnt);
m->m_ext.ext_size);
}
return;

View file

@ -1,4 +1,4 @@
/* $KAME: keydb.c,v 1.64 2000/05/11 17:02:30 itojun Exp $ */
/* $KAME: keydb.c,v 1.82 2003/09/07 07:47:33 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <net/pfkeyv2.h>
#include <netkey/keydb.h>
#include <netkey/key.h>
#include <netinet6/ipsec.h>
#include <net/net_osdep.h>
@ -69,17 +70,63 @@ keydb_newsecpolicy()
if (!p)
return p;
bzero(p, sizeof(*p));
TAILQ_INSERT_TAIL(&sptailq, p, tailq);
return p;
}
u_int32_t
keydb_newspid(void)
{
u_int32_t newid = 0;
static u_int32_t lastalloc = IPSEC_MANUAL_POLICYID_MAX;
struct secpolicy *sp;
newid = lastalloc + 1;
/* XXX possible infinite loop */
again:
TAILQ_FOREACH(sp, &sptailq, tailq) {
if (sp->id == newid)
break;
}
if (sp != NULL) {
if (newid + 1 < newid) /* wraparound */
newid = IPSEC_MANUAL_POLICYID_MAX + 1;
else
newid++;
goto again;
}
lastalloc = newid;
return newid;
}
void
keydb_delsecpolicy(p)
struct secpolicy *p;
{
TAILQ_REMOVE(&sptailq, p, tailq);
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
*/
@ -112,12 +159,36 @@ keydb_delsecashead(p)
struct secasvar *
keydb_newsecasvar()
{
struct secasvar *p;
struct secasvar *p, *q;
static u_int32_t said = 0;
p = (struct secasvar *)malloc(sizeof(*p), M_SECA, M_NOWAIT);
if (!p)
return p;
again:
said++;
if (said == 0)
said++;
TAILQ_FOREACH(q, &satailq, tailq) {
if (q->id == said)
goto again;
if (TAILQ_NEXT(q, tailq)) {
if (q->id < said && said < TAILQ_NEXT(q, tailq)->id)
break;
if (q->id + 1 < TAILQ_NEXT(q, tailq)->id) {
said = q->id + 1;
break;
}
}
}
bzero(p, sizeof(*p));
p->id = said;
if (q)
TAILQ_INSERT_AFTER(&satailq, q, p, tailq);
else
TAILQ_INSERT_TAIL(&satailq, p, tailq);
return p;
}
@ -126,6 +197,8 @@ keydb_delsecasvar(p)
struct secasvar *p;
{
TAILQ_REMOVE(&satailq, p, tailq);
free(p, M_SECA);
}
@ -144,7 +217,7 @@ keydb_newsecreplay(wsize)
bzero(p, sizeof(*p));
if (wsize != 0) {
p->bitmap = (caddr_t)malloc(wsize, M_SECA, M_NOWAIT);
p->bitmap = malloc(wsize, M_SECA, M_NOWAIT);
if (!p->bitmap) {
free(p, M_SECA);
return NULL;

View file

@ -1,5 +1,5 @@
/* $FreeBSD$ */
/* $KAME: keydb.h,v 1.14 2000/08/02 17:58:26 sakane Exp $ */
/* $KAME: keydb.h,v 1.24 2003/09/07 15:12:10 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -72,7 +72,9 @@ struct secashead {
/* Security Association */
struct secasvar {
TAILQ_ENTRY(secasvar) tailq;
LIST_ENTRY(secasvar) chain;
LIST_ENTRY(secasvar) spihash;
int refcnt; /* reference count */
u_int8_t state; /* Status of this Association */
@ -96,20 +98,22 @@ struct secasvar {
struct sadb_lifetime *lft_h; /* HARD lifetime */
struct sadb_lifetime *lft_s; /* SOFT lifetime */
u_int32_t seq; /* sequence number */
u_int64_t seq; /* sequence number */
pid_t pid; /* message's pid */
struct secashead *sah; /* back pointer to the secashead */
u_int32_t id; /* SA id */
};
/* replay prevention */
struct secreplay {
u_int32_t count;
u_int64_t count;
u_int wsize; /* window size, i.g. 4 bytes */
u_int32_t seq; /* used by sender */
u_int32_t lastseq; /* used by receiver */
caddr_t bitmap; /* used by receiver */
int overflow; /* overflow flag */
u_int64_t seq; /* used by sender */
u_int64_t lastseq; /* used by receiver */
u_int8_t *bitmap; /* used by receiver */
int overflow; /* what round does the counter take. */
};
/* socket table due to send PF_KEY messages. */
@ -143,8 +147,13 @@ struct key_cb {
};
/* secpolicy */
struct secpolicy;
struct secpolicyindex;
extern struct secpolicy *keydb_newsecpolicy(void);
extern u_int32_t keydb_newspid(void);
extern void keydb_delsecpolicy(struct secpolicy *);
extern int keydb_setsecpolicyindex
(struct secpolicy *, struct secpolicyindex *);
/* secashead */
extern struct secashead *keydb_newsecashead(void);
extern void keydb_delsecashead(struct secashead *);