[IPV6]: Share common code-paths for sticky socket options.
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Mon, 14 Apr 2008 06:21:52 +0000 (23:21 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 14 Apr 2008 06:21:52 +0000 (23:21 -0700)
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/ipv6_sockglue.c

index 2f1244dc5ebfb8129856b68eef3dbec19e952863..06de9d0e1f6b653384279180612b2b0b69df1f66 100644 (file)
@@ -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);