Commit c3dfa985 authored by Maksim Krasnyanskiy's avatar Maksim Krasnyanskiy

[Bluetooth] Convert BNEP protocol to dynamic allocation of network devices.

This will allow fixing races with rmmod and sysfs access.

Patch from Stephen Hemminger <shemminger@osdl.org>
parent 6e21ae5b
...@@ -168,11 +168,11 @@ struct bnep_session { ...@@ -168,11 +168,11 @@ struct bnep_session {
u64 mc_filter; u64 mc_filter;
struct socket *sock; struct socket *sock;
struct net_device dev; struct net_device *dev;
struct net_device_stats stats; struct net_device_stats stats;
}; };
int bnep_net_init(struct net_device *dev); void bnep_net_setup(struct net_device *dev);
int bnep_sock_init(void); int bnep_sock_init(void);
int bnep_sock_cleanup(void); int bnep_sock_cleanup(void);
......
...@@ -180,7 +180,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) ...@@ -180,7 +180,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
s->mc_filter = 0; s->mc_filter = 0;
/* Always send broadcast */ /* Always send broadcast */
set_bit(bnep_mc_hash(s->dev.broadcast), (ulong *) &s->mc_filter); set_bit(bnep_mc_hash(s->dev->broadcast), (ulong *) &s->mc_filter);
/* Add address ranges to the multicast hash */ /* Add address ranges to the multicast hash */
for (; n > 0; n--) { for (; n > 0; n--) {
...@@ -293,7 +293,7 @@ static u8 __bnep_rx_hlen[] = { ...@@ -293,7 +293,7 @@ static u8 __bnep_rx_hlen[] = {
static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
{ {
struct net_device *dev = &s->dev; struct net_device *dev = s->dev;
struct sk_buff *nskb; struct sk_buff *nskb;
u8 type; u8 type;
...@@ -451,7 +451,7 @@ static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb) ...@@ -451,7 +451,7 @@ static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
static int bnep_session(void *arg) static int bnep_session(void *arg)
{ {
struct bnep_session *s = arg; struct bnep_session *s = arg;
struct net_device *dev = &s->dev; struct net_device *dev = s->dev;
struct sock *sk = s->sock->sk; struct sock *sk = s->sock->sk;
struct sk_buff *skb; struct sk_buff *skb;
wait_queue_t wait; wait_queue_t wait;
...@@ -501,7 +501,7 @@ static int bnep_session(void *arg) ...@@ -501,7 +501,7 @@ static int bnep_session(void *arg)
__bnep_unlink_session(s); __bnep_unlink_session(s);
up_write(&bnep_session_sem); up_write(&bnep_session_sem);
kfree(s); kfree(dev);
return 0; return 0;
} }
...@@ -517,10 +517,13 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -517,10 +517,13 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
baswap((void *) dst, &bt_sk(sock->sk)->dst); baswap((void *) dst, &bt_sk(sock->sk)->dst);
baswap((void *) src, &bt_sk(sock->sk)->src); baswap((void *) src, &bt_sk(sock->sk)->src);
s = kmalloc(sizeof(struct bnep_session), GFP_KERNEL); /* session struct allocated as private part of net_device */
if (!s) dev = alloc_netdev(sizeof(struct bnep_session),
return -ENOMEM; (*req->device) ? req->device : "bnep%d",
memset(s, 0, sizeof(struct bnep_session)); bnep_net_setup);
if (!dev)
return ENOMEM;
down_write(&bnep_session_sem); down_write(&bnep_session_sem);
...@@ -530,20 +533,15 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -530,20 +533,15 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
goto failed; goto failed;
} }
dev = &s->dev; s = dev->priv;
if (*req->device)
strcpy(dev->name, req->device);
else
strcpy(dev->name, "bnep%d");
memset(dev->broadcast, 0xff, ETH_ALEN);
/* This is rx header therefore addresses are swapped. /* This is rx header therefore addresses are swapped.
* ie eh.h_dest is our local address. */ * ie eh.h_dest is our local address. */
memcpy(s->eh.h_dest, &src, ETH_ALEN); memcpy(s->eh.h_dest, &src, ETH_ALEN);
memcpy(s->eh.h_source, &dst, ETH_ALEN); memcpy(s->eh.h_source, &dst, ETH_ALEN);
memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
s->dev = dev;
s->sock = sock; s->sock = sock;
s->role = req->role; s->role = req->role;
s->state = BT_CONNECTED; s->state = BT_CONNECTED;
...@@ -569,8 +567,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -569,8 +567,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
s->proto_filter[2].end = htons(0x86DD); s->proto_filter[2].end = htons(0x86DD);
#endif #endif
dev->init = bnep_net_init;
dev->priv = s;
err = register_netdev(dev); err = register_netdev(dev);
if (err) { if (err) {
goto failed; goto failed;
...@@ -592,7 +588,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -592,7 +588,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
failed: failed:
up_write(&bnep_session_sem); up_write(&bnep_session_sem);
kfree(s); kfree(dev);
return err; return err;
} }
...@@ -624,7 +620,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) ...@@ -624,7 +620,7 @@ int bnep_del_connection(struct bnep_conndel_req *req)
static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s) static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
{ {
memcpy(ci->dst, s->eh.h_source, ETH_ALEN); memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
strcpy(ci->device, s->dev.name); strcpy(ci->device, s->dev->name);
ci->flags = s->flags; ci->flags = s->flags;
ci->state = s->state; ci->state = s->state;
ci->role = s->role; ci->role = s->role;
......
...@@ -226,11 +226,10 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -226,11 +226,10 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev)
return 0; return 0;
} }
int bnep_net_init(struct net_device *dev) void bnep_net_setup(struct net_device *dev)
{ {
struct bnep_session *s = dev->priv;
memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN); memset(dev->broadcast, 0xff, ETH_ALEN);
dev->addr_len = ETH_ALEN; dev->addr_len = ETH_ALEN;
ether_setup(dev); ether_setup(dev);
...@@ -245,6 +244,4 @@ int bnep_net_init(struct net_device *dev) ...@@ -245,6 +244,4 @@ int bnep_net_init(struct net_device *dev)
dev->watchdog_timeo = HZ * 2; dev->watchdog_timeo = HZ * 2;
dev->tx_timeout = bnep_net_timeout; dev->tx_timeout = bnep_net_timeout;
return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment