BSD 4_4 release
[unix-history] / usr / src / sys / netinet / tcp_output.c
index 067df7a..f7452e3 100644 (file)
@@ -1,10 +1,36 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)tcp_output.c        7.29 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)tcp_output.c        8.2 (Berkeley) 8/10/93
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -320,6 +346,11 @@ send:
                m->m_data += max_linkhdr;
                m->m_len = hdrlen;
                if (len <= MHLEN - hdrlen - max_linkhdr) {
                m->m_data += max_linkhdr;
                m->m_len = hdrlen;
                if (len <= MHLEN - hdrlen - max_linkhdr) {
+                       m_copydata(so->so_snd.sb_mb, off, (int) len,
+                           mtod(m, caddr_t) + hdrlen);
+                       m->m_len += len;
+               } else {
+                       m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
                        if (m->m_next == 0)
                                len = 0;
                }
                        if (m->m_next == 0)
                                len = 0;
                }
@@ -364,7 +395,23 @@ send:
        if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && 
            tp->snd_nxt == tp->snd_max)
                tp->snd_nxt--;
        if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && 
            tp->snd_nxt == tp->snd_max)
                tp->snd_nxt--;
-       ti->ti_seq = htonl(tp->snd_nxt);
+       /*
+        * If we are doing retransmissions, then snd_nxt will
+        * not reflect the first unsent octet.  For ACK only
+        * packets, we do not want the sequence number of the
+        * retransmitted packet, we want the sequence number
+        * of the next unsent octet.  So, if there is no data
+        * (and no SYN or FIN), use snd_max instead of snd_nxt
+        * when filling in ti_seq.  But if we are in persist
+        * state, snd_max might reflect one byte beyond the
+        * right edge of the window, so use snd_nxt in that
+        * case, since we know we aren't doing a retransmission.
+        * (retransmit and persist are mutually exclusive...)
+        */
+       if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
+               ti->ti_seq = htonl(tp->snd_nxt);
+       else
+               ti->ti_seq = htonl(tp->snd_max);
        ti->ti_ack = htonl(tp->rcv_nxt);
        if (optlen) {
                bcopy((caddr_t)opt, (caddr_t)(ti + 1), optlen);
        ti->ti_ack = htonl(tp->rcv_nxt);
        if (optlen) {
                bcopy((caddr_t)opt, (caddr_t)(ti + 1), optlen);
@@ -381,8 +428,6 @@ send:
                win = (long)TCP_MAXWIN << tp->rcv_scale;
        if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
                win = (long)(tp->rcv_adv - tp->rcv_nxt);
                win = (long)TCP_MAXWIN << tp->rcv_scale;
        if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
                win = (long)(tp->rcv_adv - tp->rcv_nxt);
-       if (win > IP_MAXPACKET)
-               win = IP_MAXPACKET;
        ti->ti_win = htons((u_short) (win>>tp->rcv_scale));
        if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
                ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
        ti->ti_win = htons((u_short) (win>>tp->rcv_scale));
        if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
                ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
@@ -480,7 +525,6 @@ send:
        ((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl; /* XXX */
        ((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip.ip_tos; /* XXX */
 #if BSD >= 43
        ((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl; /* XXX */
        ((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip.ip_tos; /* XXX */
 #if BSD >= 43
-#if BSD>=43
        error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
            so->so_options & SO_DONTROUTE, 0);
 #else
        error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
            so->so_options & SO_DONTROUTE, 0);
 #else
@@ -488,10 +532,6 @@ send:
            so->so_options & SO_DONTROUTE);
 #endif
     }
            so->so_options & SO_DONTROUTE);
 #endif
     }
-#else
-       error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, 
-                         so->so_options & SO_DONTROUTE);
-#endif
        if (error) {
 out:
                if (error == ENOBUFS) {
        if (error) {
 out:
                if (error == ENOBUFS) {