/*---------------------------------------------------------------- * p80211knetdev_do_ioctl * * Handle an ioctl call on one of our devices. Everything Linux * ioctl specific is done here. Then we pass the contents of the * ifr->data to the request message handler. * * Arguments: * dev Linux kernel netdevice * ifr Our private ioctl request structure, typed for the * generic struct ifreq so we can use ptr to func * w/o cast. * * Returns: * zero on success, a negative errno on failure. Possible values: * -ENETDOWN Device isn't up. * -EBUSY cmd already in progress * -ETIME p80211 cmd timed out (MSD may have its own timers) * -EFAULT memory fault copying msg from user buffer * -ENOMEM unable to allocate kernel msg buffer * -EINVAL bad magic, it the cmd really for us? * -EintR sleeping on cmd, awakened by signal, cmd cancelled. * * Call Context: * Process thread (ioctl caller). TODO: SMP support may require * locks. *---------------------------------------------------------------- */ static int p80211knetdev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int result = 0; struct p80211ioctl_req *req = (struct p80211ioctl_req *)ifr; struct wlandevice *wlandev = dev->ml_priv; u8 *msgbuf; netdev_dbg(dev, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); #ifdef SIOCETHTOOL if (cmd == SIOCETHTOOL) { result = p80211netdev_ethtool(wlandev, (void __user *)ifr->ifr_data); goto bail; } #endif /* Test the magic, assume ifr is good if it's there */ if (req->magic != P80211_IOCTL_MAGIC) { result = -EINVAL; goto bail; } if (cmd == P80211_IFTEST) { result = 0; goto bail; } else if (cmd != P80211_IFREQ) { result = -EINVAL; goto bail; } /* Allocate a buf of size req->len */ msgbuf = kmalloc(req->len, GFP_KERNEL); if (msgbuf) { if (copy_from_user(msgbuf, (void __user *)req->data, req->len)) result = -EFAULT; else result = p80211req_dorequest(wlandev, msgbuf); if (result == 0) { if (copy_to_user ((void __user *)req->data, msgbuf, req->len)) { result = -EFAULT; } } kfree(msgbuf); } else { result = -ENOMEM; } bail: /* If allocate,copyfrom or copyto fails, return errno */ return result; }
/*---------------------------------------------------------------- * p80211knetdev_do_ioctl * * Handle an ioctl call on one of our devices. Everything Linux * ioctl specific is done here. Then we pass the contents of the * ifr->data to the request message handler. * * Arguments: * dev Linux kernel netdevice * ifr Our private ioctl request structure, typed for the * generic struct ifreq so we can use ptr to func * w/o cast. * * Returns: * zero on success, a negative errno on failure. Possible values: * -ENETDOWN Device isn't up. * -EBUSY cmd already in progress * -ETIME p80211 cmd timed out (MSD may have its own timers) * -EFAULT memory fault copying msg from user buffer * -ENOMEM unable to allocate kernel msg buffer * -ENOSYS bad magic, it the cmd really for us? * -EINTR sleeping on cmd, awakened by signal, cmd cancelled. * * Call Context: * Process thread (ioctl caller). TODO: SMP support may require * locks. ----------------------------------------------------------------*/ static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) { int result = 0; p80211ioctl_req_t *req = (p80211ioctl_req_t*)ifr; wlandevice_t *wlandev = (wlandevice_t*)dev->priv; UINT8 *msgbuf; DBFENTER; WLAN_LOG_DEBUG(2, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); #if WIRELESS_EXT < 13 /* Is this a wireless extensions ioctl? */ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { if ((result = p80211wext_support_ioctl(dev, ifr, cmd)) != (-EOPNOTSUPP)) { goto bail; } } #endif #ifdef SIOCETHTOOL if (cmd == SIOCETHTOOL) { result = p80211netdev_ethtool(wlandev, (void __user *) ifr->ifr_data); goto bail; } #endif /* Test the magic, assume ifr is good if it's there */ if ( req->magic != P80211_IOCTL_MAGIC ) { result = -ENOSYS; goto bail; } if ( cmd == P80211_IFTEST ) { result = 0; goto bail; } else if ( cmd != P80211_IFREQ ) { result = -ENOSYS; goto bail; } /* Allocate a buf of size req->len */ if ((msgbuf = kmalloc( req->len, GFP_KERNEL))) { if ( copy_from_user( msgbuf, (void __user *) req->data, req->len) ) { result = -EFAULT; } else { result = p80211req_dorequest( wlandev, msgbuf); } if ( result == 0 ) { if ( copy_to_user( (void __user *) req->data, msgbuf, req->len)) { result = -EFAULT; } } kfree(msgbuf); } else { result = -ENOMEM; } bail: DBFEXIT; return result; /* If allocate,copyfrom or copyto fails, return errno */ }