diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-04-14 02:21:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-14 02:21:52 -0400 |
commit | e7712f1a7c32a5533be25ed806b1a8f7e42b452a (patch) | |
tree | 33996145bc3e087831bf6b11c2afa8baf0d8cf20 /net/ipv6/ipv6_sockglue.c | |
parent | cee8947338d46bccece54c752bf6cd4043035f05 (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.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 *)) | |||
103 | return 0; | 103 | return 0; |
104 | } | 104 | } |
105 | 105 | ||
106 | static | ||
107 | struct 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 | |||
106 | static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | 129 | static 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 | } | ||
373 | sticky_done: | 378 | sticky_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; |
416 | update: | 421 | update: |
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 | |||
438 | done: | 424 | done: |
439 | if (opt) | 425 | if (opt) |
440 | sock_kfree_s(sk, opt, opt->tot_len); | 426 | sock_kfree_s(sk, opt, opt->tot_len); |