1 /* $OpenBSD: rfcomm_socket.c,v 1.1 2007/06/01 02:46:12 uwe Exp $ */
2 /* $NetBSD: rfcomm_socket.c,v 1.7 2007/04/21 06:15:23 plunky Exp $ */
3 /* $DragonFly: src/sys/netbt/rfcomm_socket.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
6 * Copyright (c) 2006 Itronix Inc.
9 * Written by Iain Hibbert for Itronix Inc.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of Itronix Inc. may not be used to endorse
20 * or promote products derived from this software without specific
21 * prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/cdefs.h>
38 /* load symbolic names */
39 #ifdef BLUETOOTH_DEBUG
44 #include <sys/param.h>
45 #include <sys/domain.h>
46 #include <sys/kernel.h>
49 #include <sys/protosw.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <sys/systm.h>
53 #include <vm/vm_zone.h>
55 #include <netbt/bluetooth.h>
56 #include <netbt/hci.h> /* XXX for EPASSTHROUGH */
57 #include <netbt/rfcomm.h>
59 /****************************************************************************
61 * RFCOMM SOCK_STREAM Sockets - serial line emulation
65 static void rfcomm_connecting(void *);
66 static void rfcomm_connected(void *);
67 static void rfcomm_disconnected(void *, int);
68 static void *rfcomm_newconn(void *, struct sockaddr_bt
*, struct sockaddr_bt
*);
69 static void rfcomm_complete(void *, int);
70 static void rfcomm_linkmode(void *, int);
71 static void rfcomm_input(void *, struct mbuf
*);
73 static const struct btproto rfcomm_proto
= {
83 /* sysctl variables */
84 int rfcomm_sendspace
= 4096;
85 int rfcomm_recvspace
= 4096;
88 * rfcomm_ctloutput(request, socket, level, optname, opt)
92 rfcomm_ctloutput(struct socket
*so
, struct sockopt
*sopt
)
94 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
98 #ifdef notyet /* XXX */
99 DPRINTFN(2, "%s\n", prcorequests
[sopt
->sopt_dir
]);
105 if (sopt
->sopt_level
!= BTPROTO_RFCOMM
)
108 switch(sopt
->sopt_dir
) {
110 m
= m_get(M_WAITOK
, MT_DATA
);
112 m
->m_len
= rfcomm_getopt(pcb
, sopt
->sopt_name
, mtod(m
, void *));
119 err
= sooptcopyout(sopt
, mtod(m
, void *), m
->m_len
);
123 err
= rfcomm_setopt2(pcb
, sopt
->sopt_name
, so
, sopt
);
135 /**********************************************************************
141 rfcomm_connecting(void *arg
)
143 /* struct socket *so = arg; */
145 KKASSERT(arg
!= NULL
);
146 DPRINTF("Connecting\n");
150 rfcomm_connected(void *arg
)
152 struct socket
*so
= arg
;
154 KKASSERT(so
!= NULL
);
155 DPRINTF("Connected\n");
160 rfcomm_disconnected(void *arg
, int err
)
162 struct socket
*so
= arg
;
164 KKASSERT(so
!= NULL
);
165 DPRINTF("Disconnected\n");
168 soisdisconnected(so
);
172 rfcomm_newconn(void *arg
, struct sockaddr_bt
*laddr
,
173 struct sockaddr_bt
*raddr
)
175 struct socket
*so
= arg
;
177 DPRINTF("New Connection\n");
178 so
= sonewconn(so
, 0);
188 * rfcomm_complete(rfcomm_dlc, length)
190 * length bytes are sent and may be removed from socket buffer
193 rfcomm_complete(void *arg
, int length
)
195 struct socket
*so
= arg
;
197 sbdrop(&so
->so_snd
.sb
, length
);
202 * rfcomm_linkmode(rfcomm_dlc, new)
204 * link mode change notification.
207 rfcomm_linkmode(void *arg
, int new)
209 struct socket
*so
= arg
;
212 DPRINTF("auth %s, encrypt %s, secure %s\n",
213 (new & RFCOMM_LM_AUTH
? "on" : "off"),
214 (new & RFCOMM_LM_ENCRYPT
? "on" : "off"),
215 (new & RFCOMM_LM_SECURE
? "on" : "off"));
217 (void)rfcomm_getopt(so
->so_pcb
, SO_RFCOMM_LM
, &mode
);
218 if (((mode
& RFCOMM_LM_AUTH
) && !(new & RFCOMM_LM_AUTH
))
219 || ((mode
& RFCOMM_LM_ENCRYPT
) && !(new & RFCOMM_LM_ENCRYPT
))
220 || ((mode
& RFCOMM_LM_SECURE
) && !(new & RFCOMM_LM_SECURE
)))
221 rfcomm_disconnect(so
->so_pcb
, 0);
225 * rfcomm_input(rfcomm_dlc, mbuf)
228 rfcomm_input(void *arg
, struct mbuf
*m
)
230 struct socket
*so
= arg
;
232 KKASSERT(so
!= NULL
);
234 if (m
->m_pkthdr
.len
> sbspace(&so
->so_rcv
)) {
235 kprintf("%s: %d bytes dropped (socket buffer full)\n",
236 __func__
, m
->m_pkthdr
.len
);
241 DPRINTFN(10, "received %d bytes\n", m
->m_pkthdr
.len
);
243 sbappendstream(&so
->so_rcv
.sb
, m
);
248 * Implementation of usrreqs.
251 rfcomm_sdetach(struct socket
*so
)
253 return rfcomm_detach((struct rfcomm_dlc
**)&so
->so_pcb
);
257 rfcomm_sabort (struct socket
*so
)
259 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
261 rfcomm_disconnect(pcb
, 0);
262 soisdisconnected(so
);
263 return rfcomm_sdetach(so
);
267 rfcomm_sdisconnect (struct socket
*so
)
269 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
271 soisdisconnecting(so
);
272 return rfcomm_disconnect(pcb
, so
->so_linger
);
276 rfcomm_scontrol (struct socket
*so
, u_long cmd
, caddr_t data
,
277 struct ifnet
*ifp
, struct thread
*td
)
283 rfcomm_sattach (struct socket
*so
, int proto
,
284 struct pru_attach_info
*ai
)
286 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
293 * Since we have nothing to add, we attach the DLC
294 * structure directly to our PCB pointer.
296 err
= rfcomm_attach((struct rfcomm_dlc
**)&so
->so_pcb
,
301 err
= soreserve(so
, rfcomm_sendspace
, rfcomm_recvspace
,NULL
);
305 err
= rfcomm_rcvd(so
->so_pcb
, sbspace(&so
->so_rcv
));
313 rfcomm_sbind (struct socket
*so
, struct sockaddr
*nam
,
316 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
317 struct sockaddr_bt
*sa
;
319 KKASSERT(nam
!= NULL
);
320 sa
= (struct sockaddr_bt
*)nam
;
322 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
))
325 if (sa
->bt_family
!= AF_BLUETOOTH
)
328 return rfcomm_bind(pcb
, sa
);
332 rfcomm_sconnect (struct socket
*so
, struct sockaddr
*nam
,
335 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
336 struct sockaddr_bt
*sa
;
338 KKASSERT(nam
!= NULL
);
339 sa
= (struct sockaddr_bt
*)nam
;
341 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
))
344 if (sa
->bt_family
!= AF_BLUETOOTH
)
348 return rfcomm_connect(pcb
, sa
);
352 rfcomm_speeraddr (struct socket
*so
, struct sockaddr
**nam
)
354 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
355 struct sockaddr_bt
*sa
, ssa
;
359 bzero(sa
, sizeof *sa
);
360 sa
->bt_len
= sizeof(struct sockaddr_bt
);
361 sa
->bt_family
= AF_BLUETOOTH
;
362 e
= rfcomm_peeraddr(pcb
, sa
);;
363 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
368 rfcomm_ssockaddr (struct socket
*so
, struct sockaddr
**nam
)
370 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
371 struct sockaddr_bt
*sa
, ssa
;
375 bzero(sa
, sizeof *sa
);
376 sa
->bt_len
= sizeof(struct sockaddr_bt
);
377 sa
->bt_family
= AF_BLUETOOTH
;
378 e
= rfcomm_sockaddr(pcb
, sa
);;
379 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
384 rfcomm_sshutdown (struct socket
*so
)
391 rfcomm_ssend (struct socket
*so
, int flags
, struct mbuf
*m
,
392 struct sockaddr
*addr
, struct mbuf
*control
, struct thread
*td
)
394 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
399 if (control
) /* no use for that */
402 m0
= m_copym(m
, 0, M_COPYALL
, MB_DONTWAIT
);
406 sbappendstream(&so
->so_snd
.sb
, m
);
408 return rfcomm_send(pcb
, m0
);
412 rfcomm_saccept(struct socket
*so
, struct sockaddr
**nam
)
414 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
415 struct sockaddr_bt
*sa
, ssa
;
419 bzero(sa
, sizeof *sa
);
420 sa
->bt_len
= sizeof(struct sockaddr_bt
);
421 sa
->bt_family
= AF_BLUETOOTH
;
422 e
= rfcomm_peeraddr(pcb
, sa
);;
423 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
428 rfcomm_slisten(struct socket
*so
, struct thread
*td
)
430 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
431 return rfcomm_listen(pcb
);
435 rfcomm_srcvd(struct socket
*so
, int flags
)
437 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
438 return rfcomm_rcvd(pcb
, sbspace(&so
->so_rcv
));
441 struct pr_usrreqs rfcomm_usrreqs
= {
442 .pru_abort
= rfcomm_sabort
,
443 .pru_accept
= rfcomm_saccept
,
444 .pru_attach
= rfcomm_sattach
,
445 .pru_bind
= rfcomm_sbind
,
446 .pru_connect
= rfcomm_sconnect
,
447 .pru_connect2
= pru_connect2_notsupp
,
448 .pru_control
= rfcomm_scontrol
,
449 .pru_detach
= rfcomm_sdetach
,
450 .pru_disconnect
= rfcomm_sdisconnect
,
451 .pru_listen
= rfcomm_slisten
,
452 .pru_peeraddr
= rfcomm_speeraddr
,
453 .pru_rcvd
= rfcomm_srcvd
,
454 .pru_rcvoob
= pru_rcvoob_notsupp
,
455 .pru_send
= rfcomm_ssend
,
456 .pru_sense
= pru_sense_null
,
457 .pru_shutdown
= rfcomm_sshutdown
,
458 .pru_sockaddr
= rfcomm_ssockaddr
,
459 .pru_sosend
= sosend
,
460 .pru_soreceive
= soreceive
,