⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wireless.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * This file implement the Wireless Extensions APIs. * * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com> * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved. * * (As all part of the Linux kernel, this file is GPL) *//************************** DOCUMENTATION **************************//* * API definition : * -------------- * See <linux/wireless.h> for details of the APIs and the rest. * * History : * ------- * * v1 - 5.12.01 - Jean II *	o Created this file. * * v2 - 13.12.01 - Jean II *	o Move /proc/net/wireless stuff from net/core/dev.c to here *	o Make Wireless Extension IOCTLs go through here *	o Added iw_handler handling ;-) *	o Added standard ioctl description *	o Initial dumb commit strategy based on orinoco.c * * v3 - 19.12.01 - Jean II *	o Make sure we don't go out of standard_ioctl[] in ioctl_standard_call *	o Add event dispatcher function *	o Add event description *	o Propagate events as rtnetlink IFLA_WIRELESS option *	o Generate event on selected SET requests * * v4 - 18.04.02 - Jean II *	o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1 * * v5 - 21.06.02 - Jean II *	o Add IW_PRIV_TYPE_ADDR in priv_type_size (+cleanup) *	o Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes *	o Add IWEVCUSTOM for driver specific event/scanning token *	o Turn on WE_STRICT_WRITE by default + kernel warning *	o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num) *	o Fix off-by-one in test (extra_size <= IFNAMSIZ) * * v6 - 9.01.03 - Jean II *	o Add common spy support : iw_handler_set_spy(), wireless_spy_update() *	o Add enhanced spy support : iw_handler_set_thrspy() and event. *	o Add WIRELESS_EXT version display in /proc/net/wireless *//***************************** INCLUDES *****************************/#include <linux/config.h>		/* Not needed ??? */#include <linux/module.h>#include <linux/types.h>		/* off_t */#include <linux/netdevice.h>		/* struct ifreq, dev_get_by_name() */#include <linux/proc_fs.h>#include <linux/rtnetlink.h>		/* rtnetlink stuff */#include <linux/seq_file.h>#include <linux/init.h>			/* for __init */#include <linux/if_arp.h>		/* ARPHRD_ETHER */#include <linux/wireless.h>		/* Pretty obvious */#include <net/iw_handler.h>		/* New driver API */#include <asm/uaccess.h>		/* copy_to_user() *//**************************** CONSTANTS ****************************//* Enough lenience, let's make sure things are proper... */#define WE_STRICT_WRITE		/* Check write buffer size *//* I'll probably drop both the define and kernel message in the next version *//* Debugging stuff */#undef WE_IOCTL_DEBUG		/* Debug IOCTL API */#undef WE_EVENT_DEBUG		/* Debug Event dispatcher */#undef WE_SPY_DEBUG		/* Debug enhanced spy support *//* Options */#define WE_EVENT_NETLINK	/* Propagate events using rtnetlink */#define WE_SET_EVENT		/* Generate an event on some set commands *//************************* GLOBAL VARIABLES *************************//* * You should not use global variables, because of re-entrancy. * On our case, it's only const, so it's OK... *//* * Meta-data about all the standard Wireless Extension request we * know about. */static const struct iw_ioctl_description standard_ioctl[] = {	[SIOCSIWCOMMIT	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_NULL,	},	[SIOCGIWNAME	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_CHAR,		.flags		= IW_DESCR_FLAG_DUMP,	},	[SIOCSIWNWID	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,		.flags		= IW_DESCR_FLAG_EVENT,	},	[SIOCGIWNWID	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,		.flags		= IW_DESCR_FLAG_DUMP,	},	[SIOCSIWFREQ	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_FREQ,		.flags		= IW_DESCR_FLAG_EVENT,	},	[SIOCGIWFREQ	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_FREQ,		.flags		= IW_DESCR_FLAG_DUMP,	},	[SIOCSIWMODE	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_UINT,		.flags		= IW_DESCR_FLAG_EVENT,	},	[SIOCGIWMODE	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_UINT,		.flags		= IW_DESCR_FLAG_DUMP,	},	[SIOCSIWSENS	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCGIWSENS	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCSIWRANGE	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_NULL,	},	[SIOCGIWRANGE	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= 1,		.max_tokens	= sizeof(struct iw_range),		.flags		= IW_DESCR_FLAG_DUMP,	},	[SIOCSIWPRIV	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_NULL,	},	[SIOCGIWPRIV	- SIOCIWFIRST] = { /* (handled directly by us) */		.header_type	= IW_HEADER_TYPE_NULL,	},	[SIOCSIWSTATS	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_NULL,	},	[SIOCGIWSTATS	- SIOCIWFIRST] = { /* (handled directly by us) */		.header_type	= IW_HEADER_TYPE_NULL,		.flags		= IW_DESCR_FLAG_DUMP,	},	[SIOCSIWSPY	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= sizeof(struct sockaddr),		.max_tokens	= IW_MAX_SPY,	},	[SIOCGIWSPY	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= sizeof(struct sockaddr) +				  sizeof(struct iw_quality),		.max_tokens	= IW_MAX_SPY,	},	[SIOCSIWTHRSPY	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= sizeof(struct iw_thrspy),		.min_tokens	= 1,		.max_tokens	= 1,	},	[SIOCGIWTHRSPY	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= sizeof(struct iw_thrspy),		.min_tokens	= 1,		.max_tokens	= 1,	},	[SIOCSIWAP	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_ADDR,	},	[SIOCGIWAP	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_ADDR,		.flags		= IW_DESCR_FLAG_DUMP,	},	[SIOCGIWAPLIST	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= sizeof(struct sockaddr) +				  sizeof(struct iw_quality),		.max_tokens	= IW_MAX_AP,	},	[SIOCSIWSCAN	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCGIWSCAN	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= 1,		.max_tokens	= IW_SCAN_MAX_DATA,	},	[SIOCSIWESSID	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= 1,		.max_tokens	= IW_ESSID_MAX_SIZE + 1,		.flags		= IW_DESCR_FLAG_EVENT,	},	[SIOCGIWESSID	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= 1,		.max_tokens	= IW_ESSID_MAX_SIZE + 1,		.flags		= IW_DESCR_FLAG_DUMP,	},	[SIOCSIWNICKN	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= 1,		.max_tokens	= IW_ESSID_MAX_SIZE + 1,	},	[SIOCGIWNICKN	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= 1,		.max_tokens	= IW_ESSID_MAX_SIZE + 1,	},	[SIOCSIWRATE	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCGIWRATE	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCSIWRTS	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCGIWRTS	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCSIWFRAG	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCGIWFRAG	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCSIWTXPOW	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCGIWTXPOW	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCSIWRETRY	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCGIWRETRY	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCSIWENCODE	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= 1,		.max_tokens	= IW_ENCODING_TOKEN_MAX,		.flags		= IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,	},	[SIOCGIWENCODE	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= 1,		.max_tokens	= IW_ENCODING_TOKEN_MAX,		.flags		= IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,	},	[SIOCSIWPOWER	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},	[SIOCGIWPOWER	- SIOCIWFIRST] = {		.header_type	= IW_HEADER_TYPE_PARAM,	},};static const int standard_ioctl_num = (sizeof(standard_ioctl) /				       sizeof(struct iw_ioctl_description));/* * Meta-data about all the additional standard Wireless Extension events * we know about. */static const struct iw_ioctl_description standard_event[] = {	[IWEVTXDROP	- IWEVFIRST] = {		.header_type	= IW_HEADER_TYPE_ADDR,	},	[IWEVQUAL	- IWEVFIRST] = {		.header_type	= IW_HEADER_TYPE_QUAL,	},	[IWEVCUSTOM	- IWEVFIRST] = {		.header_type	= IW_HEADER_TYPE_POINT,		.token_size	= 1,		.max_tokens	= IW_CUSTOM_MAX,	},	[IWEVREGISTERED	- IWEVFIRST] = {		.header_type	= IW_HEADER_TYPE_ADDR,	},	[IWEVEXPIRED	- IWEVFIRST] = {		.header_type	= IW_HEADER_TYPE_ADDR, 	},};static const int standard_event_num = (sizeof(standard_event) /				       sizeof(struct iw_ioctl_description));/* Size (in bytes) of the various private data types */static const char priv_type_size[] = {	0,				/* IW_PRIV_TYPE_NONE */	1,				/* IW_PRIV_TYPE_BYTE */	1,				/* IW_PRIV_TYPE_CHAR */	0,				/* Not defined */	sizeof(__u32),			/* IW_PRIV_TYPE_INT */	sizeof(struct iw_freq),		/* IW_PRIV_TYPE_FLOAT */	sizeof(struct sockaddr),	/* IW_PRIV_TYPE_ADDR */	0,				/* Not defined */};/* Size (in bytes) of various events */static const int event_type_size[] = {	IW_EV_LCP_LEN,			/* IW_HEADER_TYPE_NULL */	0,	IW_EV_CHAR_LEN,			/* IW_HEADER_TYPE_CHAR */	0,	IW_EV_UINT_LEN,			/* IW_HEADER_TYPE_UINT */	IW_EV_FREQ_LEN,			/* IW_HEADER_TYPE_FREQ */	IW_EV_ADDR_LEN,			/* IW_HEADER_TYPE_ADDR */	0,	IW_EV_POINT_LEN,		/* Without variable payload */	IW_EV_PARAM_LEN,		/* IW_HEADER_TYPE_PARAM */	IW_EV_QUAL_LEN,			/* IW_HEADER_TYPE_QUAL */};/************************ COMMON SUBROUTINES ************************//* * Stuff that may be used in various place or doesn't fit in one * of the section below. *//* ---------------------------------------------------------------- *//* * Return the driver handler associated with a specific Wireless Extension. * Called from various place, so make sure it remains efficient. */static inline iw_handler get_handler(struct net_device *dev,				     unsigned int cmd){	/* Don't "optimise" the following variable, it will crash */	unsigned int	index;		/* *MUST* be unsigned */	/* Check if we have some wireless handlers defined */	if(dev->wireless_handlers == NULL)		return NULL;	/* Try as a standard command */	index = cmd - SIOCIWFIRST;	if(index < dev->wireless_handlers->num_standard)		return dev->wireless_handlers->standard[index];	/* Try as a private command */	index = cmd - SIOCIWFIRSTPRIV;	if(index < dev->wireless_handlers->num_private)		return dev->wireless_handlers->private[index];	/* Not found */	return NULL;}/* ---------------------------------------------------------------- *//* * Get statistics out of the driver */static inline struct iw_statistics *get_wireless_stats(struct net_device *dev){	return (dev->get_wireless_stats ?		dev->get_wireless_stats(dev) :		(struct iw_statistics *) NULL);	/* In the future, get_wireless_stats may move from 'struct net_device'	 * to 'struct iw_handler_def', to de-bloat struct net_device.	 * Definitely worse a thought... */}/* ---------------------------------------------------------------- *//* * Call the commit handler in the driver * (if exist and if conditions are right) * * Note : our current commit strategy is currently pretty dumb, * but we will be able to improve on that... * The goal is to try to agreagate as many changes as possible * before doing the commit. Drivers that will define a commit handler * are usually those that need a reset after changing parameters, so * we want to minimise the number of reset. * A cool idea is to use a timer : at each "set" command, we re-set the * timer, when the timer eventually fires, we call the driver. * Hopefully, more on that later. * * Also, I'm waiting to see how many people will complain about the * netif_running(dev) test. I'm open on that one... * Hopefully, the driver will remember to do a commit in "open()" ;-) */static inline int call_commit_handler(struct net_device *	dev){	if((netif_running(dev)) &&	   (dev->wireless_handlers->standard[0] != NULL)) {		/* Call the commit handler on the driver */		return dev->wireless_handlers->standard[0](dev, NULL,							   NULL, NULL);	} else		return 0;		/* Command completed successfully */}/* ---------------------------------------------------------------- *//* * Number of private arguments */static inline int get_priv_size(__u16	args){	int	num = args & IW_PRIV_SIZE_MASK;	int	type = (args & IW_PRIV_TYPE_MASK) >> 12;	return num * priv_type_size[type];}/******************** /proc/net/wireless SUPPORT ********************//* * The /proc/net/wireless file is a human readable user-space interface * exporting various wireless specific statistics from the wireless devices. * This is the most popular part of the Wireless Extensions ;-) * * This interface is a pure clone of /proc/net/dev (in net/core/dev.c). * The content of the file is basically the content of "struct iw_statistics". */#ifdef CONFIG_PROC_FS/* ---------------------------------------------------------------- *//* * Print one entry (line) of /proc/net/wireless */static __inline__ void wireless_seq_printf_stats(struct seq_file *seq,						 struct net_device *dev){	/* Get stats from the driver */	struct iw_statistics *stats = get_wireless_stats(dev);	if (stats) {		seq_printf(seq, "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d "				"%6d %6d   %6d\n",			   dev->name, stats->status, stats->qual.qual,			   stats->qual.updated & 1 ? '.' : ' ',			   ((__u8) stats->qual.level),			   stats->qual.updated & 2 ? '.' : ' ',			   ((__u8) stats->qual.noise),			   stats->qual.updated & 4 ? '.' : ' ',			   stats->discard.nwid, stats->discard.code,			   stats->discard.fragment, stats->discard.retries,			   stats->discard.misc, stats->miss.beacon);		stats->qual.updated = 0;	}}/* ---------------------------------------------------------------- *//* * Print info for /proc/net/wireless (print all entries) */static int wireless_seq_show(struct seq_file *seq, void *v)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -