aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_sockglue.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_sockglue.c')
-rw-r--r--net/ipv4/ip_sockglue.c142
1 files changed, 123 insertions, 19 deletions
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
402int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) 402static 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
887int 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
913int 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
899int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) 945static 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
1152int 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
1183int 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
1114EXPORT_SYMBOL(ip_cmsg_recv); 1214EXPORT_SYMBOL(ip_cmsg_recv);
1115 1215
1116EXPORT_SYMBOL(ip_getsockopt); 1216EXPORT_SYMBOL(ip_getsockopt);
1117EXPORT_SYMBOL(ip_setsockopt); 1217EXPORT_SYMBOL(ip_setsockopt);
1218#ifdef CONFIG_COMPAT
1219EXPORT_SYMBOL(compat_ip_getsockopt);
1220EXPORT_SYMBOL(compat_ip_setsockopt);
1221#endif