diff options
author | Dmitry Mishin <dim@openvz.org> | 2006-03-21 01:45:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-21 01:45:21 -0500 |
commit | 3fdadf7d27e3fbcf72930941884387d1f4936f04 (patch) | |
tree | 167072cf1e60b6b307610563614b435ff0caa52d /net/ipv4 | |
parent | c750360938b403e6cc193d293cfbcb099dd6c60e (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/ipv4')
-rw-r--r-- | net/ipv4/af_inet.c | 12 | ||||
-rw-r--r-- | net/ipv4/ip_sockglue.c | 142 | ||||
-rw-r--r-- | net/ipv4/raw.c | 50 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 77 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 8 | ||||
-rw-r--r-- | net/ipv4/udp.c | 51 |
6 files changed, 294 insertions, 46 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 97c276f95b35..454e523b506a 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -802,6 +802,10 @@ const struct proto_ops inet_stream_ops = { | |||
802 | .shutdown = inet_shutdown, | 802 | .shutdown = inet_shutdown, |
803 | .setsockopt = sock_common_setsockopt, | 803 | .setsockopt = sock_common_setsockopt, |
804 | .getsockopt = sock_common_getsockopt, | 804 | .getsockopt = sock_common_getsockopt, |
805 | #ifdef CONFIG_COMPAT | ||
806 | .compat_setsockopt = compat_sock_common_setsockopt, | ||
807 | .compat_getsockopt = compat_sock_common_getsockopt, | ||
808 | #endif | ||
805 | .sendmsg = inet_sendmsg, | 809 | .sendmsg = inet_sendmsg, |
806 | .recvmsg = sock_common_recvmsg, | 810 | .recvmsg = sock_common_recvmsg, |
807 | .mmap = sock_no_mmap, | 811 | .mmap = sock_no_mmap, |
@@ -823,6 +827,10 @@ const struct proto_ops inet_dgram_ops = { | |||
823 | .shutdown = inet_shutdown, | 827 | .shutdown = inet_shutdown, |
824 | .setsockopt = sock_common_setsockopt, | 828 | .setsockopt = sock_common_setsockopt, |
825 | .getsockopt = sock_common_getsockopt, | 829 | .getsockopt = sock_common_getsockopt, |
830 | #ifdef CONFIG_COMPAT | ||
831 | .compat_setsockopt = compat_sock_common_setsockopt, | ||
832 | .compat_getsockopt = compat_sock_common_getsockopt, | ||
833 | #endif | ||
826 | .sendmsg = inet_sendmsg, | 834 | .sendmsg = inet_sendmsg, |
827 | .recvmsg = sock_common_recvmsg, | 835 | .recvmsg = sock_common_recvmsg, |
828 | .mmap = sock_no_mmap, | 836 | .mmap = sock_no_mmap, |
@@ -848,6 +856,10 @@ static const struct proto_ops inet_sockraw_ops = { | |||
848 | .shutdown = inet_shutdown, | 856 | .shutdown = inet_shutdown, |
849 | .setsockopt = sock_common_setsockopt, | 857 | .setsockopt = sock_common_setsockopt, |
850 | .getsockopt = sock_common_getsockopt, | 858 | .getsockopt = sock_common_getsockopt, |
859 | #ifdef CONFIG_COMPAT | ||
860 | .compat_setsockopt = compat_sock_common_setsockopt, | ||
861 | .compat_getsockopt = compat_sock_common_getsockopt, | ||
862 | #endif | ||
851 | .sendmsg = inet_sendmsg, | 863 | .sendmsg = inet_sendmsg, |
852 | .recvmsg = sock_common_recvmsg, | 864 | .recvmsg = sock_common_recvmsg, |
853 | .mmap = sock_no_mmap, | 865 | .mmap = sock_no_mmap, |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index b5c4f61518e8..49ff1cd4e1c9 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -399,14 +399,12 @@ out: | |||
399 | * an IP socket. | 399 | * an IP socket. |
400 | */ | 400 | */ |
401 | 401 | ||
402 | int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) | 402 | static int do_ip_setsockopt(struct sock *sk, int level, |
403 | int optname, char __user *optval, int optlen) | ||
403 | { | 404 | { |
404 | struct inet_sock *inet = inet_sk(sk); | 405 | struct inet_sock *inet = inet_sk(sk); |
405 | int val=0,err; | 406 | int val=0,err; |
406 | 407 | ||
407 | if (level != SOL_IP) | ||
408 | return -ENOPROTOOPT; | ||
409 | |||
410 | if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | | 408 | if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | |
411 | (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | | 409 | (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | |
412 | (1<<IP_RETOPTS) | (1<<IP_TOS) | | 410 | (1<<IP_RETOPTS) | (1<<IP_TOS) | |
@@ -875,12 +873,7 @@ mc_msf_out: | |||
875 | break; | 873 | break; |
876 | 874 | ||
877 | default: | 875 | default: |
878 | #ifdef CONFIG_NETFILTER | ||
879 | err = nf_setsockopt(sk, PF_INET, optname, optval, | ||
880 | optlen); | ||
881 | #else | ||
882 | err = -ENOPROTOOPT; | 876 | err = -ENOPROTOOPT; |
883 | #endif | ||
884 | break; | 877 | break; |
885 | } | 878 | } |
886 | release_sock(sk); | 879 | release_sock(sk); |
@@ -891,12 +884,66 @@ e_inval: | |||
891 | return -EINVAL; | 884 | return -EINVAL; |
892 | } | 885 | } |
893 | 886 | ||
887 | int ip_setsockopt(struct sock *sk, int level, | ||
888 | int optname, char __user *optval, int optlen) | ||
889 | { | ||
890 | int err; | ||
891 | |||
892 | if (level != SOL_IP) | ||
893 | return -ENOPROTOOPT; | ||
894 | |||
895 | err = do_ip_setsockopt(sk, level, optname, optval, optlen); | ||
896 | #ifdef CONFIG_NETFILTER | ||
897 | /* we need to exclude all possible ENOPROTOOPTs except default case */ | ||
898 | if (err == -ENOPROTOOPT && optname != IP_HDRINCL && | ||
899 | optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY | ||
900 | #ifdef CONFIG_IP_MROUTE | ||
901 | && (optname < MRT_BASE || optname > (MRT_BASE + 10)) | ||
902 | #endif | ||
903 | ) { | ||
904 | lock_sock(sk); | ||
905 | err = nf_setsockopt(sk, PF_INET, optname, optval, optlen); | ||
906 | release_sock(sk); | ||
907 | } | ||
908 | #endif | ||
909 | return err; | ||
910 | } | ||
911 | |||
912 | #ifdef CONFIG_COMPAT | ||
913 | int compat_ip_setsockopt(struct sock *sk, int level, | ||
914 | int optname, char __user *optval, int optlen) | ||
915 | { | ||
916 | int err; | ||
917 | |||
918 | if (level != SOL_IP) | ||
919 | return -ENOPROTOOPT; | ||
920 | |||
921 | err = do_ip_setsockopt(sk, level, optname, optval, optlen); | ||
922 | #ifdef CONFIG_NETFILTER | ||
923 | /* we need to exclude all possible ENOPROTOOPTs except default case */ | ||
924 | if (err == -ENOPROTOOPT && optname != IP_HDRINCL && | ||
925 | optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY | ||
926 | #ifdef CONFIG_IP_MROUTE | ||
927 | && (optname < MRT_BASE || optname > (MRT_BASE + 10)) | ||
928 | #endif | ||
929 | ) { | ||
930 | lock_sock(sk); | ||
931 | err = compat_nf_setsockopt(sk, PF_INET, | ||
932 | optname, optval, optlen); | ||
933 | release_sock(sk); | ||
934 | } | ||
935 | #endif | ||
936 | return err; | ||
937 | } | ||
938 | #endif | ||
939 | |||
894 | /* | 940 | /* |
895 | * Get the options. Note for future reference. The GET of IP options gets the | 941 | * Get the options. Note for future reference. The GET of IP options gets the |
896 | * _received_ ones. The set sets the _sent_ ones. | 942 | * _received_ ones. The set sets the _sent_ ones. |
897 | */ | 943 | */ |
898 | 944 | ||
899 | int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) | 945 | static int do_ip_getsockopt(struct sock *sk, int level, int optname, |
946 | char __user *optval, int __user *optlen) | ||
900 | { | 947 | { |
901 | struct inet_sock *inet = inet_sk(sk); | 948 | struct inet_sock *inet = inet_sk(sk); |
902 | int val; | 949 | int val; |
@@ -1080,17 +1127,8 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, | |||
1080 | val = inet->freebind; | 1127 | val = inet->freebind; |
1081 | break; | 1128 | break; |
1082 | default: | 1129 | default: |
1083 | #ifdef CONFIG_NETFILTER | ||
1084 | val = nf_getsockopt(sk, PF_INET, optname, optval, | ||
1085 | &len); | ||
1086 | release_sock(sk); | ||
1087 | if (val >= 0) | ||
1088 | val = put_user(len, optlen); | ||
1089 | return val; | ||
1090 | #else | ||
1091 | release_sock(sk); | 1130 | release_sock(sk); |
1092 | return -ENOPROTOOPT; | 1131 | return -ENOPROTOOPT; |
1093 | #endif | ||
1094 | } | 1132 | } |
1095 | release_sock(sk); | 1133 | release_sock(sk); |
1096 | 1134 | ||
@@ -1111,7 +1149,73 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, | |||
1111 | return 0; | 1149 | return 0; |
1112 | } | 1150 | } |
1113 | 1151 | ||
1152 | int ip_getsockopt(struct sock *sk, int level, | ||
1153 | int optname, char __user *optval, int __user *optlen) | ||
1154 | { | ||
1155 | int err; | ||
1156 | |||
1157 | err = do_ip_getsockopt(sk, level, optname, optval, optlen); | ||
1158 | #ifdef CONFIG_NETFILTER | ||
1159 | /* we need to exclude all possible ENOPROTOOPTs except default case */ | ||
1160 | if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS | ||
1161 | #ifdef CONFIG_IP_MROUTE | ||
1162 | && (optname < MRT_BASE || optname > MRT_BASE+10) | ||
1163 | #endif | ||
1164 | ) { | ||
1165 | int len; | ||
1166 | |||
1167 | if(get_user(len,optlen)) | ||
1168 | return -EFAULT; | ||
1169 | |||
1170 | lock_sock(sk); | ||
1171 | err = nf_getsockopt(sk, PF_INET, optname, optval, | ||
1172 | &len); | ||
1173 | release_sock(sk); | ||
1174 | if (err >= 0) | ||
1175 | err = put_user(len, optlen); | ||
1176 | return err; | ||
1177 | } | ||
1178 | #endif | ||
1179 | return err; | ||
1180 | } | ||
1181 | |||
1182 | #ifdef CONFIG_COMPAT | ||
1183 | int compat_ip_getsockopt(struct sock *sk, int level, | ||
1184 | int optname, char __user *optval, int __user *optlen) | ||
1185 | { | ||
1186 | int err; | ||
1187 | |||
1188 | err = do_ip_getsockopt(sk, level, optname, optval, optlen); | ||
1189 | #ifdef CONFIG_NETFILTER | ||
1190 | /* we need to exclude all possible ENOPROTOOPTs except default case */ | ||
1191 | if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS | ||
1192 | #ifdef CONFIG_IP_MROUTE | ||
1193 | && (optname < MRT_BASE || optname > MRT_BASE+10) | ||
1194 | #endif | ||
1195 | ) { | ||
1196 | int len; | ||
1197 | |||
1198 | if(get_user(len,optlen)) | ||
1199 | return -EFAULT; | ||
1200 | |||
1201 | lock_sock(sk); | ||
1202 | err = compat_nf_getsockopt(sk, PF_INET, | ||
1203 | optname, optval, &len); | ||
1204 | release_sock(sk); | ||
1205 | if (err >= 0) | ||
1206 | err = put_user(len, optlen); | ||
1207 | return err; | ||
1208 | } | ||
1209 | #endif | ||
1210 | return err; | ||
1211 | } | ||
1212 | #endif | ||
1213 | |||
1114 | EXPORT_SYMBOL(ip_cmsg_recv); | 1214 | EXPORT_SYMBOL(ip_cmsg_recv); |
1115 | 1215 | ||
1116 | EXPORT_SYMBOL(ip_getsockopt); | 1216 | EXPORT_SYMBOL(ip_getsockopt); |
1117 | EXPORT_SYMBOL(ip_setsockopt); | 1217 | EXPORT_SYMBOL(ip_setsockopt); |
1218 | #ifdef CONFIG_COMPAT | ||
1219 | EXPORT_SYMBOL(compat_ip_getsockopt); | ||
1220 | EXPORT_SYMBOL(compat_ip_setsockopt); | ||
1221 | #endif | ||
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index f29a12da5109..f1b02b34fc0a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -660,12 +660,9 @@ static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *o | |||
660 | out: return ret; | 660 | out: return ret; |
661 | } | 661 | } |
662 | 662 | ||
663 | static int raw_setsockopt(struct sock *sk, int level, int optname, | 663 | static int do_raw_setsockopt(struct sock *sk, int level, int optname, |
664 | char __user *optval, int optlen) | 664 | char __user *optval, int optlen) |
665 | { | 665 | { |
666 | if (level != SOL_RAW) | ||
667 | return ip_setsockopt(sk, level, optname, optval, optlen); | ||
668 | |||
669 | if (optname == ICMP_FILTER) { | 666 | if (optname == ICMP_FILTER) { |
670 | if (inet_sk(sk)->num != IPPROTO_ICMP) | 667 | if (inet_sk(sk)->num != IPPROTO_ICMP) |
671 | return -EOPNOTSUPP; | 668 | return -EOPNOTSUPP; |
@@ -675,12 +672,28 @@ static int raw_setsockopt(struct sock *sk, int level, int optname, | |||
675 | return -ENOPROTOOPT; | 672 | return -ENOPROTOOPT; |
676 | } | 673 | } |
677 | 674 | ||
678 | static int raw_getsockopt(struct sock *sk, int level, int optname, | 675 | static int raw_setsockopt(struct sock *sk, int level, int optname, |
679 | char __user *optval, int __user *optlen) | 676 | char __user *optval, int optlen) |
680 | { | 677 | { |
681 | if (level != SOL_RAW) | 678 | if (level != SOL_RAW) |
682 | return ip_getsockopt(sk, level, optname, optval, optlen); | 679 | return ip_setsockopt(sk, level, optname, optval, optlen); |
680 | return do_raw_setsockopt(sk, level, optname, optval, optlen); | ||
681 | } | ||
683 | 682 | ||
683 | #ifdef CONFIG_COMPAT | ||
684 | static int compat_raw_setsockopt(struct sock *sk, int level, int optname, | ||
685 | char __user *optval, int optlen) | ||
686 | { | ||
687 | if (level != SOL_RAW) | ||
688 | return compat_ip_setsockopt(sk, level, | ||
689 | optname, optval, optlen); | ||
690 | return do_raw_setsockopt(sk, level, optname, optval, optlen); | ||
691 | } | ||
692 | #endif | ||
693 | |||
694 | static int do_raw_getsockopt(struct sock *sk, int level, int optname, | ||
695 | char __user *optval, int __user *optlen) | ||
696 | { | ||
684 | if (optname == ICMP_FILTER) { | 697 | if (optname == ICMP_FILTER) { |
685 | if (inet_sk(sk)->num != IPPROTO_ICMP) | 698 | if (inet_sk(sk)->num != IPPROTO_ICMP) |
686 | return -EOPNOTSUPP; | 699 | return -EOPNOTSUPP; |
@@ -690,6 +703,25 @@ static int raw_getsockopt(struct sock *sk, int level, int optname, | |||
690 | return -ENOPROTOOPT; | 703 | return -ENOPROTOOPT; |
691 | } | 704 | } |
692 | 705 | ||
706 | static int raw_getsockopt(struct sock *sk, int level, int optname, | ||
707 | char __user *optval, int __user *optlen) | ||
708 | { | ||
709 | if (level != SOL_RAW) | ||
710 | return ip_getsockopt(sk, level, optname, optval, optlen); | ||
711 | return do_raw_getsockopt(sk, level, optname, optval, optlen); | ||
712 | } | ||
713 | |||
714 | #ifdef CONFIG_COMPAT | ||
715 | static int compat_raw_getsockopt(struct sock *sk, int level, int optname, | ||
716 | char __user *optval, int __user *optlen) | ||
717 | { | ||
718 | if (level != SOL_RAW) | ||
719 | return compat_ip_getsockopt(sk, level, | ||
720 | optname, optval, optlen); | ||
721 | return do_raw_getsockopt(sk, level, optname, optval, optlen); | ||
722 | } | ||
723 | #endif | ||
724 | |||
693 | static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) | 725 | static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) |
694 | { | 726 | { |
695 | switch (cmd) { | 727 | switch (cmd) { |
@@ -728,6 +760,10 @@ struct proto raw_prot = { | |||
728 | .init = raw_init, | 760 | .init = raw_init, |
729 | .setsockopt = raw_setsockopt, | 761 | .setsockopt = raw_setsockopt, |
730 | .getsockopt = raw_getsockopt, | 762 | .getsockopt = raw_getsockopt, |
763 | #ifdef CONFIG_COMPAT | ||
764 | .compat_setsockopt = compat_raw_setsockopt, | ||
765 | .compat_getsockopt = compat_raw_getsockopt, | ||
766 | #endif | ||
731 | .sendmsg = raw_sendmsg, | 767 | .sendmsg = raw_sendmsg, |
732 | .recvmsg = raw_recvmsg, | 768 | .recvmsg = raw_recvmsg, |
733 | .bind = raw_bind, | 769 | .bind = raw_bind, |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 00aa80e93243..31b0123a9699 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1687,18 +1687,14 @@ int tcp_disconnect(struct sock *sk, int flags) | |||
1687 | /* | 1687 | /* |
1688 | * Socket option code for TCP. | 1688 | * Socket option code for TCP. |
1689 | */ | 1689 | */ |
1690 | int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | 1690 | static int do_tcp_setsockopt(struct sock *sk, int level, |
1691 | int optlen) | 1691 | int optname, char __user *optval, int optlen) |
1692 | { | 1692 | { |
1693 | struct tcp_sock *tp = tcp_sk(sk); | 1693 | struct tcp_sock *tp = tcp_sk(sk); |
1694 | struct inet_connection_sock *icsk = inet_csk(sk); | 1694 | struct inet_connection_sock *icsk = inet_csk(sk); |
1695 | int val; | 1695 | int val; |
1696 | int err = 0; | 1696 | int err = 0; |
1697 | 1697 | ||
1698 | if (level != SOL_TCP) | ||
1699 | return icsk->icsk_af_ops->setsockopt(sk, level, optname, | ||
1700 | optval, optlen); | ||
1701 | |||
1702 | /* This is a string value all the others are int's */ | 1698 | /* This is a string value all the others are int's */ |
1703 | if (optname == TCP_CONGESTION) { | 1699 | if (optname == TCP_CONGESTION) { |
1704 | char name[TCP_CA_NAME_MAX]; | 1700 | char name[TCP_CA_NAME_MAX]; |
@@ -1871,6 +1867,35 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | |||
1871 | return err; | 1867 | return err; |
1872 | } | 1868 | } |
1873 | 1869 | ||
1870 | int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | ||
1871 | int optlen) | ||
1872 | { | ||
1873 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
1874 | |||
1875 | if (level != SOL_TCP) | ||
1876 | return icsk->icsk_af_ops->setsockopt(sk, level, optname, | ||
1877 | optval, optlen); | ||
1878 | return do_tcp_setsockopt(sk, level, optname, optval, optlen); | ||
1879 | } | ||
1880 | |||
1881 | #ifdef CONFIG_COMPAT | ||
1882 | int compat_tcp_setsockopt(struct sock *sk, int level, | ||
1883 | int optname, char __user *optval, int optlen) | ||
1884 | { | ||
1885 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
1886 | |||
1887 | if (level != SOL_TCP) { | ||
1888 | if (icsk->icsk_af_ops->compat_setsockopt) | ||
1889 | return icsk->icsk_af_ops->compat_setsockopt(sk, | ||
1890 | level, optname, optval, optlen); | ||
1891 | else | ||
1892 | return icsk->icsk_af_ops->setsockopt(sk, | ||
1893 | level, optname, optval, optlen); | ||
1894 | } | ||
1895 | return do_tcp_setsockopt(sk, level, optname, optval, optlen); | ||
1896 | } | ||
1897 | #endif | ||
1898 | |||
1874 | /* Return information about state of tcp endpoint in API format. */ | 1899 | /* Return information about state of tcp endpoint in API format. */ |
1875 | void tcp_get_info(struct sock *sk, struct tcp_info *info) | 1900 | void tcp_get_info(struct sock *sk, struct tcp_info *info) |
1876 | { | 1901 | { |
@@ -1931,17 +1956,13 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
1931 | 1956 | ||
1932 | EXPORT_SYMBOL_GPL(tcp_get_info); | 1957 | EXPORT_SYMBOL_GPL(tcp_get_info); |
1933 | 1958 | ||
1934 | int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, | 1959 | static int do_tcp_getsockopt(struct sock *sk, int level, |
1935 | int __user *optlen) | 1960 | int optname, char __user *optval, int __user *optlen) |
1936 | { | 1961 | { |
1937 | struct inet_connection_sock *icsk = inet_csk(sk); | 1962 | struct inet_connection_sock *icsk = inet_csk(sk); |
1938 | struct tcp_sock *tp = tcp_sk(sk); | 1963 | struct tcp_sock *tp = tcp_sk(sk); |
1939 | int val, len; | 1964 | int val, len; |
1940 | 1965 | ||
1941 | if (level != SOL_TCP) | ||
1942 | return icsk->icsk_af_ops->getsockopt(sk, level, optname, | ||
1943 | optval, optlen); | ||
1944 | |||
1945 | if (get_user(len, optlen)) | 1966 | if (get_user(len, optlen)) |
1946 | return -EFAULT; | 1967 | return -EFAULT; |
1947 | 1968 | ||
@@ -2025,6 +2046,34 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, | |||
2025 | return 0; | 2046 | return 0; |
2026 | } | 2047 | } |
2027 | 2048 | ||
2049 | int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, | ||
2050 | int __user *optlen) | ||
2051 | { | ||
2052 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
2053 | |||
2054 | if (level != SOL_TCP) | ||
2055 | return icsk->icsk_af_ops->getsockopt(sk, level, optname, | ||
2056 | optval, optlen); | ||
2057 | return do_tcp_getsockopt(sk, level, optname, optval, optlen); | ||
2058 | } | ||
2059 | |||
2060 | #ifdef CONFIG_COMPAT | ||
2061 | int compat_tcp_getsockopt(struct sock *sk, int level, | ||
2062 | int optname, char __user *optval, int __user *optlen) | ||
2063 | { | ||
2064 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
2065 | |||
2066 | if (level != SOL_TCP) { | ||
2067 | if (icsk->icsk_af_ops->compat_getsockopt) | ||
2068 | return icsk->icsk_af_ops->compat_getsockopt(sk, | ||
2069 | level, optname, optval, optlen); | ||
2070 | else | ||
2071 | return icsk->icsk_af_ops->getsockopt(sk, | ||
2072 | level, optname, optval, optlen); | ||
2073 | } | ||
2074 | return do_tcp_getsockopt(sk, level, optname, optval, optlen); | ||
2075 | } | ||
2076 | #endif | ||
2028 | 2077 | ||
2029 | extern void __skb_cb_too_small_for_tcp(int, int); | 2078 | extern void __skb_cb_too_small_for_tcp(int, int); |
2030 | extern struct tcp_congestion_ops tcp_reno; | 2079 | extern struct tcp_congestion_ops tcp_reno; |
@@ -2142,3 +2191,7 @@ EXPORT_SYMBOL(tcp_sendpage); | |||
2142 | EXPORT_SYMBOL(tcp_setsockopt); | 2191 | EXPORT_SYMBOL(tcp_setsockopt); |
2143 | EXPORT_SYMBOL(tcp_shutdown); | 2192 | EXPORT_SYMBOL(tcp_shutdown); |
2144 | EXPORT_SYMBOL(tcp_statistics); | 2193 | EXPORT_SYMBOL(tcp_statistics); |
2194 | #ifdef CONFIG_COMPAT | ||
2195 | EXPORT_SYMBOL(compat_tcp_setsockopt); | ||
2196 | EXPORT_SYMBOL(compat_tcp_getsockopt); | ||
2197 | #endif | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 4eb903db1b12..249ef6c88959 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1226,6 +1226,10 @@ struct inet_connection_sock_af_ops ipv4_specific = { | |||
1226 | .net_header_len = sizeof(struct iphdr), | 1226 | .net_header_len = sizeof(struct iphdr), |
1227 | .setsockopt = ip_setsockopt, | 1227 | .setsockopt = ip_setsockopt, |
1228 | .getsockopt = ip_getsockopt, | 1228 | .getsockopt = ip_getsockopt, |
1229 | #ifdef CONFIG_COMPAT | ||
1230 | .compat_setsockopt = compat_ip_setsockopt, | ||
1231 | .compat_getsockopt = compat_ip_getsockopt, | ||
1232 | #endif | ||
1229 | .addr2sockaddr = inet_csk_addr2sockaddr, | 1233 | .addr2sockaddr = inet_csk_addr2sockaddr, |
1230 | .sockaddr_len = sizeof(struct sockaddr_in), | 1234 | .sockaddr_len = sizeof(struct sockaddr_in), |
1231 | }; | 1235 | }; |
@@ -1808,6 +1812,10 @@ struct proto tcp_prot = { | |||
1808 | .shutdown = tcp_shutdown, | 1812 | .shutdown = tcp_shutdown, |
1809 | .setsockopt = tcp_setsockopt, | 1813 | .setsockopt = tcp_setsockopt, |
1810 | .getsockopt = tcp_getsockopt, | 1814 | .getsockopt = tcp_getsockopt, |
1815 | #ifdef CONFIG_COMPAT | ||
1816 | .compat_setsockopt = compat_tcp_setsockopt, | ||
1817 | .compat_getsockopt = compat_tcp_getsockopt, | ||
1818 | #endif | ||
1811 | .sendmsg = tcp_sendmsg, | 1819 | .sendmsg = tcp_sendmsg, |
1812 | .recvmsg = tcp_recvmsg, | 1820 | .recvmsg = tcp_recvmsg, |
1813 | .backlog_rcv = tcp_v4_do_rcv, | 1821 | .backlog_rcv = tcp_v4_do_rcv, |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 00840474a449..0b0721bd45c6 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1207,16 +1207,13 @@ static int udp_destroy_sock(struct sock *sk) | |||
1207 | /* | 1207 | /* |
1208 | * Socket option code for UDP | 1208 | * Socket option code for UDP |
1209 | */ | 1209 | */ |
1210 | static int udp_setsockopt(struct sock *sk, int level, int optname, | 1210 | static int do_udp_setsockopt(struct sock *sk, int level, int optname, |
1211 | char __user *optval, int optlen) | 1211 | char __user *optval, int optlen) |
1212 | { | 1212 | { |
1213 | struct udp_sock *up = udp_sk(sk); | 1213 | struct udp_sock *up = udp_sk(sk); |
1214 | int val; | 1214 | int val; |
1215 | int err = 0; | 1215 | int err = 0; |
1216 | 1216 | ||
1217 | if (level != SOL_UDP) | ||
1218 | return ip_setsockopt(sk, level, optname, optval, optlen); | ||
1219 | |||
1220 | if(optlen<sizeof(int)) | 1217 | if(optlen<sizeof(int)) |
1221 | return -EINVAL; | 1218 | return -EINVAL; |
1222 | 1219 | ||
@@ -1256,15 +1253,31 @@ static int udp_setsockopt(struct sock *sk, int level, int optname, | |||
1256 | return err; | 1253 | return err; |
1257 | } | 1254 | } |
1258 | 1255 | ||
1259 | static int udp_getsockopt(struct sock *sk, int level, int optname, | 1256 | static int udp_setsockopt(struct sock *sk, int level, int optname, |
1257 | char __user *optval, int optlen) | ||
1258 | { | ||
1259 | if (level != SOL_UDP) | ||
1260 | return ip_setsockopt(sk, level, optname, optval, optlen); | ||
1261 | return do_udp_setsockopt(sk, level, optname, optval, optlen); | ||
1262 | } | ||
1263 | |||
1264 | #ifdef CONFIG_COMPAT | ||
1265 | static int compat_udp_setsockopt(struct sock *sk, int level, int optname, | ||
1266 | char __user *optval, int optlen) | ||
1267 | { | ||
1268 | if (level != SOL_UDP) | ||
1269 | return compat_ip_setsockopt(sk, level, | ||
1270 | optname, optval, optlen); | ||
1271 | return do_udp_setsockopt(sk, level, optname, optval, optlen); | ||
1272 | } | ||
1273 | #endif | ||
1274 | |||
1275 | static int do_udp_getsockopt(struct sock *sk, int level, int optname, | ||
1260 | char __user *optval, int __user *optlen) | 1276 | char __user *optval, int __user *optlen) |
1261 | { | 1277 | { |
1262 | struct udp_sock *up = udp_sk(sk); | 1278 | struct udp_sock *up = udp_sk(sk); |
1263 | int val, len; | 1279 | int val, len; |
1264 | 1280 | ||
1265 | if (level != SOL_UDP) | ||
1266 | return ip_getsockopt(sk, level, optname, optval, optlen); | ||
1267 | |||
1268 | if(get_user(len,optlen)) | 1281 | if(get_user(len,optlen)) |
1269 | return -EFAULT; | 1282 | return -EFAULT; |
1270 | 1283 | ||
@@ -1293,6 +1306,24 @@ static int udp_getsockopt(struct sock *sk, int level, int optname, | |||
1293 | return 0; | 1306 | return 0; |
1294 | } | 1307 | } |
1295 | 1308 | ||
1309 | static int udp_getsockopt(struct sock *sk, int level, int optname, | ||
1310 | char __user *optval, int __user *optlen) | ||
1311 | { | ||
1312 | if (level != SOL_UDP) | ||
1313 | return ip_getsockopt(sk, level, optname, optval, optlen); | ||
1314 | return do_udp_getsockopt(sk, level, optname, optval, optlen); | ||
1315 | } | ||
1316 | |||
1317 | #ifdef CONFIG_COMPAT | ||
1318 | static int compat_udp_getsockopt(struct sock *sk, int level, int optname, | ||
1319 | char __user *optval, int __user *optlen) | ||
1320 | { | ||
1321 | if (level != SOL_UDP) | ||
1322 | return compat_ip_getsockopt(sk, level, | ||
1323 | optname, optval, optlen); | ||
1324 | return do_udp_getsockopt(sk, level, optname, optval, optlen); | ||
1325 | } | ||
1326 | #endif | ||
1296 | /** | 1327 | /** |
1297 | * udp_poll - wait for a UDP event. | 1328 | * udp_poll - wait for a UDP event. |
1298 | * @file - file struct | 1329 | * @file - file struct |
@@ -1350,6 +1381,10 @@ struct proto udp_prot = { | |||
1350 | .destroy = udp_destroy_sock, | 1381 | .destroy = udp_destroy_sock, |
1351 | .setsockopt = udp_setsockopt, | 1382 | .setsockopt = udp_setsockopt, |
1352 | .getsockopt = udp_getsockopt, | 1383 | .getsockopt = udp_getsockopt, |
1384 | #ifdef CONFIG_COMPAT | ||
1385 | .compat_setsockopt = compat_udp_setsockopt, | ||
1386 | .compat_getsockopt = compat_udp_getsockopt, | ||
1387 | #endif | ||
1353 | .sendmsg = udp_sendmsg, | 1388 | .sendmsg = udp_sendmsg, |
1354 | .recvmsg = udp_recvmsg, | 1389 | .recvmsg = udp_recvmsg, |
1355 | .sendpage = udp_sendpage, | 1390 | .sendpage = udp_sendpage, |