summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ip6_forward.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2003-11-04 16:02:05 +0000
committerume <ume@FreeBSD.org>2003-11-04 16:02:05 +0000
commit373abd94036be0e5643f5134aa9fb8bb694d1624 (patch)
treefdad404b77778d90d4bdccd4cb96415d0821c8d5 /sys/netinet6/ip6_forward.c
parentb5882bdf826f86fe99c8ba32265622dcc6139367 (diff)
downloadFreeBSD-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.c54
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) {
/*
OpenPOWER on IntegriCloud