Annotation of sys/netbt/rfcomm_socket.c, Revision 1.1.1.1
1.1 nbrk 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:
4: /*-
5: * Copyright (c) 2006 Itronix Inc.
6: * All rights reserved.
7: *
8: * Written by Iain Hibbert for Itronix Inc.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
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.
21: *
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.
33: */
34:
35: #include <sys/cdefs.h>
36:
37: /* load symbolic names */
38: #ifdef BLUETOOTH_DEBUG
39: #define PRUREQUESTS
40: #define PRCOREQUESTS
41: #endif
42:
43: #include <sys/param.h>
44: #include <sys/domain.h>
45: #include <sys/kernel.h>
46: #include <sys/mbuf.h>
47: #include <sys/proc.h>
48: #include <sys/protosw.h>
49: #include <sys/socket.h>
50: #include <sys/socketvar.h>
51: #include <sys/systm.h>
52:
53: #include <netbt/bluetooth.h>
54: #include <netbt/hci.h> /* XXX for EPASSTHROUGH */
55: #include <netbt/rfcomm.h>
56:
57: /****************************************************************************
58: *
59: * RFCOMM SOCK_STREAM Sockets - serial line emulation
60: *
61: */
62:
63: static void rfcomm_connecting(void *);
64: static void rfcomm_connected(void *);
65: static void rfcomm_disconnected(void *, int);
66: static void *rfcomm_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
67: static void rfcomm_complete(void *, int);
68: static void rfcomm_linkmode(void *, int);
69: static void rfcomm_input(void *, struct mbuf *);
70:
71: static const struct btproto rfcomm_proto = {
72: rfcomm_connecting,
73: rfcomm_connected,
74: rfcomm_disconnected,
75: rfcomm_newconn,
76: rfcomm_complete,
77: rfcomm_linkmode,
78: rfcomm_input,
79: };
80:
81: /* sysctl variables */
82: int rfcomm_sendspace = 4096;
83: int rfcomm_recvspace = 4096;
84:
85: /*
86: * User Request.
87: * up is socket
88: * m is either
89: * optional mbuf chain containing message
90: * ioctl command (PRU_CONTROL)
91: * nam is either
92: * optional mbuf chain containing an address
93: * ioctl data (PRU_CONTROL)
94: * optionally protocol number (PRU_ATTACH)
95: * message flags (PRU_RCVD)
96: * ctl is either
97: * optional mbuf chain containing socket options
98: * optional interface pointer (PRU_CONTROL, PRU_PURGEIF)
99: * l is pointer to process requesting action (if any)
100: *
101: * we are responsible for disposing of m and ctl if
102: * they are mbuf chains
103: */
104: int
105: rfcomm_usrreq(struct socket *up, int req, struct mbuf *m,
106: struct mbuf *nam, struct mbuf *ctl)
107: {
108: struct rfcomm_dlc *pcb = up->so_pcb;
109: struct sockaddr_bt *sa;
110: struct mbuf *m0;
111: int err = 0;
112:
113: #ifdef notyet /* XXX */
114: DPRINTFN(2, "%s\n", prurequests[req]);
115: #endif
116:
117: switch (req) {
118: case PRU_CONTROL:
119: return EPASSTHROUGH;
120:
121: #ifdef notyet /* XXX */
122: case PRU_PURGEIF:
123: return EOPNOTSUPP;
124: #endif
125:
126: case PRU_ATTACH:
127: if (pcb != NULL)
128: return EINVAL;
129:
130: /*
131: * Since we have nothing to add, we attach the DLC
132: * structure directly to our PCB pointer.
133: */
134: err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb,
135: &rfcomm_proto, up);
136: if (err)
137: return err;
138:
139: err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace);
140: if (err)
141: return err;
142:
143: err = rfcomm_rcvd(up->so_pcb, sbspace(&up->so_rcv));
144: if (err)
145: return err;
146:
147: return 0;
148: }
149:
150: if (pcb == NULL) {
151: err = EINVAL;
152: goto release;
153: }
154:
155: switch(req) {
156: case PRU_DISCONNECT:
157: soisdisconnecting(up);
158: return rfcomm_disconnect(pcb, up->so_linger);
159:
160: case PRU_ABORT:
161: rfcomm_disconnect(pcb, 0);
162: soisdisconnected(up);
163: /* fall through to */
164: case PRU_DETACH:
165: return rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb);
166:
167: case PRU_BIND:
168: KASSERT(nam != NULL);
169: sa = mtod(nam, struct sockaddr_bt *);
170:
171: if (sa->bt_len != sizeof(struct sockaddr_bt))
172: return EINVAL;
173:
174: if (sa->bt_family != AF_BLUETOOTH)
175: return EAFNOSUPPORT;
176:
177: return rfcomm_bind(pcb, sa);
178:
179: case PRU_CONNECT:
180: KASSERT(nam != NULL);
181: sa = mtod(nam, struct sockaddr_bt *);
182:
183: if (sa->bt_len != sizeof(struct sockaddr_bt))
184: return EINVAL;
185:
186: if (sa->bt_family != AF_BLUETOOTH)
187: return EAFNOSUPPORT;
188:
189: soisconnecting(up);
190: return rfcomm_connect(pcb, sa);
191:
192: case PRU_PEERADDR:
193: KASSERT(nam != NULL);
194: sa = mtod(nam, struct sockaddr_bt *);
195: nam->m_len = sizeof(struct sockaddr_bt);
196: return rfcomm_peeraddr(pcb, sa);
197:
198: case PRU_SOCKADDR:
199: KASSERT(nam != NULL);
200: sa = mtod(nam, struct sockaddr_bt *);
201: nam->m_len = sizeof(struct sockaddr_bt);
202: return rfcomm_sockaddr(pcb, sa);
203:
204: case PRU_SHUTDOWN:
205: socantsendmore(up);
206: break;
207:
208: case PRU_SEND:
209: KASSERT(m != NULL);
210:
211: if (ctl) /* no use for that */
212: m_freem(ctl);
213:
214: m0 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
215: if (m0 == NULL)
216: return ENOMEM;
217:
218: sbappendstream(&up->so_snd, m);
219:
220: return rfcomm_send(pcb, m0);
221:
222: case PRU_SENSE:
223: return 0; /* (no release) */
224:
225: case PRU_RCVD:
226: return rfcomm_rcvd(pcb, sbspace(&up->so_rcv));
227:
228: case PRU_RCVOOB:
229: return EOPNOTSUPP; /* (no release) */
230:
231: case PRU_LISTEN:
232: return rfcomm_listen(pcb);
233:
234: case PRU_ACCEPT:
235: KASSERT(nam != NULL);
236: sa = mtod(nam, struct sockaddr_bt *);
237: nam->m_len = sizeof(struct sockaddr_bt);
238: return rfcomm_peeraddr(pcb, sa);
239:
240: case PRU_CONNECT2:
241: case PRU_SENDOOB:
242: case PRU_FASTTIMO:
243: case PRU_SLOWTIMO:
244: case PRU_PROTORCV:
245: case PRU_PROTOSEND:
246: err = EOPNOTSUPP;
247: break;
248:
249: default:
250: UNKNOWN(req);
251: err = EOPNOTSUPP;
252: break;
253: }
254:
255: release:
256: if (m) m_freem(m);
257: if (ctl) m_freem(ctl);
258: return err;
259: }
260:
261: /*
262: * rfcomm_ctloutput(request, socket, level, optname, opt)
263: *
264: */
265: int
266: rfcomm_ctloutput(int req, struct socket *so, int level,
267: int optname, struct mbuf **opt)
268: {
269: struct rfcomm_dlc *pcb = so->so_pcb;
270: struct mbuf *m;
271: int err = 0;
272:
273: #ifdef notyet /* XXX */
274: DPRINTFN(2, "%s\n", prcorequests[req]);
275: #endif
276:
277: if (pcb == NULL)
278: return EINVAL;
279:
280: if (level != BTPROTO_RFCOMM)
281: return ENOPROTOOPT;
282:
283: switch(req) {
284: case PRCO_GETOPT:
285: m = m_get(M_WAIT, MT_SOOPTS);
286: m->m_len = rfcomm_getopt(pcb, optname, mtod(m, void *));
287: if (m->m_len == 0) {
288: m_freem(m);
289: m = NULL;
290: err = ENOPROTOOPT;
291: }
292: *opt = m;
293: break;
294:
295: case PRCO_SETOPT:
296: m = *opt;
297: KASSERT(m != NULL);
298: err = rfcomm_setopt(pcb, optname, mtod(m, void *));
299: m_freem(m);
300: break;
301:
302: default:
303: err = ENOPROTOOPT;
304: break;
305: }
306:
307: return err;
308: }
309:
310: /**********************************************************************
311: *
312: * RFCOMM callbacks
313: */
314:
315: static void
316: rfcomm_connecting(void *arg)
317: {
318: /* struct socket *so = arg; */
319:
320: KASSERT(arg != NULL);
321: DPRINTF("Connecting\n");
322: }
323:
324: static void
325: rfcomm_connected(void *arg)
326: {
327: struct socket *so = arg;
328:
329: KASSERT(so != NULL);
330: DPRINTF("Connected\n");
331: soisconnected(so);
332: }
333:
334: static void
335: rfcomm_disconnected(void *arg, int err)
336: {
337: struct socket *so = arg;
338:
339: KASSERT(so != NULL);
340: DPRINTF("Disconnected\n");
341:
342: so->so_error = err;
343: soisdisconnected(so);
344: }
345:
346: static void *
347: rfcomm_newconn(void *arg, struct sockaddr_bt *laddr,
348: struct sockaddr_bt *raddr)
349: {
350: struct socket *so = arg;
351:
352: DPRINTF("New Connection\n");
353: so = sonewconn(so, 0);
354: if (so == NULL)
355: return NULL;
356:
357: soisconnecting(so);
358:
359: return so->so_pcb;
360: }
361:
362: /*
363: * rfcomm_complete(rfcomm_dlc, length)
364: *
365: * length bytes are sent and may be removed from socket buffer
366: */
367: static void
368: rfcomm_complete(void *arg, int length)
369: {
370: struct socket *so = arg;
371:
372: sbdrop(&so->so_snd, length);
373: sowwakeup(so);
374: }
375:
376: /*
377: * rfcomm_linkmode(rfcomm_dlc, new)
378: *
379: * link mode change notification.
380: */
381: static void
382: rfcomm_linkmode(void *arg, int new)
383: {
384: struct socket *so = arg;
385: int mode;
386:
387: DPRINTF("auth %s, encrypt %s, secure %s\n",
388: (new & RFCOMM_LM_AUTH ? "on" : "off"),
389: (new & RFCOMM_LM_ENCRYPT ? "on" : "off"),
390: (new & RFCOMM_LM_SECURE ? "on" : "off"));
391:
392: (void)rfcomm_getopt(so->so_pcb, SO_RFCOMM_LM, &mode);
393: if (((mode & RFCOMM_LM_AUTH) && !(new & RFCOMM_LM_AUTH))
394: || ((mode & RFCOMM_LM_ENCRYPT) && !(new & RFCOMM_LM_ENCRYPT))
395: || ((mode & RFCOMM_LM_SECURE) && !(new & RFCOMM_LM_SECURE)))
396: rfcomm_disconnect(so->so_pcb, 0);
397: }
398:
399: /*
400: * rfcomm_input(rfcomm_dlc, mbuf)
401: */
402: static void
403: rfcomm_input(void *arg, struct mbuf *m)
404: {
405: struct socket *so = arg;
406:
407: KASSERT(so != NULL);
408:
409: if (m->m_pkthdr.len > sbspace(&so->so_rcv)) {
410: printf("%s: %d bytes dropped (socket buffer full)\n",
411: __func__, m->m_pkthdr.len);
412: m_freem(m);
413: return;
414: }
415:
416: DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
417:
418: sbappendstream(&so->so_rcv, m);
419: sorwakeup(so);
420: }
CVSweb