aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
authorHuw Davies <huw@codeweavers.com>2016-06-27 15:05:28 -0400
committerPaul Moore <paul@paul-moore.com>2016-06-27 15:05:28 -0400
commit56ac42bc94b18d45b6c484edeac33be86bfb3efa (patch)
treed14e433bcc0b3fef9349a86cbb6d8d87dedfb232 /net/ipv6/tcp_ipv6.c
parent1f440c99d3207d684a3ac48d6e528af548b5c915 (diff)
ipv6: Allow request socks to contain IPv6 options.
If set, these will take precedence over the parent's options during both sending and child creation. If they're not set, the parent's options (if any) will be used. This is to allow the security_inet_conn_request() hook to modify the IPv6 options in just the same way that it already may do for IPv4. Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 711d209f9124..18daddc6001c 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -443,6 +443,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
443{ 443{
444 struct inet_request_sock *ireq = inet_rsk(req); 444 struct inet_request_sock *ireq = inet_rsk(req);
445 struct ipv6_pinfo *np = inet6_sk(sk); 445 struct ipv6_pinfo *np = inet6_sk(sk);
446 struct ipv6_txoptions *opt;
446 struct flowi6 *fl6 = &fl->u.ip6; 447 struct flowi6 *fl6 = &fl->u.ip6;
447 struct sk_buff *skb; 448 struct sk_buff *skb;
448 int err = -ENOMEM; 449 int err = -ENOMEM;
@@ -463,8 +464,10 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
463 fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts)); 464 fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
464 465
465 rcu_read_lock(); 466 rcu_read_lock();
466 err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), 467 opt = ireq->ipv6_opt;
467 np->tclass); 468 if (!opt)
469 opt = rcu_dereference(np->opt);
470 err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
468 rcu_read_unlock(); 471 rcu_read_unlock();
469 err = net_xmit_eval(err); 472 err = net_xmit_eval(err);
470 } 473 }
@@ -476,6 +479,7 @@ done:
476 479
477static void tcp_v6_reqsk_destructor(struct request_sock *req) 480static void tcp_v6_reqsk_destructor(struct request_sock *req)
478{ 481{
482 kfree(inet_rsk(req)->ipv6_opt);
479 kfree_skb(inet_rsk(req)->pktopts); 483 kfree_skb(inet_rsk(req)->pktopts);
480} 484}
481 485
@@ -1107,7 +1111,9 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
1107 but we make one more one thing there: reattach optmem 1111 but we make one more one thing there: reattach optmem
1108 to newsk. 1112 to newsk.
1109 */ 1113 */
1110 opt = rcu_dereference(np->opt); 1114 opt = ireq->ipv6_opt;
1115 if (!opt)
1116 opt = rcu_dereference(np->opt);
1111 if (opt) { 1117 if (opt) {
1112 opt = ipv6_dup_options(newsk, opt); 1118 opt = ipv6_dup_options(newsk, opt);
1113 RCU_INIT_POINTER(newnp->opt, opt); 1119 RCU_INIT_POINTER(newnp->opt, opt);