xref: /openbmc/linux/net/wireless/nl80211.c (revision f42b3800)
1 /*
2  * This is the new netlink-based wireless configuration interface.
3  *
4  * Copyright 2006, 2007	Johannes Berg <johannes@sipsolutions.net>
5  */
6 
7 #include <linux/if.h>
8 #include <linux/module.h>
9 #include <linux/err.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>
19 #include "core.h"
20 #include "nl80211.h"
21 
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,
29 };
30 
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)
35 {
36 	int ifindex;
37 
38 	if (!info->attrs[NL80211_ATTR_IFINDEX])
39 		return -EINVAL;
40 
41 	ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
42 	*dev = dev_get_by_index(&init_net, ifindex);
43 	if (!*dev)
44 		return -ENODEV;
45 
46 	*drv = cfg80211_get_dev_from_ifindex(ifindex);
47 	if (IS_ERR(*drv)) {
48 		dev_put(*dev);
49 		return PTR_ERR(*drv);
50 	}
51 
52 	return 0;
53 }
54 
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 },
60 
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 },
64 
65 	[NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
66 
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 },
72 
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_PLINK_ACTION] = { .type = NLA_U8 },
85 	[NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
86 	[NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
87 	[NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
88 				.len = IEEE80211_MAX_MESH_ID_LEN },
89 	[NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
90 };
91 
92 /* message building helper */
93 static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
94 				   int flags, u8 cmd)
95 {
96 	/* since there is no private header just add the generic one */
97 	return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
98 }
99 
100 /* netlink command implementations */
101 
102 static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
103 			      struct cfg80211_registered_device *dev)
104 {
105 	void *hdr;
106 	struct nlattr *nl_bands, *nl_band;
107 	struct nlattr *nl_freqs, *nl_freq;
108 	struct nlattr *nl_rates, *nl_rate;
109 	enum ieee80211_band band;
110 	struct ieee80211_channel *chan;
111 	struct ieee80211_rate *rate;
112 	int i;
113 
114 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
115 	if (!hdr)
116 		return -1;
117 
118 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
119 	NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
120 
121 	nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
122 	if (!nl_bands)
123 		goto nla_put_failure;
124 
125 	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
126 		if (!dev->wiphy.bands[band])
127 			continue;
128 
129 		nl_band = nla_nest_start(msg, band);
130 		if (!nl_band)
131 			goto nla_put_failure;
132 
133 		/* add frequencies */
134 		nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
135 		if (!nl_freqs)
136 			goto nla_put_failure;
137 
138 		for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
139 			nl_freq = nla_nest_start(msg, i);
140 			if (!nl_freq)
141 				goto nla_put_failure;
142 
143 			chan = &dev->wiphy.bands[band]->channels[i];
144 			NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
145 				    chan->center_freq);
146 
147 			if (chan->flags & IEEE80211_CHAN_DISABLED)
148 				NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
149 			if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
150 				NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
151 			if (chan->flags & IEEE80211_CHAN_NO_IBSS)
152 				NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
153 			if (chan->flags & IEEE80211_CHAN_RADAR)
154 				NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
155 
156 			nla_nest_end(msg, nl_freq);
157 		}
158 
159 		nla_nest_end(msg, nl_freqs);
160 
161 		/* add bitrates */
162 		nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
163 		if (!nl_rates)
164 			goto nla_put_failure;
165 
166 		for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
167 			nl_rate = nla_nest_start(msg, i);
168 			if (!nl_rate)
169 				goto nla_put_failure;
170 
171 			rate = &dev->wiphy.bands[band]->bitrates[i];
172 			NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
173 				    rate->bitrate);
174 			if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
175 				NLA_PUT_FLAG(msg,
176 					NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
177 
178 			nla_nest_end(msg, nl_rate);
179 		}
180 
181 		nla_nest_end(msg, nl_rates);
182 
183 		nla_nest_end(msg, nl_band);
184 	}
185 	nla_nest_end(msg, nl_bands);
186 
187 	return genlmsg_end(msg, hdr);
188 
189  nla_put_failure:
190 	return genlmsg_cancel(msg, hdr);
191 }
192 
193 static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
194 {
195 	int idx = 0;
196 	int start = cb->args[0];
197 	struct cfg80211_registered_device *dev;
198 
199 	mutex_lock(&cfg80211_drv_mutex);
200 	list_for_each_entry(dev, &cfg80211_drv_list, list) {
201 		if (++idx < start)
202 			continue;
203 		if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
204 				       cb->nlh->nlmsg_seq, NLM_F_MULTI,
205 				       dev) < 0)
206 			break;
207 	}
208 	mutex_unlock(&cfg80211_drv_mutex);
209 
210 	cb->args[0] = idx;
211 
212 	return skb->len;
213 }
214 
215 static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
216 {
217 	struct sk_buff *msg;
218 	struct cfg80211_registered_device *dev;
219 
220 	dev = cfg80211_get_dev_from_info(info);
221 	if (IS_ERR(dev))
222 		return PTR_ERR(dev);
223 
224 	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
225 	if (!msg)
226 		goto out_err;
227 
228 	if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
229 		goto out_free;
230 
231 	cfg80211_put_dev(dev);
232 
233 	return genlmsg_unicast(msg, info->snd_pid);
234 
235  out_free:
236 	nlmsg_free(msg);
237  out_err:
238 	cfg80211_put_dev(dev);
239 	return -ENOBUFS;
240 }
241 
242 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
243 {
244 	struct cfg80211_registered_device *rdev;
245 	int result;
246 
247 	if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
248 		return -EINVAL;
249 
250 	rdev = cfg80211_get_dev_from_info(info);
251 	if (IS_ERR(rdev))
252 		return PTR_ERR(rdev);
253 
254 	result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
255 
256 	cfg80211_put_dev(rdev);
257 	return result;
258 }
259 
260 
261 static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
262 			      struct net_device *dev)
263 {
264 	void *hdr;
265 
266 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
267 	if (!hdr)
268 		return -1;
269 
270 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
271 	NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
272 	/* TODO: interface type */
273 	return genlmsg_end(msg, hdr);
274 
275  nla_put_failure:
276 	return genlmsg_cancel(msg, hdr);
277 }
278 
279 static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
280 {
281 	int wp_idx = 0;
282 	int if_idx = 0;
283 	int wp_start = cb->args[0];
284 	int if_start = cb->args[1];
285 	struct cfg80211_registered_device *dev;
286 	struct wireless_dev *wdev;
287 
288 	mutex_lock(&cfg80211_drv_mutex);
289 	list_for_each_entry(dev, &cfg80211_drv_list, list) {
290 		if (++wp_idx < wp_start)
291 			continue;
292 		if_idx = 0;
293 
294 		mutex_lock(&dev->devlist_mtx);
295 		list_for_each_entry(wdev, &dev->netdev_list, list) {
296 			if (++if_idx < if_start)
297 				continue;
298 			if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
299 					       cb->nlh->nlmsg_seq, NLM_F_MULTI,
300 					       wdev->netdev) < 0)
301 				break;
302 		}
303 		mutex_unlock(&dev->devlist_mtx);
304 	}
305 	mutex_unlock(&cfg80211_drv_mutex);
306 
307 	cb->args[0] = wp_idx;
308 	cb->args[1] = if_idx;
309 
310 	return skb->len;
311 }
312 
313 static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
314 {
315 	struct sk_buff *msg;
316 	struct cfg80211_registered_device *dev;
317 	struct net_device *netdev;
318 	int err;
319 
320 	err = get_drv_dev_by_info_ifindex(info, &dev, &netdev);
321 	if (err)
322 		return err;
323 
324 	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
325 	if (!msg)
326 		goto out_err;
327 
328 	if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
329 		goto out_free;
330 
331 	dev_put(netdev);
332 	cfg80211_put_dev(dev);
333 
334 	return genlmsg_unicast(msg, info->snd_pid);
335 
336  out_free:
337 	nlmsg_free(msg);
338  out_err:
339 	dev_put(netdev);
340 	cfg80211_put_dev(dev);
341 	return -ENOBUFS;
342 }
343 
344 static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
345 	[NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
346 	[NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
347 	[NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
348 	[NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
349 	[NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
350 };
351 
352 static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
353 {
354 	struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
355 	int flag;
356 
357 	*mntrflags = 0;
358 
359 	if (!nla)
360 		return -EINVAL;
361 
362 	if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
363 			     nla, mntr_flags_policy))
364 		return -EINVAL;
365 
366 	for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
367 		if (flags[flag])
368 			*mntrflags |= (1<<flag);
369 
370 	return 0;
371 }
372 
373 static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
374 {
375 	struct cfg80211_registered_device *drv;
376 	struct vif_params params;
377 	int err, ifindex;
378 	enum nl80211_iftype type;
379 	struct net_device *dev;
380 	u32 flags;
381 
382 	memset(&params, 0, sizeof(params));
383 
384 	if (info->attrs[NL80211_ATTR_IFTYPE]) {
385 		type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
386 		if (type > NL80211_IFTYPE_MAX)
387 			return -EINVAL;
388 	} else
389 		return -EINVAL;
390 
391 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
392 	if (err)
393 		return err;
394 	ifindex = dev->ifindex;
395 	dev_put(dev);
396 
397 	if (!drv->ops->change_virtual_intf) {
398 		err = -EOPNOTSUPP;
399 		goto unlock;
400 	}
401 
402 	if (type == NL80211_IFTYPE_MESH_POINT &&
403 	    info->attrs[NL80211_ATTR_MESH_ID]) {
404 		params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
405 		params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
406 	}
407 
408 	rtnl_lock();
409 	err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
410 				  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
411 				  &flags);
412 	err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
413 					    type, err ? NULL : &flags, &params);
414 	rtnl_unlock();
415 
416  unlock:
417 	cfg80211_put_dev(drv);
418 	return err;
419 }
420 
421 static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
422 {
423 	struct cfg80211_registered_device *drv;
424 	struct vif_params params;
425 	int err;
426 	enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
427 	u32 flags;
428 
429 	memset(&params, 0, sizeof(params));
430 
431 	if (!info->attrs[NL80211_ATTR_IFNAME])
432 		return -EINVAL;
433 
434 	if (info->attrs[NL80211_ATTR_IFTYPE]) {
435 		type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
436 		if (type > NL80211_IFTYPE_MAX)
437 			return -EINVAL;
438 	}
439 
440 	drv = cfg80211_get_dev_from_info(info);
441 	if (IS_ERR(drv))
442 		return PTR_ERR(drv);
443 
444 	if (!drv->ops->add_virtual_intf) {
445 		err = -EOPNOTSUPP;
446 		goto unlock;
447 	}
448 
449 	if (type == NL80211_IFTYPE_MESH_POINT &&
450 	    info->attrs[NL80211_ATTR_MESH_ID]) {
451 		params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
452 		params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
453 	}
454 
455 	rtnl_lock();
456 	err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
457 				  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
458 				  &flags);
459 	err = drv->ops->add_virtual_intf(&drv->wiphy,
460 		nla_data(info->attrs[NL80211_ATTR_IFNAME]),
461 		type, err ? NULL : &flags, &params);
462 	rtnl_unlock();
463 
464 
465  unlock:
466 	cfg80211_put_dev(drv);
467 	return err;
468 }
469 
470 static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
471 {
472 	struct cfg80211_registered_device *drv;
473 	int ifindex, err;
474 	struct net_device *dev;
475 
476 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
477 	if (err)
478 		return err;
479 	ifindex = dev->ifindex;
480 	dev_put(dev);
481 
482 	if (!drv->ops->del_virtual_intf) {
483 		err = -EOPNOTSUPP;
484 		goto out;
485 	}
486 
487 	rtnl_lock();
488 	err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
489 	rtnl_unlock();
490 
491  out:
492 	cfg80211_put_dev(drv);
493 	return err;
494 }
495 
496 struct get_key_cookie {
497 	struct sk_buff *msg;
498 	int error;
499 };
500 
501 static void get_key_callback(void *c, struct key_params *params)
502 {
503 	struct get_key_cookie *cookie = c;
504 
505 	if (params->key)
506 		NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
507 			params->key_len, params->key);
508 
509 	if (params->seq)
510 		NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
511 			params->seq_len, params->seq);
512 
513 	if (params->cipher)
514 		NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
515 			    params->cipher);
516 
517 	return;
518  nla_put_failure:
519 	cookie->error = 1;
520 }
521 
522 static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
523 {
524 	struct cfg80211_registered_device *drv;
525 	int err;
526 	struct net_device *dev;
527 	u8 key_idx = 0;
528 	u8 *mac_addr = NULL;
529 	struct get_key_cookie cookie = {
530 		.error = 0,
531 	};
532 	void *hdr;
533 	struct sk_buff *msg;
534 
535 	if (info->attrs[NL80211_ATTR_KEY_IDX])
536 		key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
537 
538 	if (key_idx > 3)
539 		return -EINVAL;
540 
541 	if (info->attrs[NL80211_ATTR_MAC])
542 		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
543 
544 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
545 	if (err)
546 		return err;
547 
548 	if (!drv->ops->get_key) {
549 		err = -EOPNOTSUPP;
550 		goto out;
551 	}
552 
553 	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
554 	if (!msg) {
555 		err = -ENOMEM;
556 		goto out;
557 	}
558 
559 	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
560 			     NL80211_CMD_NEW_KEY);
561 
562 	if (IS_ERR(hdr)) {
563 		err = PTR_ERR(hdr);
564 		goto out;
565 	}
566 
567 	cookie.msg = msg;
568 
569 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
570 	NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
571 	if (mac_addr)
572 		NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
573 
574 	rtnl_lock();
575 	err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
576 				&cookie, get_key_callback);
577 	rtnl_unlock();
578 
579 	if (err)
580 		goto out;
581 
582 	if (cookie.error)
583 		goto nla_put_failure;
584 
585 	genlmsg_end(msg, hdr);
586 	err = genlmsg_unicast(msg, info->snd_pid);
587 	goto out;
588 
589  nla_put_failure:
590 	err = -ENOBUFS;
591 	nlmsg_free(msg);
592  out:
593 	cfg80211_put_dev(drv);
594 	dev_put(dev);
595 	return err;
596 }
597 
598 static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
599 {
600 	struct cfg80211_registered_device *drv;
601 	int err;
602 	struct net_device *dev;
603 	u8 key_idx;
604 
605 	if (!info->attrs[NL80211_ATTR_KEY_IDX])
606 		return -EINVAL;
607 
608 	key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
609 
610 	if (key_idx > 3)
611 		return -EINVAL;
612 
613 	/* currently only support setting default key */
614 	if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
615 		return -EINVAL;
616 
617 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
618 	if (err)
619 		return err;
620 
621 	if (!drv->ops->set_default_key) {
622 		err = -EOPNOTSUPP;
623 		goto out;
624 	}
625 
626 	rtnl_lock();
627 	err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
628 	rtnl_unlock();
629 
630  out:
631 	cfg80211_put_dev(drv);
632 	dev_put(dev);
633 	return err;
634 }
635 
636 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
637 {
638 	struct cfg80211_registered_device *drv;
639 	int err;
640 	struct net_device *dev;
641 	struct key_params params;
642 	u8 key_idx = 0;
643 	u8 *mac_addr = NULL;
644 
645 	memset(&params, 0, sizeof(params));
646 
647 	if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
648 		return -EINVAL;
649 
650 	if (info->attrs[NL80211_ATTR_KEY_DATA]) {
651 		params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
652 		params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
653 	}
654 
655 	if (info->attrs[NL80211_ATTR_KEY_IDX])
656 		key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
657 
658 	params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
659 
660 	if (info->attrs[NL80211_ATTR_MAC])
661 		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
662 
663 	if (key_idx > 3)
664 		return -EINVAL;
665 
666 	/*
667 	 * Disallow pairwise keys with non-zero index unless it's WEP
668 	 * (because current deployments use pairwise WEP keys with
669 	 * non-zero indizes but 802.11i clearly specifies to use zero)
670 	 */
671 	if (mac_addr && key_idx &&
672 	    params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
673 	    params.cipher != WLAN_CIPHER_SUITE_WEP104)
674 		return -EINVAL;
675 
676 	/* TODO: add definitions for the lengths to linux/ieee80211.h */
677 	switch (params.cipher) {
678 	case WLAN_CIPHER_SUITE_WEP40:
679 		if (params.key_len != 5)
680 			return -EINVAL;
681 		break;
682 	case WLAN_CIPHER_SUITE_TKIP:
683 		if (params.key_len != 32)
684 			return -EINVAL;
685 		break;
686 	case WLAN_CIPHER_SUITE_CCMP:
687 		if (params.key_len != 16)
688 			return -EINVAL;
689 		break;
690 	case WLAN_CIPHER_SUITE_WEP104:
691 		if (params.key_len != 13)
692 			return -EINVAL;
693 		break;
694 	default:
695 		return -EINVAL;
696 	}
697 
698 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
699 	if (err)
700 		return err;
701 
702 	if (!drv->ops->add_key) {
703 		err = -EOPNOTSUPP;
704 		goto out;
705 	}
706 
707 	rtnl_lock();
708 	err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
709 	rtnl_unlock();
710 
711  out:
712 	cfg80211_put_dev(drv);
713 	dev_put(dev);
714 	return err;
715 }
716 
717 static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
718 {
719 	struct cfg80211_registered_device *drv;
720 	int err;
721 	struct net_device *dev;
722 	u8 key_idx = 0;
723 	u8 *mac_addr = NULL;
724 
725 	if (info->attrs[NL80211_ATTR_KEY_IDX])
726 		key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
727 
728 	if (key_idx > 3)
729 		return -EINVAL;
730 
731 	if (info->attrs[NL80211_ATTR_MAC])
732 		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
733 
734 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
735 	if (err)
736 		return err;
737 
738 	if (!drv->ops->del_key) {
739 		err = -EOPNOTSUPP;
740 		goto out;
741 	}
742 
743 	rtnl_lock();
744 	err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
745 	rtnl_unlock();
746 
747  out:
748 	cfg80211_put_dev(drv);
749 	dev_put(dev);
750 	return err;
751 }
752 
753 static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
754 {
755         int (*call)(struct wiphy *wiphy, struct net_device *dev,
756 		    struct beacon_parameters *info);
757 	struct cfg80211_registered_device *drv;
758 	int err;
759 	struct net_device *dev;
760 	struct beacon_parameters params;
761 	int haveinfo = 0;
762 
763 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
764 	if (err)
765 		return err;
766 
767 	switch (info->genlhdr->cmd) {
768 	case NL80211_CMD_NEW_BEACON:
769 		/* these are required for NEW_BEACON */
770 		if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
771 		    !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
772 		    !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
773 			err = -EINVAL;
774 			goto out;
775 		}
776 
777 		call = drv->ops->add_beacon;
778 		break;
779 	case NL80211_CMD_SET_BEACON:
780 		call = drv->ops->set_beacon;
781 		break;
782 	default:
783 		WARN_ON(1);
784 		err = -EOPNOTSUPP;
785 		goto out;
786 	}
787 
788 	if (!call) {
789 		err = -EOPNOTSUPP;
790 		goto out;
791 	}
792 
793 	memset(&params, 0, sizeof(params));
794 
795 	if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
796 		params.interval =
797 		    nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
798 		haveinfo = 1;
799 	}
800 
801 	if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
802 		params.dtim_period =
803 		    nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
804 		haveinfo = 1;
805 	}
806 
807 	if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
808 		params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
809 		params.head_len =
810 		    nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
811 		haveinfo = 1;
812 	}
813 
814 	if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
815 		params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
816 		params.tail_len =
817 		    nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
818 		haveinfo = 1;
819 	}
820 
821 	if (!haveinfo) {
822 		err = -EINVAL;
823 		goto out;
824 	}
825 
826 	rtnl_lock();
827 	err = call(&drv->wiphy, dev, &params);
828 	rtnl_unlock();
829 
830  out:
831 	cfg80211_put_dev(drv);
832 	dev_put(dev);
833 	return err;
834 }
835 
836 static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
837 {
838 	struct cfg80211_registered_device *drv;
839 	int err;
840 	struct net_device *dev;
841 
842 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
843 	if (err)
844 		return err;
845 
846 	if (!drv->ops->del_beacon) {
847 		err = -EOPNOTSUPP;
848 		goto out;
849 	}
850 
851 	rtnl_lock();
852 	err = drv->ops->del_beacon(&drv->wiphy, dev);
853 	rtnl_unlock();
854 
855  out:
856 	cfg80211_put_dev(drv);
857 	dev_put(dev);
858 	return err;
859 }
860 
861 static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
862 	[NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
863 	[NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
864 	[NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
865 };
866 
867 static int parse_station_flags(struct nlattr *nla, u32 *staflags)
868 {
869 	struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
870 	int flag;
871 
872 	*staflags = 0;
873 
874 	if (!nla)
875 		return 0;
876 
877 	if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
878 			     nla, sta_flags_policy))
879 		return -EINVAL;
880 
881 	*staflags = STATION_FLAG_CHANGED;
882 
883 	for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
884 		if (flags[flag])
885 			*staflags |= (1<<flag);
886 
887 	return 0;
888 }
889 
890 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
891 				int flags, struct net_device *dev,
892 				u8 *mac_addr, struct station_info *sinfo)
893 {
894 	void *hdr;
895 	struct nlattr *sinfoattr;
896 
897 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
898 	if (!hdr)
899 		return -1;
900 
901 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
902 	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
903 
904 	sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
905 	if (!sinfoattr)
906 		goto nla_put_failure;
907 	if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
908 		NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
909 			    sinfo->inactive_time);
910 	if (sinfo->filled & STATION_INFO_RX_BYTES)
911 		NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES,
912 			    sinfo->rx_bytes);
913 	if (sinfo->filled & STATION_INFO_TX_BYTES)
914 		NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES,
915 			    sinfo->tx_bytes);
916 	if (sinfo->filled & STATION_INFO_LLID)
917 		NLA_PUT_U16(msg, NL80211_STA_INFO_LLID,
918 			    sinfo->llid);
919 	if (sinfo->filled & STATION_INFO_PLID)
920 		NLA_PUT_U16(msg, NL80211_STA_INFO_PLID,
921 			    sinfo->plid);
922 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
923 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
924 			    sinfo->plink_state);
925 
926 	nla_nest_end(msg, sinfoattr);
927 
928 	return genlmsg_end(msg, hdr);
929 
930  nla_put_failure:
931 	return genlmsg_cancel(msg, hdr);
932 }
933 
934 static int nl80211_dump_station(struct sk_buff *skb,
935 		struct netlink_callback *cb)
936 {
937 	int wp_idx = 0;
938 	int if_idx = 0;
939 	int sta_idx = cb->args[2];
940 	int wp_start = cb->args[0];
941 	int if_start = cb->args[1];
942 	struct station_info sinfo;
943 	struct cfg80211_registered_device *dev;
944 	struct wireless_dev *wdev;
945 	u8 mac_addr[ETH_ALEN];
946 	int err;
947 	int exit = 0;
948 
949 	/* TODO: filter by device */
950 	mutex_lock(&cfg80211_drv_mutex);
951 	list_for_each_entry(dev, &cfg80211_drv_list, list) {
952 		if (exit)
953 			break;
954 		if (++wp_idx < wp_start)
955 			continue;
956 		if_idx = 0;
957 
958 		mutex_lock(&dev->devlist_mtx);
959 		list_for_each_entry(wdev, &dev->netdev_list, list) {
960 			if (exit)
961 				break;
962 			if (++if_idx < if_start)
963 				continue;
964 			if (!dev->ops->dump_station)
965 				continue;
966 
967 			for (;; ++sta_idx) {
968 				rtnl_lock();
969 				err = dev->ops->dump_station(&dev->wiphy,
970 						wdev->netdev, sta_idx, mac_addr,
971 						&sinfo);
972 				rtnl_unlock();
973 				if (err) {
974 					sta_idx = 0;
975 					break;
976 				}
977 				if (nl80211_send_station(skb,
978 						NETLINK_CB(cb->skb).pid,
979 						cb->nlh->nlmsg_seq, NLM_F_MULTI,
980 						wdev->netdev, mac_addr,
981 						&sinfo) < 0) {
982 					exit = 1;
983 					break;
984 				}
985 			}
986 		}
987 		mutex_unlock(&dev->devlist_mtx);
988 	}
989 	mutex_unlock(&cfg80211_drv_mutex);
990 
991 	cb->args[0] = wp_idx;
992 	cb->args[1] = if_idx;
993 	cb->args[2] = sta_idx;
994 
995 	return skb->len;
996 }
997 
998 static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
999 {
1000 	struct cfg80211_registered_device *drv;
1001 	int err;
1002 	struct net_device *dev;
1003 	struct station_info sinfo;
1004 	struct sk_buff *msg;
1005 	u8 *mac_addr = NULL;
1006 
1007 	memset(&sinfo, 0, sizeof(sinfo));
1008 
1009 	if (!info->attrs[NL80211_ATTR_MAC])
1010 		return -EINVAL;
1011 
1012 	mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1013 
1014 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1015 	if (err)
1016 		return err;
1017 
1018 	if (!drv->ops->get_station) {
1019 		err = -EOPNOTSUPP;
1020 		goto out;
1021 	}
1022 
1023 	rtnl_lock();
1024 	err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
1025 	rtnl_unlock();
1026 
1027 	if (err)
1028 		goto out;
1029 
1030 	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1031 	if (!msg)
1032 		goto out;
1033 
1034 	if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
1035 				 dev, mac_addr, &sinfo) < 0)
1036 		goto out_free;
1037 
1038 	err = genlmsg_unicast(msg, info->snd_pid);
1039 	goto out;
1040 
1041  out_free:
1042 	nlmsg_free(msg);
1043 
1044  out:
1045 	cfg80211_put_dev(drv);
1046 	dev_put(dev);
1047 	return err;
1048 }
1049 
1050 /*
1051  * Get vlan interface making sure it is on the right wiphy.
1052  */
1053 static int get_vlan(struct nlattr *vlanattr,
1054 		    struct cfg80211_registered_device *rdev,
1055 		    struct net_device **vlan)
1056 {
1057 	*vlan = NULL;
1058 
1059 	if (vlanattr) {
1060 		*vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
1061 		if (!*vlan)
1062 			return -ENODEV;
1063 		if (!(*vlan)->ieee80211_ptr)
1064 			return -EINVAL;
1065 		if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
1066 			return -EINVAL;
1067 	}
1068 	return 0;
1069 }
1070 
1071 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1072 {
1073 	struct cfg80211_registered_device *drv;
1074 	int err;
1075 	struct net_device *dev;
1076 	struct station_parameters params;
1077 	u8 *mac_addr = NULL;
1078 
1079 	memset(&params, 0, sizeof(params));
1080 
1081 	params.listen_interval = -1;
1082 
1083 	if (info->attrs[NL80211_ATTR_STA_AID])
1084 		return -EINVAL;
1085 
1086 	if (!info->attrs[NL80211_ATTR_MAC])
1087 		return -EINVAL;
1088 
1089 	mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1090 
1091 	if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
1092 		params.supported_rates =
1093 			nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1094 		params.supported_rates_len =
1095 			nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1096 	}
1097 
1098 	if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1099 		params.listen_interval =
1100 		    nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1101 
1102 	if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
1103 				&params.station_flags))
1104 		return -EINVAL;
1105 
1106 	if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
1107 		params.plink_action =
1108 		    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
1109 
1110 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1111 	if (err)
1112 		return err;
1113 
1114 	err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1115 	if (err)
1116 		goto out;
1117 
1118 	if (!drv->ops->change_station) {
1119 		err = -EOPNOTSUPP;
1120 		goto out;
1121 	}
1122 
1123 	rtnl_lock();
1124 	err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
1125 	rtnl_unlock();
1126 
1127  out:
1128 	if (params.vlan)
1129 		dev_put(params.vlan);
1130 	cfg80211_put_dev(drv);
1131 	dev_put(dev);
1132 	return err;
1133 }
1134 
1135 static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1136 {
1137 	struct cfg80211_registered_device *drv;
1138 	int err;
1139 	struct net_device *dev;
1140 	struct station_parameters params;
1141 	u8 *mac_addr = NULL;
1142 
1143 	memset(&params, 0, sizeof(params));
1144 
1145 	if (!info->attrs[NL80211_ATTR_MAC])
1146 		return -EINVAL;
1147 
1148 	if (!info->attrs[NL80211_ATTR_STA_AID])
1149 		return -EINVAL;
1150 
1151 	if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1152 		return -EINVAL;
1153 
1154 	if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
1155 		return -EINVAL;
1156 
1157 	mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1158 	params.supported_rates =
1159 		nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1160 	params.supported_rates_len =
1161 		nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1162 	params.listen_interval =
1163 		nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1164 	params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
1165 
1166 	if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
1167 				&params.station_flags))
1168 		return -EINVAL;
1169 
1170 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1171 	if (err)
1172 		return err;
1173 
1174 	err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1175 	if (err)
1176 		goto out;
1177 
1178 	if (!drv->ops->add_station) {
1179 		err = -EOPNOTSUPP;
1180 		goto out;
1181 	}
1182 
1183 	rtnl_lock();
1184 	err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
1185 	rtnl_unlock();
1186 
1187  out:
1188 	if (params.vlan)
1189 		dev_put(params.vlan);
1190 	cfg80211_put_dev(drv);
1191 	dev_put(dev);
1192 	return err;
1193 }
1194 
1195 static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1196 {
1197 	struct cfg80211_registered_device *drv;
1198 	int err;
1199 	struct net_device *dev;
1200 	u8 *mac_addr = NULL;
1201 
1202 	if (info->attrs[NL80211_ATTR_MAC])
1203 		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1204 
1205 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1206 	if (err)
1207 		return err;
1208 
1209 	if (!drv->ops->del_station) {
1210 		err = -EOPNOTSUPP;
1211 		goto out;
1212 	}
1213 
1214 	rtnl_lock();
1215 	err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
1216 	rtnl_unlock();
1217 
1218  out:
1219 	cfg80211_put_dev(drv);
1220 	dev_put(dev);
1221 	return err;
1222 }
1223 
1224 static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
1225 				int flags, struct net_device *dev,
1226 				u8 *dst, u8 *next_hop,
1227 				struct mpath_info *pinfo)
1228 {
1229 	void *hdr;
1230 	struct nlattr *pinfoattr;
1231 
1232 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
1233 	if (!hdr)
1234 		return -1;
1235 
1236 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1237 	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
1238 	NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
1239 
1240 	pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
1241 	if (!pinfoattr)
1242 		goto nla_put_failure;
1243 	if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
1244 		NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
1245 			    pinfo->frame_qlen);
1246 	if (pinfo->filled & MPATH_INFO_DSN)
1247 		NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN,
1248 			    pinfo->dsn);
1249 	if (pinfo->filled & MPATH_INFO_METRIC)
1250 		NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
1251 			    pinfo->metric);
1252 	if (pinfo->filled & MPATH_INFO_EXPTIME)
1253 		NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME,
1254 			    pinfo->exptime);
1255 	if (pinfo->filled & MPATH_INFO_FLAGS)
1256 		NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS,
1257 			    pinfo->flags);
1258 	if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT)
1259 		NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
1260 			    pinfo->discovery_timeout);
1261 	if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES)
1262 		NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
1263 			    pinfo->discovery_retries);
1264 
1265 	nla_nest_end(msg, pinfoattr);
1266 
1267 	return genlmsg_end(msg, hdr);
1268 
1269  nla_put_failure:
1270 	return genlmsg_cancel(msg, hdr);
1271 }
1272 
1273 static int nl80211_dump_mpath(struct sk_buff *skb,
1274 		struct netlink_callback *cb)
1275 {
1276 	int wp_idx = 0;
1277 	int if_idx = 0;
1278 	int sta_idx = cb->args[2];
1279 	int wp_start = cb->args[0];
1280 	int if_start = cb->args[1];
1281 	struct mpath_info pinfo;
1282 	struct cfg80211_registered_device *dev;
1283 	struct wireless_dev *wdev;
1284 	u8 dst[ETH_ALEN];
1285 	u8 next_hop[ETH_ALEN];
1286 	int err;
1287 	int exit = 0;
1288 
1289 	/* TODO: filter by device */
1290 	mutex_lock(&cfg80211_drv_mutex);
1291 	list_for_each_entry(dev, &cfg80211_drv_list, list) {
1292 		if (exit)
1293 			break;
1294 		if (++wp_idx < wp_start)
1295 			continue;
1296 		if_idx = 0;
1297 
1298 		mutex_lock(&dev->devlist_mtx);
1299 		list_for_each_entry(wdev, &dev->netdev_list, list) {
1300 			if (exit)
1301 				break;
1302 			if (++if_idx < if_start)
1303 				continue;
1304 			if (!dev->ops->dump_mpath)
1305 				continue;
1306 
1307 			for (;; ++sta_idx) {
1308 				rtnl_lock();
1309 				err = dev->ops->dump_mpath(&dev->wiphy,
1310 						wdev->netdev, sta_idx, dst,
1311 						next_hop, &pinfo);
1312 				rtnl_unlock();
1313 				if (err) {
1314 					sta_idx = 0;
1315 					break;
1316 				}
1317 				if (nl80211_send_mpath(skb,
1318 						NETLINK_CB(cb->skb).pid,
1319 						cb->nlh->nlmsg_seq, NLM_F_MULTI,
1320 						wdev->netdev, dst, next_hop,
1321 						&pinfo) < 0) {
1322 					exit = 1;
1323 					break;
1324 				}
1325 			}
1326 		}
1327 		mutex_unlock(&dev->devlist_mtx);
1328 	}
1329 	mutex_unlock(&cfg80211_drv_mutex);
1330 
1331 	cb->args[0] = wp_idx;
1332 	cb->args[1] = if_idx;
1333 	cb->args[2] = sta_idx;
1334 
1335 	return skb->len;
1336 }
1337 
1338 static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
1339 {
1340 	struct cfg80211_registered_device *drv;
1341 	int err;
1342 	struct net_device *dev;
1343 	struct mpath_info pinfo;
1344 	struct sk_buff *msg;
1345 	u8 *dst = NULL;
1346 	u8 next_hop[ETH_ALEN];
1347 
1348 	memset(&pinfo, 0, sizeof(pinfo));
1349 
1350 	if (!info->attrs[NL80211_ATTR_MAC])
1351 		return -EINVAL;
1352 
1353 	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1354 
1355 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1356 	if (err)
1357 		return err;
1358 
1359 	if (!drv->ops->get_mpath) {
1360 		err = -EOPNOTSUPP;
1361 		goto out;
1362 	}
1363 
1364 	rtnl_lock();
1365 	err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
1366 	rtnl_unlock();
1367 
1368 	if (err)
1369 		goto out;
1370 
1371 	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1372 	if (!msg)
1373 		goto out;
1374 
1375 	if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
1376 				 dev, dst, next_hop, &pinfo) < 0)
1377 		goto out_free;
1378 
1379 	err = genlmsg_unicast(msg, info->snd_pid);
1380 	goto out;
1381 
1382  out_free:
1383 	nlmsg_free(msg);
1384 
1385  out:
1386 	cfg80211_put_dev(drv);
1387 	dev_put(dev);
1388 	return err;
1389 }
1390 
1391 static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
1392 {
1393 	struct cfg80211_registered_device *drv;
1394 	int err;
1395 	struct net_device *dev;
1396 	u8 *dst = NULL;
1397 	u8 *next_hop = NULL;
1398 
1399 	if (!info->attrs[NL80211_ATTR_MAC])
1400 		return -EINVAL;
1401 
1402 	if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
1403 		return -EINVAL;
1404 
1405 	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1406 	next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1407 
1408 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1409 	if (err)
1410 		return err;
1411 
1412 	if (!drv->ops->change_mpath) {
1413 		err = -EOPNOTSUPP;
1414 		goto out;
1415 	}
1416 
1417 	rtnl_lock();
1418 	err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
1419 	rtnl_unlock();
1420 
1421  out:
1422 	cfg80211_put_dev(drv);
1423 	dev_put(dev);
1424 	return err;
1425 }
1426 static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
1427 {
1428 	struct cfg80211_registered_device *drv;
1429 	int err;
1430 	struct net_device *dev;
1431 	u8 *dst = NULL;
1432 	u8 *next_hop = NULL;
1433 
1434 	if (!info->attrs[NL80211_ATTR_MAC])
1435 		return -EINVAL;
1436 
1437 	if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
1438 		return -EINVAL;
1439 
1440 	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1441 	next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1442 
1443 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1444 	if (err)
1445 		return err;
1446 
1447 	if (!drv->ops->add_mpath) {
1448 		err = -EOPNOTSUPP;
1449 		goto out;
1450 	}
1451 
1452 	rtnl_lock();
1453 	err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
1454 	rtnl_unlock();
1455 
1456  out:
1457 	cfg80211_put_dev(drv);
1458 	dev_put(dev);
1459 	return err;
1460 }
1461 
1462 static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
1463 {
1464 	struct cfg80211_registered_device *drv;
1465 	int err;
1466 	struct net_device *dev;
1467 	u8 *dst = NULL;
1468 
1469 	if (info->attrs[NL80211_ATTR_MAC])
1470 		dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1471 
1472 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1473 	if (err)
1474 		return err;
1475 
1476 	if (!drv->ops->del_mpath) {
1477 		err = -EOPNOTSUPP;
1478 		goto out;
1479 	}
1480 
1481 	rtnl_lock();
1482 	err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
1483 	rtnl_unlock();
1484 
1485  out:
1486 	cfg80211_put_dev(drv);
1487 	dev_put(dev);
1488 	return err;
1489 }
1490 
1491 static struct genl_ops nl80211_ops[] = {
1492 	{
1493 		.cmd = NL80211_CMD_GET_WIPHY,
1494 		.doit = nl80211_get_wiphy,
1495 		.dumpit = nl80211_dump_wiphy,
1496 		.policy = nl80211_policy,
1497 		/* can be retrieved by unprivileged users */
1498 	},
1499 	{
1500 		.cmd = NL80211_CMD_SET_WIPHY,
1501 		.doit = nl80211_set_wiphy,
1502 		.policy = nl80211_policy,
1503 		.flags = GENL_ADMIN_PERM,
1504 	},
1505 	{
1506 		.cmd = NL80211_CMD_GET_INTERFACE,
1507 		.doit = nl80211_get_interface,
1508 		.dumpit = nl80211_dump_interface,
1509 		.policy = nl80211_policy,
1510 		/* can be retrieved by unprivileged users */
1511 	},
1512 	{
1513 		.cmd = NL80211_CMD_SET_INTERFACE,
1514 		.doit = nl80211_set_interface,
1515 		.policy = nl80211_policy,
1516 		.flags = GENL_ADMIN_PERM,
1517 	},
1518 	{
1519 		.cmd = NL80211_CMD_NEW_INTERFACE,
1520 		.doit = nl80211_new_interface,
1521 		.policy = nl80211_policy,
1522 		.flags = GENL_ADMIN_PERM,
1523 	},
1524 	{
1525 		.cmd = NL80211_CMD_DEL_INTERFACE,
1526 		.doit = nl80211_del_interface,
1527 		.policy = nl80211_policy,
1528 		.flags = GENL_ADMIN_PERM,
1529 	},
1530 	{
1531 		.cmd = NL80211_CMD_GET_KEY,
1532 		.doit = nl80211_get_key,
1533 		.policy = nl80211_policy,
1534 		.flags = GENL_ADMIN_PERM,
1535 	},
1536 	{
1537 		.cmd = NL80211_CMD_SET_KEY,
1538 		.doit = nl80211_set_key,
1539 		.policy = nl80211_policy,
1540 		.flags = GENL_ADMIN_PERM,
1541 	},
1542 	{
1543 		.cmd = NL80211_CMD_NEW_KEY,
1544 		.doit = nl80211_new_key,
1545 		.policy = nl80211_policy,
1546 		.flags = GENL_ADMIN_PERM,
1547 	},
1548 	{
1549 		.cmd = NL80211_CMD_DEL_KEY,
1550 		.doit = nl80211_del_key,
1551 		.policy = nl80211_policy,
1552 		.flags = GENL_ADMIN_PERM,
1553 	},
1554 	{
1555 		.cmd = NL80211_CMD_SET_BEACON,
1556 		.policy = nl80211_policy,
1557 		.flags = GENL_ADMIN_PERM,
1558 		.doit = nl80211_addset_beacon,
1559 	},
1560 	{
1561 		.cmd = NL80211_CMD_NEW_BEACON,
1562 		.policy = nl80211_policy,
1563 		.flags = GENL_ADMIN_PERM,
1564 		.doit = nl80211_addset_beacon,
1565 	},
1566 	{
1567 		.cmd = NL80211_CMD_DEL_BEACON,
1568 		.policy = nl80211_policy,
1569 		.flags = GENL_ADMIN_PERM,
1570 		.doit = nl80211_del_beacon,
1571 	},
1572 	{
1573 		.cmd = NL80211_CMD_GET_STATION,
1574 		.doit = nl80211_get_station,
1575 		.dumpit = nl80211_dump_station,
1576 		.policy = nl80211_policy,
1577 		.flags = GENL_ADMIN_PERM,
1578 	},
1579 	{
1580 		.cmd = NL80211_CMD_SET_STATION,
1581 		.doit = nl80211_set_station,
1582 		.policy = nl80211_policy,
1583 		.flags = GENL_ADMIN_PERM,
1584 	},
1585 	{
1586 		.cmd = NL80211_CMD_NEW_STATION,
1587 		.doit = nl80211_new_station,
1588 		.policy = nl80211_policy,
1589 		.flags = GENL_ADMIN_PERM,
1590 	},
1591 	{
1592 		.cmd = NL80211_CMD_DEL_STATION,
1593 		.doit = nl80211_del_station,
1594 		.policy = nl80211_policy,
1595 		.flags = GENL_ADMIN_PERM,
1596 	},
1597 	{
1598 		.cmd = NL80211_CMD_GET_MPATH,
1599 		.doit = nl80211_get_mpath,
1600 		.dumpit = nl80211_dump_mpath,
1601 		.policy = nl80211_policy,
1602 		.flags = GENL_ADMIN_PERM,
1603 	},
1604 	{
1605 		.cmd = NL80211_CMD_SET_MPATH,
1606 		.doit = nl80211_set_mpath,
1607 		.policy = nl80211_policy,
1608 		.flags = GENL_ADMIN_PERM,
1609 	},
1610 	{
1611 		.cmd = NL80211_CMD_NEW_MPATH,
1612 		.doit = nl80211_new_mpath,
1613 		.policy = nl80211_policy,
1614 		.flags = GENL_ADMIN_PERM,
1615 	},
1616 	{
1617 		.cmd = NL80211_CMD_DEL_MPATH,
1618 		.doit = nl80211_del_mpath,
1619 		.policy = nl80211_policy,
1620 		.flags = GENL_ADMIN_PERM,
1621 	},
1622 };
1623 
1624 /* multicast groups */
1625 static struct genl_multicast_group nl80211_config_mcgrp = {
1626 	.name = "config",
1627 };
1628 
1629 /* notification functions */
1630 
1631 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
1632 {
1633 	struct sk_buff *msg;
1634 
1635 	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1636 	if (!msg)
1637 		return;
1638 
1639 	if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
1640 		nlmsg_free(msg);
1641 		return;
1642 	}
1643 
1644 	genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
1645 }
1646 
1647 /* initialisation/exit functions */
1648 
1649 int nl80211_init(void)
1650 {
1651 	int err, i;
1652 
1653 	err = genl_register_family(&nl80211_fam);
1654 	if (err)
1655 		return err;
1656 
1657 	for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
1658 		err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
1659 		if (err)
1660 			goto err_out;
1661 	}
1662 
1663 	err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
1664 	if (err)
1665 		goto err_out;
1666 
1667 	return 0;
1668  err_out:
1669 	genl_unregister_family(&nl80211_fam);
1670 	return err;
1671 }
1672 
1673 void nl80211_exit(void)
1674 {
1675 	genl_unregister_family(&nl80211_fam);
1676 }
1677