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.38 2008/10/22 18:17:46 plunky 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.38 2008/10/22 18:17:46 plunky 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 #include <netiso/iso_var.h>
   94 
   95 int             TNew;
   96 int             TPNagle1, TPNagle2;
   97 struct tp_pcb  *tp_listeners, *tp_intercepts;
   98 
   99 #ifdef ARGO_DEBUG
  100 /*
  101  * CALLED FROM:
  102  *  anywhere you want to debug...
  103  * FUNCTION and ARGUMENTS:
  104  *  print (str) followed by the control info in the mbufs of an mbuf chain (n)
  105  */
  106 void
  107 dump_mbuf(struct mbuf *n, const char *str)
  108 {
  109         struct mbuf    *nextrecord;
  110 
  111         printf("dump %s\n", str);
  112 
  113         if (n == NULL) {
  114                 printf("EMPTY:\n");
  115                 return;
  116         }
  117         while (n) {
  118                 nextrecord = n->m_nextpkt;
  119                 printf("RECORD:\n");
  120                 while (n) {
  121                         printf("%p : Len %x Data %p A %p Nx %p Tp %x\n",
  122                                n, n->m_len, n->m_data, n->m_nextpkt, n->m_next, n->m_type);
  123 #ifdef notdef
  124                         {
  125                                 char  *p = mtod(n, char *);
  126                                 int    i;
  127 
  128                                 printf("data: ");
  129                                 for (i = 0; i < n->m_len; i++) {
  130                                         if (i % 8 == 0)
  131                                                 printf("\n");
  132                                         printf("0x%x ", *(p + i));
  133                                 }
  134                                 printf("\n");
  135                         }
  136 #endif                          /* notdef */
  137                         if (n->m_next == n) {
  138                                 printf("LOOP!\n");
  139                                 return;
  140                         }
  141                         n = n->m_next;
  142                 }
  143                 n = nextrecord;
  144         }
  145         printf("\n");
  146 }
  147 
  148 #endif                          /* ARGO_DEBUG */
  149 
  150 /*
  151  * CALLED FROM:
  152  *  tp_usrreq(), PRU_RCVOOB
  153  * FUNCTION and ARGUMENTS:
  154  *      Copy data from the expedited data socket buffer into
  155  *      the pre-allocated mbuf m.
  156  *      There is an isomorphism between XPD TPDUs and expedited data TSDUs.
  157  *      XPD tpdus are limited to 16 bytes of data so they fit in one mbuf.
  158  * RETURN VALUE:
  159  *  EINVAL if debugging is on and a disaster has occurred
  160  *  ENOTCONN if the socket isn't connected
  161  *  EWOULDBLOCK if the socket is in non-blocking mode and there's no
  162  *              xpd data in the buffer
  163  *  E* whatever is returned from the fsm.
  164  */
  165 int
  166 tp_rcvoob(struct tp_pcb *tpcb, struct socket *so, struct mbuf *m,
  167     int *outflags, int inflags)
  168 {
  169         struct mbuf *n;
  170         struct sockbuf *sb = &so->so_rcv;
  171         struct tp_event E;
  172         int             error = 0;
  173         struct mbuf **nn;
  174 
  175 #ifdef ARGO_DEBUG
  176         if (argo_debug[D_XPD]) {
  177                 printf("PRU_RCVOOB, sostate 0x%x\n", so->so_state);
  178         }
  179 #endif
  180 
  181         /* if you use soreceive */
  182         if (m == NULL)
  183                 return ENOBUFS;
  184 
  185 restart:
  186         if ((((so->so_state & SS_ISCONNECTED) == 0)
  187              || (so->so_state & SS_ISDISCONNECTING) != 0) &&
  188             (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
  189                 return ENOTCONN;
  190         }
  191         /*
  192          * Take the first mbuf off the chain. Each XPD TPDU gives you a
  193          * complete TSDU so the chains don't get coalesced, but one TSDU may
  194          * span several mbufs. Nevertheless, since n should have a most 16
  195          * bytes, it will fit into m.  (size was checked in tp_input() )
  196          */
  197 
  198         /*
  199          * Code for excision of OOB data should be added to
  200          * uipc_socket2.c (like sbappend).
  201          */
  202 
  203         sblock(sb, M_WAITOK);
  204         for (nn = &sb->sb_mb; (n = *nn) != NULL; nn = &n->m_nextpkt)
  205                 if (n->m_type == MT_OOBDATA)
  206                         break;
  207 
  208         if (n == 0) {
  209 #ifdef ARGO_DEBUG
  210                 if (argo_debug[D_XPD]) {
  211                         printf("RCVOOB: empty queue!\n");
  212                 }
  213 #endif
  214                 sbunlock(sb);
  215                 if (so->so_nbio) {
  216                         return EWOULDBLOCK;
  217                 }
  218                 sbwait(sb);
  219                 goto restart;
  220         }
  221         m->m_len = 0;
  222 
  223         /* Assuming at most one xpd tpdu is in the buffer at once */
  224         while (n != NULL) {
  225                 m->m_len += n->m_len;
  226                 bcopy(mtod(n, void *), mtod(m, void *), (unsigned) n->m_len);
  227                 m->m_data += n->m_len;  /* so mtod() in bcopy() above gives
  228                                          * right addr */
  229                 n = n->m_next;
  230         }
  231         m->m_data = m->m_dat;
  232         m->m_flags |= M_EOR;
  233 
  234 #ifdef ARGO_DEBUG
  235         if (argo_debug[D_XPD]) {
  236                 printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len);
  237                 dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf");
  238                 dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf");
  239         }
  240 #endif
  241 
  242         if ((inflags & MSG_PEEK) == 0) {
  243                 n = *nn;
  244                 *nn = n->m_nextpkt;
  245                 for (; n; n = m_free(n))
  246                         sbfree(sb, n);
  247         }
  248         sbunlock(sb);
  249 
  250 #ifdef TPPT
  251         if (tp_traceflags[D_XPD]) {
  252                 tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len",
  253                             tpcb->tp_Xrcv.sb_cc, m->m_len, 0, 0);
  254         }
  255 #endif
  256         if (error == 0)
  257                 error = DoEvent(T_USR_Xrcvd);
  258         return error;
  259 }
  260 
  261 /*
  262  * CALLED FROM:
  263  *  tp_usrreq(), PRU_SENDOOB
  264  * FUNCTION and ARGUMENTS:
  265  *      Send what's in the mbuf chain (m) as an XPD TPDU.
  266  *      The mbuf may not contain more than 16 bytes of data.
  267  *      XPD TSDUs aren't segmented, so they translate into
  268  *      exactly one XPD TPDU, with EOT bit set.
  269  * RETURN VALUE:
  270  *  EWOULDBLOCK if socket is in non-blocking mode and the previous
  271  *   xpd data haven't been acked yet.
  272  *  EMSGSIZE if trying to send > max-xpd bytes (16)
  273  *  ENOBUFS if ran out of mbufs
  274  */
  275 int
  276 tp_sendoob(struct tp_pcb *tpcb, struct socket *so, struct mbuf *xdata,
  277     int *outflags)
  278 {
  279         /*
  280          * Each mbuf chain represents a sequence # in the XPD seq space.
  281          * The first one in the queue has sequence # tp_Xuna.
  282          * When we add to the XPD queue, we stuff a zero-length
  283          * mbuf (mark) into the DATA queue, with its sequence number in m_next
  284          * to be assigned to this XPD tpdu, so data xfer can stop
  285          * when it reaches the zero-length mbuf if this XPD TPDU hasn't
  286          * yet been acknowledged.
  287          */
  288         struct sockbuf *sb = &(tpcb->tp_Xsnd);
  289         struct mbuf *xmark;
  290         int    len = 0;
  291         struct tp_event E;
  292 
  293 #ifdef ARGO_DEBUG
  294         if (argo_debug[D_XPD]) {
  295                 printf("tp_sendoob:");
  296                 if (xdata)
  297                         printf("xdata len 0x%x\n", xdata->m_len);
  298         }
  299 #endif
  300         /*
  301          * DO NOT LOCK the Xsnd buffer!!!! You can have at MOST one socket
  302          * buf locked at any time!!! (otherwise you might sleep() in sblock()
  303          * w/ a signal pending and cause the system call to be aborted w/ a
  304          * locked socketbuf, which is a problem.  So the so_snd buffer lock
  305          * (done in sosend()) serves as the lock for Xpd.
  306          */
  307         if (sb->sb_mb) {        /* Anything already in eXpedited data
  308                                  * sockbuf? */
  309                 if (so->so_nbio) {
  310                         return EWOULDBLOCK;
  311                 }
  312                 while (sb->sb_mb) {
  313                         sbunlock(&so->so_snd);  /* already locked by sosend */
  314                         sbwait(&so->so_snd);
  315                         sblock(&so->so_snd, M_WAITOK);  /* sosend will unlock on
  316                                                          * return */
  317                 }
  318         }
  319         if (xdata == (struct mbuf *) 0) {
  320                 /* empty xpd packet */
  321                 xdata = m_gethdr(M_WAIT, MT_OOBDATA);
  322                 xdata->m_len = 0;
  323                 xdata->m_pkthdr.len = 0;
  324         }
  325 #ifdef ARGO_DEBUG
  326         if (argo_debug[D_XPD]) {
  327                 printf("tp_sendoob 1:");
  328                 if (xdata)
  329                         printf("xdata len 0x%x\n", xdata->m_len);
  330         }
  331 #endif
  332         xmark = xdata;          /* temporary use of variable xmark */
  333         while (xmark) {
  334                 len += xmark->m_len;
  335                 xmark = xmark->m_next;
  336         }
  337         if (len > TP_MAX_XPD_DATA) {
  338                 return EMSGSIZE;
  339         }
  340 #ifdef ARGO_DEBUG
  341         if (argo_debug[D_XPD]) {
  342                 printf("tp_sendoob 2:");
  343                 if (xdata)
  344                         printf("xdata len 0x%x\n", len);
  345         }
  346 #endif
  347 
  348 
  349 #ifdef TPPT
  350         if (tp_traceflags[D_XPD]) {
  351                 tptraceTPCB(TPPTmisc, "XPD mark m_next ", xdata->m_next, 0, 0, 0);
  352         }
  353 #endif
  354 
  355         sbappendrecord(sb, xdata);
  356 
  357 #ifdef ARGO_DEBUG
  358         if (argo_debug[D_XPD]) {
  359                 printf("tp_sendoob len 0x%x\n", len);
  360                 dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:");
  361                 dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:");
  362         }
  363 #endif
  364         return DoEvent(T_XPD_req);
  365 }
  366 
  367 /*
  368  * CALLED FROM:
  369  *  the socket routines
  370  * FUNCTION and ARGUMENTS:
  371  *      Handles all "user requests" except the [gs]ockopts() requests.
  372  *      The argument (req) is the request type (PRU*),
  373  *      (m) is an mbuf chain, generally used for send and
  374  *      receive type requests only.
  375  *      (nam) is used for addresses usually, in particular for the bind request.
  376  *
  377  */
  378 /* ARGSUSED */
  379 int
  380 tp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
  381         struct mbuf *control, struct lwp *l)
  382 {
  383         struct tp_pcb *tpcb;
  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         tpcb = sototpcb(so);
  407         if (tpcb == 0 && req != PRU_ATTACH) {
  408 #ifdef TPPT
  409                 if (tp_traceflags[D_REQUEST]) {
  410                         tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0);
  411                 }
  412 #endif
  413                 error = EINVAL;
  414                 goto release;
  415         }
  416 
  417         switch (req) {
  418 
  419         case PRU_ATTACH:
  420                 sosetlock(so);
  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((void *) 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                         iso_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                 return (0);
  728 
  729         case PRU_SOCKADDR:
  730                 (tpcb->tp_nlproto->nlp_getnetaddr) (tpcb->tp_npcb, nam, TP_LOCAL);
  731                 break;
  732 
  733         case PRU_PEERADDR:
  734                 (tpcb->tp_nlproto->nlp_getnetaddr) (tpcb->tp_npcb, nam, TP_FOREIGN);
  735                 break;
  736 
  737         default:
  738 #ifdef ARGO_DEBUG
  739                 printf("tp_usrreq UNKNOWN PRU %d\n", req);
  740 #endif                          /* ARGO_DEBUG */
  741                 error = EOPNOTSUPP;
  742         }
  743 
  744 #ifdef ARGO_DEBUG
  745         if (argo_debug[D_REQUEST]) {
  746                 printf("%s, so %p, tpcb %p, error %d, state %d\n",
  747                        "returning from tp_usrreq", so, tpcb, error,
  748                        tpcb ? tpcb->tp_state : 0);
  749         }
  750 #endif
  751 #ifdef TPPT
  752         if (tp_traceflags[D_REQUEST]) {
  753                 tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m,
  754                             tpcb ? tpcb->tp_state : 0);
  755         }
  756 #endif
  757 release:
  758         return error;
  759 }
  760 
  761 void
  762 tp_ltrace(struct socket *so, struct uio *uio)
  763 {
  764 #ifdef TPPT
  765         if (tp_traceflags[D_DATA]) {
  766                 struct tp_pcb *tpcb = sototpcb(so);
  767                 if (tpcb) {
  768                         tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so,
  769                                     uio->uio_resid, uio->uio_iovcnt, 0);
  770                 }
  771         }
  772 #endif
  773 }
  774 
  775 int
  776 tp_confirm(struct tp_pcb *tpcb)
  777 {
  778         struct tp_event E;
  779         if (tpcb->tp_state == TP_CONFIRMING)
  780                 return DoEvent(T_ACPT_req);
  781         printf("Tp confirm called when not confirming; tpcb %p, state 0x%x\n",
  782                tpcb, tpcb->tp_state);
  783         return 0;
  784 }
  785 
  786 /*
  787  * Process control data sent with sendmsg()
  788  */
  789 int
  790 tp_snd_control(struct mbuf *m, struct socket *so, struct mbuf **data)
  791 {
  792         struct sockopt sopt;
  793         struct cmsghdr *ch;
  794         int             error = 0;
  795 
  796         if (m && m->m_len) {
  797                 ch = mtod(m, struct cmsghdr *);
  798                 m->m_len -= sizeof(*ch);
  799                 m->m_data += sizeof(*ch);
  800 
  801                 sockopt_init(&sopt, ch->cmsg_level, ch->cmsg_type, 0);
  802                 error = sockopt_setmbuf(&sopt, m);
  803                 if (error == 0)
  804                         error = tp_ctloutput(PRCO_SETOPT, so, &sopt);
  805                 sockopt_destroy(&sopt);
  806                 m = NULL;
  807 
  808                 if (ch->cmsg_type == TPOPT_DISC_DATA) {
  809                         if (data && *data) {
  810                                 m_freem(*data);
  811                                 *data = 0;
  812                         }
  813                         error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0,
  814                             (struct mbuf *)0, (struct mbuf *)0,
  815                             (struct lwp *)0);
  816                 }
  817         }
  818         if (m)
  819                 m_freem(m);
  820         return error;
  821 }

Cache object: 3d1c501c77ef8d1febb7f8ddfd5652a9


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