[NETNS][IPV6] tcp - assign the netns for timewait sockets
[linux-2.6.git] / net / mac80211 / cfg.c
blob6b183a3526b0ae2f4f0b0c703d1686a2d2bc5222
1 /*
2 * mac80211 configuration hooks for cfg80211
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
6 * This file is GPLv2 as found in COPYING.
7 */
9 #include <linux/ieee80211.h>
10 #include <linux/nl80211.h>
11 #include <linux/rtnetlink.h>
12 #include <net/net_namespace.h>
13 #include <linux/rcupdate.h>
14 #include <net/cfg80211.h>
15 #include "ieee80211_i.h"
16 #include "cfg.h"
17 #include "ieee80211_rate.h"
18 #include "mesh.h"
20 static enum ieee80211_if_types
21 nl80211_type_to_mac80211_type(enum nl80211_iftype type)
23 switch (type) {
24 case NL80211_IFTYPE_UNSPECIFIED:
25 return IEEE80211_IF_TYPE_STA;
26 case NL80211_IFTYPE_ADHOC:
27 return IEEE80211_IF_TYPE_IBSS;
28 case NL80211_IFTYPE_STATION:
29 return IEEE80211_IF_TYPE_STA;
30 case NL80211_IFTYPE_MONITOR:
31 return IEEE80211_IF_TYPE_MNTR;
32 #ifdef CONFIG_MAC80211_MESH
33 case NL80211_IFTYPE_MESH_POINT:
34 return IEEE80211_IF_TYPE_MESH_POINT;
35 #endif
36 default:
37 return IEEE80211_IF_TYPE_INVALID;
41 static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
42 enum nl80211_iftype type, u32 *flags,
43 struct vif_params *params)
45 struct ieee80211_local *local = wiphy_priv(wiphy);
46 enum ieee80211_if_types itype;
47 struct net_device *dev;
48 struct ieee80211_sub_if_data *sdata;
49 int err;
51 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
52 return -ENODEV;
54 itype = nl80211_type_to_mac80211_type(type);
55 if (itype == IEEE80211_IF_TYPE_INVALID)
56 return -EINVAL;
58 err = ieee80211_if_add(local->mdev, name, &dev, itype, params);
59 if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags)
60 return err;
62 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
63 sdata->u.mntr_flags = *flags;
64 return 0;
67 static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
69 struct ieee80211_local *local = wiphy_priv(wiphy);
70 struct net_device *dev;
71 char *name;
73 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
74 return -ENODEV;
76 /* we're under RTNL */
77 dev = __dev_get_by_index(&init_net, ifindex);
78 if (!dev)
79 return 0;
81 name = dev->name;
83 return ieee80211_if_remove(local->mdev, name, -1);
86 static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
87 enum nl80211_iftype type, u32 *flags,
88 struct vif_params *params)
90 struct ieee80211_local *local = wiphy_priv(wiphy);
91 struct net_device *dev;
92 enum ieee80211_if_types itype;
93 struct ieee80211_sub_if_data *sdata;
95 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
96 return -ENODEV;
98 /* we're under RTNL */
99 dev = __dev_get_by_index(&init_net, ifindex);
100 if (!dev)
101 return -ENODEV;
103 if (netif_running(dev))
104 return -EBUSY;
106 itype = nl80211_type_to_mac80211_type(type);
107 if (itype == IEEE80211_IF_TYPE_INVALID)
108 return -EINVAL;
110 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
112 if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
113 return -EOPNOTSUPP;
115 ieee80211_if_reinit(dev);
116 ieee80211_if_set_type(dev, itype);
118 if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
119 ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
120 params->mesh_id_len,
121 params->mesh_id);
123 if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags)
124 return 0;
126 sdata->u.mntr_flags = *flags;
127 return 0;
130 static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
131 u8 key_idx, u8 *mac_addr,
132 struct key_params *params)
134 struct ieee80211_sub_if_data *sdata;
135 struct sta_info *sta = NULL;
136 enum ieee80211_key_alg alg;
137 struct ieee80211_key *key;
139 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
141 switch (params->cipher) {
142 case WLAN_CIPHER_SUITE_WEP40:
143 case WLAN_CIPHER_SUITE_WEP104:
144 alg = ALG_WEP;
145 break;
146 case WLAN_CIPHER_SUITE_TKIP:
147 alg = ALG_TKIP;
148 break;
149 case WLAN_CIPHER_SUITE_CCMP:
150 alg = ALG_CCMP;
151 break;
152 default:
153 return -EINVAL;
156 key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
157 if (!key)
158 return -ENOMEM;
160 if (mac_addr) {
161 sta = sta_info_get(sdata->local, mac_addr);
162 if (!sta) {
163 ieee80211_key_free(key);
164 return -ENOENT;
168 ieee80211_key_link(key, sdata, sta);
170 return 0;
173 static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
174 u8 key_idx, u8 *mac_addr)
176 struct ieee80211_sub_if_data *sdata;
177 struct sta_info *sta;
178 int ret;
180 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
182 if (mac_addr) {
183 sta = sta_info_get(sdata->local, mac_addr);
184 if (!sta)
185 return -ENOENT;
187 ret = 0;
188 if (sta->key) {
189 ieee80211_key_free(sta->key);
190 WARN_ON(sta->key);
191 } else
192 ret = -ENOENT;
194 return ret;
197 if (!sdata->keys[key_idx])
198 return -ENOENT;
200 ieee80211_key_free(sdata->keys[key_idx]);
201 WARN_ON(sdata->keys[key_idx]);
203 return 0;
206 static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
207 u8 key_idx, u8 *mac_addr, void *cookie,
208 void (*callback)(void *cookie,
209 struct key_params *params))
211 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
212 struct sta_info *sta = NULL;
213 u8 seq[6] = {0};
214 struct key_params params;
215 struct ieee80211_key *key;
216 u32 iv32;
217 u16 iv16;
218 int err = -ENOENT;
220 if (mac_addr) {
221 sta = sta_info_get(sdata->local, mac_addr);
222 if (!sta)
223 goto out;
225 key = sta->key;
226 } else
227 key = sdata->keys[key_idx];
229 if (!key)
230 goto out;
232 memset(&params, 0, sizeof(params));
234 switch (key->conf.alg) {
235 case ALG_TKIP:
236 params.cipher = WLAN_CIPHER_SUITE_TKIP;
238 iv32 = key->u.tkip.iv32;
239 iv16 = key->u.tkip.iv16;
241 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
242 sdata->local->ops->get_tkip_seq)
243 sdata->local->ops->get_tkip_seq(
244 local_to_hw(sdata->local),
245 key->conf.hw_key_idx,
246 &iv32, &iv16);
248 seq[0] = iv16 & 0xff;
249 seq[1] = (iv16 >> 8) & 0xff;
250 seq[2] = iv32 & 0xff;
251 seq[3] = (iv32 >> 8) & 0xff;
252 seq[4] = (iv32 >> 16) & 0xff;
253 seq[5] = (iv32 >> 24) & 0xff;
254 params.seq = seq;
255 params.seq_len = 6;
256 break;
257 case ALG_CCMP:
258 params.cipher = WLAN_CIPHER_SUITE_CCMP;
259 seq[0] = key->u.ccmp.tx_pn[5];
260 seq[1] = key->u.ccmp.tx_pn[4];
261 seq[2] = key->u.ccmp.tx_pn[3];
262 seq[3] = key->u.ccmp.tx_pn[2];
263 seq[4] = key->u.ccmp.tx_pn[1];
264 seq[5] = key->u.ccmp.tx_pn[0];
265 params.seq = seq;
266 params.seq_len = 6;
267 break;
268 case ALG_WEP:
269 if (key->conf.keylen == 5)
270 params.cipher = WLAN_CIPHER_SUITE_WEP40;
271 else
272 params.cipher = WLAN_CIPHER_SUITE_WEP104;
273 break;
276 params.key = key->conf.key;
277 params.key_len = key->conf.keylen;
279 callback(cookie, &params);
280 err = 0;
282 out:
283 return err;
286 static int ieee80211_config_default_key(struct wiphy *wiphy,
287 struct net_device *dev,
288 u8 key_idx)
290 struct ieee80211_sub_if_data *sdata;
292 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
293 ieee80211_set_default_key(sdata, key_idx);
295 return 0;
298 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
300 struct ieee80211_sub_if_data *sdata = sta->sdata;
302 sinfo->filled = STATION_INFO_INACTIVE_TIME |
303 STATION_INFO_RX_BYTES |
304 STATION_INFO_TX_BYTES;
306 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
307 sinfo->rx_bytes = sta->rx_bytes;
308 sinfo->tx_bytes = sta->tx_bytes;
310 if (ieee80211_vif_is_mesh(&sdata->vif)) {
311 #ifdef CONFIG_MAC80211_MESH
312 sinfo->filled |= STATION_INFO_LLID |
313 STATION_INFO_PLID |
314 STATION_INFO_PLINK_STATE;
316 sinfo->llid = le16_to_cpu(sta->llid);
317 sinfo->plid = le16_to_cpu(sta->plid);
318 sinfo->plink_state = sta->plink_state;
319 #endif
324 static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
325 int idx, u8 *mac, struct station_info *sinfo)
327 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
328 struct sta_info *sta;
329 int ret = -ENOENT;
331 rcu_read_lock();
333 sta = sta_info_get_by_idx(local, idx, dev);
334 if (sta) {
335 ret = 0;
336 memcpy(mac, sta->addr, ETH_ALEN);
337 sta_set_sinfo(sta, sinfo);
340 rcu_read_unlock();
342 return ret;
345 static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
346 u8 *mac, struct station_info *sinfo)
348 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
349 struct sta_info *sta;
350 int ret = -ENOENT;
352 rcu_read_lock();
354 /* XXX: verify sta->dev == dev */
356 sta = sta_info_get(local, mac);
357 if (sta) {
358 ret = 0;
359 sta_set_sinfo(sta, sinfo);
362 rcu_read_unlock();
364 return ret;
368 * This handles both adding a beacon and setting new beacon info
370 static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
371 struct beacon_parameters *params)
373 struct beacon_data *new, *old;
374 int new_head_len, new_tail_len;
375 int size;
376 int err = -EINVAL;
378 old = sdata->u.ap.beacon;
380 /* head must not be zero-length */
381 if (params->head && !params->head_len)
382 return -EINVAL;
385 * This is a kludge. beacon interval should really be part
386 * of the beacon information.
388 if (params->interval) {
389 sdata->local->hw.conf.beacon_int = params->interval;
390 if (ieee80211_hw_config(sdata->local))
391 return -EINVAL;
393 * We updated some parameter so if below bails out
394 * it's not an error.
396 err = 0;
399 /* Need to have a beacon head if we don't have one yet */
400 if (!params->head && !old)
401 return err;
403 /* sorry, no way to start beaconing without dtim period */
404 if (!params->dtim_period && !old)
405 return err;
407 /* new or old head? */
408 if (params->head)
409 new_head_len = params->head_len;
410 else
411 new_head_len = old->head_len;
413 /* new or old tail? */
414 if (params->tail || !old)
415 /* params->tail_len will be zero for !params->tail */
416 new_tail_len = params->tail_len;
417 else
418 new_tail_len = old->tail_len;
420 size = sizeof(*new) + new_head_len + new_tail_len;
422 new = kzalloc(size, GFP_KERNEL);
423 if (!new)
424 return -ENOMEM;
426 /* start filling the new info now */
428 /* new or old dtim period? */
429 if (params->dtim_period)
430 new->dtim_period = params->dtim_period;
431 else
432 new->dtim_period = old->dtim_period;
435 * pointers go into the block we allocated,
436 * memory is | beacon_data | head | tail |
438 new->head = ((u8 *) new) + sizeof(*new);
439 new->tail = new->head + new_head_len;
440 new->head_len = new_head_len;
441 new->tail_len = new_tail_len;
443 /* copy in head */
444 if (params->head)
445 memcpy(new->head, params->head, new_head_len);
446 else
447 memcpy(new->head, old->head, new_head_len);
449 /* copy in optional tail */
450 if (params->tail)
451 memcpy(new->tail, params->tail, new_tail_len);
452 else
453 if (old)
454 memcpy(new->tail, old->tail, new_tail_len);
456 rcu_assign_pointer(sdata->u.ap.beacon, new);
458 synchronize_rcu();
460 kfree(old);
462 return ieee80211_if_config_beacon(sdata->dev);
465 static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
466 struct beacon_parameters *params)
468 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
469 struct beacon_data *old;
471 if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
472 return -EINVAL;
474 old = sdata->u.ap.beacon;
476 if (old)
477 return -EALREADY;
479 return ieee80211_config_beacon(sdata, params);
482 static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
483 struct beacon_parameters *params)
485 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
486 struct beacon_data *old;
488 if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
489 return -EINVAL;
491 old = sdata->u.ap.beacon;
493 if (!old)
494 return -ENOENT;
496 return ieee80211_config_beacon(sdata, params);
499 static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
501 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
502 struct beacon_data *old;
504 if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
505 return -EINVAL;
507 old = sdata->u.ap.beacon;
509 if (!old)
510 return -ENOENT;
512 rcu_assign_pointer(sdata->u.ap.beacon, NULL);
513 synchronize_rcu();
514 kfree(old);
516 return ieee80211_if_config_beacon(dev);
519 /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
520 struct iapp_layer2_update {
521 u8 da[ETH_ALEN]; /* broadcast */
522 u8 sa[ETH_ALEN]; /* STA addr */
523 __be16 len; /* 6 */
524 u8 dsap; /* 0 */
525 u8 ssap; /* 0 */
526 u8 control;
527 u8 xid_info[3];
528 } __attribute__ ((packed));
530 static void ieee80211_send_layer2_update(struct sta_info *sta)
532 struct iapp_layer2_update *msg;
533 struct sk_buff *skb;
535 /* Send Level 2 Update Frame to update forwarding tables in layer 2
536 * bridge devices */
538 skb = dev_alloc_skb(sizeof(*msg));
539 if (!skb)
540 return;
541 msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
543 /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
544 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
546 memset(msg->da, 0xff, ETH_ALEN);
547 memcpy(msg->sa, sta->addr, ETH_ALEN);
548 msg->len = htons(6);
549 msg->dsap = 0;
550 msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
551 msg->control = 0xaf; /* XID response lsb.1111F101.
552 * F=0 (no poll command; unsolicited frame) */
553 msg->xid_info[0] = 0x81; /* XID format identifier */
554 msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
555 msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
557 skb->dev = sta->sdata->dev;
558 skb->protocol = eth_type_trans(skb, sta->sdata->dev);
559 memset(skb->cb, 0, sizeof(skb->cb));
560 netif_rx(skb);
563 static void sta_apply_parameters(struct ieee80211_local *local,
564 struct sta_info *sta,
565 struct station_parameters *params)
567 u32 rates;
568 int i, j;
569 struct ieee80211_supported_band *sband;
570 struct ieee80211_sub_if_data *sdata = sta->sdata;
573 * FIXME: updating the flags is racy when this function is
574 * called from ieee80211_change_station(), this will
575 * be resolved in a future patch.
578 if (params->station_flags & STATION_FLAG_CHANGED) {
579 sta->flags &= ~WLAN_STA_AUTHORIZED;
580 if (params->station_flags & STATION_FLAG_AUTHORIZED)
581 sta->flags |= WLAN_STA_AUTHORIZED;
583 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
584 if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE)
585 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
587 sta->flags &= ~WLAN_STA_WME;
588 if (params->station_flags & STATION_FLAG_WME)
589 sta->flags |= WLAN_STA_WME;
593 * FIXME: updating the following information is racy when this
594 * function is called from ieee80211_change_station().
595 * However, all this information should be static so
596 * maybe we should just reject attemps to change it.
599 if (params->aid) {
600 sta->aid = params->aid;
601 if (sta->aid > IEEE80211_MAX_AID)
602 sta->aid = 0; /* XXX: should this be an error? */
605 if (params->listen_interval >= 0)
606 sta->listen_interval = params->listen_interval;
608 if (params->supported_rates) {
609 rates = 0;
610 sband = local->hw.wiphy->bands[local->oper_channel->band];
612 for (i = 0; i < params->supported_rates_len; i++) {
613 int rate = (params->supported_rates[i] & 0x7f) * 5;
614 for (j = 0; j < sband->n_bitrates; j++) {
615 if (sband->bitrates[j].bitrate == rate)
616 rates |= BIT(j);
619 sta->supp_rates[local->oper_channel->band] = rates;
622 if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
623 switch (params->plink_action) {
624 case PLINK_ACTION_OPEN:
625 mesh_plink_open(sta);
626 break;
627 case PLINK_ACTION_BLOCK:
628 mesh_plink_block(sta);
629 break;
634 static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
635 u8 *mac, struct station_parameters *params)
637 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
638 struct sta_info *sta;
639 struct ieee80211_sub_if_data *sdata;
640 int err;
642 /* Prevent a race with changing the rate control algorithm */
643 if (!netif_running(dev))
644 return -ENETDOWN;
646 if (params->vlan) {
647 sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
649 if (sdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
650 sdata->vif.type != IEEE80211_IF_TYPE_AP)
651 return -EINVAL;
652 } else
653 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
655 if (compare_ether_addr(mac, dev->dev_addr) == 0)
656 return -EINVAL;
658 if (is_multicast_ether_addr(mac))
659 return -EINVAL;
661 sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
662 if (!sta)
663 return -ENOMEM;
665 sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
667 sta_apply_parameters(local, sta, params);
669 rate_control_rate_init(sta, local);
671 rcu_read_lock();
673 err = sta_info_insert(sta);
674 if (err) {
675 sta_info_destroy(sta);
676 rcu_read_unlock();
677 return err;
680 if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
681 sdata->vif.type == IEEE80211_IF_TYPE_AP)
682 ieee80211_send_layer2_update(sta);
684 rcu_read_unlock();
686 return 0;
689 static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
690 u8 *mac)
692 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
693 struct ieee80211_local *local = sdata->local;
694 struct sta_info *sta;
696 if (mac) {
697 /* XXX: get sta belonging to dev */
698 sta = sta_info_get(local, mac);
699 if (!sta)
700 return -ENOENT;
702 sta_info_unlink(&sta);
704 if (sta) {
705 synchronize_rcu();
706 sta_info_destroy(sta);
708 } else
709 sta_info_flush(local, sdata);
711 return 0;
714 static int ieee80211_change_station(struct wiphy *wiphy,
715 struct net_device *dev,
716 u8 *mac,
717 struct station_parameters *params)
719 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
720 struct sta_info *sta;
721 struct ieee80211_sub_if_data *vlansdata;
723 /* XXX: get sta belonging to dev */
724 sta = sta_info_get(local, mac);
725 if (!sta)
726 return -ENOENT;
728 if (params->vlan && params->vlan != sta->sdata->dev) {
729 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
731 if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
732 vlansdata->vif.type != IEEE80211_IF_TYPE_AP)
733 return -EINVAL;
735 sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
736 ieee80211_send_layer2_update(sta);
739 sta_apply_parameters(local, sta, params);
741 return 0;
744 #ifdef CONFIG_MAC80211_MESH
745 static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
746 u8 *dst, u8 *next_hop)
748 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
749 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
750 struct mesh_path *mpath;
751 struct sta_info *sta;
752 int err;
754 if (!netif_running(dev))
755 return -ENETDOWN;
757 if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
758 return -ENOTSUPP;
760 rcu_read_lock();
761 sta = sta_info_get(local, next_hop);
762 if (!sta) {
763 rcu_read_unlock();
764 return -ENOENT;
767 err = mesh_path_add(dst, dev);
768 if (err) {
769 rcu_read_unlock();
770 return err;
773 mpath = mesh_path_lookup(dst, dev);
774 if (!mpath) {
775 rcu_read_unlock();
776 return -ENXIO;
778 mesh_path_fix_nexthop(mpath, sta);
780 rcu_read_unlock();
781 return 0;
784 static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
785 u8 *dst)
787 if (dst)
788 return mesh_path_del(dst, dev);
790 mesh_path_flush(dev);
791 return 0;
794 static int ieee80211_change_mpath(struct wiphy *wiphy,
795 struct net_device *dev,
796 u8 *dst, u8 *next_hop)
798 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
799 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
800 struct mesh_path *mpath;
801 struct sta_info *sta;
803 if (!netif_running(dev))
804 return -ENETDOWN;
806 if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
807 return -ENOTSUPP;
809 rcu_read_lock();
811 sta = sta_info_get(local, next_hop);
812 if (!sta) {
813 rcu_read_unlock();
814 return -ENOENT;
817 mpath = mesh_path_lookup(dst, dev);
818 if (!mpath) {
819 rcu_read_unlock();
820 return -ENOENT;
823 mesh_path_fix_nexthop(mpath, sta);
825 rcu_read_unlock();
826 return 0;
829 static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
830 struct mpath_info *pinfo)
832 if (mpath->next_hop)
833 memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
834 else
835 memset(next_hop, 0, ETH_ALEN);
837 pinfo->filled = MPATH_INFO_FRAME_QLEN |
838 MPATH_INFO_DSN |
839 MPATH_INFO_METRIC |
840 MPATH_INFO_EXPTIME |
841 MPATH_INFO_DISCOVERY_TIMEOUT |
842 MPATH_INFO_DISCOVERY_RETRIES |
843 MPATH_INFO_FLAGS;
845 pinfo->frame_qlen = mpath->frame_queue.qlen;
846 pinfo->dsn = mpath->dsn;
847 pinfo->metric = mpath->metric;
848 if (time_before(jiffies, mpath->exp_time))
849 pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
850 pinfo->discovery_timeout =
851 jiffies_to_msecs(mpath->discovery_timeout);
852 pinfo->discovery_retries = mpath->discovery_retries;
853 pinfo->flags = 0;
854 if (mpath->flags & MESH_PATH_ACTIVE)
855 pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
856 if (mpath->flags & MESH_PATH_RESOLVING)
857 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
858 if (mpath->flags & MESH_PATH_DSN_VALID)
859 pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
860 if (mpath->flags & MESH_PATH_FIXED)
861 pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
862 if (mpath->flags & MESH_PATH_RESOLVING)
863 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
865 pinfo->flags = mpath->flags;
868 static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
869 u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
872 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
873 struct mesh_path *mpath;
875 if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
876 return -ENOTSUPP;
878 rcu_read_lock();
879 mpath = mesh_path_lookup(dst, dev);
880 if (!mpath) {
881 rcu_read_unlock();
882 return -ENOENT;
884 memcpy(dst, mpath->dst, ETH_ALEN);
885 mpath_set_pinfo(mpath, next_hop, pinfo);
886 rcu_read_unlock();
887 return 0;
890 static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
891 int idx, u8 *dst, u8 *next_hop,
892 struct mpath_info *pinfo)
894 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
895 struct mesh_path *mpath;
897 if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
898 return -ENOTSUPP;
900 rcu_read_lock();
901 mpath = mesh_path_lookup_by_idx(idx, dev);
902 if (!mpath) {
903 rcu_read_unlock();
904 return -ENOENT;
906 memcpy(dst, mpath->dst, ETH_ALEN);
907 mpath_set_pinfo(mpath, next_hop, pinfo);
908 rcu_read_unlock();
909 return 0;
911 #endif
913 struct cfg80211_ops mac80211_config_ops = {
914 .add_virtual_intf = ieee80211_add_iface,
915 .del_virtual_intf = ieee80211_del_iface,
916 .change_virtual_intf = ieee80211_change_iface,
917 .add_key = ieee80211_add_key,
918 .del_key = ieee80211_del_key,
919 .get_key = ieee80211_get_key,
920 .set_default_key = ieee80211_config_default_key,
921 .add_beacon = ieee80211_add_beacon,
922 .set_beacon = ieee80211_set_beacon,
923 .del_beacon = ieee80211_del_beacon,
924 .add_station = ieee80211_add_station,
925 .del_station = ieee80211_del_station,
926 .change_station = ieee80211_change_station,
927 .get_station = ieee80211_get_station,
928 .dump_station = ieee80211_dump_station,
929 #ifdef CONFIG_MAC80211_MESH
930 .add_mpath = ieee80211_add_mpath,
931 .del_mpath = ieee80211_del_mpath,
932 .change_mpath = ieee80211_change_mpath,
933 .get_mpath = ieee80211_get_mpath,
934 .dump_mpath = ieee80211_dump_mpath,
935 #endif