ipv4: Implement IP_TRANSPARENT socket option

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>
This commit is contained in:
KOVACS Krisztian 2008-10-01 07:30:02 -07:00 коммит произвёл David S. Miller
Родитель a210d01ae3
Коммит f5715aea45
5 изменённых файлов: 20 добавлений и 3 удалений

Просмотреть файл

@ -75,6 +75,7 @@ struct in_addr {
#define IP_IPSEC_POLICY 16 #define IP_IPSEC_POLICY 16
#define IP_XFRM_POLICY 17 #define IP_XFRM_POLICY 17
#define IP_PASSSEC 18 #define IP_PASSSEC 18
#define IP_TRANSPARENT 19
/* BSD compatibility */ /* BSD compatibility */
#define IP_RECVRETOPTS IP_RETOPTS #define IP_RECVRETOPTS IP_RETOPTS

Просмотреть файл

@ -129,7 +129,8 @@ struct inet_sock {
is_icsk:1, is_icsk:1,
freebind:1, freebind:1,
hdrincl:1, hdrincl:1,
mc_loop:1; mc_loop:1,
transparent:1;
int mc_index; int mc_index;
__be32 mc_addr; __be32 mc_addr;
struct ip_mc_socklist *mc_list; struct ip_mc_socklist *mc_list;

Просмотреть файл

@ -128,7 +128,8 @@ struct inet_timewait_sock {
__be16 tw_dport; __be16 tw_dport;
__u16 tw_num; __u16 tw_num;
/* And these are ours. */ /* And these are ours. */
__u8 tw_ipv6only:1; __u8 tw_ipv6only:1,
tw_transparent:1;
/* 15 bits hole, try to pack */ /* 15 bits hole, try to pack */
__u16 tw_ipv6_offset; __u16 tw_ipv6_offset;
unsigned long tw_ttd; unsigned long tw_ttd;

Просмотреть файл

@ -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_reuse = sk->sk_reuse;
tw->tw_hash = sk->sk_hash; tw->tw_hash = sk->sk_hash;
tw->tw_ipv6only = 0; tw->tw_ipv6only = 0;
tw->tw_transparent = inet->transparent;
tw->tw_prot = sk->sk_prot_creator; tw->tw_prot = sk->sk_prot_creator;
twsk_net_set(tw, hold_net(sock_net(sk))); twsk_net_set(tw, hold_net(sock_net(sk)));
atomic_set(&tw->tw_refcnt, 1); atomic_set(&tw->tw_refcnt, 1);

Просмотреть файл

@ -419,7 +419,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
(1<<IP_TTL) | (1<<IP_HDRINCL) | (1<<IP_TTL) | (1<<IP_HDRINCL) |
(1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
(1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) | (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
(1<<IP_PASSSEC))) || (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT))) ||
optname == IP_MULTICAST_TTL || optname == IP_MULTICAST_TTL ||
optname == IP_MULTICAST_LOOP) { optname == IP_MULTICAST_LOOP) {
if (optlen >= sizeof(int)) { 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); err = xfrm_user_policy(sk, optname, optval, optlen);
break; break;
case IP_TRANSPARENT:
if (!capable(CAP_NET_ADMIN)) {
err = -EPERM;
break;
}
if (optlen < 1)
goto e_inval;
inet->transparent = !!val;
break;
default: default:
err = -ENOPROTOOPT; err = -ENOPROTOOPT;
break; break;
@ -1130,6 +1140,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
case IP_FREEBIND: case IP_FREEBIND:
val = inet->freebind; val = inet->freebind;
break; break;
case IP_TRANSPARENT:
val = inet->transparent;
break;
default: default:
release_sock(sk); release_sock(sk);
return -ENOPROTOOPT; return -ENOPROTOOPT;