child-sa: Install "outbound" FWD policy
authorTobias Brunner <tobias@strongswan.org>
Fri, 1 Apr 2016 14:41:05 +0000 (16:41 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 9 Apr 2016 14:51:00 +0000 (16:51 +0200)
If there is a DROP shunt that matches outbound forwarded traffic it
would get dropped as the FWD policy we install only matches decrypted
inbound traffic.  That's because the Linux kernel first checks the FWD
policies before looking up the OUT policy and SA to encrypt the packets.

src/libcharon/sa/child_sa.c

index 9c1808b..05d42ba 100644 (file)
@@ -915,6 +915,17 @@ static status_t install_policies_internal(private_child_sa_t *this,
        {
                in_id.dir = POLICY_FWD;
                status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
        {
                in_id.dir = POLICY_FWD;
                status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
+
+               /* install an "outbound" FWD policy in case there is a drop policy
+                * matching outbound forwarded traffic, to allow another tunnel to use
+                * the reversed subnets and do the same we don't set a reqid (this also
+                * allows the kernel backend to distinguish between the two types of
+                * FWD policies) */
+               out_id.dir = POLICY_FWD;
+               other_sa->reqid = 0;
+               status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
+               /* reset the reqid for any other further policies */
+               other_sa->reqid = this->reqid;
        }
        return status;
 }
        }
        return status;
 }
@@ -958,6 +969,11 @@ static void del_policies_internal(private_child_sa_t *this,
        {
                in_id.dir = POLICY_FWD;
                charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
        {
                in_id.dir = POLICY_FWD;
                charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
+
+               out_id.dir = POLICY_FWD;
+               other_sa->reqid = 0;
+               charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
+               other_sa->reqid = this->reqid;
        }
 }
 
        }
 }