rfcomm_socket.c revision 1.8
1/* $NetBSD: rfcomm_socket.c,v 1.8 2007/10/15 18:04:34 plunky Exp $ */ 2 3/*- 4 * Copyright (c) 2006 Itronix Inc. 5 * All rights reserved. 6 * 7 * Written by Iain Hibbert for Itronix Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of Itronix Inc. may not be used to endorse 18 * or promote products derived from this software without specific 19 * prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#include <sys/cdefs.h> 35__KERNEL_RCSID(0, "$NetBSD: rfcomm_socket.c,v 1.8 2007/10/15 18:04:34 plunky Exp $"); 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/rfcomm.h> 55 56/**************************************************************************** 57 * 58 * RFCOMM SOCK_STREAM Sockets - serial line emulation 59 * 60 */ 61 62static void rfcomm_connecting(void *); 63static void rfcomm_connected(void *); 64static void rfcomm_disconnected(void *, int); 65static void *rfcomm_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); 66static void rfcomm_complete(void *, int); 67static void rfcomm_linkmode(void *, int); 68static void rfcomm_input(void *, struct mbuf *); 69 70static const struct btproto rfcomm_proto = { 71 rfcomm_connecting, 72 rfcomm_connected, 73 rfcomm_disconnected, 74 rfcomm_newconn, 75 rfcomm_complete, 76 rfcomm_linkmode, 77 rfcomm_input, 78}; 79 80/* sysctl variables */ 81int rfcomm_sendspace = 4096; 82int rfcomm_recvspace = 4096; 83 84/* 85 * User Request. 86 * up is socket 87 * m is either 88 * optional mbuf chain containing message 89 * ioctl command (PRU_CONTROL) 90 * nam is either 91 * optional mbuf chain containing an address 92 * ioctl data (PRU_CONTROL) 93 * optionally protocol number (PRU_ATTACH) 94 * message flags (PRU_RCVD) 95 * ctl is either 96 * optional mbuf chain containing socket options 97 * optional interface pointer (PRU_CONTROL, PRU_PURGEIF) 98 * l is pointer to process requesting action (if any) 99 * 100 * we are responsible for disposing of m and ctl if 101 * they are mbuf chains 102 */ 103int 104rfcomm_usrreq(struct socket *up, int req, struct mbuf *m, 105 struct mbuf *nam, struct mbuf *ctl, struct lwp *l) 106{ 107 struct rfcomm_dlc *pcb = up->so_pcb; 108 struct sockaddr_bt *sa; 109 struct mbuf *m0; 110 int err = 0; 111 112 DPRINTFN(2, "%s\n", prurequests[req]); 113 114 switch (req) { 115 case PRU_CONTROL: 116 return EPASSTHROUGH; 117 118 case PRU_PURGEIF: 119 return EOPNOTSUPP; 120 121 case PRU_ATTACH: 122 if (pcb != NULL) 123 return EINVAL; 124 125 /* 126 * Since we have nothing to add, we attach the DLC 127 * structure directly to our PCB pointer. 128 */ 129 err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace); 130 if (err) 131 return err; 132 133 err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb, 134 &rfcomm_proto, up); 135 if (err) 136 return err; 137 138 err = rfcomm_rcvd(up->so_pcb, sbspace(&up->so_rcv)); 139 if (err) { 140 rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb); 141 return err; 142 } 143 144 return 0; 145 } 146 147 if (pcb == NULL) { 148 err = EINVAL; 149 goto release; 150 } 151 152 switch(req) { 153 case PRU_DISCONNECT: 154 soisdisconnecting(up); 155 return rfcomm_disconnect(pcb, up->so_linger); 156 157 case PRU_ABORT: 158 rfcomm_disconnect(pcb, 0); 159 soisdisconnected(up); 160 /* fall through to */ 161 case PRU_DETACH: 162 return rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb); 163 164 case PRU_BIND: 165 KASSERT(nam != NULL); 166 sa = mtod(nam, struct sockaddr_bt *); 167 168 if (sa->bt_len != sizeof(struct sockaddr_bt)) 169 return EINVAL; 170 171 if (sa->bt_family != AF_BLUETOOTH) 172 return EAFNOSUPPORT; 173 174 return rfcomm_bind(pcb, sa); 175 176 case PRU_CONNECT: 177 KASSERT(nam != NULL); 178 sa = mtod(nam, struct sockaddr_bt *); 179 180 if (sa->bt_len != sizeof(struct sockaddr_bt)) 181 return EINVAL; 182 183 if (sa->bt_family != AF_BLUETOOTH) 184 return EAFNOSUPPORT; 185 186 soisconnecting(up); 187 return rfcomm_connect(pcb, sa); 188 189 case PRU_PEERADDR: 190 KASSERT(nam != NULL); 191 sa = mtod(nam, struct sockaddr_bt *); 192 nam->m_len = sizeof(struct sockaddr_bt); 193 return rfcomm_peeraddr(pcb, sa); 194 195 case PRU_SOCKADDR: 196 KASSERT(nam != NULL); 197 sa = mtod(nam, struct sockaddr_bt *); 198 nam->m_len = sizeof(struct sockaddr_bt); 199 return rfcomm_sockaddr(pcb, sa); 200 201 case PRU_SHUTDOWN: 202 socantsendmore(up); 203 break; 204 205 case PRU_SEND: 206 KASSERT(m != NULL); 207 208 if (ctl) /* no use for that */ 209 m_freem(ctl); 210 211 m0 = m_copypacket(m, M_DONTWAIT); 212 if (m0 == NULL) 213 return ENOMEM; 214 215 sbappendstream(&up->so_snd, m); 216 217 return rfcomm_send(pcb, m0); 218 219 case PRU_SENSE: 220 return 0; /* (no release) */ 221 222 case PRU_RCVD: 223 return rfcomm_rcvd(pcb, sbspace(&up->so_rcv)); 224 225 case PRU_RCVOOB: 226 return EOPNOTSUPP; /* (no release) */ 227 228 case PRU_LISTEN: 229 return rfcomm_listen(pcb); 230 231 case PRU_ACCEPT: 232 KASSERT(nam != NULL); 233 sa = mtod(nam, struct sockaddr_bt *); 234 nam->m_len = sizeof(struct sockaddr_bt); 235 return rfcomm_peeraddr(pcb, sa); 236 237 case PRU_CONNECT2: 238 case PRU_SENDOOB: 239 case PRU_FASTTIMO: 240 case PRU_SLOWTIMO: 241 case PRU_PROTORCV: 242 case PRU_PROTOSEND: 243 err = EOPNOTSUPP; 244 break; 245 246 default: 247 UNKNOWN(req); 248 err = EOPNOTSUPP; 249 break; 250 } 251 252release: 253 if (m) m_freem(m); 254 if (ctl) m_freem(ctl); 255 return err; 256} 257 258/* 259 * rfcomm_ctloutput(request, socket, level, optname, opt) 260 * 261 */ 262int 263rfcomm_ctloutput(int req, struct socket *so, int level, 264 int optname, struct mbuf **opt) 265{ 266 struct rfcomm_dlc *pcb = so->so_pcb; 267 struct mbuf *m; 268 int err = 0; 269 270 DPRINTFN(2, "%s\n", prcorequests[req]); 271 272 if (pcb == NULL) 273 return EINVAL; 274 275 if (level != BTPROTO_RFCOMM) 276 return ENOPROTOOPT; 277 278 switch(req) { 279 case PRCO_GETOPT: 280 m = m_get(M_WAIT, MT_SOOPTS); 281 m->m_len = rfcomm_getopt(pcb, optname, mtod(m, void *)); 282 if (m->m_len == 0) { 283 m_freem(m); 284 m = NULL; 285 err = ENOPROTOOPT; 286 } 287 *opt = m; 288 break; 289 290 case PRCO_SETOPT: 291 m = *opt; 292 KASSERT(m != NULL); 293 err = rfcomm_setopt(pcb, optname, mtod(m, void *)); 294 m_freem(m); 295 break; 296 297 default: 298 err = ENOPROTOOPT; 299 break; 300 } 301 302 return err; 303} 304 305/********************************************************************** 306 * 307 * RFCOMM callbacks 308 */ 309 310static void 311rfcomm_connecting(void *arg) 312{ 313 /* struct socket *so = arg; */ 314 315 KASSERT(arg != NULL); 316 DPRINTF("Connecting\n"); 317} 318 319static void 320rfcomm_connected(void *arg) 321{ 322 struct socket *so = arg; 323 324 KASSERT(so != NULL); 325 DPRINTF("Connected\n"); 326 soisconnected(so); 327} 328 329static void 330rfcomm_disconnected(void *arg, int err) 331{ 332 struct socket *so = arg; 333 334 KASSERT(so != NULL); 335 DPRINTF("Disconnected\n"); 336 337 so->so_error = err; 338 soisdisconnected(so); 339} 340 341static void * 342rfcomm_newconn(void *arg, struct sockaddr_bt *laddr, 343 struct sockaddr_bt *raddr) 344{ 345 struct socket *so = arg; 346 347 DPRINTF("New Connection\n"); 348 so = sonewconn(so, 0); 349 if (so == NULL) 350 return NULL; 351 352 soisconnecting(so); 353 354 return so->so_pcb; 355} 356 357/* 358 * rfcomm_complete(rfcomm_dlc, length) 359 * 360 * length bytes are sent and may be removed from socket buffer 361 */ 362static void 363rfcomm_complete(void *arg, int length) 364{ 365 struct socket *so = arg; 366 367 sbdrop(&so->so_snd, length); 368 sowwakeup(so); 369} 370 371/* 372 * rfcomm_linkmode(rfcomm_dlc, new) 373 * 374 * link mode change notification. 375 */ 376static void 377rfcomm_linkmode(void *arg, int new) 378{ 379 struct socket *so = arg; 380 int mode; 381 382 DPRINTF("auth %s, encrypt %s, secure %s\n", 383 (new & RFCOMM_LM_AUTH ? "on" : "off"), 384 (new & RFCOMM_LM_ENCRYPT ? "on" : "off"), 385 (new & RFCOMM_LM_SECURE ? "on" : "off")); 386 387 (void)rfcomm_getopt(so->so_pcb, SO_RFCOMM_LM, &mode); 388 if (((mode & RFCOMM_LM_AUTH) && !(new & RFCOMM_LM_AUTH)) 389 || ((mode & RFCOMM_LM_ENCRYPT) && !(new & RFCOMM_LM_ENCRYPT)) 390 || ((mode & RFCOMM_LM_SECURE) && !(new & RFCOMM_LM_SECURE))) 391 rfcomm_disconnect(so->so_pcb, 0); 392} 393 394/* 395 * rfcomm_input(rfcomm_dlc, mbuf) 396 */ 397static void 398rfcomm_input(void *arg, struct mbuf *m) 399{ 400 struct socket *so = arg; 401 402 KASSERT(so != NULL); 403 404 if (m->m_pkthdr.len > sbspace(&so->so_rcv)) { 405 printf("%s: %d bytes dropped (socket buffer full)\n", 406 __func__, m->m_pkthdr.len); 407 m_freem(m); 408 return; 409 } 410 411 DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len); 412 413 sbappendstream(&so->so_rcv, m); 414 sorwakeup(so); 415} 416