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