diff options
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 8 | ||||
-rw-r--r-- | include/net/cfg80211.h | 22 | ||||
-rw-r--r-- | net/wireless/core.c | 12 | ||||
-rw-r--r-- | net/wireless/sysfs.c | 20 |
4 files changed, 60 insertions, 2 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 84df3fcf37b3..0dbda8dfbd99 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -281,6 +281,8 @@ struct mac80211_hwsim_data { | |||
281 | struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; | 281 | struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; |
282 | struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; | 282 | struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; |
283 | 283 | ||
284 | struct mac_address addresses[2]; | ||
285 | |||
284 | struct ieee80211_channel *channel; | 286 | struct ieee80211_channel *channel; |
285 | unsigned long beacon_int; /* in jiffies unit */ | 287 | unsigned long beacon_int; /* in jiffies unit */ |
286 | unsigned int rx_filter; | 288 | unsigned int rx_filter; |
@@ -1154,7 +1156,11 @@ static int __init init_mac80211_hwsim(void) | |||
1154 | SET_IEEE80211_DEV(hw, data->dev); | 1156 | SET_IEEE80211_DEV(hw, data->dev); |
1155 | addr[3] = i >> 8; | 1157 | addr[3] = i >> 8; |
1156 | addr[4] = i; | 1158 | addr[4] = i; |
1157 | SET_IEEE80211_PERM_ADDR(hw, addr); | 1159 | memcpy(data->addresses[0].addr, addr, ETH_ALEN); |
1160 | memcpy(data->addresses[1].addr, addr, ETH_ALEN); | ||
1161 | data->addresses[1].addr[0] |= 0x40; | ||
1162 | hw->wiphy->n_addresses = 2; | ||
1163 | hw->wiphy->addresses = data->addresses; | ||
1158 | 1164 | ||
1159 | hw->channel_change_time = 1; | 1165 | hw->channel_change_time = 1; |
1160 | hw->queues = 4; | 1166 | hw->queues = 4; |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2af52704e670..c5d16f299d6f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1195,6 +1195,10 @@ enum wiphy_flags { | |||
1195 | WIPHY_FLAG_4ADDR_STATION = BIT(6), | 1195 | WIPHY_FLAG_4ADDR_STATION = BIT(6), |
1196 | }; | 1196 | }; |
1197 | 1197 | ||
1198 | struct mac_address { | ||
1199 | u8 addr[ETH_ALEN]; | ||
1200 | }; | ||
1201 | |||
1198 | /** | 1202 | /** |
1199 | * struct wiphy - wireless hardware description | 1203 | * struct wiphy - wireless hardware description |
1200 | * @idx: the wiphy index assigned to this item | 1204 | * @idx: the wiphy index assigned to this item |
@@ -1213,12 +1217,28 @@ enum wiphy_flags { | |||
1213 | * -1 = fragmentation disabled, only odd values >= 256 used | 1217 | * -1 = fragmentation disabled, only odd values >= 256 used |
1214 | * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled | 1218 | * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled |
1215 | * @net: the network namespace this wiphy currently lives in | 1219 | * @net: the network namespace this wiphy currently lives in |
1220 | * @perm_addr: permanent MAC address of this device | ||
1221 | * @addr_mask: If the device supports multiple MAC addresses by masking, | ||
1222 | * set this to a mask with variable bits set to 1, e.g. if the last | ||
1223 | * four bits are variable then set it to 00:...:00:0f. The actual | ||
1224 | * variable bits shall be determined by the interfaces added, with | ||
1225 | * interfaces not matching the mask being rejected to be brought up. | ||
1226 | * @n_addresses: number of addresses in @addresses. | ||
1227 | * @addresses: If the device has more than one address, set this pointer | ||
1228 | * to a list of addresses (6 bytes each). The first one will be used | ||
1229 | * by default for perm_addr. In this case, the mask should be set to | ||
1230 | * all-zeroes. In this case it is assumed that the device can handle | ||
1231 | * the same number of arbitrary MAC addresses. | ||
1216 | */ | 1232 | */ |
1217 | struct wiphy { | 1233 | struct wiphy { |
1218 | /* assign these fields before you register the wiphy */ | 1234 | /* assign these fields before you register the wiphy */ |
1219 | 1235 | ||
1220 | /* permanent MAC address */ | 1236 | /* permanent MAC address(es) */ |
1221 | u8 perm_addr[ETH_ALEN]; | 1237 | u8 perm_addr[ETH_ALEN]; |
1238 | u8 addr_mask[ETH_ALEN]; | ||
1239 | |||
1240 | u16 n_addresses; | ||
1241 | struct mac_address *addresses; | ||
1222 | 1242 | ||
1223 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ | 1243 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ |
1224 | u16 interface_modes; | 1244 | u16 interface_modes; |
diff --git a/net/wireless/core.c b/net/wireless/core.c index d07f57c906db..71b6b3a9cf1f 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -413,6 +413,18 @@ int wiphy_register(struct wiphy *wiphy) | |||
413 | int i; | 413 | int i; |
414 | u16 ifmodes = wiphy->interface_modes; | 414 | u16 ifmodes = wiphy->interface_modes; |
415 | 415 | ||
416 | if (WARN_ON(wiphy->addresses && !wiphy->n_addresses)) | ||
417 | return -EINVAL; | ||
418 | |||
419 | if (WARN_ON(wiphy->addresses && | ||
420 | !is_zero_ether_addr(wiphy->perm_addr) && | ||
421 | memcmp(wiphy->perm_addr, wiphy->addresses[0].addr, | ||
422 | ETH_ALEN))) | ||
423 | return -EINVAL; | ||
424 | |||
425 | if (wiphy->addresses) | ||
426 | memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN); | ||
427 | |||
416 | /* sanity check ifmodes */ | 428 | /* sanity check ifmodes */ |
417 | WARN_ON(!ifmodes); | 429 | WARN_ON(!ifmodes); |
418 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; | 430 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index efe3c5c92b2d..9f2cef3e0ca0 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -33,10 +33,30 @@ static ssize_t name ## _show(struct device *dev, \ | |||
33 | 33 | ||
34 | SHOW_FMT(index, "%d", wiphy_idx); | 34 | SHOW_FMT(index, "%d", wiphy_idx); |
35 | SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); | 35 | SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); |
36 | SHOW_FMT(address_mask, "%pM", wiphy.addr_mask); | ||
37 | |||
38 | static ssize_t addresses_show(struct device *dev, | ||
39 | struct device_attribute *attr, | ||
40 | char *buf) | ||
41 | { | ||
42 | struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy; | ||
43 | char *start = buf; | ||
44 | int i; | ||
45 | |||
46 | if (!wiphy->addresses) | ||
47 | return sprintf(buf, "%pM\n", wiphy->perm_addr); | ||
48 | |||
49 | for (i = 0; i < wiphy->n_addresses; i++) | ||
50 | buf += sprintf(buf, "%pM\n", &wiphy->addresses[i].addr); | ||
51 | |||
52 | return buf - start; | ||
53 | } | ||
36 | 54 | ||
37 | static struct device_attribute ieee80211_dev_attrs[] = { | 55 | static struct device_attribute ieee80211_dev_attrs[] = { |
38 | __ATTR_RO(index), | 56 | __ATTR_RO(index), |
39 | __ATTR_RO(macaddress), | 57 | __ATTR_RO(macaddress), |
58 | __ATTR_RO(address_mask), | ||
59 | __ATTR_RO(addresses), | ||
40 | {} | 60 | {} |
41 | }; | 61 | }; |
42 | 62 | ||