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
This commit is contained in:
parent
52f0eb2416
commit
a6f3c1e3f3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=173151
@ -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"
|
||||
@ -3340,27 +3383,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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user