staticint __init wireless_nlevent_init(void)
{ int err = register_pernet_subsys(&wext_pernet_ops);
if (err) return err;
err = register_netdevice_notifier(&wext_netdev_notifier); if (err)
unregister_pernet_subsys(&wext_pernet_ops); return err;
}
subsys_initcall(wireless_nlevent_init);
/* Process events generated by the wireless layer or the driver. */ staticvoid wireless_nlevent_process(struct work_struct *work)
{
wireless_nlevent_flush();
}
/* *Maineventdispatcher.Calledfromotherpartsanddrivers. *Sendtheeventontheappropriatechannels. *Maybecalledfrominterruptcontext.
*/ void wireless_send_event(struct net_device * dev, unsignedint cmd, union iwreq_data * wrqu, constchar * extra)
{ conststruct iw_ioctl_description * descr = NULL; int extra_len = 0; struct iw_event *event; /* Mallocated whole event */ int event_len; /* Its size */ int hdr_len; /* Size of the event header */ int wrqu_off = 0; /* Offset in wrqu */ /* Don't "optimise" the following variable, it will crash */ unsignedint cmd_index; /* *MUST* be unsigned */ struct sk_buff *skb; struct nlmsghdr *nlh; struct nlattr *nla; #ifdef CONFIG_COMPAT struct __compat_iw_event *compat_event; struct compat_iw_point compat_wrqu; struct sk_buff *compskb; int ptr_len; #endif
/* *Nothinginthekernelsendsscaneventswithdata,besafe. *Thisisnecessarybecausewecannotfixupscaneventdata *forcompat,duetobeingcontainedin'extra',butnormally *applicationsarerequiredtoretrievethescandataanyway *andnodataisincludedintheevent,thiscodifiesthat *practice.
*/ if (WARN_ON(cmd == SIOCGIWSCAN && extra))
extra = NULL;
/* Get the description of the Event */ if (cmd <= SIOCIWLAST) {
cmd_index = IW_IOCTL_IDX(cmd); if (cmd_index < standard_ioctl_num)
descr = &(standard_ioctl[cmd_index]);
} else {
cmd_index = IW_EVENT_IDX(cmd); if (cmd_index < standard_event_num)
descr = &(standard_event[cmd_index]);
} /* Don't accept unknown events */ if (descr == NULL) { /* Note : we don't return an error to the driver, because *thedriverwouldnotknowwhattodoaboutit.Itcan't *returnanerrortotheuser,becausetheeventisnot *initiatedbyauserrequest. *Thebestthedrivercoulddoistologanerrormessage. *Wewilldoitourselvesinstead...
*/
netdev_err(dev, "(WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
cmd); return;
}
/* Check extra parameters and set extra_len */ if (descr->header_type == IW_HEADER_TYPE_POINT) { /* Check if number of token fits within bounds */ if (wrqu->data.length > descr->max_tokens) {
netdev_err(dev, "(WE) : Wireless Event (cmd=0x%04X) too big (%d)\n",
cmd, wrqu->data.length); return;
} if (wrqu->data.length < descr->min_tokens) {
netdev_err(dev, "(WE) : Wireless Event (cmd=0x%04X) too small (%d)\n",
cmd, wrqu->data.length); return;
} /* Calculate extra_len - extra is NULL for restricted events */ if (extra != NULL)
extra_len = wrqu->data.length * descr->token_size; /* Always at an offset in wrqu */
wrqu_off = IW_EV_POINT_OFF;
}
/* Total length of the event */
hdr_len = event_type_size[descr->header_type];
event_len = hdr_len + extra_len;
#ifdef CONFIG_CFG80211_WEXT staticvoid wireless_warn_cfg80211_wext(void)
{
pr_warn_once("warning: `%s' uses wireless extensions which will stop working for Wi-Fi 7 hardware; use nl80211\n",
current->comm);
} #endif
/* noinline to avoid a bogus warning with -O3 */ static noinline int iw_handler_get_iwstats(struct net_device * dev, struct iw_request_info * info, union iwreq_data * wrqu, char * extra)
{ /* Get stats from the driver */ struct iw_statistics *stats;
stats = get_wireless_stats(dev); if (stats) { /* Copy statistics to extra */
memcpy(extra, stats, sizeof(struct iw_statistics));
wrqu->data.length = sizeof(struct iw_statistics);
/* Check if we need to clear the updated flag */ if (wrqu->data.flags != 0)
stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; return0;
} else return -EOPNOTSUPP;
}
static iw_handler get_handler(struct net_device *dev, unsignedint cmd)
{ /* Don't "optimise" the following variable, it will crash */ unsignedint index; /* *MUST* be unsigned */ conststruct iw_handler_def *handlers = NULL;
#ifdef CONFIG_CFG80211_WEXT if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy) {
wireless_warn_cfg80211_wext(); if (dev->ieee80211_ptr->wiphy->flags & (WIPHY_FLAG_SUPPORTS_MLO |
WIPHY_FLAG_DISABLE_WEXT)) return NULL;
handlers = dev->ieee80211_ptr->wiphy->wext;
} #endif #ifdef CONFIG_WIRELESS_EXT if (dev->wireless_handlers)
handlers = dev->wireless_handlers; #endif
if (!handlers) return NULL;
/* Try as a standard command */
index = IW_IOCTL_IDX(cmd); if (index < handlers->num_standard) return handlers->standard[index];
#ifdef CONFIG_WEXT_PRIV /* Try as a private command */
index = cmd - SIOCIWFIRSTPRIV; if (index < handlers->num_private) return handlers->private[index]; #endif
/* Calculate space needed by arguments. Always allocate *formaxspace.
*/
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; elseif (IW_IS_SET(cmd) && (iwp->length != 0)) { char essid[IW_ESSID_MAX_SIZE + 1]; unsignedint len;
len = iwp->length * descr->token_size;
if (len > IW_ESSID_MAX_SIZE) return -EFAULT;
err = copy_from_user(essid, iwp->pointer, len); if (err) return -EFAULT;
/* 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.Thetestuser_length<minis *impliedbythetestattheend.
*/
/* 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 *wecansupportanysizeGETrequests. *Thereisstillalimit:-ENOMEM.
*/
extra_size = user_length * descr->token_size;
/* Note : user_length is originally a __u16, *andtoken_sizeiscontrolledbyus, *soextra_sizewon'tgetnegativeand *won'toverflow...
*/
}
}
/* Sanity-check to ensure we never end up _allocating_ zero *bytesofdataforextra.
*/ if (extra_size <= 0) return -EFAULT;
/* 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;
}
/* 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;
}
/* Permissions are already checked in dev_ioctl() before calling us.
* The copy_to/from_user() of ifr is also dealt with in there */
/* Make sure the device exist */ if ((dev = __dev_get_by_name(net, iwr->ifr_name)) == NULL) return -ENODEV;
/* A bunch of special cases, then the generic case... *Notethat'cmd'isalreadyfilteredindev_ioctl()with
* (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ if (cmd == SIOCGIWSTATS) return standard(dev, iwr, cmd, info,
&iw_handler_get_iwstats);
/* Basic check */ if (!netif_device_present(dev)) return -ENODEV;
/* New driver API : try to find the handler */
handler = get_handler(dev, cmd); if (handler) { /* Standard and private are not the same */ if (cmd < SIOCIWFIRSTPRIV) return standard(dev, iwr, cmd, info, handler); elseif (private) returnprivate(dev, iwr, cmd, info, handler);
} return -EOPNOTSUPP;
}
/* If command is `set a parameter', or `get the encoding parameters', *checkiftheuserhastherighttodoit.
*/ staticint wext_permission_check(unsignedint cmd)
{ if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE ||
cmd == SIOCGIWENCODEEXT) &&
!capable(CAP_NET_ADMIN)) return -EPERM;
return0;
}
/* entry point from dev ioctl */ staticint wext_ioctl_dispatch(struct net *net, struct iwreq *iwr, unsignedint cmd, struct iw_request_info *info,
wext_ioctl_func standard,
wext_ioctl_func private)
{ int ret = wext_permission_check(cmd);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.