cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wext-core.c (32372B)


      1/*
      2 * This file implement the Wireless Extensions core API.
      3 *
      4 * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
      5 * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
      6 * Copyright	2009 Johannes Berg <johannes@sipsolutions.net>
      7 *
      8 * (As all part of the Linux kernel, this file is GPL)
      9 */
     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>
     15#include <linux/uaccess.h>
     16#include <linux/export.h>
     17#include <net/cfg80211.h>
     18#include <net/iw_handler.h>
     19#include <net/netlink.h>
     20#include <net/wext.h>
     21#include <net/net_namespace.h>
     22
     23typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *,
     24			       unsigned int, struct iw_request_info *,
     25			       iw_handler);
     26
     27
     28/*
     29 * Meta-data about all the standard Wireless Extension request we
     30 * know about.
     31 */
     32static const struct iw_ioctl_description standard_ioctl[] = {
     33	[IW_IOCTL_IDX(SIOCSIWCOMMIT)] = {
     34		.header_type	= IW_HEADER_TYPE_NULL,
     35	},
     36	[IW_IOCTL_IDX(SIOCGIWNAME)] = {
     37		.header_type	= IW_HEADER_TYPE_CHAR,
     38		.flags		= IW_DESCR_FLAG_DUMP,
     39	},
     40	[IW_IOCTL_IDX(SIOCSIWNWID)] = {
     41		.header_type	= IW_HEADER_TYPE_PARAM,
     42		.flags		= IW_DESCR_FLAG_EVENT,
     43	},
     44	[IW_IOCTL_IDX(SIOCGIWNWID)] = {
     45		.header_type	= IW_HEADER_TYPE_PARAM,
     46		.flags		= IW_DESCR_FLAG_DUMP,
     47	},
     48	[IW_IOCTL_IDX(SIOCSIWFREQ)] = {
     49		.header_type	= IW_HEADER_TYPE_FREQ,
     50		.flags		= IW_DESCR_FLAG_EVENT,
     51	},
     52	[IW_IOCTL_IDX(SIOCGIWFREQ)] = {
     53		.header_type	= IW_HEADER_TYPE_FREQ,
     54		.flags		= IW_DESCR_FLAG_DUMP,
     55	},
     56	[IW_IOCTL_IDX(SIOCSIWMODE)] = {
     57		.header_type	= IW_HEADER_TYPE_UINT,
     58		.flags		= IW_DESCR_FLAG_EVENT,
     59	},
     60	[IW_IOCTL_IDX(SIOCGIWMODE)] = {
     61		.header_type	= IW_HEADER_TYPE_UINT,
     62		.flags		= IW_DESCR_FLAG_DUMP,
     63	},
     64	[IW_IOCTL_IDX(SIOCSIWSENS)] = {
     65		.header_type	= IW_HEADER_TYPE_PARAM,
     66	},
     67	[IW_IOCTL_IDX(SIOCGIWSENS)] = {
     68		.header_type	= IW_HEADER_TYPE_PARAM,
     69	},
     70	[IW_IOCTL_IDX(SIOCSIWRANGE)] = {
     71		.header_type	= IW_HEADER_TYPE_NULL,
     72	},
     73	[IW_IOCTL_IDX(SIOCGIWRANGE)] = {
     74		.header_type	= IW_HEADER_TYPE_POINT,
     75		.token_size	= 1,
     76		.max_tokens	= sizeof(struct iw_range),
     77		.flags		= IW_DESCR_FLAG_DUMP,
     78	},
     79	[IW_IOCTL_IDX(SIOCSIWPRIV)] = {
     80		.header_type	= IW_HEADER_TYPE_NULL,
     81	},
     82	[IW_IOCTL_IDX(SIOCGIWPRIV)] = { /* (handled directly by us) */
     83		.header_type	= IW_HEADER_TYPE_POINT,
     84		.token_size	= sizeof(struct iw_priv_args),
     85		.max_tokens	= 16,
     86		.flags		= IW_DESCR_FLAG_NOMAX,
     87	},
     88	[IW_IOCTL_IDX(SIOCSIWSTATS)] = {
     89		.header_type	= IW_HEADER_TYPE_NULL,
     90	},
     91	[IW_IOCTL_IDX(SIOCGIWSTATS)] = { /* (handled directly by us) */
     92		.header_type	= IW_HEADER_TYPE_POINT,
     93		.token_size	= 1,
     94		.max_tokens	= sizeof(struct iw_statistics),
     95		.flags		= IW_DESCR_FLAG_DUMP,
     96	},
     97	[IW_IOCTL_IDX(SIOCSIWSPY)] = {
     98		.header_type	= IW_HEADER_TYPE_POINT,
     99		.token_size	= sizeof(struct sockaddr),
    100		.max_tokens	= IW_MAX_SPY,
    101	},
    102	[IW_IOCTL_IDX(SIOCGIWSPY)] = {
    103		.header_type	= IW_HEADER_TYPE_POINT,
    104		.token_size	= sizeof(struct sockaddr) +
    105				  sizeof(struct iw_quality),
    106		.max_tokens	= IW_MAX_SPY,
    107	},
    108	[IW_IOCTL_IDX(SIOCSIWTHRSPY)] = {
    109		.header_type	= IW_HEADER_TYPE_POINT,
    110		.token_size	= sizeof(struct iw_thrspy),
    111		.min_tokens	= 1,
    112		.max_tokens	= 1,
    113	},
    114	[IW_IOCTL_IDX(SIOCGIWTHRSPY)] = {
    115		.header_type	= IW_HEADER_TYPE_POINT,
    116		.token_size	= sizeof(struct iw_thrspy),
    117		.min_tokens	= 1,
    118		.max_tokens	= 1,
    119	},
    120	[IW_IOCTL_IDX(SIOCSIWAP)] = {
    121		.header_type	= IW_HEADER_TYPE_ADDR,
    122	},
    123	[IW_IOCTL_IDX(SIOCGIWAP)] = {
    124		.header_type	= IW_HEADER_TYPE_ADDR,
    125		.flags		= IW_DESCR_FLAG_DUMP,
    126	},
    127	[IW_IOCTL_IDX(SIOCSIWMLME)] = {
    128		.header_type	= IW_HEADER_TYPE_POINT,
    129		.token_size	= 1,
    130		.min_tokens	= sizeof(struct iw_mlme),
    131		.max_tokens	= sizeof(struct iw_mlme),
    132	},
    133	[IW_IOCTL_IDX(SIOCGIWAPLIST)] = {
    134		.header_type	= IW_HEADER_TYPE_POINT,
    135		.token_size	= sizeof(struct sockaddr) +
    136				  sizeof(struct iw_quality),
    137		.max_tokens	= IW_MAX_AP,
    138		.flags		= IW_DESCR_FLAG_NOMAX,
    139	},
    140	[IW_IOCTL_IDX(SIOCSIWSCAN)] = {
    141		.header_type	= IW_HEADER_TYPE_POINT,
    142		.token_size	= 1,
    143		.min_tokens	= 0,
    144		.max_tokens	= sizeof(struct iw_scan_req),
    145	},
    146	[IW_IOCTL_IDX(SIOCGIWSCAN)] = {
    147		.header_type	= IW_HEADER_TYPE_POINT,
    148		.token_size	= 1,
    149		.max_tokens	= IW_SCAN_MAX_DATA,
    150		.flags		= IW_DESCR_FLAG_NOMAX,
    151	},
    152	[IW_IOCTL_IDX(SIOCSIWESSID)] = {
    153		.header_type	= IW_HEADER_TYPE_POINT,
    154		.token_size	= 1,
    155		.max_tokens	= IW_ESSID_MAX_SIZE,
    156		.flags		= IW_DESCR_FLAG_EVENT,
    157	},
    158	[IW_IOCTL_IDX(SIOCGIWESSID)] = {
    159		.header_type	= IW_HEADER_TYPE_POINT,
    160		.token_size	= 1,
    161		.max_tokens	= IW_ESSID_MAX_SIZE,
    162		.flags		= IW_DESCR_FLAG_DUMP,
    163	},
    164	[IW_IOCTL_IDX(SIOCSIWNICKN)] = {
    165		.header_type	= IW_HEADER_TYPE_POINT,
    166		.token_size	= 1,
    167		.max_tokens	= IW_ESSID_MAX_SIZE,
    168	},
    169	[IW_IOCTL_IDX(SIOCGIWNICKN)] = {
    170		.header_type	= IW_HEADER_TYPE_POINT,
    171		.token_size	= 1,
    172		.max_tokens	= IW_ESSID_MAX_SIZE,
    173	},
    174	[IW_IOCTL_IDX(SIOCSIWRATE)] = {
    175		.header_type	= IW_HEADER_TYPE_PARAM,
    176	},
    177	[IW_IOCTL_IDX(SIOCGIWRATE)] = {
    178		.header_type	= IW_HEADER_TYPE_PARAM,
    179	},
    180	[IW_IOCTL_IDX(SIOCSIWRTS)] = {
    181		.header_type	= IW_HEADER_TYPE_PARAM,
    182	},
    183	[IW_IOCTL_IDX(SIOCGIWRTS)] = {
    184		.header_type	= IW_HEADER_TYPE_PARAM,
    185	},
    186	[IW_IOCTL_IDX(SIOCSIWFRAG)] = {
    187		.header_type	= IW_HEADER_TYPE_PARAM,
    188	},
    189	[IW_IOCTL_IDX(SIOCGIWFRAG)] = {
    190		.header_type	= IW_HEADER_TYPE_PARAM,
    191	},
    192	[IW_IOCTL_IDX(SIOCSIWTXPOW)] = {
    193		.header_type	= IW_HEADER_TYPE_PARAM,
    194	},
    195	[IW_IOCTL_IDX(SIOCGIWTXPOW)] = {
    196		.header_type	= IW_HEADER_TYPE_PARAM,
    197	},
    198	[IW_IOCTL_IDX(SIOCSIWRETRY)] = {
    199		.header_type	= IW_HEADER_TYPE_PARAM,
    200	},
    201	[IW_IOCTL_IDX(SIOCGIWRETRY)] = {
    202		.header_type	= IW_HEADER_TYPE_PARAM,
    203	},
    204	[IW_IOCTL_IDX(SIOCSIWENCODE)] = {
    205		.header_type	= IW_HEADER_TYPE_POINT,
    206		.token_size	= 1,
    207		.max_tokens	= IW_ENCODING_TOKEN_MAX,
    208		.flags		= IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
    209	},
    210	[IW_IOCTL_IDX(SIOCGIWENCODE)] = {
    211		.header_type	= IW_HEADER_TYPE_POINT,
    212		.token_size	= 1,
    213		.max_tokens	= IW_ENCODING_TOKEN_MAX,
    214		.flags		= IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
    215	},
    216	[IW_IOCTL_IDX(SIOCSIWPOWER)] = {
    217		.header_type	= IW_HEADER_TYPE_PARAM,
    218	},
    219	[IW_IOCTL_IDX(SIOCGIWPOWER)] = {
    220		.header_type	= IW_HEADER_TYPE_PARAM,
    221	},
    222	[IW_IOCTL_IDX(SIOCSIWGENIE)] = {
    223		.header_type	= IW_HEADER_TYPE_POINT,
    224		.token_size	= 1,
    225		.max_tokens	= IW_GENERIC_IE_MAX,
    226	},
    227	[IW_IOCTL_IDX(SIOCGIWGENIE)] = {
    228		.header_type	= IW_HEADER_TYPE_POINT,
    229		.token_size	= 1,
    230		.max_tokens	= IW_GENERIC_IE_MAX,
    231	},
    232	[IW_IOCTL_IDX(SIOCSIWAUTH)] = {
    233		.header_type	= IW_HEADER_TYPE_PARAM,
    234	},
    235	[IW_IOCTL_IDX(SIOCGIWAUTH)] = {
    236		.header_type	= IW_HEADER_TYPE_PARAM,
    237	},
    238	[IW_IOCTL_IDX(SIOCSIWENCODEEXT)] = {
    239		.header_type	= IW_HEADER_TYPE_POINT,
    240		.token_size	= 1,
    241		.min_tokens	= sizeof(struct iw_encode_ext),
    242		.max_tokens	= sizeof(struct iw_encode_ext) +
    243				  IW_ENCODING_TOKEN_MAX,
    244	},
    245	[IW_IOCTL_IDX(SIOCGIWENCODEEXT)] = {
    246		.header_type	= IW_HEADER_TYPE_POINT,
    247		.token_size	= 1,
    248		.min_tokens	= sizeof(struct iw_encode_ext),
    249		.max_tokens	= sizeof(struct iw_encode_ext) +
    250				  IW_ENCODING_TOKEN_MAX,
    251	},
    252	[IW_IOCTL_IDX(SIOCSIWPMKSA)] = {
    253		.header_type	= IW_HEADER_TYPE_POINT,
    254		.token_size	= 1,
    255		.min_tokens	= sizeof(struct iw_pmksa),
    256		.max_tokens	= sizeof(struct iw_pmksa),
    257	},
    258};
    259static const unsigned int standard_ioctl_num = ARRAY_SIZE(standard_ioctl);
    260
    261/*
    262 * Meta-data about all the additional standard Wireless Extension events
    263 * we know about.
    264 */
    265static const struct iw_ioctl_description standard_event[] = {
    266	[IW_EVENT_IDX(IWEVTXDROP)] = {
    267		.header_type	= IW_HEADER_TYPE_ADDR,
    268	},
    269	[IW_EVENT_IDX(IWEVQUAL)] = {
    270		.header_type	= IW_HEADER_TYPE_QUAL,
    271	},
    272	[IW_EVENT_IDX(IWEVCUSTOM)] = {
    273		.header_type	= IW_HEADER_TYPE_POINT,
    274		.token_size	= 1,
    275		.max_tokens	= IW_CUSTOM_MAX,
    276	},
    277	[IW_EVENT_IDX(IWEVREGISTERED)] = {
    278		.header_type	= IW_HEADER_TYPE_ADDR,
    279	},
    280	[IW_EVENT_IDX(IWEVEXPIRED)] = {
    281		.header_type	= IW_HEADER_TYPE_ADDR,
    282	},
    283	[IW_EVENT_IDX(IWEVGENIE)] = {
    284		.header_type	= IW_HEADER_TYPE_POINT,
    285		.token_size	= 1,
    286		.max_tokens	= IW_GENERIC_IE_MAX,
    287	},
    288	[IW_EVENT_IDX(IWEVMICHAELMICFAILURE)] = {
    289		.header_type	= IW_HEADER_TYPE_POINT,
    290		.token_size	= 1,
    291		.max_tokens	= sizeof(struct iw_michaelmicfailure),
    292	},
    293	[IW_EVENT_IDX(IWEVASSOCREQIE)] = {
    294		.header_type	= IW_HEADER_TYPE_POINT,
    295		.token_size	= 1,
    296		.max_tokens	= IW_GENERIC_IE_MAX,
    297	},
    298	[IW_EVENT_IDX(IWEVASSOCRESPIE)] = {
    299		.header_type	= IW_HEADER_TYPE_POINT,
    300		.token_size	= 1,
    301		.max_tokens	= IW_GENERIC_IE_MAX,
    302	},
    303	[IW_EVENT_IDX(IWEVPMKIDCAND)] = {
    304		.header_type	= IW_HEADER_TYPE_POINT,
    305		.token_size	= 1,
    306		.max_tokens	= sizeof(struct iw_pmkid_cand),
    307	},
    308};
    309static const unsigned int standard_event_num = ARRAY_SIZE(standard_event);
    310
    311/* Size (in bytes) of various events */
    312static const int event_type_size[] = {
    313	IW_EV_LCP_LEN,			/* IW_HEADER_TYPE_NULL */
    314	0,
    315	IW_EV_CHAR_LEN,			/* IW_HEADER_TYPE_CHAR */
    316	0,
    317	IW_EV_UINT_LEN,			/* IW_HEADER_TYPE_UINT */
    318	IW_EV_FREQ_LEN,			/* IW_HEADER_TYPE_FREQ */
    319	IW_EV_ADDR_LEN,			/* IW_HEADER_TYPE_ADDR */
    320	0,
    321	IW_EV_POINT_LEN,		/* Without variable payload */
    322	IW_EV_PARAM_LEN,		/* IW_HEADER_TYPE_PARAM */
    323	IW_EV_QUAL_LEN,			/* IW_HEADER_TYPE_QUAL */
    324};
    325
    326#ifdef CONFIG_COMPAT
    327static const int compat_event_type_size[] = {
    328	IW_EV_COMPAT_LCP_LEN,		/* IW_HEADER_TYPE_NULL */
    329	0,
    330	IW_EV_COMPAT_CHAR_LEN,		/* IW_HEADER_TYPE_CHAR */
    331	0,
    332	IW_EV_COMPAT_UINT_LEN,		/* IW_HEADER_TYPE_UINT */
    333	IW_EV_COMPAT_FREQ_LEN,		/* IW_HEADER_TYPE_FREQ */
    334	IW_EV_COMPAT_ADDR_LEN,		/* IW_HEADER_TYPE_ADDR */
    335	0,
    336	IW_EV_COMPAT_POINT_LEN,		/* Without variable payload */
    337	IW_EV_COMPAT_PARAM_LEN,		/* IW_HEADER_TYPE_PARAM */
    338	IW_EV_COMPAT_QUAL_LEN,		/* IW_HEADER_TYPE_QUAL */
    339};
    340#endif
    341
    342
    343/* IW event code */
    344
    345void wireless_nlevent_flush(void)
    346{
    347	struct sk_buff *skb;
    348	struct net *net;
    349
    350	down_read(&net_rwsem);
    351	for_each_net(net) {
    352		while ((skb = skb_dequeue(&net->wext_nlevents)))
    353			rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
    354				    GFP_KERNEL);
    355	}
    356	up_read(&net_rwsem);
    357}
    358EXPORT_SYMBOL_GPL(wireless_nlevent_flush);
    359
    360static int wext_netdev_notifier_call(struct notifier_block *nb,
    361				     unsigned long state, void *ptr)
    362{
    363	/*
    364	 * When a netdev changes state in any way, flush all pending messages
    365	 * to avoid them going out in a strange order, e.g. RTM_NEWLINK after
    366	 * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close()
    367	 * or similar - all of which could otherwise happen due to delays from
    368	 * schedule_work().
    369	 */
    370	wireless_nlevent_flush();
    371
    372	return NOTIFY_OK;
    373}
    374
    375static struct notifier_block wext_netdev_notifier = {
    376	.notifier_call = wext_netdev_notifier_call,
    377};
    378
    379static int __net_init wext_pernet_init(struct net *net)
    380{
    381	skb_queue_head_init(&net->wext_nlevents);
    382	return 0;
    383}
    384
    385static void __net_exit wext_pernet_exit(struct net *net)
    386{
    387	skb_queue_purge(&net->wext_nlevents);
    388}
    389
    390static struct pernet_operations wext_pernet_ops = {
    391	.init = wext_pernet_init,
    392	.exit = wext_pernet_exit,
    393};
    394
    395static int __init wireless_nlevent_init(void)
    396{
    397	int err = register_pernet_subsys(&wext_pernet_ops);
    398
    399	if (err)
    400		return err;
    401
    402	err = register_netdevice_notifier(&wext_netdev_notifier);
    403	if (err)
    404		unregister_pernet_subsys(&wext_pernet_ops);
    405	return err;
    406}
    407
    408subsys_initcall(wireless_nlevent_init);
    409
    410/* Process events generated by the wireless layer or the driver. */
    411static void wireless_nlevent_process(struct work_struct *work)
    412{
    413	wireless_nlevent_flush();
    414}
    415
    416static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);
    417
    418static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev,
    419					      struct sk_buff *skb)
    420{
    421	struct ifinfomsg *r;
    422	struct nlmsghdr  *nlh;
    423
    424	nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0);
    425	if (!nlh)
    426		return NULL;
    427
    428	r = nlmsg_data(nlh);
    429	r->ifi_family = AF_UNSPEC;
    430	r->__ifi_pad = 0;
    431	r->ifi_type = dev->type;
    432	r->ifi_index = dev->ifindex;
    433	r->ifi_flags = dev_get_flags(dev);
    434	r->ifi_change = 0;	/* Wireless changes don't affect those flags */
    435
    436	if (nla_put_string(skb, IFLA_IFNAME, dev->name))
    437		goto nla_put_failure;
    438
    439	return nlh;
    440 nla_put_failure:
    441	nlmsg_cancel(skb, nlh);
    442	return NULL;
    443}
    444
    445
    446/*
    447 * Main event dispatcher. Called from other parts and drivers.
    448 * Send the event on the appropriate channels.
    449 * May be called from interrupt context.
    450 */
    451void wireless_send_event(struct net_device *	dev,
    452			 unsigned int		cmd,
    453			 union iwreq_data *	wrqu,
    454			 const char *		extra)
    455{
    456	const struct iw_ioctl_description *	descr = NULL;
    457	int extra_len = 0;
    458	struct iw_event  *event;		/* Mallocated whole event */
    459	int event_len;				/* Its size */
    460	int hdr_len;				/* Size of the event header */
    461	int wrqu_off = 0;			/* Offset in wrqu */
    462	/* Don't "optimise" the following variable, it will crash */
    463	unsigned int	cmd_index;		/* *MUST* be unsigned */
    464	struct sk_buff *skb;
    465	struct nlmsghdr *nlh;
    466	struct nlattr *nla;
    467#ifdef CONFIG_COMPAT
    468	struct __compat_iw_event *compat_event;
    469	struct compat_iw_point compat_wrqu;
    470	struct sk_buff *compskb;
    471#endif
    472
    473	/*
    474	 * Nothing in the kernel sends scan events with data, be safe.
    475	 * This is necessary because we cannot fix up scan event data
    476	 * for compat, due to being contained in 'extra', but normally
    477	 * applications are required to retrieve the scan data anyway
    478	 * and no data is included in the event, this codifies that
    479	 * practice.
    480	 */
    481	if (WARN_ON(cmd == SIOCGIWSCAN && extra))
    482		extra = NULL;
    483
    484	/* Get the description of the Event */
    485	if (cmd <= SIOCIWLAST) {
    486		cmd_index = IW_IOCTL_IDX(cmd);
    487		if (cmd_index < standard_ioctl_num)
    488			descr = &(standard_ioctl[cmd_index]);
    489	} else {
    490		cmd_index = IW_EVENT_IDX(cmd);
    491		if (cmd_index < standard_event_num)
    492			descr = &(standard_event[cmd_index]);
    493	}
    494	/* Don't accept unknown events */
    495	if (descr == NULL) {
    496		/* Note : we don't return an error to the driver, because
    497		 * the driver would not know what to do about it. It can't
    498		 * return an error to the user, because the event is not
    499		 * initiated by a user request.
    500		 * The best the driver could do is to log an error message.
    501		 * We will do it ourselves instead...
    502		 */
    503		netdev_err(dev, "(WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
    504			   cmd);
    505		return;
    506	}
    507
    508	/* Check extra parameters and set extra_len */
    509	if (descr->header_type == IW_HEADER_TYPE_POINT) {
    510		/* Check if number of token fits within bounds */
    511		if (wrqu->data.length > descr->max_tokens) {
    512			netdev_err(dev, "(WE) : Wireless Event (cmd=0x%04X) too big (%d)\n",
    513				   cmd, wrqu->data.length);
    514			return;
    515		}
    516		if (wrqu->data.length < descr->min_tokens) {
    517			netdev_err(dev, "(WE) : Wireless Event (cmd=0x%04X) too small (%d)\n",
    518				   cmd, wrqu->data.length);
    519			return;
    520		}
    521		/* Calculate extra_len - extra is NULL for restricted events */
    522		if (extra != NULL)
    523			extra_len = wrqu->data.length * descr->token_size;
    524		/* Always at an offset in wrqu */
    525		wrqu_off = IW_EV_POINT_OFF;
    526	}
    527
    528	/* Total length of the event */
    529	hdr_len = event_type_size[descr->header_type];
    530	event_len = hdr_len + extra_len;
    531
    532	/*
    533	 * The problem for 64/32 bit.
    534	 *
    535	 * On 64-bit, a regular event is laid out as follows:
    536	 *      |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |
    537	 *      | event.len | event.cmd |     p a d d i n g     |
    538	 *      | wrqu data ... (with the correct size)         |
    539	 *
    540	 * This padding exists because we manipulate event->u,
    541	 * and 'event' is not packed.
    542	 *
    543	 * An iw_point event is laid out like this instead:
    544	 *      |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |
    545	 *      | event.len | event.cmd |     p a d d i n g     |
    546	 *      | iwpnt.len | iwpnt.flg |     p a d d i n g     |
    547	 *      | extra data  ...
    548	 *
    549	 * The second padding exists because struct iw_point is extended,
    550	 * but this depends on the platform...
    551	 *
    552	 * On 32-bit, all the padding shouldn't be there.
    553	 */
    554
    555	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
    556	if (!skb)
    557		return;
    558
    559	/* Send via the RtNetlink event channel */
    560	nlh = rtnetlink_ifinfo_prep(dev, skb);
    561	if (WARN_ON(!nlh)) {
    562		kfree_skb(skb);
    563		return;
    564	}
    565
    566	/* Add the wireless events in the netlink packet */
    567	nla = nla_reserve(skb, IFLA_WIRELESS, event_len);
    568	if (!nla) {
    569		kfree_skb(skb);
    570		return;
    571	}
    572	event = nla_data(nla);
    573
    574	/* Fill event - first clear to avoid data leaking */
    575	memset(event, 0, hdr_len);
    576	event->len = event_len;
    577	event->cmd = cmd;
    578	memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
    579	if (extra_len)
    580		memcpy(((char *) event) + hdr_len, extra, extra_len);
    581
    582	nlmsg_end(skb, nlh);
    583#ifdef CONFIG_COMPAT
    584	hdr_len = compat_event_type_size[descr->header_type];
    585	event_len = hdr_len + extra_len;
    586
    587	compskb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
    588	if (!compskb) {
    589		kfree_skb(skb);
    590		return;
    591	}
    592
    593	/* Send via the RtNetlink event channel */
    594	nlh = rtnetlink_ifinfo_prep(dev, compskb);
    595	if (WARN_ON(!nlh)) {
    596		kfree_skb(skb);
    597		kfree_skb(compskb);
    598		return;
    599	}
    600
    601	/* Add the wireless events in the netlink packet */
    602	nla = nla_reserve(compskb, IFLA_WIRELESS, event_len);
    603	if (!nla) {
    604		kfree_skb(skb);
    605		kfree_skb(compskb);
    606		return;
    607	}
    608	compat_event = nla_data(nla);
    609
    610	compat_event->len = event_len;
    611	compat_event->cmd = cmd;
    612	if (descr->header_type == IW_HEADER_TYPE_POINT) {
    613		compat_wrqu.length = wrqu->data.length;
    614		compat_wrqu.flags = wrqu->data.flags;
    615		memcpy(&compat_event->pointer,
    616			((char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF,
    617			hdr_len - IW_EV_COMPAT_LCP_LEN);
    618		if (extra_len)
    619			memcpy(((char *) compat_event) + hdr_len,
    620				extra, extra_len);
    621	} else {
    622		/* extra_len must be zero, so no if (extra) needed */
    623		memcpy(&compat_event->pointer, wrqu,
    624			hdr_len - IW_EV_COMPAT_LCP_LEN);
    625	}
    626
    627	nlmsg_end(compskb, nlh);
    628
    629	skb_shinfo(skb)->frag_list = compskb;
    630#endif
    631	skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
    632	schedule_work(&wireless_nlevent_work);
    633}
    634EXPORT_SYMBOL(wireless_send_event);
    635
    636
    637
    638/* IW handlers */
    639
    640struct iw_statistics *get_wireless_stats(struct net_device *dev)
    641{
    642#ifdef CONFIG_WIRELESS_EXT
    643	if ((dev->wireless_handlers != NULL) &&
    644	   (dev->wireless_handlers->get_wireless_stats != NULL))
    645		return dev->wireless_handlers->get_wireless_stats(dev);
    646#endif
    647
    648#ifdef CONFIG_CFG80211_WEXT
    649	if (dev->ieee80211_ptr &&
    650	    dev->ieee80211_ptr->wiphy &&
    651	    dev->ieee80211_ptr->wiphy->wext &&
    652	    dev->ieee80211_ptr->wiphy->wext->get_wireless_stats)
    653		return dev->ieee80211_ptr->wiphy->wext->get_wireless_stats(dev);
    654#endif
    655
    656	/* not found */
    657	return NULL;
    658}
    659
    660/* noinline to avoid a bogus warning with -O3 */
    661static noinline int iw_handler_get_iwstats(struct net_device *	dev,
    662				  struct iw_request_info *	info,
    663				  union iwreq_data *		wrqu,
    664				  char *			extra)
    665{
    666	/* Get stats from the driver */
    667	struct iw_statistics *stats;
    668
    669	stats = get_wireless_stats(dev);
    670	if (stats) {
    671		/* Copy statistics to extra */
    672		memcpy(extra, stats, sizeof(struct iw_statistics));
    673		wrqu->data.length = sizeof(struct iw_statistics);
    674
    675		/* Check if we need to clear the updated flag */
    676		if (wrqu->data.flags != 0)
    677			stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
    678		return 0;
    679	} else
    680		return -EOPNOTSUPP;
    681}
    682
    683static iw_handler get_handler(struct net_device *dev, unsigned int cmd)
    684{
    685	/* Don't "optimise" the following variable, it will crash */
    686	unsigned int	index;		/* *MUST* be unsigned */
    687	const struct iw_handler_def *handlers = NULL;
    688
    689#ifdef CONFIG_CFG80211_WEXT
    690	if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy)
    691		handlers = dev->ieee80211_ptr->wiphy->wext;
    692#endif
    693#ifdef CONFIG_WIRELESS_EXT
    694	if (dev->wireless_handlers)
    695		handlers = dev->wireless_handlers;
    696#endif
    697
    698	if (!handlers)
    699		return NULL;
    700
    701	/* Try as a standard command */
    702	index = IW_IOCTL_IDX(cmd);
    703	if (index < handlers->num_standard)
    704		return handlers->standard[index];
    705
    706#ifdef CONFIG_WEXT_PRIV
    707	/* Try as a private command */
    708	index = cmd - SIOCIWFIRSTPRIV;
    709	if (index < handlers->num_private)
    710		return handlers->private[index];
    711#endif
    712
    713	/* Not found */
    714	return NULL;
    715}
    716
    717static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
    718				   const struct iw_ioctl_description *descr,
    719				   iw_handler handler, struct net_device *dev,
    720				   struct iw_request_info *info)
    721{
    722	int err, extra_size, user_length = 0, essid_compat = 0;
    723	char *extra;
    724
    725	/* Calculate space needed by arguments. Always allocate
    726	 * for max space.
    727	 */
    728	extra_size = descr->max_tokens * descr->token_size;
    729
    730	/* Check need for ESSID compatibility for WE < 21 */
    731	switch (cmd) {
    732	case SIOCSIWESSID:
    733	case SIOCGIWESSID:
    734	case SIOCSIWNICKN:
    735	case SIOCGIWNICKN:
    736		if (iwp->length == descr->max_tokens + 1)
    737			essid_compat = 1;
    738		else if (IW_IS_SET(cmd) && (iwp->length != 0)) {
    739			char essid[IW_ESSID_MAX_SIZE + 1];
    740			unsigned int len;
    741			len = iwp->length * descr->token_size;
    742
    743			if (len > IW_ESSID_MAX_SIZE)
    744				return -EFAULT;
    745
    746			err = copy_from_user(essid, iwp->pointer, len);
    747			if (err)
    748				return -EFAULT;
    749
    750			if (essid[iwp->length - 1] == '\0')
    751				essid_compat = 1;
    752		}
    753		break;
    754	default:
    755		break;
    756	}
    757
    758	iwp->length -= essid_compat;
    759
    760	/* Check what user space is giving us */
    761	if (IW_IS_SET(cmd)) {
    762		/* Check NULL pointer */
    763		if (!iwp->pointer && iwp->length != 0)
    764			return -EFAULT;
    765		/* Check if number of token fits within bounds */
    766		if (iwp->length > descr->max_tokens)
    767			return -E2BIG;
    768		if (iwp->length < descr->min_tokens)
    769			return -EINVAL;
    770	} else {
    771		/* Check NULL pointer */
    772		if (!iwp->pointer)
    773			return -EFAULT;
    774		/* Save user space buffer size for checking */
    775		user_length = iwp->length;
    776
    777		/* Don't check if user_length > max to allow forward
    778		 * compatibility. The test user_length < min is
    779		 * implied by the test at the end.
    780		 */
    781
    782		/* Support for very large requests */
    783		if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
    784		    (user_length > descr->max_tokens)) {
    785			/* Allow userspace to GET more than max so
    786			 * we can support any size GET requests.
    787			 * There is still a limit : -ENOMEM.
    788			 */
    789			extra_size = user_length * descr->token_size;
    790
    791			/* Note : user_length is originally a __u16,
    792			 * and token_size is controlled by us,
    793			 * so extra_size won't get negative and
    794			 * won't overflow...
    795			 */
    796		}
    797	}
    798
    799	/* kzalloc() ensures NULL-termination for essid_compat. */
    800	extra = kzalloc(extra_size, GFP_KERNEL);
    801	if (!extra)
    802		return -ENOMEM;
    803
    804	/* If it is a SET, get all the extra data in here */
    805	if (IW_IS_SET(cmd) && (iwp->length != 0)) {
    806		if (copy_from_user(extra, iwp->pointer,
    807				   iwp->length *
    808				   descr->token_size)) {
    809			err = -EFAULT;
    810			goto out;
    811		}
    812
    813		if (cmd == SIOCSIWENCODEEXT) {
    814			struct iw_encode_ext *ee = (void *) extra;
    815
    816			if (iwp->length < sizeof(*ee) + ee->key_len) {
    817				err = -EFAULT;
    818				goto out;
    819			}
    820		}
    821	}
    822
    823	if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) {
    824		/*
    825		 * If this is a GET, but not NOMAX, it means that the extra
    826		 * data is not bounded by userspace, but by max_tokens. Thus
    827		 * set the length to max_tokens. This matches the extra data
    828		 * allocation.
    829		 * The driver should fill it with the number of tokens it
    830		 * provided, and it may check iwp->length rather than having
    831		 * knowledge of max_tokens. If the driver doesn't change the
    832		 * iwp->length, this ioctl just copies back max_token tokens
    833		 * filled with zeroes. Hopefully the driver isn't claiming
    834		 * them to be valid data.
    835		 */
    836		iwp->length = descr->max_tokens;
    837	}
    838
    839	err = handler(dev, info, (union iwreq_data *) iwp, extra);
    840
    841	iwp->length += essid_compat;
    842
    843	/* If we have something to return to the user */
    844	if (!err && IW_IS_GET(cmd)) {
    845		/* Check if there is enough buffer up there */
    846		if (user_length < iwp->length) {
    847			err = -E2BIG;
    848			goto out;
    849		}
    850
    851		if (copy_to_user(iwp->pointer, extra,
    852				 iwp->length *
    853				 descr->token_size)) {
    854			err = -EFAULT;
    855			goto out;
    856		}
    857	}
    858
    859	/* Generate an event to notify listeners of the change */
    860	if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
    861	    ((err == 0) || (err == -EIWCOMMIT))) {
    862		union iwreq_data *data = (union iwreq_data *) iwp;
    863
    864		if (descr->flags & IW_DESCR_FLAG_RESTRICT)
    865			/* If the event is restricted, don't
    866			 * export the payload.
    867			 */
    868			wireless_send_event(dev, cmd, data, NULL);
    869		else
    870			wireless_send_event(dev, cmd, data, extra);
    871	}
    872
    873out:
    874	kfree(extra);
    875	return err;
    876}
    877
    878/*
    879 * Call the commit handler in the driver
    880 * (if exist and if conditions are right)
    881 *
    882 * Note : our current commit strategy is currently pretty dumb,
    883 * but we will be able to improve on that...
    884 * The goal is to try to agreagate as many changes as possible
    885 * before doing the commit. Drivers that will define a commit handler
    886 * are usually those that need a reset after changing parameters, so
    887 * we want to minimise the number of reset.
    888 * A cool idea is to use a timer : at each "set" command, we re-set the
    889 * timer, when the timer eventually fires, we call the driver.
    890 * Hopefully, more on that later.
    891 *
    892 * Also, I'm waiting to see how many people will complain about the
    893 * netif_running(dev) test. I'm open on that one...
    894 * Hopefully, the driver will remember to do a commit in "open()" ;-)
    895 */
    896int call_commit_handler(struct net_device *dev)
    897{
    898#ifdef CONFIG_WIRELESS_EXT
    899	if (netif_running(dev) &&
    900	    dev->wireless_handlers &&
    901	    dev->wireless_handlers->standard[0])
    902		/* Call the commit handler on the driver */
    903		return dev->wireless_handlers->standard[0](dev, NULL,
    904							   NULL, NULL);
    905	else
    906		return 0;		/* Command completed successfully */
    907#else
    908	/* cfg80211 has no commit */
    909	return 0;
    910#endif
    911}
    912
    913/*
    914 * Main IOCTl dispatcher.
    915 * Check the type of IOCTL and call the appropriate wrapper...
    916 */
    917static int wireless_process_ioctl(struct net *net, struct iwreq *iwr,
    918				  unsigned int cmd,
    919				  struct iw_request_info *info,
    920				  wext_ioctl_func standard,
    921				  wext_ioctl_func private)
    922{
    923	struct net_device *dev;
    924	iw_handler	handler;
    925
    926	/* Permissions are already checked in dev_ioctl() before calling us.
    927	 * The copy_to/from_user() of ifr is also dealt with in there */
    928
    929	/* Make sure the device exist */
    930	if ((dev = __dev_get_by_name(net, iwr->ifr_name)) == NULL)
    931		return -ENODEV;
    932
    933	/* A bunch of special cases, then the generic case...
    934	 * Note that 'cmd' is already filtered in dev_ioctl() with
    935	 * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
    936	if (cmd == SIOCGIWSTATS)
    937		return standard(dev, iwr, cmd, info,
    938				&iw_handler_get_iwstats);
    939
    940#ifdef CONFIG_WEXT_PRIV
    941	if (cmd == SIOCGIWPRIV && dev->wireless_handlers)
    942		return standard(dev, iwr, cmd, info,
    943				iw_handler_get_private);
    944#endif
    945
    946	/* Basic check */
    947	if (!netif_device_present(dev))
    948		return -ENODEV;
    949
    950	/* New driver API : try to find the handler */
    951	handler = get_handler(dev, cmd);
    952	if (handler) {
    953		/* Standard and private are not the same */
    954		if (cmd < SIOCIWFIRSTPRIV)
    955			return standard(dev, iwr, cmd, info, handler);
    956		else if (private)
    957			return private(dev, iwr, cmd, info, handler);
    958	}
    959	return -EOPNOTSUPP;
    960}
    961
    962/* If command is `set a parameter', or `get the encoding parameters',
    963 * check if the user has the right to do it.
    964 */
    965static int wext_permission_check(unsigned int cmd)
    966{
    967	if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE ||
    968	     cmd == SIOCGIWENCODEEXT) &&
    969	    !capable(CAP_NET_ADMIN))
    970		return -EPERM;
    971
    972	return 0;
    973}
    974
    975/* entry point from dev ioctl */
    976static int wext_ioctl_dispatch(struct net *net, struct iwreq *iwr,
    977			       unsigned int cmd, struct iw_request_info *info,
    978			       wext_ioctl_func standard,
    979			       wext_ioctl_func private)
    980{
    981	int ret = wext_permission_check(cmd);
    982
    983	if (ret)
    984		return ret;
    985
    986	dev_load(net, iwr->ifr_name);
    987	rtnl_lock();
    988	ret = wireless_process_ioctl(net, iwr, cmd, info, standard, private);
    989	rtnl_unlock();
    990
    991	return ret;
    992}
    993
    994/*
    995 * Wrapper to call a standard Wireless Extension handler.
    996 * We do various checks and also take care of moving data between
    997 * user space and kernel space.
    998 */
    999static int ioctl_standard_call(struct net_device *	dev,
   1000			       struct iwreq		*iwr,
   1001			       unsigned int		cmd,
   1002			       struct iw_request_info	*info,
   1003			       iw_handler		handler)
   1004{
   1005	const struct iw_ioctl_description *	descr;
   1006	int					ret = -EINVAL;
   1007
   1008	/* Get the description of the IOCTL */
   1009	if (IW_IOCTL_IDX(cmd) >= standard_ioctl_num)
   1010		return -EOPNOTSUPP;
   1011	descr = &(standard_ioctl[IW_IOCTL_IDX(cmd)]);
   1012
   1013	/* Check if we have a pointer to user space data or not */
   1014	if (descr->header_type != IW_HEADER_TYPE_POINT) {
   1015
   1016		/* No extra arguments. Trivial to handle */
   1017		ret = handler(dev, info, &(iwr->u), NULL);
   1018
   1019		/* Generate an event to notify listeners of the change */
   1020		if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
   1021		   ((ret == 0) || (ret == -EIWCOMMIT)))
   1022			wireless_send_event(dev, cmd, &(iwr->u), NULL);
   1023	} else {
   1024		ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr,
   1025					      handler, dev, info);
   1026	}
   1027
   1028	/* Call commit handler if needed and defined */
   1029	if (ret == -EIWCOMMIT)
   1030		ret = call_commit_handler(dev);
   1031
   1032	/* Here, we will generate the appropriate event if needed */
   1033
   1034	return ret;
   1035}
   1036
   1037
   1038int wext_handle_ioctl(struct net *net, unsigned int cmd, void __user *arg)
   1039{
   1040	struct iw_request_info info = { .cmd = cmd, .flags = 0 };
   1041	struct iwreq iwr;
   1042	int ret;
   1043
   1044	if (copy_from_user(&iwr, arg, sizeof(iwr)))
   1045		return -EFAULT;
   1046
   1047	iwr.ifr_name[sizeof(iwr.ifr_name) - 1] = 0;
   1048
   1049	ret = wext_ioctl_dispatch(net, &iwr, cmd, &info,
   1050				  ioctl_standard_call,
   1051				  ioctl_private_call);
   1052	if (ret >= 0 &&
   1053	    IW_IS_GET(cmd) &&
   1054	    copy_to_user(arg, &iwr, sizeof(struct iwreq)))
   1055		return -EFAULT;
   1056
   1057	return ret;
   1058}
   1059
   1060#ifdef CONFIG_COMPAT
   1061static int compat_standard_call(struct net_device	*dev,
   1062				struct iwreq		*iwr,
   1063				unsigned int		cmd,
   1064				struct iw_request_info	*info,
   1065				iw_handler		handler)
   1066{
   1067	const struct iw_ioctl_description *descr;
   1068	struct compat_iw_point *iwp_compat;
   1069	struct iw_point iwp;
   1070	int err;
   1071
   1072	descr = standard_ioctl + IW_IOCTL_IDX(cmd);
   1073
   1074	if (descr->header_type != IW_HEADER_TYPE_POINT)
   1075		return ioctl_standard_call(dev, iwr, cmd, info, handler);
   1076
   1077	iwp_compat = (struct compat_iw_point *) &iwr->u.data;
   1078	iwp.pointer = compat_ptr(iwp_compat->pointer);
   1079	iwp.length = iwp_compat->length;
   1080	iwp.flags = iwp_compat->flags;
   1081
   1082	err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, info);
   1083
   1084	iwp_compat->pointer = ptr_to_compat(iwp.pointer);
   1085	iwp_compat->length = iwp.length;
   1086	iwp_compat->flags = iwp.flags;
   1087
   1088	return err;
   1089}
   1090
   1091int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
   1092			     unsigned long arg)
   1093{
   1094	void __user *argp = (void __user *)arg;
   1095	struct iw_request_info info;
   1096	struct iwreq iwr;
   1097	char *colon;
   1098	int ret;
   1099
   1100	if (copy_from_user(&iwr, argp, sizeof(struct iwreq)))
   1101		return -EFAULT;
   1102
   1103	iwr.ifr_name[IFNAMSIZ-1] = 0;
   1104	colon = strchr(iwr.ifr_name, ':');
   1105	if (colon)
   1106		*colon = 0;
   1107
   1108	info.cmd = cmd;
   1109	info.flags = IW_REQUEST_FLAG_COMPAT;
   1110
   1111	ret = wext_ioctl_dispatch(net, &iwr, cmd, &info,
   1112				  compat_standard_call,
   1113				  compat_private_call);
   1114
   1115	if (ret >= 0 &&
   1116	    IW_IS_GET(cmd) &&
   1117	    copy_to_user(argp, &iwr, sizeof(struct iwreq)))
   1118		return -EFAULT;
   1119
   1120	return ret;
   1121}
   1122#endif
   1123
   1124char *iwe_stream_add_event(struct iw_request_info *info, char *stream,
   1125			   char *ends, struct iw_event *iwe, int event_len)
   1126{
   1127	int lcp_len = iwe_stream_lcp_len(info);
   1128
   1129	event_len = iwe_stream_event_len_adjust(info, event_len);
   1130
   1131	/* Check if it's possible */
   1132	if (likely((stream + event_len) < ends)) {
   1133		iwe->len = event_len;
   1134		/* Beware of alignement issues on 64 bits */
   1135		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
   1136		memcpy(stream + lcp_len, &iwe->u,
   1137		       event_len - lcp_len);
   1138		stream += event_len;
   1139	}
   1140
   1141	return stream;
   1142}
   1143EXPORT_SYMBOL(iwe_stream_add_event);
   1144
   1145char *iwe_stream_add_point(struct iw_request_info *info, char *stream,
   1146			   char *ends, struct iw_event *iwe, char *extra)
   1147{
   1148	int event_len = iwe_stream_point_len(info) + iwe->u.data.length;
   1149	int point_len = iwe_stream_point_len(info);
   1150	int lcp_len   = iwe_stream_lcp_len(info);
   1151
   1152	/* Check if it's possible */
   1153	if (likely((stream + event_len) < ends)) {
   1154		iwe->len = event_len;
   1155		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
   1156		memcpy(stream + lcp_len,
   1157		       ((char *) &iwe->u) + IW_EV_POINT_OFF,
   1158		       IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
   1159		if (iwe->u.data.length && extra)
   1160			memcpy(stream + point_len, extra, iwe->u.data.length);
   1161		stream += event_len;
   1162	}
   1163
   1164	return stream;
   1165}
   1166EXPORT_SYMBOL(iwe_stream_add_point);
   1167
   1168char *iwe_stream_add_value(struct iw_request_info *info, char *event,
   1169			   char *value, char *ends, struct iw_event *iwe,
   1170			   int event_len)
   1171{
   1172	int lcp_len = iwe_stream_lcp_len(info);
   1173
   1174	/* Don't duplicate LCP */
   1175	event_len -= IW_EV_LCP_LEN;
   1176
   1177	/* Check if it's possible */
   1178	if (likely((value + event_len) < ends)) {
   1179		/* Add new value */
   1180		memcpy(value, &iwe->u, event_len);
   1181		value += event_len;
   1182		/* Patch LCP */
   1183		iwe->len = value - event;
   1184		memcpy(event, (char *) iwe, lcp_len);
   1185	}
   1186
   1187	return value;
   1188}
   1189EXPORT_SYMBOL(iwe_stream_add_value);