aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-06-03 12:14:03 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-16 21:32:46 -0400
commit87de87d5e47f94b4ea647a5bd1bc8dc1f7930db4 (patch)
tree09e0f3b084466a7abca17356cce7c39b7b1a8783 /net
parenta67fa76d8be4e24e2d61cd76438a893d4c2886f7 (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.c10
-rw-r--r--net/wireless/wext.c104
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
1116static 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
1149static 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
1190int 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.