Commit e7712f1a authored by YOSHIFUJI Hideaki's avatar YOSHIFUJI Hideaki Committed by David S. Miller

[IPV6]: Share common code-paths for sticky socket options.

Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cee89473
...@@ -103,6 +103,29 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) ...@@ -103,6 +103,29 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
return 0; 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, static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen) char __user *optval, int optlen)
{ {
...@@ -351,25 +374,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, ...@@ -351,25 +374,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
} }
retv = 0; retv = 0;
if (inet_sk(sk)->is_icsk) { opt = ipv6_update_options(sk, opt);
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);
}
sticky_done: sticky_done:
if (opt) if (opt)
sock_kfree_s(sk, opt, opt->tot_len); sock_kfree_s(sk, opt, opt->tot_len);
...@@ -415,26 +420,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, ...@@ -415,26 +420,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
goto done; goto done;
update: update:
retv = 0; retv = 0;
if (inet_sk(sk)->is_icsk) { opt = ipv6_update_options(sk, opt);
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);
}
done: done:
if (opt) if (opt)
sock_kfree_s(sk, opt, opt->tot_len); sock_kfree_s(sk, opt, opt->tot_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment