summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoremax <emax@FreeBSD.org>2007-10-29 19:06:47 +0000
committeremax <emax@FreeBSD.org>2007-10-29 19:06:47 +0000
commit0cf18b2c7ce05154ae8623e04f94e8a14bd9121c (patch)
treedf953789da74dcfb5970c73fff688765880623ba /sys
parent374fe7d7610608731470e6de6cfa94ef893122ec (diff)
downloadFreeBSD-src-0cf18b2c7ce05154ae8623e04f94e8a14bd9121c.zip
FreeBSD-src-0cf18b2c7ce05154ae8623e04f94e8a14bd9121c.tar.gz
Allow RFCOMM servers to bind to a ''wildcard'' RFCOMM channel
zero (0). Actual RFCOMM channel will be assigned after listen(2) call is done on a RFCOMM socket bound to a ''wildcard'' RFCOMM channel zero (0). Address locking issues in ng_btsocket_rfcomm_bind() Submitted by: Heiko Wundram (Beenic) < wundram at beenic dot net > MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c84
1 files changed, 53 insertions, 31 deletions
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
index 066885a..f815df4 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
@@ -167,8 +167,6 @@ static int ng_btsocket_rfcomm_pcb_send
(ng_btsocket_rfcomm_pcb_p pcb, int limit);
static void ng_btsocket_rfcomm_pcb_kill
(ng_btsocket_rfcomm_pcb_p pcb, int error);
-static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_channel
- (bdaddr_p src, int channel);
static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
(ng_btsocket_rfcomm_session_p s, int dlci);
static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
@@ -440,7 +438,7 @@ int
ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
struct thread *td)
{
- ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
+ ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
if (pcb == NULL)
@@ -455,13 +453,31 @@ ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
return (EINVAL);
if (sa->rfcomm_channel > 30)
return (EINVAL);
- if (sa->rfcomm_channel != 0 &&
- ng_btsocket_rfcomm_pcb_by_channel(&sa->rfcomm_bdaddr, sa->rfcomm_channel) != NULL)
- return (EADDRINUSE);
+
+ mtx_lock(&pcb->pcb_mtx);
+
+ if (sa->rfcomm_channel != 0) {
+ mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
+
+ LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
+ if (pcb1->channel == sa->rfcomm_channel &&
+ bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
+ sizeof(pcb1->src)) == 0) {
+ mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
+ mtx_unlock(&pcb->pcb_mtx);
+
+ return (EADDRINUSE);
+ }
+ }
+
+ mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
+ }
bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
pcb->channel = sa->rfcomm_channel;
+ mtx_unlock(&pcb->pcb_mtx);
+
return (0);
} /* ng_btsocket_rfcomm_bind */
@@ -796,17 +812,44 @@ ng_btsocket_rfcomm_disconnect(struct socket *so)
int
ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
{
- ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
+ ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so), pcb1;
ng_btsocket_rfcomm_session_p s = NULL;
struct socket *l2so = NULL;
- int error;
- int socreate_error;
+ int error, socreate_error, usedchannels;
if (pcb == NULL)
return (EINVAL);
- if (pcb->channel < 1 || pcb->channel > 30)
+ if (pcb->channel > 30)
return (EADDRNOTAVAIL);
+ usedchannels = 0;
+
+ mtx_lock(&pcb->pcb_mtx);
+
+ if (pcb->channel == 0) {
+ mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
+
+ LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
+ if (pcb1->channel != 0 &&
+ bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
+ usedchannels |= (1 << (pcb1->channel - 1));
+
+ for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
+ if (!(usedchannels & (1 << (pcb->channel - 1))))
+ break;
+
+ if (pcb->channel == 0) {
+ mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
+ mtx_unlock(&pcb->pcb_mtx);
+
+ return (EADDRNOTAVAIL);
+ }
+
+ mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
+ }
+
+ mtx_unlock(&pcb->pcb_mtx);
+
/*
* XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e.
* soalloc() is allowed to sleep in MALLOC. This creates "could sleep"
@@ -3341,27 +3384,6 @@ ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
} /* ng_btsocket_rfcomm_pcb_kill */
/*
- * Look for RFCOMM socket with given channel and source address
- */
-
-static ng_btsocket_rfcomm_pcb_p
-ng_btsocket_rfcomm_pcb_by_channel(bdaddr_p src, int channel)
-{
- ng_btsocket_rfcomm_pcb_p pcb = NULL;
-
- mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
-
- LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next)
- if (pcb->channel == channel &&
- bcmp(&pcb->src, src, sizeof(*src)) == 0)
- break;
-
- mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
-
- return (pcb);
-} /* ng_btsocket_rfcomm_pcb_by_channel */
-
-/*
* Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
*/
OpenPOWER on IntegriCloud