ipv4: Implement IP_TRANSPARENT socket option
authorKOVACS Krisztian <hidden@sch.bme.hu>
Wed, 1 Oct 2008 14:30:02 +0000 (07:30 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 1 Oct 2008 14:30:02 +0000 (07:30 -0700)
This patch introduces the IP_TRANSPARENT socket option: enabling that
will make the IPv4 routing omit the non-local source address check on
output. Setting IP_TRANSPARENT requires NET_ADMIN capability.

Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/in.h
include/net/inet_sock.h
include/net/inet_timewait_sock.h
net/ipv4/inet_timewait_sock.c
net/ipv4/ip_sockglue.c

index 4065313cd7eee7f3a287d3cd0629ffcb726041f1..db458beef19dabe156b52eecab7bd30e11a7e5f9 100644 (file)
@@ -75,6 +75,7 @@ struct in_addr {
 #define IP_IPSEC_POLICY        16
 #define IP_XFRM_POLICY 17
 #define IP_PASSSEC     18
+#define IP_TRANSPARENT 19
 
 /* BSD compatibility */
 #define IP_RECVRETOPTS IP_RETOPTS
index 643e26be058ef2e91640fa59c1ac1e42df6e8590..e97b66e2a9d0e3384a28e00418d974bbb41ef5ce 100644 (file)
@@ -129,7 +129,8 @@ struct inet_sock {
                                is_icsk:1,
                                freebind:1,
                                hdrincl:1,
-                               mc_loop:1;
+                               mc_loop:1,
+                               transparent:1;
        int                     mc_index;
        __be32                  mc_addr;
        struct ip_mc_socklist   *mc_list;
index 91324908fccd367953bcce47aeb537afbd242f2e..80e4977631b8b18ba67e44024895fee03adbe7f9 100644 (file)
@@ -128,7 +128,8 @@ struct inet_timewait_sock {
        __be16                  tw_dport;
        __u16                   tw_num;
        /* And these are ours. */
-       __u8                    tw_ipv6only:1;
+       __u8                    tw_ipv6only:1,
+                               tw_transparent:1;
        /* 15 bits hole, try to pack */
        __u16                   tw_ipv6_offset;
        unsigned long           tw_ttd;
index 743f011b9a84189bd9284721e4a1ac2a704e68b8..1c5fd38f8824a9a58cafc9220773b134c4a4b771 100644 (file)
@@ -126,6 +126,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
                tw->tw_reuse        = sk->sk_reuse;
                tw->tw_hash         = sk->sk_hash;
                tw->tw_ipv6only     = 0;
+               tw->tw_transparent  = inet->transparent;
                tw->tw_prot         = sk->sk_prot_creator;
                twsk_net_set(tw, hold_net(sock_net(sk)));
                atomic_set(&tw->tw_refcnt, 1);
index 105d92a039b931c0bc485503cc913057eb3b96e1..465abf0a9869c768ab7b7f0832050a2a0812f05c 100644 (file)
@@ -419,7 +419,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
                             (1<<IP_TTL) | (1<<IP_HDRINCL) |
                             (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
                             (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
-                            (1<<IP_PASSSEC))) ||
+                            (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT))) ||
            optname == IP_MULTICAST_TTL ||
            optname == IP_MULTICAST_LOOP) {
                if (optlen >= sizeof(int)) {
@@ -878,6 +878,16 @@ static int do_ip_setsockopt(struct sock *sk, int level,
                err = xfrm_user_policy(sk, optname, optval, optlen);
                break;
 
+       case IP_TRANSPARENT:
+               if (!capable(CAP_NET_ADMIN)) {
+                       err = -EPERM;
+                       break;
+               }
+               if (optlen < 1)
+                       goto e_inval;
+               inet->transparent = !!val;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -1130,6 +1140,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
        case IP_FREEBIND:
                val = inet->freebind;
                break;
+       case IP_TRANSPARENT:
+               val = inet->transparent;
+               break;
        default:
                release_sock(sk);
                return -ENOPROTOOPT;