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/netiso/tp_usrreq.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: tp_usrreq.c,v 1.23 2003/08/11 15:17:31 itojun Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 1991, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)tp_usrreq.c 8.1 (Berkeley) 6/10/93
   32  */
   33 
   34 /***********************************************************
   35                                 Copyright IBM Corporation 1987
   36 
   37                       All Rights Reserved
   38 
   39 Permission to use, copy, modify, and distribute this software and its
   40 documentation for any purpose and without fee is hereby granted,
   41 provided that the above copyright notice appear in all copies and that
   42 both that copyright notice and this permission notice appear in
   43 supporting documentation, and that the name of IBM not be
   44 used in advertising or publicity pertaining to distribution of the
   45 software without specific, written prior permission.
   46 
   47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
   49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   53 SOFTWARE.
   54 
   55 ******************************************************************/
   56 
   57 /*
   58  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
   59  */
   60 /*
   61  * tp_usrreq(), the fellow that gets called from most of the socket code.
   62  * Pretty straighforward. THe only really awful stuff here is the OOB
   63  * processing, which is done wholly here. tp_rcvoob() and tp_sendoob() are
   64  * contained here and called by tp_usrreq().
   65  */
   66 
   67 #include <sys/cdefs.h>
   68 __KERNEL_RCSID(0, "$NetBSD: tp_usrreq.c,v 1.23 2003/08/11 15:17:31 itojun Exp $");
   69 
   70 #include <sys/param.h>
   71 #include <sys/systm.h>
   72 #include <sys/mbuf.h>
   73 #include <sys/socket.h>
   74 #include <sys/socketvar.h>
   75 #include <sys/domain.h>
   76 #include <sys/protosw.h>
   77 #include <sys/errno.h>
   78 #include <sys/time.h>
   79 #include <sys/proc.h>
   80 
   81 #include <netiso/tp_param.h>
   82 #include <netiso/tp_timer.h>
   83 #include <netiso/tp_stat.h>
   84 #include <netiso/tp_seq.h>
   85 #include <netiso/tp_ip.h>
   86 #include <netiso/tp_pcb.h>
   87 #include <netiso/tp_var.h>
   88 #include <netiso/argo_debug.h>
   89 #include <netiso/tp_trace.h>
   90 #include <netiso/tp_meas.h>
   91 #include <netiso/iso.h>
   92 #include <netiso/iso_errno.h>
   93 
   94 int             TNew;
   95 int             TPNagle1, TPNagle2;
   96 struct tp_pcb  *tp_listeners, *tp_intercepts;
   97 
   98 #ifdef ARGO_DEBUG
   99 /*
  100  * CALLED FROM:
  101  *  anywhere you want to debug...
  102  * FUNCTION and ARGUMENTS:
  103  *  print (str) followed by the control info in the mbufs of an mbuf chain (n)
  104  */
  105 void
  106 dump_mbuf(n, str)
  107         struct mbuf    *n;
  108         char           *str;
  109 {
  110         struct mbuf    *nextrecord;
  111 
  112         printf("dump %s\n", str);
  113 
  114         if (n == NULL) {
  115                 printf("EMPTY:\n");
  116                 return;
  117         }
  118         while (n) {
  119                 nextrecord = n->m_nextpkt;
  120                 printf("RECORD:\n");
  121                 while (n) {
  122                         printf("%p : Len %x Data %p A %p Nx %p Tp %x\n",
  123                                n, n->m_len, n->m_data, n->m_nextpkt, n->m_next, n->m_type);
  124 #ifdef notdef
  125                         {
  126                                 char  *p = mtod(n, char *);
  127                                 int    i;
  128 
  129                                 printf("data: ");
  130                                 for (i = 0; i < n->m_len; i++) {
  131                                         if (i % 8 == 0)
  132                                                 printf("\n");
  133                                         printf("0x%x ", *(p + i));
  134                                 }
  135                                 printf("\n");
  136                         }
  137 #endif                          /* notdef */
  138                         if (n->m_next == n) {
  139                                 printf("LOOP!\n");
  140                                 return;
  141                         }
  142                         n = n->m_next;
  143                 }
  144                 n = nextrecord;
  145         }
  146         printf("\n");
  147 }
  148 
  149 #endif                          /* ARGO_DEBUG */
  150 
  151 /*
  152  * CALLED FROM:
  153  *  tp_usrreq(), PRU_RCVOOB
  154  * FUNCTION and ARGUMENTS:
  155  *      Copy data from the expedited data socket buffer into
  156  *      the pre-allocated mbuf m.
  157  *      There is an isomorphism between XPD TPDUs and expedited data TSDUs.
  158  *      XPD tpdus are limited to 16 bytes of data so they fit in one mbuf.
  159  * RETURN VALUE:
  160  *  EINVAL if debugging is on and a disaster has occurred
  161  *  ENOTCONN if the socket isn't connected
  162  *  EWOULDBLOCK if the socket is in non-blocking mode and there's no
  163  *              xpd data in the buffer
  164  *  E* whatever is returned from the fsm.
  165  */
  166 int
  167 tp_rcvoob(tpcb, so, m, outflags, inflags)
  168         struct tp_pcb  *tpcb;
  169         struct socket *so;
  170         struct mbuf *m;
  171         int            *outflags;
  172         int             inflags;
  173 {
  174         struct mbuf *n;
  175         struct sockbuf *sb = &so->so_rcv;
  176         struct tp_event E;
  177         int             error = 0;
  178         struct mbuf **nn;
  179 
  180 #ifdef ARGO_DEBUG
  181         if (argo_debug[D_XPD]) {
  182                 printf("PRU_RCVOOB, sostate 0x%x\n", so->so_state);
  183         }
  184 #endif
  185 
  186         /* if you use soreceive */
  187         if (m == NULL)
  188                 return ENOBUFS;
  189 
  190 restart:
  191         if ((((so->so_state & SS_ISCONNECTED) == 0)
  192              || (so->so_state & SS_ISDISCONNECTING) != 0) &&
  193             (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
  194                 return ENOTCONN;
  195         }
  196         /*
  197          * Take the first mbuf off the chain. Each XPD TPDU gives you a
  198          * complete TSDU so the chains don't get coalesced, but one TSDU may
  199          * span several mbufs. Nevertheless, since n should have a most 16
  200          * bytes, it will fit into m.  (size was checked in tp_input() )
  201          */
  202 
  203         /*
  204          * Code for excision of OOB data should be added to
  205          * uipc_socket2.c (like sbappend).
  206          */
  207 
  208         sblock(sb, M_WAITOK);
  209         for (nn = &sb->sb_mb; (n = *nn) != NULL; nn = &n->m_nextpkt)
  210                 if (n->m_type == MT_OOBDATA)
  211                         break;
  212 
  213         if (n == 0) {
  214 #ifdef ARGO_DEBUG
  215                 if (argo_debug[D_XPD]) {
  216                         printf("RCVOOB: empty queue!\n");
  217                 }
  218 #endif
  219                 sbunlock(sb);
  220                 if (so->so_state & SS_NBIO) {
  221                         return EWOULDBLOCK;
  222                 }
  223                 sbwait(sb);
  224                 goto restart;
  225         }
  226         m->m_len = 0;
  227 
  228         /* Assuming at most one xpd tpdu is in the buffer at once */
  229         while (n != NULL) {
  230                 m->m_len += n->m_len;
  231                 bcopy(mtod(n, caddr_t), mtod(m, caddr_t), (unsigned) n->m_len);
  232                 m->m_data += n->m_len;  /* so mtod() in bcopy() above gives
  233                                          * right addr */
  234                 n = n->m_next;
  235         }
  236         m->m_data = m->m_dat;
  237         m->m_flags |= M_EOR;
  238 
  239 #ifdef ARGO_DEBUG
  240         if (argo_debug[D_XPD]) {
  241                 printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len);
  242                 dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf");
  243                 dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf");
  244         }
  245 #endif
  246 
  247         if ((inflags & MSG_PEEK) == 0) {
  248                 n = *nn;
  249                 *nn = n->m_nextpkt;
  250                 for (; n; n = m_free(n))
  251                         sbfree(sb, n);
  252         }
  253         sbunlock(sb);
  254 
  255 #ifdef TPPT
  256         if (tp_traceflags[D_XPD]) {
  257                 tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len",
  258                             tpcb->tp_Xrcv.sb_cc, m->m_len, 0, 0);
  259         }
  260 #endif
  261         if (error == 0)
  262                 error = DoEvent(T_USR_Xrcvd);
  263         return error;
  264 }
  265 
  266 /*
  267  * CALLED FROM:
  268  *  tp_usrreq(), PRU_SENDOOB
  269  * FUNCTION and ARGUMENTS:
  270  *      Send what's in the mbuf chain (m) as an XPD TPDU.
  271  *      The mbuf may not contain more than 16 bytes of data.
  272  *      XPD TSDUs aren't segmented, so they translate into
  273  *      exactly one XPD TPDU, with EOT bit set.
  274  * RETURN VALUE:
  275  *  EWOULDBLOCK if socket is in non-blocking mode and the previous
  276  *   xpd data haven't been acked yet.
  277  *  EMSGSIZE if trying to send > max-xpd bytes (16)
  278  *  ENOBUFS if ran out of mbufs
  279  */
  280 int
  281 tp_sendoob(tpcb, so, xdata, outflags)
  282         struct tp_pcb  *tpcb;
  283         struct socket *so;
  284         struct mbuf *xdata;
  285         int            *outflags;       /* not used */
  286 {
  287         /*
  288          * Each mbuf chain represents a sequence # in the XPD seq space.
  289          * The first one in the queue has sequence # tp_Xuna.
  290          * When we add to the XPD queue, we stuff a zero-length
  291          * mbuf (mark) into the DATA queue, with its sequence number in m_next
  292          * to be assigned to this XPD tpdu, so data xfer can stop
  293          * when it reaches the zero-length mbuf if this XPD TPDU hasn't
  294          * yet been acknowledged.
  295          */
  296         struct sockbuf *sb = &(tpcb->tp_Xsnd);
  297         struct mbuf *xmark;
  298         int    len = 0;
  299         struct tp_event E;
  300 
  301 #ifdef ARGO_DEBUG
  302         if (argo_debug[D_XPD]) {
  303                 printf("tp_sendoob:");
  304                 if (xdata)
  305                         printf("xdata len 0x%x\n", xdata->m_len);
  306         }
  307 #endif
  308         /*
  309          * DO NOT LOCK the Xsnd buffer!!!! You can have at MOST one socket
  310          * buf locked at any time!!! (otherwise you might sleep() in sblock()
  311          * w/ a signal pending and cause the system call to be aborted w/ a
  312          * locked socketbuf, which is a problem.  So the so_snd buffer lock
  313          * (done in sosend()) serves as the lock for Xpd.
  314          */
  315         if (sb->sb_mb) {        /* Anything already in eXpedited data
  316                                  * sockbuf? */
  317                 if (so->so_state & SS_NBIO) {
  318                         return EWOULDBLOCK;
  319                 }
  320                 while (sb->sb_mb) {
  321                         sbunlock(&so->so_snd);  /* already locked by sosend */
  322                         sbwait(&so->so_snd);
  323                         sblock(&so->so_snd, M_WAITOK);  /* sosend will unlock on
  324                                                          * return */
  325                 }
  326         }
  327         if (xdata == (struct mbuf *) 0) {
  328                 /* empty xpd packet */
  329                 xdata = m_gethdr(M_WAIT, MT_OOBDATA);
  330                 xdata->m_len = 0;
  331                 xdata->m_pkthdr.len = 0;
  332         }
  333 #ifdef ARGO_DEBUG
  334         if (argo_debug[D_XPD]) {
  335                 printf("tp_sendoob 1:");
  336                 if (xdata)
  337                         printf("xdata len 0x%x\n", xdata->m_len);
  338         }
  339 #endif
  340         xmark = xdata;          /* temporary use of variable xmark */
  341         while (xmark) {
  342                 len += xmark->m_len;
  343                 xmark = xmark->m_next;
  344         }
  345         if (len > TP_MAX_XPD_DATA) {
  346                 return EMSGSIZE;
  347         }
  348 #ifdef ARGO_DEBUG
  349         if (argo_debug[D_XPD]) {
  350                 printf("tp_sendoob 2:");
  351                 if (xdata)
  352                         printf("xdata len 0x%x\n", len);
  353         }
  354 #endif
  355 
  356 
  357 #ifdef TPPT
  358         if (tp_traceflags[D_XPD]) {
  359                 tptraceTPCB(TPPTmisc, "XPD mark m_next ", xdata->m_next, 0, 0, 0);
  360         }
  361 #endif
  362 
  363         sbappendrecord(sb, xdata);
  364 
  365 #ifdef ARGO_DEBUG
  366         if (argo_debug[D_XPD]) {
  367                 printf("tp_sendoob len 0x%x\n", len);
  368                 dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:");
  369                 dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:");
  370         }
  371 #endif
  372         return DoEvent(T_XPD_req);
  373 }
  374 
  375 /*
  376  * CALLED FROM:
  377  *  the socket routines
  378  * FUNCTION and ARGUMENTS:
  379  *      Handles all "user requests" except the [gs]ockopts() requests.
  380  *      The argument (req) is the request type (PRU*),
  381  *      (m) is an mbuf chain, generally used for send and
  382  *      receive type requests only.
  383  *      (nam) is used for addresses usually, in particular for the bind request.
  384  *
  385  */
  386 /* ARGSUSED */
  387 int
  388 tp_usrreq(so, req, m, nam, control, p)
  389         struct socket *so;
  390         int req;
  391         struct mbuf *m, *nam, *control;
  392         struct proc *p;
  393 {
  394         struct tp_pcb *tpcb;
  395         int             s;
  396         int             error = 0;
  397         int             flags, *outflags = &flags;
  398         u_long          eotsdu = 0;
  399         struct tp_event E;
  400 
  401 #ifdef ARGO_DEBUG
  402         if (argo_debug[D_REQUEST]) {
  403                 printf("usrreq(%p,%d,%p,%p,%p)\n", so, req, m, nam, outflags);
  404                 if (so->so_error)
  405                         printf("WARNING!!! so->so_error is 0x%x\n", so->so_error);
  406         }
  407 #endif
  408 #ifdef TPPT
  409         if (tp_traceflags[D_REQUEST]) {
  410                 tptraceTPCB(TPPTusrreq, "req so m state [", req, so, m,
  411                             tpcb ? tpcb->tp_state : 0);
  412         }
  413 #endif
  414 
  415         if (req == PRU_CONTROL)
  416                 return (EOPNOTSUPP);
  417 
  418         s = splsoftnet();
  419         tpcb = sototpcb(so);
  420         if (tpcb == 0 && req != PRU_ATTACH) {
  421 #ifdef TPPT
  422                 if (tp_traceflags[D_REQUEST]) {
  423                         tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0);
  424                 }
  425 #endif
  426                 error = EINVAL;
  427                 goto release;
  428         }
  429 
  430         switch (req) {
  431 
  432         case PRU_ATTACH:
  433                 if (tpcb != 0) {
  434                         error = EISCONN;
  435                         break;
  436                 }
  437                 error = tp_attach(so, (long)nam);
  438                 if (error)
  439                         break;
  440                 tpcb = sototpcb(so);
  441                 break;
  442 
  443         case PRU_DETACH:        /* called from close() */
  444                 /* called only after disconnect was called */
  445                 error = DoEvent(T_DETACH);
  446                 if (tpcb->tp_state == TP_CLOSED) {
  447                         if (tpcb->tp_notdetached) {
  448 #ifdef ARGO_DEBUG
  449                                 if (argo_debug[D_CONN]) {
  450                                         printf("PRU_DETACH: not detached\n");
  451                                 }
  452 #endif
  453                                 tp_detach(tpcb);
  454                         }
  455                         free((caddr_t) tpcb, M_PCB);
  456                         tpcb = 0;
  457                 }
  458                 break;
  459 
  460         case PRU_BIND:
  461                 error = tp_pcbbind(tpcb, nam, p);
  462                 break;
  463 
  464         case PRU_LISTEN:
  465                 if (tpcb->tp_state != TP_CLOSED || tpcb->tp_lsuffixlen == 0 ||
  466                     tpcb->tp_next == 0)
  467                         error = EINVAL;
  468                 else {
  469                         struct tp_pcb **tt;
  470                         remque(tpcb);
  471                         tpcb->tp_next = tpcb->tp_prev = tpcb;
  472                         for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten))
  473                                 if ((*tt)->tp_lsuffixlen)
  474                                         break;
  475                         tpcb->tp_nextlisten = *tt;
  476                         *tt = tpcb;
  477                         error = DoEvent(T_LISTEN_req);
  478                 }
  479                 break;
  480 
  481         case PRU_CONNECT:
  482 #ifdef TPPT
  483                 if (tp_traceflags[D_CONN]) {
  484                         tptraceTPCB(TPPTmisc,
  485                                     "PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x",
  486                     tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen,
  487                                     tpcb->tp_class);
  488                 }
  489 #endif
  490 #ifdef ARGO_DEBUG
  491                 if (argo_debug[D_CONN]) {
  492                         printf("PRU_CONNECT: so %p *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x",
  493                                tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen,
  494                                tpcb->tp_class);
  495                 }
  496 #endif
  497                 if (tpcb->tp_lsuffixlen == 0) {
  498                         error = tp_pcbbind(tpcb, (struct mbuf *)0,
  499                             (struct proc *)0);
  500                         if (error) {
  501 #ifdef ARGO_DEBUG
  502                                 if (argo_debug[D_CONN]) {
  503                                         printf("pcbbind returns error 0x%x\n", error);
  504                                 }
  505 #endif
  506                                 break;
  507                         }
  508                 }
  509 #ifdef ARGO_DEBUG
  510                 if (argo_debug[D_CONN]) {
  511                         printf("isop %p isop->isop_socket offset 12 :\n", tpcb->tp_npcb);
  512                         dump_buf(tpcb->tp_npcb, 16);
  513                 }
  514 #endif
  515                 if ((error = tp_route_to(nam, tpcb, /* channel */ 0)) != 0)
  516                         break;
  517 #ifdef ARGO_DEBUG
  518                 if (argo_debug[D_CONN]) {
  519                         printf(
  520                                "PRU_CONNECT after tpcb %p so %p npcb %p flags 0x%x\n",
  521                                tpcb, so, tpcb->tp_npcb, tpcb->tp_flags);
  522                         printf("isop %p isop->isop_socket offset 12 :\n", tpcb->tp_npcb);
  523                         dump_buf(tpcb->tp_npcb, 16);
  524                 }
  525 #endif
  526                 if (tpcb->tp_fsuffixlen == 0) {
  527                         /* didn't set peer extended suffix */
  528                         (tpcb->tp_nlproto->nlp_getsufx) (tpcb->tp_npcb,
  529                                               &tpcb->tp_fsuffixlen,
  530                                               tpcb->tp_fsuffix, TP_FOREIGN);
  531                 }
  532                 if (tpcb->tp_state == TP_CLOSED) {
  533                         soisconnecting(so);
  534                         error = DoEvent(T_CONN_req);
  535                 } else {
  536                         (tpcb->tp_nlproto->nlp_pcbdisc) (tpcb->tp_npcb);
  537                         error = EISCONN;
  538                 }
  539 #ifdef TP_PERF_MEAS
  540                 if (DOPERF(tpcb)) {
  541                         u_int           lsufx, fsufx;
  542                         lsufx = *(u_short *) (tpcb->tp_lsuffix);
  543                         fsufx = *(u_short *) (tpcb->tp_fsuffix);
  544 
  545                         tpmeas(tpcb->tp_lref,
  546                                TPtime_open | (tpcb->tp_xtd_format << 4),
  547                                &time, lsufx, fsufx, tpcb->tp_fref);
  548                 }
  549 #endif
  550                 break;
  551 
  552         case PRU_CONNECT2:
  553                 error = EOPNOTSUPP;     /* for unix domain sockets */
  554                 break;
  555 
  556         case PRU_DISCONNECT:
  557                 E.TPDU_ATTR(REQ).e_reason = E_TP_NORMAL_DISC ^ TP_ERROR_MASK;
  558                 error = DoEvent(T_DISC_req);
  559                 break;
  560 
  561         case PRU_ACCEPT:
  562                 (tpcb->tp_nlproto->nlp_getnetaddr) (tpcb->tp_npcb, nam, TP_FOREIGN);
  563 #ifdef ARGO_DEBUG
  564                 if (argo_debug[D_REQUEST]) {
  565                         printf("ACCEPT PEERADDDR:");
  566                         dump_buf(mtod(nam, char *), nam->m_len);
  567                 }
  568 #endif
  569 #ifdef TP_PERF_MEAS
  570                 if (DOPERF(tpcb)) {
  571                         u_int           lsufx, fsufx;
  572                         lsufx = *(u_short *) (tpcb->tp_lsuffix);
  573                         fsufx = *(u_short *) (tpcb->tp_fsuffix);
  574 
  575                         tpmeas(tpcb->tp_lref, TPtime_open,
  576                                &time, lsufx, fsufx, tpcb->tp_fref);
  577                 }
  578 #endif
  579                 break;
  580 
  581         case PRU_SHUTDOWN:
  582                 /*
  583                  * recv end may have been released; local credit might be
  584                  * zero
  585                  */
  586                 E.TPDU_ATTR(REQ).e_reason = E_TP_NORMAL_DISC ^ TP_ERROR_MASK;
  587                 error = DoEvent(T_DISC_req);
  588                 break;
  589 
  590         case PRU_RCVD:
  591                 if (so->so_state & SS_ISCONFIRMING) {
  592                         if (tpcb->tp_state == TP_CONFIRMING)
  593                                 error = tp_confirm(tpcb);
  594                         break;
  595                 }
  596 #ifdef TPPT
  597                 if (tp_traceflags[D_DATA]) {
  598                         tptraceTPCB(TPPTmisc,
  599                                     "RCVD BF: lcredit sent_lcdt cc hiwat \n",
  600                                     tpcb->tp_lcredit, tpcb->tp_sent_lcdt,
  601                                     so->so_rcv.sb_cc, so->so_rcv.sb_hiwat);
  602                         LOCAL_CREDIT(tpcb);
  603                         tptraceTPCB(TPPTmisc,
  604                                     "PRU_RCVD AF sbspace lcredit hiwat cc",
  605                                     sbspace(&so->so_rcv), tpcb->tp_lcredit,
  606                                     so->so_rcv.sb_cc, so->so_rcv.sb_hiwat);
  607                 }
  608 #endif
  609 #ifdef ARGO_DEBUG
  610                 if (argo_debug[D_REQUEST]) {
  611                         printf("RCVD: cc %ld space %ld hiwat %ld\n",
  612                                so->so_rcv.sb_cc, sbspace(&so->so_rcv),
  613                                so->so_rcv.sb_hiwat);
  614                 }
  615 #endif
  616                 if (((long) nam) & MSG_OOB)
  617                         error = DoEvent(T_USR_Xrcvd);
  618                 else
  619                         error = DoEvent(T_USR_rcvd);
  620                 break;
  621 
  622         case PRU_RCVOOB:
  623                 if ((so->so_state & SS_ISCONNECTED) == 0) {
  624                         error = ENOTCONN;
  625                         break;
  626                 }
  627                 if (!tpcb->tp_xpd_service) {
  628                         error = EOPNOTSUPP;
  629                         break;
  630                 }
  631                 /* kludge - nam is really flags here */
  632                 error = tp_rcvoob(tpcb, so, m, outflags, (long) nam);
  633                 break;
  634 
  635         case PRU_SEND:
  636         case PRU_SENDOOB:
  637                 if (control) {
  638                         error = tp_snd_control(control, so, &m);
  639                         control = NULL;
  640                         if (error)
  641                                 break;
  642                 }
  643                 if ((so->so_state & SS_ISCONFIRMING) &&
  644                     (tpcb->tp_state == TP_CONFIRMING) &&
  645                     (error = tp_confirm(tpcb)))
  646                         break;
  647                 if (req == PRU_SENDOOB) {
  648                         error = (tpcb->tp_xpd_service == 0) ?
  649                                 EOPNOTSUPP : tp_sendoob(tpcb, so, m, outflags);
  650                         break;
  651                 }
  652                 if (m == 0)
  653                         break;
  654                 if (m->m_flags & M_EOR) {
  655                         eotsdu = 1;
  656                         m->m_flags &= ~M_EOR;
  657                 }
  658                 if (eotsdu == 0 && m->m_pkthdr.len == 0)
  659                         break;
  660                 if (tpcb->tp_state != TP_AKWAIT && tpcb->tp_state != TP_OPEN) {
  661                         error = ENOTCONN;
  662                         break;
  663                 }
  664                 /*
  665                  * The protocol machine copies mbuf chains,
  666                  * prepends headers, assigns seq numbers, and
  667                  * puts the packets on the device.
  668                  * When they are acked they are removed from the socket buf.
  669                  *
  670                  * sosend calls this up until sbspace goes negative.
  671                  * Sbspace may be made negative by appending this mbuf chain,
  672                  * possibly by a whole cluster.
  673                  */
  674                 {
  675                         /*
  676                          * Could have eotsdu and no data.(presently MUST have
  677                          * an mbuf though, even if its length == 0)
  678                          */
  679                         int             totlen = m->m_pkthdr.len;
  680                         struct sockbuf *sb = &so->so_snd;
  681 #ifdef TP_PERF_MEAS
  682                         if (DOPERF(tpcb)) {
  683                                 PStat(tpcb, Nb_from_sess) += totlen;
  684                                 tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0,
  685                                        PStat(tpcb, Nb_from_sess), totlen);
  686                         }
  687 #endif
  688 #ifdef ARGO_DEBUG
  689                         if (argo_debug[D_SYSCALL]) {
  690                                 printf(
  691                                        "PRU_SEND: eot %ld before sbappend %p len 0x%x to sb @ %p\n",
  692                                        eotsdu, m, totlen, sb);
  693                                 dump_mbuf(sb->sb_mb, "so_snd.sb_mb");
  694                                 dump_mbuf(m, "m : to be added");
  695                         }
  696 #endif
  697                         tp_packetize(tpcb, m, eotsdu);
  698 #ifdef ARGO_DEBUG
  699                         if (argo_debug[D_SYSCALL]) {
  700                                 printf("PRU_SEND: eot %ld after sbappend %p\n", eotsdu, m);
  701                                 dump_mbuf(sb->sb_mb, "so_snd.sb_mb");
  702                         }
  703 #endif
  704                         if (tpcb->tp_state == TP_OPEN)
  705                                 error = DoEvent(T_DATA_req);
  706 #ifdef ARGO_DEBUG
  707                         if (argo_debug[D_SYSCALL]) {
  708                                 printf("PRU_SEND: after driver error 0x%x \n", error);
  709                                 printf("so_snd %p cc 0t%ld mbcnt 0t%ld\n",
  710                                        sb, sb->sb_cc, sb->sb_mbcnt);
  711                                 dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver");
  712                         }
  713 #endif
  714                 }
  715                 break;
  716 
  717         case PRU_ABORT: /* called from close() */
  718                 /*
  719                  * called for each incoming connect queued on the parent
  720                  * (accepting) socket
  721                  */
  722                 if (tpcb->tp_state == TP_OPEN || tpcb->tp_state == TP_CONFIRMING) {
  723                         E.TPDU_ATTR(REQ).e_reason = E_TP_NO_SESSION ^ TP_ERROR_MASK;
  724                         error = DoEvent(T_DISC_req);    /* pretend it was a
  725                                                          * close() */
  726                 }
  727                 break;
  728 
  729         case PRU_SENSE:
  730                 /*
  731                  * stat: don't bother with a blocksize.
  732                  */
  733                 splx(s);
  734                 return (0);
  735 
  736         case PRU_SOCKADDR:
  737                 (tpcb->tp_nlproto->nlp_getnetaddr) (tpcb->tp_npcb, nam, TP_LOCAL);
  738                 break;
  739 
  740         case PRU_PEERADDR:
  741                 (tpcb->tp_nlproto->nlp_getnetaddr) (tpcb->tp_npcb, nam, TP_FOREIGN);
  742                 break;
  743 
  744         default:
  745 #ifdef ARGO_DEBUG
  746                 printf("tp_usrreq UNKNOWN PRU %d\n", req);
  747 #endif                          /* ARGO_DEBUG */
  748                 error = EOPNOTSUPP;
  749         }
  750 
  751 #ifdef ARGO_DEBUG
  752         if (argo_debug[D_REQUEST]) {
  753                 printf("%s, so %p, tpcb %p, error %d, state %d\n",
  754                        "returning from tp_usrreq", so, tpcb, error,
  755                        tpcb ? tpcb->tp_state : 0);
  756         }
  757 #endif
  758 #ifdef TPPT
  759         if (tp_traceflags[D_REQUEST]) {
  760                 tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m,
  761                             tpcb ? tpcb->tp_state : 0);
  762         }
  763 #endif
  764 release:
  765         splx(s);
  766         return error;
  767 }
  768 
  769 void
  770 tp_ltrace(so, uio)
  771         struct socket  *so;
  772         struct uio     *uio;
  773 {
  774 #ifdef TPPT
  775         if (tp_traceflags[D_DATA]) {
  776                 struct tp_pcb *tpcb = sototpcb(so);
  777                 if (tpcb) {
  778                         tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so,
  779                                     uio->uio_resid, uio->uio_iovcnt, 0);
  780                 }
  781         }
  782 #endif
  783 }
  784 
  785 int
  786 tp_confirm(tpcb)
  787         struct tp_pcb *tpcb;
  788 {
  789         struct tp_event E;
  790         if (tpcb->tp_state == TP_CONFIRMING)
  791                 return DoEvent(T_ACPT_req);
  792         printf("Tp confirm called when not confirming; tpcb %p, state 0x%x\n",
  793                tpcb, tpcb->tp_state);
  794         return 0;
  795 }
  796 
  797 /*
  798  * Process control data sent with sendmsg()
  799  */
  800 int
  801 tp_snd_control(m, so, data)
  802         struct mbuf    *m;
  803         struct socket  *so;
  804         struct mbuf **data;
  805 {
  806         struct cmsghdr *ch;
  807         int             error = 0;
  808 
  809         if (m && m->m_len) {
  810                 ch = mtod(m, struct cmsghdr *);
  811                 m->m_len -= sizeof(*ch);
  812                 m->m_data += sizeof(*ch);
  813                 error = tp_ctloutput(PRCO_SETOPT,
  814                                      so, ch->cmsg_level, ch->cmsg_type, &m);
  815                 if (ch->cmsg_type == TPOPT_DISC_DATA) {
  816                         if (data && *data) {
  817                                 m_freem(*data);
  818                                 *data = 0;
  819                         }
  820                         error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0,
  821                             (struct mbuf *)0, (struct mbuf *)0,
  822                             (struct proc *)0);
  823                 }
  824         }
  825         if (m)
  826                 m_freem(m);
  827         return error;
  828 }

Cache object: d9769d706d53345ad35dc05d43a0e3c4


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