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

Cache object: eff08130b32a5b3a4396f87bf0fc4d34


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