[PATCH] WE-20 for kernel 2.6.16

This is version 20 of the Wireless Extensions. This is the
completion of the RtNetlink work I started early 2004, it enables the
full Wireless Extension API over RtNetlink.

	Few comments on the patch :
	o totally driver transparent, no change in drivers needed.
	o iwevent were already RtNetlink based since they were created
(around 2.5.7). This adds all the regular SET and GET requests over
RtNetlink, using the exact same mechanism and data format as iwevents.
	o This is a Kconfig option, as currently most people have no
need for it. Surprisingly, patch is actually small and well
encapsulated.
	o Tested on SMP, attention as been paid to make it 64 bits clean.
	o Code do probably too many checks and could be further
optimised, but better safe than sorry.
	o RtNetlink based version of the Wireless Tools available on
my web page for people inclined to try out this stuff.

	I would also like to thank Alexey Kuznetsov for his helpful
suggestions to make this patch better.

Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Jean Tourrilhes 2006-02-22 15:10:56 -08:00 committed by John W. Linville
parent 9a107aa24a
commit 711e2c33ac
5 changed files with 947 additions and 93 deletions

View File

@ -25,6 +25,15 @@ config NET_RADIO
the tools from
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
config NET_WIRELESS_RTNETLINK
bool "Wireless Extension API over RtNetlink"
---help---
Support the Wireless Extension API over the RtNetlink socket
in addition to the traditional ioctl interface (selected above).
For now, few tools use this facility, but it might grow in the
future. The only downside is that it adds 4.5 kB to your kernel.
# Note : the cards are obsolete (can't buy them anymore), but the drivers
# are not, as people are still using them...
comment "Obsolete Wireless cards support (pre-802.11)"

View File

@ -1,10 +1,10 @@
/*
* This file define a set of standard wireless extensions
*
* Version : 19 18.3.05
* Version : 20 17.2.06
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
* Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
*/
#ifndef _LINUX_WIRELESS_H
@ -80,7 +80,7 @@
* (there is some stuff that will be added in the future...)
* I just plan to increment with each new version.
*/
#define WIRELESS_EXT 19
#define WIRELESS_EXT 20
/*
* Changes :
@ -204,6 +204,10 @@
* - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
* - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
* - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
*
* V19 to V20
* ----------
* - RtNetlink requests support (SET/GET)
*/
/**************************** CONSTANTS ****************************/

View File

@ -4,7 +4,7 @@
* Version : 7 18.3.05
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 2001-2005 Jean Tourrilhes, All Rights Reserved.
* Copyright (c) 2001-2006 Jean Tourrilhes, All Rights Reserved.
*/
#ifndef _IW_HANDLER_H
@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
/* Handle IOCTLs, called in net/core/dev.c */
extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
/* Handle RtNetlink requests, called in net/core/rtnetlink.c */
extern int wireless_rtnetlink_set(struct net_device * dev,
char * data,
int len);
extern int wireless_rtnetlink_get(struct net_device * dev,
char * data,
int len,
char ** p_buf,
int * p_len);
/* Second : functions that may be called by driver modules */
/* Send a single event to user space */

View File

@ -51,6 +51,10 @@
#include <net/sock.h>
#include <net/pkt_sched.h>
#include <net/netlink.h>
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
#include <linux/wireless.h>
#include <net/iw_handler.h>
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
static DEFINE_MUTEX(rtnl_mutex);
@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
goto out;
}
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
if (ida[IFLA_WIRELESS - 1]) {
/* Call Wireless Extensions.
* Various stuff checked in there... */
err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
if (err)
goto out;
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
err = 0;
out:
@ -477,6 +492,83 @@ out:
return err;
}
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
{
struct ifinfomsg *ifm = NLMSG_DATA(in_nlh);
struct rtattr **ida = arg;
struct net_device *dev;
struct ifinfomsg *r;
struct nlmsghdr *nlh;
int err = -ENOBUFS;
struct sk_buff *skb;
unsigned char *b;
char *iw_buf = NULL;
int iw_buf_len = 0;
if (ifm->ifi_index >= 0)
dev = dev_get_by_index(ifm->ifi_index);
else
return -EINVAL;
if (!dev)
return -ENODEV;
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
if (ida[IFLA_WIRELESS - 1]) {
/* Call Wireless Extensions. We need to know the size before
* we can alloc. Various stuff checked in there... */
err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
if (err)
goto out;
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
/* Create a skb big enough to include all the data.
* Some requests are way bigger than 4k... Jean II */
skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
GFP_KERNEL);
if (!skb)
goto out;
b = skb->tail;
/* Put in the message the usual good stuff */
nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
RTM_NEWLINK, sizeof(*r));
r = NLMSG_DATA(nlh);
r->ifi_family = AF_UNSPEC;
r->__ifi_pad = 0;
r->ifi_type = dev->type;
r->ifi_index = dev->ifindex;
r->ifi_flags = dev->flags;
r->ifi_change = 0;
/* Put the wireless payload if it exist */
if(iw_buf != NULL)
RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
iw_buf + IW_EV_POINT_OFF);
nlh->nlmsg_len = skb->tail - b;
/* Needed ? */
NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
if (err > 0)
err = 0;
out:
if(iw_buf != NULL)
kfree(iw_buf);
dev_put(dev);
return err;
rtattr_failure:
nlmsg_failure:
kfree_skb(skb);
goto out;
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx;
@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len)
static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
{
[RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
[RTM_GETLINK - RTM_BASE] = {
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
.doit = do_getlink,
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
.dumpit = rtnetlink_dump_ifinfo },
[RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
[RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
[RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },

File diff suppressed because it is too large Load Diff