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.38 2019/01/28 12:53:01 martin 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.38 2019/01/28 12:53:01 martin 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 static int
   85 rfcomm_attach(struct socket *so, int proto)
   86 {
   87         int error;
   88 
   89         KASSERT(so->so_pcb == NULL);
   90 
   91         if (so->so_lock == NULL) {
   92                 mutex_obj_hold(bt_lock);
   93                 so->so_lock = bt_lock;
   94                 solock(so);
   95         }
   96         KASSERT(solocked(so));
   97 
   98         /*
   99          * Since we have nothing to add, we attach the DLC
  100          * structure directly to our PCB pointer.
  101          */
  102         error = soreserve(so, rfcomm_sendspace, rfcomm_recvspace);
  103         if (error)
  104                 return error;
  105 
  106         error = rfcomm_attach_pcb((struct rfcomm_dlc **)&so->so_pcb,
  107                                 &rfcomm_proto, so);
  108         if (error)
  109                 return error;
  110 
  111         error = rfcomm_rcvd_pcb(so->so_pcb, sbspace(&so->so_rcv));
  112         if (error) {
  113                 rfcomm_detach_pcb((struct rfcomm_dlc **)&so->so_pcb);
  114                 return error;
  115         }
  116         return 0;
  117 }
  118 
  119 static void
  120 rfcomm_detach(struct socket *so)
  121 {
  122         KASSERT(so->so_pcb != NULL);
  123         rfcomm_detach_pcb((struct rfcomm_dlc **)&so->so_pcb);
  124         KASSERT(so->so_pcb == NULL);
  125 }
  126 
  127 static int
  128 rfcomm_accept(struct socket *so, struct sockaddr *nam)
  129 {
  130         struct rfcomm_dlc *pcb = so->so_pcb;
  131 
  132         KASSERT(solocked(so));
  133         KASSERT(nam != NULL);
  134 
  135         if (pcb == NULL)
  136                 return EINVAL;
  137 
  138         return rfcomm_peeraddr_pcb(pcb, (struct sockaddr_bt *)nam);
  139 }
  140 
  141 static int
  142 rfcomm_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
  143 {
  144         struct rfcomm_dlc *pcb = so->so_pcb;
  145         struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
  146 
  147         KASSERT(solocked(so));
  148         KASSERT(nam != NULL);
  149 
  150         if (pcb == NULL)
  151                 return EINVAL;
  152 
  153         if (sa->bt_len != sizeof(struct sockaddr_bt))
  154                 return EINVAL;
  155 
  156         if (sa->bt_family != AF_BLUETOOTH)
  157                 return EAFNOSUPPORT;
  158 
  159         return rfcomm_bind_pcb(pcb, sa);
  160 }
  161 
  162 static int
  163 rfcomm_listen(struct socket *so, struct lwp *l)
  164 {
  165         struct rfcomm_dlc *pcb = so->so_pcb;
  166 
  167         KASSERT(solocked(so));
  168 
  169         if (pcb == NULL)
  170                 return EINVAL;
  171 
  172         return rfcomm_listen_pcb(pcb);
  173 }
  174 
  175 static int
  176 rfcomm_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
  177 {
  178         struct rfcomm_dlc *pcb = so->so_pcb;
  179         struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
  180 
  181         KASSERT(solocked(so));
  182         KASSERT(nam != NULL);
  183 
  184         if (pcb == NULL)
  185                 return EINVAL;
  186 
  187         if (sa->bt_len != sizeof(struct sockaddr_bt))
  188                 return EINVAL;
  189 
  190         if (sa->bt_family != AF_BLUETOOTH)
  191                 return EAFNOSUPPORT;
  192 
  193         soisconnecting(so);
  194         return rfcomm_connect_pcb(pcb, sa);
  195 }
  196 
  197 static int
  198 rfcomm_connect2(struct socket *so, struct socket *so2)
  199 {
  200         struct rfcomm_dlc *pcb = so->so_pcb;
  201 
  202         KASSERT(solocked(so));
  203 
  204         if (pcb == NULL)
  205                 return EINVAL;
  206 
  207         return EOPNOTSUPP;
  208 }
  209 
  210 static int
  211 rfcomm_disconnect(struct socket *so)
  212 {
  213         struct rfcomm_dlc *pcb = so->so_pcb;
  214 
  215         KASSERT(solocked(so));
  216 
  217         if (pcb == NULL)
  218                 return EINVAL;
  219 
  220         soisdisconnecting(so);
  221         return rfcomm_disconnect_pcb(pcb, so->so_linger);
  222 }
  223 
  224 static int
  225 rfcomm_shutdown(struct socket *so)
  226 {
  227         KASSERT(solocked(so));
  228 
  229         socantsendmore(so);
  230         return 0;
  231 }
  232 
  233 static int
  234 rfcomm_abort(struct socket *so)
  235 {
  236         struct rfcomm_dlc *pcb = so->so_pcb;
  237 
  238         KASSERT(solocked(so));
  239 
  240         if (pcb == NULL)
  241                 return EINVAL;
  242 
  243         rfcomm_disconnect_pcb(pcb, 0);
  244         soisdisconnected(so);
  245         rfcomm_detach(so);
  246         return 0;
  247 }
  248 
  249 static int
  250 rfcomm_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
  251 {
  252         return EPASSTHROUGH;
  253 }
  254 
  255 static int
  256 rfcomm_stat(struct socket *so, struct stat *ub)
  257 {
  258         KASSERT(solocked(so));
  259 
  260         return 0;
  261 }
  262 
  263 static int
  264 rfcomm_peeraddr(struct socket *so, struct sockaddr *nam)
  265 {
  266         struct rfcomm_dlc *pcb = so->so_pcb;
  267 
  268         KASSERT(solocked(so));
  269         KASSERT(pcb != NULL);
  270         KASSERT(nam != NULL);
  271 
  272         return rfcomm_peeraddr_pcb(pcb, (struct sockaddr_bt *)nam);
  273 }
  274 
  275 static int
  276 rfcomm_sockaddr(struct socket *so, struct sockaddr *nam)
  277 {
  278         struct rfcomm_dlc *pcb = so->so_pcb;
  279 
  280         KASSERT(solocked(so));
  281         KASSERT(pcb != NULL);
  282         KASSERT(nam != NULL);
  283 
  284         return rfcomm_sockaddr_pcb(pcb, (struct sockaddr_bt *)nam);
  285 }
  286 
  287 static int
  288 rfcomm_rcvd(struct socket *so, int flags, struct lwp *l)
  289 {
  290         struct rfcomm_dlc *pcb = so->so_pcb;
  291 
  292         KASSERT(solocked(so));
  293 
  294         if (pcb == NULL)
  295                 return EINVAL;
  296 
  297         return rfcomm_rcvd_pcb(pcb, sbspace(&so->so_rcv));
  298 }
  299 
  300 static int
  301 rfcomm_recvoob(struct socket *so, struct mbuf *m, int flags)
  302 {
  303         KASSERT(solocked(so));
  304 
  305         return EOPNOTSUPP;
  306 }
  307 
  308 static int
  309 rfcomm_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
  310     struct mbuf *control, struct lwp *l)
  311 {
  312         struct rfcomm_dlc *pcb = so->so_pcb;
  313         int err = 0;
  314         struct mbuf *m0;
  315 
  316         KASSERT(solocked(so));
  317         KASSERT(m != NULL);
  318 
  319         if (control)    /* no use for that */
  320                 m_freem(control);
  321 
  322         if (pcb == NULL) {
  323                 err = EINVAL;
  324                 goto release;
  325         }
  326 
  327         m0 = m_copypacket(m, M_DONTWAIT);
  328         if (m0 == NULL) {
  329                 err = ENOMEM;
  330                 goto release;
  331         }
  332 
  333         sbappendstream(&so->so_snd, m);
  334         return rfcomm_send_pcb(pcb, m0);
  335 
  336 release:
  337         m_freem(m);
  338         return err;
  339 }
  340 
  341 static int
  342 rfcomm_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
  343 {
  344         KASSERT(solocked(so));
  345 
  346         m_freem(m);
  347         m_freem(control);
  348 
  349         return EOPNOTSUPP;
  350 }
  351 
  352 static int
  353 rfcomm_purgeif(struct socket *so, struct ifnet *ifp)
  354 {
  355 
  356         return EOPNOTSUPP;
  357 }
  358 
  359 /*
  360  * rfcomm_ctloutput(req, socket, sockopt)
  361  *
  362  */
  363 int
  364 rfcomm_ctloutput(int req, struct socket *so, struct sockopt *sopt)
  365 {
  366         struct rfcomm_dlc *pcb = so->so_pcb;
  367         int err = 0;
  368 
  369         DPRINTFN(2, "%s\n", prcorequests[req]);
  370 
  371         if (pcb == NULL)
  372                 return EINVAL;
  373 
  374         if (sopt->sopt_level != BTPROTO_RFCOMM)
  375                 return ENOPROTOOPT;
  376 
  377         switch(req) {
  378         case PRCO_GETOPT:
  379                 err = rfcomm_getopt(pcb, sopt);
  380                 break;
  381 
  382         case PRCO_SETOPT:
  383                 err = rfcomm_setopt(pcb, sopt);
  384                 break;
  385 
  386         default:
  387                 err = ENOPROTOOPT;
  388                 break;
  389         }
  390 
  391         return err;
  392 }
  393 
  394 /**********************************************************************
  395  *
  396  * RFCOMM callbacks
  397  */
  398 
  399 static void
  400 rfcomm_connecting(void *arg)
  401 {
  402         /* struct socket *so = arg; */
  403 
  404         KASSERT(arg != NULL);
  405         DPRINTF("Connecting\n");
  406 }
  407 
  408 static void
  409 rfcomm_connected(void *arg)
  410 {
  411         struct socket *so = arg;
  412 
  413         KASSERT(so != NULL);
  414         DPRINTF("Connected\n");
  415         soisconnected(so);
  416 }
  417 
  418 static void
  419 rfcomm_disconnected(void *arg, int err)
  420 {
  421         struct socket *so = arg;
  422 
  423         KASSERT(so != NULL);
  424         DPRINTF("Disconnected\n");
  425 
  426         so->so_error = err;
  427         soisdisconnected(so);
  428 }
  429 
  430 static void *
  431 rfcomm_newconn(void *arg, struct sockaddr_bt *laddr,
  432     struct sockaddr_bt *raddr)
  433 {
  434         struct socket *so = arg;
  435 
  436         DPRINTF("New Connection\n");
  437         so = sonewconn(so, false);
  438         if (so == NULL)
  439                 return NULL;
  440 
  441         soisconnecting(so);
  442 
  443         return so->so_pcb;
  444 }
  445 
  446 /*
  447  * rfcomm_complete(rfcomm_dlc, length)
  448  *
  449  * length bytes are sent and may be removed from socket buffer
  450  */
  451 static void
  452 rfcomm_complete(void *arg, int length)
  453 {
  454         struct socket *so = arg;
  455 
  456         sbdrop(&so->so_snd, length);
  457         sowwakeup(so);
  458 }
  459 
  460 /*
  461  * rfcomm_linkmode(rfcomm_dlc, new)
  462  *
  463  * link mode change notification.
  464  */
  465 static void
  466 rfcomm_linkmode(void *arg, int new)
  467 {
  468         struct socket *so = arg;
  469         struct sockopt sopt;
  470         int mode;
  471 
  472         DPRINTF("auth %s, encrypt %s, secure %s\n",
  473                 (new & RFCOMM_LM_AUTH ? "on" : "off"),
  474                 (new & RFCOMM_LM_ENCRYPT ? "on" : "off"),
  475                 (new & RFCOMM_LM_SECURE ? "on" : "off"));
  476 
  477         sockopt_init(&sopt, BTPROTO_RFCOMM, SO_RFCOMM_LM, 0);
  478         (void)rfcomm_getopt(so->so_pcb, &sopt);
  479         (void)sockopt_getint(&sopt, &mode);
  480         sockopt_destroy(&sopt);
  481 
  482         if (((mode & RFCOMM_LM_AUTH) && !(new & RFCOMM_LM_AUTH))
  483             || ((mode & RFCOMM_LM_ENCRYPT) && !(new & RFCOMM_LM_ENCRYPT))
  484             || ((mode & RFCOMM_LM_SECURE) && !(new & RFCOMM_LM_SECURE)))
  485                 rfcomm_disconnect_pcb(so->so_pcb, 0);
  486 }
  487 
  488 /*
  489  * rfcomm_input(rfcomm_dlc, mbuf)
  490  */
  491 static void
  492 rfcomm_input(void *arg, struct mbuf *m)
  493 {
  494         struct socket *so = arg;
  495 
  496         KASSERT(so != NULL);
  497 
  498         if (m->m_pkthdr.len > sbspace(&so->so_rcv)) {
  499                 printf("%s: %d bytes dropped (socket buffer full)\n",
  500                         __func__, m->m_pkthdr.len);
  501                 m_freem(m);
  502                 return;
  503         }
  504 
  505         DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
  506 
  507         sbappendstream(&so->so_rcv, m);
  508         sorwakeup(so);
  509 }
  510 
  511 PR_WRAP_USRREQS(rfcomm)
  512 
  513 #define rfcomm_attach           rfcomm_attach_wrapper
  514 #define rfcomm_detach           rfcomm_detach_wrapper
  515 #define rfcomm_accept           rfcomm_accept_wrapper
  516 #define rfcomm_bind             rfcomm_bind_wrapper
  517 #define rfcomm_listen           rfcomm_listen_wrapper
  518 #define rfcomm_connect          rfcomm_connect_wrapper
  519 #define rfcomm_connect2         rfcomm_connect2_wrapper
  520 #define rfcomm_disconnect       rfcomm_disconnect_wrapper
  521 #define rfcomm_shutdown         rfcomm_shutdown_wrapper
  522 #define rfcomm_abort            rfcomm_abort_wrapper
  523 #define rfcomm_ioctl            rfcomm_ioctl_wrapper
  524 #define rfcomm_stat             rfcomm_stat_wrapper
  525 #define rfcomm_peeraddr         rfcomm_peeraddr_wrapper
  526 #define rfcomm_sockaddr         rfcomm_sockaddr_wrapper
  527 #define rfcomm_rcvd             rfcomm_rcvd_wrapper
  528 #define rfcomm_recvoob          rfcomm_recvoob_wrapper
  529 #define rfcomm_send             rfcomm_send_wrapper
  530 #define rfcomm_sendoob          rfcomm_sendoob_wrapper
  531 #define rfcomm_purgeif          rfcomm_purgeif_wrapper
  532 
  533 const struct pr_usrreqs rfcomm_usrreqs = {
  534         .pr_attach      = rfcomm_attach,
  535         .pr_detach      = rfcomm_detach,
  536         .pr_accept      = rfcomm_accept,
  537         .pr_bind        = rfcomm_bind,
  538         .pr_listen      = rfcomm_listen,
  539         .pr_connect     = rfcomm_connect,
  540         .pr_connect2    = rfcomm_connect2,
  541         .pr_disconnect  = rfcomm_disconnect,
  542         .pr_shutdown    = rfcomm_shutdown,
  543         .pr_abort       = rfcomm_abort,
  544         .pr_ioctl       = rfcomm_ioctl,
  545         .pr_stat        = rfcomm_stat,
  546         .pr_peeraddr    = rfcomm_peeraddr,
  547         .pr_sockaddr    = rfcomm_sockaddr,
  548         .pr_rcvd        = rfcomm_rcvd,
  549         .pr_recvoob     = rfcomm_recvoob,
  550         .pr_send        = rfcomm_send,
  551         .pr_sendoob     = rfcomm_sendoob,
  552         .pr_purgeif     = rfcomm_purgeif,
  553 };

Cache object: 2d4c34270bfffa2815176f027e35e42e


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