diff options
author | ume <ume@FreeBSD.org> | 2003-11-04 16:02:05 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2003-11-04 16:02:05 +0000 |
commit | 373abd94036be0e5643f5134aa9fb8bb694d1624 (patch) | |
tree | fdad404b77778d90d4bdccd4cb96415d0821c8d5 /sys/netinet6/ip6_forward.c | |
parent | b5882bdf826f86fe99c8ba32265622dcc6139367 (diff) | |
download | FreeBSD-src-373abd94036be0e5643f5134aa9fb8bb694d1624.zip FreeBSD-src-373abd94036be0e5643f5134aa9fb8bb694d1624.tar.gz |
- 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
Diffstat (limited to 'sys/netinet6/ip6_forward.c')
-rw-r--r-- | sys/netinet6/ip6_forward.c | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index 7e847e9..4f2a35c 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -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,9 +254,24 @@ 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). * Don't panic, we need no more updates to extension headers @@ -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) { /* |