2 * This is the new netlink-based wireless configuration interface.
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
8 #include <linux/module.h>
10 #include <linux/mutex.h>
11 #include <linux/list.h>
12 #include <linux/if_ether.h>
13 #include <linux/ieee80211.h>
14 #include <linux/nl80211.h>
15 #include <linux/rtnetlink.h>
16 #include <linux/netlink.h>
17 #include <net/genetlink.h>
18 #include <net/cfg80211.h>
22 /* the netlink family */
23 static struct genl_family nl80211_fam
= {
24 .id
= GENL_ID_GENERATE
, /* don't bother with a hardcoded ID */
25 .name
= "nl80211", /* have users key off the name instead */
26 .hdrsize
= 0, /* no private header */
27 .version
= 1, /* no particular meaning now */
28 .maxattr
= NL80211_ATTR_MAX
,
31 /* internal helper: get drv and dev */
32 static int get_drv_dev_by_info_ifindex(struct genl_info
*info
,
33 struct cfg80211_registered_device
**drv
,
34 struct net_device
**dev
)
38 if (!info
->attrs
[NL80211_ATTR_IFINDEX
])
41 ifindex
= nla_get_u32(info
->attrs
[NL80211_ATTR_IFINDEX
]);
42 *dev
= dev_get_by_index(&init_net
, ifindex
);
46 *drv
= cfg80211_get_dev_from_ifindex(ifindex
);
55 /* policy for the attributes */
56 static struct nla_policy nl80211_policy
[NL80211_ATTR_MAX
+1] __read_mostly
= {
57 [NL80211_ATTR_WIPHY
] = { .type
= NLA_U32
},
58 [NL80211_ATTR_WIPHY_NAME
] = { .type
= NLA_NUL_STRING
,
59 .len
= BUS_ID_SIZE
-1 },
61 [NL80211_ATTR_IFTYPE
] = { .type
= NLA_U32
},
62 [NL80211_ATTR_IFINDEX
] = { .type
= NLA_U32
},
63 [NL80211_ATTR_IFNAME
] = { .type
= NLA_NUL_STRING
, .len
= IFNAMSIZ
-1 },
65 [NL80211_ATTR_MAC
] = { .type
= NLA_BINARY
, .len
= ETH_ALEN
},
67 [NL80211_ATTR_KEY_DATA
] = { .type
= NLA_BINARY
,
68 .len
= WLAN_MAX_KEY_LEN
},
69 [NL80211_ATTR_KEY_IDX
] = { .type
= NLA_U8
},
70 [NL80211_ATTR_KEY_CIPHER
] = { .type
= NLA_U32
},
71 [NL80211_ATTR_KEY_DEFAULT
] = { .type
= NLA_FLAG
},
73 [NL80211_ATTR_BEACON_INTERVAL
] = { .type
= NLA_U32
},
74 [NL80211_ATTR_DTIM_PERIOD
] = { .type
= NLA_U32
},
75 [NL80211_ATTR_BEACON_HEAD
] = { .type
= NLA_BINARY
,
76 .len
= IEEE80211_MAX_DATA_LEN
},
77 [NL80211_ATTR_BEACON_TAIL
] = { .type
= NLA_BINARY
,
78 .len
= IEEE80211_MAX_DATA_LEN
},
79 [NL80211_ATTR_STA_AID
] = { .type
= NLA_U16
},
80 [NL80211_ATTR_STA_FLAGS
] = { .type
= NLA_NESTED
},
81 [NL80211_ATTR_STA_LISTEN_INTERVAL
] = { .type
= NLA_U16
},
82 [NL80211_ATTR_STA_SUPPORTED_RATES
] = { .type
= NLA_BINARY
,
83 .len
= NL80211_MAX_SUPP_RATES
},
84 [NL80211_ATTR_STA_VLAN
] = { .type
= NLA_U32
},
87 /* message building helper */
88 static inline void *nl80211hdr_put(struct sk_buff
*skb
, u32 pid
, u32 seq
,
91 /* since there is no private header just add the generic one */
92 return genlmsg_put(skb
, pid
, seq
, &nl80211_fam
, flags
, cmd
);
95 /* netlink command implementations */
97 static int nl80211_send_wiphy(struct sk_buff
*msg
, u32 pid
, u32 seq
, int flags
,
98 struct cfg80211_registered_device
*dev
)
102 hdr
= nl80211hdr_put(msg
, pid
, seq
, flags
, NL80211_CMD_NEW_WIPHY
);
106 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY
, dev
->idx
);
107 NLA_PUT_STRING(msg
, NL80211_ATTR_WIPHY_NAME
, wiphy_name(&dev
->wiphy
));
108 return genlmsg_end(msg
, hdr
);
111 return genlmsg_cancel(msg
, hdr
);
114 static int nl80211_dump_wiphy(struct sk_buff
*skb
, struct netlink_callback
*cb
)
117 int start
= cb
->args
[0];
118 struct cfg80211_registered_device
*dev
;
120 mutex_lock(&cfg80211_drv_mutex
);
121 list_for_each_entry(dev
, &cfg80211_drv_list
, list
) {
124 if (nl80211_send_wiphy(skb
, NETLINK_CB(cb
->skb
).pid
,
125 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
129 mutex_unlock(&cfg80211_drv_mutex
);
136 static int nl80211_get_wiphy(struct sk_buff
*skb
, struct genl_info
*info
)
139 struct cfg80211_registered_device
*dev
;
141 dev
= cfg80211_get_dev_from_info(info
);
145 msg
= nlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
149 if (nl80211_send_wiphy(msg
, info
->snd_pid
, info
->snd_seq
, 0, dev
) < 0)
152 cfg80211_put_dev(dev
);
154 return genlmsg_unicast(msg
, info
->snd_pid
);
159 cfg80211_put_dev(dev
);
163 static int nl80211_set_wiphy(struct sk_buff
*skb
, struct genl_info
*info
)
165 struct cfg80211_registered_device
*rdev
;
168 if (!info
->attrs
[NL80211_ATTR_WIPHY_NAME
])
171 rdev
= cfg80211_get_dev_from_info(info
);
173 return PTR_ERR(rdev
);
175 result
= cfg80211_dev_rename(rdev
, nla_data(info
->attrs
[NL80211_ATTR_WIPHY_NAME
]));
177 cfg80211_put_dev(rdev
);
182 static int nl80211_send_iface(struct sk_buff
*msg
, u32 pid
, u32 seq
, int flags
,
183 struct net_device
*dev
)
187 hdr
= nl80211hdr_put(msg
, pid
, seq
, flags
, NL80211_CMD_NEW_INTERFACE
);
191 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, dev
->ifindex
);
192 NLA_PUT_STRING(msg
, NL80211_ATTR_IFNAME
, dev
->name
);
193 /* TODO: interface type */
194 return genlmsg_end(msg
, hdr
);
197 return genlmsg_cancel(msg
, hdr
);
200 static int nl80211_dump_interface(struct sk_buff
*skb
, struct netlink_callback
*cb
)
204 int wp_start
= cb
->args
[0];
205 int if_start
= cb
->args
[1];
206 struct cfg80211_registered_device
*dev
;
207 struct wireless_dev
*wdev
;
209 mutex_lock(&cfg80211_drv_mutex
);
210 list_for_each_entry(dev
, &cfg80211_drv_list
, list
) {
211 if (++wp_idx
< wp_start
)
215 mutex_lock(&dev
->devlist_mtx
);
216 list_for_each_entry(wdev
, &dev
->netdev_list
, list
) {
217 if (++if_idx
< if_start
)
219 if (nl80211_send_iface(skb
, NETLINK_CB(cb
->skb
).pid
,
220 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
224 mutex_unlock(&dev
->devlist_mtx
);
226 mutex_unlock(&cfg80211_drv_mutex
);
228 cb
->args
[0] = wp_idx
;
229 cb
->args
[1] = if_idx
;
234 static int nl80211_get_interface(struct sk_buff
*skb
, struct genl_info
*info
)
237 struct cfg80211_registered_device
*dev
;
238 struct net_device
*netdev
;
241 err
= get_drv_dev_by_info_ifindex(info
, &dev
, &netdev
);
245 msg
= nlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
249 if (nl80211_send_iface(msg
, info
->snd_pid
, info
->snd_seq
, 0, netdev
) < 0)
253 cfg80211_put_dev(dev
);
255 return genlmsg_unicast(msg
, info
->snd_pid
);
261 cfg80211_put_dev(dev
);
265 static int nl80211_set_interface(struct sk_buff
*skb
, struct genl_info
*info
)
267 struct cfg80211_registered_device
*drv
;
269 enum nl80211_iftype type
;
270 struct net_device
*dev
;
272 if (info
->attrs
[NL80211_ATTR_IFTYPE
]) {
273 type
= nla_get_u32(info
->attrs
[NL80211_ATTR_IFTYPE
]);
274 if (type
> NL80211_IFTYPE_MAX
)
279 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
282 ifindex
= dev
->ifindex
;
285 if (!drv
->ops
->change_virtual_intf
) {
291 err
= drv
->ops
->change_virtual_intf(&drv
->wiphy
, ifindex
, type
);
295 cfg80211_put_dev(drv
);
299 static int nl80211_new_interface(struct sk_buff
*skb
, struct genl_info
*info
)
301 struct cfg80211_registered_device
*drv
;
303 enum nl80211_iftype type
= NL80211_IFTYPE_UNSPECIFIED
;
305 if (!info
->attrs
[NL80211_ATTR_IFNAME
])
308 if (info
->attrs
[NL80211_ATTR_IFTYPE
]) {
309 type
= nla_get_u32(info
->attrs
[NL80211_ATTR_IFTYPE
]);
310 if (type
> NL80211_IFTYPE_MAX
)
314 drv
= cfg80211_get_dev_from_info(info
);
318 if (!drv
->ops
->add_virtual_intf
) {
324 err
= drv
->ops
->add_virtual_intf(&drv
->wiphy
,
325 nla_data(info
->attrs
[NL80211_ATTR_IFNAME
]), type
);
329 cfg80211_put_dev(drv
);
333 static int nl80211_del_interface(struct sk_buff
*skb
, struct genl_info
*info
)
335 struct cfg80211_registered_device
*drv
;
337 struct net_device
*dev
;
339 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
342 ifindex
= dev
->ifindex
;
345 if (!drv
->ops
->del_virtual_intf
) {
351 err
= drv
->ops
->del_virtual_intf(&drv
->wiphy
, ifindex
);
355 cfg80211_put_dev(drv
);
359 struct get_key_cookie
{
364 static void get_key_callback(void *c
, struct key_params
*params
)
366 struct get_key_cookie
*cookie
= c
;
369 NLA_PUT(cookie
->msg
, NL80211_ATTR_KEY_DATA
,
370 params
->key_len
, params
->key
);
373 NLA_PUT(cookie
->msg
, NL80211_ATTR_KEY_SEQ
,
374 params
->seq_len
, params
->seq
);
377 NLA_PUT_U32(cookie
->msg
, NL80211_ATTR_KEY_CIPHER
,
385 static int nl80211_get_key(struct sk_buff
*skb
, struct genl_info
*info
)
387 struct cfg80211_registered_device
*drv
;
389 struct net_device
*dev
;
392 struct get_key_cookie cookie
= {
398 if (info
->attrs
[NL80211_ATTR_KEY_IDX
])
399 key_idx
= nla_get_u8(info
->attrs
[NL80211_ATTR_KEY_IDX
]);
404 if (info
->attrs
[NL80211_ATTR_MAC
])
405 mac_addr
= nla_data(info
->attrs
[NL80211_ATTR_MAC
]);
407 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
411 if (!drv
->ops
->get_key
) {
416 msg
= nlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
422 hdr
= nl80211hdr_put(msg
, info
->snd_pid
, info
->snd_seq
, 0,
423 NL80211_CMD_NEW_KEY
);
432 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, dev
->ifindex
);
433 NLA_PUT_U8(msg
, NL80211_ATTR_KEY_IDX
, key_idx
);
435 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, mac_addr
);
438 err
= drv
->ops
->get_key(&drv
->wiphy
, dev
, key_idx
, mac_addr
,
439 &cookie
, get_key_callback
);
446 goto nla_put_failure
;
448 genlmsg_end(msg
, hdr
);
449 err
= genlmsg_unicast(msg
, info
->snd_pid
);
456 cfg80211_put_dev(drv
);
461 static int nl80211_set_key(struct sk_buff
*skb
, struct genl_info
*info
)
463 struct cfg80211_registered_device
*drv
;
465 struct net_device
*dev
;
468 if (!info
->attrs
[NL80211_ATTR_KEY_IDX
])
471 key_idx
= nla_get_u8(info
->attrs
[NL80211_ATTR_KEY_IDX
]);
476 /* currently only support setting default key */
477 if (!info
->attrs
[NL80211_ATTR_KEY_DEFAULT
])
480 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
484 if (!drv
->ops
->set_default_key
) {
490 err
= drv
->ops
->set_default_key(&drv
->wiphy
, dev
, key_idx
);
494 cfg80211_put_dev(drv
);
499 static int nl80211_new_key(struct sk_buff
*skb
, struct genl_info
*info
)
501 struct cfg80211_registered_device
*drv
;
503 struct net_device
*dev
;
504 struct key_params params
;
508 memset(¶ms
, 0, sizeof(params
));
510 if (!info
->attrs
[NL80211_ATTR_KEY_CIPHER
])
513 if (info
->attrs
[NL80211_ATTR_KEY_DATA
]) {
514 params
.key
= nla_data(info
->attrs
[NL80211_ATTR_KEY_DATA
]);
515 params
.key_len
= nla_len(info
->attrs
[NL80211_ATTR_KEY_DATA
]);
518 if (info
->attrs
[NL80211_ATTR_KEY_IDX
])
519 key_idx
= nla_get_u8(info
->attrs
[NL80211_ATTR_KEY_IDX
]);
521 params
.cipher
= nla_get_u32(info
->attrs
[NL80211_ATTR_KEY_CIPHER
]);
523 if (info
->attrs
[NL80211_ATTR_MAC
])
524 mac_addr
= nla_data(info
->attrs
[NL80211_ATTR_MAC
]);
530 * Disallow pairwise keys with non-zero index unless it's WEP
531 * (because current deployments use pairwise WEP keys with
532 * non-zero indizes but 802.11i clearly specifies to use zero)
534 if (mac_addr
&& key_idx
&&
535 params
.cipher
!= WLAN_CIPHER_SUITE_WEP40
&&
536 params
.cipher
!= WLAN_CIPHER_SUITE_WEP104
)
539 /* TODO: add definitions for the lengths to linux/ieee80211.h */
540 switch (params
.cipher
) {
541 case WLAN_CIPHER_SUITE_WEP40
:
542 if (params
.key_len
!= 5)
545 case WLAN_CIPHER_SUITE_TKIP
:
546 if (params
.key_len
!= 32)
549 case WLAN_CIPHER_SUITE_CCMP
:
550 if (params
.key_len
!= 16)
553 case WLAN_CIPHER_SUITE_WEP104
:
554 if (params
.key_len
!= 13)
561 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
565 if (!drv
->ops
->add_key
) {
571 err
= drv
->ops
->add_key(&drv
->wiphy
, dev
, key_idx
, mac_addr
, ¶ms
);
575 cfg80211_put_dev(drv
);
580 static int nl80211_del_key(struct sk_buff
*skb
, struct genl_info
*info
)
582 struct cfg80211_registered_device
*drv
;
584 struct net_device
*dev
;
588 if (info
->attrs
[NL80211_ATTR_KEY_IDX
])
589 key_idx
= nla_get_u8(info
->attrs
[NL80211_ATTR_KEY_IDX
]);
594 if (info
->attrs
[NL80211_ATTR_MAC
])
595 mac_addr
= nla_data(info
->attrs
[NL80211_ATTR_MAC
]);
597 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
601 if (!drv
->ops
->del_key
) {
607 err
= drv
->ops
->del_key(&drv
->wiphy
, dev
, key_idx
, mac_addr
);
611 cfg80211_put_dev(drv
);
616 static int nl80211_addset_beacon(struct sk_buff
*skb
, struct genl_info
*info
)
618 int (*call
)(struct wiphy
*wiphy
, struct net_device
*dev
,
619 struct beacon_parameters
*info
);
620 struct cfg80211_registered_device
*drv
;
622 struct net_device
*dev
;
623 struct beacon_parameters params
;
626 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
630 switch (info
->genlhdr
->cmd
) {
631 case NL80211_CMD_NEW_BEACON
:
632 /* these are required for NEW_BEACON */
633 if (!info
->attrs
[NL80211_ATTR_BEACON_INTERVAL
] ||
634 !info
->attrs
[NL80211_ATTR_DTIM_PERIOD
] ||
635 !info
->attrs
[NL80211_ATTR_BEACON_HEAD
]) {
640 call
= drv
->ops
->add_beacon
;
642 case NL80211_CMD_SET_BEACON
:
643 call
= drv
->ops
->set_beacon
;
656 memset(¶ms
, 0, sizeof(params
));
658 if (info
->attrs
[NL80211_ATTR_BEACON_INTERVAL
]) {
660 nla_get_u32(info
->attrs
[NL80211_ATTR_BEACON_INTERVAL
]);
664 if (info
->attrs
[NL80211_ATTR_DTIM_PERIOD
]) {
666 nla_get_u32(info
->attrs
[NL80211_ATTR_DTIM_PERIOD
]);
670 if (info
->attrs
[NL80211_ATTR_BEACON_HEAD
]) {
671 params
.head
= nla_data(info
->attrs
[NL80211_ATTR_BEACON_HEAD
]);
673 nla_len(info
->attrs
[NL80211_ATTR_BEACON_HEAD
]);
677 if (info
->attrs
[NL80211_ATTR_BEACON_TAIL
]) {
678 params
.tail
= nla_data(info
->attrs
[NL80211_ATTR_BEACON_TAIL
]);
680 nla_len(info
->attrs
[NL80211_ATTR_BEACON_TAIL
]);
690 err
= call(&drv
->wiphy
, dev
, ¶ms
);
694 cfg80211_put_dev(drv
);
699 static int nl80211_del_beacon(struct sk_buff
*skb
, struct genl_info
*info
)
701 struct cfg80211_registered_device
*drv
;
703 struct net_device
*dev
;
705 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
709 if (!drv
->ops
->del_beacon
) {
715 err
= drv
->ops
->del_beacon(&drv
->wiphy
, dev
);
719 cfg80211_put_dev(drv
);
724 static const struct nla_policy sta_flags_policy
[NL80211_STA_FLAG_MAX
+ 1] = {
725 [NL80211_STA_FLAG_AUTHORIZED
] = { .type
= NLA_FLAG
},
726 [NL80211_STA_FLAG_SHORT_PREAMBLE
] = { .type
= NLA_FLAG
},
727 [NL80211_STA_FLAG_WME
] = { .type
= NLA_FLAG
},
730 static int parse_station_flags(struct nlattr
*nla
, u32
*staflags
)
732 struct nlattr
*flags
[NL80211_STA_FLAG_MAX
+ 1];
740 if (nla_parse_nested(flags
, NL80211_STA_FLAG_MAX
,
741 nla
, sta_flags_policy
))
744 *staflags
= STATION_FLAG_CHANGED
;
746 for (flag
= 1; flag
<= NL80211_STA_FLAG_MAX
; flag
++)
748 *staflags
|= (1<<flag
);
753 static int nl80211_send_station(struct sk_buff
*msg
, u32 pid
, u32 seq
,
754 int flags
, struct net_device
*dev
,
755 u8
*mac_addr
, struct station_stats
*stats
)
758 struct nlattr
*statsattr
;
760 hdr
= nl80211hdr_put(msg
, pid
, seq
, flags
, NL80211_CMD_NEW_STATION
);
764 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, dev
->ifindex
);
765 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, mac_addr
);
767 statsattr
= nla_nest_start(msg
, NL80211_ATTR_STA_STATS
);
769 goto nla_put_failure
;
770 if (stats
->filled
& STATION_STAT_INACTIVE_TIME
)
771 NLA_PUT_U32(msg
, NL80211_STA_STAT_INACTIVE_TIME
,
772 stats
->inactive_time
);
773 if (stats
->filled
& STATION_STAT_RX_BYTES
)
774 NLA_PUT_U32(msg
, NL80211_STA_STAT_RX_BYTES
,
776 if (stats
->filled
& STATION_STAT_TX_BYTES
)
777 NLA_PUT_U32(msg
, NL80211_STA_STAT_TX_BYTES
,
780 nla_nest_end(msg
, statsattr
);
782 return genlmsg_end(msg
, hdr
);
785 return genlmsg_cancel(msg
, hdr
);
789 static int nl80211_get_station(struct sk_buff
*skb
, struct genl_info
*info
)
791 struct cfg80211_registered_device
*drv
;
793 struct net_device
*dev
;
794 struct station_stats stats
;
798 memset(&stats
, 0, sizeof(stats
));
800 if (!info
->attrs
[NL80211_ATTR_MAC
])
803 mac_addr
= nla_data(info
->attrs
[NL80211_ATTR_MAC
]);
805 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
809 if (!drv
->ops
->get_station
) {
815 err
= drv
->ops
->get_station(&drv
->wiphy
, dev
, mac_addr
, &stats
);
818 msg
= nlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
822 if (nl80211_send_station(msg
, info
->snd_pid
, info
->snd_seq
, 0,
823 dev
, mac_addr
, &stats
) < 0)
826 err
= genlmsg_unicast(msg
, info
->snd_pid
);
833 cfg80211_put_dev(drv
);
839 * Get vlan interface making sure it is on the right wiphy.
841 static int get_vlan(struct nlattr
*vlanattr
,
842 struct cfg80211_registered_device
*rdev
,
843 struct net_device
**vlan
)
848 *vlan
= dev_get_by_index(&init_net
, nla_get_u32(vlanattr
));
851 if (!(*vlan
)->ieee80211_ptr
)
853 if ((*vlan
)->ieee80211_ptr
->wiphy
!= &rdev
->wiphy
)
859 static int nl80211_set_station(struct sk_buff
*skb
, struct genl_info
*info
)
861 struct cfg80211_registered_device
*drv
;
863 struct net_device
*dev
;
864 struct station_parameters params
;
867 memset(¶ms
, 0, sizeof(params
));
869 params
.listen_interval
= -1;
871 if (info
->attrs
[NL80211_ATTR_STA_AID
])
874 if (!info
->attrs
[NL80211_ATTR_MAC
])
877 mac_addr
= nla_data(info
->attrs
[NL80211_ATTR_MAC
]);
879 if (info
->attrs
[NL80211_ATTR_STA_SUPPORTED_RATES
]) {
880 params
.supported_rates
=
881 nla_data(info
->attrs
[NL80211_ATTR_STA_SUPPORTED_RATES
]);
882 params
.supported_rates_len
=
883 nla_len(info
->attrs
[NL80211_ATTR_STA_SUPPORTED_RATES
]);
886 if (info
->attrs
[NL80211_ATTR_STA_LISTEN_INTERVAL
])
887 params
.listen_interval
=
888 nla_get_u16(info
->attrs
[NL80211_ATTR_STA_LISTEN_INTERVAL
]);
890 if (parse_station_flags(info
->attrs
[NL80211_ATTR_STA_FLAGS
],
891 ¶ms
.station_flags
))
894 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
898 err
= get_vlan(info
->attrs
[NL80211_ATTR_STA_VLAN
], drv
, ¶ms
.vlan
);
902 if (!drv
->ops
->change_station
) {
908 err
= drv
->ops
->change_station(&drv
->wiphy
, dev
, mac_addr
, ¶ms
);
913 dev_put(params
.vlan
);
914 cfg80211_put_dev(drv
);
919 static int nl80211_new_station(struct sk_buff
*skb
, struct genl_info
*info
)
921 struct cfg80211_registered_device
*drv
;
923 struct net_device
*dev
;
924 struct station_parameters params
;
927 memset(¶ms
, 0, sizeof(params
));
929 if (!info
->attrs
[NL80211_ATTR_MAC
])
932 if (!info
->attrs
[NL80211_ATTR_STA_AID
])
935 if (!info
->attrs
[NL80211_ATTR_STA_LISTEN_INTERVAL
])
938 if (!info
->attrs
[NL80211_ATTR_STA_SUPPORTED_RATES
])
941 mac_addr
= nla_data(info
->attrs
[NL80211_ATTR_MAC
]);
942 params
.supported_rates
=
943 nla_data(info
->attrs
[NL80211_ATTR_STA_SUPPORTED_RATES
]);
944 params
.supported_rates_len
=
945 nla_len(info
->attrs
[NL80211_ATTR_STA_SUPPORTED_RATES
]);
946 params
.listen_interval
=
947 nla_get_u16(info
->attrs
[NL80211_ATTR_STA_LISTEN_INTERVAL
]);
948 params
.listen_interval
= nla_get_u16(info
->attrs
[NL80211_ATTR_STA_AID
]);
950 if (parse_station_flags(info
->attrs
[NL80211_ATTR_STA_FLAGS
],
951 ¶ms
.station_flags
))
954 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
958 err
= get_vlan(info
->attrs
[NL80211_ATTR_STA_VLAN
], drv
, ¶ms
.vlan
);
962 if (!drv
->ops
->add_station
) {
968 err
= drv
->ops
->add_station(&drv
->wiphy
, dev
, mac_addr
, ¶ms
);
973 dev_put(params
.vlan
);
974 cfg80211_put_dev(drv
);
979 static int nl80211_del_station(struct sk_buff
*skb
, struct genl_info
*info
)
981 struct cfg80211_registered_device
*drv
;
983 struct net_device
*dev
;
986 if (info
->attrs
[NL80211_ATTR_MAC
])
987 mac_addr
= nla_data(info
->attrs
[NL80211_ATTR_MAC
]);
989 err
= get_drv_dev_by_info_ifindex(info
, &drv
, &dev
);
993 if (!drv
->ops
->del_station
) {
999 err
= drv
->ops
->del_station(&drv
->wiphy
, dev
, mac_addr
);
1003 cfg80211_put_dev(drv
);
1008 static struct genl_ops nl80211_ops
[] = {
1010 .cmd
= NL80211_CMD_GET_WIPHY
,
1011 .doit
= nl80211_get_wiphy
,
1012 .dumpit
= nl80211_dump_wiphy
,
1013 .policy
= nl80211_policy
,
1014 /* can be retrieved by unprivileged users */
1017 .cmd
= NL80211_CMD_SET_WIPHY
,
1018 .doit
= nl80211_set_wiphy
,
1019 .policy
= nl80211_policy
,
1020 .flags
= GENL_ADMIN_PERM
,
1023 .cmd
= NL80211_CMD_GET_INTERFACE
,
1024 .doit
= nl80211_get_interface
,
1025 .dumpit
= nl80211_dump_interface
,
1026 .policy
= nl80211_policy
,
1027 /* can be retrieved by unprivileged users */
1030 .cmd
= NL80211_CMD_SET_INTERFACE
,
1031 .doit
= nl80211_set_interface
,
1032 .policy
= nl80211_policy
,
1033 .flags
= GENL_ADMIN_PERM
,
1036 .cmd
= NL80211_CMD_NEW_INTERFACE
,
1037 .doit
= nl80211_new_interface
,
1038 .policy
= nl80211_policy
,
1039 .flags
= GENL_ADMIN_PERM
,
1042 .cmd
= NL80211_CMD_DEL_INTERFACE
,
1043 .doit
= nl80211_del_interface
,
1044 .policy
= nl80211_policy
,
1045 .flags
= GENL_ADMIN_PERM
,
1048 .cmd
= NL80211_CMD_GET_KEY
,
1049 .doit
= nl80211_get_key
,
1050 .policy
= nl80211_policy
,
1051 .flags
= GENL_ADMIN_PERM
,
1054 .cmd
= NL80211_CMD_SET_KEY
,
1055 .doit
= nl80211_set_key
,
1056 .policy
= nl80211_policy
,
1057 .flags
= GENL_ADMIN_PERM
,
1060 .cmd
= NL80211_CMD_NEW_KEY
,
1061 .doit
= nl80211_new_key
,
1062 .policy
= nl80211_policy
,
1063 .flags
= GENL_ADMIN_PERM
,
1066 .cmd
= NL80211_CMD_DEL_KEY
,
1067 .doit
= nl80211_del_key
,
1068 .policy
= nl80211_policy
,
1069 .flags
= GENL_ADMIN_PERM
,
1072 .cmd
= NL80211_CMD_SET_BEACON
,
1073 .policy
= nl80211_policy
,
1074 .flags
= GENL_ADMIN_PERM
,
1075 .doit
= nl80211_addset_beacon
,
1078 .cmd
= NL80211_CMD_NEW_BEACON
,
1079 .policy
= nl80211_policy
,
1080 .flags
= GENL_ADMIN_PERM
,
1081 .doit
= nl80211_addset_beacon
,
1084 .cmd
= NL80211_CMD_DEL_BEACON
,
1085 .policy
= nl80211_policy
,
1086 .flags
= GENL_ADMIN_PERM
,
1087 .doit
= nl80211_del_beacon
,
1090 .cmd
= NL80211_CMD_GET_STATION
,
1091 .doit
= nl80211_get_station
,
1092 /* TODO: implement dumpit */
1093 .policy
= nl80211_policy
,
1094 .flags
= GENL_ADMIN_PERM
,
1097 .cmd
= NL80211_CMD_SET_STATION
,
1098 .doit
= nl80211_set_station
,
1099 .policy
= nl80211_policy
,
1100 .flags
= GENL_ADMIN_PERM
,
1103 .cmd
= NL80211_CMD_NEW_STATION
,
1104 .doit
= nl80211_new_station
,
1105 .policy
= nl80211_policy
,
1106 .flags
= GENL_ADMIN_PERM
,
1109 .cmd
= NL80211_CMD_DEL_STATION
,
1110 .doit
= nl80211_del_station
,
1111 .policy
= nl80211_policy
,
1112 .flags
= GENL_ADMIN_PERM
,
1116 /* multicast groups */
1117 static struct genl_multicast_group nl80211_config_mcgrp
= {
1121 /* notification functions */
1123 void nl80211_notify_dev_rename(struct cfg80211_registered_device
*rdev
)
1125 struct sk_buff
*msg
;
1127 msg
= nlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
1131 if (nl80211_send_wiphy(msg
, 0, 0, 0, rdev
) < 0) {
1136 genlmsg_multicast(msg
, 0, nl80211_config_mcgrp
.id
, GFP_KERNEL
);
1139 /* initialisation/exit functions */
1141 int nl80211_init(void)
1145 err
= genl_register_family(&nl80211_fam
);
1149 for (i
= 0; i
< ARRAY_SIZE(nl80211_ops
); i
++) {
1150 err
= genl_register_ops(&nl80211_fam
, &nl80211_ops
[i
]);
1155 err
= genl_register_mc_group(&nl80211_fam
, &nl80211_config_mcgrp
);
1161 genl_unregister_family(&nl80211_fam
);
1165 void nl80211_exit(void)
1167 genl_unregister_family(&nl80211_fam
);