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  -  FREEBSD11  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: rfcomm_socket.c,v 1.4 2008/11/22 04:42:58 uwe Exp $   */
    2 /*      $NetBSD: rfcomm_socket.c,v 1.10 2008/08/06 15:01:24 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 /* load symbolic names */
   36 #ifdef BLUETOOTH_DEBUG
   37 #define PRUREQUESTS
   38 #define PRCOREQUESTS
   39 #endif
   40 
   41 #include <sys/param.h>
   42 #include <sys/domain.h>
   43 #include <sys/kernel.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/proc.h>
   46 #include <sys/protosw.h>
   47 #include <sys/socket.h>
   48 #include <sys/socketvar.h>
   49 #include <sys/systm.h>
   50 
   51 #include <netbt/bluetooth.h>
   52 #include <netbt/hci.h>          /* XXX for EPASSTHROUGH */
   53 #include <netbt/rfcomm.h>
   54 
   55 /****************************************************************************
   56  *
   57  *      RFCOMM SOCK_STREAM Sockets - serial line emulation
   58  *
   59  */
   60 
   61 static void rfcomm_connecting(void *);
   62 static void rfcomm_connected(void *);
   63 static void rfcomm_disconnected(void *, int);
   64 static void *rfcomm_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
   65 static void rfcomm_complete(void *, int);
   66 static void rfcomm_linkmode(void *, int);
   67 static void rfcomm_input(void *, struct mbuf *);
   68 
   69 static const struct btproto rfcomm_proto = {
   70         rfcomm_connecting,
   71         rfcomm_connected,
   72         rfcomm_disconnected,
   73         rfcomm_newconn,
   74         rfcomm_complete,
   75         rfcomm_linkmode,
   76         rfcomm_input,
   77 };
   78 
   79 /* sysctl variables */
   80 int rfcomm_sendspace = 4096;
   81 int rfcomm_recvspace = 4096;
   82 
   83 /*
   84  * User Request.
   85  * up is socket
   86  * m is either
   87  *      optional mbuf chain containing message
   88  *      ioctl command (PRU_CONTROL)
   89  * nam is either
   90  *      optional mbuf chain containing an address
   91  *      ioctl data (PRU_CONTROL)
   92  *      optionally protocol number (PRU_ATTACH)
   93  *      message flags (PRU_RCVD)
   94  * ctl is either
   95  *      optional mbuf chain containing socket options
   96  *      optional interface pointer (PRU_CONTROL, PRU_PURGEIF)
   97  * l is pointer to process requesting action (if any)
   98  *
   99  * we are responsible for disposing of m and ctl if
  100  * they are mbuf chains
  101  */
  102 int
  103 rfcomm_usrreq(struct socket *up, int req, struct mbuf *m,
  104     struct mbuf *nam, struct mbuf *ctl, struct proc *p)
  105 {
  106         struct rfcomm_dlc *pcb = up->so_pcb;
  107         struct sockaddr_bt *sa;
  108         struct mbuf *m0;
  109         int err = 0;
  110 
  111 #ifdef notyet                   /* XXX */
  112         DPRINTFN(2, "%s\n", prurequests[req]);
  113 #endif
  114 
  115         switch (req) {
  116         case PRU_CONTROL:
  117                 return EPASSTHROUGH;
  118 
  119 #ifdef notyet                   /* XXX */
  120         case PRU_PURGEIF:
  121                 return EOPNOTSUPP;
  122 #endif
  123 
  124         case PRU_ATTACH:
  125                 /* XXX solock() and bt_lock fiddling in NetBSD */
  126                 if (pcb != NULL)
  127                         return EINVAL;
  128                 /*
  129                  * Since we have nothing to add, we attach the DLC
  130                  * structure directly to our PCB pointer.
  131                  */
  132                 err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace);
  133                 if (err)
  134                         return err;
  135 
  136                 err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb,
  137                                         &rfcomm_proto, up);
  138                 if (err)
  139                         return err;
  140 
  141                 err = rfcomm_rcvd(up->so_pcb, sbspace(&up->so_rcv));
  142                 if (err) {
  143                         rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb);
  144                         return err;
  145                 }
  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 }

Cache object: 4111be3228078f7816509a5e72190cbb


[ 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.