Annotation of 43BSD/sys/netinet/tcp_subr.c, revision 1.1.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.