Commit 711e2c33 authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by John W. Linville

[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: default avatarJean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 9a107aa2
...@@ -25,6 +25,15 @@ config NET_RADIO ...@@ -25,6 +25,15 @@ config NET_RADIO
the tools from the tools from
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. <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 # Note : the cards are obsolete (can't buy them anymore), but the drivers
# are not, as people are still using them... # are not, as people are still using them...
comment "Obsolete Wireless cards support (pre-802.11)" comment "Obsolete Wireless cards support (pre-802.11)"
......
/* /*
* This file define a set of standard wireless extensions * 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> * 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 #ifndef _LINUX_WIRELESS_H
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
* (there is some stuff that will be added in the future...) * (there is some stuff that will be added in the future...)
* I just plan to increment with each new version. * I just plan to increment with each new version.
*/ */
#define WIRELESS_EXT 19 #define WIRELESS_EXT 20
/* /*
* Changes : * Changes :
...@@ -204,6 +204,10 @@ ...@@ -204,6 +204,10 @@
* - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
* - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
* - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
*
* V19 to V20
* ----------
* - RtNetlink requests support (SET/GET)
*/ */
/**************************** CONSTANTS ****************************/ /**************************** CONSTANTS ****************************/
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Version : 7 18.3.05 * Version : 7 18.3.05
* *
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> * 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 #ifndef _IW_HANDLER_H
...@@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset, ...@@ -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 */ /* Handle IOCTLs, called in net/core/dev.c */
extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); 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 */ /* Second : functions that may be called by driver modules */
/* Send a single event to user space */ /* Send a single event to user space */
......
...@@ -51,6 +51,10 @@ ...@@ -51,6 +51,10 @@
#include <net/sock.h> #include <net/sock.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/netlink.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); static DEFINE_MUTEX(rtnl_mutex);
...@@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
goto out; 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; err = 0;
out: out:
...@@ -477,6 +492,83 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -477,6 +492,83 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
return err; 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) static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
{ {
int idx; int idx;
...@@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len) ...@@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len)
static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = 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_SETLINK - RTM_BASE] = { .doit = do_setlink },
[RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
[RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment