diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-04-14 08:21:52 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-14 08:21:52 +0200 |
commit | e7712f1a7c32a5533be25ed806b1a8f7e42b452a (patch) | |
tree | 33996145bc3e087831bf6b11c2afa8baf0d8cf20 /net | |
parent | [IPV6] MROUTE: Do not call ipv6_find_idev() directly. (diff) | |
download | linux-e7712f1a7c32a5533be25ed806b1a8f7e42b452a.tar.xz linux-e7712f1a7c32a5533be25ed806b1a8f7e42b452a.zip |
[IPV6]: Share common code-paths for sticky socket options.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-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 2f1244dc5ebf..06de9d0e1f6b 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); |