|
@@ -1112,6 +1112,110 @@ int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
+static int compat_standard_call(struct net_device *dev,
|
|
|
+ struct iwreq *iwr,
|
|
|
+ unsigned int cmd,
|
|
|
+ iw_handler handler)
|
|
|
+{
|
|
|
+ const struct iw_ioctl_description *descr;
|
|
|
+ struct compat_iw_point *iwp_compat;
|
|
|
+ struct iw_request_info info;
|
|
|
+ struct iw_point iwp;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ descr = standard_ioctl + (cmd - SIOCIWFIRST);
|
|
|
+
|
|
|
+ if (descr->header_type != IW_HEADER_TYPE_POINT)
|
|
|
+ return ioctl_standard_call(dev, iwr, cmd, handler);
|
|
|
+
|
|
|
+ iwp_compat = (struct compat_iw_point *) &iwr->u.data;
|
|
|
+ iwp.pointer = compat_ptr(iwp_compat->pointer);
|
|
|
+ iwp.length = iwp_compat->length;
|
|
|
+ iwp.flags = iwp_compat->flags;
|
|
|
+
|
|
|
+ info.cmd = cmd;
|
|
|
+ info.flags = 0;
|
|
|
+
|
|
|
+ err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, &info);
|
|
|
+
|
|
|
+ iwp_compat->pointer = ptr_to_compat(iwp.pointer);
|
|
|
+ iwp_compat->length = iwp.length;
|
|
|
+ iwp_compat->flags = iwp.flags;
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int compat_private_call(struct net_device *dev, struct iwreq *iwr,
|
|
|
+ unsigned int cmd, iw_handler handler)
|
|
|
+{
|
|
|
+ const struct iw_priv_args *descr;
|
|
|
+ struct iw_request_info info;
|
|
|
+ int ret, extra_size;
|
|
|
+
|
|
|
+ extra_size = get_priv_descr_and_size(dev, cmd, &descr);
|
|
|
+
|
|
|
+ /* Prepare the call */
|
|
|
+ info.cmd = cmd;
|
|
|
+ info.flags = 0;
|
|
|
+
|
|
|
+ /* Check if we have a pointer to user space data or not. */
|
|
|
+ if (extra_size == 0) {
|
|
|
+ /* No extra arguments. Trivial to handle */
|
|
|
+ ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u));
|
|
|
+ } else {
|
|
|
+ struct compat_iw_point *iwp_compat;
|
|
|
+ struct iw_point iwp;
|
|
|
+
|
|
|
+ iwp_compat = (struct compat_iw_point *) &iwr->u.data;
|
|
|
+ iwp.pointer = compat_ptr(iwp_compat->pointer);
|
|
|
+ iwp.length = iwp_compat->length;
|
|
|
+ iwp.flags = iwp_compat->flags;
|
|
|
+
|
|
|
+ ret = ioctl_private_iw_point(&iwp, cmd, descr,
|
|
|
+ handler, dev, &info, extra_size);
|
|
|
+
|
|
|
+ iwp_compat->pointer = ptr_to_compat(iwp.pointer);
|
|
|
+ iwp_compat->length = iwp.length;
|
|
|
+ iwp_compat->flags = iwp.flags;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Call commit handler if needed and defined */
|
|
|
+ if (ret == -EIWCOMMIT)
|
|
|
+ ret = call_commit_handler(dev);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
|
|
|
+ unsigned long arg)
|
|
|
+{
|
|
|
+ void __user *argp = (void __user *)arg;
|
|
|
+ struct iwreq iwr;
|
|
|
+ char *colon;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (copy_from_user(&iwr, argp, sizeof(struct iwreq)))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ iwr.ifr_name[IFNAMSIZ-1] = 0;
|
|
|
+ colon = strchr(iwr.ifr_name, ':');
|
|
|
+ if (colon)
|
|
|
+ *colon = 0;
|
|
|
+
|
|
|
+ ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd,
|
|
|
+ compat_standard_call,
|
|
|
+ compat_private_call);
|
|
|
+
|
|
|
+ if (ret >= 0 &&
|
|
|
+ IW_IS_GET(cmd) &&
|
|
|
+ copy_to_user(argp, &iwr, sizeof(struct iwreq)))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/************************* EVENT PROCESSING *************************/
|
|
|
/*
|
|
|
* Process events generated by the wireless layer or the driver.
|