mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-29 10:01:25 +00:00
wext: Extract standard call iw_point handling into seperate function.
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
208887d4cc
commit
84149b0fca
1 changed files with 134 additions and 124 deletions
|
@ -694,6 +694,138 @@ void wext_proc_exit(struct net *net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ---------------------------------------------------------------- */
|
/* ---------------------------------------------------------------- */
|
||||||
|
static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
|
||||||
|
const struct iw_ioctl_description *descr,
|
||||||
|
iw_handler handler, struct net_device *dev,
|
||||||
|
struct iw_request_info *info)
|
||||||
|
{
|
||||||
|
int err, extra_size, user_length = 0, essid_compat = 0;
|
||||||
|
char *extra;
|
||||||
|
|
||||||
|
/* Calculate space needed by arguments. Always allocate
|
||||||
|
* for max space.
|
||||||
|
*/
|
||||||
|
extra_size = descr->max_tokens * descr->token_size;
|
||||||
|
|
||||||
|
/* Check need for ESSID compatibility for WE < 21 */
|
||||||
|
switch (cmd) {
|
||||||
|
case SIOCSIWESSID:
|
||||||
|
case SIOCGIWESSID:
|
||||||
|
case SIOCSIWNICKN:
|
||||||
|
case SIOCGIWNICKN:
|
||||||
|
if (iwp->length == descr->max_tokens + 1)
|
||||||
|
essid_compat = 1;
|
||||||
|
else if (IW_IS_SET(cmd) && (iwp->length != 0)) {
|
||||||
|
char essid[IW_ESSID_MAX_SIZE + 1];
|
||||||
|
|
||||||
|
err = copy_from_user(essid, iwp->pointer,
|
||||||
|
iwp->length *
|
||||||
|
descr->token_size);
|
||||||
|
if (err)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
if (essid[iwp->length - 1] == '\0')
|
||||||
|
essid_compat = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
iwp->length -= essid_compat;
|
||||||
|
|
||||||
|
/* Check what user space is giving us */
|
||||||
|
if (IW_IS_SET(cmd)) {
|
||||||
|
/* Check NULL pointer */
|
||||||
|
if (!iwp->pointer && iwp->length != 0)
|
||||||
|
return -EFAULT;
|
||||||
|
/* Check if number of token fits within bounds */
|
||||||
|
if (iwp->length > descr->max_tokens)
|
||||||
|
return -E2BIG;
|
||||||
|
if (iwp->length < descr->min_tokens)
|
||||||
|
return -EINVAL;
|
||||||
|
} else {
|
||||||
|
/* Check NULL pointer */
|
||||||
|
if (!iwp->pointer)
|
||||||
|
return -EFAULT;
|
||||||
|
/* Save user space buffer size for checking */
|
||||||
|
user_length = iwp->length;
|
||||||
|
|
||||||
|
/* Don't check if user_length > max to allow forward
|
||||||
|
* compatibility. The test user_length < min is
|
||||||
|
* implied by the test at the end.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Support for very large requests */
|
||||||
|
if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
|
||||||
|
(user_length > descr->max_tokens)) {
|
||||||
|
/* Allow userspace to GET more than max so
|
||||||
|
* we can support any size GET requests.
|
||||||
|
* There is still a limit : -ENOMEM.
|
||||||
|
*/
|
||||||
|
extra_size = user_length * descr->token_size;
|
||||||
|
|
||||||
|
/* Note : user_length is originally a __u16,
|
||||||
|
* and token_size is controlled by us,
|
||||||
|
* so extra_size won't get negative and
|
||||||
|
* won't overflow...
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* kzalloc() ensures NULL-termination for essid_compat. */
|
||||||
|
extra = kzalloc(extra_size, GFP_KERNEL);
|
||||||
|
if (!extra)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* If it is a SET, get all the extra data in here */
|
||||||
|
if (IW_IS_SET(cmd) && (iwp->length != 0)) {
|
||||||
|
if (copy_from_user(extra, iwp->pointer,
|
||||||
|
iwp->length *
|
||||||
|
descr->token_size)) {
|
||||||
|
err = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = handler(dev, info, (union iwreq_data *) iwp, extra);
|
||||||
|
|
||||||
|
iwp->length += essid_compat;
|
||||||
|
|
||||||
|
/* If we have something to return to the user */
|
||||||
|
if (!err && IW_IS_GET(cmd)) {
|
||||||
|
/* Check if there is enough buffer up there */
|
||||||
|
if (user_length < iwp->length) {
|
||||||
|
err = -E2BIG;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_to_user(iwp->pointer, extra,
|
||||||
|
iwp->length *
|
||||||
|
descr->token_size)) {
|
||||||
|
err = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate an event to notify listeners of the change */
|
||||||
|
if ((descr->flags & IW_DESCR_FLAG_EVENT) && err == -EIWCOMMIT) {
|
||||||
|
union iwreq_data *data = (union iwreq_data *) iwp;
|
||||||
|
|
||||||
|
if (descr->flags & IW_DESCR_FLAG_RESTRICT)
|
||||||
|
/* If the event is restricted, don't
|
||||||
|
* export the payload.
|
||||||
|
*/
|
||||||
|
wireless_send_event(dev, cmd, data, NULL);
|
||||||
|
else
|
||||||
|
wireless_send_event(dev, cmd, data, extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree(extra);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper to call a standard Wireless Extension handler.
|
* Wrapper to call a standard Wireless Extension handler.
|
||||||
* We do various checks and also take care of moving data between
|
* We do various checks and also take care of moving data between
|
||||||
|
@ -729,130 +861,8 @@ static int ioctl_standard_call(struct net_device * dev,
|
||||||
((ret == 0) || (ret == -EIWCOMMIT)))
|
((ret == 0) || (ret == -EIWCOMMIT)))
|
||||||
wireless_send_event(dev, cmd, &(iwr->u), NULL);
|
wireless_send_event(dev, cmd, &(iwr->u), NULL);
|
||||||
} else {
|
} else {
|
||||||
char * extra;
|
ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr,
|
||||||
int extra_size;
|
handler, dev, &info);
|
||||||
int user_length = 0;
|
|
||||||
int err;
|
|
||||||
int essid_compat = 0;
|
|
||||||
|
|
||||||
/* Calculate space needed by arguments. Always allocate
|
|
||||||
* for max space. Easier, and won't last long... */
|
|
||||||
extra_size = descr->max_tokens * descr->token_size;
|
|
||||||
|
|
||||||
/* Check need for ESSID compatibility for WE < 21 */
|
|
||||||
switch (cmd) {
|
|
||||||
case SIOCSIWESSID:
|
|
||||||
case SIOCGIWESSID:
|
|
||||||
case SIOCSIWNICKN:
|
|
||||||
case SIOCGIWNICKN:
|
|
||||||
if (iwr->u.data.length == descr->max_tokens + 1)
|
|
||||||
essid_compat = 1;
|
|
||||||
else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
|
|
||||||
char essid[IW_ESSID_MAX_SIZE + 1];
|
|
||||||
|
|
||||||
err = copy_from_user(essid, iwr->u.data.pointer,
|
|
||||||
iwr->u.data.length *
|
|
||||||
descr->token_size);
|
|
||||||
if (err)
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
if (essid[iwr->u.data.length - 1] == '\0')
|
|
||||||
essid_compat = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
iwr->u.data.length -= essid_compat;
|
|
||||||
|
|
||||||
/* Check what user space is giving us */
|
|
||||||
if (IW_IS_SET(cmd)) {
|
|
||||||
/* Check NULL pointer */
|
|
||||||
if ((iwr->u.data.pointer == NULL) &&
|
|
||||||
(iwr->u.data.length != 0))
|
|
||||||
return -EFAULT;
|
|
||||||
/* Check if number of token fits within bounds */
|
|
||||||
if (iwr->u.data.length > descr->max_tokens)
|
|
||||||
return -E2BIG;
|
|
||||||
if (iwr->u.data.length < descr->min_tokens)
|
|
||||||
return -EINVAL;
|
|
||||||
} else {
|
|
||||||
/* Check NULL pointer */
|
|
||||||
if (iwr->u.data.pointer == NULL)
|
|
||||||
return -EFAULT;
|
|
||||||
/* Save user space buffer size for checking */
|
|
||||||
user_length = iwr->u.data.length;
|
|
||||||
|
|
||||||
/* Don't check if user_length > max to allow forward
|
|
||||||
* compatibility. The test user_length < min is
|
|
||||||
* implied by the test at the end. */
|
|
||||||
|
|
||||||
/* Support for very large requests */
|
|
||||||
if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
|
|
||||||
(user_length > descr->max_tokens)) {
|
|
||||||
/* Allow userspace to GET more than max so
|
|
||||||
* we can support any size GET requests.
|
|
||||||
* There is still a limit : -ENOMEM. */
|
|
||||||
extra_size = user_length * descr->token_size;
|
|
||||||
/* Note : user_length is originally a __u16,
|
|
||||||
* and token_size is controlled by us,
|
|
||||||
* so extra_size won't get negative and
|
|
||||||
* won't overflow... */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the kernel buffer */
|
|
||||||
/* kzalloc ensures NULL-termination for essid_compat */
|
|
||||||
extra = kzalloc(extra_size, GFP_KERNEL);
|
|
||||||
if (extra == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* If it is a SET, get all the extra data in here */
|
|
||||||
if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
|
|
||||||
err = copy_from_user(extra, iwr->u.data.pointer,
|
|
||||||
iwr->u.data.length *
|
|
||||||
descr->token_size);
|
|
||||||
if (err) {
|
|
||||||
kfree(extra);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call the handler */
|
|
||||||
ret = handler(dev, &info, &(iwr->u), extra);
|
|
||||||
|
|
||||||
iwr->u.data.length += essid_compat;
|
|
||||||
|
|
||||||
/* If we have something to return to the user */
|
|
||||||
if (!ret && IW_IS_GET(cmd)) {
|
|
||||||
/* Check if there is enough buffer up there */
|
|
||||||
if (user_length < iwr->u.data.length) {
|
|
||||||
kfree(extra);
|
|
||||||
return -E2BIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = copy_to_user(iwr->u.data.pointer, extra,
|
|
||||||
iwr->u.data.length *
|
|
||||||
descr->token_size);
|
|
||||||
if (err)
|
|
||||||
ret = -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate an event to notify listeners of the change */
|
|
||||||
if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
|
|
||||||
((ret == 0) || (ret == -EIWCOMMIT))) {
|
|
||||||
if (descr->flags & IW_DESCR_FLAG_RESTRICT)
|
|
||||||
/* If the event is restricted, don't
|
|
||||||
* export the payload */
|
|
||||||
wireless_send_event(dev, cmd, &(iwr->u), NULL);
|
|
||||||
else
|
|
||||||
wireless_send_event(dev, cmd, &(iwr->u),
|
|
||||||
extra);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cleanup - I told you it wasn't that long ;-) */
|
|
||||||
kfree(extra);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call commit handler if needed and defined */
|
/* Call commit handler if needed and defined */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue