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.31 2006/11/16 01:33:51 christos 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.31 2006/11/16 01:33:51 christos 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, const 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 lwp *l)
  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, l);
  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 lwp *)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                         struct timeval  now;
  531 
  532                         lsufx = *(u_short *) (tpcb->tp_lsuffix);
  533                         fsufx = *(u_short *) (tpcb->tp_fsuffix);
  534 
  535                         getmicrotime(&now);
  536                         tpmeas(tpcb->tp_lref,
  537                                TPtime_open | (tpcb->tp_xtd_format << 4),
  538                                &now, lsufx, fsufx, tpcb->tp_fref);
  539                 }
  540 #endif
  541                 break;
  542 
  543         case PRU_CONNECT2:
  544                 error = EOPNOTSUPP;     /* for unix domain sockets */
  545                 break;
  546 
  547         case PRU_DISCONNECT:
  548                 E.TPDU_ATTR(REQ).e_reason = E_TP_NORMAL_DISC ^ TP_ERROR_MASK;
  549                 error = DoEvent(T_DISC_req);
  550                 break;
  551 
  552         case PRU_ACCEPT:
  553                 (tpcb->tp_nlproto->nlp_getnetaddr) (tpcb->tp_npcb, nam, TP_FOREIGN);
  554 #ifdef ARGO_DEBUG
  555                 if (argo_debug[D_REQUEST]) {
  556                         printf("ACCEPT PEERADDDR:");
  557                         dump_buf(mtod(nam, char *), nam->m_len);
  558                 }
  559 #endif
  560 #ifdef TP_PERF_MEAS
  561                 if (DOPERF(tpcb)) {
  562                         u_int           lsufx, fsufx;
  563                         struct timeval  now;
  564 
  565                         lsufx = *(u_short *) (tpcb->tp_lsuffix);
  566                         fsufx = *(u_short *) (tpcb->tp_fsuffix);
  567 
  568                         getmicrotime(&now);
  569                         tpmeas(tpcb->tp_lref, TPtime_open,
  570                                &time, lsufx, fsufx, tpcb->tp_fref);
  571                 }
  572 #endif
  573                 break;
  574 
  575         case PRU_SHUTDOWN:
  576                 /*
  577                  * recv end may have been released; local credit might be
  578                  * zero
  579                  */
  580                 E.TPDU_ATTR(REQ).e_reason = E_TP_NORMAL_DISC ^ TP_ERROR_MASK;
  581                 error = DoEvent(T_DISC_req);
  582                 break;
  583 
  584         case PRU_RCVD:
  585                 if (so->so_state & SS_ISCONFIRMING) {
  586                         if (tpcb->tp_state == TP_CONFIRMING)
  587                                 error = tp_confirm(tpcb);
  588                         break;
  589                 }
  590 #ifdef TPPT
  591                 if (tp_traceflags[D_DATA]) {
  592                         tptraceTPCB(TPPTmisc,
  593                                     "RCVD BF: lcredit sent_lcdt cc hiwat \n",
  594                                     tpcb->tp_lcredit, tpcb->tp_sent_lcdt,
  595                                     so->so_rcv.sb_cc, so->so_rcv.sb_hiwat);
  596                         LOCAL_CREDIT(tpcb);
  597                         tptraceTPCB(TPPTmisc,
  598                                     "PRU_RCVD AF sbspace lcredit hiwat cc",
  599                                     sbspace(&so->so_rcv), tpcb->tp_lcredit,
  600                                     so->so_rcv.sb_cc, so->so_rcv.sb_hiwat);
  601                 }
  602 #endif
  603 #ifdef ARGO_DEBUG
  604                 if (argo_debug[D_REQUEST]) {
  605                         printf("RCVD: cc %ld space %ld hiwat %ld\n",
  606                                so->so_rcv.sb_cc, sbspace(&so->so_rcv),
  607                                so->so_rcv.sb_hiwat);
  608                 }
  609 #endif
  610                 if (((long) nam) & MSG_OOB)
  611                         error = DoEvent(T_USR_Xrcvd);
  612                 else
  613                         error = DoEvent(T_USR_rcvd);
  614                 break;
  615 
  616         case PRU_RCVOOB:
  617                 if ((so->so_state & SS_ISCONNECTED) == 0) {
  618                         error = ENOTCONN;
  619                         break;
  620                 }
  621                 if (!tpcb->tp_xpd_service) {
  622                         error = EOPNOTSUPP;
  623                         break;
  624                 }
  625                 /* kludge - nam is really flags here */
  626                 error = tp_rcvoob(tpcb, so, m, outflags, (long) nam);
  627                 break;
  628 
  629         case PRU_SEND:
  630         case PRU_SENDOOB:
  631                 if (control) {
  632                         error = tp_snd_control(control, so, &m);
  633                         control = NULL;
  634                         if (error)
  635                                 break;
  636                 }
  637                 if ((so->so_state & SS_ISCONFIRMING) &&
  638                     (tpcb->tp_state == TP_CONFIRMING) &&
  639                     (error = tp_confirm(tpcb)))
  640                         break;
  641                 if (req == PRU_SENDOOB) {
  642                         error = (tpcb->tp_xpd_service == 0) ?
  643                                 EOPNOTSUPP : tp_sendoob(tpcb, so, m, outflags);
  644                         break;
  645                 }
  646                 if (m == 0)
  647                         break;
  648                 if (m->m_flags & M_EOR) {
  649                         eotsdu = 1;
  650                         m->m_flags &= ~M_EOR;
  651                 }
  652                 if (eotsdu == 0 && m->m_pkthdr.len == 0)
  653                         break;
  654                 if (tpcb->tp_state != TP_AKWAIT && tpcb->tp_state != TP_OPEN) {
  655                         error = ENOTCONN;
  656                         break;
  657                 }
  658                 /*
  659                  * The protocol machine copies mbuf chains,
  660                  * prepends headers, assigns seq numbers, and
  661                  * puts the packets on the device.
  662                  * When they are acked they are removed from the socket buf.
  663                  *
  664                  * sosend calls this up until sbspace goes negative.
  665                  * Sbspace may be made negative by appending this mbuf chain,
  666                  * possibly by a whole cluster.
  667                  */
  668                 {
  669                         /*
  670                          * Could have eotsdu and no data.(presently MUST have
  671                          * an mbuf though, even if its length == 0)
  672                          */
  673                         int             totlen = m->m_pkthdr.len;
  674                         struct sockbuf *sb = &so->so_snd;
  675 #ifdef TP_PERF_MEAS
  676                         if (DOPERF(tpcb)) {
  677                                 PStat(tpcb, Nb_from_sess) += totlen;
  678                                 tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0,
  679                                        PStat(tpcb, Nb_from_sess), totlen);
  680                         }
  681 #endif
  682 #ifdef ARGO_DEBUG
  683                         if (argo_debug[D_SYSCALL]) {
  684                                 printf(
  685                                        "PRU_SEND: eot %ld before sbappend %p len 0x%x to sb @ %p\n",
  686                                        eotsdu, m, totlen, sb);
  687                                 dump_mbuf(sb->sb_mb, "so_snd.sb_mb");
  688                                 dump_mbuf(m, "m : to be added");
  689                         }
  690 #endif
  691                         tp_packetize(tpcb, m, eotsdu);
  692 #ifdef ARGO_DEBUG
  693                         if (argo_debug[D_SYSCALL]) {
  694                                 printf("PRU_SEND: eot %ld after sbappend %p\n", eotsdu, m);
  695                                 dump_mbuf(sb->sb_mb, "so_snd.sb_mb");
  696                         }
  697 #endif
  698                         if (tpcb->tp_state == TP_OPEN)
  699                                 error = DoEvent(T_DATA_req);
  700 #ifdef ARGO_DEBUG
  701                         if (argo_debug[D_SYSCALL]) {
  702                                 printf("PRU_SEND: after driver error 0x%x \n", error);
  703                                 printf("so_snd %p cc 0t%ld mbcnt 0t%ld\n",
  704                                        sb, sb->sb_cc, sb->sb_mbcnt);
  705                                 dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver");
  706                         }
  707 #endif
  708                 }
  709                 break;
  710 
  711         case PRU_ABORT: /* called from close() */
  712                 /*
  713                  * called for each incoming connect queued on the parent
  714                  * (accepting) socket
  715                  */
  716                 if (tpcb->tp_state == TP_OPEN || tpcb->tp_state == TP_CONFIRMING) {
  717                         E.TPDU_ATTR(REQ).e_reason = E_TP_NO_SESSION ^ TP_ERROR_MASK;
  718                         error = DoEvent(T_DISC_req);    /* pretend it was a
  719                                                          * close() */
  720                 }
  721                 break;
  722 
  723         case PRU_SENSE:
  724                 /*
  725                  * stat: don't bother with a blocksize.
  726                  */
  727                 splx(s);
  728                 return (0);
  729 
  730         case PRU_SOCKADDR:
  731                 (tpcb->tp_nlproto->nlp_getnetaddr) (tpcb->tp_npcb, nam, TP_LOCAL);
  732                 break;
  733 
  734         case PRU_PEERADDR:
  735                 (tpcb->tp_nlproto->nlp_getnetaddr) (tpcb->tp_npcb, nam, TP_FOREIGN);
  736                 break;
  737 
  738         default:
  739 #ifdef ARGO_DEBUG
  740                 printf("tp_usrreq UNKNOWN PRU %d\n", req);
  741 #endif                          /* ARGO_DEBUG */
  742                 error = EOPNOTSUPP;
  743         }
  744 
  745 #ifdef ARGO_DEBUG
  746         if (argo_debug[D_REQUEST]) {
  747                 printf("%s, so %p, tpcb %p, error %d, state %d\n",
  748                        "returning from tp_usrreq", so, tpcb, error,
  749                        tpcb ? tpcb->tp_state : 0);
  750         }
  751 #endif
  752 #ifdef TPPT
  753         if (tp_traceflags[D_REQUEST]) {
  754                 tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m,
  755                             tpcb ? tpcb->tp_state : 0);
  756         }
  757 #endif
  758 release:
  759         splx(s);
  760         return error;
  761 }
  762 
  763 void
  764 tp_ltrace(struct socket *so, struct uio *uio)
  765 {
  766 #ifdef TPPT
  767         if (tp_traceflags[D_DATA]) {
  768                 struct tp_pcb *tpcb = sototpcb(so);
  769                 if (tpcb) {
  770                         tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so,
  771                                     uio->uio_resid, uio->uio_iovcnt, 0);
  772                 }
  773         }
  774 #endif
  775 }
  776 
  777 int
  778 tp_confirm(struct tp_pcb *tpcb)
  779 {
  780         struct tp_event E;
  781         if (tpcb->tp_state == TP_CONFIRMING)
  782                 return DoEvent(T_ACPT_req);
  783         printf("Tp confirm called when not confirming; tpcb %p, state 0x%x\n",
  784                tpcb, tpcb->tp_state);
  785         return 0;
  786 }
  787 
  788 /*
  789  * Process control data sent with sendmsg()
  790  */
  791 int
  792 tp_snd_control(struct mbuf *m, struct socket *so, struct mbuf **data)
  793 {
  794         struct cmsghdr *ch;
  795         int             error = 0;
  796 
  797         if (m && m->m_len) {
  798                 ch = mtod(m, struct cmsghdr *);
  799                 m->m_len -= sizeof(*ch);
  800                 m->m_data += sizeof(*ch);
  801                 error = tp_ctloutput(PRCO_SETOPT,
  802                                      so, ch->cmsg_level, ch->cmsg_type, &m);
  803                 if (ch->cmsg_type == TPOPT_DISC_DATA) {
  804                         if (data && *data) {
  805                                 m_freem(*data);
  806                                 *data = 0;
  807                         }
  808                         error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0,
  809                             (struct mbuf *)0, (struct mbuf *)0,
  810                             (struct lwp *)0);
  811                 }
  812         }
  813         if (m)
  814                 m_freem(m);
  815         return error;
  816 }

Cache object: 62518343e5a81b3e116aa5ba43c4f194


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