1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39#include "slirp.h"
40
41static const uint8_t tcp_outflags[TCP_NSTATES] = {
42 TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
43 TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
44 TH_FIN|TH_ACK, TH_ACK, TH_ACK,
45};
46
47
48#undef MAX_TCPOPTLEN
49#define MAX_TCPOPTLEN 32
50
51
52
53
54int
55tcp_output(struct tcpcb *tp)
56{
57 register struct socket *so = tp->t_socket;
58 register long len, win;
59 int off, flags, error;
60 register struct mbuf *m;
61 register struct tcpiphdr *ti, tcpiph_save;
62 struct ip *ip;
63 struct ip6 *ip6;
64 uint8_t opt[MAX_TCPOPTLEN];
65 unsigned optlen, hdrlen;
66 int idle, sendalot;
67
68 DEBUG_CALL("tcp_output");
69 DEBUG_ARG("tp = %p", tp);
70
71
72
73
74
75
76
77 idle = (tp->snd_max == tp->snd_una);
78 if (idle && tp->t_idle >= tp->t_rxtcur)
79
80
81
82
83
84 tp->snd_cwnd = tp->t_maxseg;
85again:
86 sendalot = 0;
87 off = tp->snd_nxt - tp->snd_una;
88 win = MIN(tp->snd_wnd, tp->snd_cwnd);
89
90 flags = tcp_outflags[tp->t_state];
91
92 DEBUG_MISC(" --- tcp_output flags = 0x%x", flags);
93
94
95
96
97
98
99
100 if (tp->t_force) {
101 if (win == 0) {
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 if (off < so->so_snd.sb_cc)
119 flags &= ~TH_FIN;
120 win = 1;
121 } else {
122 tp->t_timer[TCPT_PERSIST] = 0;
123 tp->t_rxtshift = 0;
124 }
125 }
126
127 len = MIN(so->so_snd.sb_cc, win) - off;
128
129 if (len < 0) {
130
131
132
133
134
135
136
137
138
139
140 len = 0;
141 if (win == 0) {
142 tp->t_timer[TCPT_REXMT] = 0;
143 tp->snd_nxt = tp->snd_una;
144 }
145 }
146
147 if (len > tp->t_maxseg) {
148 len = tp->t_maxseg;
149 sendalot = 1;
150 }
151 if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
152 flags &= ~TH_FIN;
153
154 win = sbspace(&so->so_rcv);
155
156
157
158
159
160
161
162
163
164
165
166 if (len) {
167 if (len == tp->t_maxseg)
168 goto send;
169 if ((1 || idle || tp->t_flags & TF_NODELAY) &&
170 len + off >= so->so_snd.sb_cc)
171 goto send;
172 if (tp->t_force)
173 goto send;
174 if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)
175 goto send;
176 if (SEQ_LT(tp->snd_nxt, tp->snd_max))
177 goto send;
178 }
179
180
181
182
183
184
185
186
187 if (win > 0) {
188
189
190
191
192
193 long adv = MIN(win, (long)TCP_MAXWIN << tp->rcv_scale) -
194 (tp->rcv_adv - tp->rcv_nxt);
195
196 if (adv >= (long) (2 * tp->t_maxseg))
197 goto send;
198 if (2 * adv >= (long) so->so_rcv.sb_datalen)
199 goto send;
200 }
201
202
203
204
205 if (tp->t_flags & TF_ACKNOW)
206 goto send;
207 if (flags & (TH_SYN|TH_RST))
208 goto send;
209 if (SEQ_GT(tp->snd_up, tp->snd_una))
210 goto send;
211
212
213
214
215
216 if (flags & TH_FIN &&
217 ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
218 goto send;
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242 if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 &&
243 tp->t_timer[TCPT_PERSIST] == 0) {
244 tp->t_rxtshift = 0;
245 tcp_setpersist(tp);
246 }
247
248
249
250
251 return (0);
252
253send:
254
255
256
257
258
259
260
261
262 optlen = 0;
263 hdrlen = sizeof (struct tcpiphdr);
264 if (flags & TH_SYN) {
265 tp->snd_nxt = tp->iss;
266 if ((tp->t_flags & TF_NOOPT) == 0) {
267 uint16_t mss;
268
269 opt[0] = TCPOPT_MAXSEG;
270 opt[1] = 4;
271 mss = htons((uint16_t) tcp_mss(tp, 0));
272 memcpy((char *)(opt + 2), (char *)&mss, sizeof(mss));
273 optlen = 4;
274 }
275 }
276
277 hdrlen += optlen;
278
279
280
281
282
283 if (len > tp->t_maxseg - optlen) {
284 len = tp->t_maxseg - optlen;
285 sendalot = 1;
286 }
287
288
289
290
291
292
293 if (len) {
294 m = m_get(so->slirp);
295 if (m == NULL) {
296 error = 1;
297 goto out;
298 }
299 m->m_data += IF_MAXLINKHDR;
300 m->m_len = hdrlen;
301
302 sbcopy(&so->so_snd, off, (int) len, mtod(m, char *) + hdrlen);
303 m->m_len += len;
304
305
306
307
308
309
310
311 if (off + len == so->so_snd.sb_cc)
312 flags |= TH_PUSH;
313 } else {
314 m = m_get(so->slirp);
315 if (m == NULL) {
316 error = 1;
317 goto out;
318 }
319 m->m_data += IF_MAXLINKHDR;
320 m->m_len = hdrlen;
321 }
322
323 ti = mtod(m, struct tcpiphdr *);
324
325 memcpy((char *)ti, &tp->t_template, sizeof (struct tcpiphdr));
326
327
328
329
330
331
332 if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
333 tp->snd_nxt == tp->snd_max)
334 tp->snd_nxt--;
335
336
337
338
339
340
341
342
343
344
345
346
347
348 if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
349 ti->ti_seq = htonl(tp->snd_nxt);
350 else
351 ti->ti_seq = htonl(tp->snd_max);
352 ti->ti_ack = htonl(tp->rcv_nxt);
353 if (optlen) {
354 memcpy((char *)(ti + 1), (char *)opt, optlen);
355 ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
356 }
357 ti->ti_flags = flags;
358
359
360
361
362 if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
363 win = 0;
364 if (win > (long)TCP_MAXWIN << tp->rcv_scale)
365 win = (long)TCP_MAXWIN << tp->rcv_scale;
366 if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
367 win = (long)(tp->rcv_adv - tp->rcv_nxt);
368 ti->ti_win = htons((uint16_t) (win>>tp->rcv_scale));
369
370 if (SEQ_GT(tp->snd_up, tp->snd_una)) {
371 ti->ti_urp = htons((uint16_t)(tp->snd_up - ntohl(ti->ti_seq)));
372 ti->ti_flags |= TH_URG;
373 } else
374
375
376
377
378
379
380 tp->snd_up = tp->snd_una;
381
382
383
384
385
386 if (len + optlen)
387 ti->ti_len = htons((uint16_t)(sizeof (struct tcphdr) +
388 optlen + len));
389 ti->ti_sum = cksum(m, (int)(hdrlen + len));
390
391
392
393
394
395 if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {
396 tcp_seq startseq = tp->snd_nxt;
397
398
399
400
401 if (flags & (TH_SYN|TH_FIN)) {
402 if (flags & TH_SYN)
403 tp->snd_nxt++;
404 if (flags & TH_FIN) {
405 tp->snd_nxt++;
406 tp->t_flags |= TF_SENTFIN;
407 }
408 }
409 tp->snd_nxt += len;
410 if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
411 tp->snd_max = tp->snd_nxt;
412
413
414
415
416 if (tp->t_rtt == 0) {
417 tp->t_rtt = 1;
418 tp->t_rtseq = startseq;
419 }
420 }
421
422
423
424
425
426
427
428
429
430 if (tp->t_timer[TCPT_REXMT] == 0 &&
431 tp->snd_nxt != tp->snd_una) {
432 tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
433 if (tp->t_timer[TCPT_PERSIST]) {
434 tp->t_timer[TCPT_PERSIST] = 0;
435 tp->t_rxtshift = 0;
436 }
437 }
438 } else
439 if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
440 tp->snd_max = tp->snd_nxt + len;
441
442
443
444
445
446
447
448 m->m_len = hdrlen + len;
449 tcpiph_save = *mtod(m, struct tcpiphdr *);
450
451 switch (so->so_ffamily) {
452 case AF_INET:
453 m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
454 - sizeof(struct ip);
455 m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
456 - sizeof(struct ip);
457 ip = mtod(m, struct ip *);
458
459 ip->ip_len = m->m_len;
460 ip->ip_dst = tcpiph_save.ti_dst;
461 ip->ip_src = tcpiph_save.ti_src;
462 ip->ip_p = tcpiph_save.ti_pr;
463
464 ip->ip_ttl = IPDEFTTL;
465 ip->ip_tos = so->so_iptos;
466 error = ip_output(so, m);
467 break;
468
469 case AF_INET6:
470 m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
471 - sizeof(struct ip6);
472 m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
473 - sizeof(struct ip6);
474 ip6 = mtod(m, struct ip6 *);
475
476 ip6->ip_pl = tcpiph_save.ti_len;
477 ip6->ip_dst = tcpiph_save.ti_dst6;
478 ip6->ip_src = tcpiph_save.ti_src6;
479 ip6->ip_nh = tcpiph_save.ti_nh6;
480
481 error = ip6_output(so, m, 0);
482 break;
483
484 default:
485 g_assert_not_reached();
486 }
487
488 if (error) {
489out:
490 return (error);
491 }
492
493
494
495
496
497
498
499 if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
500 tp->rcv_adv = tp->rcv_nxt + win;
501 tp->last_ack_sent = tp->rcv_nxt;
502 tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
503 if (sendalot)
504 goto again;
505
506 return (0);
507}
508
509void
510tcp_setpersist(struct tcpcb *tp)
511{
512 int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
513
514
515
516
517 TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
518 t * tcp_backoff[tp->t_rxtshift],
519 TCPTV_PERSMIN, TCPTV_PERSMAX);
520 if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
521 tp->t_rxtshift++;
522}
523