diff options
author | emax <emax@FreeBSD.org> | 2007-10-29 19:06:47 +0000 |
---|---|---|
committer | emax <emax@FreeBSD.org> | 2007-10-29 19:06:47 +0000 |
commit | 0cf18b2c7ce05154ae8623e04f94e8a14bd9121c (patch) | |
tree | df953789da74dcfb5970c73fff688765880623ba | |
parent | 374fe7d7610608731470e6de6cfa94ef893122ec (diff) | |
download | FreeBSD-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
-rw-r--r-- | sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c | 84 |
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 */ |