Annotation of XNU/bsd/kern/uipc_socket.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /* Copyright (c) 1998, 1999 Apple Computer, Inc. All Rights Reserved */
                     23: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     24: /*
                     25:  * Copyright (c) 1982, 1986, 1988, 1990, 1993
                     26:  *     The Regents of the University of California.  All rights reserved.
                     27:  *
                     28:  * Redistribution and use in source and binary forms, with or without
                     29:  * modification, are permitted provided that the following conditions
                     30:  * are met:
                     31:  * 1. Redistributions of source code must retain the above copyright
                     32:  *    notice, this list of conditions and the following disclaimer.
                     33:  * 2. Redistributions in binary form must reproduce the above copyright
                     34:  *    notice, this list of conditions and the following disclaimer in the
                     35:  *    documentation and/or other materials provided with the distribution.
                     36:  * 3. All advertising materials mentioning features or use of this software
                     37:  *    must display the following acknowledgement:
                     38:  *     This product includes software developed by the University of
                     39:  *     California, Berkeley and its contributors.
                     40:  * 4. Neither the name of the University nor the names of its contributors
                     41:  *    may be used to endorse or promote products derived from this software
                     42:  *    without specific prior written permission.
                     43:  *
                     44:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     45:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     46:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     47:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     48:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     49:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     50:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     51:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     52:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     53:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     54:  * SUCH DAMAGE.
                     55:  *
                     56:  *     @(#)uipc_socket.c       8.6 (Berkeley) 5/2/95
                     57:  */
                     58: 
                     59: #include <sys/param.h>
                     60: #include <sys/systm.h>
                     61: #include <sys/proc.h>
                     62: #include <sys/fcntl.h>
                     63: #include <sys/malloc.h>
                     64: #include <sys/mbuf.h>
                     65: #include <sys/domain.h>
                     66: #include <sys/kernel.h>
                     67: #include <sys/poll.h>
                     68: #include <sys/protosw.h>
                     69: #include <sys/socket.h>
                     70: #include <sys/socketvar.h>
                     71: #include <sys/resourcevar.h>
                     72: #include <sys/signalvar.h>
                     73: #include <sys/sysctl.h>
                     74: #include <sys/uio.h>
                     75: #include <sys/ev.h>
                     76: #include <sys/kdebug.h>
                     77: 
                     78: #if ISFB31
                     79: #include <vm/vm_zone.h>
                     80: #else
                     81: #include <kern/zalloc.h>
                     82: #endif
                     83: 
                     84: #include <machine/limits.h>
                     85: 
                     86: int socket_debug = 0;
                     87: int socket_zone = M_SOCKET;
                     88: so_gen_t       so_gencnt;      /* generation count for sockets */
                     89: 
                     90: MALLOC_DEFINE(M_SONAME, "soname", "socket name");
                     91: MALLOC_DEFINE(M_PCB, "pcb", "protocol control block");
                     92: 
                     93: #if KDEBUG
                     94: #define DBG_LAYER_IN_BEG       NETDBG_CODE(DBG_NETSOCK, 0)
                     95: #define DBG_LAYER_IN_END       NETDBG_CODE(DBG_NETSOCK, 2)
                     96: #define DBG_LAYER_OUT_BEG      NETDBG_CODE(DBG_NETSOCK, 1)
                     97: #define DBG_LAYER_OUT_END      NETDBG_CODE(DBG_NETSOCK, 3)
                     98: #define DBG_FNC_SOSEND         NETDBG_CODE(DBG_NETSOCK, (4 << 8) | 1)
                     99: #define DBG_FNC_SORECEIVE      NETDBG_CODE(DBG_NETSOCK, (8 << 8))
                    100: #endif
                    101: 
                    102: SYSCTL_DECL(_kern_ipc);
                    103: 
                    104: static int somaxconn = SOMAXCONN;
                    105: SYSCTL_INT(_kern_ipc, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW, &somaxconn,
                    106:           0, "");
                    107: 
                    108: /*
                    109:  * Socket operation routines.
                    110:  * These routines are called by the routines in
                    111:  * sys_socket.c or from a system process, and
                    112:  * implement the semantics of socket operations by
                    113:  * switching out to the protocol specific routines.
                    114:  */
                    115: 
                    116: void socketinit()
                    117: {
                    118: }
                    119: 
                    120: 
                    121: /*
                    122:  * Get a socket structure from our zone, and initialize it.
                    123:  * We don't implement `waitok' yet (see comments in uipc_domain.c).
                    124:  * Note that it would probably be better to allocate socket
                    125:  * and PCB at the same time, but I'm not convinced that all
                    126:  * the protocols can be easily modified to do this.
                    127:  */
                    128: struct socket *
                    129: soalloc(waitok)
                    130:        int waitok;
                    131: {
                    132:        struct socket *so;
                    133: 
                    134:        so = _MALLOC_ZONE(sizeof(*so), socket_zone, M_WAITOK);
                    135:        if (so) {
                    136:                /* XXX race condition for reentrant kernel */
                    137:                bzero(so, sizeof *so);
                    138:                so->so_gencnt = ++so_gencnt;
                    139:                so->so_zone = socket_zone;
                    140:        }
                    141:        return so;
                    142: }
                    143: 
                    144: int
                    145: socreate(dom, aso, type, proto)
                    146:        int dom;
                    147:        struct socket **aso;
                    148:        register int type;
                    149:        int proto;
                    150: 
                    151: {
                    152:        struct proc *p = current_proc();
                    153:        register struct protosw *prp;
                    154:        struct socket *so;
                    155:        register int error = 0;
                    156: 
                    157:        if (proto)
                    158:                prp = pffindproto(dom, proto, type);
                    159:        else
                    160:                prp = pffindtype(dom, type);
                    161:        if (prp == 0 || prp->pr_usrreqs->pru_attach == 0)
                    162:                return (EPROTONOSUPPORT);
                    163:        if (prp->pr_type != type)
                    164:                return (EPROTOTYPE);
                    165:        so = soalloc(p != 0);
                    166:        if (so == 0)
                    167:                return (ENOBUFS);
                    168: 
                    169:        TAILQ_INIT(&so->so_incomp);
                    170:        TAILQ_INIT(&so->so_comp);
                    171:        so->so_type = type;
                    172: 
                    173:        if (p != 0) {
                    174:                if (p->p_ucred->cr_uid == 0)
                    175:                        so->so_state = SS_PRIV;
                    176: 
                    177:                so->so_uid = p->p_ucred->cr_uid;
                    178:        }
                    179: 
                    180:        so->so_proto = prp;
                    181:        so->so_rcv.sb_flags |= SB_RECV; /* XXX */
                    182:        if (prp->pr_sfilter.tqh_first)
                    183:                error = sfilter_init(so);
                    184:        if (error == 0)
                    185:                error = (*prp->pr_usrreqs->pru_attach)(so, proto, p);
                    186: 
                    187:        if (error) {
                    188:                so->so_state |= SS_NOFDREF;
                    189:                sofree(so);
                    190:                return (error);
                    191:        }
                    192:        prp->pr_domain->dom_refs++;
                    193:        so->so_rcv.sb_so = so->so_snd.sb_so = so;
                    194:        TAILQ_INIT(&so->so_evlist);
                    195:        *aso = so;
                    196:        return (0);
                    197: }
                    198: 
                    199: int
                    200: sobind(so, nam)
                    201:        struct socket *so;
                    202:        struct sockaddr *nam;
                    203: 
                    204: {
                    205:        struct proc *p = current_proc();
                    206:        int error;
                    207:        struct kextcb *kp;
                    208:        int s = splnet();
                    209: 
                    210:        error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, p);
                    211:        if (error == 0)         /* ??? */
                    212:        {       kp = sotokextcb(so);
                    213:                while (kp)
                    214:                {       if (kp->e_soif && kp->e_soif->sf_sobind)
                    215:                        {       error = (*kp->e_soif->sf_sobind)(so, nam, kp);
                    216:                                if (error)
                    217:                                {       if (error == EJUSTRETURN)
                    218:                                                break;
                    219:                                        splx(s);
                    220:                                        return(error);
                    221:                                }
                    222:                        }
                    223:                        kp = kp->e_next;
                    224:                }
                    225:        }
                    226:        splx(s);
                    227:        return (error);
                    228: }
                    229: 
                    230: void
                    231: sodealloc(so)
                    232:        struct socket *so;
                    233: {
                    234:        so->so_gencnt = ++so_gencnt;
                    235:        _FREE_ZONE(so, sizeof(*so), so->so_zone);
                    236: }
                    237: 
                    238: int
                    239: solisten(so, backlog)
                    240:        register struct socket *so;
                    241:        int backlog;
                    242: 
                    243: {
                    244:        struct kextcb *kp;
                    245:        struct proc *p = current_proc();
                    246:        int s, error;
                    247: 
                    248:        s = splnet();
                    249:        error = (*so->so_proto->pr_usrreqs->pru_listen)(so, p);
                    250:        if (error) {
                    251:                splx(s);
                    252:                return (error);
                    253:        }
                    254:        if (so->so_comp.tqh_first == NULL)
                    255:                so->so_options |= SO_ACCEPTCONN;
                    256:        if (backlog < 0 || backlog > somaxconn)
                    257:                backlog = somaxconn;
                    258:        so->so_qlimit = backlog;
                    259:        kp = sotokextcb(so);
                    260:        while (kp)
                    261:        {       
                    262:                if (kp->e_soif && kp->e_soif->sf_solisten)
                    263:                {       error = (*kp->e_soif->sf_solisten)(so, kp);
                    264:                        if (error)
                    265:                        {       if (error == EJUSTRETURN)
                    266:                                        break;
                    267:                                splx(s);
                    268:                                return(error);
                    269:                        }
                    270:                }
                    271:                kp = kp->e_next;
                    272:        }
                    273: 
                    274:        splx(s);
                    275:        return (0);
                    276: }
                    277: 
                    278: 
                    279: void
                    280: sofree(so)
                    281:        register struct socket *so;
                    282: {      int error;
                    283:        struct kextcb *kp;
                    284:        struct socket *head = so->so_head;
                    285: 
                    286:        kp = sotokextcb(so);
                    287:        while (kp)
                    288:        {       if (kp->e_soif && kp->e_soif->sf_sofree)
                    289:                {       error = (*kp->e_soif->sf_sofree)(so, kp);
                    290:                        if (error)
                    291:                                return; /* void fn */
                    292:                }
                    293:                kp = kp->e_next;
                    294:        }
                    295: 
                    296:        if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
                    297:                return;
                    298:        if (head != NULL) {
                    299:                if (so->so_state & SS_INCOMP) {
                    300:                        TAILQ_REMOVE(&head->so_incomp, so, so_list);
                    301:                        head->so_incqlen--;
                    302:                } else if (so->so_state & SS_COMP) {
                    303:                        TAILQ_REMOVE(&head->so_comp, so, so_list);
                    304:                } else {
                    305:                        panic("sofree: not queued");
                    306:                }
                    307:                head->so_qlen--;
                    308:                so->so_state &= ~(SS_INCOMP|SS_COMP);
                    309:                so->so_head = NULL;
                    310:        }
                    311: 
                    312:        sbrelease(&so->so_snd);
                    313:        sorflush(so);
                    314:        sfilter_term(so);
                    315:        sodealloc(so);
                    316: }
                    317: 
                    318: /*
                    319:  * Close a socket on last file table reference removal.
                    320:  * Initiate disconnect if connected.
                    321:  * Free socket when disconnect complete.
                    322:  */
                    323: int
                    324: soclose(so)
                    325:        register struct socket *so;
                    326: {
                    327:        int s = splnet();               /* conservative */
                    328:        int error = 0;
                    329:        struct kextcb *kp;
                    330: 
                    331: #if FB31SIG
                    332:        funsetown(so->so_pgid);
                    333: #endif
                    334:        kp = sotokextcb(so);
                    335:        while (kp)
                    336:        {       if (kp->e_soif && kp->e_soif->sf_soclose)
                    337:                {       error = (*kp->e_soif->sf_soclose)(so, kp);
                    338:                        if (error)
                    339:                        {       splx(s);
                    340:                                return((error == EJUSTRETURN) ? 0 : error);
                    341:                        }
                    342:                }
                    343:                kp = kp->e_next;
                    344:        }
                    345: 
                    346:        if (so->so_options & SO_ACCEPTCONN) {
                    347:                struct socket *sp, *sonext;
                    348: 
                    349:                for (sp = so->so_incomp.tqh_first; sp != NULL; sp = sonext) {
                    350:                        sonext = sp->so_list.tqe_next;
                    351:                        (void) soabort(sp);
                    352:                }
                    353:                for (sp = so->so_comp.tqh_first; sp != NULL; sp = sonext) {
                    354:                        sonext = sp->so_list.tqe_next;
                    355:                        (void) soabort(sp);
                    356:                }
                    357:        }
                    358:        if (so->so_pcb == 0)
                    359:                goto discard;
                    360:        if (so->so_state & SS_ISCONNECTED) {
                    361:                if ((so->so_state & SS_ISDISCONNECTING) == 0) {
                    362:                        error = sodisconnect(so);
                    363:                        if (error)
                    364:                                goto drop;
                    365:                }
                    366:                if (so->so_options & SO_LINGER) {
                    367:                        if ((so->so_state & SS_ISDISCONNECTING) &&
                    368:                            (so->so_state & SS_NBIO))
                    369:                                goto drop;
                    370:                        while (so->so_state & SS_ISCONNECTED) {
                    371:                                error = tsleep((caddr_t)&so->so_timeo,
                    372:                                    PSOCK | PCATCH, "soclos", so->so_linger);
                    373:                                if (error)
                    374:                                        break;
                    375:                        }
                    376:                }
                    377:        }
                    378: drop:
                    379:        if (so->so_pcb) {
                    380:                int error2 = (*so->so_proto->pr_usrreqs->pru_detach)(so);
                    381:                if (error == 0)
                    382:                        error = error2;
                    383:        }
                    384: discard:
                    385:        if (so->so_state & SS_NOFDREF)
                    386:                panic("soclose: NOFDREF");
                    387:        so->so_state |= SS_NOFDREF;
                    388:        so->so_proto->pr_domain->dom_refs--;
                    389:        evsofree(so);
                    390:        sofree(so);
                    391:        splx(s);
                    392:        return (error);
                    393: }
                    394: 
                    395: /*
                    396:  * Must be called at splnet...
                    397:  */
                    398: int
                    399: soabort(so)
                    400:        struct socket *so;
                    401: {
                    402: 
                    403:        return (*so->so_proto->pr_usrreqs->pru_abort)(so);
                    404: }
                    405: 
                    406: int
                    407: soaccept(so, nam)
                    408:        register struct socket *so;
                    409:        struct sockaddr **nam;
                    410: {      int s = splnet();
                    411:        int error;
                    412:        struct kextcb *kp;
                    413: 
                    414:        if ((so->so_state & SS_NOFDREF) == 0)
                    415:                panic("soaccept: !NOFDREF");
                    416:        so->so_state &= ~SS_NOFDREF;
                    417:        error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam);
                    418:        if (error == 0)
                    419:        {       kp = sotokextcb(so);
                    420:                while (kp) {
                    421:                        if (kp->e_soif && kp->e_soif->sf_soaccept)
                    422:                        {       error = (*kp->e_soif->sf_soaccept)(so, nam, kp);
                    423:                                if (error)
                    424:                                {       if (error == EJUSTRETURN)
                    425:                                                break;
                    426:                                        splx(s);
                    427:                                        return(error);
                    428:                                }
                    429:                        }
                    430:                        kp = kp->e_next;
                    431:                }
                    432:        }
                    433:     
                    434:     
                    435:        splx(s);
                    436:        return (error);
                    437: }
                    438: 
                    439: int
                    440: soconnect(so, nam)
                    441:        register struct socket *so;
                    442:        struct sockaddr *nam;
                    443: 
                    444: {
                    445:        int s;
                    446:        int error;
                    447:        struct proc *p = current_proc();
                    448:        struct kextcb *kp;
                    449: 
                    450:        if (so->so_options & SO_ACCEPTCONN)
                    451:                return (EOPNOTSUPP);
                    452:        s = splnet();
                    453:        /*
                    454:         * If protocol is connection-based, can only connect once.
                    455:         * Otherwise, if connected, try to disconnect first.
                    456:         * This allows user to disconnect by connecting to, e.g.,
                    457:         * a null address.
                    458:         */
                    459:        if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
                    460:            ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
                    461:            (error = sodisconnect(so))))
                    462:                error = EISCONN;
                    463:        else {
                    464:                error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, p);
                    465:                if (error == 0)
                    466:                {       
                    467:                        kp = sotokextcb(so);
                    468:                        while (kp)
                    469:                        {       
                    470:                                if (kp->e_soif && kp->e_soif->sf_soconnect)
                    471:                                {       error = (*kp->e_soif->sf_soconnect)(so, nam, kp);
                    472:                                        if (error)
                    473:                                        {       if (error == EJUSTRETURN)
                    474:                                                        break;
                    475:                                                splx(s);
                    476:                                                return(error);
                    477:                                        }
                    478:                                }
                    479:                                kp = kp->e_next;
                    480:                        }
                    481:                }
                    482:        }
                    483: 
                    484:        splx(s);
                    485:        return (error);
                    486: }
                    487: 
                    488: int
                    489: soconnect2(so1, so2)
                    490:        register struct socket *so1;
                    491:        struct socket *so2;
                    492: {
                    493:        int s = splnet();
                    494:        int error;
                    495:        struct kextcb *kp;
                    496: 
                    497:        error = (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2);
                    498:        if (error == 0)
                    499:        {       kp = sotokextcb(so1);
                    500:                while (kp)
                    501:                {       if (kp->e_soif && kp->e_soif->sf_soconnect2)
                    502:                        {       error = (*kp->e_soif->sf_soconnect2)(so1, so2, kp);
                    503:                                if (error)
                    504:                                {       if (error == EJUSTRETURN)
                    505:                                                break;
                    506:                                        splx(s);
                    507:                                        return(error);
                    508:                                }
                    509:                        }
                    510:                        kp = kp->e_next;
                    511:                }
                    512:        }
                    513:        splx(s);
                    514:        return (error);
                    515: }
                    516: 
                    517: int
                    518: sodisconnect(so)
                    519:        register struct socket *so;
                    520: {
                    521:        int s = splnet();
                    522:        int error;
                    523:        struct kextcb *kp;
                    524: 
                    525:        if ((so->so_state & SS_ISCONNECTED) == 0) {
                    526:                error = ENOTCONN;
                    527:                goto bad;
                    528:        }
                    529:        if (so->so_state & SS_ISDISCONNECTING) {
                    530:                error = EALREADY;
                    531:                goto bad;
                    532:        }
                    533:        error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so);
                    534: 
                    535:        if (error == 0)
                    536:        {       kp = sotokextcb(so);
                    537:                while (kp)
                    538:                {       if (kp->e_soif && kp->e_soif->sf_sodisconnect)
                    539:                        {       error = (*kp->e_soif->sf_sodisconnect)(so, kp);
                    540:                                if (error)
                    541:                                {       if (error == EJUSTRETURN)
                    542:                                                break;
                    543:                                        splx(s);
                    544:                                        return(error);
                    545:                                }
                    546:                        }
                    547:                        kp = kp->e_next;
                    548:                }
                    549:        }
                    550: 
                    551: bad:
                    552:        splx(s);
                    553:        return (error);
                    554: }
                    555: 
                    556: #define        SBLOCKWAIT(f)   (((f) & MSG_DONTWAIT) ? M_DONTWAIT : M_WAIT)
                    557: /*
                    558:  * Send on a socket.
                    559:  * If send must go all at once and message is larger than
                    560:  * send buffering, then hard error.
                    561:  * Lock against other senders.
                    562:  * If must go all at once and not enough room now, then
                    563:  * inform user that this would block and do nothing.
                    564:  * Otherwise, if nonblocking, send as much as possible.
                    565:  * The data to be sent is described by "uio" if nonzero,
                    566:  * otherwise by the mbuf chain "top" (which must be null
                    567:  * if uio is not).  Data provided in mbuf chain must be small
                    568:  * enough to send all at once.
                    569:  *
                    570:  * Returns nonzero on error, timeout or signal; callers
                    571:  * must check for short counts if EINTR/ERESTART are returned.
                    572:  * Data and control buffers are freed on return.
                    573:  * Experiment:
                    574:  * MSG_HOLD: go thru most of sosend(), but just enqueue the mbuf
                    575:  * MSG_SEND: go thru as for MSG_HOLD on current fragment, then
                    576:  *  point at the mbuf chain being constructed and go from there.
                    577:  */
                    578: int
                    579: sosend(so, addr, uio, top, control, flags)
                    580:        register struct socket *so;
                    581:        struct sockaddr *addr;
                    582:        struct uio *uio;
                    583:        struct mbuf *top;
                    584:        struct mbuf *control;
                    585:        int flags;
                    586: 
                    587: {
                    588:        struct mbuf **mp;
                    589:        register struct mbuf *m;
                    590:        register long space, len, resid;
                    591:        int clen = 0, error, s, dontroute, mlen, sendflags;
                    592:        int atomic = sosendallatonce(so) || top;
                    593:        struct proc *p = current_proc();
                    594:        struct kextcb *kp;
                    595: 
                    596:        if (uio)
                    597:                resid = uio->uio_resid;
                    598:        else
                    599:                resid = top->m_pkthdr.len;
                    600: 
                    601:        KERNEL_DEBUG((DBG_FNC_SOSEND | DBG_FUNC_START),
                    602:                     so,
                    603:                     resid,
                    604:                     so->so_snd.sb_cc,
                    605:                     so->so_snd.sb_lowat,
                    606:                     so->so_snd.sb_hiwat);
                    607: 
                    608:        /*
                    609:         * In theory resid should be unsigned.
                    610:         * However, space must be signed, as it might be less than 0
                    611:         * if we over-committed, and we must use a signed comparison
                    612:         * of space and resid.  On the other hand, a negative resid
                    613:         * causes us to loop sending 0-length segments to the protocol.
                    614:         *
                    615:         * Also check to make sure that MSG_EOR isn't used on SOCK_STREAM
                    616:         * type sockets since that's an error.
                    617:         */
                    618:        if (resid < 0 || so->so_type == SOCK_STREAM && (flags & MSG_EOR)) {
                    619:                error = EINVAL;
                    620:                goto out;
                    621:        }
                    622: 
                    623:        dontroute =
                    624:            (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
                    625:            (so->so_proto->pr_flags & PR_ATOMIC);
                    626:        if (p)
                    627:                p->p_stats->p_ru.ru_msgsnd++;
                    628:        if (control)
                    629:                clen = control->m_len;
                    630: #define        snderr(errno)   { error = errno; splx(s); goto release; }
                    631: 
                    632: restart:
                    633:        error = sblock(&so->so_snd, SBLOCKWAIT(flags));
                    634:        if (error)
                    635:                goto out;
                    636:        do {
                    637:                s = splnet();
                    638:                if (so->so_state & SS_CANTSENDMORE)
                    639:                        snderr(EPIPE);
                    640:                if (so->so_error) {
                    641:                        error = so->so_error;
                    642:                        so->so_error = 0;
                    643:                        splx(s);
                    644:                        goto release;
                    645:                }
                    646:                if ((so->so_state & SS_ISCONNECTED) == 0) {
                    647:                        /*
                    648:                         * `sendto' and `sendmsg' is allowed on a connection-
                    649:                         * based socket if it supports implied connect.
                    650:                         * Return ENOTCONN if not connected and no address is
                    651:                         * supplied.
                    652:                         */
                    653:                        if ((so->so_proto->pr_flags & PR_CONNREQUIRED) &&
                    654:                            (so->so_proto->pr_flags & PR_IMPLOPCL) == 0) {
                    655:                                if ((so->so_state & SS_ISCONFIRMING) == 0 &&
                    656:                                    !(resid == 0 && clen != 0))
                    657:                                        snderr(ENOTCONN);
                    658:                        } else if (addr == 0 && !(flags&MSG_HOLD))
                    659:                            snderr(so->so_proto->pr_flags & PR_CONNREQUIRED ?
                    660:                                   ENOTCONN : EDESTADDRREQ);
                    661:                }
                    662:                space = sbspace(&so->so_snd);
                    663:                if (flags & MSG_OOB)
                    664:                        space += 1024;
                    665:                if ((atomic && resid > so->so_snd.sb_hiwat) ||
                    666:                    clen > so->so_snd.sb_hiwat)
                    667:                        snderr(EMSGSIZE);
                    668:                if (space < resid + clen && uio &&
                    669:                    (atomic || space < so->so_snd.sb_lowat || space < clen)) {
                    670:                        if (so->so_state & SS_NBIO)
                    671:                                snderr(EWOULDBLOCK);
                    672:                        sbunlock(&so->so_snd);
                    673:                        error = sbwait(&so->so_snd);
                    674:                        splx(s);
                    675:                        if (error)
                    676:                                goto out;
                    677:                        goto restart;
                    678:                }
                    679:                splx(s);
                    680:                mp = &top;
                    681:                space -= clen;
                    682:                do {
                    683:                    if (uio == NULL) {
                    684:                        /*
                    685:                         * Data is prepackaged in "top".
                    686:                         */
                    687:                        resid = 0;
                    688:                        if (flags & MSG_EOR)
                    689:                                top->m_flags |= M_EOR;
                    690:                    } else do {
                    691:                        KERNEL_DEBUG(DBG_FNC_SOSEND | DBG_FUNC_NONE, -1, 0, 0, 0, 0);
                    692:                        if (top == 0) {
                    693:                                MGETHDR(m, M_WAIT, MT_DATA);
                    694:                                mlen = MHLEN;
                    695:                                m->m_pkthdr.len = 0;
                    696:                                m->m_pkthdr.rcvif = (struct ifnet *)0;
                    697:                        } else {
                    698:                                MGET(m, M_WAIT, MT_DATA);
                    699:                                mlen = MLEN;
                    700:                        }
                    701:                        if (resid >= MINCLSIZE) {
                    702:                                MCLGET(m, M_WAIT);
                    703:                                if ((m->m_flags & M_EXT) == 0)
                    704:                                        goto nopages;
                    705:                                mlen = MCLBYTES;
                    706:                                len = min(min(mlen, resid), space);
                    707:                        } else {
                    708: nopages:
                    709:                                len = min(min(mlen, resid), space);
                    710:                                /*
                    711:                                 * For datagram protocols, leave room
                    712:                                 * for protocol headers in first mbuf.
                    713:                                 */
                    714:                                if (atomic && top == 0 && len < mlen)
                    715:                                        MH_ALIGN(m, len);
                    716:                        }
                    717:                        KERNEL_DEBUG(DBG_FNC_SOSEND | DBG_FUNC_NONE, -1, 0, 0, 0, 0);
                    718:                        space -= len;
                    719:                        error = uiomove(mtod(m, caddr_t), (int)len, uio);
                    720:                        resid = uio->uio_resid;
                    721:                        
                    722:                        m->m_len = len;
                    723:                        *mp = m;
                    724:                        top->m_pkthdr.len += len;
                    725:                        if (error)
                    726:                                goto release;
                    727:                        mp = &m->m_next;
                    728:                        if (resid <= 0) {
                    729:                                if (flags & MSG_EOR)
                    730:                                        top->m_flags |= M_EOR;
                    731:                                break;
                    732:                        }
                    733:                    } while (space > 0 && (atomic || resid < MINCLSIZE));
                    734: 
                    735:                    if (flags & (MSG_HOLD|MSG_SEND))
                    736:                    {   /* Enqueue for later, go away if HOLD */
                    737:                        register struct mbuf *mb1;
                    738:                        if (so->so_temp && (flags & MSG_FLUSH))
                    739:                        {       m_freem(so->so_temp);
                    740:                                so->so_temp = NULL;
                    741:                        }
                    742:                        if (so->so_temp)
                    743:                                so->so_tail->m_next = top;
                    744:                        else
                    745:                                so->so_temp = top;
                    746:                        mb1 = top;
                    747:                        while (mb1->m_next)
                    748:                                mb1 = mb1->m_next;
                    749:                        so->so_tail = mb1;
                    750:                        if (flags&MSG_HOLD)
                    751:                        {       top = NULL;
                    752:                                goto release;
                    753:                        }
                    754:                        top = so->so_temp;
                    755:                    }
                    756:                    if (dontroute)
                    757:                            so->so_options |= SO_DONTROUTE;
                    758:                    s = splnet();                               /* XXX */
                    759:                    kp = sotokextcb(so);
                    760:                    /* Compute flags here, for pru_send and NKEs */
                    761:                    sendflags = (flags & MSG_OOB) ? PRUS_OOB :
                    762:                        /*
                    763:                         * If the user set MSG_EOF, the protocol
                    764:                         * understands this flag and nothing left to
                    765:                         * send then use PRU_SEND_EOF instead of PRU_SEND.
                    766:                         */
                    767:                        ((flags & MSG_EOF) &&
                    768:                         (so->so_proto->pr_flags & PR_IMPLOPCL) &&
                    769:                         (resid <= 0)) ?
                    770:                                PRUS_EOF :
                    771:                        /* If there is more to send set PRUS_MORETOCOME */
                    772:                        (resid > 0 && space > 0) ? PRUS_MORETOCOME : 0;
                    773:                    while (kp)
                    774:                    {   if (kp->e_soif && kp->e_soif->sf_sosend)
                    775:                        {       error = (*kp->e_soif->sf_sosend)(so, &addr,
                    776:                                                                 &uio, &top,
                    777:                                                                 &control,
                    778:                                                                 &sendflags,
                    779:                                                                 kp);
                    780:                                if (error)
                    781:                                {       if (error == EJUSTRETURN)
                    782:                                        {       sbunlock(&so->so_snd);
                    783:                                                return(0);
                    784:                                        }
                    785:                                        goto release;
                    786:                                }
                    787:                        }
                    788:                        kp = kp->e_next;
                    789:                    }
                    790: 
                    791:                    error = (*so->so_proto->pr_usrreqs->pru_send)(so,
                    792:                        sendflags, top, addr, control, p);
                    793:                    splx(s);
                    794:                    if (flags & MSG_SEND)
                    795:                        so->so_temp = NULL;
                    796: 
                    797:                    if (dontroute)
                    798:                            so->so_options &= ~SO_DONTROUTE;
                    799:                    clen = 0;
                    800:                    control = 0;
                    801:                    top = 0;
                    802:                    mp = &top;
                    803:                    if (error)
                    804:                        goto release;
                    805:                } while (resid && space > 0);
                    806:        } while (resid);
                    807: 
                    808: release:
                    809:        sbunlock(&so->so_snd);
                    810: out:
                    811:        if (top)
                    812:                m_freem(top);
                    813:        if (control)
                    814:                m_freem(control);
                    815: 
                    816:        KERNEL_DEBUG(DBG_FNC_SOSEND | DBG_FUNC_END,
                    817:                     so,
                    818:                     resid,
                    819:                     so->so_snd.sb_cc,
                    820:                     space,
                    821:                     error);
                    822: 
                    823:        return (error);
                    824: }
                    825: 
                    826: /*
                    827:  * Implement receive operations on a socket.
                    828:  * We depend on the way that records are added to the sockbuf
                    829:  * by sbappend*.  In particular, each record (mbufs linked through m_next)
                    830:  * must begin with an address if the protocol so specifies,
                    831:  * followed by an optional mbuf or mbufs containing ancillary data,
                    832:  * and then zero or more mbufs of data.
                    833:  * In order to avoid blocking network interrupts for the entire time here,
                    834:  * we splx() while doing the actual copy to user space.
                    835:  * Although the sockbuf is locked, new data may still be appended,
                    836:  * and thus we must maintain consistency of the sockbuf during that time.
                    837:  *
                    838:  * The caller may receive the data as a single mbuf chain by supplying
                    839:  * an mbuf **mp0 for use in returning the chain.  The uio is then used
                    840:  * only for the count in uio_resid.
                    841:  */
                    842: int
                    843: soreceive(so, psa, uio, mp0, controlp, flagsp)
                    844:        register struct socket *so;
                    845:        struct sockaddr **psa;
                    846:        struct uio *uio;
                    847:        struct mbuf **mp0;
                    848:        struct mbuf **controlp;
                    849:        int *flagsp;
                    850: {
                    851:        register struct mbuf *m, **mp;
                    852:        register int flags, len, error, s, offset;
                    853:        struct protosw *pr = so->so_proto;
                    854:        struct mbuf *nextrecord;
                    855:        int moff, type = 0;
                    856:        int orig_resid = uio->uio_resid;
                    857:        struct kextcb *kp;
                    858:        
                    859:        KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_START,
                    860:                     so,
                    861:                     uio->uio_resid,
                    862:                     so->so_rcv.sb_cc,
                    863:                     so->so_rcv.sb_lowat,
                    864:                     so->so_rcv.sb_hiwat);
                    865: 
                    866:        kp = sotokextcb(so);
                    867:        while (kp)
                    868:        {       if (kp->e_soif && kp->e_soif->sf_soreceive)
                    869:                {       error = (*kp->e_soif->sf_soreceive)(so, psa, &uio,
                    870:                                                            mp0, controlp,
                    871:                                                            flagsp, kp);
                    872:                        if (error)
                    873:                                return((error == EJUSTRETURN) ? 0 : error);
                    874:                }
                    875:                kp = kp->e_next;
                    876:        }
                    877: 
                    878:        mp = mp0;
                    879:        if (psa)
                    880:                *psa = 0;
                    881:        if (controlp)
                    882:                *controlp = 0;
                    883:        if (flagsp)
                    884:                flags = *flagsp &~ MSG_EOR;
                    885:        else
                    886:                flags = 0;
                    887:        if (flags & MSG_OOB) {
                    888:                m = m_get(M_WAIT, MT_DATA);
                    889:                error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK);
                    890:                if (error)
                    891:                        goto bad;
                    892:                do {
                    893:                        error = uiomove(mtod(m, caddr_t),
                    894:                            (int) min(uio->uio_resid, m->m_len), uio);
                    895:                        m = m_free(m);
                    896:                } while (uio->uio_resid && error == 0 && m);
                    897: bad:
                    898:                if (m)
                    899:                        m_freem(m);
                    900:                
                    901:                KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END, error,0,0,0,0);
                    902:                return (error);
                    903:        }
                    904:        if (mp)
                    905:                *mp = (struct mbuf *)0;
                    906:        if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
                    907:                (*pr->pr_usrreqs->pru_rcvd)(so, 0);
                    908: 
                    909: restart:
                    910:        if (error = sblock(&so->so_rcv, SBLOCKWAIT(flags)))
                    911:        {
                    912:                KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END, error,0,0,0,0);
                    913:                return (error);
                    914:        }
                    915:        s = splnet();
                    916: 
                    917:        m = so->so_rcv.sb_mb;
                    918:        /*
                    919:         * If we have less data than requested, block awaiting more
                    920:         * (subject to any timeout) if:
                    921:         *   1. the current count is less than the low water mark, or
                    922:         *   2. MSG_WAITALL is set, and it is possible to do the entire
                    923:         *      receive operation at once if we block (resid <= hiwat).
                    924:         *   3. MSG_DONTWAIT is not set
                    925:         * If MSG_WAITALL is set but resid is larger than the receive buffer,
                    926:         * we have to do the receive in sections, and thus risk returning
                    927:         * a short count if a timeout or signal occurs after we start.
                    928:         */
                    929:        if (m == 0 || (((flags & MSG_DONTWAIT) == 0 &&
                    930:            so->so_rcv.sb_cc < uio->uio_resid) &&
                    931:            (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
                    932:            ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
                    933:            m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) {
                    934:                KASSERT(m != 0 || !so->so_rcv.sb_cc, ("receive 1"));
                    935:                if (so->so_error) {
                    936:                        if (m)
                    937:                                goto dontblock;
                    938:                        error = so->so_error;
                    939:                        if ((flags & MSG_PEEK) == 0)
                    940:                                so->so_error = 0;
                    941:                        goto release;
                    942:                }
                    943:                if (so->so_state & SS_CANTRCVMORE) {
                    944:                        if (m)
                    945:                                goto dontblock;
                    946:                        else
                    947:                                goto release;
                    948:                }
                    949:                for (; m; m = m->m_next)
                    950:                        if (m->m_type == MT_OOBDATA  || (m->m_flags & M_EOR)) {
                    951:                                m = so->so_rcv.sb_mb;
                    952:                                goto dontblock;
                    953:                        }
                    954:                if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
                    955:                    (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
                    956:                        error = ENOTCONN;
                    957:                        goto release;
                    958:                }
                    959:                if (uio->uio_resid == 0)
                    960:                        goto release;
                    961:                if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
                    962:                        error = EWOULDBLOCK;
                    963:                        goto release;
                    964:                }
                    965:                sbunlock(&so->so_rcv);
                    966:                if (socket_debug)
                    967:                    printf("Waiting for socket data\n");
                    968:                error = sbwait(&so->so_rcv);
                    969:                if (socket_debug)
                    970:                    printf("SORECEIVE - sbwait returned %d\n", error);
                    971:                splx(s);
                    972:                if (error)
                    973:                {
                    974:                    KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END, error,0,0,0,0);
                    975:                    return (error);
                    976:                }
                    977:                goto restart;
                    978:        }
                    979: dontblock:
                    980: #ifdef notyet /* XXXX */
                    981:        if (uio->uio_procp)
                    982:                uio->uio_procp->p_stats->p_ru.ru_msgrcv++;
                    983: #endif
                    984:        nextrecord = m->m_nextpkt;
                    985:        if ((pr->pr_flags & PR_ADDR) && m->m_type == MT_SONAME) {
                    986:                KASSERT(m->m_type == MT_SONAME, ("receive 1a"));
                    987:                orig_resid = 0;
                    988:                if (psa)
                    989:                        *psa = dup_sockaddr(mtod(m, struct sockaddr *),
                    990:                                            mp0 == 0);
                    991:                if (flags & MSG_PEEK) {
                    992:                        m = m->m_next;
                    993:                } else {
                    994:                        sbfree(&so->so_rcv, m);
                    995:                        MFREE(m, so->so_rcv.sb_mb);
                    996:                        m = so->so_rcv.sb_mb;
                    997:                }
                    998:        }
                    999:        while (m && m->m_type == MT_CONTROL && error == 0) {
                   1000:                if (flags & MSG_PEEK) {
                   1001:                        if (controlp)
                   1002:                                *controlp = m_copy(m, 0, m->m_len);
                   1003:                        m = m->m_next;
                   1004:                } else {
                   1005:                        sbfree(&so->so_rcv, m);
                   1006:                        if (controlp) {
                   1007:                                if (pr->pr_domain->dom_externalize &&
                   1008:                                    mtod(m, struct cmsghdr *)->cmsg_type ==
                   1009:                                    SCM_RIGHTS)
                   1010:                                   error = (*pr->pr_domain->dom_externalize)(m);
                   1011:                                *controlp = m;
                   1012:                                so->so_rcv.sb_mb = m->m_next;
                   1013:                                m->m_next = 0;
                   1014:                                m = so->so_rcv.sb_mb;
                   1015:                        } else {
                   1016:                                MFREE(m, so->so_rcv.sb_mb);
                   1017:                                m = so->so_rcv.sb_mb;
                   1018:                        }
                   1019:                }
                   1020:                if (controlp) {
                   1021:                        orig_resid = 0;
                   1022:                        controlp = &(*controlp)->m_next;
                   1023:                }
                   1024:        }
                   1025:        if (m) {
                   1026:                if ((flags & MSG_PEEK) == 0)
                   1027:                        m->m_nextpkt = nextrecord;
                   1028:                type = m->m_type;
                   1029:                if (type == MT_OOBDATA)
                   1030:                        flags |= MSG_OOB;
                   1031:        }
                   1032:        moff = 0;
                   1033:        offset = 0;
                   1034:        while (m && uio->uio_resid > 0 && error == 0) {
                   1035:                if (m->m_type == MT_OOBDATA) {
                   1036:                        if (type != MT_OOBDATA)
                   1037:                                break;
                   1038:                } else if (type == MT_OOBDATA)
                   1039:                        break;
                   1040: #if 0
                   1041: /*
                   1042:  * This assertion needs rework.  The trouble is Appletalk is uses many
                   1043:  * mbuf types (NOT listed in mbuf.h!) which will trigger this panic.
                   1044:  * For now just remove the assertion...  CSM 9/98
                   1045:  */
                   1046:                else
                   1047:                    KASSERT(m->m_type == MT_DATA || m->m_type == MT_HEADER,
                   1048:                        ("receive 3"));
                   1049: #endif
                   1050:                so->so_state &= ~SS_RCVATMARK;
                   1051:                len = uio->uio_resid;
                   1052:                if (so->so_oobmark && len > so->so_oobmark - offset)
                   1053:                        len = so->so_oobmark - offset;
                   1054:                if (len > m->m_len - moff)
                   1055:                        len = m->m_len - moff;
                   1056:                /*
                   1057:                 * If mp is set, just pass back the mbufs.
                   1058:                 * Otherwise copy them out via the uio, then free.
                   1059:                 * Sockbuf must be consistent here (points to current mbuf,
                   1060:                 * it points to next record) when we drop priority;
                   1061:                 * we must note any additions to the sockbuf when we
                   1062:                 * block interrupts again.
                   1063:                 */
                   1064:                if (mp == 0) {
                   1065:                        splx(s);
                   1066:                        error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
                   1067:                        s = splnet();
                   1068:                        if (error)
                   1069:                                goto release;
                   1070:                } else
                   1071:                        uio->uio_resid -= len;
                   1072:                if (len == m->m_len - moff) {
                   1073:                        if (m->m_flags & M_EOR)
                   1074:                                flags |= MSG_EOR;
                   1075:                        if (flags & MSG_PEEK) {
                   1076:                                m = m->m_next;
                   1077:                                moff = 0;
                   1078:                        } else {
                   1079:                                nextrecord = m->m_nextpkt;
                   1080:                                sbfree(&so->so_rcv, m);
                   1081:                                if (mp) {
                   1082:                                        *mp = m;
                   1083:                                        mp = &m->m_next;
                   1084:                                        so->so_rcv.sb_mb = m = m->m_next;
                   1085:                                        *mp = (struct mbuf *)0;
                   1086:                                } else {
                   1087:                                        MFREE(m, so->so_rcv.sb_mb);
                   1088:                                        m = so->so_rcv.sb_mb;
                   1089:                                }
                   1090:                                if (m)
                   1091:                                        m->m_nextpkt = nextrecord;
                   1092:                        }
                   1093:                } else {
                   1094:                        if (flags & MSG_PEEK)
                   1095:                                moff += len;
                   1096:                        else {
                   1097:                                if (mp)
                   1098:                                        *mp = m_copym(m, 0, len, M_WAIT);
                   1099:                                m->m_data += len;
                   1100:                                m->m_len -= len;
                   1101:                                so->so_rcv.sb_cc -= len;
                   1102:                        }
                   1103:                }
                   1104:                if (so->so_oobmark) {
                   1105:                        if ((flags & MSG_PEEK) == 0) {
                   1106:                                so->so_oobmark -= len;
                   1107:                                if (so->so_oobmark == 0) {
                   1108:                                        so->so_state |= SS_RCVATMARK;
                   1109:                                        postevent(so, 0, EV_OOB);
                   1110:                                        break;
                   1111:                                }
                   1112:                        } else {
                   1113:                                offset += len;
                   1114:                                if (offset == so->so_oobmark)
                   1115:                                        break;
                   1116:                        }
                   1117:                }
                   1118:                if (flags & MSG_EOR)
                   1119:                        break;
                   1120:                /*
                   1121:                 * If the MSG_WAITALL flag is set (for non-atomic socket),
                   1122:                 * we must not quit until "uio->uio_resid == 0" or an error
                   1123:                 * termination.  If a signal/timeout occurs, return
                   1124:                 * with a short count but without error.
                   1125:                 * Keep sockbuf locked against other readers.
                   1126:                 */
                   1127:                while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
                   1128:                    !sosendallatonce(so) && !nextrecord) {
                   1129:                        if (so->so_error || so->so_state & SS_CANTRCVMORE)
                   1130:                                break;
                   1131:                        error = sbwait(&so->so_rcv);
                   1132:                        if (error) {
                   1133:                                sbunlock(&so->so_rcv);
                   1134:                                splx(s);
                   1135:                                KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END, 0,0,0,0,0);
                   1136:                                return (0);
                   1137:                        }
                   1138:                        m = so->so_rcv.sb_mb;
                   1139:                        if (m)
                   1140:                                nextrecord = m->m_nextpkt;
                   1141:                }
                   1142:        }
                   1143: 
                   1144:        if (m && pr->pr_flags & PR_ATOMIC) {
                   1145:                if (so->so_options & SO_DONTTRUNC)
                   1146:                        flags |= MSG_RCVMORE;
                   1147:                else
                   1148:                {       flags |= MSG_TRUNC;
                   1149:                        if ((flags & MSG_PEEK) == 0)
                   1150:                                (void) sbdroprecord(&so->so_rcv);
                   1151:                }
                   1152:        }
                   1153:        if ((flags & MSG_PEEK) == 0) {
                   1154:                if (m == 0)
                   1155:                        so->so_rcv.sb_mb = nextrecord;
                   1156:                if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
                   1157:                        (*pr->pr_usrreqs->pru_rcvd)(so, flags);
                   1158:        }
                   1159:        if ((so->so_options & SO_WANTMORE) && so->so_rcv.sb_cc > 0)
                   1160:                flags |= MSG_HAVEMORE;
                   1161:        if (orig_resid == uio->uio_resid && orig_resid &&
                   1162:            (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
                   1163:                sbunlock(&so->so_rcv);
                   1164:                splx(s);
                   1165:                goto restart;
                   1166:        }
                   1167: 
                   1168:        if (flagsp)
                   1169:                *flagsp |= flags;
                   1170: release:
                   1171:        sbunlock(&so->so_rcv);
                   1172:        splx(s);
                   1173: 
                   1174:        KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END,
                   1175:                     so,
                   1176:                     uio->uio_resid,
                   1177:                     so->so_rcv.sb_cc,
                   1178:                     0,
                   1179:                     error);
                   1180: 
                   1181:        return (error);
                   1182: }
                   1183: 
                   1184: int
                   1185: soshutdown(so, how)
                   1186:        register struct socket *so;
                   1187:        register int how;
                   1188: {
                   1189:        register struct protosw *pr = so->so_proto;
                   1190:        struct kextcb *kp;
                   1191:        int ret;
                   1192: 
                   1193:        kp = sotokextcb(so);
                   1194:        while (kp)
                   1195:        {       if (kp->e_soif && kp->e_soif->sf_soshutdown)
                   1196:                {       ret = (*kp->e_soif->sf_soshutdown)(so, how, kp);
                   1197:                        if (ret)
                   1198:                                return((ret == EJUSTRETURN) ? 0 : ret);
                   1199:                }
                   1200:                kp = kp->e_next;
                   1201:        }
                   1202: 
                   1203:        how++;
                   1204:        if (how & FREAD) {
                   1205:                sorflush(so);
                   1206:                postevent(so, 0, EV_RCLOSED);
                   1207:        }
                   1208:        if (how & FWRITE) {
                   1209:            ret = ((*pr->pr_usrreqs->pru_shutdown)(so));
                   1210:            postevent(so, 0, EV_WCLOSED);
                   1211:            return(ret);
                   1212:        }
                   1213:        return (0);
                   1214: }
                   1215: 
                   1216: void
                   1217: sorflush(so)
                   1218:        register struct socket *so;
                   1219: {
                   1220:        register struct sockbuf *sb = &so->so_rcv;
                   1221:        register struct protosw *pr = so->so_proto;
                   1222:        register int s, error;
                   1223:        struct sockbuf asb;
                   1224:        struct kextcb *kp;
                   1225: 
                   1226:        kp = sotokextcb(so);
                   1227:        while (kp)
                   1228:        {       if (kp->e_soif && kp->e_soif->sf_sorflush)
                   1229:                {       if ((*kp->e_soif->sf_sorflush)(so, kp))
                   1230:                                return;
                   1231:                }
                   1232:                kp = kp->e_next;
                   1233:        }
                   1234: 
                   1235:        sb->sb_flags |= SB_NOINTR;
                   1236:        (void) sblock(sb, M_WAIT);
                   1237:        s = splimp();
                   1238:        socantrcvmore(so);
                   1239:        sbunlock(sb);
                   1240:        asb = *sb;
                   1241:        bzero((caddr_t)sb, sizeof (*sb));
                   1242:        splx(s);
                   1243:        if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
                   1244:                (*pr->pr_domain->dom_dispose)(asb.sb_mb);
                   1245:        sbrelease(&asb);
                   1246: }
                   1247: 
                   1248: /*
                   1249:  * Perhaps this routine, and sooptcopyout(), below, ought to come in
                   1250:  * an additional variant to handle the case where the option value needs
                   1251:  * to be some kind of integer, but not a specific size.
                   1252:  * In addition to their use here, these functions are also called by the
                   1253:  * protocol-level pr_ctloutput() routines.
                   1254:  */
                   1255: int
                   1256: sooptcopyin(sopt, buf, len, minlen)
                   1257:        struct  sockopt *sopt;
                   1258:        void    *buf;
                   1259:        size_t  len;
                   1260:        size_t  minlen;
                   1261: {
                   1262:        size_t  valsize;
                   1263: 
                   1264:        /*
                   1265:         * If the user gives us more than we wanted, we ignore it,
                   1266:         * but if we don't get the minimum length the caller
                   1267:         * wants, we return EINVAL.  On success, sopt->sopt_valsize
                   1268:         * is set to however much we actually retrieved.
                   1269:         */
                   1270:        if ((valsize = sopt->sopt_valsize) < minlen)
                   1271:                return EINVAL;
                   1272:        if (valsize > len)
                   1273:                sopt->sopt_valsize = valsize = len;
                   1274: 
                   1275:        if (sopt->sopt_p != 0)
                   1276:                return (copyin(sopt->sopt_val, buf, valsize));
                   1277: 
                   1278:        bcopy(sopt->sopt_val, buf, valsize);
                   1279:        return 0;
                   1280: }
                   1281: 
                   1282: int
                   1283: sosetopt(so, sopt)
                   1284:        struct socket *so;
                   1285:        struct sockopt *sopt;
                   1286: {
                   1287:        int     error, optval;
                   1288:        struct  linger l;
                   1289:        struct  timeval tv;
                   1290:        short   val;
                   1291:        struct kextcb *kp;
                   1292: 
                   1293:        kp = sotokextcb(so);
                   1294:        while (kp)
                   1295:        {       if (kp->e_soif && kp->e_soif->sf_socontrol)
                   1296:                {       error = (*kp->e_soif->sf_socontrol)(so, sopt, kp);
                   1297:                        if (error)
                   1298:                                return((error == EJUSTRETURN) ? 0 : error);
                   1299:                }
                   1300:                kp = kp->e_next;
                   1301:        }
                   1302: 
                   1303:        error = 0;
                   1304:        if (sopt->sopt_level != SOL_SOCKET) {
                   1305:                if (so->so_proto && so->so_proto->pr_ctloutput)
                   1306:                        return ((*so->so_proto->pr_ctloutput)
                   1307:                                  (so, sopt));
                   1308:                error = ENOPROTOOPT;
                   1309:        } else {
                   1310:                switch (sopt->sopt_name) {
                   1311:                case SO_LINGER:
                   1312:                        error = sooptcopyin(sopt, &l, sizeof l, sizeof l);
                   1313:                        if (error)
                   1314:                                goto bad;
                   1315: 
                   1316:                        so->so_linger = l.l_linger;
                   1317:                        if (l.l_onoff)
                   1318:                                so->so_options |= SO_LINGER;
                   1319:                        else
                   1320:                                so->so_options &= ~SO_LINGER;
                   1321:                        break;
                   1322: 
                   1323:                case SO_DEBUG:
                   1324:                case SO_KEEPALIVE:
                   1325:                case SO_DONTROUTE:
                   1326:                case SO_USELOOPBACK:
                   1327:                case SO_BROADCAST:
                   1328:                case SO_REUSEADDR:
                   1329:                case SO_REUSEPORT:
                   1330:                case SO_OOBINLINE:
                   1331:                case SO_TIMESTAMP:
                   1332:                case SO_DONTTRUNC:
                   1333:                case SO_WANTMORE:
                   1334:                        error = sooptcopyin(sopt, &optval, sizeof optval,
                   1335:                                            sizeof optval);
                   1336:                        if (error)
                   1337:                                goto bad;
                   1338:                        if (optval)
                   1339:                                so->so_options |= sopt->sopt_name;
                   1340:                        else
                   1341:                                so->so_options &= ~sopt->sopt_name;
                   1342:                        break;
                   1343: 
                   1344:                case SO_SNDBUF:
                   1345:                case SO_RCVBUF:
                   1346:                case SO_SNDLOWAT:
                   1347:                case SO_RCVLOWAT:
                   1348:                        error = sooptcopyin(sopt, &optval, sizeof optval,
                   1349:                                            sizeof optval);
                   1350:                        if (error)
                   1351:                                goto bad;
                   1352: 
                   1353:                        /*
                   1354:                         * Values < 1 make no sense for any of these
                   1355:                         * options, so disallow them.
                   1356:                         */
                   1357:                        if (optval < 1) {
                   1358:                                error = EINVAL;
                   1359:                                goto bad;
                   1360:                        }
                   1361: 
                   1362:                        switch (sopt->sopt_name) {
                   1363:                        case SO_SNDBUF:
                   1364:                        case SO_RCVBUF:
                   1365:                                if (sbreserve(sopt->sopt_name == SO_SNDBUF ?
                   1366:                                              &so->so_snd : &so->so_rcv,
                   1367:                                              (u_long) optval) == 0) {
                   1368:                                        error = ENOBUFS;
                   1369:                                        goto bad;
                   1370:                                }
                   1371:                                break;
                   1372: 
                   1373:                        /*
                   1374:                         * Make sure the low-water is never greater than
                   1375:                         * the high-water.
                   1376:                         */
                   1377:                        case SO_SNDLOWAT:
                   1378:                                so->so_snd.sb_lowat =
                   1379:                                    (optval > so->so_snd.sb_hiwat) ?
                   1380:                                    so->so_snd.sb_hiwat : optval;
                   1381:                                break;
                   1382:                        case SO_RCVLOWAT:
                   1383:                                so->so_rcv.sb_lowat =
                   1384:                                    (optval > so->so_rcv.sb_hiwat) ?
                   1385:                                    so->so_rcv.sb_hiwat : optval;
                   1386:                                break;
                   1387:                        }
                   1388:                        break;
                   1389: 
                   1390:                case SO_SNDTIMEO:
                   1391:                case SO_RCVTIMEO:
                   1392:                        error = sooptcopyin(sopt, &tv, sizeof tv,
                   1393:                                            sizeof tv);
                   1394:                        if (error)
                   1395:                                goto bad;
                   1396: 
                   1397:                        if (tv.tv_sec > SHRT_MAX / hz - hz) {
                   1398:                                error = EDOM;
                   1399:                                goto bad;
                   1400:                        }
                   1401:                        val = tv.tv_sec * hz + tv.tv_usec / tick;
                   1402: 
                   1403:                        switch (sopt->sopt_name) {
                   1404:                        case SO_SNDTIMEO:
                   1405:                                so->so_snd.sb_timeo = val;
                   1406:                                break;
                   1407:                        case SO_RCVTIMEO:
                   1408:                                so->so_rcv.sb_timeo = val;
                   1409:                                break;
                   1410:                        }
                   1411:                        break;
                   1412: 
                   1413:                case SO_NKE:
                   1414:                {       struct so_nke nke;
                   1415:                        struct NFDescriptor *nf1, *nf2 = NULL;
                   1416: 
                   1417:                         error = sooptcopyin(sopt, &nke,
                   1418:                                            sizeof nke, sizeof nke);
                   1419:                        if (error)
                   1420:                          goto bad;
                   1421: 
                   1422:                        error = nke_insert(so, &nke);
                   1423:                        break;
                   1424:                }
                   1425: 
                   1426:                default:
                   1427:                        error = ENOPROTOOPT;
                   1428:                        break;
                   1429:                }
                   1430:                if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
                   1431:                        (void) ((*so->so_proto->pr_ctloutput)
                   1432:                                  (so, sopt));
                   1433:                }
                   1434:        }
                   1435: bad:
                   1436:        return (error);
                   1437: }
                   1438: 
                   1439: /* Helper routine for getsockopt */
                   1440: int
                   1441: sooptcopyout(sopt, buf, len)
                   1442:        struct  sockopt *sopt;
                   1443:        void    *buf;
                   1444:        size_t  len;
                   1445: {
                   1446:        int     error;
                   1447:        size_t  valsize;
                   1448: 
                   1449:        error = 0;
                   1450: 
                   1451:        /*
                   1452:         * Documented get behavior is that we always return a value,
                   1453:         * possibly truncated to fit in the user's buffer.
                   1454:         * Traditional behavior is that we always tell the user
                   1455:         * precisely how much we copied, rather than something useful
                   1456:         * like the total amount we had available for her.
                   1457:         * Note that this interface is not idempotent; the entire answer must
                   1458:         * generated ahead of time.
                   1459:         */
                   1460:        valsize = min(len, sopt->sopt_valsize);
                   1461:        sopt->sopt_valsize = valsize;
                   1462:        if (sopt->sopt_val != 0) {
                   1463:                if (sopt->sopt_p != 0)
                   1464:                        error = copyout(buf, sopt->sopt_val, valsize);
                   1465:                else
                   1466:                        bcopy(buf, sopt->sopt_val, valsize);
                   1467:        }
                   1468:        return error;
                   1469: }
                   1470: 
                   1471: int
                   1472: sogetopt(so, sopt)
                   1473:        struct socket *so;
                   1474:        struct sockopt *sopt;
                   1475: {
                   1476:        int     error, optval;
                   1477:        struct  linger l;
                   1478:        struct  timeval tv;
                   1479:        struct mbuf  *m;
                   1480:        struct kextcb *kp;
                   1481: 
                   1482:        kp = sotokextcb(so);
                   1483:        while (kp)
                   1484:        {       if (kp->e_soif && kp->e_soif->sf_socontrol)
                   1485:                {       error = (*kp->e_soif->sf_socontrol)(so, sopt, kp);
                   1486:                        if (error)
                   1487:                                return((error == EJUSTRETURN) ? 0 : error);
                   1488:                }
                   1489:                kp = kp->e_next;
                   1490:        }
                   1491: 
                   1492:        error = 0;
                   1493:        if (sopt->sopt_level != SOL_SOCKET) {
                   1494:                if (so->so_proto && so->so_proto->pr_ctloutput) {
                   1495:                        return ((*so->so_proto->pr_ctloutput)
                   1496:                                  (so, sopt));
                   1497:                } else
                   1498:                        return (ENOPROTOOPT);
                   1499:        } else {
                   1500:                switch (sopt->sopt_name) {
                   1501:                case SO_LINGER:
                   1502:                        l.l_onoff = so->so_options & SO_LINGER;
                   1503:                        l.l_linger = so->so_linger;
                   1504:                        error = sooptcopyout(sopt, &l, sizeof l);
                   1505:                        break;
                   1506: 
                   1507:                case SO_USELOOPBACK:
                   1508:                case SO_DONTROUTE:
                   1509:                case SO_DEBUG:
                   1510:                case SO_KEEPALIVE:
                   1511:                case SO_REUSEADDR:
                   1512:                case SO_REUSEPORT:
                   1513:                case SO_BROADCAST:
                   1514:                case SO_OOBINLINE:
                   1515:                case SO_TIMESTAMP:
                   1516:                case SO_DONTTRUNC:
                   1517:                case SO_WANTMORE:
                   1518:                        optval = so->so_options & sopt->sopt_name;
                   1519: integer:
                   1520:                        error = sooptcopyout(sopt, &optval, sizeof optval);
                   1521:                        break;
                   1522: 
                   1523:                case SO_TYPE:
                   1524:                        optval = so->so_type;
                   1525:                        goto integer;
                   1526: 
                   1527:                case SO_NREAD:
                   1528:                {       int pkt_total;
                   1529:                        struct mbuf *m1;
                   1530: 
                   1531:                        pkt_total = 0;
                   1532:                        m1 = so->so_rcv.sb_mb;
                   1533:                        if (so->so_proto->pr_flags & PR_ATOMIC)
                   1534:                        {
                   1535: #if 0
                   1536:                                kprintf("SKT CC: %d\n", so->so_rcv.sb_cc);
                   1537: #endif
                   1538:                                while (m1)
                   1539:                                {       if (m1->m_type == MT_DATA)
                   1540:                                                pkt_total += m1->m_len;
                   1541: #if 0
                   1542:                                        kprintf("CNT: %d/%d\n", m1->m_len, pkt_total);
                   1543: #endif
                   1544:                                        m1 = m1->m_next;
                   1545:                                }
                   1546:                                optval = pkt_total;
                   1547:                        } else
                   1548:                                optval = so->so_rcv.sb_cc;
                   1549: #if 0
                   1550:                        kprintf("RTN: %d\n", optval);
                   1551: #endif
                   1552:                        goto integer;
                   1553:                }
                   1554:                case SO_ERROR:
                   1555:                        optval = so->so_error;
                   1556:                        so->so_error = 0;
                   1557:                        goto integer;
                   1558: 
                   1559:                case SO_SNDBUF:
                   1560:                        optval = so->so_snd.sb_hiwat;
                   1561:                        goto integer;
                   1562: 
                   1563:                case SO_RCVBUF:
                   1564:                        optval = so->so_rcv.sb_hiwat;
                   1565:                        goto integer;
                   1566: 
                   1567:                case SO_SNDLOWAT:
                   1568:                        optval = so->so_snd.sb_lowat;
                   1569:                        goto integer;
                   1570: 
                   1571:                case SO_RCVLOWAT:
                   1572:                        optval = so->so_rcv.sb_lowat;
                   1573:                        goto integer;
                   1574: 
                   1575:                case SO_SNDTIMEO:
                   1576:                case SO_RCVTIMEO:
                   1577:                        optval = (sopt->sopt_name == SO_SNDTIMEO ?
                   1578:                                  so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
                   1579: 
                   1580:                        tv.tv_sec = optval / hz;
                   1581:                        tv.tv_usec = (optval % hz) * tick;
                   1582:                        error = sooptcopyout(sopt, &tv, sizeof tv);
                   1583:                        break;                  
                   1584: 
                   1585:                default:
                   1586:                        error = ENOPROTOOPT;
                   1587:                        break;
                   1588:                }
                   1589:                return (error);
                   1590:        }
                   1591: }
                   1592: 
                   1593: void
                   1594: sohasoutofband(so)
                   1595:        register struct socket *so;
                   1596: {
                   1597:        struct proc *p;
                   1598: 
                   1599:        struct kextcb *kp;
                   1600: 
                   1601:        kp = sotokextcb(so);
                   1602:        while (kp)
                   1603:        {       if (kp->e_soif && kp->e_soif->sf_sohasoutofband)
                   1604:                {       if ((*kp->e_soif->sf_sohasoutofband)(so, kp))
                   1605:                                return;
                   1606:                }
                   1607:                kp = kp->e_next;
                   1608:        }
                   1609:        if (so->so_pgid < 0)
                   1610:                gsignal(-so->so_pgid, SIGURG);
                   1611:        else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
                   1612:                psignal(p, SIGURG);
                   1613:        selwakeup(&so->so_rcv.sb_sel);
                   1614: }
                   1615: 
                   1616: /*
                   1617:  * Network filter support
                   1618:  */
                   1619: /* Run the list of filters, creating extension control blocks */
                   1620: sfilter_init(register struct socket *so)
                   1621: {      struct kextcb *kp, **kpp;
                   1622:        struct protosw *prp;
                   1623:        struct NFDescriptor *nfp;
                   1624: 
                   1625:        prp = so->so_proto;
                   1626:        nfp = prp->pr_sfilter.tqh_first; /* non-null */
                   1627:        kpp = &so->so_ext;
                   1628:        kp = NULL;
                   1629:        while (nfp)
                   1630:        {       MALLOC(kp, struct kextcb *, sizeof(*kp),
                   1631:                            M_TEMP, M_WAITOK);
                   1632:                if (kp == NULL)
                   1633:                        return(ENOBUFS); /* so_free will clean up */
                   1634:                *kpp = kp;
                   1635:                kpp = &kp->e_next;
                   1636:                kp->e_next = NULL;
                   1637:                kp->e_fcb = NULL;
                   1638:                kp->e_nfd = nfp;
                   1639:                kp->e_soif = nfp->nf_soif;
                   1640:                kp->e_sout = nfp->nf_soutil;
                   1641:                /*
                   1642:                 * Ignore return value for create
                   1643:                 * Everyone gets a chance at startup
                   1644:                 */
                   1645:                if (kp->e_soif && kp->e_soif->sf_socreate)
                   1646:                        (*kp->e_soif->sf_socreate)(so, prp, kp);
                   1647:                nfp = nfp->nf_next.tqe_next;
                   1648:        }
                   1649:        return(0);
                   1650: }
                   1651: 
                   1652: 
                   1653: /*
                   1654:  * Run the list of filters, freeing extension control blocks
                   1655:  * Assumes the soif/soutil blocks have been handled.
                   1656:  */
                   1657: sfilter_term(struct socket *so)
                   1658: {      struct kextcb *kp, *kp1;
                   1659: 
                   1660:        kp = so->so_ext;
                   1661:        while (kp)
                   1662:        {       kp1 = kp->e_next;
                   1663:                /*
                   1664:                 * Ignore return code on termination; everyone must
                   1665:                 *  get terminated.
                   1666:                 */
                   1667:                if (kp->e_soif && kp->e_soif->sf_sofree)
                   1668:                        kp->e_soif->sf_sofree(so, kp);
                   1669:                FREE(kp, M_TEMP);
                   1670:                kp = kp1;
                   1671:        }
                   1672:        return(0);
                   1673: }
                   1674: 
                   1675: 
                   1676: int
                   1677: sopoll(struct socket *so, int events, struct ucred *cred)
                   1678: {
                   1679:        struct proc *p = current_proc();
                   1680:        int revents = 0;
                   1681:        int s = splnet();
                   1682: 
                   1683:        if (events & (POLLIN | POLLRDNORM))
                   1684:                if (soreadable(so))
                   1685:                        revents |= events & (POLLIN | POLLRDNORM);
                   1686: 
                   1687:        if (events & (POLLOUT | POLLWRNORM))
                   1688:                if (sowriteable(so))
                   1689:                        revents |= events & (POLLOUT | POLLWRNORM);
                   1690: 
                   1691:        if (events & (POLLPRI | POLLRDBAND))
                   1692:                if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
                   1693:                        revents |= events & (POLLPRI | POLLRDBAND);
                   1694: 
                   1695:        if (revents == 0) {
                   1696:                if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
                   1697:                        selrecord(p, &so->so_rcv.sb_sel);
                   1698:                        so->so_rcv.sb_flags |= SB_SEL;
                   1699:                }
                   1700: 
                   1701:                if (events & (POLLOUT | POLLWRNORM)) {
                   1702:                        selrecord(p, &so->so_snd.sb_sel);
                   1703:                        so->so_snd.sb_flags |= SB_SEL;
                   1704:                }
                   1705:        }
                   1706: 
                   1707:        splx(s);
                   1708:        return (revents);
                   1709: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.