mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
[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:
parent
9a107aa24a
commit
711e2c33ac
5 changed files with 947 additions and 93 deletions
|
@ -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)"
|
||||
|
|
|
@ -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 ****************************/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue