1 /* $OpenBSD: src/sys/netbt/rfcomm_socket.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
2 /* $NetBSD: rfcomm_socket.c,v 1.8 2007/10/15 18:04:34 plunky Exp $ */
5 * Copyright (c) 2006 Itronix Inc.
8 * Written by Iain Hibbert for Itronix Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of Itronix Inc. may not be used to endorse
19 * or promote products derived from this software without specific
20 * prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
35 /* load symbolic names */
36 #ifdef BLUETOOTH_DEBUG
41 #include <sys/param.h>
42 #include <sys/domain.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h> /* for M_NOWAIT */
47 #include <sys/protosw.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/systm.h>
52 #include <sys/msgport2.h>
54 #include <vm/vm_zone.h>
56 #include <netbt/bluetooth.h>
57 #include <netbt/hci.h> /* XXX for EPASSTHROUGH */
58 #include <netbt/rfcomm.h>
60 /****************************************************************************
62 * RFCOMM SOCK_STREAM Sockets - serial line emulation
66 static void rfcomm_connecting(void *);
67 static void rfcomm_connected(void *);
68 static void rfcomm_disconnected(void *, int);
69 static void *rfcomm_newconn(void *, struct sockaddr_bt
*, struct sockaddr_bt
*);
70 static void rfcomm_complete(void *, int);
71 static void rfcomm_linkmode(void *, int);
72 static void rfcomm_input(void *, struct mbuf
*);
74 static const struct btproto rfcomm_proto
= {
84 /* sysctl variables */
85 int rfcomm_sendspace
= 4096;
86 int rfcomm_recvspace
= 4096;
89 * rfcomm_ctloutput(request, socket, level, optname, opt)
93 rfcomm_ctloutput(netmsg_t msg
)
95 struct socket
*so
= msg
->ctloutput
.base
.nm_so
;
96 struct sockopt
*sopt
= msg
->ctloutput
.nm_sopt
;
97 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
101 #ifdef notyet /* XXX */
102 DPRINTFN(2, "%s\n", prcorequests
[sopt
->sopt_dir
]);
110 if (sopt
->sopt_level
!= BTPROTO_RFCOMM
) {
115 switch(sopt
->sopt_dir
) {
117 m
= m_get(M_WAITOK
, MT_DATA
);
119 m
->m_len
= rfcomm_getopt(pcb
, sopt
->sopt_name
, mtod(m
, void *));
126 soopt_from_kbuf(sopt
, mtod(m
, void *), m
->m_len
);
130 error
= rfcomm_setopt2(pcb
, sopt
->sopt_name
, so
, sopt
);
139 lwkt_replymsg(&msg
->ctloutput
.base
.lmsg
, error
);
142 /**********************************************************************
148 rfcomm_connecting(void *arg
)
150 /* struct socket *so = arg; */
152 KKASSERT(arg
!= NULL
);
153 DPRINTF("Connecting\n");
157 rfcomm_connected(void *arg
)
159 struct socket
*so
= arg
;
161 KKASSERT(so
!= NULL
);
162 DPRINTF("Connected\n");
167 rfcomm_disconnected(void *arg
, int err
)
169 struct socket
*so
= arg
;
171 KKASSERT(so
!= NULL
);
172 DPRINTF("Disconnected\n");
175 soisdisconnected(so
);
179 rfcomm_newconn(void *arg
, struct sockaddr_bt
*laddr
,
180 struct sockaddr_bt
*raddr
)
182 struct socket
*so
= arg
;
184 DPRINTF("New Connection\n");
185 so
= sonewconn(so
, 0);
195 * rfcomm_complete(rfcomm_dlc, length)
197 * length bytes are sent and may be removed from socket buffer
200 rfcomm_complete(void *arg
, int length
)
202 struct socket
*so
= arg
;
204 sbdrop(&so
->so_snd
.sb
, length
);
209 * rfcomm_linkmode(rfcomm_dlc, new)
211 * link mode change notification.
214 rfcomm_linkmode(void *arg
, int new)
216 struct socket
*so
= arg
;
219 DPRINTF("auth %s, encrypt %s, secure %s\n",
220 (new & RFCOMM_LM_AUTH
? "on" : "off"),
221 (new & RFCOMM_LM_ENCRYPT
? "on" : "off"),
222 (new & RFCOMM_LM_SECURE
? "on" : "off"));
224 (void)rfcomm_getopt(so
->so_pcb
, SO_RFCOMM_LM
, &mode
);
225 if (((mode
& RFCOMM_LM_AUTH
) && !(new & RFCOMM_LM_AUTH
))
226 || ((mode
& RFCOMM_LM_ENCRYPT
) && !(new & RFCOMM_LM_ENCRYPT
))
227 || ((mode
& RFCOMM_LM_SECURE
) && !(new & RFCOMM_LM_SECURE
)))
228 rfcomm_disconnect(so
->so_pcb
, 0);
232 * rfcomm_input(rfcomm_dlc, mbuf)
235 rfcomm_input(void *arg
, struct mbuf
*m
)
237 struct socket
*so
= arg
;
239 KKASSERT(so
!= NULL
);
241 if (m
->m_pkthdr
.len
> sbspace(&so
->so_rcv
)) {
242 kprintf("%s: %d bytes dropped (socket buffer full)\n",
243 __func__
, m
->m_pkthdr
.len
);
248 DPRINTFN(10, "received %d bytes\n", m
->m_pkthdr
.len
);
250 sbappendstream(&so
->so_rcv
.sb
, m
);
255 * Implementation of usrreqs.
258 rfcomm_sdetach(netmsg_t msg
)
260 struct socket
*so
= msg
->detach
.base
.nm_so
;
263 error
= rfcomm_detach((struct rfcomm_dlc
**)&so
->so_pcb
);
264 lwkt_replymsg(&msg
->detach
.base
.lmsg
, error
);
268 * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
269 * will sofree() it when we return.
272 rfcomm_sabort(netmsg_t msg
)
274 struct socket
*so
= msg
->abort
.base
.nm_so
;
275 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
277 rfcomm_disconnect(pcb
, 0);
278 soisdisconnected(so
);
280 /* msg invalid now */
284 rfcomm_sdisconnect(netmsg_t msg
)
286 struct socket
*so
= msg
->abort
.base
.nm_so
;
287 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
290 soisdisconnecting(so
);
291 error
= rfcomm_disconnect(pcb
, so
->so_linger
);
292 lwkt_replymsg(&msg
->disconnect
.base
.lmsg
, error
);
296 rfcomm_scontrol(netmsg_t msg
)
298 lwkt_replymsg(&msg
->control
.base
.lmsg
, EPASSTHROUGH
);
302 rfcomm_sattach(netmsg_t msg
)
304 struct socket
*so
= msg
->attach
.base
.nm_so
;
305 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
314 * Since we have nothing to add, we attach the DLC
315 * structure directly to our PCB pointer.
317 error
= soreserve(so
, rfcomm_sendspace
, rfcomm_recvspace
, NULL
);
321 error
= rfcomm_attach((struct rfcomm_dlc
**)&so
->so_pcb
,
326 error
= rfcomm_rcvd(so
->so_pcb
, sbspace(&so
->so_rcv
));
328 rfcomm_detach((struct rfcomm_dlc
**)&so
->so_pcb
);
330 lwkt_replymsg(&msg
->attach
.base
.lmsg
, error
);
334 rfcomm_sbind(netmsg_t msg
)
336 struct socket
*so
= msg
->bind
.base
.nm_so
;
337 struct sockaddr
*nam
= msg
->bind
.nm_nam
;
338 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
339 struct sockaddr_bt
*sa
;
342 KKASSERT(nam
!= NULL
);
343 sa
= (struct sockaddr_bt
*)nam
;
345 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
)) {
347 } else if (sa
->bt_family
!= AF_BLUETOOTH
) {
348 error
= EAFNOSUPPORT
;
350 error
= rfcomm_bind(pcb
, sa
);
352 lwkt_replymsg(&msg
->bind
.base
.lmsg
, error
);
356 rfcomm_sconnect(netmsg_t msg
)
358 struct socket
*so
= msg
->connect
.base
.nm_so
;
359 struct sockaddr
*nam
= msg
->connect
.nm_nam
;
360 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
361 struct sockaddr_bt
*sa
;
364 KKASSERT(nam
!= NULL
);
365 sa
= (struct sockaddr_bt
*)nam
;
367 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
)) {
369 } else if (sa
->bt_family
!= AF_BLUETOOTH
) {
370 error
= EAFNOSUPPORT
;
373 error
= rfcomm_connect(pcb
, sa
);
375 lwkt_replymsg(&msg
->connect
.base
.lmsg
, error
);
379 rfcomm_speeraddr(netmsg_t msg
)
381 struct socket
*so
= msg
->peeraddr
.base
.nm_so
;
382 struct sockaddr
**nam
= msg
->peeraddr
.nm_nam
;
383 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
384 struct sockaddr_bt
*sa
, ssa
;
388 bzero(sa
, sizeof *sa
);
389 sa
->bt_len
= sizeof(struct sockaddr_bt
);
390 sa
->bt_family
= AF_BLUETOOTH
;
391 error
= rfcomm_peeraddr(pcb
, sa
);
392 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
394 lwkt_replymsg(&msg
->peeraddr
.base
.lmsg
, error
);
398 rfcomm_ssockaddr(netmsg_t msg
)
400 struct socket
*so
= msg
->sockaddr
.base
.nm_so
;
401 struct sockaddr
**nam
= msg
->sockaddr
.nm_nam
;
402 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
403 struct sockaddr_bt
*sa
, ssa
;
407 bzero(sa
, sizeof *sa
);
408 sa
->bt_len
= sizeof(struct sockaddr_bt
);
409 sa
->bt_family
= AF_BLUETOOTH
;
410 error
= rfcomm_sockaddr(pcb
, sa
);
411 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
413 lwkt_replymsg(&msg
->sockaddr
.base
.lmsg
, error
);
417 rfcomm_sshutdown(netmsg_t msg
)
419 struct socket
*so
= msg
->shutdown
.base
.nm_so
;
422 lwkt_replymsg(&msg
->shutdown
.base
.lmsg
, 0);
426 rfcomm_ssend(netmsg_t msg
)
428 struct socket
*so
= msg
->send
.base
.nm_so
;
429 struct mbuf
*m
= msg
->send
.nm_m
;
430 struct mbuf
*control
= msg
->send
.nm_control
;
431 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
437 /* no use for that */
443 m0
= m_copym(m
, 0, M_COPYALL
, M_NOWAIT
);
445 sbappendstream(&so
->so_snd
.sb
, m
);
446 error
= rfcomm_send(pcb
, m0
);
450 lwkt_replymsg(&msg
->send
.base
.lmsg
, error
);
454 rfcomm_saccept(netmsg_t msg
)
456 struct socket
*so
= msg
->accept
.base
.nm_so
;
457 struct sockaddr
**nam
= msg
->accept
.nm_nam
;
458 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
459 struct sockaddr_bt
*sa
, ssa
;
463 bzero(sa
, sizeof *sa
);
464 sa
->bt_len
= sizeof(struct sockaddr_bt
);
465 sa
->bt_family
= AF_BLUETOOTH
;
466 error
= rfcomm_peeraddr(pcb
, sa
);
467 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
469 lwkt_replymsg(&msg
->accept
.base
.lmsg
, error
);
473 rfcomm_slisten(netmsg_t msg
)
475 struct socket
*so
= msg
->listen
.base
.nm_so
;
476 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*)so
->so_pcb
;
479 error
= rfcomm_listen(pcb
);
480 lwkt_replymsg(&msg
->listen
.base
.lmsg
, error
);
484 rfcomm_srcvd(netmsg_t msg
)
486 struct socket
*so
= msg
->rcvd
.base
.nm_so
;
487 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
490 error
= rfcomm_rcvd(pcb
, sbspace(&so
->so_rcv
));
491 lwkt_replymsg(&msg
->rcvd
.base
.lmsg
, error
);
494 struct pr_usrreqs rfcomm_usrreqs
= {
495 .pru_abort
= rfcomm_sabort
,
496 .pru_accept
= rfcomm_saccept
,
497 .pru_attach
= rfcomm_sattach
,
498 .pru_bind
= rfcomm_sbind
,
499 .pru_connect
= rfcomm_sconnect
,
500 .pru_connect2
= pr_generic_notsupp
,
501 .pru_control
= rfcomm_scontrol
,
502 .pru_detach
= rfcomm_sdetach
,
503 .pru_disconnect
= rfcomm_sdisconnect
,
504 .pru_listen
= rfcomm_slisten
,
505 .pru_peeraddr
= rfcomm_speeraddr
,
506 .pru_rcvd
= rfcomm_srcvd
,
507 .pru_rcvoob
= pr_generic_notsupp
,
508 .pru_send
= rfcomm_ssend
,
509 .pru_sense
= pru_sense_null
,
510 .pru_shutdown
= rfcomm_sshutdown
,
511 .pru_sockaddr
= rfcomm_ssockaddr
,
512 .pru_sosend
= sosend
,
513 .pru_soreceive
= soreceive