|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
1.1.1.2 ! root 33: * from: @(#)tcp_subr.c 7.20 (Berkeley) 12/1/90
! 34: * tcp_subr.c,v 1.4 1993/05/22 11:42:44 cgd Exp
1.1 root 35: */
36:
37: #include "param.h"
38: #include "systm.h"
39: #include "malloc.h"
40: #include "mbuf.h"
41: #include "socket.h"
42: #include "socketvar.h"
43: #include "protosw.h"
44: #include "errno.h"
45:
46: #include "../net/route.h"
47: #include "../net/if.h"
48:
49: #include "in.h"
50: #include "in_systm.h"
51: #include "ip.h"
52: #include "in_pcb.h"
53: #include "ip_var.h"
54: #include "ip_icmp.h"
55: #include "tcp.h"
56: #include "tcp_fsm.h"
57: #include "tcp_seq.h"
58: #include "tcp_timer.h"
59: #include "tcp_var.h"
60: #include "tcpip.h"
61:
62: /* patchable/settable parameters for tcp */
63: int tcp_ttl = TCP_TTL;
64: int tcp_mssdflt = TCP_MSS;
65: int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
66:
67: extern struct inpcb *tcp_last_inpcb;
68:
69: /*
70: * Tcp initialization
71: */
72: tcp_init()
73: {
74:
75: tcp_iss = 1; /* wrong */
76: tcb.inp_next = tcb.inp_prev = &tcb;
77: if (max_protohdr < sizeof(struct tcpiphdr))
78: max_protohdr = sizeof(struct tcpiphdr);
79: if (max_linkhdr + sizeof(struct tcpiphdr) > MHLEN)
80: panic("tcp_init");
81: }
82:
83: /*
84: * Create template to be used to send tcp packets on a connection.
85: * Call after host entry created, allocates an mbuf and fills
86: * in a skeletal tcp/ip header, minimizing the amount of work
87: * necessary when the connection is used.
88: */
89: struct tcpiphdr *
90: tcp_template(tp)
91: struct tcpcb *tp;
92: {
93: register struct inpcb *inp = tp->t_inpcb;
94: register struct mbuf *m;
95: register struct tcpiphdr *n;
96:
97: if ((n = tp->t_template) == 0) {
98: m = m_get(M_DONTWAIT, MT_HEADER);
99: if (m == NULL)
100: return (0);
101: m->m_len = sizeof (struct tcpiphdr);
102: n = mtod(m, struct tcpiphdr *);
103: }
104: n->ti_next = n->ti_prev = 0;
105: n->ti_x1 = 0;
106: n->ti_pr = IPPROTO_TCP;
107: n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
108: n->ti_src = inp->inp_laddr;
109: n->ti_dst = inp->inp_faddr;
110: n->ti_sport = inp->inp_lport;
111: n->ti_dport = inp->inp_fport;
112: n->ti_seq = 0;
113: n->ti_ack = 0;
114: n->ti_x2 = 0;
115: n->ti_off = 5;
116: n->ti_flags = 0;
117: n->ti_win = 0;
118: n->ti_sum = 0;
119: n->ti_urp = 0;
120: return (n);
121: }
122:
123: /*
124: * Send a single message to the TCP at address specified by
125: * the given TCP/IP header. If m == 0, then we make a copy
126: * of the tcpiphdr at ti and send directly to the addressed host.
127: * This is used to force keep alive messages out using the TCP
128: * template for a connection tp->t_template. If flags are given
129: * then we send a message back to the TCP which originated the
130: * segment ti, and discard the mbuf containing it and any other
131: * attached mbufs.
132: *
133: * In any case the ack and sequence number of the transmitted
134: * segment are as specified by the parameters.
135: */
136: tcp_respond(tp, ti, m, ack, seq, flags)
137: struct tcpcb *tp;
138: register struct tcpiphdr *ti;
139: register struct mbuf *m;
140: tcp_seq ack, seq;
141: int flags;
142: {
143: register int tlen;
144: int win = 0;
145: struct route *ro = 0;
146:
147: if (tp) {
148: win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
149: ro = &tp->t_inpcb->inp_route;
150: }
151: if (m == 0) {
152: m = m_gethdr(M_DONTWAIT, MT_HEADER);
153: if (m == NULL)
154: return;
155: #ifdef TCP_COMPAT_42
156: tlen = 1;
157: #else
158: tlen = 0;
159: #endif
160: m->m_data += max_linkhdr;
161: *mtod(m, struct tcpiphdr *) = *ti;
162: ti = mtod(m, struct tcpiphdr *);
163: flags = TH_ACK;
164: } else {
165: m_freem(m->m_next);
166: m->m_next = 0;
167: m->m_data = (caddr_t)ti;
168: m->m_len = sizeof (struct tcpiphdr);
169: tlen = 0;
170: #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
171: xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long);
172: xchg(ti->ti_dport, ti->ti_sport, u_short);
173: #undef xchg
174: }
175: ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
176: tlen += sizeof (struct tcpiphdr);
177: m->m_len = tlen;
178: m->m_pkthdr.len = tlen;
179: m->m_pkthdr.rcvif = (struct ifnet *) 0;
180: ti->ti_next = ti->ti_prev = 0;
181: ti->ti_x1 = 0;
182: ti->ti_seq = htonl(seq);
183: ti->ti_ack = htonl(ack);
184: ti->ti_x2 = 0;
185: ti->ti_off = sizeof (struct tcphdr) >> 2;
186: ti->ti_flags = flags;
187: ti->ti_win = htons((u_short)win);
188: ti->ti_urp = 0;
189: ti->ti_sum = in_cksum(m, tlen);
190: ((struct ip *)ti)->ip_len = tlen;
191: ((struct ip *)ti)->ip_ttl = tcp_ttl;
192: (void) ip_output(m, (struct mbuf *)0, ro, 0);
193: }
194:
195: /*
196: * Create a new TCP control block, making an
197: * empty reassembly queue and hooking it to the argument
198: * protocol control block.
199: */
200: struct tcpcb *
201: tcp_newtcpcb(inp)
202: struct inpcb *inp;
203: {
204: struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
205: register struct tcpcb *tp;
206:
207: if (m == NULL)
208: return ((struct tcpcb *)0);
209: tp = mtod(m, struct tcpcb *);
210: tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
211: tp->t_maxseg = tcp_mssdflt;
212:
213: tp->t_flags = 0; /* sends options! */
214: tp->t_inpcb = inp;
215: /*
216: * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
217: * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives
218: * reasonable initial retransmit time.
219: */
220: tp->t_srtt = TCPTV_SRTTBASE;
221: tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2;
222: tp->t_rttmin = TCPTV_MIN;
223: TCPT_RANGESET(tp->t_rxtcur,
224: ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
225: TCPTV_MIN, TCPTV_REXMTMAX);
226: tp->snd_cwnd = TCP_MAXWIN;
227: tp->snd_ssthresh = TCP_MAXWIN;
228: inp->inp_ip.ip_ttl = tcp_ttl;
229: inp->inp_ppcb = (caddr_t)tp;
230: return (tp);
231: }
232:
233: /*
234: * Drop a TCP connection, reporting
235: * the specified error. If connection is synchronized,
236: * then send a RST to peer.
237: */
238: struct tcpcb *
239: tcp_drop(tp, errno)
240: register struct tcpcb *tp;
241: int errno;
242: {
243: struct socket *so = tp->t_inpcb->inp_socket;
244:
245: if (TCPS_HAVERCVDSYN(tp->t_state)) {
246: tp->t_state = TCPS_CLOSED;
247: (void) tcp_output(tp);
248: tcpstat.tcps_drops++;
249: } else
250: tcpstat.tcps_conndrops++;
251: if (errno == ETIMEDOUT && tp->t_softerror)
252: errno = tp->t_softerror;
253: so->so_error = errno;
254: return (tcp_close(tp));
255: }
256:
257: /*
258: * Close a TCP control block:
259: * discard all space held by the tcp
260: * discard internet protocol block
261: * wake up any sleepers
262: */
263: struct tcpcb *
264: tcp_close(tp)
265: register struct tcpcb *tp;
266: {
267: register struct tcpiphdr *t;
268: struct inpcb *inp = tp->t_inpcb;
269: struct socket *so = inp->inp_socket;
270: register struct mbuf *m;
271: #ifdef RTV_RTT
272: register struct rtentry *rt;
273:
274: /*
275: * If we sent enough data to get some meaningful characteristics,
276: * save them in the routing entry. 'Enough' is arbitrarily
277: * defined as the sendpipesize (default 4K) * 16. This would
278: * give us 16 rtt samples assuming we only get one sample per
279: * window (the usual case on a long haul net). 16 samples is
280: * enough for the srtt filter to converge to within 5% of the correct
281: * value; fewer samples and we could save a very bogus rtt.
282: *
283: * Don't update the default route's characteristics and don't
284: * update anything that the user "locked".
285: */
286: if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) &&
287: (rt = inp->inp_route.ro_rt) &&
288: ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr != INADDR_ANY) {
289: register u_long i;
290:
291: if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
292: i = tp->t_srtt *
293: (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
294: if (rt->rt_rmx.rmx_rtt && i)
295: /*
296: * filter this update to half the old & half
297: * the new values, converting scale.
298: * See route.h and tcp_var.h for a
299: * description of the scaling constants.
300: */
301: rt->rt_rmx.rmx_rtt =
302: (rt->rt_rmx.rmx_rtt + i) / 2;
303: else
304: rt->rt_rmx.rmx_rtt = i;
305: }
306: if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
307: i = tp->t_rttvar *
308: (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
309: if (rt->rt_rmx.rmx_rttvar && i)
310: rt->rt_rmx.rmx_rttvar =
311: (rt->rt_rmx.rmx_rttvar + i) / 2;
312: else
313: rt->rt_rmx.rmx_rttvar = i;
314: }
315: /*
316: * update the pipelimit (ssthresh) if it has been updated
317: * already or if a pipesize was specified & the threshhold
318: * got below half the pipesize. I.e., wait for bad news
319: * before we start updating, then update on both good
320: * and bad news.
321: */
322: if ((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&
323: (i = tp->snd_ssthresh) && rt->rt_rmx.rmx_ssthresh ||
324: i < (rt->rt_rmx.rmx_sendpipe / 2)) {
325: /*
326: * convert the limit from user data bytes to
327: * packets then to packet data bytes.
328: */
329: i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
330: if (i < 2)
331: i = 2;
332: i *= (u_long)(tp->t_maxseg + sizeof (struct tcpiphdr));
333: if (rt->rt_rmx.rmx_ssthresh)
334: rt->rt_rmx.rmx_ssthresh =
335: (rt->rt_rmx.rmx_ssthresh + i) / 2;
336: else
337: rt->rt_rmx.rmx_ssthresh = i;
338: }
339: }
340: #endif RTV_RTT
341: /* free the reassembly queue, if any */
342: t = tp->seg_next;
343: while (t != (struct tcpiphdr *)tp) {
344: t = (struct tcpiphdr *)t->ti_next;
345: m = REASS_MBUF((struct tcpiphdr *)t->ti_prev);
346: remque(t->ti_prev);
347: m_freem(m);
348: }
349: if (tp->t_template)
350: (void) m_free(dtom(tp->t_template));
351: (void) m_free(dtom(tp));
352: inp->inp_ppcb = 0;
353: soisdisconnected(so);
354: /* clobber input pcb cache if we're closing the cached connection */
355: if (inp == tcp_last_inpcb)
356: tcp_last_inpcb = &tcb;
357: in_pcbdetach(inp);
358: tcpstat.tcps_closed++;
359: return ((struct tcpcb *)0);
360: }
361:
362: tcp_drain()
363: {
364:
365: }
366:
367: /*
368: * Notify a tcp user of an asynchronous error;
369: * store error as soft error, but wake up user
370: * (for now, won't do anything until can select for soft error).
371: */
372: tcp_notify(inp, error)
373: register struct inpcb *inp;
374: int error;
375: {
376:
377: ((struct tcpcb *)inp->inp_ppcb)->t_softerror = error;
378: wakeup((caddr_t) &inp->inp_socket->so_timeo);
379: sorwakeup(inp->inp_socket);
380: sowwakeup(inp->inp_socket);
381: }
382:
383: tcp_ctlinput(cmd, sa, ip)
384: int cmd;
385: struct sockaddr *sa;
386: register struct ip *ip;
387: {
388: register struct tcphdr *th;
389: extern struct in_addr zeroin_addr;
390: extern u_char inetctlerrmap[];
391: int (*notify)() = tcp_notify, tcp_quench();
392:
393: if (cmd == PRC_QUENCH)
394: notify = tcp_quench;
395: else if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)
396: return;
397: if (ip) {
398: th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
1.1.1.2 ! root 399: /* Ignore forged ICMP_UNREACH with dport==0 and sport==0. */
! 400: if (!th->th_dport || !th->th_sport)
! 401: return;
1.1 root 402: in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport,
403: cmd, notify);
404: } else
405: in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify);
406: }
407:
408: /*
409: * When a source quench is received, close congestion window
410: * to one segment. We will gradually open it again as we proceed.
411: */
412: tcp_quench(inp)
413: struct inpcb *inp;
414: {
415: struct tcpcb *tp = intotcpcb(inp);
416:
417: if (tp)
418: tp->snd_cwnd = tp->t_maxseg;
419: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.