diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 64 |
1 files changed, 25 insertions, 39 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 2f1244dc5eb..06de9d0e1f6 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -103,6 +103,29 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) return 0; } +static +struct ipv6_txoptions *ipv6_update_options(struct sock *sk, + struct ipv6_txoptions *opt) +{ + if (inet_sk(sk)->is_icsk) { + if (opt && + !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) && + inet_sk(sk)->daddr != LOOPBACK4_IPV6) { + struct inet_connection_sock *icsk = inet_csk(sk); + icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; + icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); + } + opt = xchg(&inet6_sk(sk)->opt, opt); + } else { + write_lock(&sk->sk_dst_lock); + opt = xchg(&inet6_sk(sk)->opt, opt); + write_unlock(&sk->sk_dst_lock); + } + sk_dst_reset(sk); + + return opt; +} + static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { @@ -351,25 +374,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, } retv = 0; - if (inet_sk(sk)->is_icsk) { - if (opt) { - struct inet_connection_sock *icsk = inet_csk(sk); - if (!((1 << sk->sk_state) & - (TCPF_LISTEN | TCPF_CLOSE)) - && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { - icsk->icsk_ext_hdr_len = - opt->opt_flen + opt->opt_nflen; - icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); - } - } - opt = xchg(&np->opt, opt); - sk_dst_reset(sk); - } else { - write_lock(&sk->sk_dst_lock); - opt = xchg(&np->opt, opt); - write_unlock(&sk->sk_dst_lock); - sk_dst_reset(sk); - } + opt = ipv6_update_options(sk, opt); sticky_done: if (opt) sock_kfree_s(sk, opt, opt->tot_len); @@ -415,26 +420,7 @@ sticky_done: goto done; update: retv = 0; - if (inet_sk(sk)->is_icsk) { - if (opt) { - struct inet_connection_sock *icsk = inet_csk(sk); - if (!((1 << sk->sk_state) & - (TCPF_LISTEN | TCPF_CLOSE)) - && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { - icsk->icsk_ext_hdr_len = - opt->opt_flen + opt->opt_nflen; - icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); - } - } - opt = xchg(&np->opt, opt); - sk_dst_reset(sk); - } else { - write_lock(&sk->sk_dst_lock); - opt = xchg(&np->opt, opt); - write_unlock(&sk->sk_dst_lock); - sk_dst_reset(sk); - } - + opt = ipv6_update_options(sk, opt); done: if (opt) sock_kfree_s(sk, opt, opt->tot_len); |