ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/slirp/tcp_output.c
Revision: 1.2
Committed: 2012-03-30T01:10:28Z (12 years, 2 months ago) by asvitkine
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -5 lines
Log Message:
Switch slirp to 3-clause BSD license. This change went in upstream to QEMU's
version of slirp (where this code comes from), with the following checkin:

commit 2f5f89963186d42a7ded253bc6cf5b32abb45cec
Author: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Mon Jan 26 19:37:41 2009 +0000

    Remove the advertising clause from the slirp license

    According to the FSF, the 4-clause BSD license, which slirp is covered under,
    is not compatible with the GPL or LGPL[1].

    [1] http://www.fsf.org/licensing/licenses/index_html#GPLIncompatibleLicenses

    There are three declared copyright holders in slirp that use the 4-clause
    BSD license, the Regents of UC Berkley, Danny Gasparovski, and Kelly Price.
    Below are the appropriate permissions to remove the advertise clause from slirp
    from each party.

    Special thanks go to Richard Fontana from Red Hat for contacting all of the
    necessary authors to resolve this issue!

    Regents of UC Berkley:
    From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change

    July 22, 1999

    To All Licensees, Distributors of Any Version of BSD:

    As you know, certain of the Berkeley Software Distribution ("BSD") source
    code files require that further distributions of products containing all or
    portions of the software, acknowledge within their advertising materials
    that such products contain software developed by UC Berkeley and its
    contributors.

    Specifically, the provision reads:

    "     * 3. All advertising materials mentioning features or use of this software
          *    must display the following acknowledgement:
          *    This product includes software developed by the University of
          *    California, Berkeley and its contributors."

    Effective immediately, licensees and distributors are no longer required to
    include the acknowledgement within advertising materials.  Accordingly, the
    foregoing paragraph of those BSD Unix files containing it is hereby deleted
    in its entirety.

    William Hoskins
    Director, Office of Technology Licensing
    University of California, Berkeley

    Danny Gasparovski:

    Subject: RE: Slirp license
    Date: Thu, 8 Jan 2009 10:51:00 +1100
    From: "Gasparovski, Daniel" <Daniel.Gasparovski@ato.gov.au>
    To: "Richard Fontana" <rfontana@redhat.com>

    Hi Richard,

    I have no objection to having Slirp code in QEMU be licensed under the
    3-clause BSD license.

    Thanks for taking the effort to consult me about this.


    Dan ...

    Kelly Price:

    Date: Thu, 8 Jan 2009 19:38:56 -0500
    From: "Kelly Price" <strredwolf@gmail.com>
    To: "Richard Fontana" <rfontana@redhat.com>
    Subject: Re: Slirp license

    Thanks for contacting me, Richard.  I'm glad you were able to find
    Dan, as I've been "keeping the light on" for Slirp.  I have no use for
    it now, and I have little time for it (now holding onto Keenspot's
    Comic Genesis and having a regular US state government position). If
    Dan would like to return to the project, I'd love to give it back to
    him.

    As for copyright, I don't own all of it.  Dan does, so I will defer to
    him.  Any of my patches I will gladly license to the 3-part BSD
    license.  My interest in re-licensing was because we didn't have ready
    info to contact Dan.  If Dan would like to port Slirp back out of
    QEMU, a lot of us 64-bit users would be grateful.

    Feel free to share this email address with Dan.  I will be glad to
    effect a transfer of the project to him and Mr. Bellard of the QEMU
    project.

    Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6451 c046a42c-6fe2-441c-8c8c-71466251a162

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * Copyright (c) 1982, 1986, 1988, 1990, 1993
3     * The Regents of the University of California. 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 asvitkine 1.2 * 3. Neither the name of the University nor the names of its contributors
14 gbeauche 1.1 * may be used to endorse or promote products derived from this software
15     * without specific prior written permission.
16     *
17     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20     * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27     * SUCH DAMAGE.
28     *
29     * @(#)tcp_output.c 8.3 (Berkeley) 12/30/93
30     * tcp_output.c,v 1.3 1994/09/15 10:36:55 davidg Exp
31     */
32    
33     /*
34     * Changes and additions relating to SLiRP
35     * Copyright (c) 1995 Danny Gasparovski.
36     *
37     * Please read the file COPYRIGHT for the
38     * terms and conditions of the copyright.
39     */
40    
41     #include <slirp.h>
42    
43     /*
44     * Since this is only used in "stats socket", we give meaning
45     * names instead of the REAL names
46     */
47     char *tcpstates[] = {
48     /* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */
49     "REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD",
50     "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
51     "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT",
52     };
53    
54     u_char tcp_outflags[TCP_NSTATES] = {
55     TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
56     TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
57     TH_FIN|TH_ACK, TH_ACK, TH_ACK,
58     };
59    
60    
61     #define MAX_TCPOPTLEN 32 /* max # bytes that go in options */
62    
63     /*
64     * Tcp output routine: figure out what should be sent and send it.
65     */
66     int
67     tcp_output(tp)
68     register struct tcpcb *tp;
69     {
70     register struct socket *so = tp->t_socket;
71     register long len, win;
72     int off, flags, error;
73     register struct mbuf *m;
74     register struct tcpiphdr *ti;
75     u_char opt[MAX_TCPOPTLEN];
76     unsigned optlen, hdrlen;
77     int idle, sendalot;
78    
79     DEBUG_CALL("tcp_output");
80     DEBUG_ARG("tp = %lx", (long )tp);
81    
82     /*
83     * Determine length of data that should be transmitted,
84     * and flags that will be used.
85     * If there is some data or critical controls (SYN, RST)
86     * to send, then transmit; otherwise, investigate further.
87     */
88     idle = (tp->snd_max == tp->snd_una);
89     if (idle && tp->t_idle >= tp->t_rxtcur)
90     /*
91     * We have been idle for "a while" and no acks are
92     * expected to clock out any data we send --
93     * slow start to get ack "clock" running again.
94     */
95     tp->snd_cwnd = tp->t_maxseg;
96     again:
97     sendalot = 0;
98     off = tp->snd_nxt - tp->snd_una;
99     win = min(tp->snd_wnd, tp->snd_cwnd);
100    
101     flags = tcp_outflags[tp->t_state];
102    
103     DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
104    
105     /*
106     * If in persist timeout with window of 0, send 1 byte.
107     * Otherwise, if window is small but nonzero
108     * and timer expired, we will send what we can
109     * and go to transmit state.
110     */
111     if (tp->t_force) {
112     if (win == 0) {
113     /*
114     * If we still have some data to send, then
115     * clear the FIN bit. Usually this would
116     * happen below when it realizes that we
117     * aren't sending all the data. However,
118     * if we have exactly 1 byte of unset data,
119     * then it won't clear the FIN bit below,
120     * and if we are in persist state, we wind
121     * up sending the packet without recording
122     * that we sent the FIN bit.
123     *
124     * We can't just blindly clear the FIN bit,
125     * because if we don't have any more data
126     * to send then the probe will be the FIN
127     * itself.
128     */
129     if (off < so->so_snd.sb_cc)
130     flags &= ~TH_FIN;
131     win = 1;
132     } else {
133     tp->t_timer[TCPT_PERSIST] = 0;
134     tp->t_rxtshift = 0;
135     }
136     }
137    
138     len = min(so->so_snd.sb_cc, win) - off;
139    
140     if (len < 0) {
141     /*
142     * If FIN has been sent but not acked,
143     * but we haven't been called to retransmit,
144     * len will be -1. Otherwise, window shrank
145     * after we sent into it. If window shrank to 0,
146     * cancel pending retransmit and pull snd_nxt
147     * back to (closed) window. We will enter persist
148     * state below. If the window didn't close completely,
149     * just wait for an ACK.
150     */
151     len = 0;
152     if (win == 0) {
153     tp->t_timer[TCPT_REXMT] = 0;
154     tp->snd_nxt = tp->snd_una;
155     }
156     }
157    
158     if (len > tp->t_maxseg) {
159     len = tp->t_maxseg;
160     sendalot = 1;
161     }
162     if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
163     flags &= ~TH_FIN;
164    
165     win = sbspace(&so->so_rcv);
166    
167     /*
168     * Sender silly window avoidance. If connection is idle
169     * and can send all data, a maximum segment,
170     * at least a maximum default-size segment do it,
171     * or are forced, do it; otherwise don't bother.
172     * If peer's buffer is tiny, then send
173     * when window is at least half open.
174     * If retransmitting (possibly after persist timer forced us
175     * to send into a small window), then must resend.
176     */
177     if (len) {
178     if (len == tp->t_maxseg)
179     goto send;
180     if ((1 || idle || tp->t_flags & TF_NODELAY) &&
181     len + off >= so->so_snd.sb_cc)
182     goto send;
183     if (tp->t_force)
184     goto send;
185     if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)
186     goto send;
187     if (SEQ_LT(tp->snd_nxt, tp->snd_max))
188     goto send;
189     }
190    
191     /*
192     * Compare available window to amount of window
193     * known to peer (as advertised window less
194     * next expected input). If the difference is at least two
195     * max size segments, or at least 50% of the maximum possible
196     * window, then want to send a window update to peer.
197     */
198     if (win > 0) {
199     /*
200     * "adv" is the amount we can increase the window,
201     * taking into account that we are limited by
202     * TCP_MAXWIN << tp->rcv_scale.
203     */
204     long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
205     (tp->rcv_adv - tp->rcv_nxt);
206    
207     if (adv >= (long) (2 * tp->t_maxseg))
208     goto send;
209     if (2 * adv >= (long) so->so_rcv.sb_datalen)
210     goto send;
211     }
212    
213     /*
214     * Send if we owe peer an ACK.
215     */
216     if (tp->t_flags & TF_ACKNOW)
217     goto send;
218     if (flags & (TH_SYN|TH_RST))
219     goto send;
220     if (SEQ_GT(tp->snd_up, tp->snd_una))
221     goto send;
222     /*
223     * If our state indicates that FIN should be sent
224     * and we have not yet done so, or we're retransmitting the FIN,
225     * then we need to send.
226     */
227     if (flags & TH_FIN &&
228     ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
229     goto send;
230    
231     /*
232     * TCP window updates are not reliable, rather a polling protocol
233     * using ``persist'' packets is used to insure receipt of window
234     * updates. The three ``states'' for the output side are:
235     * idle not doing retransmits or persists
236     * persisting to move a small or zero window
237     * (re)transmitting and thereby not persisting
238     *
239     * tp->t_timer[TCPT_PERSIST]
240     * is set when we are in persist state.
241     * tp->t_force
242     * is set when we are called to send a persist packet.
243     * tp->t_timer[TCPT_REXMT]
244     * is set when we are retransmitting
245     * The output side is idle when both timers are zero.
246     *
247     * If send window is too small, there is data to transmit, and no
248     * retransmit or persist is pending, then go to persist state.
249     * If nothing happens soon, send when timer expires:
250     * if window is nonzero, transmit what we can,
251     * otherwise force out a byte.
252     */
253     if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 &&
254     tp->t_timer[TCPT_PERSIST] == 0) {
255     tp->t_rxtshift = 0;
256     tcp_setpersist(tp);
257     }
258    
259     /*
260     * No reason to send a segment, just return.
261     */
262     tcpstat.tcps_didnuttin++;
263    
264     return (0);
265    
266     send:
267     /*
268     * Before ESTABLISHED, force sending of initial options
269     * unless TCP set not to do any options.
270     * NOTE: we assume that the IP/TCP header plus TCP options
271     * always fit in a single mbuf, leaving room for a maximum
272     * link header, i.e.
273     * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
274     */
275     optlen = 0;
276     hdrlen = sizeof (struct tcpiphdr);
277     if (flags & TH_SYN) {
278     tp->snd_nxt = tp->iss;
279     if ((tp->t_flags & TF_NOOPT) == 0) {
280     u_int16_t mss;
281    
282     opt[0] = TCPOPT_MAXSEG;
283     opt[1] = 4;
284     mss = htons((u_int16_t) tcp_mss(tp, 0));
285     memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));
286     optlen = 4;
287    
288     /* if ((tp->t_flags & TF_REQ_SCALE) &&
289     * ((flags & TH_ACK) == 0 ||
290     * (tp->t_flags & TF_RCVD_SCALE))) {
291     * *((u_int32_t *) (opt + optlen)) = htonl(
292     * TCPOPT_NOP << 24 |
293     * TCPOPT_WINDOW << 16 |
294     * TCPOLEN_WINDOW << 8 |
295     * tp->request_r_scale);
296     * optlen += 4;
297     * }
298     */
299     }
300     }
301    
302     /*
303     * Send a timestamp and echo-reply if this is a SYN and our side
304     * wants to use timestamps (TF_REQ_TSTMP is set) or both our side
305     * and our peer have sent timestamps in our SYN's.
306     */
307     /* if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
308     * (flags & TH_RST) == 0 &&
309     * ((flags & (TH_SYN|TH_ACK)) == TH_SYN ||
310     * (tp->t_flags & TF_RCVD_TSTMP))) {
311     * u_int32_t *lp = (u_int32_t *)(opt + optlen);
312     *
313     * / * Form timestamp option as shown in appendix A of RFC 1323. * /
314     * *lp++ = htonl(TCPOPT_TSTAMP_HDR);
315     * *lp++ = htonl(tcp_now);
316     * *lp = htonl(tp->ts_recent);
317     * optlen += TCPOLEN_TSTAMP_APPA;
318     * }
319     */
320     hdrlen += optlen;
321    
322     /*
323     * Adjust data length if insertion of options will
324     * bump the packet length beyond the t_maxseg length.
325     */
326     if (len > tp->t_maxseg - optlen) {
327     len = tp->t_maxseg - optlen;
328     sendalot = 1;
329     }
330    
331     /*
332     * Grab a header mbuf, attaching a copy of data to
333     * be transmitted, and initialize the header from
334     * the template for sends on this connection.
335     */
336     if (len) {
337     if (tp->t_force && len == 1)
338     tcpstat.tcps_sndprobe++;
339     else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
340     tcpstat.tcps_sndrexmitpack++;
341     tcpstat.tcps_sndrexmitbyte += len;
342     } else {
343     tcpstat.tcps_sndpack++;
344     tcpstat.tcps_sndbyte += len;
345     }
346    
347     m = m_get();
348     if (m == NULL) {
349     /* error = ENOBUFS; */
350     error = 1;
351     goto out;
352     }
353     m->m_data += if_maxlinkhdr;
354     m->m_len = hdrlen;
355    
356     /*
357     * This will always succeed, since we make sure our mbufs
358     * are big enough to hold one MSS packet + header + ... etc.
359     */
360     /* if (len <= MHLEN - hdrlen - max_linkhdr) { */
361    
362     sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
363     m->m_len += len;
364    
365     /* } else {
366     * m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
367     * if (m->m_next == 0)
368     * len = 0;
369     * }
370     */
371     /*
372     * If we're sending everything we've got, set PUSH.
373     * (This will keep happy those implementations which only
374     * give data to the user when a buffer fills or
375     * a PUSH comes in.)
376     */
377     if (off + len == so->so_snd.sb_cc)
378     flags |= TH_PUSH;
379     } else {
380     if (tp->t_flags & TF_ACKNOW)
381     tcpstat.tcps_sndacks++;
382     else if (flags & (TH_SYN|TH_FIN|TH_RST))
383     tcpstat.tcps_sndctrl++;
384     else if (SEQ_GT(tp->snd_up, tp->snd_una))
385     tcpstat.tcps_sndurg++;
386     else
387     tcpstat.tcps_sndwinup++;
388    
389     m = m_get();
390     if (m == NULL) {
391     /* error = ENOBUFS; */
392     error = 1;
393     goto out;
394     }
395     m->m_data += if_maxlinkhdr;
396     m->m_len = hdrlen;
397     }
398    
399     ti = mtod(m, struct tcpiphdr *);
400    
401     memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
402    
403     /*
404     * Fill in fields, remembering maximum advertised
405     * window for use in delaying messages about window sizes.
406     * If resending a FIN, be sure not to use a new sequence number.
407     */
408     if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
409     tp->snd_nxt == tp->snd_max)
410     tp->snd_nxt--;
411     /*
412     * If we are doing retransmissions, then snd_nxt will
413     * not reflect the first unsent octet. For ACK only
414     * packets, we do not want the sequence number of the
415     * retransmitted packet, we want the sequence number
416     * of the next unsent octet. So, if there is no data
417     * (and no SYN or FIN), use snd_max instead of snd_nxt
418     * when filling in ti_seq. But if we are in persist
419     * state, snd_max might reflect one byte beyond the
420     * right edge of the window, so use snd_nxt in that
421     * case, since we know we aren't doing a retransmission.
422     * (retransmit and persist are mutually exclusive...)
423     */
424     if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
425     ti->ti_seq = htonl(tp->snd_nxt);
426     else
427     ti->ti_seq = htonl(tp->snd_max);
428     ti->ti_ack = htonl(tp->rcv_nxt);
429     if (optlen) {
430     memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);
431     ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
432     }
433     ti->ti_flags = flags;
434     /*
435     * Calculate receive window. Don't shrink window,
436     * but avoid silly window syndrome.
437     */
438     if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
439     win = 0;
440     if (win > (long)TCP_MAXWIN << tp->rcv_scale)
441     win = (long)TCP_MAXWIN << tp->rcv_scale;
442     if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
443     win = (long)(tp->rcv_adv - tp->rcv_nxt);
444     ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale));
445    
446     if (SEQ_GT(tp->snd_up, tp->snd_una)) {
447     ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq)));
448     #ifdef notdef
449     if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
450     ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));
451     #endif
452     ti->ti_flags |= TH_URG;
453     } else
454     /*
455     * If no urgent pointer to send, then we pull
456     * the urgent pointer to the left edge of the send window
457     * so that it doesn't drift into the send window on sequence
458     * number wraparound.
459     */
460     tp->snd_up = tp->snd_una; /* drag it along */
461    
462     /*
463     * Put TCP length in extended header, and then
464     * checksum extended header and data.
465     */
466     if (len + optlen)
467     ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) +
468     optlen + len));
469     ti->ti_sum = cksum(m, (int)(hdrlen + len));
470    
471     /*
472     * In transmit state, time the transmission and arrange for
473     * the retransmit. In persist state, just set snd_max.
474     */
475     if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {
476     tcp_seq startseq = tp->snd_nxt;
477    
478     /*
479     * Advance snd_nxt over sequence space of this segment.
480     */
481     if (flags & (TH_SYN|TH_FIN)) {
482     if (flags & TH_SYN)
483     tp->snd_nxt++;
484     if (flags & TH_FIN) {
485     tp->snd_nxt++;
486     tp->t_flags |= TF_SENTFIN;
487     }
488     }
489     tp->snd_nxt += len;
490     if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
491     tp->snd_max = tp->snd_nxt;
492     /*
493     * Time this transmission if not a retransmission and
494     * not currently timing anything.
495     */
496     if (tp->t_rtt == 0) {
497     tp->t_rtt = 1;
498     tp->t_rtseq = startseq;
499     tcpstat.tcps_segstimed++;
500     }
501     }
502    
503     /*
504     * Set retransmit timer if not currently set,
505     * and not doing an ack or a keep-alive probe.
506     * Initial value for retransmit timer is smoothed
507     * round-trip time + 2 * round-trip time variance.
508     * Initialize shift counter which is used for backoff
509     * of retransmit time.
510     */
511     if (tp->t_timer[TCPT_REXMT] == 0 &&
512     tp->snd_nxt != tp->snd_una) {
513     tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
514     if (tp->t_timer[TCPT_PERSIST]) {
515     tp->t_timer[TCPT_PERSIST] = 0;
516     tp->t_rxtshift = 0;
517     }
518     }
519     } else
520     if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
521     tp->snd_max = tp->snd_nxt + len;
522    
523     /*
524     * Fill in IP length and desired time to live and
525     * send to IP level. There should be a better way
526     * to handle ttl and tos; we could keep them in
527     * the template, but need a way to checksum without them.
528     */
529     m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
530    
531     {
532    
533     ((struct ip *)ti)->ip_len = m->m_len;
534    
535     ((struct ip *)ti)->ip_ttl = ip_defttl;
536     ((struct ip *)ti)->ip_tos = so->so_iptos;
537    
538     /* #if BSD >= 43 */
539     /* Don't do IP options... */
540     /* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
541     * so->so_options & SO_DONTROUTE, 0);
542     */
543     error = ip_output(so, m);
544    
545     /* #else
546     * error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
547     * so->so_options & SO_DONTROUTE);
548     * #endif
549     */
550     }
551     if (error) {
552     out:
553     /* if (error == ENOBUFS) {
554     * tcp_quench(tp->t_inpcb, 0);
555     * return (0);
556     * }
557     */
558     /* if ((error == EHOSTUNREACH || error == ENETDOWN)
559     * && TCPS_HAVERCVDSYN(tp->t_state)) {
560     * tp->t_softerror = error;
561     * return (0);
562     * }
563     */
564     return (error);
565     }
566     tcpstat.tcps_sndtotal++;
567    
568     /*
569     * Data sent (as far as we can tell).
570     * If this advertises a larger window than any other segment,
571     * then remember the size of the advertised window.
572     * Any pending ACK has now been sent.
573     */
574     if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
575     tp->rcv_adv = tp->rcv_nxt + win;
576     tp->last_ack_sent = tp->rcv_nxt;
577     tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
578     if (sendalot)
579     goto again;
580    
581     return (0);
582     }
583    
584     void
585     tcp_setpersist(tp)
586     register struct tcpcb *tp;
587     {
588     int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
589    
590     /* if (tp->t_timer[TCPT_REXMT])
591     * panic("tcp_output REXMT");
592     */
593     /*
594     * Start/restart persistence timer.
595     */
596     TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
597     t * tcp_backoff[tp->t_rxtshift],
598     TCPTV_PERSMIN, TCPTV_PERSMAX);
599     if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
600     tp->t_rxtshift++;
601     }