From bd337c581b2b0d933d37f664bf55b342577fed3a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Mar 2015 16:44:03 -0700 Subject: ipv6: add missing ireq_net & ir_cookie initializations I forgot to update dccp_v6_conn_request() & cookie_v6_check(). They both need to set ireq->ireq_net and ireq->ir_cookie Lets clear ireq->ir_cookie in inet_reqsk_alloc() Signed-off-by: Eric Dumazet Fixes: 33cf7c90fe2f ("net: add real socket cookies") Signed-off-by: David S. Miller --- include/net/inet_sock.h | 1 + net/dccp/ipv4.c | 1 - net/dccp/ipv6.c | 1 + net/ipv4/tcp_input.c | 1 - net/ipv6/syncookies.c | 1 + 5 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index e565afdc14ad..30f7170abbf3 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -249,6 +249,7 @@ static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops if (req != NULL) { kmemcheck_annotate_bitfield(ireq, flags); ireq->opt = NULL; + atomic64_set(&ireq->ir_cookie, 0); } return req; diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index a78e0b999f96..f695874b5ade 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -642,7 +642,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ireq->ir_loc_addr = ip_hdr(skb)->daddr; ireq->ir_rmt_addr = ip_hdr(skb)->saddr; write_pnet(&ireq->ireq_net, sock_net(sk)); - atomic64_set(&ireq->ir_cookie, 0); /* * Step 3: Process LISTEN state diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 6bcaa33cd804..703a21acf434 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -403,6 +403,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) ireq = inet_rsk(req); ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr; ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr; + write_pnet(&ireq->ireq_net, sock_net(sk)); if (ipv6_opt_accepted(sk, skb, IP6CB(skb)) || np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 26f24995bd3d..da61a8e75f68 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5966,7 +5966,6 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; tcp_openreq_init(req, &tmp_opt, skb, sk); write_pnet(&inet_rsk(req)->ireq_net, sock_net(sk)); - atomic64_set(&inet_rsk(req)->ir_cookie, 0); af_ops->init_req(req, sk, skb); diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 7337fc7947e2..66bba6a84e47 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -196,6 +196,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) ireq = inet_rsk(req); treq = tcp_rsk(req); treq->listener = NULL; + write_pnet(&ireq->ireq_net, sock_net(sk)); if (security_inet_conn_request(sk, skb, req)) goto out_free; -- cgit v1.2.3 From 10feb428a5045d5eb18a5d755fbb8f0cc9645626 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Mar 2015 16:44:04 -0700 Subject: inet: add TCP_NEW_SYN_RECV state TCP_SYN_RECV state is currently used by fast open sockets. Initial TCP requests (the pseudo sockets created when a SYN is received) are not yet associated to a state. They are attached to their parent, and the parent is in TCP_LISTEN state. This commit adds TCP_NEW_SYN_RECV state, so that we can convert TCP stack to a different schem gradually. This state is not exported to user space. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp_states.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/net/tcp_states.h b/include/net/tcp_states.h index b0b645988bd8..50e78a74d0df 100644 --- a/include/net/tcp_states.h +++ b/include/net/tcp_states.h @@ -25,6 +25,7 @@ enum { TCP_LAST_ACK, TCP_LISTEN, TCP_CLOSING, /* Now a valid state */ + TCP_NEW_SYN_RECV, TCP_MAX_STATES /* Leave at the end! */ }; @@ -44,7 +45,8 @@ enum { TCPF_CLOSE_WAIT = (1 << 8), TCPF_LAST_ACK = (1 << 9), TCPF_LISTEN = (1 << 10), - TCPF_CLOSING = (1 << 11) + TCPF_CLOSING = (1 << 11), + TCPF_NEW_SYN_RECV = (1 << 12), }; #endif /* _LINUX_TCP_STATES_H */ -- cgit v1.2.3 From d34ac51b76e8c7de6094cfb11780ef9c2b93469f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Mar 2015 16:44:05 -0700 Subject: inet: add ireq_state field to inet_request_sock We need to identify request sock when they'll be visible in global ehash table. ireq_state is an alias to req.__req_common.skc_state. Its value is set to TCP_NEW_SYN_RECV Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/inet_sock.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 30f7170abbf3..b31f01de5cd6 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -27,6 +27,7 @@ #include #include #include +#include /** struct ip_options - IP Options * @@ -79,6 +80,7 @@ struct inet_request_sock { #define ir_iif req.__req_common.skc_bound_dev_if #define ir_cookie req.__req_common.skc_cookie #define ireq_net req.__req_common.skc_net +#define ireq_state req.__req_common.skc_state kmemcheck_bitfield_begin(flags); u16 snd_wscale : 4, @@ -250,6 +252,7 @@ static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops kmemcheck_annotate_bitfield(ireq, flags); ireq->opt = NULL; atomic64_set(&ireq->ir_cookie, 0); + ireq->ireq_state = TCP_NEW_SYN_RECV; } return req; -- cgit v1.2.3 From 1e2e01172fd11b4dbfee746c0c8fbcaa9dbf22a0 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Mar 2015 16:44:06 -0700 Subject: inet: add rsk_refcnt/ireq_refcnt to request socks When request socks will be in ehash, they'll need to be refcounted. This patch adds rsk_refcnt/ireq_refcnt macros, and adds reqsk_put() function, but nothing yet use them. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/inet_sock.h | 1 + include/net/request_sock.h | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index b31f01de5cd6..9d6470c16a27 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -81,6 +81,7 @@ struct inet_request_sock { #define ir_cookie req.__req_common.skc_cookie #define ireq_net req.__req_common.skc_net #define ireq_state req.__req_common.skc_state +#define ireq_refcnt req.__req_common.skc_refcnt kmemcheck_bitfield_begin(flags); u16 snd_wscale : 4, diff --git a/include/net/request_sock.h b/include/net/request_sock.h index 7f830ff67f08..e255ecf8bb40 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -49,6 +49,8 @@ int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req); */ struct request_sock { struct sock_common __req_common; +#define rsk_refcnt __req_common.skc_refcnt + struct request_sock *dl_next; u16 mss; u8 num_retrans; /* number of retransmits */ @@ -86,6 +88,12 @@ static inline void reqsk_free(struct request_sock *req) __reqsk_free(req); } +static inline void reqsk_put(struct request_sock *req) +{ + if (atomic_dec_and_test(&req->rsk_refcnt)) + reqsk_free(req); +} + extern int sysctl_max_syn_backlog; /** struct listen_sock - listen state -- cgit v1.2.3 From 0159dfd3d7dff2da646f53039d29319b830207be Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Mar 2015 16:44:07 -0700 Subject: net: add req_prot_cleanup() & req_prot_init() helpers Make proto_register() & proto_unregister() a bit nicer. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/sock.c | 69 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/net/core/sock.c b/net/core/sock.c index c8842f279f7a..63d871a91b5c 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2726,6 +2726,42 @@ static inline void release_proto_idx(struct proto *prot) } #endif +static void req_prot_cleanup(struct request_sock_ops *rsk_prot) +{ + if (!rsk_prot) + return; + kfree(rsk_prot->slab_name); + rsk_prot->slab_name = NULL; + if (rsk_prot->slab) { + kmem_cache_destroy(rsk_prot->slab); + rsk_prot->slab = NULL; + } +} + +static int req_prot_init(const struct proto *prot) +{ + struct request_sock_ops *rsk_prot = prot->rsk_prot; + + if (!rsk_prot) + return 0; + + rsk_prot->slab_name = kasprintf(GFP_KERNEL, "request_sock_%s", + prot->name); + if (!rsk_prot->slab_name) + return -ENOMEM; + + rsk_prot->slab = kmem_cache_create(rsk_prot->slab_name, + rsk_prot->obj_size, 0, + SLAB_HWCACHE_ALIGN, NULL); + + if (!rsk_prot->slab) { + pr_crit("%s: Can't create request sock SLAB cache!\n", + prot->name); + return -ENOMEM; + } + return 0; +} + int proto_register(struct proto *prot, int alloc_slab) { if (alloc_slab) { @@ -2739,21 +2775,8 @@ int proto_register(struct proto *prot, int alloc_slab) goto out; } - if (prot->rsk_prot != NULL) { - prot->rsk_prot->slab_name = kasprintf(GFP_KERNEL, "request_sock_%s", prot->name); - if (prot->rsk_prot->slab_name == NULL) - goto out_free_sock_slab; - - prot->rsk_prot->slab = kmem_cache_create(prot->rsk_prot->slab_name, - prot->rsk_prot->obj_size, 0, - SLAB_HWCACHE_ALIGN, NULL); - - if (prot->rsk_prot->slab == NULL) { - pr_crit("%s: Can't create request sock SLAB cache!\n", - prot->name); - goto out_free_request_sock_slab_name; - } - } + if (req_prot_init(prot)) + goto out_free_request_sock_slab; if (prot->twsk_prot != NULL) { prot->twsk_prot->twsk_slab_name = kasprintf(GFP_KERNEL, "tw_sock_%s", prot->name); @@ -2782,14 +2805,8 @@ int proto_register(struct proto *prot, int alloc_slab) out_free_timewait_sock_slab_name: kfree(prot->twsk_prot->twsk_slab_name); out_free_request_sock_slab: - if (prot->rsk_prot && prot->rsk_prot->slab) { - kmem_cache_destroy(prot->rsk_prot->slab); - prot->rsk_prot->slab = NULL; - } -out_free_request_sock_slab_name: - if (prot->rsk_prot) - kfree(prot->rsk_prot->slab_name); -out_free_sock_slab: + req_prot_cleanup(prot->rsk_prot); + kmem_cache_destroy(prot->slab); prot->slab = NULL; out: @@ -2809,11 +2826,7 @@ void proto_unregister(struct proto *prot) prot->slab = NULL; } - if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) { - kmem_cache_destroy(prot->rsk_prot->slab); - kfree(prot->rsk_prot->slab_name); - prot->rsk_prot->slab = NULL; - } + req_prot_cleanup(prot->rsk_prot); if (prot->twsk_prot != NULL && prot->twsk_prot->twsk_slab != NULL) { kmem_cache_destroy(prot->twsk_prot->twsk_slab); -- cgit v1.2.3 From 41b822c59e21414d829bcfd00df0c8f7f13b1b95 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Mar 2015 16:44:08 -0700 Subject: inet: prepare sock_edemux() & sock_gen_put() for new SYN_RECV state sock_edemux() & sock_gen_put() should be ready to cope with request socks. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/request_sock.h | 5 +++++ include/net/sock.h | 2 +- net/core/sock.c | 2 ++ net/ipv4/inet_hashtables.c | 2 ++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/net/request_sock.h b/include/net/request_sock.h index e255ecf8bb40..3275cf31f731 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -77,6 +77,11 @@ static inline struct request_sock *reqsk_alloc(const struct request_sock_ops *op return req; } +static inline struct request_sock *inet_reqsk(struct sock *sk) +{ + return (struct request_sock *)sk; +} + static inline void __reqsk_free(struct request_sock *req) { kmem_cache_free(req->rsk_ops->slab, req); diff --git a/include/net/sock.h b/include/net/sock.h index 9411c3421dd3..f10832ca2e90 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1625,7 +1625,7 @@ static inline void sock_put(struct sock *sk) sk_free(sk); } /* Generic version of sock_put(), dealing with all sockets - * (TCP_TIMEWAIT, ESTABLISHED...) + * (TCP_TIMEWAIT, TCP_NEW_SYN_RECV, ESTABLISHED...) */ void sock_gen_put(struct sock *sk); diff --git a/net/core/sock.c b/net/core/sock.c index 63d871a91b5c..4bc42efb3e40 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1668,6 +1668,8 @@ void sock_edemux(struct sk_buff *skb) if (sk->sk_state == TCP_TIME_WAIT) inet_twsk_put(inet_twsk(sk)); + else if (sk->sk_state == TCP_NEW_SYN_RECV) + reqsk_put(inet_reqsk(sk)); else sock_put(sk); } diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index f6a12b97d12b..64401a2fdd33 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -262,6 +262,8 @@ void sock_gen_put(struct sock *sk) if (sk->sk_state == TCP_TIME_WAIT) inet_twsk_free(inet_twsk(sk)); + else if (sk->sk_state == TCP_NEW_SYN_RECV) + reqsk_free(inet_reqsk(sk)); else sk_free(sk); } -- cgit v1.2.3 From d4f06873b636519cedbe8d2eeae77c713c6a121c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Mar 2015 16:44:09 -0700 Subject: inet: get_openreq4() & get_openreq6() do not need listener ireq->ir_num contains local port, use it. Also, get_openreq4() dumping listen_sk->refcnt makes litle sense. inet_diag_fill_req() can also use ireq->ir_num Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 3 +-- net/ipv4/tcp_ipv4.c | 8 ++++---- net/ipv6/tcp_ipv6.c | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 29317ff4a007..c55a6fa3162d 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -718,7 +718,6 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, const struct nlmsghdr *unlh) { const struct inet_request_sock *ireq = inet_rsk(req); - struct inet_sock *inet = inet_sk(sk); struct inet_diag_msg *r; struct nlmsghdr *nlh; long tmo; @@ -744,7 +743,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, if (tmo < 0) tmo = 0; - r->id.idiag_sport = inet->inet_sport; + r->id.idiag_sport = htons(ireq->ir_num); r->id.idiag_dport = ireq->ir_rmt_port; memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f0c6fc32bfa8..70b0f701bbdb 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2204,7 +2204,7 @@ void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo) } EXPORT_SYMBOL(tcp_proc_unregister); -static void get_openreq4(const struct sock *sk, const struct request_sock *req, +static void get_openreq4(const struct request_sock *req, struct seq_file *f, int i, kuid_t uid) { const struct inet_request_sock *ireq = inet_rsk(req); @@ -2214,7 +2214,7 @@ static void get_openreq4(const struct sock *sk, const struct request_sock *req, " %02X %08X:%08X %02X:%08lX %08X %5u %8d %u %d %pK", i, ireq->ir_loc_addr, - ntohs(inet_sk(sk)->inet_sport), + ireq->ir_num, ireq->ir_rmt_addr, ntohs(ireq->ir_rmt_port), TCP_SYN_RECV, @@ -2225,7 +2225,7 @@ static void get_openreq4(const struct sock *sk, const struct request_sock *req, from_kuid_munged(seq_user_ns(f), uid), 0, /* non standard timer */ 0, /* open_requests have no inode */ - atomic_read(&sk->sk_refcnt), + 0, req); } @@ -2332,7 +2332,7 @@ static int tcp4_seq_show(struct seq_file *seq, void *v) get_tcp4_sock(v, seq, st->num); break; case TCP_SEQ_STATE_OPENREQ: - get_openreq4(st->syn_wait_sk, v, seq, st->num, st->uid); + get_openreq4(v, seq, st->num, st->uid); break; } out: diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5d46832c6f72..1ccfede7d55f 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1689,7 +1689,7 @@ static void tcp_v6_destroy_sock(struct sock *sk) #ifdef CONFIG_PROC_FS /* Proc filesystem TCPv6 sock list dumping. */ static void get_openreq6(struct seq_file *seq, - const struct sock *sk, struct request_sock *req, int i, kuid_t uid) + struct request_sock *req, int i, kuid_t uid) { int ttd = req->expires - jiffies; const struct in6_addr *src = &inet_rsk(req)->ir_v6_loc_addr; @@ -1827,7 +1827,7 @@ static int tcp6_seq_show(struct seq_file *seq, void *v) get_tcp6_sock(seq, v, st->num); break; case TCP_SEQ_STATE_OPENREQ: - get_openreq6(seq, st->syn_wait_sk, v, st->num, st->uid); + get_openreq6(seq, v, st->num, st->uid); break; } out: -- cgit v1.2.3 From 3f66b083a5b7f1a63540c24df3679c24f2e935a9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Mar 2015 16:44:10 -0700 Subject: inet: introduce ireq_family Before inserting request socks into general hash table, fill their socket family. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/inet_sock.h | 1 + net/dccp/ipv4.c | 1 + net/dccp/ipv6.c | 1 + net/ipv4/inet_diag.c | 2 +- net/ipv4/syncookies.c | 1 + net/ipv4/tcp_ipv4.c | 1 + net/ipv6/syncookies.c | 1 + net/ipv6/tcp_ipv6.c | 1 + 8 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 9d6470c16a27..b3053fdd871e 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -82,6 +82,7 @@ struct inet_request_sock { #define ireq_net req.__req_common.skc_net #define ireq_state req.__req_common.skc_state #define ireq_refcnt req.__req_common.skc_refcnt +#define ireq_family req.__req_common.skc_family kmemcheck_bitfield_begin(flags); u16 snd_wscale : 4, diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index f695874b5ade..8f6f4004daac 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -642,6 +642,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ireq->ir_loc_addr = ip_hdr(skb)->daddr; ireq->ir_rmt_addr = ip_hdr(skb)->saddr; write_pnet(&ireq->ireq_net, sock_net(sk)); + ireq->ireq_family = AF_INET; /* * Step 3: Process LISTEN state diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 703a21acf434..5166b0043f95 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -404,6 +404,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr; ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr; write_pnet(&ireq->ireq_net, sock_net(sk)); + ireq->ireq_family = AF_INET6; if (ipv6_opt_accepted(sk, skb, IP6CB(skb)) || np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index c55a6fa3162d..43789c99031f 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -728,7 +728,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, return -EMSGSIZE; r = nlmsg_data(nlh); - r->idiag_family = sk->sk_family; + r->idiag_family = ireq->ireq_family; r->idiag_state = TCP_SYN_RECV; r->idiag_timer = 1; r->idiag_retrans = req->num_retrans; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 18e5a67fda81..0c432730c7b4 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -347,6 +347,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) treq->snt_synack = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0; treq->listener = NULL; write_pnet(&ireq->ireq_net, sock_net(sk)); + ireq->ireq_family = AF_INET; /* We throwed the options of the initial SYN away, so we hope * the ACK carries the same options again (see RFC1122 4.2.3.8) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 70b0f701bbdb..1f514a0c5e60 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1228,6 +1228,7 @@ static void tcp_v4_init_req(struct request_sock *req, struct sock *sk, ireq->ir_rmt_addr = ip_hdr(skb)->saddr; ireq->no_srccheck = inet_sk(sk)->transparent; ireq->opt = tcp_v4_save_options(skb); + ireq->ireq_family = AF_INET; } static struct dst_entry *tcp_v4_route_req(struct sock *sk, struct flowi *fl, diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 66bba6a84e47..58875ce8e178 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -197,6 +197,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) treq = tcp_rsk(req); treq->listener = NULL; write_pnet(&ireq->ireq_net, sock_net(sk)); + ireq->ireq_family = AF_INET6; if (security_inet_conn_request(sk, skb, req)) goto out_free; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1ccfede7d55f..c5fc6a5e4adc 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -749,6 +749,7 @@ static void tcp_v6_init_req(struct request_sock *req, struct sock *sk, atomic_inc(&skb->users); ireq->pktopts = skb; } + ireq->ireq_family = AF_INET6; } static struct dst_entry *tcp_v6_route_req(struct sock *sk, struct flowi *fl, -- cgit v1.2.3