Annotation of XNU/bsd/netinet/tcp_usrreq.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: /*
                     23:  * Copyright (c) 1982, 1986, 1988, 1993
                     24:  *     The Regents of the University of California.  All rights reserved.
                     25:  *
                     26:  * Redistribution and use in source and binary forms, with or without
                     27:  * modification, are permitted provided that the following conditions
                     28:  * are met:
                     29:  * 1. Redistributions of source code must retain the above copyright
                     30:  *    notice, this list of conditions and the following disclaimer.
                     31:  * 2. Redistributions in binary form must reproduce the above copyright
                     32:  *    notice, this list of conditions and the following disclaimer in the
                     33:  *    documentation and/or other materials provided with the distribution.
                     34:  * 3. All advertising materials mentioning features or use of this software
                     35:  *    must display the following acknowledgement:
                     36:  *     This product includes software developed by the University of
                     37:  *     California, Berkeley and its contributors.
                     38:  * 4. Neither the name of the University nor the names of its contributors
                     39:  *    may be used to endorse or promote products derived from this software
                     40:  *    without specific prior written permission.
                     41:  *
                     42:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     43:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     44:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     45:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     46:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     47:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     48:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     49:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     50:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     51:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     52:  * SUCH DAMAGE.
                     53:  *
                     54:  *     From: @(#)tcp_usrreq.c  8.2 (Berkeley) 1/3/94
                     55:  */
                     56: 
                     57: #if ISFB31
                     58: #include "opt_tcpdebug.h"
                     59: #endif
                     60: 
                     61: #include <sys/param.h>
                     62: #include <sys/systm.h>
                     63: #include <sys/kernel.h>
                     64: #include <sys/sysctl.h>
                     65: #include <sys/mbuf.h>
                     66: #include <sys/socket.h>
                     67: #include <sys/socketvar.h>
                     68: #include <sys/protosw.h>
                     69: 
                     70: #include <net/if.h>
                     71: #include <net/route.h>
                     72: 
                     73: #include <netinet/in.h>
                     74: #include <netinet/in_systm.h>
                     75: #include <netinet/in_pcb.h>
                     76: #include <netinet/in_var.h>
                     77: #include <netinet/ip_var.h>
                     78: #include <netinet/tcp.h>
                     79: #include <netinet/tcp_fsm.h>
                     80: #include <netinet/tcp_seq.h>
                     81: #include <netinet/tcp_timer.h>
                     82: #include <netinet/tcp_var.h>
                     83: #include <netinet/tcpip.h>
                     84: #if TCPDEBUG
                     85: #include <netinet/tcp_debug.h>
                     86: #endif
                     87: 
                     88: /*
                     89:  * TCP protocol interface to socket abstraction.
                     90:  */
                     91: extern char *tcpstates[];      /* XXX ??? */
                     92: 
                     93: static int     tcp_attach __P((struct socket *, struct proc *));
                     94: static int     tcp_connect __P((struct tcpcb *, struct sockaddr *, 
                     95:                                 struct proc *));
                     96: static struct tcpcb *
                     97:                tcp_disconnect __P((struct tcpcb *));
                     98: static struct tcpcb *
                     99:                tcp_usrclosed __P((struct tcpcb *));
                    100: 
                    101: #if TCPDEBUG
                    102: #define        TCPDEBUG0       int ostate
                    103: #define        TCPDEBUG1()     ostate = tp ? tp->t_state : 0
                    104: #define        TCPDEBUG2(req)  if (tp && (so->so_options & SO_DEBUG)) \
                    105:                                tcp_trace(TA_USER, ostate, tp, 0, req)
                    106: #else
                    107: #define        TCPDEBUG0
                    108: #define        TCPDEBUG1()
                    109: #define        TCPDEBUG2(req)
                    110: #endif
                    111: 
                    112: /*
                    113:  * TCP attaches to socket via pru_attach(), reserving space,
                    114:  * and an internet control block.
                    115:  */
                    116: static int
                    117: tcp_usr_attach(struct socket *so, int proto, struct proc *p)
                    118: {
                    119:        int s = splnet();
                    120:        int error;
                    121:        struct inpcb *inp = sotoinpcb(so);
                    122:        struct tcpcb *tp = 0;
                    123:        TCPDEBUG0;
                    124: 
                    125:        TCPDEBUG1();
                    126:        if (inp) {
                    127:                error = EISCONN;
                    128:                goto out;
                    129:        }
                    130: 
                    131:        error = tcp_attach(so, p);
                    132:        if (error)
                    133:                goto out;
                    134: 
                    135:        if ((so->so_options & SO_LINGER) && so->so_linger == 0)
                    136:                so->so_linger = TCP_LINGERTIME * hz;
                    137:        tp = sototcpcb(so);
                    138: out:
                    139:        TCPDEBUG2(PRU_ATTACH);
                    140:        splx(s);
                    141:        return error;
                    142: }
                    143: 
                    144: /*
                    145:  * pru_detach() detaches the TCP protocol from the socket.
                    146:  * If the protocol state is non-embryonic, then can't
                    147:  * do this directly: have to initiate a pru_disconnect(),
                    148:  * which may finish later; embryonic TCB's can just
                    149:  * be discarded here.
                    150:  */
                    151: static int
                    152: tcp_usr_detach(struct socket *so)
                    153: {
                    154:        int s = splnet();
                    155:        int error = 0;
                    156:        struct inpcb *inp = sotoinpcb(so);
                    157:        struct tcpcb *tp;
                    158:        TCPDEBUG0;
                    159: 
                    160:        if (inp == 0) {
                    161:                splx(s);
                    162:                return EINVAL;  /* XXX */
                    163:        }
                    164:        tp = intotcpcb(inp);
                    165:        TCPDEBUG1();
                    166:        tp = tcp_disconnect(tp);
                    167: 
                    168:        TCPDEBUG2(PRU_DETACH);
                    169:        splx(s);
                    170:        return error;
                    171: }
                    172: 
                    173: #define        COMMON_START()  TCPDEBUG0; \
                    174:                        do { \
                    175:                                     if (inp == 0) { \
                    176:                                             splx(s); \
                    177:                                             return EINVAL; \
                    178:                                     } \
                    179:                                     tp = intotcpcb(inp); \
                    180:                                     TCPDEBUG1(); \
                    181:                     } while(0)
                    182:                             
                    183: #define COMMON_END(req)        out: TCPDEBUG2(req); splx(s); return error; goto out
                    184: 
                    185: 
                    186: /*
                    187:  * Give the socket an address.
                    188:  */
                    189: static int
                    190: tcp_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
                    191: {
                    192:        int s = splnet();
                    193:        int error = 0;
                    194:        struct inpcb *inp = sotoinpcb(so);
                    195:        struct tcpcb *tp;
                    196:        struct sockaddr_in *sinp;
                    197: 
                    198:        COMMON_START();
                    199: 
                    200:        /*
                    201:         * Must check for multicast addresses and disallow binding
                    202:         * to them.
                    203:         */
                    204:        sinp = (struct sockaddr_in *)nam;
                    205:        if (sinp->sin_family == AF_INET &&
                    206:            IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
                    207:                error = EAFNOSUPPORT;
                    208:                goto out;
                    209:        }
                    210:        error = in_pcbbind(inp, nam, p);
                    211:        if (error)
                    212:                goto out;
                    213:        COMMON_END(PRU_BIND);
                    214: 
                    215: }
                    216: 
                    217: /*
                    218:  * Prepare to accept connections.
                    219:  */
                    220: static int
                    221: tcp_usr_listen(struct socket *so, struct proc *p)
                    222: {
                    223:        int s = splnet();
                    224:        int error = 0;
                    225:        struct inpcb *inp = sotoinpcb(so);
                    226:        struct tcpcb *tp;
                    227: 
                    228:        COMMON_START();
                    229:        if (inp->inp_lport == 0)
                    230:                error = in_pcbbind(inp, (struct sockaddr *)0, p);
                    231:        if (error == 0)
                    232:                tp->t_state = TCPS_LISTEN;
                    233:        COMMON_END(PRU_LISTEN);
                    234: }
                    235: 
                    236: /*
                    237:  * Initiate connection to peer.
                    238:  * Create a template for use in transmissions on this connection.
                    239:  * Enter SYN_SENT state, and mark socket as connecting.
                    240:  * Start keep-alive timer, and seed output sequence space.
                    241:  * Send initial segment on connection.
                    242:  */
                    243: static int
                    244: tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
                    245: {
                    246:        int s = splnet();
                    247:        int error = 0;
                    248:        struct inpcb *inp = sotoinpcb(so);
                    249:        struct tcpcb *tp;
                    250:        struct sockaddr_in *sinp;
                    251: 
                    252:        COMMON_START();
                    253: 
                    254:        /*
                    255:         * Must disallow TCP ``connections'' to multicast addresses.
                    256:         */
                    257:        sinp = (struct sockaddr_in *)nam;
                    258:        if (sinp->sin_family == AF_INET
                    259:            && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
                    260:                error = EAFNOSUPPORT;
                    261:                goto out;
                    262:        }
                    263: 
                    264:        if ((error = tcp_connect(tp, nam, p)) != 0)
                    265:                goto out;
                    266:        error = tcp_output(tp);
                    267:        COMMON_END(PRU_CONNECT);
                    268: }
                    269: 
                    270: /*
                    271:  * Initiate disconnect from peer.
                    272:  * If connection never passed embryonic stage, just drop;
                    273:  * else if don't need to let data drain, then can just drop anyways,
                    274:  * else have to begin TCP shutdown process: mark socket disconnecting,
                    275:  * drain unread data, state switch to reflect user close, and
                    276:  * send segment (e.g. FIN) to peer.  Socket will be really disconnected
                    277:  * when peer sends FIN and acks ours.
                    278:  *
                    279:  * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
                    280:  */
                    281: static int
                    282: tcp_usr_disconnect(struct socket *so)
                    283: {
                    284:        int s = splnet();
                    285:        int error = 0;
                    286:        struct inpcb *inp = sotoinpcb(so);
                    287:        struct tcpcb *tp;
                    288: 
                    289:        COMMON_START();
                    290:        tp = tcp_disconnect(tp);
                    291:        COMMON_END(PRU_DISCONNECT);
                    292: }
                    293: 
                    294: /*
                    295:  * Accept a connection.  Essentially all the work is
                    296:  * done at higher levels; just return the address
                    297:  * of the peer, storing through addr.
                    298:  */
                    299: static int
                    300: tcp_usr_accept(struct socket *so, struct sockaddr **nam)
                    301: {
                    302:        int s = splnet();
                    303:        int error = 0;
                    304:        struct inpcb *inp = sotoinpcb(so);
                    305:        struct tcpcb *tp;
                    306: 
                    307:        COMMON_START();
                    308:        in_setpeeraddr(so, nam);
                    309:        COMMON_END(PRU_ACCEPT);
                    310: }
                    311: 
                    312: /*
                    313:  * Mark the connection as being incapable of further output.
                    314:  */
                    315: static int
                    316: tcp_usr_shutdown(struct socket *so)
                    317: {
                    318:        int s = splnet();
                    319:        int error = 0;
                    320:        struct inpcb *inp = sotoinpcb(so);
                    321:        struct tcpcb *tp;
                    322: 
                    323:        COMMON_START();
                    324:        socantsendmore(so);
                    325:        tp = tcp_usrclosed(tp);
                    326:        if (tp)
                    327:                error = tcp_output(tp);
                    328:        COMMON_END(PRU_SHUTDOWN);
                    329: }
                    330: 
                    331: /*
                    332:  * After a receive, possibly send window update to peer.
                    333:  */
                    334: static int
                    335: tcp_usr_rcvd(struct socket *so, int flags)
                    336: {
                    337:        int s = splnet();
                    338:        int error = 0;
                    339:        struct inpcb *inp = sotoinpcb(so);
                    340:        struct tcpcb *tp;
                    341: 
                    342:        COMMON_START();
                    343:        tcp_output(tp);
                    344:        COMMON_END(PRU_RCVD);
                    345: }
                    346: 
                    347: /*
                    348:  * Do a send by putting data in output queue and updating urgent
                    349:  * marker if URG set.  Possibly send more data.
                    350:  */
                    351: static int
                    352: tcp_usr_send(struct socket *so, int flags, struct mbuf *m, 
                    353:             struct sockaddr *nam, struct mbuf *control, struct proc *p)
                    354: {
                    355:        int s = splnet();
                    356:        int error = 0;
                    357:        struct inpcb *inp = sotoinpcb(so);
                    358:        struct tcpcb *tp;
                    359: 
                    360:        COMMON_START();
                    361:        if (control && control->m_len) {
                    362:                m_freem(control); /* XXX shouldn't caller do this??? */
                    363:                if (m)
                    364:                        m_freem(m);
                    365:                error = EINVAL;
                    366:                goto out;
                    367:        }
                    368: 
                    369:        if(!(flags & PRUS_OOB)) {
                    370:                sbappend(&so->so_snd, m);
                    371:                if (nam && tp->t_state < TCPS_SYN_SENT) {
                    372:                        /*
                    373:                         * Do implied connect if not yet connected,
                    374:                         * initialize window to default value, and
                    375:                         * initialize maxseg/maxopd using peer's cached
                    376:                         * MSS.
                    377:                         */
                    378:                        error = tcp_connect(tp, nam, p);
                    379:                        if (error)
                    380:                                goto out;
                    381:                        tp->snd_wnd = TTCP_CLIENT_SND_WND;
                    382:                        tcp_mss(tp, -1);
                    383:                }
                    384: 
                    385:                if (flags & PRUS_EOF) {
                    386:                        /*
                    387:                         * Close the send side of the connection after
                    388:                         * the data is sent.
                    389:                         */
                    390:                        socantsendmore(so);
                    391:                        tp = tcp_usrclosed(tp);
                    392:                }
                    393:                if (tp != NULL) {
                    394:                        if (flags & PRUS_MORETOCOME)
                    395:                                tp->t_flags |= TF_MORETOCOME;
                    396:                        error = tcp_output(tp);
                    397:                        if (flags & PRUS_MORETOCOME)
                    398:                                tp->t_flags &= ~TF_MORETOCOME;
                    399:                }
                    400:        } else {
                    401:                if (sbspace(&so->so_snd) < -512) {
                    402:                        m_freem(m);
                    403:                        error = ENOBUFS;
                    404:                        goto out;
                    405:                }
                    406:                /*
                    407:                 * According to RFC961 (Assigned Protocols),
                    408:                 * the urgent pointer points to the last octet
                    409:                 * of urgent data.  We continue, however,
                    410:                 * to consider it to indicate the first octet
                    411:                 * of data past the urgent section.
                    412:                 * Otherwise, snd_up should be one lower.
                    413:                 */
                    414:                sbappend(&so->so_snd, m);
                    415:                if (nam && tp->t_state < TCPS_SYN_SENT) {
                    416:                        /*
                    417:                         * Do implied connect if not yet connected,
                    418:                         * initialize window to default value, and
                    419:                         * initialize maxseg/maxopd using peer's cached
                    420:                         * MSS.
                    421:                         */
                    422:                        error = tcp_connect(tp, nam, p);
                    423:                        if (error)
                    424:                                goto out;
                    425:                        tp->snd_wnd = TTCP_CLIENT_SND_WND;
                    426:                        tcp_mss(tp, -1);
                    427:                }
                    428:                tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
                    429:                tp->t_force = 1;
                    430:                error = tcp_output(tp);
                    431:                tp->t_force = 0;
                    432:        }
                    433:        COMMON_END((flags & PRUS_OOB) ? PRU_SENDOOB : 
                    434:                   ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
                    435: }
                    436: 
                    437: /*
                    438:  * Abort the TCP.
                    439:  */
                    440: static int
                    441: tcp_usr_abort(struct socket *so)
                    442: {
                    443:        int s = splnet();
                    444:        int error = 0;
                    445:        struct inpcb *inp = sotoinpcb(so);
                    446:        struct tcpcb *tp;
                    447: 
                    448:        COMMON_START();
                    449:        tp = tcp_drop(tp, ECONNABORTED);
                    450:        COMMON_END(PRU_ABORT);
                    451: }
                    452: 
                    453: /*
                    454:  * Receive out-of-band data.
                    455:  */
                    456: static int
                    457: tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags)
                    458: {
                    459:        int s = splnet();
                    460:        int error = 0;
                    461:        struct inpcb *inp = sotoinpcb(so);
                    462:        struct tcpcb *tp;
                    463: 
                    464:        COMMON_START();
                    465:        if ((so->so_oobmark == 0 &&
                    466:             (so->so_state & SS_RCVATMARK) == 0) ||
                    467:            so->so_options & SO_OOBINLINE ||
                    468:            tp->t_oobflags & TCPOOB_HADDATA) {
                    469:                error = EINVAL;
                    470:                goto out;
                    471:        }
                    472:        if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) {
                    473:                error = EWOULDBLOCK;
                    474:                goto out;
                    475:        }
                    476:        m->m_len = 1;
                    477:        *mtod(m, caddr_t) = tp->t_iobc;
                    478:        if ((flags & MSG_PEEK) == 0)
                    479:                tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA);
                    480:        COMMON_END(PRU_RCVOOB);
                    481: }
                    482: 
                    483: /* xxx - should be const */
                    484: struct pr_usrreqs tcp_usrreqs = {
                    485:        tcp_usr_abort, tcp_usr_accept, tcp_usr_attach, tcp_usr_bind,
                    486:        tcp_usr_connect, pru_connect2_notsupp, in_control, tcp_usr_detach,
                    487:        tcp_usr_disconnect, tcp_usr_listen, in_setpeeraddr, tcp_usr_rcvd,
                    488:        tcp_usr_rcvoob, tcp_usr_send, pru_sense_null, tcp_usr_shutdown,
                    489:        in_setsockaddr, sosend, soreceive, sopoll
                    490: };
                    491: 
                    492: /*
                    493:  * Common subroutine to open a TCP connection to remote host specified
                    494:  * by struct sockaddr_in in mbuf *nam.  Call in_pcbbind to assign a local
                    495:  * port number if needed.  Call in_pcbladdr to do the routing and to choose
                    496:  * a local host address (interface).  If there is an existing incarnation
                    497:  * of the same connection in TIME-WAIT state and if the remote host was
                    498:  * sending CC options and if the connection duration was < MSL, then
                    499:  * truncate the previous TIME-WAIT state and proceed.
                    500:  * Initialize connection parameters and enter SYN-SENT state.
                    501:  */
                    502: static int
                    503: tcp_connect(tp, nam, p)
                    504:        register struct tcpcb *tp;
                    505:        struct sockaddr *nam;
                    506:        struct proc *p;
                    507: {
                    508:        struct inpcb *inp = tp->t_inpcb, *oinp;
                    509:        struct socket *so = inp->inp_socket;
                    510:        struct tcpcb *otp;
                    511:        struct sockaddr_in *sin = (struct sockaddr_in *)nam;
                    512:        struct sockaddr_in *ifaddr;
                    513:        struct rmxp_tao *taop;
                    514:        struct rmxp_tao tao_noncached;
                    515:        int error;
                    516: 
                    517:        if (inp->inp_lport == 0) {
                    518:                error = in_pcbbind(inp, (struct sockaddr *)0, p);
                    519:                if (error)
                    520:                        return error;
                    521:        }
                    522: 
                    523:        /*
                    524:         * Cannot simply call in_pcbconnect, because there might be an
                    525:         * earlier incarnation of this same connection still in
                    526:         * TIME_WAIT state, creating an ADDRINUSE error.
                    527:         */
                    528:        error = in_pcbladdr(inp, nam, &ifaddr);
                    529:        if (error)
                    530:                return error;
                    531:        oinp = in_pcblookup_hash(inp->inp_pcbinfo,
                    532:            sin->sin_addr, sin->sin_port,
                    533:            inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr
                    534:                                                : ifaddr->sin_addr,
                    535:            inp->inp_lport,  0);
                    536:        if (oinp) {
                    537:                if (oinp != inp && (otp = intotcpcb(oinp)) != NULL &&
                    538:                otp->t_state == TCPS_TIME_WAIT &&
                    539:                    otp->t_duration < TCPTV_MSL &&
                    540:                    (otp->t_flags & TF_RCVD_CC))
                    541:                        otp = tcp_close(otp);
                    542:                else
                    543:                        return EADDRINUSE;
                    544:        }
                    545:        if (inp->inp_laddr.s_addr == INADDR_ANY)
                    546:                inp->inp_laddr = ifaddr->sin_addr;
                    547:        inp->inp_faddr = sin->sin_addr;
                    548:        inp->inp_fport = sin->sin_port;
                    549:        in_pcbrehash(inp);
                    550: 
                    551:        tp->t_template = tcp_template(tp);
                    552:        if (tp->t_template == 0) {
                    553:                in_pcbdisconnect(inp);
                    554:                return ENOBUFS;
                    555:        }
                    556: 
                    557:        /* Compute window scaling to request.  */
                    558:        while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
                    559:            (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
                    560:                tp->request_r_scale++;
                    561: 
                    562:        soisconnecting(so);
                    563:        tcpstat.tcps_connattempt++;
                    564:        tp->t_state = TCPS_SYN_SENT;
                    565:        tp->t_timer[TCPT_KEEP] = tcp_keepinit;
                    566:        tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
                    567:        tcp_sendseqinit(tp);
                    568: 
                    569:        /*
                    570:         * Generate a CC value for this connection and
                    571:         * check whether CC or CCnew should be used.
                    572:         */
                    573:        if ((taop = tcp_gettaocache(tp->t_inpcb)) == NULL) {
                    574:                taop = &tao_noncached;
                    575:                bzero(taop, sizeof(*taop));
                    576:        }
                    577: 
                    578:        tp->cc_send = CC_INC(tcp_ccgen);
                    579:        if (taop->tao_ccsent != 0 &&
                    580:            CC_GEQ(tp->cc_send, taop->tao_ccsent)) {
                    581:                taop->tao_ccsent = tp->cc_send;
                    582:        } else {
                    583:                taop->tao_ccsent = 0;
                    584:                tp->t_flags |= TF_SENDCCNEW;
                    585:        }
                    586: 
                    587:        return 0;
                    588: }
                    589: 
                    590: /*
                    591:  * The new sockopt interface makes it possible for us to block in the
                    592:  * copyin/out step (if we take a page fault).  Taking a page fault at
                    593:  * splnet() is probably a Bad Thing.  (Since sockets and pcbs both now
                    594:  * use TSM, there probably isn't any need for this function to run at
                    595:  * splnet() any more.  This needs more examination.)
                    596:  */
                    597: int
                    598: tcp_ctloutput(so, sopt)
                    599:        struct socket *so;
                    600:        struct sockopt *sopt;
                    601: {
                    602:        int     error, opt, optval, s;
                    603:        struct  inpcb *inp;
                    604:        struct  tcpcb *tp;
                    605: 
                    606:        error = 0;
                    607:        s = splnet();           /* XXX */
                    608:        inp = sotoinpcb(so);
                    609:        if (inp == NULL) {
                    610:                splx(s);
                    611:                return (ECONNRESET);
                    612:        }
                    613:        if (sopt->sopt_level != IPPROTO_TCP) {
                    614:                error = ip_ctloutput(so, sopt);
                    615:                splx(s);
                    616:                return (error);
                    617:        }
                    618:        tp = intotcpcb(inp);
                    619: 
                    620:        switch (sopt->sopt_dir) {
                    621:        case SOPT_SET:
                    622:                switch (sopt->sopt_name) {
                    623:                case TCP_NODELAY:
                    624:                case TCP_NOOPT:
                    625:                case TCP_NOPUSH:
                    626:                        error = sooptcopyin(sopt, &optval, sizeof optval,
                    627:                                            sizeof optval);
                    628:                        if (error)
                    629:                                break;
                    630: 
                    631:                        switch (sopt->sopt_name) {
                    632:                        case TCP_NODELAY:
                    633:                                opt = TF_NODELAY;
                    634:                                break;
                    635:                        case TCP_NOOPT:
                    636:                                opt = TF_NOOPT;
                    637:                                break;
                    638:                        case TCP_NOPUSH:
                    639:                                opt = TF_NOPUSH;
                    640:                                break;
                    641:                        default:
                    642:                                opt = 0; /* dead code to fool gcc */
                    643:                                break;
                    644:                        }
                    645: 
                    646:                        if (optval)
                    647:                                tp->t_flags |= opt;
                    648:                        else
                    649:                                tp->t_flags &= ~opt;
                    650:                        break;
                    651: 
                    652:                case TCP_MAXSEG:
                    653:                        error = sooptcopyin(sopt, &optval, sizeof optval,
                    654:                                            sizeof optval);
                    655:                        if (error)
                    656:                                break;
                    657: 
                    658:                        if (optval > 0 && optval <= tp->t_maxseg)
                    659:                                tp->t_maxseg = optval;
                    660:                        else
                    661:                                error = EINVAL;
                    662:                        break;
                    663: 
                    664:                default:
                    665:                        error = ENOPROTOOPT;
                    666:                        break;
                    667:                }
                    668:                break;
                    669: 
                    670:        case SOPT_GET:
                    671:                switch (sopt->sopt_name) {
                    672:                case TCP_NODELAY:
                    673:                        optval = tp->t_flags & TF_NODELAY;
                    674:                        break;
                    675:                case TCP_MAXSEG:
                    676:                        optval = tp->t_maxseg;
                    677:                        break;
                    678:                case TCP_NOOPT:
                    679:                        optval = tp->t_flags & TF_NOOPT;
                    680:                        break;
                    681:                case TCP_NOPUSH:
                    682:                        optval = tp->t_flags & TF_NOPUSH;
                    683:                        break;
                    684:                default:
                    685:                        error = ENOPROTOOPT;
                    686:                        break;
                    687:                }
                    688:                if (error == 0)
                    689:                        error = sooptcopyout(sopt, &optval, sizeof optval);
                    690:                break;
                    691:        }
                    692:        splx(s);
                    693:        return (error);
                    694: }
                    695: 
                    696: /*
                    697:  * tcp_sendspace and tcp_recvspace are the default send and receive window
                    698:  * sizes, respectively.  These are obsolescent (this information should
                    699:  * be set by the route).
                    700:  */
                    701: u_long tcp_sendspace = 1024*16;
                    702: SYSCTL_INT(_net_inet_tcp, TCPCTL_SENDSPACE, sendspace,
                    703:        CTLFLAG_RW, &tcp_sendspace , 0, "");
                    704: u_long tcp_recvspace = 1024*16;
                    705: SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace,
                    706:        CTLFLAG_RW, &tcp_recvspace , 0, "");
                    707: 
                    708: /*
                    709:  * Attach TCP protocol to socket, allocating
                    710:  * internet protocol control block, tcp control block,
                    711:  * bufer space, and entering LISTEN state if to accept connections.
                    712:  */
                    713: static int
                    714: tcp_attach(so, p)
                    715:        struct socket *so;
                    716:        struct proc *p;
                    717: {
                    718:        register struct tcpcb *tp;
                    719:        struct inpcb *inp;
                    720:        int error;
                    721: 
                    722:        if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
                    723:                error = soreserve(so, tcp_sendspace, tcp_recvspace);
                    724:                if (error)
                    725:                        return (error);
                    726:        }
                    727:        error = in_pcballoc(so, &tcbinfo, p);
                    728:        if (error)
                    729:                return (error);
                    730:        inp = sotoinpcb(so);
                    731:        tp = tcp_newtcpcb(inp);
                    732:        if (tp == 0) {
                    733:                int nofd = so->so_state & SS_NOFDREF;   /* XXX */
                    734: 
                    735:                so->so_state &= ~SS_NOFDREF;    /* don't free the socket yet */
                    736:                in_pcbdetach(inp);
                    737:                so->so_state |= nofd;
                    738:                return (ENOBUFS);
                    739:        }
                    740:        tp->t_state = TCPS_CLOSED;
                    741:        return (0);
                    742: }
                    743: 
                    744: /*
                    745:  * Initiate (or continue) disconnect.
                    746:  * If embryonic state, just send reset (once).
                    747:  * If in ``let data drain'' option and linger null, just drop.
                    748:  * Otherwise (hard), mark socket disconnecting and drop
                    749:  * current input data; switch states based on user close, and
                    750:  * send segment to peer (with FIN).
                    751:  */
                    752: static struct tcpcb *
                    753: tcp_disconnect(tp)
                    754:        register struct tcpcb *tp;
                    755: {
                    756:        struct socket *so = tp->t_inpcb->inp_socket;
                    757: 
                    758:        if (tp->t_state < TCPS_ESTABLISHED)
                    759:                tp = tcp_close(tp);
                    760:        else if ((so->so_options & SO_LINGER) && so->so_linger == 0)
                    761:                tp = tcp_drop(tp, 0);
                    762:        else {
                    763:                soisdisconnecting(so);
                    764:                sbflush(&so->so_rcv);
                    765:                tp = tcp_usrclosed(tp);
                    766:                if (tp)
                    767:                        (void) tcp_output(tp);
                    768:        }
                    769:        return (tp);
                    770: }
                    771: 
                    772: /*
                    773:  * User issued close, and wish to trail through shutdown states:
                    774:  * if never received SYN, just forget it.  If got a SYN from peer,
                    775:  * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
                    776:  * If already got a FIN from peer, then almost done; go to LAST_ACK
                    777:  * state.  In all other cases, have already sent FIN to peer (e.g.
                    778:  * after PRU_SHUTDOWN), and just have to play tedious game waiting
                    779:  * for peer to send FIN or not respond to keep-alives, etc.
                    780:  * We can let the user exit from the close as soon as the FIN is acked.
                    781:  */
                    782: static struct tcpcb *
                    783: tcp_usrclosed(tp)
                    784:        register struct tcpcb *tp;
                    785: {
                    786: 
                    787:        switch (tp->t_state) {
                    788: 
                    789:        case TCPS_CLOSED:
                    790:        case TCPS_LISTEN:
                    791:                tp->t_state = TCPS_CLOSED;
                    792:                tp = tcp_close(tp);
                    793:                break;
                    794: 
                    795:        case TCPS_SYN_SENT:
                    796:        case TCPS_SYN_RECEIVED:
                    797:                tp->t_flags |= TF_NEEDFIN;
                    798:                break;
                    799: 
                    800:        case TCPS_ESTABLISHED:
                    801:                tp->t_state = TCPS_FIN_WAIT_1;
                    802:                break;
                    803: 
                    804:        case TCPS_CLOSE_WAIT:
                    805:                tp->t_state = TCPS_LAST_ACK;
                    806:                break;
                    807:        }
                    808:        if (tp && tp->t_state >= TCPS_FIN_WAIT_2) {
                    809:                soisdisconnected(tp->t_inpcb->inp_socket);
                    810:                /* To prevent the connection hanging in FIN_WAIT_2 forever. */
                    811:                if (tp->t_state == TCPS_FIN_WAIT_2)
                    812:                        tp->t_timer[TCPT_2MSL] = tcp_maxidle;
                    813:        }
                    814:        return (tp);
                    815: }
                    816: 

unix.superglobalmegacorp.com

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