summaryrefslogtreecommitdiff
path: root/net/ipv6/ipv6_sockglue.c
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-04-14 10:21:52 +0400
committerDavid S. Miller <davem@davemloft.net>2008-04-14 10:21:52 +0400
commite7712f1a7c32a5533be25ed806b1a8f7e42b452a (patch)
tree33996145bc3e087831bf6b11c2afa8baf0d8cf20 /net/ipv6/ipv6_sockglue.c
parentcee8947338d46bccece54c752bf6cd4043035f05 (diff)
downloadlinux-e7712f1a7c32a5533be25ed806b1a8f7e42b452a.tar.xz
[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/ipv6/ipv6_sockglue.c')
-rw-r--r--net/ipv6/ipv6_sockglue.c64
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);