xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 4547)
1 /* tcp_usrreq.c 1.3 81/10/18 */
2 #include "../h/param.h"
3 #include "../bbnnet/net.h"
4 #include "../bbnnet/tcp.h"
5 #include "../bbnnet/ip.h"
6 #include "../bbnnet/imp.h"
7 #include "../bbnnet/ucb.h"
8 #include "../bbnnet/fsm.h"
9 #include "../bbnnet/tcp_pred.h"
10 
11 lis_cls(wp)             /* passive open (1) */
12 struct work *wp;
13 {
14 
15 COUNT(LIS_CLS);
16 	t_open(wp->w_tcb, PASSIVE);
17 
18 	return(LISTEN);
19 }
20 
21 sys_cls(wp)             /* active open (6) */
22 register struct work *wp;
23 {
24 
25 COUNT(SYS_CLS);
26 	t_open(wp->w_tcb, ACTIVE);
27 	send_ctl(wp->w_tcb);            /* send SYN */
28 
29 	return(SYN_SENT);
30 }
31 
32 cls_opn(wp)             /* close request before receiving foreign SYN (10) */
33 struct work *wp;
34 {
35 
36 COUNT(CLS_OPN);
37 	t_close(wp->w_tcb, UCLOSED);
38 
39 	return(CLOSED);
40 }
41 
42 cl2_clw(wp)             /* close request after receiving foreign FIN (13) */
43 struct work *wp;
44 {
45 	register struct tcb *tp;
46 
47 COUNT(CL2_CLW);
48 	tp = wp->w_tcb;
49 
50 	tp->snd_fin = TRUE;             /* send our own FIN */
51 	send_ctl(tp);
52 	tp->usr_closed = TRUE;
53 
54 	return(CLOSING2);
55 }
56 
57 cls_rwt(wp)             /* rcv request after foreign close (20) */
58 struct work *wp;
59 {
60 	register struct tcb *tp;
61 
62 COUNT(CLS_RWT);
63 	tp = wp->w_tcb;
64 
65 	present_data(tp);       /* present any remaining data */
66 
67 	if (rcv_empty(tp)) {
68         	t_close(tp, UCLOSED);
69          	return(CLOSED);
70 	} else
71 		return(RCV_WAIT);
72 
73 }
74 
75 fw1_syr(wp)             /* close request on synced connection (24,25) */
76 struct work *wp;
77 {
78 	register struct tcb *tp;
79 
80 COUNT(FW1_SYR);
81 	tp = wp->w_tcb;
82 
83 	tp->snd_fin = TRUE;                     /* send FIN */
84 	send_ctl(tp);
85 	tp->usr_closed = TRUE;
86 
87 	return(FIN_W1);
88 }
89 
90 sss_snd(wp)             /* send request on open connection (40,41) */
91 struct work *wp;
92 {
93 	register struct tcb *tp;
94 	register struct mbuf *m, *n;
95 	register struct ucb *up;
96 	register off;
97 	sequence last;
98 
99 COUNT(SSS_SND);
100 	tp = wp->w_tcb;
101 	up = tp->t_ucb;
102 
103 	last = tp->snd_off;
104 
105 	/* count number of mbufs in send data */
106 
107 	for (m = n = (struct mbuf *)wp->w_dat; m != NULL; m = m->m_next) {
108 		up->uc_ssize++;
109 		last += m->m_len;
110 	}
111 
112 	/* find end of send buffer and append data */
113 
114 	if ((m = up->uc_sbuf) != NULL) {        /* something in send buffer */
115 		while (m->m_next != NULL) {             /* find the end */
116 			m = m->m_next;
117 			last += m->m_len;
118 		}
119 		last += m->m_len;
120 
121 		/* if there's room in old buffer for new data, consolidate */
122 
123 		off = m->m_off + m->m_len;
124 		while (n != NULL && (MSIZE - off) >= n->m_len) {
125 			bcopy((caddr_t)((int)n + n->m_off),
126 			      (caddr_t)((int)m + off), n->m_len);
127 			m->m_len += n->m_len;
128 			off += n->m_len;
129 			up->uc_ssize--;
130 			n = m_free(n);
131 		}
132 		m->m_next = n;
133 
134 	} else                                  /* nothing in send buffer */
135 		up->uc_sbuf = n;
136 
137 	if (up->uc_flags & UEOL) {               /* set EOL */
138 		tp->snd_end = last;
139 	}
140 
141 	if (up->uc_flags & UURG) {              /* urgent data */
142 		tp->snd_urp = last+1;
143 		tp->snd_urg = TRUE;
144 	}
145 
146 	send(tp);
147 
148 	return(SAME);
149 }
150 
151 sss_rcv(wp)             /* rcv request on open connection (42) */
152 struct work *wp;
153 {
154 	register struct tcb *tp;
155 
156 COUNT(SSS_RCV);
157 	tp = wp->w_tcb;
158 
159 	send_ctl(tp);                   /* send new window */
160 	present_data(tp);
161 
162 	return(SAME);
163 }
164 
165 cls_nsy(wp)                  /* abort request on unsynced connection (44) */
166 struct work *wp;
167 {
168 
169 COUNT(CLS_NSY);
170 	t_close(wp->w_tcb, UABORT);
171 
172 	return(CLOSED);
173 }
174 
175 cls_syn(wp)             /* abort request on synced connection (45) */
176 struct work *wp;
177 {
178 	register struct tcb *tp;
179 
180 COUNT(CLS_SYN);
181 	tp = wp->w_tcb;
182 
183 	tp->snd_rst = TRUE;            /* send reset */
184 	send_null(tp);
185 	t_close(tp, UABORT);
186 
187 	return(CLOSED);
188 }
189 
190 cls_act(wp)             /* net closing open connection (47) */
191 struct work *wp;
192 {
193 
194 COUNT(CLS_ACT);
195 	t_close(wp->w_tcb, UNETDWN);
196 
197 	return(CLOSED);
198 }
199 
200 cls_err(wp)             /* invalid user request in closing states */
201 struct work *wp;
202 {
203 COUNT(CLS_ERR);
204 	to_user(wp->w_tcb->t_ucb, UCLSERR);
205 
206 	return(SAME);
207 }
208 
209 timers(wp)              /* timer processor (14,17,34,35,36,37,38) */
210 struct work *wp;
211 {
212 	register struct tcb *tp;
213 	register type;
214 
215 COUNT(TIMERS);
216 	tp = wp->w_tcb;
217 	type = wp->w_stype;
218 
219 	switch (type) {
220 
221 	case TINIT:             /* initialization timer */
222 
223 		if (!tp->syn_acked) {           /* haven't got ACK of our SYN (35) */
224 
225 			t_close(tp, UINTIMO);
226 			return(CLOSED);
227 		}
228 		break;
229 
230 	case TFINACK:           /* fin-ack timer */
231 
232 		if (tp->t_state == TIME_WAIT) {
233 
234 			/* can be sure our ACK of for FIN was rcvd,
235 			   can close if no data left for user */
236 
237 			if (rcv_empty(tp)) {            /* 14 */
238 				t_close(tp, UCLOSED);
239 				return(CLOSED);
240 			} else                          /* 17 */
241 				return(RCV_WAIT);
242 
243 		} else if (tp->t_state == CLOSING1)     /* 37 */
244 
245 			/* safe to close */
246 
247 			tp->waited_2_ml = TRUE;
248 
249 	        break;
250 
251 	case TREXMT:            /* retransmission timer */
252 
253 		/* set up for a retransmission, increase rexmt time
254 		   in case of multiple retransmissions. */
255 
256 	        if (tp->t_rexmt_val > tp->snd_una) {   /* 34 */
257 	        	tp->snd_nxt = tp->snd_una;
258 	        	tp->rexmt = TRUE;
259 			tp->t_xmtime = tp->t_xmtime << 1;
260         		if (tp->t_xmtime > T_REMAX)
261         			tp->t_xmtime = T_REMAX;
262 	        	send(tp);
263 	        }
264 		break;
265 
266 	case TREXMTTL:          /* retransmit too long */
267 
268 		/* tell user */
269 
270         	if (tp->t_rtl_val > tp->snd_una)        /* 36 */
271         		to_user(tp->t_ucb, URXTIMO);
272 
273 		/* if user has already closed, abort the connection */
274 
275 		if (tp->usr_closed) {
276 			t_close(tp, URXTIMO);
277 			return(CLOSED);
278 		}
279 		break;
280 
281 	case TPERSIST:          /* persist timer */
282 
283 		/* force a byte send through closed window */
284 
285         	tp->force_one = TRUE;                   /* 38 */
286         	send(tp);
287 		break;
288 	}
289 
290 	return(SAME);
291 }
292