summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c')
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c433
1 files changed, 285 insertions, 148 deletions
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
index f4c99f7..7cf45d6 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ng_btsocket_l2cap.c,v 1.5 2002/10/26 03:34:37 max Exp $
+ * $Id: ng_btsocket_l2cap.c,v 1.14 2003/04/06 22:53:18 max Exp $
* $FreeBSD$
*/
@@ -95,15 +95,12 @@ static struct ng_type typestruct = {
/* Globals */
extern int ifqmaxlen;
static u_int32_t ng_btsocket_l2cap_debug_level;
-static u_int32_t ng_btsocket_l2cap_ioctl_timeout;
static node_p ng_btsocket_l2cap_node;
static struct ng_bt_itemq ng_btsocket_l2cap_queue;
static struct mtx ng_btsocket_l2cap_queue_mtx;
static struct task ng_btsocket_l2cap_queue_task;
static LIST_HEAD(, ng_btsocket_l2cap_pcb) ng_btsocket_l2cap_sockets;
static struct mtx ng_btsocket_l2cap_sockets_mtx;
-static u_int32_t ng_btsocket_l2cap_token;
-static struct mtx ng_btsocket_l2cap_token_mtx;
static LIST_HEAD(, ng_btsocket_l2cap_rtentry) ng_btsocket_l2cap_rt;
static struct mtx ng_btsocket_l2cap_rt_mtx;
static struct task ng_btsocket_l2cap_rt_task;
@@ -116,10 +113,6 @@ SYSCTL_INT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, debug_level,
CTLFLAG_RW,
&ng_btsocket_l2cap_debug_level, NG_BTSOCKET_WARN_LEVEL,
"Bluetooth SEQPACKET L2CAP sockets debug level");
-SYSCTL_INT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, ioctl_timeout,
- CTLFLAG_RW,
- &ng_btsocket_l2cap_ioctl_timeout, 5,
- "Bluetooth SEQPACKET L2CAP sockets ioctl timeout");
SYSCTL_INT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, queue_len,
CTLFLAG_RD,
&ng_btsocket_l2cap_queue.len, 0,
@@ -155,26 +148,26 @@ SYSCTL_INT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, queue_drops,
*/
static int ng_btsocket_l2cap_process_l2ca_con_req_rsp
- (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
+ (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p, struct socket **);
static int ng_btsocket_l2cap_process_l2ca_con_rsp_rsp
- (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
+ (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p, struct socket **);
static int ng_btsocket_l2cap_process_l2ca_con_ind
- (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
+ (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p, struct socket **);
static int ng_btsocket_l2cap_process_l2ca_cfg_req_rsp
- (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
+ (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p, struct socket **);
static int ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp
- (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
+ (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p, struct socket **);
static int ng_btsocket_l2cap_process_l2ca_cfg_ind
- (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
+ (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p, struct socket **);
static int ng_btsocket_l2cap_process_l2ca_discon_rsp
- (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
+ (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p, struct socket **);
static int ng_btsocket_l2cap_process_l2ca_discon_ind
- (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
+ (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p, struct socket **);
static int ng_btsocket_l2cap_process_l2ca_write_rsp
- (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
+ (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p, struct socket **);
/*
* Send L2CA_xxx messages to the lower layer
@@ -209,9 +202,14 @@ static void ng_btsocket_l2cap_process_timeout (void *);
static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_addr(bdaddr_p, int);
static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_token(u_int32_t);
static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_cid (bdaddr_p, int);
-static void ng_btsocket_l2cap_get_token (u_int32_t *);
static int ng_btsocket_l2cap_result2errno(int);
+#define ng_btsocket_l2cap_wakeup_input_task() \
+ taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_queue_task)
+
+#define ng_btsocket_l2cap_wakeup_route_task() \
+ taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_rt_task)
+
/*****************************************************************************
*****************************************************************************
** Netgraph node interface
@@ -309,8 +307,7 @@ ng_btsocket_l2cap_node_disconnect(hook_p hook)
*/
if (NG_HOOK_PRIVATE(hook) != NULL)
- return (taskqueue_enqueue(taskqueue_swi_giant,
- &ng_btsocket_l2cap_rt_task));
+ return (ng_btsocket_l2cap_wakeup_route_task());
NG_HOOK_UNREF(hook); /* Remove extra reference */
@@ -343,8 +340,7 @@ ng_btsocket_l2cap_node_rcvmsg(node_p node, item_p item, hook_p hook)
}
NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_l2cap_queue, item);
- error = taskqueue_enqueue(taskqueue_swi_giant,
- &ng_btsocket_l2cap_queue_task);
+ error = ng_btsocket_l2cap_wakeup_input_task();
}
mtx_unlock(&ng_btsocket_l2cap_queue_mtx);
} else {
@@ -377,8 +373,7 @@ ng_btsocket_l2cap_node_rcvdata(hook_p hook, item_p item)
NGI_SET_HOOK(item, hook);
NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_l2cap_queue, item);
- error = taskqueue_enqueue(taskqueue_swi_giant,
- &ng_btsocket_l2cap_queue_task);
+ error = ng_btsocket_l2cap_wakeup_input_task();
}
mtx_unlock(&ng_btsocket_l2cap_queue_mtx);
@@ -392,7 +387,7 @@ ng_btsocket_l2cap_node_rcvdata(hook_p hook, item_p item)
static int
ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
- ng_btsocket_l2cap_rtentry_p rt)
+ ng_btsocket_l2cap_rtentry_p rt, struct socket **sop)
{
ng_l2cap_l2ca_con_op *op = NULL;
ng_btsocket_l2cap_pcb_t *pcb = NULL;
@@ -403,10 +398,14 @@ ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
op = (ng_l2cap_l2ca_con_op *)(msg->data);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+
/* Look for the socket with the token */
pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
- if (pcb == NULL)
+ if (pcb == NULL) {
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (ENOENT);
+ }
mtx_lock(&pcb->pcb_mtx);
@@ -423,6 +422,8 @@ ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
if (pcb->state != NG_BTSOCKET_L2CAP_CONNECTING) {
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+
return (ENOENT);
}
@@ -431,6 +432,8 @@ ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
if (op->result == NG_L2CAP_PENDING) {
ng_btsocket_l2cap_timeout(pcb);
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+
return (0);
}
@@ -451,6 +454,9 @@ ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
/* ... and close the socket */
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb->so);
+
+ if (pcb->so->so_state & SS_NOFDREF)
+ *sop = pcb->so;
} else {
pcb->cfg_state = NG_BTSOCKET_L2CAP_CFG_IN_SENT;
pcb->state = NG_BTSOCKET_L2CAP_CONFIGURING;
@@ -467,9 +473,13 @@ ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
pcb->so->so_error = ng_btsocket_l2cap_result2errno(op->result);
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb->so);
+
+ if (pcb->so->so_state & SS_NOFDREF)
+ *sop = pcb->so;
}
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (error);
} /* ng_btsocket_l2cap_process_l2ca_con_req_rsp */
@@ -480,7 +490,7 @@ ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
static int
ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(struct ng_mesg *msg,
- ng_btsocket_l2cap_rtentry_p rt)
+ ng_btsocket_l2cap_rtentry_p rt, struct socket **sop)
{
ng_l2cap_l2ca_con_rsp_op *op = NULL;
ng_btsocket_l2cap_pcb_t *pcb = NULL;
@@ -490,10 +500,14 @@ ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(struct ng_mesg *msg,
op = (ng_l2cap_l2ca_con_rsp_op *)(msg->data);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+
/* Look for the socket with the token */
pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
- if (pcb == NULL)
+ if (pcb == NULL) {
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (ENOENT);
+ }
mtx_lock(&pcb->pcb_mtx);
@@ -509,6 +523,8 @@ ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(struct ng_mesg *msg,
if (pcb->state != NG_BTSOCKET_L2CAP_CONNECTING) {
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+
return (ENOENT);
}
@@ -520,6 +536,9 @@ ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(struct ng_mesg *msg,
pcb->so->so_error = ng_btsocket_l2cap_result2errno(op->result);
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb->so);
+
+ if (pcb->so->so_state & SS_NOFDREF)
+ *sop = pcb->so;
} else {
/* Move to CONFIGURING state and wait for CONFIG_IND */
pcb->cfg_state = 0;
@@ -528,6 +547,7 @@ ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(struct ng_mesg *msg,
}
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (0);
} /* ng_btsocket_process_l2ca_con_rsp_rsp */
@@ -540,7 +560,7 @@ ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(struct ng_mesg *msg,
static int
ng_btsocket_l2cap_process_l2ca_con_ind(struct ng_mesg *msg,
- ng_btsocket_l2cap_rtentry_p rt)
+ ng_btsocket_l2cap_rtentry_p rt, struct socket **sop)
{
ng_l2cap_l2ca_con_ind_ip *ip = NULL;
ng_btsocket_l2cap_pcb_t *pcb = NULL, *pcb1 = NULL;
@@ -562,6 +582,8 @@ ng_btsocket_l2cap_process_l2ca_con_ind(struct ng_mesg *msg,
ip->bdaddr.b[5], ip->bdaddr.b[4], ip->bdaddr.b[3],
ip->bdaddr.b[2], ip->bdaddr.b[1], ip->bdaddr.b[0],
ip->psm, ip->lcid, ip->ident);
+
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
pcb = ng_btsocket_l2cap_pcb_by_addr(&rt->src, ip->psm);
if (pcb != NULL) {
@@ -593,7 +615,7 @@ ng_btsocket_l2cap_process_l2ca_con_ind(struct ng_mesg *msg,
KASSERT((pcb1 != NULL),
("%s: pcb1 == NULL\n", __func__));
- mtx_lock(&pcb1->pcb_mtx);
+ mtx_lock(&pcb1->pcb_mtx);
if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(pcb->src)) != 0)
bcopy(&pcb->src, &pcb1->src, sizeof(pcb1->src));
@@ -625,6 +647,9 @@ respond:
pcb1->so->so_error = error;
pcb1->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb1->so);
+
+ if (pcb1->so->so_state & SS_NOFDREF)
+ *sop = pcb1->so;
} else {
pcb1->state = NG_BTSOCKET_L2CAP_CONNECTING;
soisconnecting(pcb1->so);
@@ -638,6 +663,8 @@ respond:
if (pcb != NULL)
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+
return (error);
} /* ng_btsocket_l2cap_process_l2ca_con_ind */
@@ -647,7 +674,7 @@ respond:
static int
ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg,
- ng_btsocket_l2cap_rtentry_p rt)
+ ng_btsocket_l2cap_rtentry_p rt, struct socket **sop)
{
ng_l2cap_l2ca_cfg_op *op = NULL;
ng_btsocket_l2cap_pcb_p pcb = NULL;
@@ -657,6 +684,8 @@ ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg,
op = (ng_l2cap_l2ca_cfg_op *)(msg->data);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+
/*
* Socket must have issued a Configure request, so we must have a
* socket that wants to be configured. Use Netgraph message token
@@ -671,6 +700,7 @@ ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg,
* Disconnect, because we do not know channel ID
*/
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (ENOENT);
}
@@ -689,6 +719,8 @@ ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg,
if (pcb->state != NG_BTSOCKET_L2CAP_CONFIGURING) {
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+
return (ENOENT);
}
@@ -745,9 +777,13 @@ ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg,
/* ... and close the socket */
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb->so);
+
+ if (pcb->so->so_state & SS_NOFDREF)
+ *sop = pcb->so;
}
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (0);
} /* ng_btsocket_l2cap_process_l2ca_cfg_req_rsp */
@@ -758,7 +794,7 @@ ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg,
static int
ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp(struct ng_mesg *msg,
- ng_btsocket_l2cap_rtentry_p rt)
+ ng_btsocket_l2cap_rtentry_p rt, struct socket **sop)
{
ng_l2cap_l2ca_cfg_rsp_op *op = NULL;
ng_btsocket_l2cap_pcb_t *pcb = NULL;
@@ -769,10 +805,14 @@ ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp(struct ng_mesg *msg,
op = (ng_l2cap_l2ca_cfg_rsp_op *)(msg->data);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+
/* Look for the socket with the token */
pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
- if (pcb == NULL)
+ if (pcb == NULL) {
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (ENOENT);
+ }
mtx_lock(&pcb->pcb_mtx);
@@ -789,6 +829,8 @@ ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp(struct ng_mesg *msg,
if (pcb->state != NG_BTSOCKET_L2CAP_CONFIGURING) {
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+
return (ENOENT);
}
@@ -821,6 +863,7 @@ ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp(struct ng_mesg *msg,
}
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (error);
@@ -834,7 +877,11 @@ disconnect:
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb->so);
+ if (pcb->so->so_state & SS_NOFDREF)
+ *sop = pcb->so;
+
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (error);
} /* ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp */
@@ -845,7 +892,7 @@ disconnect:
static int
ng_btsocket_l2cap_process_l2ca_cfg_ind(struct ng_mesg *msg,
- ng_btsocket_l2cap_rtentry_p rt)
+ ng_btsocket_l2cap_rtentry_p rt, struct socket **sop)
{
ng_l2cap_l2ca_cfg_ind_ip *ip = NULL;
ng_btsocket_l2cap_pcb_t *pcb = NULL;
@@ -856,10 +903,14 @@ ng_btsocket_l2cap_process_l2ca_cfg_ind(struct ng_mesg *msg,
ip = (ng_l2cap_l2ca_cfg_ind_ip *)(msg->data);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+
/* Check for the open socket that has given channel ID */
pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, ip->lcid);
- if (pcb == NULL)
+ if (pcb == NULL) {
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (ENOENT);
+ }
mtx_lock(&pcb->pcb_mtx);
@@ -876,6 +927,8 @@ ng_btsocket_l2cap_process_l2ca_cfg_ind(struct ng_mesg *msg,
/* XXX FIXME re-configuration on open socket */
if (pcb->state != NG_BTSOCKET_L2CAP_CONFIGURING) {
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+
return (ENOENT);
}
@@ -894,29 +947,28 @@ ng_btsocket_l2cap_process_l2ca_cfg_ind(struct ng_mesg *msg,
* if any send disconnect to close the channel.
*/
- if (sbreserve(&pcb->so->so_snd, ip->omtu, pcb->so, curthread)) {
- if (!(pcb->cfg_state & NG_BTSOCKET_L2CAP_CFG_OUT_SENT)) {
- error = ng_btsocket_l2cap_send_l2ca_cfg_rsp(pcb);
- if (error == 0)
- pcb->cfg_state |= NG_BTSOCKET_L2CAP_CFG_OUT_SENT;
- }
- } else
- error = ENOBUFS;
+ if (!(pcb->cfg_state & NG_BTSOCKET_L2CAP_CFG_OUT_SENT)) {
+ error = ng_btsocket_l2cap_send_l2ca_cfg_rsp(pcb);
+ if (error != 0) {
+ ng_btsocket_l2cap_untimeout(pcb);
- if (error != 0) {
- ng_btsocket_l2cap_untimeout(pcb);
+ pcb->so->so_error = error;
- pcb->so->so_error = error;
+ /* Send disconnect with "zero" token */
+ ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
- /* Send disconnect with "zero" token */
- ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
+ /* ... and close the socket */
+ pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
+ soisdisconnected(pcb->so);
- /* ... and close the socket */
- pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
- soisdisconnected(pcb->so);
+ if (pcb->so->so_state & SS_NOFDREF)
+ *sop = pcb->so;
+ } else
+ pcb->cfg_state |= NG_BTSOCKET_L2CAP_CFG_OUT_SENT;
}
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (error);
} /* ng_btsocket_l2cap_process_l2cap_cfg_ind */
@@ -927,7 +979,7 @@ ng_btsocket_l2cap_process_l2ca_cfg_ind(struct ng_mesg *msg,
static int
ng_btsocket_l2cap_process_l2ca_discon_rsp(struct ng_mesg *msg,
- ng_btsocket_l2cap_rtentry_p rt)
+ ng_btsocket_l2cap_rtentry_p rt, struct socket **sop)
{
ng_l2cap_l2ca_discon_op *op = NULL;
ng_btsocket_l2cap_pcb_t *pcb = NULL;
@@ -938,6 +990,8 @@ ng_btsocket_l2cap_process_l2ca_discon_rsp(struct ng_mesg *msg,
op = (ng_l2cap_l2ca_discon_op *)(msg->data);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+
/*
* Socket layer must have issued L2CA_Disconnect request, so there
* must be a socket that wants to be disconnected. Use Netgraph
@@ -945,8 +999,10 @@ ng_btsocket_l2cap_process_l2ca_discon_rsp(struct ng_mesg *msg,
*/
pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
- if (pcb == NULL)
+ if (pcb == NULL) {
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (0);
+ }
mtx_lock(&pcb->pcb_mtx);
@@ -966,9 +1022,13 @@ ng_btsocket_l2cap_process_l2ca_discon_rsp(struct ng_mesg *msg,
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb->so);
+
+ if (pcb->so->so_state & SS_NOFDREF)
+ *sop = pcb->so;
}
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (0);
} /* ng_btsocket_l2cap_process_l2ca_discon_rsp */
@@ -979,7 +1039,7 @@ ng_btsocket_l2cap_process_l2ca_discon_rsp(struct ng_mesg *msg,
static int
ng_btsocket_l2cap_process_l2ca_discon_ind(struct ng_mesg *msg,
- ng_btsocket_l2cap_rtentry_p rt)
+ ng_btsocket_l2cap_rtentry_p rt, struct socket **sop)
{
ng_l2cap_l2ca_discon_ind_ip *ip = NULL;
ng_btsocket_l2cap_pcb_t *pcb = NULL;
@@ -990,10 +1050,14 @@ ng_btsocket_l2cap_process_l2ca_discon_ind(struct ng_mesg *msg,
ip = (ng_l2cap_l2ca_discon_ind_ip *)(msg->data);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+
/* Look for the socket with given channel ID */
pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, ip->lcid);
- if (pcb == NULL)
+ if (pcb == NULL) {
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (0);
+ }
/*
* Channel has already been destroyed, so disconnect the socket
@@ -1019,7 +1083,11 @@ ng_btsocket_l2cap_process_l2ca_discon_ind(struct ng_mesg *msg,
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb->so);
+ if (pcb->so->so_state & SS_NOFDREF)
+ *sop = pcb->so;
+
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (0);
} /* ng_btsocket_l2cap_process_l2ca_discon_ind */
@@ -1030,7 +1098,7 @@ ng_btsocket_l2cap_process_l2ca_discon_ind(struct ng_mesg *msg,
static int
ng_btsocket_l2cap_process_l2ca_write_rsp(struct ng_mesg *msg,
- ng_btsocket_l2cap_rtentry_p rt)
+ ng_btsocket_l2cap_rtentry_p rt, struct socket **sop)
{
ng_l2cap_l2ca_write_op *op = NULL;
ng_btsocket_l2cap_pcb_t *pcb = NULL;
@@ -1041,10 +1109,14 @@ ng_btsocket_l2cap_process_l2ca_write_rsp(struct ng_mesg *msg,
op = (ng_l2cap_l2ca_write_op *)(msg->data);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+
/* Look for the socket with given token */
pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
- if (pcb == NULL)
+ if (pcb == NULL) {
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (ENOENT);
+ }
mtx_lock(&pcb->pcb_mtx);
@@ -1061,6 +1133,8 @@ ng_btsocket_l2cap_process_l2ca_write_rsp(struct ng_mesg *msg,
if (pcb->state != NG_BTSOCKET_L2CAP_OPEN) {
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+
return (ENOENT);
}
@@ -1087,6 +1161,7 @@ ng_btsocket_l2cap_process_l2ca_write_rsp(struct ng_mesg *msg,
sowwakeup(pcb->so);
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (0);
} /* ng_btsocket_l2cap_process_l2ca_write_rsp */
@@ -1329,7 +1404,7 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
*/
NG_BTSOCKET_L2CAP_INFO(
-"%s: Received L2CAP datat packet: src bdaddr=%x:%x:%x:%x:%x:%x, " \
+"%s: Received L2CAP data packet: src bdaddr=%x:%x:%x:%x:%x:%x, " \
"dcid=%d, length=%d\n",
__func__,
rt->src.b[5], rt->src.b[4], rt->src.b[3],
@@ -1337,10 +1412,15 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
hdr->dcid, hdr->length);
if (NG_L2CAP_FIRST_CID <= hdr->dcid && hdr->dcid <= NG_L2CAP_LAST_CID) {
+
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+
/* Normal packet: find connected socket */
pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, hdr->dcid);
- if (pcb == NULL)
+ if (pcb == NULL) {
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
goto drop;
+ }
mtx_lock(&pcb->pcb_mtx);
@@ -1353,6 +1433,7 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
hdr->dcid, pcb->state);
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
goto drop;
}
@@ -1367,6 +1448,7 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
hdr->dcid, hdr->length, pcb->imtu);
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
goto drop;
}
@@ -1390,6 +1472,7 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
sbspace(&pcb->so->so_rcv));
mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
goto drop;
}
@@ -1398,8 +1481,10 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
m = NULL;
sorwakeup(pcb->so);
+
mtx_unlock(&pcb->pcb_mtx);
- } else if (hdr->dcid == NG_L2CAP_CLT_CID) {
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+ } else if (hdr->dcid == NG_L2CAP_CLT_CID) {
/* Broadcast packet: give packet to all sockets */
/* Check packet size against connectionless MTU */
@@ -1472,7 +1557,7 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
next:
mtx_unlock(&pcb->pcb_mtx);
}
-
+
mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
}
drop:
@@ -1496,23 +1581,27 @@ ng_btsocket_l2cap_default_msg_input(struct ng_mesg *msg, hook_p hook)
if (bcmp(msg->data, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
break;
+ mtx_lock(&ng_btsocket_l2cap_rt_mtx);
+
rt = (ng_btsocket_l2cap_rtentry_t *) NG_HOOK_PRIVATE(hook);
if (rt == NULL) {
MALLOC(rt, ng_btsocket_l2cap_rtentry_p, sizeof(*rt),
M_NETGRAPH_BTSOCKET_L2CAP, M_NOWAIT|M_ZERO);
- if (rt == NULL)
+ if (rt == NULL) {
+ mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
break;
+ }
- mtx_lock(&ng_btsocket_l2cap_rt_mtx);
LIST_INSERT_HEAD(&ng_btsocket_l2cap_rt, rt, next);
- mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
NG_HOOK_SET_PRIVATE(hook, rt);
}
-
+
bcopy(msg->data, &rt->src, sizeof(rt->src));
rt->hook = hook;
+ mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
+
NG_BTSOCKET_L2CAP_INFO(
"%s: Updating hook \"%s\", src bdaddr=%x:%x:%x:%x:%x:%x\n",
__func__, NG_HOOK_NAME(hook),
@@ -1536,7 +1625,8 @@ ng_btsocket_l2cap_default_msg_input(struct ng_mesg *msg, hook_p hook)
static void
ng_btsocket_l2cap_l2ca_msg_input(struct ng_mesg *msg, hook_p hook)
{
- ng_btsocket_l2cap_rtentry_p rt = NULL;
+ ng_btsocket_l2cap_rtentry_p rt = NULL;
+ struct socket *so = NULL;
if (hook == NULL) {
NG_BTSOCKET_L2CAP_ALERT(
@@ -1553,39 +1643,39 @@ ng_btsocket_l2cap_l2ca_msg_input(struct ng_mesg *msg, hook_p hook)
switch (msg->header.cmd) {
case NGM_L2CAP_L2CA_CON: /* L2CA_Connect response */
- ng_btsocket_l2cap_process_l2ca_con_req_rsp(msg, rt);
+ ng_btsocket_l2cap_process_l2ca_con_req_rsp(msg, rt, &so);
break;
case NGM_L2CAP_L2CA_CON_RSP: /* L2CA_ConnectRsp response */
- ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(msg, rt);
+ ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(msg, rt, &so);
break;
case NGM_L2CAP_L2CA_CON_IND: /* L2CA_Connect indicator */
- ng_btsocket_l2cap_process_l2ca_con_ind(msg, rt);
+ ng_btsocket_l2cap_process_l2ca_con_ind(msg, rt, &so);
break;
case NGM_L2CAP_L2CA_CFG: /* L2CA_Config response */
- ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(msg, rt);
+ ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(msg, rt, &so);
break;
case NGM_L2CAP_L2CA_CFG_RSP: /* L2CA_ConfigRsp response */
- ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp(msg, rt);
+ ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp(msg, rt, &so);
break;
case NGM_L2CAP_L2CA_CFG_IND: /* L2CA_Config indicator */
- ng_btsocket_l2cap_process_l2ca_cfg_ind(msg, rt);
+ ng_btsocket_l2cap_process_l2ca_cfg_ind(msg, rt, &so);
break;
case NGM_L2CAP_L2CA_DISCON: /* L2CA_Disconnect response */
- ng_btsocket_l2cap_process_l2ca_discon_rsp(msg, rt);
+ ng_btsocket_l2cap_process_l2ca_discon_rsp(msg, rt, &so);
break;
case NGM_L2CAP_L2CA_DISCON_IND: /* L2CA_Disconnect indicator */
- ng_btsocket_l2cap_process_l2ca_discon_ind(msg, rt);
+ ng_btsocket_l2cap_process_l2ca_discon_ind(msg, rt, &so);
break;
case NGM_L2CAP_L2CA_WRITE: /* L2CA_Write response */
- ng_btsocket_l2cap_process_l2ca_write_rsp(msg, rt);
+ ng_btsocket_l2cap_process_l2ca_write_rsp(msg, rt, &so);
break;
/* XXX FIXME add other L2CA messages */
@@ -1597,6 +1687,9 @@ ng_btsocket_l2cap_l2ca_msg_input(struct ng_mesg *msg, hook_p hook)
}
drop:
NG_FREE_MSG(msg);
+
+ if (so != NULL)
+ ng_btsocket_l2cap_detach(so);
} /* ng_btsocket_l2cap_l2ca_msg_input */
/*
@@ -1675,7 +1768,7 @@ drop:
static void
ng_btsocket_l2cap_rtclean(void *context, int pending)
{
- ng_btsocket_l2cap_pcb_p pcb = NULL;
+ ng_btsocket_l2cap_pcb_p pcb = NULL, pcb_next = NULL;
ng_btsocket_l2cap_rtentry_p rt = NULL;
mtx_lock(&ng_btsocket_l2cap_rt_mtx);
@@ -1685,8 +1778,9 @@ ng_btsocket_l2cap_rtclean(void *context, int pending)
* First disconnect all sockets that use "invalid" hook
*/
- LIST_FOREACH(pcb, &ng_btsocket_l2cap_sockets, next) {
+ for (pcb = LIST_FIRST(&ng_btsocket_l2cap_sockets); pcb != NULL; ) {
mtx_lock(&pcb->pcb_mtx);
+ pcb_next = LIST_NEXT(pcb, next);
if (pcb->rt != NULL &&
pcb->rt->hook != NULL && NG_HOOK_NOT_VALID(pcb->rt->hook)) {
@@ -1698,18 +1792,38 @@ ng_btsocket_l2cap_rtclean(void *context, int pending)
soisdisconnected(pcb->so);
pcb->token = 0;
+ pcb->cid = 0;
pcb->rt = NULL;
+
+ if (pcb->so->so_state & SS_NOFDREF) {
+ struct socket *so = pcb->so;
+
+ LIST_REMOVE(pcb, next);
+
+ mtx_unlock(&pcb->pcb_mtx);
+
+ mtx_destroy(&pcb->pcb_mtx);
+ bzero(pcb, sizeof(*pcb));
+ FREE(pcb, M_NETGRAPH_BTSOCKET_L2CAP);
+
+ soisdisconnected(so);
+ so->so_pcb = NULL;
+ sotryfree(so);
+
+ goto next;
+ }
}
mtx_unlock(&pcb->pcb_mtx);
+next:
+ pcb = pcb_next;
}
/*
* Now cleanup routing table
*/
- rt = LIST_FIRST(&ng_btsocket_l2cap_rt);
- while (rt != NULL) {
+ for (rt = LIST_FIRST(&ng_btsocket_l2cap_rt); rt != NULL; ) {
ng_btsocket_l2cap_rtentry_p rt_next = LIST_NEXT(rt, next);
if (rt->hook != NULL && NG_HOOK_NOT_VALID(rt->hook)) {
@@ -1740,7 +1854,6 @@ ng_btsocket_l2cap_init(void)
ng_btsocket_l2cap_node = NULL;
ng_btsocket_l2cap_debug_level = NG_BTSOCKET_WARN_LEVEL;
- ng_btsocket_l2cap_ioctl_timeout = 5;
/* Register Netgraph node type */
error = ng_newtype(&typestruct);
@@ -1786,11 +1899,6 @@ ng_btsocket_l2cap_init(void)
mtx_init(&ng_btsocket_l2cap_sockets_mtx,
"btsocks_l2cap_sockets_mtx", NULL, MTX_DEF);
- /* Tokens */
- ng_btsocket_l2cap_token = 0;
- mtx_init(&ng_btsocket_l2cap_token_mtx,
- "btsocks_l2cap_token_mtx", NULL, MTX_DEF);
-
/* Routing table */
LIST_INIT(&ng_btsocket_l2cap_rt);
mtx_init(&ng_btsocket_l2cap_rt_mtx,
@@ -1832,6 +1940,7 @@ ng_btsocket_l2cap_accept(struct socket *so, struct sockaddr **nam)
int
ng_btsocket_l2cap_attach(struct socket *so, int proto, struct thread *td)
{
+ static u_int32_t token = 0;
ng_btsocket_l2cap_pcb_p pcb = so2l2cap_pcb(so);
int error;
@@ -1886,15 +1995,52 @@ ng_btsocket_l2cap_attach(struct socket *so, int proto, struct thread *td)
pcb->flush_timo = NG_L2CAP_FLUSH_TIMO_DEFAULT;
pcb->link_timo = NG_L2CAP_LINK_TIMO_DEFAULT;
- ng_btsocket_l2cap_get_token(&pcb->token);
-
callout_handle_init(&pcb->timo);
- mtx_init(&pcb->pcb_mtx, "btsocket_pcb_mtx", NULL, MTX_DEF);
- /* Add the PCB to the list */
- mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+ /*
+ * XXX Mark PCB mutex as DUPOK to prevent "duplicated lock of
+ * the same type" message. When accepting new L2CAP connection
+ * ng_btsocket_l2cap_process_l2ca_con_ind() holds both PCB mutexes
+ * for "old" (accepting) PCB and "new" (created) PCB.
+ */
+
+ mtx_init(&pcb->pcb_mtx, "btsocks_l2cap_pcb_mtx", NULL,
+ MTX_DEF|MTX_DUPOK);
+
+ /*
+ * Add the PCB to the list
+ *
+ * XXX FIXME VERY IMPORTANT!
+ *
+ * This is totally FUBAR. We could get here in two cases:
+ *
+ * 1) When user calls socket()
+ * 2) When we need to accept new incomming connection and call
+ * sonewconn()
+ *
+ * In the first case we must aquire ng_btsocket_l2cap_sockets_mtx.
+ * In the second case we hold ng_btsocket_l2cap_sockets_mtx already.
+ * So we now need to distinguish between these cases. From reading
+ * /sys/kern/uipc_socket2.c we can find out that sonewconn() calls
+ * pru_attach with proto == 0 and td == NULL. For now use this fact
+ * to figure out if we were called from socket() or from sonewconn().
+ */
+
+ if (td != NULL)
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+ else
+ mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
+
+ /* Set PCB token. Use ng_btsocket_l2cap_sockets_mtx for protection */
+ if (++ token == 0)
+ token ++;
+
+ pcb->token = token;
+
LIST_INSERT_HEAD(&ng_btsocket_l2cap_sockets, pcb, next);
- mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+
+ if (td != NULL)
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
return (0);
} /* ng_btsocket_l2cap_attach */
@@ -1989,10 +2135,6 @@ ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam,
if (pcb->psm != 0 && pcb->psm != le16toh(sa->l2cap_psm))
return (EINVAL);
- /* Send destination address and PSM */
- bcopy(&sa->l2cap_bdaddr, &pcb->dst, sizeof(pcb->dst));
- pcb->psm = le16toh(sa->l2cap_psm);
-
/*
* Routing. Socket should be bound to some source address. The source
* address can be ANY. Destination address must be set and it must not
@@ -2000,11 +2142,17 @@ ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam,
* src != dst.
*/
+ mtx_lock(&ng_btsocket_l2cap_rt_mtx);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+ mtx_lock(&pcb->pcb_mtx);
+
+ /* Send destination address and PSM */
+ bcopy(&sa->l2cap_bdaddr, &pcb->dst, sizeof(pcb->dst));
+ pcb->psm = le16toh(sa->l2cap_psm);
+
pcb->rt = NULL;
have_src = bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(pcb->src));
- mtx_lock(&ng_btsocket_l2cap_rt_mtx);
-
LIST_FOREACH(rt, &ng_btsocket_l2cap_rt, next) {
if (rt->hook == NULL || NG_HOOK_NOT_VALID(rt->hook))
continue;
@@ -2027,14 +2175,11 @@ ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam,
} else
error = EHOSTUNREACH;
- mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
-
/*
* Send L2CA_Connect request
*/
if (error == 0) {
- mtx_lock(&pcb->pcb_mtx);
error = ng_btsocket_l2cap_send_l2ca_con_req(pcb);
if (error == 0) {
pcb->flags |= NG_BTSOCKET_L2CAP_CLIENT;
@@ -2043,9 +2188,12 @@ ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam,
ng_btsocket_l2cap_timeout(pcb);
}
- mtx_unlock(&pcb->pcb_mtx);
}
+ mtx_unlock(&pcb->pcb_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
+ mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
+
return (error);
} /* ng_btsocket_l2cap_connect */
@@ -2117,12 +2265,11 @@ ng_btsocket_l2cap_ctloutput(struct socket *so, struct sockopt *sopt)
case SOPT_SET:
/*
- * We do not allow to change these parameters while
- * socket is connected or we are in the process of
- * creating a connection
- *
- * XXX may be this should indicate re-configuration of the
- * open channel?
+ * XXX
+ * We do not allow to change these parameters while socket is
+ * connected or we are in the process of creating a connection.
+ * May be this should indicate re-configuration of the open
+ * channel?
*/
if (pcb->state != NG_BTSOCKET_L2CAP_CLOSED)
@@ -2178,6 +2325,7 @@ ng_btsocket_l2cap_detach(struct socket *so)
if (ng_btsocket_l2cap_node == NULL)
return (EINVAL);
+ mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
mtx_lock(&pcb->pcb_mtx);
/* XXX what to do with pending request? */
@@ -2190,21 +2338,20 @@ ng_btsocket_l2cap_detach(struct socket *so)
ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
- soisdisconnected(so);
- so->so_pcb = NULL;
- sotryfree(so);
+ LIST_REMOVE(pcb, next);
mtx_unlock(&pcb->pcb_mtx);
-
- mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
- LIST_REMOVE(pcb, next);
mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
mtx_destroy(&pcb->pcb_mtx);
bzero(pcb, sizeof(*pcb));
FREE(pcb, M_NETGRAPH_BTSOCKET_L2CAP);
+ soisdisconnected(so);
+ so->so_pcb = NULL;
+ sotryfree(so);
+
return (0);
} /* ng_btsocket_l2cap_detach */
@@ -2389,7 +2536,7 @@ ng_btsocket_l2cap_send2(ng_btsocket_l2cap_pcb_p pcb)
return (ENOBUFS);
/* Create L2CA packet header */
- M_PREPEND(m, sizeof(*hdr), M_NOWAIT);
+ M_PREPEND(m, sizeof(*hdr), M_DONTWAIT);
if (m != NULL)
if (m->m_len < sizeof(*hdr))
m = m_pullup(m, sizeof(*hdr));
@@ -2454,7 +2601,7 @@ ng_btsocket_l2cap_sockaddr(struct socket *so, struct sockaddr **nam)
/*
* Look for the socket that listens on given PSM and bdaddr. Returns exact or
- * close match (if any).
+ * close match (if any). Caller must hold ng_btsocket_l2cap_sockets_mtx.
*/
static ng_btsocket_l2cap_pcb_p
@@ -2462,7 +2609,7 @@ ng_btsocket_l2cap_pcb_by_addr(bdaddr_p bdaddr, int psm)
{
ng_btsocket_l2cap_pcb_p p = NULL, p1 = NULL;
- mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+ mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next) {
if (p->so == NULL || !(p->so->so_options & SO_ACCEPTCONN) ||
@@ -2476,13 +2623,12 @@ ng_btsocket_l2cap_pcb_by_addr(bdaddr_p bdaddr, int psm)
p1 = p;
}
- mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
-
return ((p != NULL)? p : p1);
} /* ng_btsocket_l2cap_pcb_by_addr */
/*
- * Look for the socket that has given token
+ * Look for the socket that has given token.
+ * Caller must hold ng_btsocket_l2cap_sockets_mtx.
*/
static ng_btsocket_l2cap_pcb_p
@@ -2490,21 +2636,21 @@ ng_btsocket_l2cap_pcb_by_token(u_int32_t token)
{
ng_btsocket_l2cap_pcb_p p = NULL;
- if (token != 0) {
- mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+ if (token == 0)
+ return (NULL);
- LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next)
- if (p->token == token)
- break;
+ mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
- mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
- }
+ LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next)
+ if (p->token == token)
+ break;
return (p);
} /* ng_btsocket_l2cap_pcb_by_token */
/*
- * Look for the socket that assigned to given source address and channel ID
+ * Look for the socket that assigned to given source address and channel ID.
+ * Caller must hold ng_btsocket_l2cap_sockets_mtx
*/
static ng_btsocket_l2cap_pcb_p
@@ -2512,14 +2658,12 @@ ng_btsocket_l2cap_pcb_by_cid(bdaddr_p src, int cid)
{
ng_btsocket_l2cap_pcb_p p = NULL;
- mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
+ mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next)
if (p->cid == cid && bcmp(src, &p->src, sizeof(p->src)) == 0)
break;
- mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
-
return (p);
} /* ng_btsocket_l2cap_pcb_by_cid */
@@ -2565,7 +2709,8 @@ ng_btsocket_l2cap_untimeout(ng_btsocket_l2cap_pcb_p pcb)
static void
ng_btsocket_l2cap_process_timeout(void *xpcb)
{
- ng_btsocket_l2cap_pcb_p pcb = (ng_btsocket_l2cap_pcb_p) xpcb;
+ ng_btsocket_l2cap_pcb_p pcb = (ng_btsocket_l2cap_pcb_p) xpcb;
+ struct socket *so = NULL;
mtx_lock(&pcb->pcb_mtx);
@@ -2582,6 +2727,9 @@ ng_btsocket_l2cap_process_timeout(void *xpcb)
/* ... and close the socket */
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb->so);
+
+ if (pcb->so->so_state & SS_NOFDREF)
+ so = pcb->so;
break;
case NG_BTSOCKET_L2CAP_OPEN:
@@ -2594,6 +2742,9 @@ ng_btsocket_l2cap_process_timeout(void *xpcb)
/* Disconnect timeout - disconnect the socket anyway */
pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
soisdisconnected(pcb->so);
+
+ if (pcb->so->so_state & SS_NOFDREF)
+ so = pcb->so;
break;
default:
@@ -2603,24 +2754,10 @@ ng_btsocket_l2cap_process_timeout(void *xpcb)
}
mtx_unlock(&pcb->pcb_mtx);
-} /* ng_btsocket_l2cap_process_timeout */
-/*
- * Get next token
- */
-
-static void
-ng_btsocket_l2cap_get_token(u_int32_t *token)
-{
- mtx_lock(&ng_btsocket_l2cap_token_mtx);
-
- if (++ ng_btsocket_l2cap_token == 0)
- ng_btsocket_l2cap_token = 1;
-
- *token = ng_btsocket_l2cap_token;
-
- mtx_unlock(&ng_btsocket_l2cap_token_mtx);
-} /* ng_btsocket_l2cap_get_token */
+ if (so != NULL)
+ ng_btsocket_l2cap_detach(so);
+} /* ng_btsocket_l2cap_process_timeout */
/*
* Translate HCI/L2CAP error code into "errno" code
OpenPOWER on IntegriCloud