13d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg/* 23d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * This file implement the Wireless Extensions priv API. 33d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * 43d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> 53d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. 63d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> 73d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * 83d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * (As all part of the Linux kernel, this file is GPL) 93d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg */ 105a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 113d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg#include <linux/wireless.h> 123d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg#include <linux/netdevice.h> 133d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg#include <net/iw_handler.h> 143d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg#include <net/wext.h> 153d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 163d23e349d807177eaf519d444677cee86b1a04cfJohannes Bergint iw_handler_get_private(struct net_device * dev, 173d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg struct iw_request_info * info, 183d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg union iwreq_data * wrqu, 193d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg char * extra) 203d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg{ 213d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Check if the driver has something to export */ 223d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if ((dev->wireless_handlers->num_private_args == 0) || 233d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg (dev->wireless_handlers->private_args == NULL)) 243d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return -EOPNOTSUPP; 253d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 263d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Check if there is enough buffer up there */ 273d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (wrqu->data.length < dev->wireless_handlers->num_private_args) { 283d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* User space can't know in advance how large the buffer 293d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * needs to be. Give it a hint, so that we can support 303d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * any size buffer we want somewhat efficiently... */ 313d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg wrqu->data.length = dev->wireless_handlers->num_private_args; 323d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return -E2BIG; 333d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 343d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 353d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Set the number of available ioctls. */ 363d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg wrqu->data.length = dev->wireless_handlers->num_private_args; 373d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 383d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Copy structure to the user buffer. */ 393d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg memcpy(extra, dev->wireless_handlers->private_args, 403d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg sizeof(struct iw_priv_args) * wrqu->data.length); 413d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 423d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return 0; 433d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg} 443d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 453d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg/* Size (in bytes) of the various private data types */ 463d23e349d807177eaf519d444677cee86b1a04cfJohannes Bergstatic const char iw_priv_type_size[] = { 473d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 0, /* IW_PRIV_TYPE_NONE */ 483d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1, /* IW_PRIV_TYPE_BYTE */ 493d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1, /* IW_PRIV_TYPE_CHAR */ 503d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 0, /* Not defined */ 513d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg sizeof(__u32), /* IW_PRIV_TYPE_INT */ 523d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ 533d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ 543d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 0, /* Not defined */ 553d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg}; 563d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 573d23e349d807177eaf519d444677cee86b1a04cfJohannes Bergstatic int get_priv_size(__u16 args) 583d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg{ 593d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int num = args & IW_PRIV_SIZE_MASK; 603d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int type = (args & IW_PRIV_TYPE_MASK) >> 12; 613d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 623d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return num * iw_priv_type_size[type]; 633d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg} 643d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 653d23e349d807177eaf519d444677cee86b1a04cfJohannes Bergstatic int adjust_priv_size(__u16 args, struct iw_point *iwp) 663d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg{ 673d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int num = iwp->length; 683d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int max = args & IW_PRIV_SIZE_MASK; 693d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int type = (args & IW_PRIV_TYPE_MASK) >> 12; 703d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 713d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Make sure the driver doesn't goof up */ 723d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (max < num) 733d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg num = max; 743d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 753d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return num * iw_priv_type_size[type]; 763d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg} 773d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 783d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg/* 793d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * Wrapper to call a private Wireless Extension handler. 803d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * We do various checks and also take care of moving data between 813d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * user space and kernel space. 823d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * It's not as nice and slimline as the standard wrapper. The cause 833d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * is struct iw_priv_args, which was not really designed for the 843d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * job we are going here. 853d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * 863d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * IMPORTANT : This function prevent to set and get data on the same 873d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * IOCTL and enforce the SET/GET convention. Not doing it would be 883d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * far too hairy... 893d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * If you need to set and get data at the same time, please don't use 903d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * a iw_handler but process it in your ioctl handler (i.e. use the 913d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * old driver API). 923d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg */ 933d23e349d807177eaf519d444677cee86b1a04cfJohannes Bergstatic int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd, 943d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg const struct iw_priv_args **descrp) 953d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg{ 963d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg const struct iw_priv_args *descr; 973d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int i, extra_size; 983d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 993d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg descr = NULL; 1003d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg for (i = 0; i < dev->wireless_handlers->num_private_args; i++) { 1013d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (cmd == dev->wireless_handlers->private_args[i].cmd) { 1023d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg descr = &dev->wireless_handlers->private_args[i]; 1033d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg break; 1043d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 1053d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 1063d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1073d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg extra_size = 0; 1083d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (descr) { 1093d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (IW_IS_SET(cmd)) { 1103d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int offset = 0; /* For sub-ioctls */ 1113d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Check for sub-ioctl handler */ 1123d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (descr->name[0] == '\0') 1133d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Reserve one int for sub-ioctl index */ 1143d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg offset = sizeof(__u32); 1153d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1163d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Size of set arguments */ 1173d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg extra_size = get_priv_size(descr->set_args); 1183d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1193d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Does it fits in iwr ? */ 1203d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if ((descr->set_args & IW_PRIV_SIZE_FIXED) && 1213d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg ((extra_size + offset) <= IFNAMSIZ)) 1223d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg extra_size = 0; 1233d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } else { 1243d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Size of get arguments */ 1253d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg extra_size = get_priv_size(descr->get_args); 1263d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1273d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Does it fits in iwr ? */ 1283d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if ((descr->get_args & IW_PRIV_SIZE_FIXED) && 1293d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg (extra_size <= IFNAMSIZ)) 1303d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg extra_size = 0; 1313d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 1323d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 1333d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg *descrp = descr; 1343d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return extra_size; 1353d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg} 1363d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1373d23e349d807177eaf519d444677cee86b1a04cfJohannes Bergstatic int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, 1383d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg const struct iw_priv_args *descr, 1393d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iw_handler handler, struct net_device *dev, 1403d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg struct iw_request_info *info, int extra_size) 1413d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg{ 1423d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg char *extra; 1433d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int err; 1443d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1453d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Check what user space is giving us */ 1463d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (IW_IS_SET(cmd)) { 1473d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (!iwp->pointer && iwp->length != 0) 1483d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return -EFAULT; 1493d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1503d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK)) 1513d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return -E2BIG; 1523d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } else if (!iwp->pointer) 1533d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return -EFAULT; 1543d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 155df6d02300f7c2fbd0fbe626d819c8e5237d72c62Johannes Berg extra = kzalloc(extra_size, GFP_KERNEL); 1563d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (!extra) 1573d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return -ENOMEM; 1583d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1593d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* If it is a SET, get all the extra data in here */ 1603d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (IW_IS_SET(cmd) && (iwp->length != 0)) { 1613d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (copy_from_user(extra, iwp->pointer, extra_size)) { 1623d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg err = -EFAULT; 1633d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg goto out; 1643d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 1653d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 1663d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1673d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Call the handler */ 1683d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg err = handler(dev, info, (union iwreq_data *) iwp, extra); 1693d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1703d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* If we have something to return to the user */ 1713d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (!err && IW_IS_GET(cmd)) { 1723d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Adjust for the actual length if it's variable, 1733d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg * avoid leaking kernel bits outside. 1743d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg */ 1753d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) 1763d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg extra_size = adjust_priv_size(descr->get_args, iwp); 1773d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1783d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (copy_to_user(iwp->pointer, extra, extra_size)) 1793d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg err = -EFAULT; 1803d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 1813d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1823d23e349d807177eaf519d444677cee86b1a04cfJohannes Bergout: 1833d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg kfree(extra); 1843d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return err; 1853d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg} 1863d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1873d23e349d807177eaf519d444677cee86b1a04cfJohannes Bergint ioctl_private_call(struct net_device *dev, struct iwreq *iwr, 1883d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg unsigned int cmd, struct iw_request_info *info, 1893d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iw_handler handler) 1903d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg{ 1913d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int extra_size = 0, ret = -EINVAL; 1923d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg const struct iw_priv_args *descr; 1933d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1943d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg extra_size = get_priv_descr_and_size(dev, cmd, &descr); 1953d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 1963d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Check if we have a pointer to user space data or not. */ 1973d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (extra_size == 0) { 1983d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* No extra arguments. Trivial to handle */ 1993d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); 2003d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } else { 2013d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, 2023d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg handler, dev, info, extra_size); 2033d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 2043d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2053d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Call commit handler if needed and defined */ 2063d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (ret == -EIWCOMMIT) 2073d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg ret = call_commit_handler(dev); 2083d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2093d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return ret; 2103d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg} 2113d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2123d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg#ifdef CONFIG_COMPAT 2133d23e349d807177eaf519d444677cee86b1a04cfJohannes Bergint compat_private_call(struct net_device *dev, struct iwreq *iwr, 2143d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg unsigned int cmd, struct iw_request_info *info, 2153d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iw_handler handler) 2163d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg{ 2173d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg const struct iw_priv_args *descr; 2183d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg int ret, extra_size; 2193d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2203d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg extra_size = get_priv_descr_and_size(dev, cmd, &descr); 2213d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2223d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Check if we have a pointer to user space data or not. */ 2233d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (extra_size == 0) { 2243d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* No extra arguments. Trivial to handle */ 2253d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); 2263d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } else { 2273d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg struct compat_iw_point *iwp_compat; 2283d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg struct iw_point iwp; 2293d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2303d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iwp_compat = (struct compat_iw_point *) &iwr->u.data; 2313d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iwp.pointer = compat_ptr(iwp_compat->pointer); 2323d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iwp.length = iwp_compat->length; 2333d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iwp.flags = iwp_compat->flags; 2343d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2353d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg ret = ioctl_private_iw_point(&iwp, cmd, descr, 2363d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg handler, dev, info, extra_size); 2373d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2383d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iwp_compat->pointer = ptr_to_compat(iwp.pointer); 2393d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iwp_compat->length = iwp.length; 2403d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg iwp_compat->flags = iwp.flags; 2413d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg } 2423d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2433d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg /* Call commit handler if needed and defined */ 2443d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg if (ret == -EIWCOMMIT) 2453d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg ret = call_commit_handler(dev); 2463d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg 2473d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg return ret; 2483d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg} 2493d23e349d807177eaf519d444677cee86b1a04cfJohannes Berg#endif 250