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

Cache object: 3f44542115bec8c9baf7c751c04f412f


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