* [PATCH 1/10] d80211: fix SIOCGIWESSID ioctl
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
2006-04-21 20:53 ` [PATCH 2/10] d80211: use is_multicast_ether_addr Jiri Benc
` (8 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
Flags for SIOCGIWESSID ioctl were not set, thus SSID was never displayed by
iwconfig.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
net/d80211/ieee80211_ioctl.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
56d18689a4964cc2e906cfb5164b31649735774a
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index dfa0ef7..792fcf4 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1782,8 +1782,11 @@ static int ieee80211_ioctl_giwessid(stru
if (sdata->type == IEEE80211_IF_TYPE_STA ||
sdata->type == IEEE80211_IF_TYPE_IBSS) {
int res = ieee80211_sta_get_ssid(dev, ssid, &len);
- if (res == 0)
+ if (res == 0) {
data->length = len;
+ data->flags = 1;
+ } else
+ data->flags = 0;
return res;
}
@@ -1792,6 +1795,7 @@ static int ieee80211_ioctl_giwessid(stru
len = IW_ESSID_MAX_SIZE;
memcpy(ssid, local->conf.ssid, len);
data->length = len;
+ data->flags = 1;
return 0;
}
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 2/10] d80211: use is_multicast_ether_addr
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
2006-04-21 20:53 ` [PATCH 1/10] d80211: fix SIOCGIWESSID ioctl Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
2006-04-21 20:53 ` [PATCH 3/10] d80211: fix Oops caused by packets sent directly to master device Jiri Benc
` (7 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
Replace custom MULTICAST_ADDR macro with is_multicast_ether_addr function.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
net/d80211/ieee80211.c | 29 +++++++++++++++--------------
net/d80211/ieee80211_i.h | 2 --
2 files changed, 15 insertions(+), 16 deletions(-)
f01885676fc8b7adb838b110b4f6449cbb17dae5
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 64cc66f..eb701ac 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -731,7 +731,7 @@ ieee80211_tx_h_misc(struct ieee80211_txr
u16 dur;
struct ieee80211_tx_control *control = tx->u.tx.control;
- if (!MULTICAST_ADDR(hdr->addr1)) {
+ if (!is_multicast_ether_addr(hdr->addr1)) {
if (tx->skb->len >= tx->local->rts_threshold &&
tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD) {
control->use_rts_cts = 1;
@@ -766,7 +766,7 @@ ieee80211_tx_h_misc(struct ieee80211_txr
/* Setup duration field for the first fragment of the frame. Duration
* for remaining fragments will be updated when they are being sent
* to low-level driver in ieee80211_tx(). */
- dur = ieee80211_duration(tx, MULTICAST_ADDR(hdr->addr1),
+ dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1),
tx->fragmented ? tx->u.tx.extra_frag[0]->len :
0);
hdr->duration_id = cpu_to_le16(dur);
@@ -1072,8 +1072,8 @@ static void inline ieee80211_tx_prepare(
tx->fc = le16_to_cpu(hdr->frame_control);
control->power_level = local->conf.power_level;
tx->u.tx.control = control;
- tx->u.tx.unicast = !MULTICAST_ADDR(hdr->addr1);
- control->no_ack = MULTICAST_ADDR(hdr->addr1);
+ tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1);
+ control->no_ack = is_multicast_ether_addr(hdr->addr1);
tx->fragmented = local->fragmentation_threshold <
IEEE80211_MAX_FRAG_THRESHOLD && tx->u.tx.unicast &&
skb->len + 4 /* FCS */ > local->fragmentation_threshold &&
@@ -2229,7 +2229,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
|| sdata->type == IEEE80211_IF_TYPE_VLAN)) {
- if (MULTICAST_ADDR(skb->data)) {
+ if (is_multicast_ether_addr(skb->data)) {
/* send multicast frames both to higher layers in
* local net stack and back to the wireless media */
skb2 = skb_copy(skb, GFP_ATOMIC);
@@ -2659,7 +2659,8 @@ ieee80211_rx_h_defragment(struct ieee802
frag = WLAN_GET_SEQ_FRAG(sc);
if (likely((!(rx->fc & WLAN_FC_MOREFRAG) && frag == 0) ||
- (rx->skb)->len < 24 || MULTICAST_ADDR(hdr->addr1))) {
+ (rx->skb)->len < 24 ||
+ is_multicast_ether_addr(hdr->addr1))) {
/* not fragmented */
goto out;
}
@@ -2747,7 +2748,7 @@ ieee80211_rx_h_defragment(struct ieee802
out:
if (rx->sta)
rx->sta->rx_packets++;
- if (MULTICAST_ADDR(hdr->addr1))
+ if (is_multicast_ether_addr(hdr->addr1))
rx->local->dot11MulticastReceivedFrameCount++;
#ifdef IEEE80211_LEDS
else
@@ -2778,7 +2779,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
hdr = (struct ieee80211_hdr *) rx->skb->data;
/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
- if (rx->sta && !MULTICAST_ADDR(hdr->addr1)) {
+ if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
if (unlikely(rx->fc & WLAN_FC_RETRY &&
rx->sta->last_seq_ctrl[rx->u.rx.queue] ==
hdr->seq_ctrl)) {
@@ -2900,7 +2901,7 @@ ieee80211_rx_h_sta_process(struct ieee80
if (memcmp(bssid, rx->sdata->u.sta.bssid, ETH_ALEN) == 0)
sta->last_rx = jiffies;
} else
- if (!MULTICAST_ADDR(hdr->addr1) ||
+ if (!is_multicast_ether_addr(hdr->addr1) ||
rx->sdata->type == IEEE80211_IF_TYPE_STA) {
/* Update last_rx only for unicast frames in order to prevent
* the Probe Request frames (the only broadcast frames from a
@@ -3415,7 +3416,7 @@ ieee80211_tx_h_load_stats(struct ieee802
hdrtime = CHAN_UTIL_HDR_LONG;
load = hdrtime;
- if (!MULTICAST_ADDR(hdr->addr1))
+ if (!is_multicast_ether_addr(hdr->addr1))
load += hdrtime;
if (tx->u.tx.control->use_rts_cts)
@@ -3481,7 +3482,7 @@ ieee80211_rx_h_load_stats(struct ieee802
hdrtime = CHAN_UTIL_HDR_LONG;
load = hdrtime;
- if (!MULTICAST_ADDR(hdr->addr1))
+ if (!is_multicast_ether_addr(hdr->addr1))
load += hdrtime;
load += skb->len * rate->rate_inv;
@@ -3792,7 +3793,7 @@ #endif /* IEEE80211_LEDS */
if (status->ack) {
if (frag == 0) {
local->dot11TransmittedFrameCount++;
- if (MULTICAST_ADDR(hdr->addr1))
+ if (is_multicast_ether_addr(hdr->addr1))
local->dot11MulticastTransmittedFrameCount++;
if (status->retry_count > 0)
local->dot11RetryCount++;
@@ -3804,8 +3805,8 @@ #endif /* IEEE80211_LEDS */
* with an individual address in the address 1 field or an MPDU
* with a multicast address in the address 1 field of type Data
* or Management. */
- if (!MULTICAST_ADDR(hdr->addr1) || type == WLAN_FC_TYPE_DATA ||
- type == WLAN_FC_TYPE_MGMT)
+ if (!is_multicast_ether_addr(hdr->addr1) ||
+ type == WLAN_FC_TYPE_DATA || type == WLAN_FC_TYPE_MGMT)
local->dot11TransmittedFragmentCount++;
} else {
if (frag == 0)
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 2dbb132..400c675 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -50,8 +50,6 @@ #define MAC2STR(a) ((a)[0] & 0xff), ((a)
((a)[3] & 0xff), ((a)[4] & 0xff), ((a)[5] & 0xff)
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MULTICAST_ADDR(a) ((a)[0] & 0x01)
-
/* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent
* reception of at least three fragmented frames. This limit can be increased
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 3/10] d80211: fix Oops caused by packets sent directly to master device
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
2006-04-21 20:53 ` [PATCH 1/10] d80211: fix SIOCGIWESSID ioctl Jiri Benc
2006-04-21 20:53 ` [PATCH 2/10] d80211: use is_multicast_ether_addr Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
2006-04-21 20:53 ` [PATCH 4/10] d80211: don't use pointer in ieee80211_tx_control Jiri Benc
` (6 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
Sending packets to master interface directly causes dereferencing of pointer
containing random data. The same problem happens when originating virtual
interface is removed while a packet is queued.
We really shouldn't store pointer to ieee80211_sub_if_data in skb->cb. Store
ifindex there instead.
Also, there is no need for internal ieee80211_tx_packet_data structure to be
declared in d80211.h. As this patch touches this structure anyway, let's
move it to ieee80211_i.h.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
include/net/d80211.h | 11 -----
net/d80211/ieee80211.c | 89 +++++++++++++++++++++++++++++++++++---------
net/d80211/ieee80211_i.h | 12 ++++++
net/d80211/ieee80211_sta.c | 3 +
net/d80211/wme.c | 2 -
5 files changed, 85 insertions(+), 32 deletions(-)
8d3a2dea3e4cefad23f3dad3e2eeeb5bdcff3dbb
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 23bcbfa..e44e21c 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -188,17 +188,6 @@ struct ieee80211_tx_control {
struct ieee80211_sub_if_data *sdata; /* internal */
};
-/* Stored in sk_buff->cb */
-struct ieee80211_tx_packet_data {
- struct ieee80211_sub_if_data *sdata;
- unsigned long jiffies;
- unsigned int req_tx_status:1;
- unsigned int do_not_encrypt:1;
- unsigned int pkt_probe_resp:1;
- unsigned int requeue:1;
- unsigned int queue:4;
-};
-
#define RX_FLAG_MMIC_ERROR 0x1
#define RX_FLAG_DECRYPTED 0x2
#define RX_FLAG_XR_DOUBLE_CHIRP 0x4
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index eb701ac..f768de5 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1051,23 +1051,21 @@ ieee80211_tx_h_ps_buf(struct ieee80211_t
}
-static void inline ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
- struct sk_buff *skb,
- struct net_device *dev,
- struct ieee80211_tx_control *control)
+static void inline
+__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ struct sk_buff *skb,
+ struct net_device *dev,
+ struct ieee80211_tx_control *control)
{
struct ieee80211_local *local = dev->priv;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct ieee80211_tx_packet_data *pkt_data;
int hdrlen;
- pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
-
memset(tx, 0, sizeof(*tx));
tx->skb = skb;
- tx->dev = pkt_data->sdata->dev; /* use original interface */
+ tx->dev = dev; /* use original interface */
tx->local = local;
- tx->sdata = pkt_data->sdata;
+ tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
tx->sta = sta_info_get(local, hdr->addr1);
tx->fc = le16_to_cpu(hdr->frame_control);
control->power_level = local->conf.power_level;
@@ -1095,6 +1093,37 @@ static void inline ieee80211_tx_prepare(
}
+/* FIXME: This is not nice but currently there doesn't exist more elegant way */
+static int inline is_ieee80211_device(struct net_device *dev)
+{
+ return (dev->wireless_handlers ==
+ (struct iw_handler_def *) &ieee80211_iw_handler_def);
+}
+
+/* Device in tx->dev has a reference added; use dev_put(tx->dev) when
+ * finished with it. */
+static void inline ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ struct sk_buff *skb,
+ struct net_device *mdev,
+ struct ieee80211_tx_control *control)
+{
+ struct ieee80211_tx_packet_data *pkt_data;
+ struct net_device *dev;
+
+ pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+ dev = dev_get_by_index(pkt_data->ifindex);
+ if (unlikely(dev && !is_ieee80211_device(dev))) {
+ dev_put(dev);
+ dev = NULL;
+ }
+ if (unlikely(!dev)) {
+ printk(KERN_WARNING "%s: NULL ifindex in pkt_data\n",
+ mdev->name);
+ dev = mdev;
+ dev_hold(dev);
+ }
+ __ieee80211_tx_prepare(tx, skb, dev, control);
+}
static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
struct ieee80211_tx_control *control, int mgmt)
@@ -1111,7 +1140,7 @@ static int ieee80211_tx(struct net_devic
return 0;
}
- ieee80211_tx_prepare(&tx, skb, dev, control);
+ __ieee80211_tx_prepare(&tx, skb, dev, control);
sta = tx.sta;
tx.u.tx.mgmt_interface = mgmt;
@@ -1136,8 +1165,8 @@ static int ieee80211_tx(struct net_devic
return 0;
}
- ieee80211_dump_frame(dev->name, "TX to low-level driver", skb);
- ret = local->hw->tx(dev, skb, control);
+ ieee80211_dump_frame(local->mdev->name, "TX to low-level driver", skb);
+ ret = local->hw->tx(local->mdev, skb, control);
#ifdef IEEE80211_LEDS
if (!ret && local->tx_led_counter++ == 0) {
ieee80211_tx_led(1, dev);
@@ -1177,9 +1206,9 @@ #endif /* IEEE80211_LEDS */
dur = ieee80211_duration(&tx, 0, next_len);
hdr->duration_id = cpu_to_le16(dur);
- ieee80211_dump_frame(dev->name,
+ ieee80211_dump_frame(local->mdev->name,
"TX to low-level driver", skb);
- ret = local->hw->tx(dev, tx.u.tx.extra_frag[i],
+ ret = local->hw->tx(local->mdev, tx.u.tx.extra_frag[i],
control);
if (ret > 0)
goto drop;
@@ -1212,6 +1241,7 @@ static int ieee80211_master_start_xmit(s
{
struct ieee80211_tx_control control;
struct ieee80211_tx_packet_data *pkt_data;
+ struct net_device *odev = NULL;
struct ieee80211_sub_if_data *sdata;
int ret;
@@ -1222,7 +1252,23 @@ static int ieee80211_master_start_xmit(s
*/
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
memset(&control, 0, sizeof(struct ieee80211_tx_control));
- control.sdata = pkt_data->sdata;
+
+ if (pkt_data->ifindex)
+ odev = dev_get_by_index(pkt_data->ifindex);
+ if (unlikely(odev && !is_ieee80211_device(odev))) {
+ dev_put(odev);
+ odev = NULL;
+ }
+ if (unlikely(!odev)) {
+#ifdef CONFIG_D80211_VERBOSE_DEBUG
+ printk(KERN_DEBUG "%s: Discarded packet with nonexistent "
+ "originating device\n", dev->name);
+#endif
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ control.sdata = IEEE80211_DEV_TO_SUB_IF(dev);
control.req_tx_status = pkt_data->req_tx_status;
control.do_not_encrypt = pkt_data->do_not_encrypt;
control.pkt_type =
@@ -1230,8 +1276,9 @@ static int ieee80211_master_start_xmit(s
control.requeue = pkt_data->requeue;
control.queue = pkt_data->queue;
- ret = ieee80211_tx(dev, skb, &control,
+ ret = ieee80211_tx(odev, skb, &control,
control.sdata->type == IEEE80211_IF_TYPE_MGMT);
+ dev_put(odev);
return ret;
}
@@ -1401,7 +1448,8 @@ #endif
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
- pkt_data->sdata = sdata;
+ pkt_data->ifindex = sdata->dev->ifindex;
+ pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
pkt_data->do_not_encrypt = no_encrypt;
skb->dev = sdata->master;
@@ -1452,7 +1500,8 @@ ieee80211_mgmt_start_xmit(struct sk_buff
pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
- pkt_data->sdata = sdata;
+ pkt_data->ifindex = sdata->dev->ifindex;
+ pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP)
@@ -1680,6 +1729,7 @@ ieee80211_get_buffered_bc(struct net_dev
if (res == TXRX_DROP || res == TXRX_QUEUED)
break;
}
+ dev_put(tx.dev);
if (res == TXRX_DROP) {
I802_DEBUG_INC(local->tx_handlers_drop);
@@ -3644,7 +3694,8 @@ static void ieee80211_remove_tx_extra(st
struct ieee80211_tx_packet_data *pkt_data;
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
- pkt_data->sdata = control->sdata;
+ pkt_data->ifindex = control->sdata->dev->ifindex;
+ pkt_data->mgmt_iface = (control->sdata->type == IEEE80211_IF_TYPE_MGMT);
pkt_data->req_tx_status = control->req_tx_status;
pkt_data->do_not_encrypt = control->do_not_encrypt;
pkt_data->pkt_probe_resp = (control->pkt_type == PKT_PROBE_RESP);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 400c675..b29a5e8 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -143,6 +143,18 @@ #ifdef CONFIG_HOSTAPD_WPA_TESTING
#endif /* CONFIG_HOSTAPD_WPA_TESTING */
};
+/* Stored in sk_buff->cb */
+struct ieee80211_tx_packet_data {
+ int ifindex;
+ unsigned long jiffies;
+ unsigned int req_tx_status:1;
+ unsigned int do_not_encrypt:1;
+ unsigned int pkt_probe_resp:1;
+ unsigned int requeue:1;
+ unsigned int queue:4;
+ unsigned int mgmt_iface:1;
+};
+
struct ieee80211_passive_scan {
unsigned int in_scan:1; /* this must be cleared before calling
* netif_oper(WAKEUP) */
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index d9c3d67..2720f1d 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -399,7 +399,8 @@ static void ieee80211_sta_tx(struct net_
pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
- pkt_data->sdata = sdata;
+ pkt_data->ifindex = sdata->dev->ifindex;
+ pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
pkt_data->do_not_encrypt = !encrypt;
if (probe_resp)
pkt_data->pkt_probe_resp = 1;
diff --git a/net/d80211/wme.c b/net/d80211/wme.c
index 51a197a..f20d3e0 100644
--- a/net/d80211/wme.c
+++ b/net/d80211/wme.c
@@ -190,7 +190,7 @@ static inline int classify80211(struct s
return IEEE80211_TX_QUEUE_DATA0;
}
- if (unlikely(pkt_data->sdata->type == IEEE80211_IF_TYPE_MGMT)) {
+ if (unlikely(pkt_data->mgmt_iface)) {
/* Data frames from hostapd (mainly, EAPOL) use AC_VO
* and they will include QoS control fields if
* the target STA is using WME. */
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 4/10] d80211: don't use pointer in ieee80211_tx_control
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
` (2 preceding siblings ...)
2006-04-21 20:53 ` [PATCH 3/10] d80211: fix Oops caused by packets sent directly to master device Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
2006-04-21 20:53 ` [PATCH 5/10] d80211: per-interface SSID Jiri Benc
` (5 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
A problem similar to the one with ieee80211_sub_if_data and skb->cb happens
to ieee80211_sub_if_data and ieee80211_tx_control. When originating
interface is removed while packet is sent to the driver, bad things will
happen. Use ifindex instead.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
include/net/d80211.h | 3 ++-
net/d80211/ieee80211.c | 12 +++++++-----
2 files changed, 9 insertions(+), 6 deletions(-)
2f1956069a10abdc9a1d4f38ba413ae511428224
diff --git a/include/net/d80211.h b/include/net/d80211.h
index e44e21c..3943e30 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -185,7 +185,8 @@ struct ieee80211_tx_control {
* struct ieee80211_rate). To be used to limit
* packet dropping when probing higher rates, if hw
* supports multiple retry rates. -1 = not used */
- struct ieee80211_sub_if_data *sdata; /* internal */
+ int type; /* internal */
+ int ifindex; /* internal */
};
#define RX_FLAG_MMIC_ERROR 0x1
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index f768de5..425bd51 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1242,7 +1242,7 @@ static int ieee80211_master_start_xmit(s
struct ieee80211_tx_control control;
struct ieee80211_tx_packet_data *pkt_data;
struct net_device *odev = NULL;
- struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_sub_if_data *sdata, *osdata;
int ret;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1267,8 +1267,10 @@ #endif
dev_kfree_skb(skb);
return 0;
}
+ osdata = IEEE80211_DEV_TO_SUB_IF(odev);
- control.sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ control.ifindex = odev->ifindex;
+ control.type = osdata->type;
control.req_tx_status = pkt_data->req_tx_status;
control.do_not_encrypt = pkt_data->do_not_encrypt;
control.pkt_type =
@@ -1277,7 +1279,7 @@ #endif
control.queue = pkt_data->queue;
ret = ieee80211_tx(odev, skb, &control,
- control.sdata->type == IEEE80211_IF_TYPE_MGMT);
+ control.type == IEEE80211_IF_TYPE_MGMT);
dev_put(odev);
return ret;
@@ -3694,8 +3696,8 @@ static void ieee80211_remove_tx_extra(st
struct ieee80211_tx_packet_data *pkt_data;
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
- pkt_data->ifindex = control->sdata->dev->ifindex;
- pkt_data->mgmt_iface = (control->sdata->type == IEEE80211_IF_TYPE_MGMT);
+ pkt_data->ifindex = control->ifindex;
+ pkt_data->mgmt_iface = (control->type == IEEE80211_IF_TYPE_MGMT);
pkt_data->req_tx_status = control->req_tx_status;
pkt_data->do_not_encrypt = control->do_not_encrypt;
pkt_data->pkt_probe_resp = (control->pkt_type == PKT_PROBE_RESP);
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 5/10] d80211: per-interface SSID
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
` (3 preceding siblings ...)
2006-04-21 20:53 ` [PATCH 4/10] d80211: don't use pointer in ieee80211_tx_control Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
2006-04-21 20:53 ` [PATCH 6/10] d80211: per-interface generic_elem Jiri Benc
` (4 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
Allow SSID to be set independently for each interface.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
include/net/d80211.h | 9 ++++++--
net/d80211/ieee80211.c | 6 ++++-
net/d80211/ieee80211_i.h | 3 +++
net/d80211/ieee80211_ioctl.c | 47 +++++++++++++++++++++++++-----------------
4 files changed, 43 insertions(+), 22 deletions(-)
41fbbdfe8770f3492f888fcd459b2f9d2d615b0b
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 3943e30..065b34c 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -251,8 +251,6 @@ struct ieee80211_conf {
/* these fields are used by low level drivers for hardware
* that generate beacons independently */
- u8 *ssid;
- size_t ssid_len;
u8 *generic_elem;
size_t generic_elem_len;
@@ -344,6 +342,11 @@ struct ieee80211_if_init_conf {
* during the live of the interface; this field is present only for
* convenience.
* @bssid: BSSID of the network we are associated to/creating.
+ * @ssid: used (together with @ssid_len) by drivers for hardware that
+ * generate beacons independently. The pointer is valid only during
+ * config_interface() callback (so copy the value somewhere if you need
+ * it).
+ * @ssid_len: length of the @ssid field.
*
* This structure is passed to config_interface() callback of
* &struct ieee80211_hw.
@@ -351,6 +354,8 @@ struct ieee80211_if_init_conf {
struct ieee80211_if_conf {
int type;
u8 *bssid;
+ u8 *ssid;
+ size_t ssid_len;
};
typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL }
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 425bd51..984c2b0 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1762,6 +1762,11 @@ int ieee80211_if_config(struct net_devic
if (sdata->type == IEEE80211_IF_TYPE_STA ||
sdata->type == IEEE80211_IF_TYPE_IBSS) {
conf.bssid = sdata->u.sta.bssid;
+ conf.ssid = sdata->u.sta.ssid;
+ conf.ssid_len = sdata->u.sta.ssid_len;
+ } else if (sdata->type == IEEE80211_IF_TYPE_AP) {
+ conf.ssid = sdata->u.ap.ssid;
+ conf.ssid_len = sdata->u.ap.ssid_len;
}
return local->hw->config_interface(local->mdev, dev->ifindex, &conf);
}
@@ -4337,7 +4342,6 @@ void ieee80211_unregister_hw(struct net_
kfree(local->basic_rates[i]);
}
- kfree(local->conf.ssid);
kfree(local->conf.generic_elem);
ieee80211_proc_deinit_interface(local);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index b29a5e8..e78beb2 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -192,6 +192,9 @@ struct ieee80211_if_ap {
u8 *beacon_head, *beacon_tail;
int beacon_head_len, beacon_tail_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ size_t ssid_len;
+
/* TODO: sta_aid could be replaced by 2008-bit large bitfield of
* that could be used in TIM element generation. This would also
* make TIM element generation a bit faster. */
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 792fcf4..6b73e27 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1746,7 +1746,6 @@ static int ieee80211_ioctl_siwessid(stru
struct iw_request_info *info,
struct iw_point *data, char *ssid)
{
- struct ieee80211_local *local = dev->priv;
struct ieee80211_sub_if_data *sdata;
size_t len = data->length;
@@ -1759,14 +1758,14 @@ static int ieee80211_ioctl_siwessid(stru
sdata->type == IEEE80211_IF_TYPE_IBSS)
return ieee80211_sta_set_ssid(dev, ssid, len);
- kfree(local->conf.ssid);
- local->conf.ssid = kmalloc(len + 1, GFP_KERNEL);
- if (local->conf.ssid == NULL)
- return -ENOMEM;
- memcpy(local->conf.ssid, ssid, len);
- local->conf.ssid[len] = '\0';
- local->conf.ssid_len = len;
- return ieee80211_hw_config(dev);
+ if (sdata->type == IEEE80211_IF_TYPE_AP) {
+ memcpy(sdata->u.ap.ssid, ssid, len);
+ memset(sdata->u.ap.ssid + len, 0,
+ IEEE80211_MAX_SSID_LEN - len);
+ sdata->u.ap.ssid_len = len;
+ return ieee80211_if_config(dev);
+ }
+ return -EOPNOTSUPP;
}
@@ -1774,7 +1773,6 @@ static int ieee80211_ioctl_giwessid(stru
struct iw_request_info *info,
struct iw_point *data, char *ssid)
{
- struct ieee80211_local *local = dev->priv;
size_t len;
struct ieee80211_sub_if_data *sdata;
@@ -1790,13 +1788,16 @@ static int ieee80211_ioctl_giwessid(stru
return res;
}
- len = local->conf.ssid_len;
- if (len > IW_ESSID_MAX_SIZE)
- len = IW_ESSID_MAX_SIZE;
- memcpy(ssid, local->conf.ssid, len);
- data->length = len;
- data->flags = 1;
- return 0;
+ if (sdata->type == IEEE80211_IF_TYPE_AP) {
+ len = sdata->u.ap.ssid_len;
+ if (len > IW_ESSID_MAX_SIZE)
+ len = IW_ESSID_MAX_SIZE;
+ memcpy(ssid, sdata->u.ap.ssid, len);
+ data->length = len;
+ data->flags = 1;
+ return 0;
+ }
+ return -EOPNOTSUPP;
}
@@ -1848,12 +1849,20 @@ static int ieee80211_ioctl_siwscan(struc
struct iw_point *data, char *extra)
{
struct ieee80211_local *local = dev->priv;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
u8 *ssid = NULL;
size_t ssid_len = 0;
if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
- ssid = local->conf.ssid;
- ssid_len = local->conf.ssid_len;
+ if (sdata->type == IEEE80211_IF_TYPE_STA ||
+ sdata->type == IEEE80211_IF_TYPE_IBSS) {
+ ssid = sdata->u.sta.ssid;
+ ssid_len = sdata->u.sta.ssid_len;
+ } else if (sdata == IEEE80211_IF_TYPE_AP) {
+ ssid = sdata->u.ap.ssid;
+ ssid_len = sdata->u.ap.ssid_len;
+ } else
+ return -EINVAL;
}
return ieee80211_sta_req_scan(dev, ssid, ssid_len);
}
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 6/10] d80211: per-interface generic_elem
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
` (4 preceding siblings ...)
2006-04-21 20:53 ` [PATCH 5/10] d80211: per-interface SSID Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
2006-04-21 20:53 ` [PATCH 7/10] d80211: get rid of default AP interface Jiri Benc
` (3 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
Allow generic element to be set independently for each interface.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
include/net/d80211.h | 12 +++++++-----
net/d80211/ieee80211.c | 6 ++++--
net/d80211/ieee80211_i.h | 2 ++
net/d80211/ieee80211_iface.c | 1 +
net/d80211/ieee80211_ioctl.c | 19 ++++++++++---------
5 files changed, 24 insertions(+), 16 deletions(-)
330ee7fb14673a5c69000a2c31c83830d7c6c456
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 065b34c..4bdbdbe 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -249,11 +249,6 @@ struct ieee80211_conf {
int short_slot_time:1; /* use IEEE 802.11g Short Slot Time */
int ssid_hidden:1; /* do not broadcast the ssid */
- /* these fields are used by low level drivers for hardware
- * that generate beacons independently */
- u8 *generic_elem;
- size_t generic_elem_len;
-
u8 power_level; /* transmit power limit for current
* regulatory domain; in dBm */
u8 antenna_max; /* maximum antenna gain */
@@ -347,6 +342,11 @@ struct ieee80211_if_init_conf {
* config_interface() callback (so copy the value somewhere if you need
* it).
* @ssid_len: length of the @ssid field.
+ * @generic_elem: used (together with @generic_elem_len) by drivers for
+ * hardware that generate beacons independently. The pointer is valid
+ * only during config_interface() callback (so copy the value somewhere
+ * if you need it).
+ * @generic_elem_len: length of the generic element.
*
* This structure is passed to config_interface() callback of
* &struct ieee80211_hw.
@@ -356,6 +356,8 @@ struct ieee80211_if_conf {
u8 *bssid;
u8 *ssid;
size_t ssid_len;
+ u8 *generic_elem;
+ size_t generic_elem_len;
};
typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL }
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 984c2b0..ad63bab 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1764,9 +1764,13 @@ int ieee80211_if_config(struct net_devic
conf.bssid = sdata->u.sta.bssid;
conf.ssid = sdata->u.sta.ssid;
conf.ssid_len = sdata->u.sta.ssid_len;
+ conf.generic_elem = sdata->u.sta.extra_ie;
+ conf.generic_elem_len = sdata->u.sta.extra_ie_len;
} else if (sdata->type == IEEE80211_IF_TYPE_AP) {
conf.ssid = sdata->u.ap.ssid;
conf.ssid_len = sdata->u.ap.ssid_len;
+ conf.generic_elem = sdata->u.ap.generic_elem;
+ conf.generic_elem_len = sdata->u.ap.generic_elem_len;
}
return local->hw->config_interface(local->mdev, dev->ifindex, &conf);
}
@@ -4342,8 +4346,6 @@ void ieee80211_unregister_hw(struct net_
kfree(local->basic_rates[i]);
}
- kfree(local->conf.generic_elem);
-
ieee80211_proc_deinit_interface(local);
if (skb_queue_len(&local->skb_queue)
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index e78beb2..98c30ff 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -194,6 +194,8 @@ struct ieee80211_if_ap {
u8 ssid[IEEE80211_MAX_SSID_LEN];
size_t ssid_len;
+ u8 *generic_elem;
+ size_t generic_elem_len;
/* TODO: sta_aid could be replaced by 2008-bit large bitfield of
* that could be used in TIM element generation. This would also
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index dd809c2..42ea643 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -175,6 +175,7 @@ #endif
kfree(sdata->u.ap.beacon_head);
kfree(sdata->u.ap.beacon_tail);
+ kfree(sdata->u.ap.generic_elem);
if (dev != local->mdev) {
struct sk_buff *skb;
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 6b73e27..3eaad0a 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1137,7 +1137,6 @@ #endif
static int ieee80211_set_gen_ie(struct net_device *dev, u8 *ie, size_t len)
{
- struct ieee80211_local *local = dev->priv;
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1145,14 +1144,16 @@ static int ieee80211_set_gen_ie(struct n
sdata->type == IEEE80211_IF_TYPE_IBSS)
return ieee80211_sta_set_extra_ie(dev, ie, len);
- kfree(local->conf.generic_elem);
- local->conf.generic_elem = kmalloc(len, GFP_KERNEL);
- if (local->conf.generic_elem == NULL)
- return -ENOMEM;
- memcpy(local->conf.generic_elem, ie, len);
- local->conf.generic_elem_len = len;
-
- return ieee80211_hw_config(dev);
+ if (sdata->type == IEEE80211_IF_TYPE_AP) {
+ kfree(sdata->u.ap.generic_elem);
+ sdata->u.ap.generic_elem = kmalloc(len, GFP_KERNEL);
+ if (sdata->u.ap.generic_elem == NULL)
+ return -ENOMEM;
+ memcpy(sdata->u.ap.generic_elem, ie, len);
+ sdata->u.ap.generic_elem_len = len;
+ return ieee80211_if_config(dev);
+ }
+ return -EOPNOTSUPP;
}
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 7/10] d80211: get rid of default AP interface
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
` (5 preceding siblings ...)
2006-04-21 20:53 ` [PATCH 6/10] d80211: per-interface generic_elem Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
2006-04-21 20:53 ` [PATCH 8/10] d80211: get rid of default management interface Jiri Benc
` (2 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
There is no need for default non-removable AP interface (wlanX), it just
confuses users. This patch removes it and renames master interface from
wlanX.11 to wlanX.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
net/d80211/ieee80211.c | 78 +++++++++---------------------------------
net/d80211/ieee80211_i.h | 3 +-
net/d80211/ieee80211_iface.c | 3 +-
net/d80211/ieee80211_ioctl.c | 12 +++---
net/d80211/ieee80211_proc.c | 8 ++--
5 files changed, 27 insertions(+), 77 deletions(-)
11da4bbdb5dd3f83a991f9e8df2d2356606b87b4
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index ad63bab..2386454 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -2032,7 +2032,7 @@ static int ieee80211_open(struct net_dev
struct net_device *ndev = nsdata->dev;
if (ndev != dev && ndev != local->mdev &&
- ndev != local->wdev && ndev != local->apdev &&
+ ndev != local->apdev &&
netif_running(ndev) &&
memcmp(dev->dev_addr, ndev->dev_addr, ETH_ALEN) == 0 &&
!identical_mac_addr_allowed(sdata->type, nsdata->type)) {
@@ -3684,7 +3684,7 @@ static void ieee80211_tasklet_handler(un
break;
default: /* should never get here! */
printk(KERN_ERR "%s: Unknown message type (%d)\n",
- local->wdev->name, skb->pkt_type);
+ local->mdev->name, skb->pkt_type);
dev_kfree_skb(skb);
break;
}
@@ -3979,7 +3979,7 @@ static void ieee80211_if_init(struct net
}
-/* Must not be called for wdev, mdev and apdev */
+/* Must not be called for mdev and apdev */
void ieee80211_if_setup(struct net_device *dev)
{
ether_setup(dev);
@@ -4018,7 +4018,7 @@ static void ieee80211_precalc_rates(stru
struct net_device *ieee80211_alloc_hw(size_t priv_data_len,
void (*setup)(struct net_device *))
{
- struct net_device *dev, *apdev, *mdev;
+ struct net_device *apdev, *mdev;
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
int alloc_size;
@@ -4042,10 +4042,6 @@ struct net_device *ieee80211_alloc_hw(si
* 17c0 *****************
* * sub_if *
* *****************
- * * master net_dev*
- * *****************
- * * sub_if *
- * *****************
*/
alloc_size = sizeof(struct net_device) +
sizeof(struct ieee80211_sub_if_data) + 3 +
@@ -4053,8 +4049,6 @@ struct net_device *ieee80211_alloc_hw(si
priv_data_len + 3 +
sizeof(struct net_device) + 3 +
sizeof(struct ieee80211_sub_if_data) + 3 +
- sizeof(struct net_device) + 3 +
- sizeof(struct ieee80211_sub_if_data) + 3 +
4096;
mdev = (struct net_device *) kzalloc(alloc_size, GFP_KERNEL);
if (mdev == NULL)
@@ -4069,29 +4063,14 @@ struct net_device *ieee80211_alloc_hw(si
((char *) local + ((sizeof(struct ieee80211_local) + 3) & ~3));
apdev = (struct net_device *)
((char *) local->hw_priv + ((priv_data_len + 3) & ~3));
- dev = (struct net_device *)
- ((char *) apdev +
- ((sizeof(struct net_device) + 3) & ~3) +
- ((sizeof(struct ieee80211_sub_if_data) + 3) & ~3));
- dev->priv = local;
- ether_setup(dev);
- memcpy(dev->name, "wlan%d", 7);
+ ether_setup(mdev);
+ memcpy(mdev->name, "wlan%d", 7);
- dev->hard_start_xmit = ieee80211_subif_start_xmit;
- dev->wireless_handlers =
- (struct iw_handler_def *) &ieee80211_iw_handler_def;
- dev->do_ioctl = ieee80211_ioctl;
- dev->change_mtu = ieee80211_change_mtu;
- dev->tx_timeout = ieee80211_tx_timeout;
- dev->get_stats = ieee80211_get_stats;
- dev->open = ieee80211_open;
- dev->stop = ieee80211_stop;
- dev->tx_queue_len = 0;
- dev->set_mac_address = ieee80211_set_mac_address;
+ if (strlen(mdev->name) + 2 >= sizeof(mdev->name))
+ goto fail;
local->dev_index = -1;
- local->wdev = dev;
local->mdev = mdev;
local->rx_handlers = ieee80211_rx_handlers;
local->tx_handlers = ieee80211_tx_handlers;
@@ -4119,22 +4098,11 @@ struct net_device *ieee80211_alloc_hw(si
init_timer(&local->stat_timer);
local->stat_timer.function = ieee80211_stat_refresh;
local->stat_timer.data = (unsigned long) local;
- ieee80211_rx_bss_list_init(dev);
+ ieee80211_rx_bss_list_init(mdev);
sta_info_init(local);
- ieee80211_if_init(dev);
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- sdata->dev = dev;
- sdata->master = mdev;
- sdata->local = local;
- ieee80211_if_sdata_init(sdata);
- ieee80211_if_set_type(dev, IEEE80211_IF_TYPE_AP);
- list_add_tail(&sdata->list, &local->sub_if_list);
-
- if (strlen(dev->name) + 2 >= sizeof(dev->name))
- goto fail;
+ ieee80211_if_init(mdev);
apdev = (struct net_device *)
((char *) local->hw_priv + ((priv_data_len + 3) & ~3));
@@ -4149,7 +4117,7 @@ struct net_device *ieee80211_alloc_hw(si
apdev->type = ARPHRD_IEEE80211_PRISM;
apdev->hard_header_parse = header_parse_80211;
apdev->tx_queue_len = 0;
- sprintf(apdev->name, "%sap", dev->name);
+ sprintf(apdev->name, "%sap", mdev->name);
sdata = IEEE80211_DEV_TO_SUB_IF(apdev);
sdata->type = IEEE80211_IF_TYPE_MGMT;
@@ -4158,7 +4126,6 @@ struct net_device *ieee80211_alloc_hw(si
sdata->local = local;
list_add_tail(&sdata->list, &local->sub_if_list);
- ether_setup(mdev);
mdev->hard_start_xmit = ieee80211_master_start_xmit;
mdev->wireless_handlers =
(struct iw_handler_def *) &ieee80211_iw_handler_def;
@@ -4170,7 +4137,6 @@ struct net_device *ieee80211_alloc_hw(si
mdev->stop = ieee80211_master_stop;
mdev->type = ARPHRD_IEEE80211;
mdev->hard_header_parse = header_parse_80211;
- sprintf(mdev->name, "%s.11", dev->name);
sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
sdata->type = IEEE80211_IF_TYPE_AP;
@@ -4226,19 +4192,15 @@ int ieee80211_register_hw(struct net_dev
sta_info_start(local);
- result = register_netdev(local->wdev);
- if (result < 0)
- goto fail_1st_dev;
-
result = register_netdev(local->apdev);
if (result < 0)
- goto fail_2nd_dev;
+ goto fail_1st_dev;
if (hw->fraglist)
dev->features |= NETIF_F_FRAGLIST;
result = register_netdev(dev);
if (result < 0)
- goto fail_3rd_dev;
+ goto fail_2nd_dev;
if (rate_control_initialize(local) < 0) {
printk(KERN_DEBUG "%s: Failed to initialize rate control "
@@ -4255,10 +4217,8 @@ int ieee80211_register_hw(struct net_dev
fail_rate:
unregister_netdev(dev);
-fail_3rd_dev:
- unregister_netdev(local->apdev);
fail_2nd_dev:
- unregister_netdev(local->wdev);
+ unregister_netdev(local->apdev);
fail_1st_dev:
sta_info_stop(local);
ieee80211_unregister_sysfs(local);
@@ -4284,12 +4244,6 @@ int ieee80211_update_hw(struct net_devic
local->apdev->mem_start = dev->mem_start;
local->apdev->mem_end = dev->mem_end;
- memcpy(local->wdev->dev_addr, dev->dev_addr, ETH_ALEN);
- local->wdev->base_addr = dev->base_addr;
- local->wdev->irq = dev->irq;
- local->wdev->mem_start = dev->mem_start;
- local->wdev->mem_end = dev->mem_end;
-
if (!hw->modes || !hw->modes->channels || !hw->modes->rates ||
!hw->modes->num_channels || !hw->modes->num_rates)
return -1;
@@ -4470,14 +4424,14 @@ static int rate_control_initialize(struc
local->rate_ctrl_priv = rate_control_alloc(local);
if (local->rate_ctrl_priv) {
printk(KERN_DEBUG "%s: Selected rate control "
- "algorithm '%s'\n", local->wdev->name,
+ "algorithm '%s'\n", local->mdev->name,
local->rate_ctrl->name);
return 0;
}
}
printk(KERN_WARNING "%s: Failed to select rate control algorithm\n",
- local->wdev->name);
+ local->mdev->name);
return -1;
}
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 98c30ff..77517c9 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -316,8 +316,7 @@ #define IEEE80211_SUB_IF_TO_DEV(sub_if)
struct ieee80211_local {
struct ieee80211_hw *hw;
void *hw_priv;
- struct net_device *mdev; /* wlan#.11 - "master" 802.11 device */
- struct net_device *wdev; /* wlan# - default Ethernet (data) devide */
+ struct net_device *mdev; /* wlan# - "master" 802.11 device */
struct net_device *apdev; /* wlan#ap - management frames (hostapd) */
int open_count;
int monitors;
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 42ea643..58fd946 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -258,7 +258,6 @@ int ieee80211_if_remove(struct net_devic
if ((sdata->type == id || id == -1) &&
strcmp(name, sdata->dev->name) == 0 &&
sdata->dev != local->mdev &&
- sdata->dev != local->wdev &&
sdata->dev != local->apdev) {
__ieee80211_if_del(local, sdata);
return 0;
@@ -271,7 +270,7 @@ void ieee80211_if_free(struct net_device
{
struct ieee80211_local *local = dev->priv;
- BUG_ON(dev == local->mdev || dev == local->wdev || dev == local->apdev);
+ BUG_ON(dev == local->mdev || dev == local->apdev);
kfree(dev);
}
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 3eaad0a..1d3f5cf 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -499,13 +499,11 @@ static int ieee80211_set_encryption(stru
* must be used. This should be done automatically
* based on configured station devices. For the time
* being, this can be only set at compile time. */
- if (sdata->type == IEEE80211_IF_TYPE_STA) {
- if (0 /* FIX: more than one STA per AP */)
- try_hwaccel = 0;
- } else
- if (sdata->type != IEEE80211_IF_TYPE_AP ||
- dev != local->wdev)
- try_hwaccel = 0;
+ /* FIXME: There is no more anything like "default
+ * interface". We should try hwaccel if there is just one
+ * interface - for now, hwaccel is unconditionaly
+ * disabled. */
+ try_hwaccel = 0;
} else {
set_tx_key = 0;
if (idx != 0) {
diff --git a/net/d80211/ieee80211_proc.c b/net/d80211/ieee80211_proc.c
index a886280..c9f5567 100644
--- a/net/d80211/ieee80211_proc.c
+++ b/net/d80211/ieee80211_proc.c
@@ -702,7 +702,7 @@ void ieee80211_proc_init_interface(struc
if (!ieee80211_proc)
return;
- local->proc = proc_mkdir(local->wdev->name, ieee80211_proc);
+ local->proc = proc_mkdir(local->mdev->name, ieee80211_proc);
if (!local->proc)
return;
@@ -722,7 +722,7 @@ void ieee80211_proc_init_interface(struc
ieee80211_proc_debug_read, local);
create_proc_read_entry("info", 0, local->proc,
ieee80211_proc_info_read, local);
- ieee80211_proc_init_virtual(local->wdev);
+ ieee80211_proc_init_virtual(local->mdev);
}
@@ -731,7 +731,7 @@ void ieee80211_proc_deinit_interface(str
if (!local->proc)
return;
- ieee80211_proc_deinit_virtual(local->wdev);
+ ieee80211_proc_deinit_virtual(local->mdev);
remove_proc_entry("iface", local->proc);
remove_proc_entry("sta", local->proc);
remove_proc_entry("counters", local->proc);
@@ -742,7 +742,7 @@ void ieee80211_proc_deinit_interface(str
remove_proc_entry("multicast", local->proc);
remove_proc_entry("info", local->proc);
local->proc = NULL;
- remove_proc_entry(local->wdev->name, ieee80211_proc);
+ remove_proc_entry(local->mdev->name, ieee80211_proc);
}
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 8/10] d80211: get rid of default management interface
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
` (6 preceding siblings ...)
2006-04-21 20:53 ` [PATCH 7/10] d80211: get rid of default AP interface Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
2006-04-21 20:59 ` Johannes Berg
2006-04-22 2:44 ` Jouni Malinen
2006-04-21 20:53 ` [PATCH 9/10] d80211: rename master interface Jiri Benc
2006-04-21 20:53 ` [PATCH 10/10] d80211: add one default interface Jiri Benc
9 siblings, 2 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
Default management interface (wlanXap) confuses users. It is only needed for
AP mode (and only until interfaces are converted to use native 802.11
frames).
This patch removes default management interface. When a new interface is
switched to AP mode, a management interface is created automatically. This
also fixes some problems with multiple AP interfaces - now you have
different management interface for each AP interface.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
net/d80211/ieee80211.c | 204 +++++++++++++++++++++++++-----------------
net/d80211/ieee80211_i.h | 6 +
net/d80211/ieee80211_iface.c | 73 ++++++++++++++-
3 files changed, 193 insertions(+), 90 deletions(-)
726d59fb8b157daf368b097cef7d3d2ed8c61784
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 2386454..31f979c 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -59,6 +59,8 @@ static int rate_control_initialize(struc
static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);
+static void ieee80211_rx_michael_mic_report(struct ieee80211_txrx_data *rx,
+ struct ieee80211_hdr *hdr);
struct ieee80211_key_conf *
ieee80211_key_data2conf(struct ieee80211_local *local,
@@ -1954,8 +1956,6 @@ static inline int identical_mac_addr_all
{
return (type1 == IEEE80211_IF_TYPE_MNTR ||
type2 == IEEE80211_IF_TYPE_MNTR ||
- type1 == IEEE80211_IF_TYPE_MGMT ||
- type2 == IEEE80211_IF_TYPE_MGMT ||
(type1 == IEEE80211_IF_TYPE_AP &&
type2 == IEEE80211_IF_TYPE_WDS) ||
(type1 == IEEE80211_IF_TYPE_WDS &&
@@ -1990,6 +1990,20 @@ static int ieee80211_master_stop(struct
return 0;
}
+static int ieee80211_ap_open(struct net_device *dev)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ if (!netif_running(sdata->u.ap.apdev))
+ return -EOPNOTSUPP;
+ return 0;
+}
+
+static int ieee80211_ap_stop(struct net_device *dev)
+{
+ return 0;
+}
+
/* Check if running monitor interfaces should go to a "soft monitor" mode
* and switch them if necessary. */
static inline void ieee80211_start_soft_monitor(struct ieee80211_local *local)
@@ -2032,7 +2046,6 @@ static int ieee80211_open(struct net_dev
struct net_device *ndev = nsdata->dev;
if (ndev != dev && ndev != local->mdev &&
- ndev != local->apdev &&
netif_running(ndev) &&
memcmp(dev->dev_addr, ndev->dev_addr, ETH_ALEN) == 0 &&
!identical_mac_addr_allowed(sdata->type, nsdata->type)) {
@@ -2087,7 +2100,9 @@ static int ieee80211_open(struct net_dev
}
local->open_count++;
- if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+ if (sdata->type == IEEE80211_IF_TYPE_AP)
+ dev_open(sdata->u.ap.apdev);
+ else if (sdata->type == IEEE80211_IF_TYPE_MNTR)
local->monitors++;
netif_start_queue(dev);
@@ -2112,7 +2127,9 @@ static int ieee80211_stop(struct net_dev
netif_stop_queue(dev);
- if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+ if (sdata->type == IEEE80211_IF_TYPE_AP)
+ dev_close(sdata->u.ap.apdev);
+ else if (sdata->type == IEEE80211_IF_TYPE_MNTR)
local->monitors--;
local->open_count--;
@@ -2356,6 +2373,7 @@ ieee80211_get_rate(struct ieee80211_loca
}
+/* If dev is master device, skb will be sent to all AP interfaces. */
void
ieee80211_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
struct ieee80211_rx_status *status, u32 msg_type)
@@ -2363,13 +2381,15 @@ ieee80211_rx_mgmt(struct net_device *dev
struct ieee80211_local *local = dev->priv;
struct ieee80211_frame_info *fi;
size_t hlen;
- struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_sub_if_data *sdata, *apsdata, *prev = NULL;
- if (msg_type != ieee80211_msg_monitor)
- dev = local->apdev;
- skb->dev = dev;
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (msg_type != ieee80211_msg_monitor &&
+ sdata->type != IEEE80211_IF_TYPE_AP && dev != local->mdev) {
+ dev_kfree_skb(skb);
+ return;
+ }
if (skb_headroom(skb) < sizeof(struct ieee80211_frame_info)) {
I802_DEBUG_INC(local->rx_expand_skb_head);
@@ -2443,15 +2463,56 @@ ieee80211_rx_mgmt(struct net_device *dev
fi->ssi_type = htonl(ieee80211_ssi_none);
}
- sdata->stats.rx_packets++;
- sdata->stats.rx_bytes += skb->len;
-
skb->mac.raw = skb->data;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = __constant_htons(ETH_P_802_2);
memset(skb->cb, 0, sizeof(skb->cb));
- netif_rx(skb);
+
+ if (msg_type == ieee80211_msg_monitor) {
+ skb->dev = dev;
+ sdata->stats.rx_packets++;
+ sdata->stats.rx_bytes += skb->len;
+ netif_rx(skb);
+ return;
+ }
+
+ if (dev == local->mdev) {
+ list_for_each_entry(sdata, &local->sub_if_list, list) {
+ if (sdata->type != IEEE80211_IF_TYPE_AP ||
+ sdata->dev == local->mdev)
+ continue;
+ if (prev) {
+ struct sk_buff *skb_new;
+
+ skb_new = skb_copy(skb, GFP_ATOMIC);
+ if (skb_new == NULL) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: failed "
+ "to copy message for %s",
+ dev->name,
+ prev->u.ap.apdev->name);
+ }
+ continue;
+ }
+ skb_new->dev = prev->u.ap.apdev;
+ apsdata = IEEE80211_DEV_TO_SUB_IF(skb_new->dev);
+ apsdata->stats.rx_packets++;
+ apsdata->stats.rx_bytes += skb_new->len;
+ netif_rx(skb_new);
+ }
+ prev = sdata;
+ }
+ sdata = prev;
+ }
+ if (sdata) {
+ skb->dev = sdata->u.ap.apdev;
+ apsdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
+ apsdata->stats.rx_packets++;
+ apsdata->stats.rx_bytes += skb->len;
+ netif_rx(skb);
+ } else
+ dev_kfree_skb(skb);
}
@@ -2839,6 +2900,11 @@ ieee80211_rx_h_check(struct ieee80211_tx
int always_sta_key;
hdr = (struct ieee80211_hdr *) rx->skb->data;
+ if ((rx->u.rx.status->flag & RX_FLAG_MMIC_ERROR)) {
+ ieee80211_rx_michael_mic_report(rx, hdr);
+ return TXRX_QUEUED;
+ }
+
/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
if (unlikely(rx->fc & WLAN_FC_RETRY &&
@@ -3207,10 +3273,8 @@ static u8 * ieee80211_get_bssid(struct i
return NULL;
}
-static void ieee80211_rx_michael_mic_report(struct net_device *dev,
- struct ieee80211_hdr *hdr,
- struct sta_info *sta,
- struct ieee80211_txrx_data *rx)
+static void ieee80211_rx_michael_mic_report(struct ieee80211_txrx_data *rx,
+ struct ieee80211_hdr *hdr)
{
int keyidx, hdrlen;
@@ -3224,22 +3288,22 @@ static void ieee80211_rx_michael_mic_rep
* frames (hw does not verify MIC for them). */
printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC "
"failure from " MACSTR " to " MACSTR " keyidx=%d\n",
- dev->name, MAC2STR(hdr->addr2), MAC2STR(hdr->addr1), keyidx);
+ rx->dev->name, MAC2STR(hdr->addr2), MAC2STR(hdr->addr1), keyidx);
- if (sta == NULL) {
+ if (rx->sta == NULL) {
/* Some hardware versions seem to generate incorrect
* Michael MIC reports; ignore them to avoid triggering
* countermeasures. */
printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
"error for unknown address " MACSTR "\n",
- dev->name, MAC2STR(hdr->addr2));
+ rx->dev->name, MAC2STR(hdr->addr2));
goto ignore;
}
if (!(rx->fc & WLAN_FC_ISWEP)) {
printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
"error for a frame with no ISWEP flag (src "
- MACSTR ")\n", dev->name, MAC2STR(hdr->addr2));
+ MACSTR ")\n", rx->dev->name, MAC2STR(hdr->addr2));
goto ignore;
}
@@ -3253,7 +3317,8 @@ static void ieee80211_rx_michael_mic_rep
if (keyidx) {
printk(KERN_DEBUG "%s: ignored Michael MIC error for "
"a frame with non-zero keyidx (%d) (src " MACSTR
- ")\n", dev->name, keyidx, MAC2STR(hdr->addr2));
+ ")\n", rx->dev->name, keyidx,
+ MAC2STR(hdr->addr2));
goto ignore;
}
}
@@ -3264,7 +3329,7 @@ static void ieee80211_rx_michael_mic_rep
printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
"error for a frame that cannot be encrypted "
"(fc=0x%04x) (src " MACSTR ")\n",
- dev->name, rx->fc, MAC2STR(hdr->addr2));
+ rx->dev->name, rx->fc, MAC2STR(hdr->addr2));
goto ignore;
}
@@ -3355,11 +3420,6 @@ void __ieee80211_rx(struct net_device *d
else
sta = rx.sta = NULL;
- if ((status->flag & RX_FLAG_MMIC_ERROR)) {
- ieee80211_rx_michael_mic_report(dev, hdr, sta, &rx);
- goto end;
- }
-
if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
!local->iff_promiscs && !multicast) {
rx.dev = sta->dev;
@@ -3444,7 +3504,6 @@ void __ieee80211_rx(struct net_device *d
dev_kfree_skb(skb);
}
- end:
if (sta)
sta_info_release(local, sta);
}
@@ -3761,6 +3820,7 @@ void ieee80211_tx_status(struct net_devi
struct sk_buff *skb2;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_local *local = dev->priv;
+ struct net_device *odev;
u16 frag, type;
u32 msg_type;
@@ -3894,7 +3954,21 @@ #endif /* IEEE80211_LEDS */
skb = skb2;
/* Send frame to hostapd */
- ieee80211_rx_mgmt(dev, skb, NULL, msg_type);
+ odev = dev_get_by_index(status->control.ifindex);
+ if (unlikely(odev && !is_ieee80211_device(odev))) {
+ dev_put(odev);
+ odev = NULL;
+ }
+ if (unlikely(!odev)) {
+#ifdef CONFIG_D80211_VERBOSE_DEBUG
+ printk(KERN_DEBUG "%s: Discarded tx_status from nonexistent "
+ "device\n", dev->name);
+#endif
+ dev_kfree_skb(skb);
+ return;
+ }
+ ieee80211_rx_mgmt(odev, skb, NULL, msg_type);
+ dev_put(odev);
}
@@ -3998,6 +4072,19 @@ void ieee80211_if_setup(struct net_devic
dev->destructor = ieee80211_if_free;
}
+void ieee80211_if_ap_setup(struct net_device *dev)
+{
+ ether_setup(dev);
+ dev->hard_start_xmit = ieee80211_mgmt_start_xmit;
+ dev->change_mtu = ieee80211_change_mtu_apdev;
+ dev->get_stats = ieee80211_get_stats;
+ dev->open = ieee80211_ap_open;
+ dev->stop = ieee80211_ap_stop;
+ dev->type = ARPHRD_IEEE80211_PRISM;
+ dev->hard_header_parse = header_parse_80211;
+ dev->tx_queue_len = 0;
+ dev->destructor = ieee80211_if_free;
+}
static void ieee80211_precalc_rates(struct ieee80211_hw *hw)
{
@@ -4018,7 +4105,7 @@ static void ieee80211_precalc_rates(stru
struct net_device *ieee80211_alloc_hw(size_t priv_data_len,
void (*setup)(struct net_device *))
{
- struct net_device *apdev, *mdev;
+ struct net_device *mdev;
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
int alloc_size;
@@ -4038,17 +4125,11 @@ struct net_device *ieee80211_alloc_hw(si
* 0b84 *****************
* * hw_priv *
* 1664 *****************
- * * ap net_dev *
- * 17c0 *****************
- * * sub_if *
- * *****************
*/
alloc_size = sizeof(struct net_device) +
sizeof(struct ieee80211_sub_if_data) + 3 +
sizeof(struct ieee80211_local) + 3 +
priv_data_len + 3 +
- sizeof(struct net_device) + 3 +
- sizeof(struct ieee80211_sub_if_data) + 3 +
4096;
mdev = (struct net_device *) kzalloc(alloc_size, GFP_KERNEL);
if (mdev == NULL)
@@ -4061,15 +4142,10 @@ struct net_device *ieee80211_alloc_hw(si
local = mdev->priv;
local->hw_priv = (void *)
((char *) local + ((sizeof(struct ieee80211_local) + 3) & ~3));
- apdev = (struct net_device *)
- ((char *) local->hw_priv + ((priv_data_len + 3) & ~3));
ether_setup(mdev);
memcpy(mdev->name, "wlan%d", 7);
- if (strlen(mdev->name) + 2 >= sizeof(mdev->name))
- goto fail;
-
local->dev_index = -1;
local->mdev = mdev;
local->rx_handlers = ieee80211_rx_handlers;
@@ -4104,28 +4180,6 @@ struct net_device *ieee80211_alloc_hw(si
ieee80211_if_init(mdev);
- apdev = (struct net_device *)
- ((char *) local->hw_priv + ((priv_data_len + 3) & ~3));
- local->apdev = apdev;
- ether_setup(apdev);
- apdev->priv = local;
- apdev->hard_start_xmit = ieee80211_mgmt_start_xmit;
- apdev->change_mtu = ieee80211_change_mtu_apdev;
- apdev->get_stats = ieee80211_get_stats;
- apdev->open = ieee80211_open;
- apdev->stop = ieee80211_stop;
- apdev->type = ARPHRD_IEEE80211_PRISM;
- apdev->hard_header_parse = header_parse_80211;
- apdev->tx_queue_len = 0;
- sprintf(apdev->name, "%sap", mdev->name);
-
- sdata = IEEE80211_DEV_TO_SUB_IF(apdev);
- sdata->type = IEEE80211_IF_TYPE_MGMT;
- sdata->dev = apdev;
- sdata->master = mdev;
- sdata->local = local;
- list_add_tail(&sdata->list, &local->sub_if_list);
-
mdev->hard_start_xmit = ieee80211_master_start_xmit;
mdev->wireless_handlers =
(struct iw_handler_def *) &ieee80211_iw_handler_def;
@@ -4155,10 +4209,6 @@ struct net_device *ieee80211_alloc_hw(si
setup(mdev);
return mdev;
-
- fail:
- ieee80211_free_hw(mdev);
- return NULL;
}
@@ -4192,15 +4242,11 @@ int ieee80211_register_hw(struct net_dev
sta_info_start(local);
- result = register_netdev(local->apdev);
- if (result < 0)
- goto fail_1st_dev;
-
if (hw->fraglist)
dev->features |= NETIF_F_FRAGLIST;
result = register_netdev(dev);
if (result < 0)
- goto fail_2nd_dev;
+ goto fail_dev;
if (rate_control_initialize(local) < 0) {
printk(KERN_DEBUG "%s: Failed to initialize rate control "
@@ -4217,9 +4263,7 @@ int ieee80211_register_hw(struct net_dev
fail_rate:
unregister_netdev(dev);
-fail_2nd_dev:
- unregister_netdev(local->apdev);
-fail_1st_dev:
+fail_dev:
sta_info_stop(local);
ieee80211_unregister_sysfs(local);
fail_sysfs:
@@ -4238,12 +4282,6 @@ int ieee80211_update_hw(struct net_devic
if (hw->queues == 0)
hw->queues = 1;
- memcpy(local->apdev->dev_addr, dev->dev_addr, ETH_ALEN);
- local->apdev->base_addr = dev->base_addr;
- local->apdev->irq = dev->irq;
- local->apdev->mem_start = dev->mem_start;
- local->apdev->mem_end = dev->mem_end;
-
if (!hw->modes || !hw->modes->channels || !hw->modes->rates ||
!hw->modes->num_channels || !hw->modes->num_rates)
return -1;
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 77517c9..ea1d9ab 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -189,6 +189,8 @@ typedef ieee80211_txrx_result (*ieee8021
(struct ieee80211_txrx_data *rx);
struct ieee80211_if_ap {
+ struct net_device *apdev; /* wlan#ap - management frames (hostapd) */
+
u8 *beacon_head, *beacon_tail;
int beacon_head_len, beacon_tail_len;
@@ -317,7 +319,6 @@ struct ieee80211_local {
struct ieee80211_hw *hw;
void *hw_priv;
struct net_device *mdev; /* wlan# - "master" 802.11 device */
- struct net_device *apdev; /* wlan#ap - management frames (hostapd) */
int open_count;
int monitors;
struct ieee80211_conf conf;
@@ -518,6 +519,7 @@ void ieee80211_prepare_rates(struct net_
void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
void ieee80211_if_setup(struct net_device *dev);
+void ieee80211_if_ap_setup(struct net_device *dev);
/* ieee80211_ioctl.c */
int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -586,7 +588,7 @@ int ieee80211_dev_find_index(struct ieee
/* ieee80211_iface.c */
int ieee80211_if_add(struct net_device *dev, const char *name,
struct net_device **new_dev);
-void ieee80211_if_set_type(struct net_device *dev, int type);
+int ieee80211_if_set_type(struct net_device *dev, int type);
void ieee80211_if_reinit(struct net_device *dev);
void __ieee80211_if_del(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 58fd946..d71d4f9 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -87,9 +87,65 @@ int ieee80211_if_add(struct net_device *
return 0;
}
-void ieee80211_if_set_type(struct net_device *dev, int type)
+static int ieee80211_if_add_apdev(struct net_device *dev)
+{
+ struct net_device *ndev;
+ struct ieee80211_local *local = dev->priv;
+ struct ieee80211_sub_if_data *sdata, *nsdata;
+ int alloc_size, ret;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ ASSERT_RTNL();
+ alloc_size = sizeof(struct net_device) + 3 +
+ sizeof(struct ieee80211_sub_if_data) + 3;
+
+ ndev = (struct net_device *) kzalloc(alloc_size, GFP_KERNEL);
+ if (ndev == NULL)
+ return -ENOMEM;
+ snprintf(ndev->name, IFNAMSIZ, "%sap", dev->name);
+
+ ndev->priv = local;
+ memcpy(ndev->dev_addr, dev->dev_addr, ETH_ALEN);
+ ndev->base_addr = dev->base_addr;
+ ndev->irq = dev->irq;
+ ndev->mem_start = dev->mem_start;
+ ndev->mem_end = dev->mem_end;
+ ieee80211_if_ap_setup(ndev);
+
+ nsdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+ nsdata->type = IEEE80211_IF_TYPE_AP;
+ nsdata->master = local->mdev;
+ nsdata->dev = ndev;
+ nsdata->local = local;
+ ieee80211_if_sdata_init(nsdata);
+
+ ret = register_netdevice(ndev);
+ if (ret) {
+ if (ret == -EEXIST)
+ printk(KERN_DEBUG "%s: apdev name %s already exists\n",
+ dev->name, ndev->name);
+ kfree(ndev);
+ return ret;
+ }
+ sdata->u.ap.apdev = ndev;
+ nsdata->u.ap.apdev = dev;
+ return 0;
+}
+
+static void ieee80211_if_del_apdev(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct net_device *apdev;
+
+ ASSERT_RTNL();
+ apdev = sdata->u.ap.apdev;
+ unregister_netdevice(apdev);
+}
+
+int ieee80211_if_set_type(struct net_device *dev, int type)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ int res = 0;
sdata->type = type;
switch (type) {
@@ -104,7 +160,11 @@ void ieee80211_if_set_type(struct net_de
sdata->u.ap.max_ratectrl_rateidx = -1;
skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
sdata->bss = &sdata->u.ap;
- break;
+ res = ieee80211_if_add_apdev(dev);
+ if (!res)
+ break;
+ sdata->type = IEEE80211_IF_TYPE_STA;
+ /* fallback to STA, but keep error value in `res' */
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS: {
struct ieee80211_sub_if_data *msdata;
@@ -131,7 +191,9 @@ void ieee80211_if_set_type(struct net_de
default:
printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
dev->name, __FUNCTION__, type);
+ res = -EINVAL;
}
+ return res;
}
/* Must be called with rtnl lock held. */
@@ -183,6 +245,8 @@ #endif
local->total_ps_buffered--;
dev_kfree_skb(skb);
}
+
+ ieee80211_if_del_apdev(dev);
}
break;
@@ -257,8 +321,7 @@ int ieee80211_if_remove(struct net_devic
list_for_each_entry_safe(sdata, n, &local->sub_if_list, list) {
if ((sdata->type == id || id == -1) &&
strcmp(name, sdata->dev->name) == 0 &&
- sdata->dev != local->mdev &&
- sdata->dev != local->apdev) {
+ sdata->dev != local->mdev) {
__ieee80211_if_del(local, sdata);
return 0;
}
@@ -270,7 +333,7 @@ void ieee80211_if_free(struct net_device
{
struct ieee80211_local *local = dev->priv;
- BUG_ON(dev == local->mdev || dev == local->apdev);
+ BUG_ON(dev == local->mdev);
kfree(dev);
}
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 8/10] d80211: get rid of default management interface
2006-04-21 20:53 ` [PATCH 8/10] d80211: get rid of default management interface Jiri Benc
@ 2006-04-21 20:59 ` Johannes Berg
2006-04-21 21:03 ` Jiri Benc
2006-04-22 2:44 ` Jouni Malinen
1 sibling, 1 reply; 18+ messages in thread
From: Johannes Berg @ 2006-04-21 20:59 UTC (permalink / raw)
To: Jiri Benc; +Cc: netdev, Jouni Malinen
[-- Attachment #1: Type: text/plain, Size: 484 bytes --]
On Fri, 2006-04-21 at 22:53 +0200, Jiri Benc wrote:
> Default management interface (wlanXap) confuses users. It is only needed for
> AP mode (and only until interfaces are converted to use native 802.11
> frames).
What's the management interface used for? In some small discussion
didn't we say that we'd rather move to having one netlink socket for
this?
Maybe then we can get away with not having native 802.11 devices which
seem to somewhat scare people...
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/10] d80211: get rid of default management interface
2006-04-21 20:59 ` Johannes Berg
@ 2006-04-21 21:03 ` Jiri Benc
0 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 21:03 UTC (permalink / raw)
To: Johannes Berg; +Cc: netdev, Jouni Malinen
On Fri, 21 Apr 2006 22:59:58 +0200, Johannes Berg wrote:
> What's the management interface used for? In some small discussion
> didn't we say that we'd rather move to having one netlink socket for
> this?
Yes, it's just a temporary solution.
> Maybe then we can get away with not having native 802.11 devices which
> seem to somewhat scare people...
We'll see :-) It's not so important now.
--
Jiri Benc
SUSE Labs
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/10] d80211: get rid of default management interface
2006-04-21 20:53 ` [PATCH 8/10] d80211: get rid of default management interface Jiri Benc
2006-04-21 20:59 ` Johannes Berg
@ 2006-04-22 2:44 ` Jouni Malinen
2006-04-24 13:01 ` Jiri Benc
1 sibling, 1 reply; 18+ messages in thread
From: Jouni Malinen @ 2006-04-22 2:44 UTC (permalink / raw)
To: Jiri Benc; +Cc: netdev
On Fri, Apr 21, 2006 at 10:53:28PM +0200, Jiri Benc wrote:
> Default management interface (wlanXap) confuses users. It is only needed for
> AP mode (and only until interfaces are converted to use native 802.11
> frames).
Or when using user space MLME in client mode which is something that I
just got working as far as scanning and association is concerned. In
other words, wpa_supplicant will be needing this interface..
> This patch removes default management interface. When a new interface is
> switched to AP mode, a management interface is created automatically. This
> also fixes some problems with multiple AP interfaces - now you have
> different management interface for each AP interface.
That sounds like something that could break multi-BSSID/SSID aware
hostapd. Are you saying that there would be new wlanXap like interface
for each BSS/VLAN interface? What are the problems this is fixing with
multiple AP interfaces? So far, hostapd has been responsible for
receiving all management from a single interface and then internally
decide which BSS/multi-SSID entry to use for each.
I would assume that hostapd could be changed to process frames from
multiple interfaces (at least if this is only for multi-BSSID, not for
multi-SSID/VLAN case). There may be some special cases, where it would
be easier to just be able to use one interface. Likewise, I would expect
single interface to be closer to a design that would be using netlink
for getting management frames into user space.
--
Jouni Malinen PGP id EFC895FA
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/10] d80211: get rid of default management interface
2006-04-22 2:44 ` Jouni Malinen
@ 2006-04-24 13:01 ` Jiri Benc
2006-04-26 18:53 ` John W. Linville
0 siblings, 1 reply; 18+ messages in thread
From: Jiri Benc @ 2006-04-24 13:01 UTC (permalink / raw)
To: Jouni Malinen; +Cc: netdev
On Fri, 21 Apr 2006 19:44:31 -0700, Jouni Malinen wrote:
> On Fri, Apr 21, 2006 at 10:53:28PM +0200, Jiri Benc wrote:
> > Default management interface (wlanXap) confuses users. It is only needed for
> > AP mode (and only until interfaces are converted to use native 802.11
> > frames).
>
> Or when using user space MLME in client mode which is something that I
> just got working as far as scanning and association is concerned. In
> other words, wpa_supplicant will be needing this interface..
I think we can (and should) wait with userspace MLME until the netlink
interface is implemented.
> That sounds like something that could break multi-BSSID/SSID aware
> hostapd. Are you saying that there would be new wlanXap like interface
> for each BSS/VLAN interface? What are the problems this is fixing with
> multiple AP interfaces?
Thinking about it more, only implementation problems. I was just lazy
and implementing things the way I did seemed to be easier. My fault,
sorry, didn't realize hostapd is aware of multiple BSSes.
> So far, hostapd has been responsible for
> receiving all management from a single interface and then internally
> decide which BSS/multi-SSID entry to use for each.
>
> I would assume that hostapd could be changed to process frames from
> multiple interfaces (at least if this is only for multi-BSSID, not for
> multi-SSID/VLAN case).
There is no point in changing hostapd as this solution is temporary only
and hostapd will need to be changed for netlink anyway.
I will fix the patch.
Thanks,
Jiri
--
Jiri Benc
SUSE Labs
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 8/10] d80211: get rid of default management interface
2006-04-24 13:01 ` Jiri Benc
@ 2006-04-26 18:53 ` John W. Linville
0 siblings, 0 replies; 18+ messages in thread
From: John W. Linville @ 2006-04-26 18:53 UTC (permalink / raw)
To: Jiri Benc; +Cc: Jouni Malinen, netdev
On Mon, Apr 24, 2006 at 03:01:48PM +0200, Jiri Benc wrote:
> On Fri, 21 Apr 2006 19:44:31 -0700, Jouni Malinen wrote:
> > On Fri, Apr 21, 2006 at 10:53:28PM +0200, Jiri Benc wrote:
> > > Default management interface (wlanXap) confuses users. It is only needed for
> > > AP mode (and only until interfaces are converted to use native 802.11
> > > frames).
> >
> > Or when using user space MLME in client mode which is something that I
> > just got working as far as scanning and association is concerned. In
> > other words, wpa_supplicant will be needing this interface..
>
> I think we can (and should) wait with userspace MLME until the netlink
> interface is implemented.
>
> > That sounds like something that could break multi-BSSID/SSID aware
> > hostapd. Are you saying that there would be new wlanXap like interface
> > for each BSS/VLAN interface? What are the problems this is fixing with
> > multiple AP interfaces?
>
> Thinking about it more, only implementation problems. I was just lazy
> and implementing things the way I did seemed to be easier. My fault,
> sorry, didn't realize hostapd is aware of multiple BSSes.
>
> > So far, hostapd has been responsible for
> > receiving all management from a single interface and then internally
> > decide which BSS/multi-SSID entry to use for each.
> >
> > I would assume that hostapd could be changed to process frames from
> > multiple interfaces (at least if this is only for multi-BSSID, not for
> > multi-SSID/VLAN case).
>
> There is no point in changing hostapd as this solution is temporary only
> and hostapd will need to be changed for netlink anyway.
>
> I will fix the patch.
I'm going to skip this patch for now. I'll merge the rest.
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 9/10] d80211: rename master interface
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
` (7 preceding siblings ...)
2006-04-21 20:53 ` [PATCH 8/10] d80211: get rid of default management interface Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
2006-04-21 21:02 ` Stephen Hemminger
2006-04-21 20:53 ` [PATCH 10/10] d80211: add one default interface Jiri Benc
9 siblings, 1 reply; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
Rename master interface to wmasterX to better reflect its purpose.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
net/d80211/ieee80211.c | 2 +-
net/d80211/ieee80211_i.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
784f203467e4421aa0ecac34cb1647f4bdfe51be
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 31f979c..1fd13dd 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4144,7 +4144,7 @@ struct net_device *ieee80211_alloc_hw(si
((char *) local + ((sizeof(struct ieee80211_local) + 3) & ~3));
ether_setup(mdev);
- memcpy(mdev->name, "wlan%d", 7);
+ memcpy(mdev->name, "wmaster%d", 10);
local->dev_index = -1;
local->mdev = mdev;
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index ea1d9ab..3580d1e 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -318,7 +318,7 @@ #define IEEE80211_SUB_IF_TO_DEV(sub_if)
struct ieee80211_local {
struct ieee80211_hw *hw;
void *hw_priv;
- struct net_device *mdev; /* wlan# - "master" 802.11 device */
+ struct net_device *mdev; /* wmaster# - "master" 802.11 device */
int open_count;
int monitors;
struct ieee80211_conf conf;
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 9/10] d80211: rename master interface
2006-04-21 20:53 ` [PATCH 9/10] d80211: rename master interface Jiri Benc
@ 2006-04-21 21:02 ` Stephen Hemminger
2006-04-21 21:06 ` Jiri Benc
0 siblings, 1 reply; 18+ messages in thread
From: Stephen Hemminger @ 2006-04-21 21:02 UTC (permalink / raw)
To: Jiri Benc; +Cc: netdev
On Fri, 21 Apr 2006 22:53:29 +0200 (CEST)
Jiri Benc <jbenc@suse.cz> wrote:
> Rename master interface to wmasterX to better reflect its purpose.
>
> Signed-off-by: Jiri Benc <jbenc@suse.cz>
>
> ---
>
> net/d80211/ieee80211.c | 2 +-
> net/d80211/ieee80211_i.h | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> 784f203467e4421aa0ecac34cb1647f4bdfe51be
> diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
> index 31f979c..1fd13dd 100644
> --- a/net/d80211/ieee80211.c
> +++ b/net/d80211/ieee80211.c
> @@ -4144,7 +4144,7 @@ struct net_device *ieee80211_alloc_hw(si
> ((char *) local + ((sizeof(struct ieee80211_local) + 3) & ~3));
>
> ether_setup(mdev);
> - memcpy(mdev->name, "wlan%d", 7);
> + memcpy(mdev->name, "wmaster%d", 10);
Why not use strlcpy or strncpy? and use sizeof(mdev->name) or IFNAMSIZ
rather than hard coded 10.
>
> local->dev_index = -1;
> local->mdev = mdev;
> diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
> index ea1d9ab..3580d1e 100644
> --- a/net/d80211/ieee80211_i.h
> +++ b/net/d80211/ieee80211_i.h
> @@ -318,7 +318,7 @@ #define IEEE80211_SUB_IF_TO_DEV(sub_if)
> struct ieee80211_local {
> struct ieee80211_hw *hw;
> void *hw_priv;
> - struct net_device *mdev; /* wlan# - "master" 802.11 device */
> + struct net_device *mdev; /* wmaster# - "master" 802.11 device */
> int open_count;
> int monitors;
> struct ieee80211_conf conf;
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH 9/10] d80211: rename master interface
2006-04-21 21:02 ` Stephen Hemminger
@ 2006-04-21 21:06 ` Jiri Benc
0 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 21:06 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
On Fri, 21 Apr 2006 14:02:54 -0700, Stephen Hemminger wrote:
> On Fri, 21 Apr 2006 22:53:29 +0200 (CEST)
> Jiri Benc <jbenc@suse.cz> wrote:
> > - memcpy(mdev->name, "wlan%d", 7);
> > + memcpy(mdev->name, "wmaster%d", 10);
>
> Why not use strlcpy or strncpy? and use sizeof(mdev->name) or IFNAMSIZ
> rather than hard coded 10.
Good idea :-) Will fix it, thanks.
Jiri
--
Jiri Benc
SUSE Labs
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 10/10] d80211: add one default interface
2006-04-21 20:53 [PATCH 0/10] d80211: bugfixes and reducing number of interfaces Jiri Benc
` (8 preceding siblings ...)
2006-04-21 20:53 ` [PATCH 9/10] d80211: rename master interface Jiri Benc
@ 2006-04-21 20:53 ` Jiri Benc
9 siblings, 0 replies; 18+ messages in thread
From: Jiri Benc @ 2006-04-21 20:53 UTC (permalink / raw)
To: netdev
The wireless card is useless with master interface (wmasterX) only. Adding
at least one virtual interface is necessity for every user. To save users
a lot of pain (and to maintain backward compatibility) we should add one
virtual interface by default. It is called wlanX (hopefully the name users
are used to) and set to STA mode.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
net/d80211/ieee80211.c | 9 +++++++++
net/d80211/ieee80211_i.h | 2 +-
net/d80211/ieee80211_iface.c | 18 ++++++++++++------
net/d80211/ieee80211_ioctl.c | 8 ++++----
net/d80211/ieee80211_sysfs.c | 2 +-
5 files changed, 27 insertions(+), 12 deletions(-)
a808727dea7cd4e8bf1185246e37a2780fb58292
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 1fd13dd..a03ab09 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4215,6 +4215,7 @@ struct net_device *ieee80211_alloc_hw(si
int ieee80211_register_hw(struct net_device *dev, struct ieee80211_hw *hw)
{
struct ieee80211_local *local = dev->priv;
+ struct net_device *sta_dev;
int result;
if (!hw)
@@ -4259,6 +4260,14 @@ int ieee80211_register_hw(struct net_dev
ieee80211_wep_init(local);
ieee80211_proc_init_interface(local);
+
+ /* add one default STA interface */
+ rtnl_lock();
+ result = ieee80211_if_add(dev, "wlan%d", 1, &sta_dev);
+ if (result == 0)
+ ieee80211_if_set_type(sta_dev, IEEE80211_IF_TYPE_STA);
+ rtnl_unlock();
+
return 0;
fail_rate:
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 3580d1e..422d198 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -587,7 +587,7 @@ int ieee80211_dev_find_index(struct ieee
/* ieee80211_iface.c */
int ieee80211_if_add(struct net_device *dev, const char *name,
- struct net_device **new_dev);
+ int format, struct net_device **new_dev);
int ieee80211_if_set_type(struct net_device *dev, int type);
void ieee80211_if_reinit(struct net_device *dev);
void __ieee80211_if_del(struct ieee80211_local *local,
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index d71d4f9..4398567 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -26,7 +26,7 @@ void ieee80211_if_sdata_init(struct ieee
/* Must be called with rtnl lock held. */
int ieee80211_if_add(struct net_device *dev, const char *name,
- struct net_device **new_dev)
+ int format, struct net_device **new_dev)
{
struct net_device *ndev, *tmp_dev;
struct ieee80211_local *local = dev->priv;
@@ -54,6 +54,10 @@ int ieee80211_if_add(struct net_device *
break;
dev_put(tmp_dev);
} while (i < 10000);
+ } else if (format) {
+ ret = dev_alloc_name(ndev, name);
+ if (ret)
+ goto fail;
} else {
snprintf(ndev->name, IFNAMSIZ, "%s", name);
}
@@ -75,16 +79,18 @@ int ieee80211_if_add(struct net_device *
ieee80211_if_sdata_init(sdata);
ret = register_netdevice(ndev);
- if (ret) {
- kfree(ndev);
- *new_dev = NULL;
- return ret;
- }
+ if (ret)
+ goto fail;
list_add(&sdata->list, &local->sub_if_list);
ieee80211_proc_init_virtual(ndev);
return 0;
+
+fail:
+ kfree(ndev);
+ *new_dev = NULL;
+ return ret;
}
static int ieee80211_if_add_apdev(struct net_device *dev)
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 1d3f5cf..5d31a8f 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -931,7 +931,7 @@ static int ieee80211_ioctl_add_if(struct
if (left < sizeof(struct hostapd_if_wds))
return -EPROTO;
- res = ieee80211_if_add(dev, param->u.if_info.name, &new_dev);
+ res = ieee80211_if_add(dev, param->u.if_info.name, 0, &new_dev);
if (res)
return res;
ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_WDS);
@@ -943,7 +943,7 @@ static int ieee80211_ioctl_add_if(struct
if (left < sizeof(struct hostapd_if_vlan))
return -EPROTO;
- res = ieee80211_if_add(dev, param->u.if_info.name, &new_dev);
+ res = ieee80211_if_add(dev, param->u.if_info.name, 0, &new_dev);
if (res)
return res;
ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_VLAN);
@@ -960,7 +960,7 @@ #endif
if (left < sizeof(struct hostapd_if_bss))
return -EPROTO;
- res = ieee80211_if_add(dev, param->u.if_info.name, &new_dev);
+ res = ieee80211_if_add(dev, param->u.if_info.name, 0, &new_dev);
if (res)
return res;
ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_AP);
@@ -975,7 +975,7 @@ #endif
if (left < sizeof(struct hostapd_if_sta))
return -EPROTO;
- res = ieee80211_if_add(dev, param->u.if_info.name, &new_dev);
+ res = ieee80211_if_add(dev, param->u.if_info.name, 0, &new_dev);
if (res)
return res;
ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_STA);
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 546e2b7..463f9aa 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -30,7 +30,7 @@ static ssize_t store_add_iface(struct cl
if (len > IFNAMSIZ)
return -EINVAL;
rtnl_lock();
- res = ieee80211_if_add(local->mdev, buf, &new_dev);
+ res = ieee80211_if_add(local->mdev, buf, 0, &new_dev);
if (res == 0)
ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_STA);
rtnl_unlock();
--
1.3.0
^ permalink raw reply related [flat|nested] 18+ messages in thread