summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2014-05-13 10:17:35 -0700
committerDavid S. Miller <davem@davemloft.net>2014-05-13 18:35:09 -0400
commit84f39b08d7868ce10eeaf640627cb89777f0ae93 (patch)
treeb8040290a249b8242767c1bb7f433deb40b4e6e0 /include
parent1b3c61dc1aebf5d3d6c3981ba3eedc1e66f3ecda (diff)
net: support marking accepting TCP sockets
When using mark-based routing, sockets returned from accept() may need to be marked differently depending on the incoming connection request. This is the case, for example, if different socket marks identify different networks: a listening socket may want to accept connections from all networks, but each connection should be marked with the network that the request came in on, so that subsequent packets are sent on the correct network. This patch adds a sysctl to mark TCP sockets based on the fwmark of the incoming SYN packet. If enabled, and an unmarked socket receives a SYN, then the SYN packet's fwmark is written to the connection's inet_request_sock, and later written back to the accepted socket when the connection is established. If the socket already has a nonzero mark, then the behaviour is the same as it is today, i.e., the listening socket's fwmark is used. Black-box tested using user-mode linux: - IPv4/IPv6 SYN+ACK, FIN, etc. packets are routed based on the mark of the incoming SYN packet. - The socket returned by accept() is marked with the mark of the incoming SYN packet. - Tested with syncookies=1 and syncookies=2. Signed-off-by: Lorenzo Colitti <lorenzo@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/net/inet_sock.h10
-rw-r--r--include/net/netns/ipv4.h1
2 files changed, 11 insertions, 0 deletions
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 1833c3f389ee..b1edf17bec01 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -90,6 +90,7 @@ struct inet_request_sock {
kmemcheck_bitfield_end(flags);
struct ip_options_rcu *opt;
struct sk_buff *pktopts;
+ u32 ir_mark;
};
static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
@@ -97,6 +98,15 @@ static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
return (struct inet_request_sock *)sk;
}
+static inline u32 inet_request_mark(struct sock *sk, struct sk_buff *skb)
+{
+ if (!sk->sk_mark && sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept) {
+ return skb->mark;
+ } else {
+ return sk->sk_mark;
+ }
+}
+
struct inet_cork {
unsigned int flags;
__be32 addr;
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index a32fc4d705da..2f0cfad66666 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -78,6 +78,7 @@ struct netns_ipv4 {
int sysctl_ip_fwd_use_pmtu;
int sysctl_fwmark_reflect;
+ int sysctl_tcp_fwmark_accept;
struct ping_group_range ping_group_range;