The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netbt/rfcomm_socket.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: rfcomm_socket.c,v 1.10 2008/08/06 15:01:24 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.10 2008/08/06 15:01:24 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 
   62 static void rfcomm_connecting(void *);
   63 static void rfcomm_connected(void *);
   64 static void rfcomm_disconnected(void *, int);
   65 static void *rfcomm_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
   66 static void rfcomm_complete(void *, int);
   67 static void rfcomm_linkmode(void *, int);
   68 static void rfcomm_input(void *, struct mbuf *);
   69 
   70 static 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 */
   81 int rfcomm_sendspace = 4096;
   82 int 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  */
  103 int
  104 rfcomm_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 (up->so_lock == NULL) {
  123                         mutex_obj_hold(bt_lock);
  124                         up->so_lock = bt_lock;
  125                         solock(up);
  126                 }
  127                 KASSERT(solocked(up));
  128                 if (pcb != NULL)
  129                         return EINVAL;
  130                 /*
  131                  * Since we have nothing to add, we attach the DLC
  132                  * structure directly to our PCB pointer.
  133                  */
  134                 err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace);
  135                 if (err)
  136                         return err;
  137 
  138                 err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb,
  139                                         &rfcomm_proto, up);
  140                 if (err)
  141                         return err;
  142 
  143                 err = rfcomm_rcvd(up->so_pcb, sbspace(&up->so_rcv));
  144                 if (err) {
  145                         rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb);
  146                         return err;
  147                 }
  148 
  149                 return 0;
  150         }
  151 
  152         if (pcb == NULL) {
  153                 err = EINVAL;
  154                 goto release;
  155         }
  156 
  157         switch(req) {
  158         case PRU_DISCONNECT:
  159                 soisdisconnecting(up);
  160                 return rfcomm_disconnect(pcb, up->so_linger);
  161 
  162         case PRU_ABORT:
  163                 rfcomm_disconnect(pcb, 0);
  164                 soisdisconnected(up);
  165                 /* fall through to */
  166         case PRU_DETACH:
  167                 return rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb);
  168 
  169         case PRU_BIND:
  170                 KASSERT(nam != NULL);
  171                 sa = mtod(nam, struct sockaddr_bt *);
  172 
  173                 if (sa->bt_len != sizeof(struct sockaddr_bt))
  174                         return EINVAL;
  175 
  176                 if (sa->bt_family != AF_BLUETOOTH)
  177                         return EAFNOSUPPORT;
  178 
  179                 return rfcomm_bind(pcb, sa);
  180 
  181         case PRU_CONNECT:
  182                 KASSERT(nam != NULL);
  183                 sa = mtod(nam, struct sockaddr_bt *);
  184 
  185                 if (sa->bt_len != sizeof(struct sockaddr_bt))
  186                         return EINVAL;
  187 
  188                 if (sa->bt_family != AF_BLUETOOTH)
  189                         return EAFNOSUPPORT;
  190 
  191                 soisconnecting(up);
  192                 return rfcomm_connect(pcb, sa);
  193 
  194         case PRU_PEERADDR:
  195                 KASSERT(nam != NULL);
  196                 sa = mtod(nam, struct sockaddr_bt *);
  197                 nam->m_len = sizeof(struct sockaddr_bt);
  198                 return rfcomm_peeraddr(pcb, sa);
  199 
  200         case PRU_SOCKADDR:
  201                 KASSERT(nam != NULL);
  202                 sa = mtod(nam, struct sockaddr_bt *);
  203                 nam->m_len = sizeof(struct sockaddr_bt);
  204                 return rfcomm_sockaddr(pcb, sa);
  205 
  206         case PRU_SHUTDOWN:
  207                 socantsendmore(up);
  208                 break;
  209 
  210         case PRU_SEND:
  211                 KASSERT(m != NULL);
  212 
  213                 if (ctl)        /* no use for that */
  214                         m_freem(ctl);
  215 
  216                 m0 = m_copypacket(m, M_DONTWAIT);
  217                 if (m0 == NULL)
  218                         return ENOMEM;
  219 
  220                 sbappendstream(&up->so_snd, m);
  221 
  222                 return rfcomm_send(pcb, m0);
  223 
  224         case PRU_SENSE:
  225                 return 0;               /* (no release) */
  226 
  227         case PRU_RCVD:
  228                 return rfcomm_rcvd(pcb, sbspace(&up->so_rcv));
  229 
  230         case PRU_RCVOOB:
  231                 return EOPNOTSUPP;      /* (no release) */
  232 
  233         case PRU_LISTEN:
  234                 return rfcomm_listen(pcb);
  235 
  236         case PRU_ACCEPT:
  237                 KASSERT(nam != NULL);
  238                 sa = mtod(nam, struct sockaddr_bt *);
  239                 nam->m_len = sizeof(struct sockaddr_bt);
  240                 return rfcomm_peeraddr(pcb, sa);
  241 
  242         case PRU_CONNECT2:
  243         case PRU_SENDOOB:
  244         case PRU_FASTTIMO:
  245         case PRU_SLOWTIMO:
  246         case PRU_PROTORCV:
  247         case PRU_PROTOSEND:
  248                 err = EOPNOTSUPP;
  249                 break;
  250 
  251         default:
  252                 UNKNOWN(req);
  253                 err = EOPNOTSUPP;
  254                 break;
  255         }
  256 
  257 release:
  258         if (m) m_freem(m);
  259         if (ctl) m_freem(ctl);
  260         return err;
  261 }
  262 
  263 /*
  264  * rfcomm_ctloutput(req, socket, sockopt)
  265  *
  266  */
  267 int
  268 rfcomm_ctloutput(int req, struct socket *so, struct sockopt *sopt)
  269 {
  270         struct rfcomm_dlc *pcb = so->so_pcb;
  271         int err = 0;
  272 
  273         DPRINTFN(2, "%s\n", prcorequests[req]);
  274 
  275         if (pcb == NULL)
  276                 return EINVAL;
  277 
  278         if (sopt->sopt_level != BTPROTO_RFCOMM)
  279                 return ENOPROTOOPT;
  280 
  281         switch(req) {
  282         case PRCO_GETOPT:
  283                 err = rfcomm_getopt(pcb, sopt);
  284                 break;
  285 
  286         case PRCO_SETOPT:
  287                 err = rfcomm_setopt(pcb, sopt);
  288                 break;
  289 
  290         default:
  291                 err = ENOPROTOOPT;
  292                 break;
  293         }
  294 
  295         return err;
  296 }
  297 
  298 /**********************************************************************
  299  *
  300  * RFCOMM callbacks
  301  */
  302 
  303 static void
  304 rfcomm_connecting(void *arg)
  305 {
  306         /* struct socket *so = arg; */
  307 
  308         KASSERT(arg != NULL);
  309         DPRINTF("Connecting\n");
  310 }
  311 
  312 static void
  313 rfcomm_connected(void *arg)
  314 {
  315         struct socket *so = arg;
  316 
  317         KASSERT(so != NULL);
  318         DPRINTF("Connected\n");
  319         soisconnected(so);
  320 }
  321 
  322 static void
  323 rfcomm_disconnected(void *arg, int err)
  324 {
  325         struct socket *so = arg;
  326 
  327         KASSERT(so != NULL);
  328         DPRINTF("Disconnected\n");
  329 
  330         so->so_error = err;
  331         soisdisconnected(so);
  332 }
  333 
  334 static void *
  335 rfcomm_newconn(void *arg, struct sockaddr_bt *laddr,
  336     struct sockaddr_bt *raddr)
  337 {
  338         struct socket *so = arg;
  339 
  340         DPRINTF("New Connection\n");
  341         so = sonewconn(so, 0);
  342         if (so == NULL)
  343                 return NULL;
  344 
  345         soisconnecting(so);
  346 
  347         return so->so_pcb;
  348 }
  349 
  350 /*
  351  * rfcomm_complete(rfcomm_dlc, length)
  352  *
  353  * length bytes are sent and may be removed from socket buffer
  354  */
  355 static void
  356 rfcomm_complete(void *arg, int length)
  357 {
  358         struct socket *so = arg;
  359 
  360         sbdrop(&so->so_snd, length);
  361         sowwakeup(so);
  362 }
  363 
  364 /*
  365  * rfcomm_linkmode(rfcomm_dlc, new)
  366  *
  367  * link mode change notification.
  368  */
  369 static void
  370 rfcomm_linkmode(void *arg, int new)
  371 {
  372         struct socket *so = arg;
  373         struct sockopt sopt;
  374         int mode;
  375 
  376         DPRINTF("auth %s, encrypt %s, secure %s\n",
  377                 (new & RFCOMM_LM_AUTH ? "on" : "off"),
  378                 (new & RFCOMM_LM_ENCRYPT ? "on" : "off"),
  379                 (new & RFCOMM_LM_SECURE ? "on" : "off"));
  380 
  381         sockopt_init(&sopt, BTPROTO_RFCOMM, SO_RFCOMM_LM, 0);
  382         (void)rfcomm_getopt(so->so_pcb, &sopt);
  383         (void)sockopt_getint(&sopt, &mode);
  384         sockopt_destroy(&sopt);
  385 
  386         if (((mode & RFCOMM_LM_AUTH) && !(new & RFCOMM_LM_AUTH))
  387             || ((mode & RFCOMM_LM_ENCRYPT) && !(new & RFCOMM_LM_ENCRYPT))
  388             || ((mode & RFCOMM_LM_SECURE) && !(new & RFCOMM_LM_SECURE)))
  389                 rfcomm_disconnect(so->so_pcb, 0);
  390 }
  391 
  392 /*
  393  * rfcomm_input(rfcomm_dlc, mbuf)
  394  */
  395 static void
  396 rfcomm_input(void *arg, struct mbuf *m)
  397 {
  398         struct socket *so = arg;
  399 
  400         KASSERT(so != NULL);
  401 
  402         if (m->m_pkthdr.len > sbspace(&so->so_rcv)) {
  403                 printf("%s: %d bytes dropped (socket buffer full)\n",
  404                         __func__, m->m_pkthdr.len);
  405                 m_freem(m);
  406                 return;
  407         }
  408 
  409         DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
  410 
  411         sbappendstream(&so->so_rcv, m);
  412         sorwakeup(so);
  413 }

Cache object: 5c416fecd1624870c0b0010fc74fd33f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.