10 #include <linux/kernel.h>
11 #include <linux/netdevice.h>
12 #include <linux/rtnetlink.h>
13 #include <linux/slab.h>
14 #include <linux/wireless.h>
16 #include <linux/export.h>
76 .max_tokens =
sizeof(
struct iw_range),
99 .token_size =
sizeof(
struct sockaddr),
104 .token_size =
sizeof(
struct sockaddr) +
105 sizeof(struct iw_quality),
130 .min_tokens =
sizeof(
struct iw_mlme),
131 .max_tokens =
sizeof(
struct iw_mlme),
133 [IW_IOCTL_IDX(SIOCGIWAPLIST)] = {
135 .token_size =
sizeof(
struct sockaddr) +
136 sizeof(struct iw_quality),
146 [IW_IOCTL_IDX(SIOCGIWSCAN)] = {
243 IW_ENCODING_TOKEN_MAX,
245 [IW_IOCTL_IDX(SIOCGIWENCODEEXT)] = {
250 IW_ENCODING_TOKEN_MAX,
252 [IW_IOCTL_IDX(SIOCSIWPMKSA)] = {
255 .min_tokens =
sizeof(
struct iw_pmksa),
256 .max_tokens =
sizeof(
struct iw_pmksa),
259 static const unsigned int standard_ioctl_num =
ARRAY_SIZE(standard_ioctl);
293 [IW_EVENT_IDX(IWEVASSOCREQIE)] = {
309 static const unsigned int standard_event_num =
ARRAY_SIZE(standard_event);
312 static const int event_type_size[] = {
327 static const int compat_event_type_size[] = {
328 IW_EV_COMPAT_LCP_LEN,
330 IW_EV_COMPAT_CHAR_LEN,
332 IW_EV_COMPAT_UINT_LEN,
333 IW_EV_COMPAT_FREQ_LEN,
334 IW_EV_COMPAT_ADDR_LEN,
336 IW_EV_COMPAT_POINT_LEN,
337 IW_EV_COMPAT_PARAM_LEN,
338 IW_EV_COMPAT_QUAL_LEN,
347 skb_queue_head_init(&net->wext_nlevents);
351 static void __net_exit wext_pernet_exit(
struct net *net)
357 .
init = wext_pernet_init,
358 .exit = wext_pernet_exit,
361 static int __init wireless_nlevent_init(
void)
385 static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);
393 nlh = nlmsg_put(skb, 0, 0,
RTM_NEWLINK,
sizeof(*r), 0);
406 goto nla_put_failure;
410 nlmsg_cancel(skb, nlh);
432 unsigned int cmd_index;
437 struct __compat_iw_event *compat_event;
438 struct compat_iw_point compat_wrqu;
450 if (
WARN_ON(cmd == SIOCGIWSCAN && extra))
456 if (cmd_index < standard_ioctl_num)
457 descr = &(standard_ioctl[cmd_index]);
460 if (cmd_index < standard_event_num)
461 descr = &(standard_event[cmd_index]);
472 netdev_err(dev,
"(WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
481 netdev_err(dev,
"(WE) : Wireless Event (cmd=0x%04X) too big (%d)\n",
482 cmd, wrqu->
data.length);
486 netdev_err(dev,
"(WE) : Wireless Event (cmd=0x%04X) too small (%d)\n",
487 cmd, wrqu->
data.length);
499 event_len = hdr_len + extra_len;
529 nlh = rtnetlink_ifinfo_prep(dev, skb);
541 event = nla_data(nla);
544 memset(event, 0, hdr_len);
545 event->len = event_len;
549 memcpy(((
char *) event) + hdr_len, extra, extra_len);
553 hdr_len = compat_event_type_size[descr->
header_type];
554 event_len = hdr_len + extra_len;
563 nlh = rtnetlink_ifinfo_prep(dev, compskb);
577 compat_event = nla_data(nla);
579 compat_event->len = event_len;
580 compat_event->cmd =
cmd;
582 compat_wrqu.length = wrqu->
data.length;
583 compat_wrqu.flags = wrqu->
data.flags;
584 memcpy(&compat_event->pointer,
585 ((
char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF,
586 hdr_len - IW_EV_COMPAT_LCP_LEN);
588 memcpy(((
char *) compat_event) + hdr_len,
592 memcpy(&compat_event->pointer, wrqu,
593 hdr_len - IW_EV_COMPAT_LCP_LEN);
596 nlmsg_end(compskb, nlh);
598 skb_shinfo(skb)->frag_list = compskb;
611 #ifdef CONFIG_WIRELESS_EXT
612 if ((dev->wireless_handlers !=
NULL) &&
613 (dev->wireless_handlers->get_wireless_stats !=
NULL))
614 return dev->wireless_handlers->get_wireless_stats(dev);
617 #ifdef CONFIG_CFG80211_WEXT
622 return dev->
ieee80211_ptr->wiphy->wext->get_wireless_stats(dev);
629 static int iw_handler_get_iwstats(
struct net_device * dev,
644 if (wrqu->
data.flags != 0)
657 #ifdef CONFIG_CFG80211_WEXT
661 #ifdef CONFIG_WIRELESS_EXT
662 if (dev->wireless_handlers)
663 handlers = dev->wireless_handlers;
674 #ifdef CONFIG_WEXT_PRIV
677 if (index < handlers->num_private)
678 return handlers->private[
index];
685 static int ioctl_standard_iw_point(
struct iw_point *iwp,
unsigned int cmd,
718 if (essid[iwp->
length - 1] ==
'\0')
726 iwp->
length -= essid_compat;
743 user_length = iwp->
length;
807 err = handler(dev, info, (
union iwreq_data *) iwp, extra);
809 iwp->
length += essid_compat;
814 if (user_length < iwp->
length) {
866 #ifdef CONFIG_WIRELESS_EXT
867 if ((netif_running(dev)) &&
868 (dev->wireless_handlers->standard[0] !=
NULL))
870 return dev->wireless_handlers->standard[0](
dev,
NULL,
884 static int wireless_process_ioctl(
struct net *net,
struct ifreq *ifr,
905 return standard(dev, iwr, cmd, info,
906 &iw_handler_get_iwstats);
908 #ifdef CONFIG_WEXT_PRIV
910 return standard(dev, iwr, cmd, info,
915 if (!netif_device_present(dev))
919 handler = get_handler(dev, cmd);
922 if (cmd < SIOCIWFIRSTPRIV)
923 return standard(dev, iwr, cmd, info, handler);
929 return dev->
netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
936 static int wext_permission_check(
unsigned int cmd)
939 cmd == SIOCGIWENCODEEXT) &&
947 static int wext_ioctl_dispatch(
struct net *net,
struct ifreq *ifr,
952 int ret = wext_permission_check(cmd);
959 ret = wireless_process_ioctl(net, ifr, cmd, info, standard,
private);
970 static int ioctl_standard_call(
struct net_device * dev,
988 ret = handler(dev, info, &(iwr->
u),
NULL);
995 ret = ioctl_standard_iw_point(&iwr->
u.
data, cmd, descr,
1015 ret = wext_ioctl_dispatch(net, ifr, cmd, &info,
1016 ioctl_standard_call,
1026 #ifdef CONFIG_COMPAT
1027 static int compat_standard_call(
struct net_device *dev,
1034 struct compat_iw_point *iwp_compat;
1041 return ioctl_standard_call(dev, iwr, cmd, info, handler);
1043 iwp_compat = (
struct compat_iw_point *) &iwr->
u.
data;
1044 iwp.
pointer = compat_ptr(iwp_compat->pointer);
1045 iwp.
length = iwp_compat->length;
1046 iwp.
flags = iwp_compat->flags;
1048 err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, info);
1050 iwp_compat->pointer = ptr_to_compat(iwp.
pointer);
1051 iwp_compat->length = iwp.
length;
1052 iwp_compat->flags = iwp.
flags;
1057 int compat_wext_handle_ioctl(
struct net *net,
unsigned int cmd,
1070 colon =
strchr(iwr.ifr_name,
':');
1077 ret = wext_ioctl_dispatch(net, (
struct ifreq *) &iwr, cmd, &info,
1078 compat_standard_call,