diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-03 12:14:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-16 21:32:46 -0400 |
commit | 87de87d5e47f94b4ea647a5bd1bc8dc1f7930db4 (patch) | |
tree | 09e0f3b084466a7abca17356cce7c39b7b1a8783 /net | |
parent | a67fa76d8be4e24e2d61cd76438a893d4c2886f7 (diff) |
wext: Dispatch and handle compat ioctls entirely in net/wireless/wext.c
Next we can kill the hacks in fs/compat_ioctl.c and also
dispatch compat ioctls down into the driver and 80211 protocol
helper layers in order to handle iw_point objects embedded in
stream replies which need to be translated.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/socket.c | 10 | ||||
-rw-r--r-- | net/wireless/wext.c | 104 |
2 files changed, 114 insertions, 0 deletions
diff --git a/net/socket.c b/net/socket.c index 66c4a8cf6db9..81fe82513046 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -90,6 +90,7 @@ | |||
90 | #include <asm/unistd.h> | 90 | #include <asm/unistd.h> |
91 | 91 | ||
92 | #include <net/compat.h> | 92 | #include <net/compat.h> |
93 | #include <net/wext.h> | ||
93 | 94 | ||
94 | #include <net/sock.h> | 95 | #include <net/sock.h> |
95 | #include <linux/netfilter.h> | 96 | #include <linux/netfilter.h> |
@@ -2210,10 +2211,19 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd, | |||
2210 | { | 2211 | { |
2211 | struct socket *sock = file->private_data; | 2212 | struct socket *sock = file->private_data; |
2212 | int ret = -ENOIOCTLCMD; | 2213 | int ret = -ENOIOCTLCMD; |
2214 | struct sock *sk; | ||
2215 | struct net *net; | ||
2216 | |||
2217 | sk = sock->sk; | ||
2218 | net = sock_net(sk); | ||
2213 | 2219 | ||
2214 | if (sock->ops->compat_ioctl) | 2220 | if (sock->ops->compat_ioctl) |
2215 | ret = sock->ops->compat_ioctl(sock, cmd, arg); | 2221 | ret = sock->ops->compat_ioctl(sock, cmd, arg); |
2216 | 2222 | ||
2223 | if (ret == -ENOIOCTLCMD && | ||
2224 | (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) | ||
2225 | ret = compat_wext_handle_ioctl(net, cmd, arg); | ||
2226 | |||
2217 | return ret; | 2227 | return ret; |
2218 | } | 2228 | } |
2219 | #endif | 2229 | #endif |
diff --git a/net/wireless/wext.c b/net/wireless/wext.c index 09022cbb58ba..1a4636a9fcde 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c | |||
@@ -1112,6 +1112,110 @@ int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | |||
1112 | return ret; | 1112 | return ret; |
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | #ifdef CONFIG_COMPAT | ||
1116 | static int compat_standard_call(struct net_device *dev, | ||
1117 | struct iwreq *iwr, | ||
1118 | unsigned int cmd, | ||
1119 | iw_handler handler) | ||
1120 | { | ||
1121 | const struct iw_ioctl_description *descr; | ||
1122 | struct compat_iw_point *iwp_compat; | ||
1123 | struct iw_request_info info; | ||
1124 | struct iw_point iwp; | ||
1125 | int err; | ||
1126 | |||
1127 | descr = standard_ioctl + (cmd - SIOCIWFIRST); | ||
1128 | |||
1129 | if (descr->header_type != IW_HEADER_TYPE_POINT) | ||
1130 | return ioctl_standard_call(dev, iwr, cmd, handler); | ||
1131 | |||
1132 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | ||
1133 | iwp.pointer = compat_ptr(iwp_compat->pointer); | ||
1134 | iwp.length = iwp_compat->length; | ||
1135 | iwp.flags = iwp_compat->flags; | ||
1136 | |||
1137 | info.cmd = cmd; | ||
1138 | info.flags = 0; | ||
1139 | |||
1140 | err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, &info); | ||
1141 | |||
1142 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | ||
1143 | iwp_compat->length = iwp.length; | ||
1144 | iwp_compat->flags = iwp.flags; | ||
1145 | |||
1146 | return err; | ||
1147 | } | ||
1148 | |||
1149 | static int compat_private_call(struct net_device *dev, struct iwreq *iwr, | ||
1150 | unsigned int cmd, iw_handler handler) | ||
1151 | { | ||
1152 | const struct iw_priv_args *descr; | ||
1153 | struct iw_request_info info; | ||
1154 | int ret, extra_size; | ||
1155 | |||
1156 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | ||
1157 | |||
1158 | /* Prepare the call */ | ||
1159 | info.cmd = cmd; | ||
1160 | info.flags = 0; | ||
1161 | |||
1162 | /* Check if we have a pointer to user space data or not. */ | ||
1163 | if (extra_size == 0) { | ||
1164 | /* No extra arguments. Trivial to handle */ | ||
1165 | ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); | ||
1166 | } else { | ||
1167 | struct compat_iw_point *iwp_compat; | ||
1168 | struct iw_point iwp; | ||
1169 | |||
1170 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | ||
1171 | iwp.pointer = compat_ptr(iwp_compat->pointer); | ||
1172 | iwp.length = iwp_compat->length; | ||
1173 | iwp.flags = iwp_compat->flags; | ||
1174 | |||
1175 | ret = ioctl_private_iw_point(&iwp, cmd, descr, | ||
1176 | handler, dev, &info, extra_size); | ||
1177 | |||
1178 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | ||
1179 | iwp_compat->length = iwp.length; | ||
1180 | iwp_compat->flags = iwp.flags; | ||
1181 | } | ||
1182 | |||
1183 | /* Call commit handler if needed and defined */ | ||
1184 | if (ret == -EIWCOMMIT) | ||
1185 | ret = call_commit_handler(dev); | ||
1186 | |||
1187 | return ret; | ||
1188 | } | ||
1189 | |||
1190 | int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | ||
1191 | unsigned long arg) | ||
1192 | { | ||
1193 | void __user *argp = (void __user *)arg; | ||
1194 | struct iwreq iwr; | ||
1195 | char *colon; | ||
1196 | int ret; | ||
1197 | |||
1198 | if (copy_from_user(&iwr, argp, sizeof(struct iwreq))) | ||
1199 | return -EFAULT; | ||
1200 | |||
1201 | iwr.ifr_name[IFNAMSIZ-1] = 0; | ||
1202 | colon = strchr(iwr.ifr_name, ':'); | ||
1203 | if (colon) | ||
1204 | *colon = 0; | ||
1205 | |||
1206 | ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, | ||
1207 | compat_standard_call, | ||
1208 | compat_private_call); | ||
1209 | |||
1210 | if (ret >= 0 && | ||
1211 | IW_IS_GET(cmd) && | ||
1212 | copy_to_user(argp, &iwr, sizeof(struct iwreq))) | ||
1213 | return -EFAULT; | ||
1214 | |||
1215 | return ret; | ||
1216 | } | ||
1217 | #endif | ||
1218 | |||
1115 | /************************* EVENT PROCESSING *************************/ | 1219 | /************************* EVENT PROCESSING *************************/ |
1116 | /* | 1220 | /* |
1117 | * Process events generated by the wireless layer or the driver. | 1221 | * Process events generated by the wireless layer or the driver. |