aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDmitry Mishin <dim@openvz.org>2006-03-21 01:45:21 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-21 01:45:21 -0500
commit3fdadf7d27e3fbcf72930941884387d1f4936f04 (patch)
tree167072cf1e60b6b307610563614b435ff0caa52d /net/ipv6
parentc750360938b403e6cc193d293cfbcb099dd6c60e (diff)
[NET]: {get|set}sockopt compatibility layer
This patch extends {get|set}sockopt compatibility layer in order to move protocol specific parts to their place and avoid huge universal net/compat.c file in the future. Signed-off-by: Dmitry Mishin <dim@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/af_inet6.c12
-rw-r--r--net/ipv6/ipv6_sockglue.c163
-rw-r--r--net/ipv6/ipv6_syms.c4
-rw-r--r--net/ipv6/raw.c112
-rw-r--r--net/ipv6/tcp_ipv6.c12
-rw-r--r--net/ipv6/udp.c52
6 files changed, 292 insertions, 63 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 6c9711ac1c03..97844c4cd9b1 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -470,6 +470,10 @@ const struct proto_ops inet6_stream_ops = {
470 .shutdown = inet_shutdown, /* ok */ 470 .shutdown = inet_shutdown, /* ok */
471 .setsockopt = sock_common_setsockopt, /* ok */ 471 .setsockopt = sock_common_setsockopt, /* ok */
472 .getsockopt = sock_common_getsockopt, /* ok */ 472 .getsockopt = sock_common_getsockopt, /* ok */
473#ifdef CONFIG_COMPAT
474 .compat_setsockopt = compat_sock_common_setsockopt,
475 .compat_getsockopt = compat_sock_common_getsockopt,
476#endif
473 .sendmsg = inet_sendmsg, /* ok */ 477 .sendmsg = inet_sendmsg, /* ok */
474 .recvmsg = sock_common_recvmsg, /* ok */ 478 .recvmsg = sock_common_recvmsg, /* ok */
475 .mmap = sock_no_mmap, 479 .mmap = sock_no_mmap,
@@ -491,6 +495,10 @@ const struct proto_ops inet6_dgram_ops = {
491 .shutdown = inet_shutdown, /* ok */ 495 .shutdown = inet_shutdown, /* ok */
492 .setsockopt = sock_common_setsockopt, /* ok */ 496 .setsockopt = sock_common_setsockopt, /* ok */
493 .getsockopt = sock_common_getsockopt, /* ok */ 497 .getsockopt = sock_common_getsockopt, /* ok */
498#ifdef CONFIG_COMPAT
499 .compat_setsockopt = compat_sock_common_setsockopt,
500 .compat_getsockopt = compat_sock_common_getsockopt,
501#endif
494 .sendmsg = inet_sendmsg, /* ok */ 502 .sendmsg = inet_sendmsg, /* ok */
495 .recvmsg = sock_common_recvmsg, /* ok */ 503 .recvmsg = sock_common_recvmsg, /* ok */
496 .mmap = sock_no_mmap, 504 .mmap = sock_no_mmap,
@@ -519,6 +527,10 @@ static const struct proto_ops inet6_sockraw_ops = {
519 .shutdown = inet_shutdown, /* ok */ 527 .shutdown = inet_shutdown, /* ok */
520 .setsockopt = sock_common_setsockopt, /* ok */ 528 .setsockopt = sock_common_setsockopt, /* ok */
521 .getsockopt = sock_common_getsockopt, /* ok */ 529 .getsockopt = sock_common_getsockopt, /* ok */
530#ifdef CONFIG_COMPAT
531 .compat_setsockopt = compat_sock_common_setsockopt,
532 .compat_getsockopt = compat_sock_common_getsockopt,
533#endif
522 .sendmsg = inet_sendmsg, /* ok */ 534 .sendmsg = inet_sendmsg, /* ok */
523 .recvmsg = sock_common_recvmsg, /* ok */ 535 .recvmsg = sock_common_recvmsg, /* ok */
524 .mmap = sock_no_mmap, 536 .mmap = sock_no_mmap,
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index f7142ba519ab..988eac58e9d1 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -109,19 +109,13 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
109 return 0; 109 return 0;
110} 110}
111 111
112int ipv6_setsockopt(struct sock *sk, int level, int optname, 112static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
113 char __user *optval, int optlen) 113 char __user *optval, int optlen)
114{ 114{
115 struct ipv6_pinfo *np = inet6_sk(sk); 115 struct ipv6_pinfo *np = inet6_sk(sk);
116 int val, valbool; 116 int val, valbool;
117 int retv = -ENOPROTOOPT; 117 int retv = -ENOPROTOOPT;
118 118
119 if (level == SOL_IP && sk->sk_type != SOCK_RAW)
120 return udp_prot.setsockopt(sk, level, optname, optval, optlen);
121
122 if(level!=SOL_IPV6)
123 goto out;
124
125 if (optval == NULL) 119 if (optval == NULL)
126 val=0; 120 val=0;
127 else if (get_user(val, (int __user *) optval)) 121 else if (get_user(val, (int __user *) optval))
@@ -613,17 +607,9 @@ done:
613 retv = xfrm_user_policy(sk, optname, optval, optlen); 607 retv = xfrm_user_policy(sk, optname, optval, optlen);
614 break; 608 break;
615 609
616#ifdef CONFIG_NETFILTER
617 default:
618 retv = nf_setsockopt(sk, PF_INET6, optname, optval,
619 optlen);
620 break;
621#endif
622
623 } 610 }
624 release_sock(sk); 611 release_sock(sk);
625 612
626out:
627 return retv; 613 return retv;
628 614
629e_inval: 615e_inval:
@@ -631,6 +617,65 @@ e_inval:
631 return -EINVAL; 617 return -EINVAL;
632} 618}
633 619
620int ipv6_setsockopt(struct sock *sk, int level, int optname,
621 char __user *optval, int optlen)
622{
623 int err;
624
625 if (level == SOL_IP && sk->sk_type != SOCK_RAW)
626 return udp_prot.setsockopt(sk, level, optname, optval, optlen);
627
628 if (level != SOL_IPV6)
629 return -ENOPROTOOPT;
630
631 err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
632#ifdef CONFIG_NETFILTER
633 /* we need to exclude all possible ENOPROTOOPTs except default case */
634 if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
635 optname != IPV6_XFRM_POLICY) {
636 lock_sock(sk);
637 err = nf_setsockopt(sk, PF_INET6, optname, optval,
638 optlen);
639 release_sock(sk);
640 }
641#endif
642 return err;
643}
644
645
646#ifdef CONFIG_COMPAT
647int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
648 char __user *optval, int optlen)
649{
650 int err;
651
652 if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
653 if (udp_prot.compat_setsockopt)
654 return udp_prot.compat_setsockopt(sk, level,
655 optname, optval, optlen);
656 else
657 return udp_prot.setsockopt(sk, level,
658 optname, optval, optlen);
659 }
660
661 if (level != SOL_IPV6)
662 return -ENOPROTOOPT;
663
664 err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
665#ifdef CONFIG_NETFILTER
666 /* we need to exclude all possible ENOPROTOOPTs except default case */
667 if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
668 optname != IPV6_XFRM_POLICY) {
669 lock_sock(sk);
670 err = compat_nf_setsockopt(sk, PF_INET6, optname, optval,
671 optlen);
672 release_sock(sk);
673 }
674#endif
675 return err;
676}
677#endif
678
634static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, 679static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
635 char __user *optval, int len) 680 char __user *optval, int len)
636{ 681{
@@ -642,17 +687,13 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
642 return len; 687 return len;
643} 688}
644 689
645int ipv6_getsockopt(struct sock *sk, int level, int optname, 690static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
646 char __user *optval, int __user *optlen) 691 char __user *optval, int __user *optlen)
647{ 692{
648 struct ipv6_pinfo *np = inet6_sk(sk); 693 struct ipv6_pinfo *np = inet6_sk(sk);
649 int len; 694 int len;
650 int val; 695 int val;
651 696
652 if (level == SOL_IP && sk->sk_type != SOCK_RAW)
653 return udp_prot.getsockopt(sk, level, optname, optval, optlen);
654 if(level!=SOL_IPV6)
655 return -ENOPROTOOPT;
656 if (get_user(len, optlen)) 697 if (get_user(len, optlen))
657 return -EFAULT; 698 return -EFAULT;
658 switch (optname) { 699 switch (optname) {
@@ -842,17 +883,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
842 break; 883 break;
843 884
844 default: 885 default:
845#ifdef CONFIG_NETFILTER
846 lock_sock(sk);
847 val = nf_getsockopt(sk, PF_INET6, optname, optval,
848 &len);
849 release_sock(sk);
850 if (val >= 0)
851 val = put_user(len, optlen);
852 return val;
853#else
854 return -EINVAL; 886 return -EINVAL;
855#endif
856 } 887 }
857 len = min_t(unsigned int, sizeof(int), len); 888 len = min_t(unsigned int, sizeof(int), len);
858 if(put_user(len, optlen)) 889 if(put_user(len, optlen))
@@ -862,6 +893,78 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
862 return 0; 893 return 0;
863} 894}
864 895
896int ipv6_getsockopt(struct sock *sk, int level, int optname,
897 char __user *optval, int __user *optlen)
898{
899 int err;
900
901 if (level == SOL_IP && sk->sk_type != SOCK_RAW)
902 return udp_prot.getsockopt(sk, level, optname, optval, optlen);
903
904 if(level != SOL_IPV6)
905 return -ENOPROTOOPT;
906
907 err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
908#ifdef CONFIG_NETFILTER
909 /* we need to exclude all possible EINVALs except default case */
910 if (err == -ENOPROTOOPT && optname != IPV6_ADDRFORM &&
911 optname != MCAST_MSFILTER) {
912 int len;
913
914 if (get_user(len, optlen))
915 return -EFAULT;
916
917 lock_sock(sk);
918 err = nf_getsockopt(sk, PF_INET6, optname, optval,
919 &len);
920 release_sock(sk);
921 if (err >= 0)
922 err = put_user(len, optlen);
923 }
924#endif
925 return err;
926}
927
928#ifdef CONFIG_COMPAT
929int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
930 char __user *optval, int __user *optlen)
931{
932 int err;
933
934 if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
935 if (udp_prot.compat_getsockopt)
936 return udp_prot.compat_getsockopt(sk, level,
937 optname, optval, optlen);
938 else
939 return udp_prot.getsockopt(sk, level,
940 optname, optval, optlen);
941 }
942
943 if(level != SOL_IPV6)
944 return -ENOPROTOOPT;
945
946 err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
947#ifdef CONFIG_NETFILTER
948 /* we need to exclude all possible EINVALs except default case */
949 if (err == -ENOPROTOOPT && optname != IPV6_ADDRFORM &&
950 optname != MCAST_MSFILTER) {
951 int len;
952
953 if (get_user(len, optlen))
954 return -EFAULT;
955
956 lock_sock(sk);
957 err = compat_nf_getsockopt(sk, PF_INET6, optname, optval,
958 &len);
959 release_sock(sk);
960 if (err >= 0)
961 err = put_user(len, optlen);
962 }
963#endif
964 return err;
965}
966#endif
967
865void __init ipv6_packet_init(void) 968void __init ipv6_packet_init(void)
866{ 969{
867 dev_add_pack(&ipv6_packet_type); 970 dev_add_pack(&ipv6_packet_type);
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c
index 16482785bdfd..61419e11e35d 100644
--- a/net/ipv6/ipv6_syms.c
+++ b/net/ipv6/ipv6_syms.c
@@ -18,6 +18,10 @@ EXPORT_SYMBOL(ip6_route_output);
18EXPORT_SYMBOL(addrconf_lock); 18EXPORT_SYMBOL(addrconf_lock);
19EXPORT_SYMBOL(ipv6_setsockopt); 19EXPORT_SYMBOL(ipv6_setsockopt);
20EXPORT_SYMBOL(ipv6_getsockopt); 20EXPORT_SYMBOL(ipv6_getsockopt);
21#ifdef CONFIG_COMPAT
22EXPORT_SYMBOL(compat_ipv6_setsockopt);
23EXPORT_SYMBOL(compat_ipv6_getsockopt);
24#endif
21EXPORT_SYMBOL(inet6_register_protosw); 25EXPORT_SYMBOL(inet6_register_protosw);
22EXPORT_SYMBOL(inet6_unregister_protosw); 26EXPORT_SYMBOL(inet6_unregister_protosw);
23EXPORT_SYMBOL(inet6_add_protocol); 27EXPORT_SYMBOL(inet6_add_protocol);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index ae20a0ec9bd8..8de5a8e59149 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -859,29 +859,12 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname,
859} 859}
860 860
861 861
862static int rawv6_setsockopt(struct sock *sk, int level, int optname, 862static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
863 char __user *optval, int optlen) 863 char __user *optval, int optlen)
864{ 864{
865 struct raw6_sock *rp = raw6_sk(sk); 865 struct raw6_sock *rp = raw6_sk(sk);
866 int val; 866 int val;
867 867
868 switch(level) {
869 case SOL_RAW:
870 break;
871
872 case SOL_ICMPV6:
873 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
874 return -EOPNOTSUPP;
875 return rawv6_seticmpfilter(sk, level, optname, optval,
876 optlen);
877 case SOL_IPV6:
878 if (optname == IPV6_CHECKSUM)
879 break;
880 default:
881 return ipv6_setsockopt(sk, level, optname, optval,
882 optlen);
883 };
884
885 if (get_user(val, (int __user *)optval)) 868 if (get_user(val, (int __user *)optval))
886 return -EFAULT; 869 return -EFAULT;
887 870
@@ -906,12 +889,9 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname,
906 } 889 }
907} 890}
908 891
909static int rawv6_getsockopt(struct sock *sk, int level, int optname, 892static int rawv6_setsockopt(struct sock *sk, int level, int optname,
910 char __user *optval, int __user *optlen) 893 char __user *optval, int optlen)
911{ 894{
912 struct raw6_sock *rp = raw6_sk(sk);
913 int val, len;
914
915 switch(level) { 895 switch(level) {
916 case SOL_RAW: 896 case SOL_RAW:
917 break; 897 break;
@@ -919,15 +899,47 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
919 case SOL_ICMPV6: 899 case SOL_ICMPV6:
920 if (inet_sk(sk)->num != IPPROTO_ICMPV6) 900 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
921 return -EOPNOTSUPP; 901 return -EOPNOTSUPP;
922 return rawv6_geticmpfilter(sk, level, optname, optval, 902 return rawv6_seticmpfilter(sk, level, optname, optval,
923 optlen); 903 optlen);
924 case SOL_IPV6: 904 case SOL_IPV6:
925 if (optname == IPV6_CHECKSUM) 905 if (optname == IPV6_CHECKSUM)
926 break; 906 break;
927 default: 907 default:
928 return ipv6_getsockopt(sk, level, optname, optval, 908 return ipv6_setsockopt(sk, level, optname, optval,
929 optlen); 909 optlen);
930 }; 910 };
911 return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
912}
913
914#ifdef CONFIG_COMPAT
915static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname,
916 char __user *optval, int optlen)
917{
918 switch(level) {
919 case SOL_RAW:
920 break;
921
922 case SOL_ICMPV6:
923 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
924 return -EOPNOTSUPP;
925 return rawv6_seticmpfilter(sk, level, optname, optval,
926 optlen);
927 case SOL_IPV6:
928 if (optname == IPV6_CHECKSUM)
929 break;
930 default:
931 return compat_ipv6_setsockopt(sk, level,
932 optname, optval, optlen);
933 };
934 return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
935}
936#endif
937
938static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
939 char __user *optval, int __user *optlen)
940{
941 struct raw6_sock *rp = raw6_sk(sk);
942 int val, len;
931 943
932 if (get_user(len,optlen)) 944 if (get_user(len,optlen))
933 return -EFAULT; 945 return -EFAULT;
@@ -953,6 +965,52 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
953 return 0; 965 return 0;
954} 966}
955 967
968static int rawv6_getsockopt(struct sock *sk, int level, int optname,
969 char __user *optval, int __user *optlen)
970{
971 switch(level) {
972 case SOL_RAW:
973 break;
974
975 case SOL_ICMPV6:
976 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
977 return -EOPNOTSUPP;
978 return rawv6_geticmpfilter(sk, level, optname, optval,
979 optlen);
980 case SOL_IPV6:
981 if (optname == IPV6_CHECKSUM)
982 break;
983 default:
984 return ipv6_getsockopt(sk, level, optname, optval,
985 optlen);
986 };
987 return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
988}
989
990#ifdef CONFIG_COMPAT
991static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname,
992 char __user *optval, int __user *optlen)
993{
994 switch(level) {
995 case SOL_RAW:
996 break;
997
998 case SOL_ICMPV6:
999 if (inet_sk(sk)->num != IPPROTO_ICMPV6)
1000 return -EOPNOTSUPP;
1001 return rawv6_geticmpfilter(sk, level, optname, optval,
1002 optlen);
1003 case SOL_IPV6:
1004 if (optname == IPV6_CHECKSUM)
1005 break;
1006 default:
1007 return compat_ipv6_getsockopt(sk, level,
1008 optname, optval, optlen);
1009 };
1010 return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
1011}
1012#endif
1013
956static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) 1014static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
957{ 1015{
958 switch(cmd) { 1016 switch(cmd) {
@@ -1008,6 +1066,10 @@ struct proto rawv6_prot = {
1008 .destroy = inet6_destroy_sock, 1066 .destroy = inet6_destroy_sock,
1009 .setsockopt = rawv6_setsockopt, 1067 .setsockopt = rawv6_setsockopt,
1010 .getsockopt = rawv6_getsockopt, 1068 .getsockopt = rawv6_getsockopt,
1069#ifdef CONFIG_COMPAT
1070 .compat_setsockopt = compat_rawv6_setsockopt,
1071 .compat_getsockopt = compat_rawv6_getsockopt,
1072#endif
1011 .sendmsg = rawv6_sendmsg, 1073 .sendmsg = rawv6_sendmsg,
1012 .recvmsg = rawv6_recvmsg, 1074 .recvmsg = rawv6_recvmsg,
1013 .bind = rawv6_bind, 1075 .bind = rawv6_bind,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index af6a0c60f903..2f8975e0150a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1308,6 +1308,10 @@ static struct inet_connection_sock_af_ops ipv6_specific = {
1308 1308
1309 .setsockopt = ipv6_setsockopt, 1309 .setsockopt = ipv6_setsockopt,
1310 .getsockopt = ipv6_getsockopt, 1310 .getsockopt = ipv6_getsockopt,
1311#ifdef CONFIG_COMPAT
1312 .compat_setsockopt = compat_ipv6_setsockopt,
1313 .compat_getsockopt = compat_ipv6_getsockopt,
1314#endif
1311 .addr2sockaddr = inet6_csk_addr2sockaddr, 1315 .addr2sockaddr = inet6_csk_addr2sockaddr,
1312 .sockaddr_len = sizeof(struct sockaddr_in6) 1316 .sockaddr_len = sizeof(struct sockaddr_in6)
1313}; 1317};
@@ -1327,6 +1331,10 @@ static struct inet_connection_sock_af_ops ipv6_mapped = {
1327 1331
1328 .setsockopt = ipv6_setsockopt, 1332 .setsockopt = ipv6_setsockopt,
1329 .getsockopt = ipv6_getsockopt, 1333 .getsockopt = ipv6_getsockopt,
1334#ifdef CONFIG_COMPAT
1335 .compat_setsockopt = compat_ipv6_setsockopt,
1336 .compat_getsockopt = compat_ipv6_getsockopt,
1337#endif
1330 .addr2sockaddr = inet6_csk_addr2sockaddr, 1338 .addr2sockaddr = inet6_csk_addr2sockaddr,
1331 .sockaddr_len = sizeof(struct sockaddr_in6) 1339 .sockaddr_len = sizeof(struct sockaddr_in6)
1332}; 1340};
@@ -1566,6 +1574,10 @@ struct proto tcpv6_prot = {
1566 .shutdown = tcp_shutdown, 1574 .shutdown = tcp_shutdown,
1567 .setsockopt = tcp_setsockopt, 1575 .setsockopt = tcp_setsockopt,
1568 .getsockopt = tcp_getsockopt, 1576 .getsockopt = tcp_getsockopt,
1577#ifdef CONFIG_COMPAT
1578 .compat_setsockopt = compat_tcp_setsockopt,
1579 .compat_getsockopt = compat_tcp_getsockopt,
1580#endif
1569 .sendmsg = tcp_sendmsg, 1581 .sendmsg = tcp_sendmsg,
1570 .recvmsg = tcp_recvmsg, 1582 .recvmsg = tcp_recvmsg,
1571 .backlog_rcv = tcp_v6_do_rcv, 1583 .backlog_rcv = tcp_v6_do_rcv,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index c47648892c04..538ada00646a 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -880,16 +880,13 @@ static int udpv6_destroy_sock(struct sock *sk)
880/* 880/*
881 * Socket option code for UDP 881 * Socket option code for UDP
882 */ 882 */
883static int udpv6_setsockopt(struct sock *sk, int level, int optname, 883static int do_udpv6_setsockopt(struct sock *sk, int level, int optname,
884 char __user *optval, int optlen) 884 char __user *optval, int optlen)
885{ 885{
886 struct udp_sock *up = udp_sk(sk); 886 struct udp_sock *up = udp_sk(sk);
887 int val; 887 int val;
888 int err = 0; 888 int err = 0;
889 889
890 if (level != SOL_UDP)
891 return ipv6_setsockopt(sk, level, optname, optval, optlen);
892
893 if(optlen<sizeof(int)) 890 if(optlen<sizeof(int))
894 return -EINVAL; 891 return -EINVAL;
895 892
@@ -927,15 +924,31 @@ static int udpv6_setsockopt(struct sock *sk, int level, int optname,
927 return err; 924 return err;
928} 925}
929 926
930static int udpv6_getsockopt(struct sock *sk, int level, int optname, 927static int udpv6_setsockopt(struct sock *sk, int level, int optname,
928 char __user *optval, int optlen)
929{
930 if (level != SOL_UDP)
931 return ipv6_setsockopt(sk, level, optname, optval, optlen);
932 return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
933}
934
935#ifdef CONFIG_COMPAT
936static int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
937 char __user *optval, int optlen)
938{
939 if (level != SOL_UDP)
940 return compat_ipv6_setsockopt(sk, level,
941 optname, optval, optlen);
942 return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
943}
944#endif
945
946static int do_udpv6_getsockopt(struct sock *sk, int level, int optname,
931 char __user *optval, int __user *optlen) 947 char __user *optval, int __user *optlen)
932{ 948{
933 struct udp_sock *up = udp_sk(sk); 949 struct udp_sock *up = udp_sk(sk);
934 int val, len; 950 int val, len;
935 951
936 if (level != SOL_UDP)
937 return ipv6_getsockopt(sk, level, optname, optval, optlen);
938
939 if(get_user(len,optlen)) 952 if(get_user(len,optlen))
940 return -EFAULT; 953 return -EFAULT;
941 954
@@ -964,6 +977,25 @@ static int udpv6_getsockopt(struct sock *sk, int level, int optname,
964 return 0; 977 return 0;
965} 978}
966 979
980static int udpv6_getsockopt(struct sock *sk, int level, int optname,
981 char __user *optval, int __user *optlen)
982{
983 if (level != SOL_UDP)
984 return ipv6_getsockopt(sk, level, optname, optval, optlen);
985 return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
986}
987
988#ifdef CONFIG_COMPAT
989static int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
990 char __user *optval, int __user *optlen)
991{
992 if (level != SOL_UDP)
993 return compat_ipv6_getsockopt(sk, level,
994 optname, optval, optlen);
995 return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
996}
997#endif
998
967static struct inet6_protocol udpv6_protocol = { 999static struct inet6_protocol udpv6_protocol = {
968 .handler = udpv6_rcv, 1000 .handler = udpv6_rcv,
969 .err_handler = udpv6_err, 1001 .err_handler = udpv6_err,
@@ -1046,6 +1078,10 @@ struct proto udpv6_prot = {
1046 .destroy = udpv6_destroy_sock, 1078 .destroy = udpv6_destroy_sock,
1047 .setsockopt = udpv6_setsockopt, 1079 .setsockopt = udpv6_setsockopt,
1048 .getsockopt = udpv6_getsockopt, 1080 .getsockopt = udpv6_getsockopt,
1081#ifdef CONFIG_COMPAT
1082 .compat_setsockopt = compat_udpv6_setsockopt,
1083 .compat_getsockopt = compat_udpv6_getsockopt,
1084#endif
1049 .sendmsg = udpv6_sendmsg, 1085 .sendmsg = udpv6_sendmsg,
1050 .recvmsg = udpv6_recvmsg, 1086 .recvmsg = udpv6_recvmsg,
1051 .backlog_rcv = udpv6_queue_rcv_skb, 1087 .backlog_rcv = udpv6_queue_rcv_skb,