2 * mac80211 configuration hooks for cfg80211
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
6 * This file is GPLv2 as found in COPYING.
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"
17 #include "ieee80211_rate.h"
18 #ifdef CONFIG_MAC80211_MESH
22 #define DEFAULT_RATES 0
24 static enum ieee80211_if_types
25 nl80211_type_to_mac80211_type(enum nl80211_iftype type
)
28 case NL80211_IFTYPE_UNSPECIFIED
:
29 return IEEE80211_IF_TYPE_STA
;
30 case NL80211_IFTYPE_ADHOC
:
31 return IEEE80211_IF_TYPE_IBSS
;
32 case NL80211_IFTYPE_STATION
:
33 return IEEE80211_IF_TYPE_STA
;
34 case NL80211_IFTYPE_MONITOR
:
35 return IEEE80211_IF_TYPE_MNTR
;
36 #ifdef CONFIG_MAC80211_MESH
37 case NL80211_IFTYPE_MESH_POINT
:
38 return IEEE80211_IF_TYPE_MESH_POINT
;
41 return IEEE80211_IF_TYPE_INVALID
;
45 static int ieee80211_add_iface(struct wiphy
*wiphy
, char *name
,
46 enum nl80211_iftype type
, u32
*flags
,
47 struct vif_params
*params
)
49 struct ieee80211_local
*local
= wiphy_priv(wiphy
);
50 enum ieee80211_if_types itype
;
51 struct net_device
*dev
;
52 struct ieee80211_sub_if_data
*sdata
;
55 if (unlikely(local
->reg_state
!= IEEE80211_DEV_REGISTERED
))
58 itype
= nl80211_type_to_mac80211_type(type
);
59 if (itype
== IEEE80211_IF_TYPE_INVALID
)
62 err
= ieee80211_if_add(local
->mdev
, name
, &dev
, itype
, params
);
63 if (err
|| itype
!= IEEE80211_IF_TYPE_MNTR
|| !flags
)
66 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
67 sdata
->u
.mntr_flags
= *flags
;
71 static int ieee80211_del_iface(struct wiphy
*wiphy
, int ifindex
)
73 struct ieee80211_local
*local
= wiphy_priv(wiphy
);
74 struct net_device
*dev
;
77 if (unlikely(local
->reg_state
!= IEEE80211_DEV_REGISTERED
))
80 /* we're under RTNL */
81 dev
= __dev_get_by_index(&init_net
, ifindex
);
87 return ieee80211_if_remove(local
->mdev
, name
, -1);
90 static int ieee80211_change_iface(struct wiphy
*wiphy
, int ifindex
,
91 enum nl80211_iftype type
, u32
*flags
,
92 struct vif_params
*params
)
94 struct ieee80211_local
*local
= wiphy_priv(wiphy
);
95 struct net_device
*dev
;
96 enum ieee80211_if_types itype
;
97 struct ieee80211_sub_if_data
*sdata
;
99 if (unlikely(local
->reg_state
!= IEEE80211_DEV_REGISTERED
))
102 /* we're under RTNL */
103 dev
= __dev_get_by_index(&init_net
, ifindex
);
107 if (netif_running(dev
))
110 itype
= nl80211_type_to_mac80211_type(type
);
111 if (itype
== IEEE80211_IF_TYPE_INVALID
)
114 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
116 if (sdata
->vif
.type
== IEEE80211_IF_TYPE_VLAN
)
119 ieee80211_if_reinit(dev
);
120 ieee80211_if_set_type(dev
, itype
);
122 #ifdef CONFIG_MAC80211_MESH
123 if (sdata
->vif
.type
== IEEE80211_IF_TYPE_MESH_POINT
&&
124 params
->mesh_id_len
) {
125 sdata
->u
.sta
.mesh_id_len
= params
->mesh_id_len
;
126 memcpy(sdata
->u
.sta
.mesh_id
, params
->mesh_id
,
127 params
->mesh_id_len
);
131 if (sdata
->vif
.type
!= IEEE80211_IF_TYPE_MNTR
|| !flags
)
134 sdata
->u
.mntr_flags
= *flags
;
138 static int ieee80211_add_key(struct wiphy
*wiphy
, struct net_device
*dev
,
139 u8 key_idx
, u8
*mac_addr
,
140 struct key_params
*params
)
142 struct ieee80211_sub_if_data
*sdata
;
143 struct sta_info
*sta
= NULL
;
144 enum ieee80211_key_alg alg
;
146 struct ieee80211_key
*key
;
148 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
150 switch (params
->cipher
) {
151 case WLAN_CIPHER_SUITE_WEP40
:
152 case WLAN_CIPHER_SUITE_WEP104
:
155 case WLAN_CIPHER_SUITE_TKIP
:
158 case WLAN_CIPHER_SUITE_CCMP
:
165 key
= ieee80211_key_alloc(alg
, key_idx
, params
->key_len
, params
->key
);
170 sta
= sta_info_get(sdata
->local
, mac_addr
);
172 ieee80211_key_free(key
);
177 ieee80211_key_link(key
, sdata
, sta
);
187 static int ieee80211_del_key(struct wiphy
*wiphy
, struct net_device
*dev
,
188 u8 key_idx
, u8
*mac_addr
)
190 struct ieee80211_sub_if_data
*sdata
;
191 struct sta_info
*sta
;
193 struct ieee80211_key
*key
;
195 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
198 sta
= sta_info_get(sdata
->local
, mac_addr
);
205 ieee80211_key_free(key
);
214 if (!sdata
->keys
[key_idx
])
217 key
= sdata
->keys
[key_idx
];
218 ieee80211_key_free(key
);
219 WARN_ON(sdata
->keys
[key_idx
]);
224 static int ieee80211_get_key(struct wiphy
*wiphy
, struct net_device
*dev
,
225 u8 key_idx
, u8
*mac_addr
, void *cookie
,
226 void (*callback
)(void *cookie
,
227 struct key_params
*params
))
229 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
230 struct sta_info
*sta
= NULL
;
232 struct key_params params
;
233 struct ieee80211_key
*key
;
239 sta
= sta_info_get(sdata
->local
, mac_addr
);
245 key
= sdata
->keys
[key_idx
];
250 memset(¶ms
, 0, sizeof(params
));
252 switch (key
->conf
.alg
) {
254 params
.cipher
= WLAN_CIPHER_SUITE_TKIP
;
256 iv32
= key
->u
.tkip
.iv32
;
257 iv16
= key
->u
.tkip
.iv16
;
259 if (key
->flags
& KEY_FLAG_UPLOADED_TO_HARDWARE
&&
260 sdata
->local
->ops
->get_tkip_seq
)
261 sdata
->local
->ops
->get_tkip_seq(
262 local_to_hw(sdata
->local
),
263 key
->conf
.hw_key_idx
,
266 seq
[0] = iv16
& 0xff;
267 seq
[1] = (iv16
>> 8) & 0xff;
268 seq
[2] = iv32
& 0xff;
269 seq
[3] = (iv32
>> 8) & 0xff;
270 seq
[4] = (iv32
>> 16) & 0xff;
271 seq
[5] = (iv32
>> 24) & 0xff;
276 params
.cipher
= WLAN_CIPHER_SUITE_CCMP
;
277 seq
[0] = key
->u
.ccmp
.tx_pn
[5];
278 seq
[1] = key
->u
.ccmp
.tx_pn
[4];
279 seq
[2] = key
->u
.ccmp
.tx_pn
[3];
280 seq
[3] = key
->u
.ccmp
.tx_pn
[2];
281 seq
[4] = key
->u
.ccmp
.tx_pn
[1];
282 seq
[5] = key
->u
.ccmp
.tx_pn
[0];
287 if (key
->conf
.keylen
== 5)
288 params
.cipher
= WLAN_CIPHER_SUITE_WEP40
;
290 params
.cipher
= WLAN_CIPHER_SUITE_WEP104
;
294 params
.key
= key
->conf
.key
;
295 params
.key_len
= key
->conf
.keylen
;
297 callback(cookie
, ¶ms
);
306 static int ieee80211_config_default_key(struct wiphy
*wiphy
,
307 struct net_device
*dev
,
310 struct ieee80211_sub_if_data
*sdata
;
312 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
313 ieee80211_set_default_key(sdata
, key_idx
);
318 static void sta_set_sinfo(struct sta_info
*sta
, struct station_info
*sinfo
)
320 #ifdef CONFIG_MAC80211_MESH
321 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(sta
->dev
);
324 sinfo
->filled
= STATION_INFO_INACTIVE_TIME
|
325 STATION_INFO_RX_BYTES
|
326 STATION_INFO_TX_BYTES
;
328 sinfo
->inactive_time
= jiffies_to_msecs(jiffies
- sta
->last_rx
);
329 sinfo
->rx_bytes
= sta
->rx_bytes
;
330 sinfo
->tx_bytes
= sta
->tx_bytes
;
332 #ifdef CONFIG_MAC80211_MESH
333 if (sdata
->vif
.type
== IEEE80211_IF_TYPE_MESH_POINT
) {
334 sinfo
->filled
|= STATION_INFO_LLID
|
336 STATION_INFO_PLINK_STATE
;
338 sinfo
->llid
= le16_to_cpu(sta
->llid
);
339 sinfo
->plid
= le16_to_cpu(sta
->plid
);
340 sinfo
->plink_state
= sta
->plink_state
;
346 static int ieee80211_dump_station(struct wiphy
*wiphy
, struct net_device
*dev
,
347 int idx
, u8
*mac
, struct station_info
*sinfo
)
349 struct ieee80211_local
*local
= wdev_priv(dev
->ieee80211_ptr
);
350 struct sta_info
*sta
;
352 sta
= sta_info_get_by_idx(local
, idx
, dev
);
356 memcpy(mac
, sta
->addr
, ETH_ALEN
);
357 sta_set_sinfo(sta
, sinfo
);
363 static int ieee80211_get_station(struct wiphy
*wiphy
, struct net_device
*dev
,
364 u8
*mac
, struct station_info
*sinfo
)
366 struct ieee80211_local
*local
= wdev_priv(dev
->ieee80211_ptr
);
367 struct sta_info
*sta
;
369 sta
= sta_info_get(local
, mac
);
373 /* XXX: verify sta->dev == dev */
374 sta_set_sinfo(sta
, sinfo
);
381 * This handles both adding a beacon and setting new beacon info
383 static int ieee80211_config_beacon(struct ieee80211_sub_if_data
*sdata
,
384 struct beacon_parameters
*params
)
386 struct beacon_data
*new, *old
;
387 int new_head_len
, new_tail_len
;
391 old
= sdata
->u
.ap
.beacon
;
393 /* head must not be zero-length */
394 if (params
->head
&& !params
->head_len
)
398 * This is a kludge. beacon interval should really be part
399 * of the beacon information.
401 if (params
->interval
) {
402 sdata
->local
->hw
.conf
.beacon_int
= params
->interval
;
403 if (ieee80211_hw_config(sdata
->local
))
406 * We updated some parameter so if below bails out
412 /* Need to have a beacon head if we don't have one yet */
413 if (!params
->head
&& !old
)
416 /* sorry, no way to start beaconing without dtim period */
417 if (!params
->dtim_period
&& !old
)
420 /* new or old head? */
422 new_head_len
= params
->head_len
;
424 new_head_len
= old
->head_len
;
426 /* new or old tail? */
427 if (params
->tail
|| !old
)
428 /* params->tail_len will be zero for !params->tail */
429 new_tail_len
= params
->tail_len
;
431 new_tail_len
= old
->tail_len
;
433 size
= sizeof(*new) + new_head_len
+ new_tail_len
;
435 new = kzalloc(size
, GFP_KERNEL
);
439 /* start filling the new info now */
441 /* new or old dtim period? */
442 if (params
->dtim_period
)
443 new->dtim_period
= params
->dtim_period
;
445 new->dtim_period
= old
->dtim_period
;
448 * pointers go into the block we allocated,
449 * memory is | beacon_data | head | tail |
451 new->head
= ((u8
*) new) + sizeof(*new);
452 new->tail
= new->head
+ new_head_len
;
453 new->head_len
= new_head_len
;
454 new->tail_len
= new_tail_len
;
458 memcpy(new->head
, params
->head
, new_head_len
);
460 memcpy(new->head
, old
->head
, new_head_len
);
462 /* copy in optional tail */
464 memcpy(new->tail
, params
->tail
, new_tail_len
);
467 memcpy(new->tail
, old
->tail
, new_tail_len
);
469 rcu_assign_pointer(sdata
->u
.ap
.beacon
, new);
475 return ieee80211_if_config_beacon(sdata
->dev
);
478 static int ieee80211_add_beacon(struct wiphy
*wiphy
, struct net_device
*dev
,
479 struct beacon_parameters
*params
)
481 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
482 struct beacon_data
*old
;
484 if (sdata
->vif
.type
!= IEEE80211_IF_TYPE_AP
)
487 old
= sdata
->u
.ap
.beacon
;
492 return ieee80211_config_beacon(sdata
, params
);
495 static int ieee80211_set_beacon(struct wiphy
*wiphy
, struct net_device
*dev
,
496 struct beacon_parameters
*params
)
498 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
499 struct beacon_data
*old
;
501 if (sdata
->vif
.type
!= IEEE80211_IF_TYPE_AP
)
504 old
= sdata
->u
.ap
.beacon
;
509 return ieee80211_config_beacon(sdata
, params
);
512 static int ieee80211_del_beacon(struct wiphy
*wiphy
, struct net_device
*dev
)
514 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
515 struct beacon_data
*old
;
517 if (sdata
->vif
.type
!= IEEE80211_IF_TYPE_AP
)
520 old
= sdata
->u
.ap
.beacon
;
525 rcu_assign_pointer(sdata
->u
.ap
.beacon
, NULL
);
529 return ieee80211_if_config_beacon(dev
);
532 /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
533 struct iapp_layer2_update
{
534 u8 da
[ETH_ALEN
]; /* broadcast */
535 u8 sa
[ETH_ALEN
]; /* STA addr */
541 } __attribute__ ((packed
));
543 static void ieee80211_send_layer2_update(struct sta_info
*sta
)
545 struct iapp_layer2_update
*msg
;
548 /* Send Level 2 Update Frame to update forwarding tables in layer 2
551 skb
= dev_alloc_skb(sizeof(*msg
));
554 msg
= (struct iapp_layer2_update
*)skb_put(skb
, sizeof(*msg
));
556 /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
557 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
559 memset(msg
->da
, 0xff, ETH_ALEN
);
560 memcpy(msg
->sa
, sta
->addr
, ETH_ALEN
);
563 msg
->ssap
= 0x01; /* NULL LSAP, CR Bit: Response */
564 msg
->control
= 0xaf; /* XID response lsb.1111F101.
565 * F=0 (no poll command; unsolicited frame) */
566 msg
->xid_info
[0] = 0x81; /* XID format identifier */
567 msg
->xid_info
[1] = 1; /* LLC types/classes: Type 1 LLC */
568 msg
->xid_info
[2] = 0; /* XID sender's receive window size (RW) */
571 skb
->protocol
= eth_type_trans(skb
, sta
->dev
);
572 memset(skb
->cb
, 0, sizeof(skb
->cb
));
576 static void sta_apply_parameters(struct ieee80211_local
*local
,
577 struct sta_info
*sta
,
578 struct station_parameters
*params
)
582 struct ieee80211_supported_band
*sband
;
583 #ifdef CONFIG_MAC80211_MESH
584 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(sta
->dev
);
587 if (params
->station_flags
& STATION_FLAG_CHANGED
) {
588 sta
->flags
&= ~WLAN_STA_AUTHORIZED
;
589 if (params
->station_flags
& STATION_FLAG_AUTHORIZED
)
590 sta
->flags
|= WLAN_STA_AUTHORIZED
;
592 sta
->flags
&= ~WLAN_STA_SHORT_PREAMBLE
;
593 if (params
->station_flags
& STATION_FLAG_SHORT_PREAMBLE
)
594 sta
->flags
|= WLAN_STA_SHORT_PREAMBLE
;
596 sta
->flags
&= ~WLAN_STA_WME
;
597 if (params
->station_flags
& STATION_FLAG_WME
)
598 sta
->flags
|= WLAN_STA_WME
;
602 sta
->aid
= params
->aid
;
603 if (sta
->aid
> IEEE80211_MAX_AID
)
604 sta
->aid
= 0; /* XXX: should this be an error? */
607 if (params
->listen_interval
>= 0)
608 sta
->listen_interval
= params
->listen_interval
;
610 if (params
->supported_rates
) {
612 sband
= local
->hw
.wiphy
->bands
[local
->oper_channel
->band
];
614 for (i
= 0; i
< params
->supported_rates_len
; i
++) {
615 int rate
= (params
->supported_rates
[i
] & 0x7f) * 5;
616 for (j
= 0; j
< sband
->n_bitrates
; j
++) {
617 if (sband
->bitrates
[j
].bitrate
== rate
)
621 sta
->supp_rates
[local
->oper_channel
->band
] = rates
;
624 #ifdef CONFIG_MAC80211_MESH
625 if (sdata
->vif
.type
== IEEE80211_IF_TYPE_MESH_POINT
&&
626 params
->plink_action
)
627 switch (params
->plink_action
) {
628 case PLINK_ACTION_OPEN
:
629 mesh_plink_open(sta
);
631 case PLINK_ACTION_BLOCK
:
632 mesh_plink_block(sta
);
638 static int ieee80211_add_station(struct wiphy
*wiphy
, struct net_device
*dev
,
639 u8
*mac
, struct station_parameters
*params
)
641 struct ieee80211_local
*local
= wdev_priv(dev
->ieee80211_ptr
);
642 struct sta_info
*sta
;
643 struct ieee80211_sub_if_data
*sdata
;
645 /* Prevent a race with changing the rate control algorithm */
646 if (!netif_running(dev
))
650 sdata
= IEEE80211_DEV_TO_SUB_IF(params
->vlan
);
652 if (sdata
->vif
.type
!= IEEE80211_IF_TYPE_VLAN
||
653 sdata
->vif
.type
!= IEEE80211_IF_TYPE_AP
)
656 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
658 #ifdef CONFIG_MAC80211_MESH
659 if (sdata
->vif
.type
== IEEE80211_IF_TYPE_MESH_POINT
)
660 sta
= mesh_plink_add(mac
, DEFAULT_RATES
, dev
);
663 sta
= sta_info_add(local
, dev
, mac
, GFP_KERNEL
);
668 sta
->dev
= sdata
->dev
;
669 if (sdata
->vif
.type
== IEEE80211_IF_TYPE_VLAN
||
670 sdata
->vif
.type
== IEEE80211_IF_TYPE_AP
)
671 ieee80211_send_layer2_update(sta
);
673 sta
->flags
= WLAN_STA_AUTH
| WLAN_STA_ASSOC
;
675 sta_apply_parameters(local
, sta
, params
);
677 rate_control_rate_init(sta
, local
);
684 static int ieee80211_del_station(struct wiphy
*wiphy
, struct net_device
*dev
,
687 struct ieee80211_local
*local
= wdev_priv(dev
->ieee80211_ptr
);
688 struct sta_info
*sta
;
691 /* XXX: get sta belonging to dev */
692 sta
= sta_info_get(local
, mac
);
699 sta_info_flush(local
, dev
);
704 static int ieee80211_change_station(struct wiphy
*wiphy
,
705 struct net_device
*dev
,
707 struct station_parameters
*params
)
709 struct ieee80211_local
*local
= wdev_priv(dev
->ieee80211_ptr
);
710 struct sta_info
*sta
;
711 struct ieee80211_sub_if_data
*vlansdata
;
713 /* XXX: get sta belonging to dev */
714 sta
= sta_info_get(local
, mac
);
718 if (params
->vlan
&& params
->vlan
!= sta
->dev
) {
719 vlansdata
= IEEE80211_DEV_TO_SUB_IF(params
->vlan
);
721 if (vlansdata
->vif
.type
!= IEEE80211_IF_TYPE_VLAN
||
722 vlansdata
->vif
.type
!= IEEE80211_IF_TYPE_AP
)
725 sta
->dev
= params
->vlan
;
726 ieee80211_send_layer2_update(sta
);
729 sta_apply_parameters(local
, sta
, params
);
736 #ifdef CONFIG_MAC80211_MESH
737 static int ieee80211_add_mpath(struct wiphy
*wiphy
, struct net_device
*dev
,
738 u8
*dst
, u8
*next_hop
)
740 struct ieee80211_local
*local
= wdev_priv(dev
->ieee80211_ptr
);
741 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
742 struct mesh_path
*mpath
;
743 struct sta_info
*sta
;
746 if (!netif_running(dev
))
749 if (sdata
->vif
.type
!= IEEE80211_IF_TYPE_MESH_POINT
)
752 sta
= sta_info_get(local
, next_hop
);
756 err
= mesh_path_add(dst
, dev
);
761 mpath
= mesh_path_lookup(dst
, dev
);
767 mesh_path_fix_nexthop(mpath
, sta
);
773 static int ieee80211_del_mpath(struct wiphy
*wiphy
, struct net_device
*dev
,
777 return mesh_path_del(dst
, dev
);
779 mesh_path_flush(dev
);
783 static int ieee80211_change_mpath(struct wiphy
*wiphy
,
784 struct net_device
*dev
,
785 u8
*dst
, u8
*next_hop
)
787 struct ieee80211_local
*local
= wdev_priv(dev
->ieee80211_ptr
);
788 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
789 struct mesh_path
*mpath
;
790 struct sta_info
*sta
;
792 if (!netif_running(dev
))
795 if (sdata
->vif
.type
!= IEEE80211_IF_TYPE_MESH_POINT
)
798 sta
= sta_info_get(local
, next_hop
);
803 mpath
= mesh_path_lookup(dst
, dev
);
810 mesh_path_fix_nexthop(mpath
, sta
);
816 static void mpath_set_pinfo(struct mesh_path
*mpath
, u8
*next_hop
,
817 struct mpath_info
*pinfo
)
820 memcpy(next_hop
, mpath
->next_hop
->addr
, ETH_ALEN
);
822 memset(next_hop
, 0, ETH_ALEN
);
824 pinfo
->filled
= MPATH_INFO_FRAME_QLEN
|
828 MPATH_INFO_DISCOVERY_TIMEOUT
|
829 MPATH_INFO_DISCOVERY_RETRIES
|
832 pinfo
->frame_qlen
= mpath
->frame_queue
.qlen
;
833 pinfo
->dsn
= mpath
->dsn
;
834 pinfo
->metric
= mpath
->metric
;
835 if (time_before(jiffies
, mpath
->exp_time
))
836 pinfo
->exptime
= jiffies_to_msecs(mpath
->exp_time
- jiffies
);
837 pinfo
->discovery_timeout
=
838 jiffies_to_msecs(mpath
->discovery_timeout
);
839 pinfo
->discovery_retries
= mpath
->discovery_retries
;
841 if (mpath
->flags
& MESH_PATH_ACTIVE
)
842 pinfo
->flags
|= NL80211_MPATH_FLAG_ACTIVE
;
843 if (mpath
->flags
& MESH_PATH_RESOLVING
)
844 pinfo
->flags
|= NL80211_MPATH_FLAG_RESOLVING
;
845 if (mpath
->flags
& MESH_PATH_DSN_VALID
)
846 pinfo
->flags
|= NL80211_MPATH_FLAG_DSN_VALID
;
847 if (mpath
->flags
& MESH_PATH_FIXED
)
848 pinfo
->flags
|= NL80211_MPATH_FLAG_FIXED
;
849 if (mpath
->flags
& MESH_PATH_RESOLVING
)
850 pinfo
->flags
|= NL80211_MPATH_FLAG_RESOLVING
;
852 pinfo
->flags
= mpath
->flags
;
855 static int ieee80211_get_mpath(struct wiphy
*wiphy
, struct net_device
*dev
,
856 u8
*dst
, u8
*next_hop
, struct mpath_info
*pinfo
)
859 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
860 struct mesh_path
*mpath
;
862 if (sdata
->vif
.type
!= IEEE80211_IF_TYPE_MESH_POINT
)
866 mpath
= mesh_path_lookup(dst
, dev
);
871 memcpy(dst
, mpath
->dst
, ETH_ALEN
);
872 mpath_set_pinfo(mpath
, next_hop
, pinfo
);
877 static int ieee80211_dump_mpath(struct wiphy
*wiphy
, struct net_device
*dev
,
878 int idx
, u8
*dst
, u8
*next_hop
,
879 struct mpath_info
*pinfo
)
881 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
882 struct mesh_path
*mpath
;
884 if (sdata
->vif
.type
!= IEEE80211_IF_TYPE_MESH_POINT
)
888 mpath
= mesh_path_lookup_by_idx(idx
, dev
);
893 memcpy(dst
, mpath
->dst
, ETH_ALEN
);
894 mpath_set_pinfo(mpath
, next_hop
, pinfo
);
900 struct cfg80211_ops mac80211_config_ops
= {
901 .add_virtual_intf
= ieee80211_add_iface
,
902 .del_virtual_intf
= ieee80211_del_iface
,
903 .change_virtual_intf
= ieee80211_change_iface
,
904 .add_key
= ieee80211_add_key
,
905 .del_key
= ieee80211_del_key
,
906 .get_key
= ieee80211_get_key
,
907 .set_default_key
= ieee80211_config_default_key
,
908 .add_beacon
= ieee80211_add_beacon
,
909 .set_beacon
= ieee80211_set_beacon
,
910 .del_beacon
= ieee80211_del_beacon
,
911 .add_station
= ieee80211_add_station
,
912 .del_station
= ieee80211_del_station
,
913 .change_station
= ieee80211_change_station
,
914 .get_station
= ieee80211_get_station
,
915 .dump_station
= ieee80211_dump_station
,
916 #ifdef CONFIG_MAC80211_MESH
917 .add_mpath
= ieee80211_add_mpath
,
918 .del_mpath
= ieee80211_del_mpath
,
919 .change_mpath
= ieee80211_change_mpath
,
920 .get_mpath
= ieee80211_get_mpath
,
921 .dump_mpath
= ieee80211_dump_mpath
,