aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ipv6_sockglue.c
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-04-14 02:21:52 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-14 02:21:52 -0400
commite7712f1a7c32a5533be25ed806b1a8f7e42b452a (patch)
tree33996145bc3e087831bf6b11c2afa8baf0d8cf20 /net/ipv6/ipv6_sockglue.c
parentcee8947338d46bccece54c752bf6cd4043035f05 (diff)
[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 *))
103 return 0; 103 return 0;
104} 104}
105 105
106static
107struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
108 struct ipv6_txoptions *opt)
109{
110 if (inet_sk(sk)->is_icsk) {
111 if (opt &&
112 !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
113 inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
114 struct inet_connection_sock *icsk = inet_csk(sk);
115 icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen;
116 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
117 }
118 opt = xchg(&inet6_sk(sk)->opt, opt);
119 } else {
120 write_lock(&sk->sk_dst_lock);
121 opt = xchg(&inet6_sk(sk)->opt, opt);
122 write_unlock(&sk->sk_dst_lock);
123 }
124 sk_dst_reset(sk);
125
126 return opt;
127}
128
106static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, 129static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
107 char __user *optval, int optlen) 130 char __user *optval, int optlen)
108{ 131{
@@ -351,25 +374,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
351 } 374 }
352 375
353 retv = 0; 376 retv = 0;
354 if (inet_sk(sk)->is_icsk) { 377 opt = ipv6_update_options(sk, opt);
355 if (opt) {
356 struct inet_connection_sock *icsk = inet_csk(sk);
357 if (!((1 << sk->sk_state) &
358 (TCPF_LISTEN | TCPF_CLOSE))
359 && inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
360 icsk->icsk_ext_hdr_len =
361 opt->opt_flen + opt->opt_nflen;
362 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
363 }
364 }
365 opt = xchg(&np->opt, opt);
366 sk_dst_reset(sk);
367 } else {
368 write_lock(&sk->sk_dst_lock);
369 opt = xchg(&np->opt, opt);
370 write_unlock(&sk->sk_dst_lock);
371 sk_dst_reset(sk);
372 }
373sticky_done: 378sticky_done:
374 if (opt) 379 if (opt)
375 sock_kfree_s(sk, opt, opt->tot_len); 380 sock_kfree_s(sk, opt, opt->tot_len);
@@ -415,26 +420,7 @@ sticky_done:
415 goto done; 420 goto done;
416update: 421update:
417 retv = 0; 422 retv = 0;
418 if (inet_sk(sk)->is_icsk) { 423 opt = ipv6_update_options(sk, opt);
419 if (opt) {
420 struct inet_connection_sock *icsk = inet_csk(sk);
421 if (!((1 << sk->sk_state) &
422 (TCPF_LISTEN | TCPF_CLOSE))
423 && inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
424 icsk->icsk_ext_hdr_len =
425 opt->opt_flen + opt->opt_nflen;
426 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
427 }
428 }
429 opt = xchg(&np->opt, opt);
430 sk_dst_reset(sk);
431 } else {
432 write_lock(&sk->sk_dst_lock);
433 opt = xchg(&np->opt, opt);
434 write_unlock(&sk->sk_dst_lock);
435 sk_dst_reset(sk);
436 }
437
438done: 424done:
439 if (opt) 425 if (opt)
440 sock_kfree_s(sk, opt, opt->tot_len); 426 sock_kfree_s(sk, opt, opt->tot_len);