aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/inet_timewait_sock.h1
-rw-r--r--include/net/net_namespace.h2
-rw-r--r--include/net/sock.h3
-rw-r--r--net/core/sock.c1
-rw-r--r--net/core/sock_diag.c12
-rw-r--r--net/ipv4/inet_timewait_sock.c1
6 files changed, 20 insertions, 0 deletions
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index f908dfc06..44975efe4 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -116,6 +116,7 @@ struct inet_timewait_sock {
#define tw_dport __tw_common.skc_dport
#define tw_num __tw_common.skc_num
#define tw_portpair __tw_common.skc_portpair
+#define tw_cookie __tw_common.skc_cookie
int tw_timeout;
volatile unsigned char tw_substate;
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 0faaed2e2..b69e8e8d7 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -54,6 +54,8 @@ struct net {
#endif
spinlock_t rules_mod_lock;
+ atomic64_t cookie_gen;
+
struct list_head list; /* list of network namespaces */
struct list_head cleanup_list; /* namespaces on death row */
struct list_head exit_list; /* Use only net_mutex */
diff --git a/include/net/sock.h b/include/net/sock.h
index 1fa662430..8d3d22ce2 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -192,6 +192,8 @@ struct sock_common {
#ifdef CONFIG_NET_NS
struct net *skc_net;
#endif
+ atomic64_t skc_cookie;
+
/*
* fields between dontcopy_begin/dontcopy_end
* are not copied in sock_copy()
@@ -306,6 +308,7 @@ struct sock {
#define sk_bind_node __sk_common.skc_bind_node
#define sk_prot __sk_common.skc_prot
#define sk_net __sk_common.skc_net
+#define sk_cookie __sk_common.skc_cookie
socket_lock_t sk_lock;
struct sk_buff_head sk_receive_queue;
/*
diff --git a/net/core/sock.c b/net/core/sock.c
index 88900b4d9..ba8394b57 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1521,6 +1521,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
newsk->sk_err = 0;
newsk->sk_err_soft = 0;
newsk->sk_priority = 0;
+ atomic64_set(&newsk->sk_cookie, 0);
/*
* Before updating sk_refcnt, we must commit prior changes to memory
* (Documentation/RCU/rculist_nulls.txt for details)
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index 3f78978b2..3bd136463 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -13,6 +13,18 @@ static const struct sock_diag_handler *sock_diag_handlers[AF_MAX];
static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh);
static DEFINE_MUTEX(sock_diag_table_mutex);
+static u64 sock_gen_cookie(struct sock *sk)
+{
+ while (1) {
+ u64 res = atomic64_read(&sk->sk_cookie);
+
+ if (res)
+ return res;
+ res = atomic64_inc_return(&sock_net(sk)->cookie_gen);
+ atomic64_cmpxchg(&sk->sk_cookie, 0, res);
+ }
+}
+
int sock_diag_check_cookie(void *sk, __u32 *cookie)
{
if ((cookie[0] != INET_DIAG_NOCOOKIE ||
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index 1f27c9f4a..d9e3b5b73 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -196,6 +196,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
tw->tw_ipv6only = 0;
tw->tw_transparent = inet->transparent;
tw->tw_prot = sk->sk_prot_creator;
+ atomic64_set(&tw->tw_cookie, atomic64_read(&sk->sk_cookie));
twsk_net_set(tw, hold_net(sock_net(sk)));
/*
* Because we use RCU lookups, we should not set tw_refcnt