# 2.11BSD#431 - /usr/src/sys/netinet/tcp_subr.c

##### Functions

    tcp_close         X
    tcp_ctlinput      X
    tcp_drain         X
    tcp_drop          X
    tcp_init          X
    tcp_newtcpcb      X
    tcp_notify        X
    tcp_quench        X
    tcp_respond       X
    tcp_template      X

##### Macros

    xchg              X

       1: /*
       2:  * Copyright (c) 1982, 1986 Regents of the University of California.
       3:  * All rights reserved.
       4:  *
       5:  * Redistribution and use in source and binary forms are permitted
       6:  * provided that this notice is preserved and that due credit is given
       7:  * to the University of California at Berkeley. The name of the University
       8:  * may not be used to endorse or promote products derived from this
       9:  * software without specific prior written permission. This software
      10:  * is provided ``as is'' without express or implied warranty.
      11:  *
      12:  *	@(#)tcp_subr.c	7.13.3 (2.11BSD GTE) 1995/10/10
      13:  */
      14:
      15: #include "param.h"
      16: #include "systm.h"
      17: #include "mbuf.h"
      18: #include "socket.h"
      19: #include "socketvar.h"
      20: #include "protosw.h"
      21: #include "errno.h"
      22:
      23: #include "../net/route.h"
      24: #include "../net/if.h"
      25:
      26: #include "domain.h"
      27: #include "in.h"
      28: #include "in_pcb.h"
      29: #include "in_systm.h"
      30: #include "ip.h"
      31: #include "ip_var.h"
      32: #include "ip_icmp.h"
      33: #include "tcp.h"
      34: #include "tcp_fsm.h"
      35: #include "tcp_seq.h"
      36: #include "tcp_timer.h"
      37: #include "tcp_var.h"
      38: #include "tcpip.h"
      39:
      40: /*
      41:  * Tcp initialization
      42:  */
      43: tcp_init()
      44: {
      45:
      46:     tcp_iss = 1;        /* wrong */
      47:     tcb.inp_next = tcb.inp_prev = &tcb;
      48: }
      49:
      50: /*
      51:  * Create template to be used to send tcp packets on a connection.
      52:  * Call after host entry created, allocates an mbuf and fills
      53:  * in a skeletal tcp/ip header, minimizing the amount of work
      54:  * necessary when the connection is used.
      55:  */
      56: struct tcpiphdr *
      57: tcp_template(tp)
      58:     struct tcpcb *tp;
      59: {
      60:     register struct inpcb *inp = tp->t_inpcb;
      61:     register struct mbuf *m;
      62:     register struct tcpiphdr *n;
      63:
      64:     if ((n = tp->t_template) == 0) {
      65:         m = m_get(M_DONTWAIT, MT_HEADER);
      66:         if (m == NULL)
      67:             return (0);
      68:         m->m_off = MMAXOFF - sizeof (struct tcpiphdr);
      69:         m->m_len = sizeof (struct tcpiphdr);
      70:         n = mtod(m, struct tcpiphdr *);
      71:     }
      72:     n->ti_next = n->ti_prev = 0;
      73:     n->ti_x1 = 0;
      74:     n->ti_pad = 0;
      75:     n->ti_pr = IPPROTO_TCP;
      76:     n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
      77:     n->ti_src = inp->inp_laddr;
      78:     n->ti_dst = inp->inp_faddr;
      79:     n->ti_sport = inp->inp_lport;
      80:     n->ti_dport = inp->inp_fport;
      81:     n->ti_seq = 0;
      82:     n->ti_ack = 0;
      83:     n->ti_x2 = 0;
      84:     n->ti_off = 5;
      85:     n->ti_flags = 0;
      86:     n->ti_win = 0;
      87:     n->ti_sum = 0;
      88:     n->ti_urp = 0;
      89:     return (n);
      90: }
      91:
      92: /*
      93:  * Send a single message to the TCP at address specified by
      94:  * the given TCP/IP header.  If flags==0, then we make a copy
      95:  * of the tcpiphdr at ti and send directly to the addressed host.
      96:  * This is used to force keep alive messages out using the TCP
      97:  * template for a connection tp->t_template.  If flags are given
      98:  * then we send a message back to the TCP which originated the
      99:  * segment ti, and discard the mbuf containing it and any other
     100:  * attached mbufs.
     101:  *
     102:  * In any case the ack and sequence number of the transmitted
     103:  * segment are as specified by the parameters.
     104:  */
     105: tcp_respond(tp, ti, ack, seq, flags)
     106:     struct tcpcb *tp;
     107:     register struct tcpiphdr *ti;
     108:     tcp_seq ack, seq;
     109:     int flags;
     110: {
     111:     register struct mbuf *m;
     112:     int win = 0, tlen;
     113:     struct route *ro = 0;
     114:
     115:     if (tp) {
     116:         win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
     117:         ro = &tp->t_inpcb->inp_route;
     118:     }
     119:     if (flags == 0) {
     120:         m = m_get(M_DONTWAIT, MT_HEADER);
     121:         if (m == NULL)
     122:             return;
     123: #ifdef TCP_COMPAT_42
     124:         tlen = 1;
     125: #else
     126:         tlen = 0;
     127: #endif
     128:         m->m_len = sizeof (struct tcpiphdr) + tlen;
     129:         *mtod(m, struct tcpiphdr *) = *ti;
     130:         ti = mtod(m, struct tcpiphdr *);
     131:         flags = TH_ACK;
     132:     } else {
     133:         m = dtom(ti);
     134:         m_freem(m->m_next);
     135:         m->m_next = 0;
     136:         m->m_off = (int)ti - (int)m;
     137:         tlen = 0;
     138:         m->m_len = sizeof (struct tcpiphdr);
     139: #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
     140:         xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long);
     141:         xchg(ti->ti_dport, ti->ti_sport, u_short);
     142: #undef xchg
     143:     }
     144:     ti->ti_next = ti->ti_prev = 0;
     145:     ti->ti_x1 = 0;
     146:     ti->ti_pad = 0;
     147:     ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
     148:     ti->ti_seq = htonl(seq);
     149:     ti->ti_ack = htonl(ack);
     150:     ti->ti_x2 = 0;
     151:     ti->ti_off = sizeof (struct tcphdr) >> 2;
     152:     ti->ti_flags = flags;
     153:     ti->ti_win = htons((u_short)win);
     154:     ti->ti_urp = 0;
     155:     ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + tlen);
     156:     ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + tlen;
     157:     ((struct ip *)ti)->ip_ttl = ip_defttl;
     158:     (void) ip_output(m, (struct mbuf *)0, ro, 0);
     159: }
     160:
     161: /*
     162:  * Create a new TCP control block, making an
     163:  * empty reassembly queue and hooking it to the argument
     164:  * protocol control block.
     165:  */
     166: struct tcpcb *
     167: tcp_newtcpcb(inp)
     168:     struct inpcb *inp;
     169: {
     170:     struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
     171:     register struct tcpcb *tp;
     172:
     173:     if (m == NULL)
     174:         return ((struct tcpcb *)0);
     175:     tp = mtod(m, struct tcpcb *);
     176:     tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
     177:     tp->t_maxseg = TCP_MSS;
     178:     tp->t_flags = 0;        /* sends options! */
     179:     tp->t_inpcb = inp;
     180:     /*
     181: 	 * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
     182: 	 * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
     183: 	 * reasonable initial retransmit time.
     184: 	 */
     185:     tp->t_srtt = TCPTV_SRTTBASE;
     186:     tp->t_rttvar = TCPTV_SRTTDFLT << 2;
     187:     TCPT_RANGESET(tp->t_rxtcur,
     188:         ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
     189:         TCPTV_MIN, TCPTV_REXMTMAX);
     190:     tp->snd_cwnd = sbspace(&inp->inp_socket->so_snd);
     191:     tp->snd_ssthresh = 65535;       /* XXX */
     192:     inp->inp_ppcb = (caddr_t)tp;
     193:     return (tp);
     194: }
     195:
     196: /*
     197:  * Drop a TCP connection, reporting
     198:  * the specified error.  If connection is synchronized,
     199:  * then send a RST to peer.
     200:  */
     201: struct tcpcb *
     202: tcp_drop(tp, errno)
     203:     register struct tcpcb *tp;
     204:     int errno;
     205: {
     206:     struct socket *so = tp->t_inpcb->inp_socket;
     207:
     208:     if (TCPS_HAVERCVDSYN(tp->t_state)) {
     209:         tp->t_state = TCPS_CLOSED;
     210:         (void) tcp_output(tp);
     211:         tcpstat.tcps_drops++;
     212:     } else
     213:         tcpstat.tcps_conndrops++;
     214:     so->so_error = errno;
     215:     return (tcp_close(tp));
     216: }
     217:
     218: /*
     219:  * Close a TCP control block:
     220:  *	discard all space held by the tcp
     221:  *	discard internet protocol block
     222:  *	wake up any sleepers
     223:  */
     224: struct tcpcb *
     225: tcp_close(tp)
     226:     register struct tcpcb *tp;
     227: {
     228:     register struct tcpiphdr *t;
     229:     struct inpcb *inp = tp->t_inpcb;
     230:     struct socket *so = inp->inp_socket;
     231:     register struct mbuf *m;
     232:
     233:     t = tp->seg_next;
     234:     while (t != (struct tcpiphdr *)tp) {
     235:         t = (struct tcpiphdr *)t->ti_next;
     236:         m = dtom(t->ti_prev);
     237:         remque(t->ti_prev);
     238:         m_freem(m);
     239:     }
     240:     if (tp->t_template)
     241:         (void) m_free(dtom(tp->t_template));
     242:     (void) m_free(dtom(tp));
     243:     inp->inp_ppcb = 0;
     244:     soisdisconnected(so);
     245:     in_pcbdetach(inp);
     246:     tcpstat.tcps_closed++;
     247:     return ((struct tcpcb *)0);
     248: }
     249:
     250: tcp_drain()
     251: {
     252:     register struct inpcb *ip, *ipnxt;
     253:     register struct tcpcb *tp;
     254:
     255:     /*
     256: 	 * Search through tcb's and look for TIME_WAIT states to liberate,
     257: 	 * these are due to go away soon anyhow and we're short of space or
     258:  	 * we wouldn't be here...
     259: 	 */
     260:     ip = tcb.inp_next;
     261:     if (ip == 0)
     262:         return;
     263:     for (; ip != &tcb; ip = ipnxt) {
     264:         ipnxt = ip->inp_next;
     265:         tp = intotcpcb(ip);
     266:         if (tp == 0)
     267:             continue;
     268:         if (tp->t_state == TCPS_TIME_WAIT)
     269:             tcp_close(tp);
     270:     }
     271: }
     272:
     273: /*
     274:  * Notify a tcp user of an asynchronous error;
     275:  * just wake up so that he can collect error status.
     276:  */
     277: tcp_notify(inp, error)
     278:     register struct inpcb *inp;
     279:     int error;
     280: {
     281:
     282:     inp->inp_socket->so_error = error;
     283:     WAKEUP((caddr_t) &inp->inp_socket->so_timeo);
     284:     sorwakeup(inp->inp_socket);
     285:     sowwakeup(inp->inp_socket);
     286: }
     287:
     288: tcp_ctlinput(cmd, sa, ip)
     289:     register int cmd;
     290:     struct sockaddr *sa;
     291:     register struct ip *ip;
     292: {
     293:     register struct tcphdr *th;
     294:     extern struct in_addr zeroin_addr;
     295:     extern u_char inetctlerrmap[];
     296:     int (*notify)() = tcp_notify, tcp_quench();
     297:
     298:     if (cmd == PRC_QUENCH)
     299:         notify = tcp_quench;
     300:     else if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)
     301:         return;
     302:     if (ip) {
     303:         th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
     304:         in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport,
     305:             cmd, notify);
     306:     } else
     307:         in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify);
     308: }
     309:
     310: /*
     311:  * When a source quench is received, close congestion window
     312:  * to one segment.  We will gradually open it again as we proceed.
     313:  */
     314: tcp_quench(inp)
     315:     struct inpcb *inp;
     316: {
     317:     struct tcpcb *tp = intotcpcb(inp);
     318:
     319:     if (tp)
     320:         tp->snd_cwnd = tp->t_maxseg;
     321: }

#### Defined functions

tcp_close defined in line 224; used 2 times

- in line 215, 269

tcp_ctlinput defined in line 288; never used
tcp_drain defined in line 250; never used
tcp_drop defined in line 201; never used
tcp_init defined in line 43; never used
tcp_newtcpcb defined in line 166; never used
tcp_notify defined in line 277; used 1 times

- in line 296

tcp_quench defined in line 314; used 2 times

- in line 296-299(2)

tcp_respond defined in line 105; never used
tcp_template defined in line 56; never used

#### Defined macros

xchg defined in line 139; used 3 times

- in line 140-142(3)

Last modified: 1995-10-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1796 |