Annotation of 43BSD/sys/netinet/tcp_subr.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  *
        !             6:  *     @(#)tcp_subr.c  7.1 (Berkeley) 6/5/86
        !             7:  */
        !             8: 
        !             9: #include "param.h"
        !            10: #include "systm.h"
        !            11: #include "mbuf.h"
        !            12: #include "socket.h"
        !            13: #include "socketvar.h"
        !            14: #include "protosw.h"
        !            15: #include "errno.h"
        !            16: 
        !            17: #include "../net/route.h"
        !            18: #include "../net/if.h"
        !            19: 
        !            20: #include "in.h"
        !            21: #include "in_pcb.h"
        !            22: #include "in_systm.h"
        !            23: #include "ip.h"
        !            24: #include "ip_var.h"
        !            25: #include "ip_icmp.h"
        !            26: #include "tcp.h"
        !            27: #include "tcp_fsm.h"
        !            28: #include "tcp_seq.h"
        !            29: #include "tcp_timer.h"
        !            30: #include "tcp_var.h"
        !            31: #include "tcpip.h"
        !            32: 
        !            33: /*
        !            34:  * Tcp initialization
        !            35:  */
        !            36: tcp_init()
        !            37: {
        !            38: 
        !            39:        tcp_iss = 1;            /* wrong */
        !            40:        tcb.inp_next = tcb.inp_prev = &tcb;
        !            41:        tcp_alpha = TCP_ALPHA;
        !            42:        tcp_beta = TCP_BETA;
        !            43: }
        !            44: 
        !            45: /*
        !            46:  * Create template to be used to send tcp packets on a connection.
        !            47:  * Call after host entry created, allocates an mbuf and fills
        !            48:  * in a skeletal tcp/ip header, minimizing the amount of work
        !            49:  * necessary when the connection is used.
        !            50:  */
        !            51: struct tcpiphdr *
        !            52: tcp_template(tp)
        !            53:        struct tcpcb *tp;
        !            54: {
        !            55:        register struct inpcb *inp = tp->t_inpcb;
        !            56:        register struct mbuf *m;
        !            57:        register struct tcpiphdr *n;
        !            58: 
        !            59:        if ((n = tp->t_template) == 0) {
        !            60:                m = m_get(M_WAIT, MT_HEADER);
        !            61:                if (m == NULL)
        !            62:                        return (0);
        !            63:                m->m_off = MMAXOFF - sizeof (struct tcpiphdr);
        !            64:                m->m_len = sizeof (struct tcpiphdr);
        !            65:                n = mtod(m, struct tcpiphdr *);
        !            66:        }
        !            67:        n->ti_next = n->ti_prev = 0;
        !            68:        n->ti_x1 = 0;
        !            69:        n->ti_pr = IPPROTO_TCP;
        !            70:        n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
        !            71:        n->ti_src = inp->inp_laddr;
        !            72:        n->ti_dst = inp->inp_faddr;
        !            73:        n->ti_sport = inp->inp_lport;
        !            74:        n->ti_dport = inp->inp_fport;
        !            75:        n->ti_seq = 0;
        !            76:        n->ti_ack = 0;
        !            77:        n->ti_x2 = 0;
        !            78:        n->ti_off = 5;
        !            79:        n->ti_flags = 0;
        !            80:        n->ti_win = 0;
        !            81:        n->ti_sum = 0;
        !            82:        n->ti_urp = 0;
        !            83:        return (n);
        !            84: }
        !            85: 
        !            86: /*
        !            87:  * Send a single message to the TCP at address specified by
        !            88:  * the given TCP/IP header.  If flags==0, then we make a copy
        !            89:  * of the tcpiphdr at ti and send directly to the addressed host.
        !            90:  * This is used to force keep alive messages out using the TCP
        !            91:  * template for a connection tp->t_template.  If flags are given
        !            92:  * then we send a message back to the TCP which originated the
        !            93:  * segment ti, and discard the mbuf containing it and any other
        !            94:  * attached mbufs.
        !            95:  *
        !            96:  * In any case the ack and sequence number of the transmitted
        !            97:  * segment are as specified by the parameters.
        !            98:  */
        !            99: tcp_respond(tp, ti, ack, seq, flags)
        !           100:        struct tcpcb *tp;
        !           101:        register struct tcpiphdr *ti;
        !           102:        tcp_seq ack, seq;
        !           103:        int flags;
        !           104: {
        !           105:        struct mbuf *m;
        !           106:        int win = 0, tlen;
        !           107:        struct route *ro = 0;
        !           108: 
        !           109:        if (tp) {
        !           110:                win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
        !           111:                ro = &tp->t_inpcb->inp_route;
        !           112:        }
        !           113:        if (flags == 0) {
        !           114:                m = m_get(M_DONTWAIT, MT_HEADER);
        !           115:                if (m == NULL)
        !           116:                        return;
        !           117:                m->m_len = sizeof (struct tcpiphdr) + 1;
        !           118:                *mtod(m, struct tcpiphdr *) = *ti;
        !           119:                ti = mtod(m, struct tcpiphdr *);
        !           120:                flags = TH_ACK;
        !           121:                tlen = 1;
        !           122:        } else {
        !           123:                m = dtom(ti);
        !           124:                m_freem(m->m_next);
        !           125:                m->m_next = 0;
        !           126:                m->m_off = (int)ti - (int)m;
        !           127:                m->m_len = sizeof (struct tcpiphdr);
        !           128: #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
        !           129:                xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long);
        !           130:                xchg(ti->ti_dport, ti->ti_sport, u_short);
        !           131: #undef xchg
        !           132:                tlen = 0;
        !           133:        }
        !           134:        ti->ti_next = ti->ti_prev = 0;
        !           135:        ti->ti_x1 = 0;
        !           136:        ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
        !           137:        ti->ti_seq = htonl(seq);
        !           138:        ti->ti_ack = htonl(ack);
        !           139:        ti->ti_x2 = 0;
        !           140:        ti->ti_off = sizeof (struct tcphdr) >> 2;
        !           141:        ti->ti_flags = flags;
        !           142:        ti->ti_win = htons((u_short)win);
        !           143:        ti->ti_urp = 0;
        !           144:        ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + tlen);
        !           145:        ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + tlen;
        !           146:        ((struct ip *)ti)->ip_ttl = TCP_TTL;
        !           147:        (void) ip_output(m, (struct mbuf *)0, ro, 0);
        !           148: }
        !           149: 
        !           150: /*
        !           151:  * Create a new TCP control block, making an
        !           152:  * empty reassembly queue and hooking it to the argument
        !           153:  * protocol control block.
        !           154:  */
        !           155: struct tcpcb *
        !           156: tcp_newtcpcb(inp)
        !           157:        struct inpcb *inp;
        !           158: {
        !           159:        struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
        !           160:        register struct tcpcb *tp;
        !           161: 
        !           162:        if (m == NULL)
        !           163:                return ((struct tcpcb *)0);
        !           164:        tp = mtod(m, struct tcpcb *);
        !           165:        tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
        !           166:        tp->t_maxseg = TCP_MSS;
        !           167:        tp->t_flags = 0;                /* sends options! */
        !           168:        tp->t_inpcb = inp;
        !           169:        tp->t_srtt = TCPTV_SRTTBASE;
        !           170:        tp->snd_cwnd = sbspace(&inp->inp_socket->so_snd);
        !           171:        inp->inp_ppcb = (caddr_t)tp;
        !           172:        return (tp);
        !           173: }
        !           174: 
        !           175: /*
        !           176:  * Drop a TCP connection, reporting
        !           177:  * the specified error.  If connection is synchronized,
        !           178:  * then send a RST to peer.
        !           179:  */
        !           180: struct tcpcb *
        !           181: tcp_drop(tp, errno)
        !           182:        register struct tcpcb *tp;
        !           183:        int errno;
        !           184: {
        !           185:        struct socket *so = tp->t_inpcb->inp_socket;
        !           186: 
        !           187:        if (TCPS_HAVERCVDSYN(tp->t_state)) {
        !           188:                tp->t_state = TCPS_CLOSED;
        !           189:                (void) tcp_output(tp);
        !           190:        }
        !           191:        so->so_error = errno;
        !           192:        return (tcp_close(tp));
        !           193: }
        !           194: 
        !           195: /*
        !           196:  * Close a TCP control block:
        !           197:  *     discard all space held by the tcp
        !           198:  *     discard internet protocol block
        !           199:  *     wake up any sleepers
        !           200:  */
        !           201: struct tcpcb *
        !           202: tcp_close(tp)
        !           203:        register struct tcpcb *tp;
        !           204: {
        !           205:        register struct tcpiphdr *t;
        !           206:        struct inpcb *inp = tp->t_inpcb;
        !           207:        struct socket *so = inp->inp_socket;
        !           208:        register struct mbuf *m;
        !           209: 
        !           210:        t = tp->seg_next;
        !           211:        while (t != (struct tcpiphdr *)tp) {
        !           212:                t = (struct tcpiphdr *)t->ti_next;
        !           213:                m = dtom(t->ti_prev);
        !           214:                remque(t->ti_prev);
        !           215:                m_freem(m);
        !           216:        }
        !           217:        if (tp->t_template)
        !           218:                (void) m_free(dtom(tp->t_template));
        !           219:        if (tp->t_tcpopt)
        !           220:                (void) m_free(dtom(tp->t_tcpopt));
        !           221:        (void) m_free(dtom(tp));
        !           222:        inp->inp_ppcb = 0;
        !           223:        soisdisconnected(so);
        !           224:        in_pcbdetach(inp);
        !           225:        return ((struct tcpcb *)0);
        !           226: }
        !           227: 
        !           228: tcp_drain()
        !           229: {
        !           230: 
        !           231: }
        !           232: 
        !           233: tcp_ctlinput(cmd, sa)
        !           234:        int cmd;
        !           235:        struct sockaddr *sa;
        !           236: {
        !           237:        extern u_char inetctlerrmap[];
        !           238:        struct sockaddr_in *sin;
        !           239:        int tcp_quench(), in_rtchange();
        !           240: 
        !           241:        if ((unsigned)cmd > PRC_NCMDS)
        !           242:                return;
        !           243:        if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
        !           244:                return;
        !           245:        sin = (struct sockaddr_in *)sa;
        !           246:        if (sin->sin_addr.s_addr == INADDR_ANY)
        !           247:                return;
        !           248: 
        !           249:        switch (cmd) {
        !           250: 
        !           251:        case PRC_QUENCH:
        !           252:                in_pcbnotify(&tcb, &sin->sin_addr, 0, tcp_quench);
        !           253:                break;
        !           254: 
        !           255:        case PRC_ROUTEDEAD:
        !           256:        case PRC_REDIRECT_NET:
        !           257:        case PRC_REDIRECT_HOST:
        !           258:        case PRC_REDIRECT_TOSNET:
        !           259:        case PRC_REDIRECT_TOSHOST:
        !           260:                in_pcbnotify(&tcb, &sin->sin_addr, 0, in_rtchange);
        !           261:                break;
        !           262: 
        !           263:        default:
        !           264:                if (inetctlerrmap[cmd] == 0)
        !           265:                        return;         /* XXX */
        !           266:                in_pcbnotify(&tcb, &sin->sin_addr, (int)inetctlerrmap[cmd],
        !           267:                        (int (*)())0);
        !           268:        }
        !           269: }
        !           270: 
        !           271: /*
        !           272:  * When a source quench is received, close congestion window
        !           273:  * to 80% of the outstanding data (but not less than one segment).
        !           274:  */
        !           275: tcp_quench(inp)
        !           276:        struct inpcb *inp;
        !           277: {
        !           278:        struct tcpcb *tp = intotcpcb(inp);
        !           279: 
        !           280:        if (tp)
        !           281:            tp->snd_cwnd = MAX(8 * (tp->snd_nxt - tp->snd_una) / 10,
        !           282:                tp->t_maxseg);
        !           283: }

unix.superglobalmegacorp.com

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