aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
authorJean Tourrilhes <jt@hpl.hp.com>2006-02-22 18:10:56 -0500
committerJohn W. Linville <linville@tuxdriver.com>2006-03-23 07:12:57 -0500
commit711e2c33ac9221a419a9e28d05dd78a6a9c5fd4d (patch)
tree2d04ff5de8a0d933d3d123a52a6e4285f84e9025 /net/core/rtnetlink.c
parent9a107aa24a1dbc05d58a4fdd2c4d2861f8bd5ae6 (diff)
[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>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c98
1 files changed, 97 insertions, 1 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index ae10d3740faa..3fcfa9c59e1f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -51,6 +51,10 @@
51#include <net/sock.h> 51#include <net/sock.h>
52#include <net/pkt_sched.h> 52#include <net/pkt_sched.h>
53#include <net/netlink.h> 53#include <net/netlink.h>
54#ifdef CONFIG_NET_WIRELESS_RTNETLINK
55#include <linux/wireless.h>
56#include <net/iw_handler.h>
57#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
54 58
55static DEFINE_MUTEX(rtnl_mutex); 59static DEFINE_MUTEX(rtnl_mutex);
56 60
@@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
467 goto out; 471 goto out;
468 } 472 }
469 473
474#ifdef CONFIG_NET_WIRELESS_RTNETLINK
475 if (ida[IFLA_WIRELESS - 1]) {
476
477 /* Call Wireless Extensions.
478 * Various stuff checked in there... */
479 err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
480 if (err)
481 goto out;
482 }
483#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
484
470 err = 0; 485 err = 0;
471 486
472out: 487out:
@@ -477,6 +492,83 @@ out:
477 return err; 492 return err;
478} 493}
479 494
495#ifdef CONFIG_NET_WIRELESS_RTNETLINK
496static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
497{
498 struct ifinfomsg *ifm = NLMSG_DATA(in_nlh);
499 struct rtattr **ida = arg;
500 struct net_device *dev;
501 struct ifinfomsg *r;
502 struct nlmsghdr *nlh;
503 int err = -ENOBUFS;
504 struct sk_buff *skb;
505 unsigned char *b;
506 char *iw_buf = NULL;
507 int iw_buf_len = 0;
508
509 if (ifm->ifi_index >= 0)
510 dev = dev_get_by_index(ifm->ifi_index);
511 else
512 return -EINVAL;
513 if (!dev)
514 return -ENODEV;
515
516#ifdef CONFIG_NET_WIRELESS_RTNETLINK
517 if (ida[IFLA_WIRELESS - 1]) {
518
519 /* Call Wireless Extensions. We need to know the size before
520 * we can alloc. Various stuff checked in there... */
521 err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
522 if (err)
523 goto out;
524 }
525#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
526
527 /* Create a skb big enough to include all the data.
528 * Some requests are way bigger than 4k... Jean II */
529 skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
530 GFP_KERNEL);
531 if (!skb)
532 goto out;
533 b = skb->tail;
534
535 /* Put in the message the usual good stuff */
536 nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
537 RTM_NEWLINK, sizeof(*r));
538 r = NLMSG_DATA(nlh);
539 r->ifi_family = AF_UNSPEC;
540 r->__ifi_pad = 0;
541 r->ifi_type = dev->type;
542 r->ifi_index = dev->ifindex;
543 r->ifi_flags = dev->flags;
544 r->ifi_change = 0;
545
546 /* Put the wireless payload if it exist */
547 if(iw_buf != NULL)
548 RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
549 iw_buf + IW_EV_POINT_OFF);
550
551 nlh->nlmsg_len = skb->tail - b;
552
553 /* Needed ? */
554 NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
555
556 err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
557 if (err > 0)
558 err = 0;
559out:
560 if(iw_buf != NULL)
561 kfree(iw_buf);
562 dev_put(dev);
563 return err;
564
565rtattr_failure:
566nlmsg_failure:
567 kfree_skb(skb);
568 goto out;
569}
570#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
571
480static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) 572static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
481{ 573{
482 int idx; 574 int idx;
@@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len)
642 734
643static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = 735static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
644{ 736{
645 [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo }, 737 [RTM_GETLINK - RTM_BASE] = {
738#ifdef CONFIG_NET_WIRELESS_RTNETLINK
739 .doit = do_getlink,
740#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
741 .dumpit = rtnetlink_dump_ifinfo },
646 [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, 742 [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
647 [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 743 [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
648 [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 744 [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },