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/dev/kttcp.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: kttcp.c,v 1.28 2008/04/24 11:38:36 ad Exp $    */
    2 
    3 /*
    4  * Copyright (c) 2002 Wasabi Systems, Inc.
    5  * All rights reserved.
    6  *
    7  * Written by Frank van der Linden and Jason R. Thorpe for
    8  * Wasabi Systems, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed for the NetBSD Project by
   21  *      Wasabi Systems, Inc.
   22  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
   23  *    or promote products derived from this software without specific prior
   24  *    written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * kttcp.c -- provides kernel support for testing network testing,
   41  *            see kttcp(4)
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __KERNEL_RCSID(0, "$NetBSD: kttcp.c,v 1.28 2008/04/24 11:38:36 ad Exp $");
   46 
   47 #include <sys/param.h>
   48 #include <sys/types.h>
   49 #include <sys/ioctl.h>
   50 #include <sys/file.h>
   51 #include <sys/filedesc.h>
   52 #include <sys/conf.h>
   53 #include <sys/systm.h>
   54 #include <sys/protosw.h>
   55 #include <sys/proc.h>
   56 #include <sys/resourcevar.h>
   57 #include <sys/signal.h>
   58 #include <sys/socketvar.h>
   59 #include <sys/socket.h>
   60 #include <sys/mbuf.h>
   61 #include <sys/mount.h>
   62 #include <sys/syscallargs.h>
   63 
   64 #include <dev/kttcpio.h>
   65 
   66 static int kttcp_send(struct lwp *l, struct kttcp_io_args *);
   67 static int kttcp_recv(struct lwp *l, struct kttcp_io_args *);
   68 static int kttcp_sosend(struct socket *, unsigned long long,
   69                         unsigned long long *, struct lwp *, int);
   70 static int kttcp_soreceive(struct socket *, unsigned long long,
   71                            unsigned long long *, struct lwp *, int *);
   72 
   73 void    kttcpattach(int);
   74 
   75 dev_type_ioctl(kttcpioctl);
   76 
   77 const struct cdevsw kttcp_cdevsw = {
   78         nullopen, nullclose, noread, nowrite, kttcpioctl,
   79         nostop, notty, nopoll, nommap, nokqfilter, D_OTHER
   80 };
   81 
   82 void
   83 kttcpattach(int count)
   84 {
   85         /* Do nothing. */
   86 }
   87 
   88 int
   89 kttcpioctl(dev_t dev, u_long cmd, void *data, int flag,
   90     struct lwp *l)
   91 {
   92         int error;
   93 
   94         if ((flag & FWRITE) == 0)
   95                 return EPERM;
   96 
   97         switch (cmd) {
   98         case KTTCP_IO_SEND:
   99                 error = kttcp_send(l, (struct kttcp_io_args *) data);
  100                 break;
  101 
  102         case KTTCP_IO_RECV:
  103                 error = kttcp_recv(l, (struct kttcp_io_args *) data);
  104                 break;
  105 
  106         default:
  107                 return EINVAL;
  108         }
  109 
  110         return error;
  111 }
  112 
  113 static int
  114 kttcp_send(struct lwp *l, struct kttcp_io_args *kio)
  115 {
  116         struct socket *so;
  117         int error;
  118         struct timeval t0, t1;
  119         unsigned long long len, done;
  120 
  121         if (kio->kio_totalsize >= KTTCP_MAX_XMIT)
  122                 return EINVAL;
  123 
  124         if ((error = fd_getsock(kio->kio_socket, &so)) != 0)
  125                 return error;
  126 
  127         len = kio->kio_totalsize;
  128         microtime(&t0);
  129         do {
  130                 error = kttcp_sosend(so, len, &done, l, 0);
  131                 len -= done;
  132         } while (error == 0 && len > 0);
  133 
  134         fd_putfile(kio->kio_socket);
  135 
  136         microtime(&t1);
  137         if (error != 0)
  138                 return error;
  139         timersub(&t1, &t0, &kio->kio_elapsed);
  140 
  141         kio->kio_bytesdone = kio->kio_totalsize - len;
  142 
  143         return 0;
  144 }
  145 
  146 static int
  147 kttcp_recv(struct lwp *l, struct kttcp_io_args *kio)
  148 {
  149         struct socket *so;
  150         int error;
  151         struct timeval t0, t1;
  152         unsigned long long len, done;
  153 
  154         done = 0;       /* XXX gcc */
  155 
  156         if (kio->kio_totalsize > KTTCP_MAX_XMIT)
  157                 return EINVAL;
  158 
  159         if ((error = fd_getsock(kio->kio_socket, &so)) != 0)
  160                 return error;
  161         len = kio->kio_totalsize;
  162         microtime(&t0);
  163         do {
  164                 error = kttcp_soreceive(so, len, &done, l, NULL);
  165                 len -= done;
  166         } while (error == 0 && len > 0 && done > 0);
  167 
  168         fd_putfile(kio->kio_socket);
  169 
  170         microtime(&t1);
  171         if (error == EPIPE)
  172                 error = 0;
  173         if (error != 0)
  174                 return error;
  175         timersub(&t1, &t0, &kio->kio_elapsed);
  176 
  177         kio->kio_bytesdone = kio->kio_totalsize - len;
  178 
  179         return 0;
  180 }
  181 
  182 #define SBLOCKWAIT(f)   (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
  183 
  184 /*
  185  * Slightly changed version of sosend()
  186  */
  187 static int
  188 kttcp_sosend(struct socket *so, unsigned long long slen,
  189              unsigned long long *done, struct lwp *l, int flags)
  190 {
  191         struct mbuf **mp, *m, *top;
  192         long space, len, mlen;
  193         int error, dontroute, atomic;
  194         long long resid;
  195 
  196         atomic = sosendallatonce(so);
  197         resid = slen;
  198         top = NULL;
  199         /*
  200          * In theory resid should be unsigned.
  201          * However, space must be signed, as it might be less than 0
  202          * if we over-committed, and we must use a signed comparison
  203          * of space and resid.  On the other hand, a negative resid
  204          * causes us to loop sending 0-length segments to the protocol.
  205          */
  206         if (resid < 0) {
  207                 error = EINVAL;
  208                 goto out;
  209         }
  210         dontroute =
  211             (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
  212             (so->so_proto->pr_flags & PR_ATOMIC);
  213         l->l_ru.ru_msgsnd++;
  214 #define snderr(errno)   { error = errno; goto release; }
  215         solock(so);
  216  restart:
  217         if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0)
  218                 goto out;
  219         do {
  220                 if (so->so_state & SS_CANTSENDMORE)
  221                         snderr(EPIPE);
  222                 if (so->so_error) {
  223                         error = so->so_error;
  224                         so->so_error = 0;
  225                         goto release;
  226                 }
  227                 if ((so->so_state & SS_ISCONNECTED) == 0) {
  228                         if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
  229                                 if ((so->so_state & SS_ISCONFIRMING) == 0)
  230                                         snderr(ENOTCONN);
  231                         } else
  232                                 snderr(EDESTADDRREQ);
  233                 }
  234                 space = sbspace(&so->so_snd);
  235                 if (flags & MSG_OOB)
  236                         space += 1024;
  237                 if ((atomic && resid > so->so_snd.sb_hiwat))
  238                         snderr(EMSGSIZE);
  239                 if (space < resid && (atomic || space < so->so_snd.sb_lowat)) {
  240                         if (so->so_nbio)
  241                                 snderr(EWOULDBLOCK);
  242                         SBLASTRECORDCHK(&so->so_rcv,
  243                             "kttcp_soreceive sbwait 1");
  244                         SBLASTMBUFCHK(&so->so_rcv,
  245                             "kttcp_soreceive sbwait 1");
  246                         sbunlock(&so->so_snd);
  247                         error = sbwait(&so->so_snd);
  248                         if (error)
  249                                 goto out;
  250                         goto restart;
  251                 }
  252                 mp = &top;
  253                 do {
  254                         sounlock(so);
  255                         do {
  256                                 if (top == 0) {
  257                                         m = m_gethdr(M_WAIT, MT_DATA);
  258                                         mlen = MHLEN;
  259                                         m->m_pkthdr.len = 0;
  260                                         m->m_pkthdr.rcvif = NULL;
  261                                 } else {
  262                                         m = m_get(M_WAIT, MT_DATA);
  263                                         mlen = MLEN;
  264                                 }
  265                                 if (resid >= MINCLSIZE && space >= MCLBYTES) {
  266                                         m_clget(m, M_WAIT);
  267                                         if ((m->m_flags & M_EXT) == 0)
  268                                                 goto nopages;
  269                                         mlen = MCLBYTES;
  270 #ifdef  MAPPED_MBUFS
  271                                         len = lmin(MCLBYTES, resid);
  272 #else
  273                                         if (atomic && top == 0) {
  274                                                 len = lmin(MCLBYTES - max_hdr,
  275                                                     resid);
  276                                                 m->m_data += max_hdr;
  277                                         } else
  278                                                 len = lmin(MCLBYTES, resid);
  279 #endif
  280                                         space -= len;
  281                                 } else {
  282 nopages:
  283                                         len = lmin(lmin(mlen, resid), space);
  284                                         space -= len;
  285                                         /*
  286                                          * For datagram protocols, leave room
  287                                          * for protocol headers in first mbuf.
  288                                          */
  289                                         if (atomic && top == 0 && len < mlen)
  290                                                 MH_ALIGN(m, len);
  291                                 }
  292                                 resid -= len;
  293                                 m->m_len = len;
  294                                 *mp = m;
  295                                 top->m_pkthdr.len += len;
  296                                 if (error)
  297                                         goto release;
  298                                 mp = &m->m_next;
  299                                 if (resid <= 0) {
  300                                         if (flags & MSG_EOR)
  301                                                 top->m_flags |= M_EOR;
  302                                         break;
  303                                 }
  304                         } while (space > 0 && atomic);
  305                         solock(so);
  306 
  307                         if (so->so_state & SS_CANTSENDMORE)
  308                                 snderr(EPIPE);
  309                         if (dontroute)
  310                                 so->so_options |= SO_DONTROUTE;
  311                         if (resid > 0)
  312                                 so->so_state |= SS_MORETOCOME;
  313                         error = (*so->so_proto->pr_usrreq)(so,
  314                             (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
  315                             top, NULL, NULL, l);
  316                         if (dontroute)
  317                                 so->so_options &= ~SO_DONTROUTE;
  318                         if (resid > 0)
  319                                 so->so_state &= ~SS_MORETOCOME;
  320                         top = 0;
  321                         mp = &top;
  322                         if (error)
  323                                 goto release;
  324                 } while (resid && space > 0);
  325         } while (resid);
  326 
  327  release:
  328         sbunlock(&so->so_snd);
  329  out:
  330         sounlock(so);
  331         if (top)
  332                 m_freem(top);
  333         *done = slen - resid;
  334 #if 0
  335         printf("sosend: error %d slen %llu resid %lld\n", error, slen, resid);
  336 #endif
  337         return (error);
  338 }
  339 
  340 static int
  341 kttcp_soreceive(struct socket *so, unsigned long long slen,
  342     unsigned long long *done, struct lwp *l, int *flagsp)
  343 {
  344         struct mbuf *m, **mp;
  345         int flags, len, error, offset, moff, type;
  346         long long orig_resid, resid;
  347         const struct protosw *pr;
  348         struct mbuf *nextrecord;
  349 
  350         pr = so->so_proto;
  351         mp = NULL;
  352         type = 0;
  353         resid = orig_resid = slen;
  354         if (flagsp)
  355                 flags = *flagsp &~ MSG_EOR;
  356         else
  357                 flags = 0;
  358         if (flags & MSG_OOB) {
  359                 m = m_get(M_WAIT, MT_DATA);
  360                 solock(so);
  361                 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
  362                     (struct mbuf *)(long)(flags & MSG_PEEK), NULL, NULL);
  363                 sounlock(so);
  364                 if (error)
  365                         goto bad;
  366                 do {
  367                         resid -= min(resid, m->m_len);
  368                         m = m_free(m);
  369                 } while (resid && error == 0 && m);
  370  bad:
  371                 if (m)
  372                         m_freem(m);
  373                 return (error);
  374         }
  375         if (mp)
  376                 *mp = NULL;
  377         solock(so);
  378         if (so->so_state & SS_ISCONFIRMING && resid)
  379                 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, NULL);
  380  restart:
  381         if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0)
  382                 return (error);
  383         m = so->so_rcv.sb_mb;
  384         /*
  385          * If we have less data than requested, block awaiting more
  386          * (subject to any timeout) if:
  387          *   1. the current count is less than the low water mark,
  388          *   2. MSG_WAITALL is set, and it is possible to do the entire
  389          *      receive operation at once if we block (resid <= hiwat), or
  390          *   3. MSG_DONTWAIT is not set.
  391          * If MSG_WAITALL is set but resid is larger than the receive buffer,
  392          * we have to do the receive in sections, and thus risk returning
  393          * a short count if a timeout or signal occurs after we start.
  394          */
  395         if (m == NULL || (((flags & MSG_DONTWAIT) == 0 &&
  396             so->so_rcv.sb_cc < resid) &&
  397             (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
  398             ((flags & MSG_WAITALL) && resid <= so->so_rcv.sb_hiwat)) &&
  399             m->m_nextpkt == NULL && (pr->pr_flags & PR_ATOMIC) == 0)) {
  400 #ifdef DIAGNOSTIC
  401                 if (m == NULL && so->so_rcv.sb_cc)
  402                         panic("receive 1");
  403 #endif
  404                 if (so->so_error) {
  405                         if (m)
  406                                 goto dontblock;
  407                         error = so->so_error;
  408                         if ((flags & MSG_PEEK) == 0)
  409                                 so->so_error = 0;
  410                         goto release;
  411                 }
  412                 if (so->so_state & SS_CANTRCVMORE) {
  413                         if (m)
  414                                 goto dontblock;
  415                         else
  416                                 goto release;
  417                 }
  418                 for (; m; m = m->m_next)
  419                         if (m->m_type == MT_OOBDATA  || (m->m_flags & M_EOR)) {
  420                                 m = so->so_rcv.sb_mb;
  421                                 goto dontblock;
  422                         }
  423                 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
  424                     (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
  425                         error = ENOTCONN;
  426                         goto release;
  427                 }
  428                 if (resid == 0)
  429                         goto release;
  430                 if (so->so_nbio || (flags & MSG_DONTWAIT)) {
  431                         error = EWOULDBLOCK;
  432                         goto release;
  433                 }
  434                 sbunlock(&so->so_rcv);
  435                 error = sbwait(&so->so_rcv);
  436                 if (error) {
  437                         sounlock(so);
  438                         return (error);
  439                 }
  440                 goto restart;
  441         }
  442  dontblock:
  443         /*
  444          * On entry here, m points to the first record of the socket buffer.
  445          * While we process the initial mbufs containing address and control
  446          * info, we save a copy of m->m_nextpkt into nextrecord.
  447          */
  448 #ifdef notyet /* XXXX */
  449         if (uio->uio_lwp)
  450                 uio->uio_lwp->l_ru.ru_msgrcv++;
  451 #endif
  452         KASSERT(m == so->so_rcv.sb_mb);
  453         SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 1");
  454         SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 1");
  455         nextrecord = m->m_nextpkt;
  456         if (pr->pr_flags & PR_ADDR) {
  457 #ifdef DIAGNOSTIC
  458                 if (m->m_type != MT_SONAME)
  459                         panic("receive 1a");
  460 #endif
  461                 orig_resid = 0;
  462                 if (flags & MSG_PEEK) {
  463                         m = m->m_next;
  464                 } else {
  465                         sbfree(&so->so_rcv, m);
  466                         MFREE(m, so->so_rcv.sb_mb);
  467                         m = so->so_rcv.sb_mb;
  468                 }
  469         }
  470         while (m && m->m_type == MT_CONTROL && error == 0) {
  471                 if (flags & MSG_PEEK) {
  472                         m = m->m_next;
  473                 } else {
  474                         sbfree(&so->so_rcv, m);
  475                         MFREE(m, so->so_rcv.sb_mb);
  476                         m = so->so_rcv.sb_mb;
  477                 }
  478         }
  479 
  480         /*
  481          * If m is non-NULL, we have some data to read.  From now on,
  482          * make sure to keep sb_lastrecord consistent when working on
  483          * the last packet on the chain (nextrecord == NULL) and we
  484          * change m->m_nextpkt.
  485          */
  486         if (m) {
  487                 if ((flags & MSG_PEEK) == 0) {
  488                         m->m_nextpkt = nextrecord;
  489                         /*
  490                          * If nextrecord == NULL (this is a single chain),
  491                          * then sb_lastrecord may not be valid here if m
  492                          * was changed earlier.
  493                          */
  494                         if (nextrecord == NULL) {
  495                                 KASSERT(so->so_rcv.sb_mb == m);
  496                                 so->so_rcv.sb_lastrecord = m;
  497                         }
  498                 }
  499                 type = m->m_type;
  500                 if (type == MT_OOBDATA)
  501                         flags |= MSG_OOB;
  502         } else {
  503                 if ((flags & MSG_PEEK) == 0) {
  504                         KASSERT(so->so_rcv.sb_mb == m);
  505                         so->so_rcv.sb_mb = nextrecord;
  506                         SB_EMPTY_FIXUP(&so->so_rcv);
  507                 }
  508         }
  509         SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 2");
  510         SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 2");
  511 
  512         moff = 0;
  513         offset = 0;
  514         while (m && resid > 0 && error == 0) {
  515                 if (m->m_type == MT_OOBDATA) {
  516                         if (type != MT_OOBDATA)
  517                                 break;
  518                 } else if (type == MT_OOBDATA)
  519                         break;
  520 #ifdef DIAGNOSTIC
  521                 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
  522                         panic("receive 3");
  523 #endif
  524                 so->so_state &= ~SS_RCVATMARK;
  525                 len = resid;
  526                 if (so->so_oobmark && len > so->so_oobmark - offset)
  527                         len = so->so_oobmark - offset;
  528                 if (len > m->m_len - moff)
  529                         len = m->m_len - moff;
  530                 /*
  531                  * If mp is set, just pass back the mbufs.
  532                  * Otherwise copy them out via the uio, then free.
  533                  * Sockbuf must be consistent here (points to current mbuf,
  534                  * it points to next record) when we drop priority;
  535                  * we must note any additions to the sockbuf when we
  536                  * block interrupts again.
  537                  */
  538                 resid -= len;
  539                 if (len == m->m_len - moff) {
  540                         if (m->m_flags & M_EOR)
  541                                 flags |= MSG_EOR;
  542                         if (flags & MSG_PEEK) {
  543                                 m = m->m_next;
  544                                 moff = 0;
  545                         } else {
  546                                 nextrecord = m->m_nextpkt;
  547                                 sbfree(&so->so_rcv, m);
  548                                 if (mp) {
  549                                         *mp = m;
  550                                         mp = &m->m_next;
  551                                         so->so_rcv.sb_mb = m = m->m_next;
  552                                         *mp = NULL;
  553                                 } else {
  554                                         MFREE(m, so->so_rcv.sb_mb);
  555                                         m = so->so_rcv.sb_mb;
  556                                 }
  557                                 /*
  558                                  * If m != NULL, we also know that
  559                                  * so->so_rcv.sb_mb != NULL.
  560                                  */
  561                                 KASSERT(so->so_rcv.sb_mb == m);
  562                                 if (m) {
  563                                         m->m_nextpkt = nextrecord;
  564                                         if (nextrecord == NULL)
  565                                                 so->so_rcv.sb_lastrecord = m;
  566                                 } else {
  567                                         so->so_rcv.sb_mb = nextrecord;
  568                                         SB_EMPTY_FIXUP(&so->so_rcv);
  569                                 }
  570                                 SBLASTRECORDCHK(&so->so_rcv,
  571                                     "kttcp_soreceive 3");
  572                                 SBLASTMBUFCHK(&so->so_rcv,
  573                                     "kttcp_soreceive 3");
  574                         }
  575                 } else {
  576                         if (flags & MSG_PEEK)
  577                                 moff += len;
  578                         else {
  579                                 if (mp) {
  580                                         sounlock(so);
  581                                         *mp = m_copym(m, 0, len, M_WAIT);
  582                                         solock(so);
  583                                 }
  584                                 m->m_data += len;
  585                                 m->m_len -= len;
  586                                 so->so_rcv.sb_cc -= len;
  587                         }
  588                 }
  589                 if (so->so_oobmark) {
  590                         if ((flags & MSG_PEEK) == 0) {
  591                                 so->so_oobmark -= len;
  592                                 if (so->so_oobmark == 0) {
  593                                         so->so_state |= SS_RCVATMARK;
  594                                         break;
  595                                 }
  596                         } else {
  597                                 offset += len;
  598                                 if (offset == so->so_oobmark)
  599                                         break;
  600                         }
  601                 }
  602                 if (flags & MSG_EOR)
  603                         break;
  604                 /*
  605                  * If the MSG_WAITALL flag is set (for non-atomic socket),
  606                  * we must not quit until "uio->uio_resid == 0" or an error
  607                  * termination.  If a signal/timeout occurs, return
  608                  * with a short count but without error.
  609                  * Keep sockbuf locked against other readers.
  610                  */
  611                 while (flags & MSG_WAITALL && m == NULL && resid > 0 &&
  612                     !sosendallatonce(so) && !nextrecord) {
  613                         if (so->so_error || so->so_state & SS_CANTRCVMORE)
  614                                 break;
  615                         /*
  616                          * If we are peeking and the socket receive buffer is
  617                          * full, stop since we can't get more data to peek at.
  618                          */
  619                         if ((flags & MSG_PEEK) && sbspace(&so->so_rcv) <= 0)
  620                                 break;
  621                         /*
  622                          * If we've drained the socket buffer, tell the
  623                          * protocol in case it needs to do something to
  624                          * get it filled again.
  625                          */
  626                         if ((pr->pr_flags & PR_WANTRCVD) && so->so_pcb)
  627                                 (*pr->pr_usrreq)(so, PRU_RCVD, NULL,
  628                                     (struct mbuf *)(long)flags, NULL, NULL);
  629                         SBLASTRECORDCHK(&so->so_rcv,
  630                             "kttcp_soreceive sbwait 2");
  631                         SBLASTMBUFCHK(&so->so_rcv,
  632                             "kttcp_soreceive sbwait 2");
  633                         error = sbwait(&so->so_rcv);
  634                         if (error) {
  635                                 sbunlock(&so->so_rcv);
  636                                 sounlock(so);
  637                                 return (0);
  638                         }
  639                         if ((m = so->so_rcv.sb_mb) != NULL)
  640                                 nextrecord = m->m_nextpkt;
  641                 }
  642         }
  643 
  644         if (m && pr->pr_flags & PR_ATOMIC) {
  645                 flags |= MSG_TRUNC;
  646                 if ((flags & MSG_PEEK) == 0)
  647                         (void) sbdroprecord(&so->so_rcv);
  648         }
  649         if ((flags & MSG_PEEK) == 0) {
  650                 if (m == NULL) {
  651                         /*
  652                          * First part is an SB_EMPTY_FIXUP().  Second part
  653                          * makes sure sb_lastrecord is up-to-date if
  654                          * there is still data in the socket buffer.
  655                          */
  656                         so->so_rcv.sb_mb = nextrecord;
  657                         if (so->so_rcv.sb_mb == NULL) {
  658                                 so->so_rcv.sb_mbtail = NULL;
  659                                 so->so_rcv.sb_lastrecord = NULL;
  660                         } else if (nextrecord->m_nextpkt == NULL)
  661                                 so->so_rcv.sb_lastrecord = nextrecord;
  662                 }
  663                 SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 4");
  664                 SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 4");
  665                 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
  666                         (*pr->pr_usrreq)(so, PRU_RCVD, NULL,
  667                             (struct mbuf *)(long)flags, NULL, NULL);
  668         }
  669         if (orig_resid == resid && orig_resid &&
  670             (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
  671                 sbunlock(&so->so_rcv);
  672                 goto restart;
  673         }
  674 
  675         if (flagsp)
  676                 *flagsp |= flags;
  677  release:
  678         sbunlock(&so->so_rcv);
  679         sounlock(so);
  680         *done = slen - resid;
  681 #if 0
  682         printf("soreceive: error %d slen %llu resid %lld\n", error, slen, resid);
  683 #endif
  684         return (error);
  685 }

Cache object: b975689f544b4abc5b9ebe364d5ee5b9


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