diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2007-03-18 20:35:57 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:24:16 -0400 |
commit | 4c6510a738c71ca6b4b7b624a7d0a00acebfd7fb (patch) | |
tree | d24c3f769fb2947e87f9e25ed33316ad867bea74 | |
parent | 3fbe070a4293e8ab2d2edb1bc23f1e5220ce61af (diff) |
[IPV6]: Return correct result for sticky options.
We returned incorrect result with IPV6_RTHDRDSTOPTS, IPV6_RTHDR and
IPV6_DSTOPTS.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 1cb7a084f0c0..eceed09e434d 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -797,13 +797,32 @@ EXPORT_SYMBOL(compat_ipv6_setsockopt); | |||
797 | #endif | 797 | #endif |
798 | 798 | ||
799 | static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, | 799 | static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, |
800 | char __user *optval, int len) | 800 | int optname, char __user *optval, int len) |
801 | { | 801 | { |
802 | struct ipv6_opt_hdr *hdr; | 802 | struct ipv6_opt_hdr *hdr; |
803 | 803 | ||
804 | if (!opt || !opt->hopopt) | 804 | if (!opt) |
805 | return 0; | ||
806 | |||
807 | switch(optname) { | ||
808 | case IPV6_HOPOPTS: | ||
809 | hdr = opt->hopopt; | ||
810 | break; | ||
811 | case IPV6_RTHDRDSTOPTS: | ||
812 | hdr = opt->dst0opt; | ||
813 | break; | ||
814 | case IPV6_RTHDR: | ||
815 | hdr = (struct ipv6_opt_hdr *)opt->srcrt; | ||
816 | break; | ||
817 | case IPV6_DSTOPTS: | ||
818 | hdr = opt->dst1opt; | ||
819 | break; | ||
820 | default: | ||
821 | return -EINVAL; /* should not happen */ | ||
822 | } | ||
823 | |||
824 | if (!hdr) | ||
805 | return 0; | 825 | return 0; |
806 | hdr = opt->hopopt; | ||
807 | 826 | ||
808 | len = min_t(unsigned int, len, ipv6_optlen(hdr)); | 827 | len = min_t(unsigned int, len, ipv6_optlen(hdr)); |
809 | if (copy_to_user(optval, hdr, ipv6_optlen(hdr))) | 828 | if (copy_to_user(optval, hdr, ipv6_optlen(hdr))) |
@@ -946,7 +965,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
946 | 965 | ||
947 | lock_sock(sk); | 966 | lock_sock(sk); |
948 | len = ipv6_getsockopt_sticky(sk, np->opt, | 967 | len = ipv6_getsockopt_sticky(sk, np->opt, |
949 | optval, len); | 968 | optname, optval, len); |
950 | release_sock(sk); | 969 | release_sock(sk); |
951 | return put_user(len, optlen); | 970 | return put_user(len, optlen); |
952 | } | 971 | } |