/* tcp_output.c 4.10 81/11/08 */
#include "../h/socketvar.h"
#include "../net/inet_cksum.h"
#include "../net/inet_host.h"
#include "../net/inet_systm.h"
#include "../net/tcp_var.h"
#include "../net/tcp_fsm.h"
#include "/usr/include/errno.h"
* Special routines to send control messages.
register struct socket
*so
= tp
->t_socket
;
ihave
= so
->so_rcv
.sb_hiwat
-
(so
->so_rcv
.sb_cc
+ tp
->seqcnt
);
hehas
= tp
->rcv_adv
- tp
->rcv_nxt
;
if ((100*(ihave
-hehas
)/so
->so_rcv
.sb_hiwat
) < 35)
tcp_output(tp
, 0, 0, (struct mbuf
*)0);
tp
->tc_flags
&= ~TC_ACK_DUE
;
/* don't send a reset in response to a reset */
tp
->tc_flags
|= TC_SND_RST
;
tp
->snd_nxt
= n
->t_ackno
;
tp
->tc_flags
&= ~TC_SYN_RCVD
;
tp
->tc_flags
&= ~TC_SND_RST
;
* Tcp segment output routine.
register struct socket
*so
;
register unsigned long last
, wind
;
int flags
= 0, forced
, sent
;
struct mbuf
*tcp_sndcopy();
tp
->snd_lst
= tp
->snd_nxt
;
if (tp
->snd_nxt
== tp
->iss
) {
for (m
= so
->so_snd
.sb_mb
; m
!= NULL
; m
= m
->m_next
)
if (tp
->snd_nxt
> last
) {
if ((tp
->tc_flags
&TC_SND_FIN
) &&
(tp
->seq_fin
== tp
->iss
|| tp
->snd_nxt
<= tp
->seq_fin
)) {
tp
->seq_fin
= tp
->snd_lst
++;
if (tp
->tc_flags
&TC_SYN_ACKED
) {
wind
= tp
->snd_una
+ tp
->snd_wnd
;
tp
->snd_lst
= min(last
, wind
);
if ((len
= tp
->snd_lst
- tp
->snd_nxt
) > 1024)
tp
->snd_lst
-= len
- 1024;
if ((tp
->tc_flags
&TC_FORCE_ONE
) && (tp
->snd_lst
== wind
)) {
tp
->snd_lst
= tp
->snd_nxt
+ 1;
} else if (tp
->snd_nxt
>= tp
->snd_lst
&& (tp
->tc_flags
&TC_SND_FIN
) == 0)
m
= tcp_sndcopy(tp
, MAX(tp
->iss
+1,tp
->snd_nxt
), tp
->snd_lst
);
if (tp
->snd_end
> tp
->iss
&& tp
->snd_end
<= tp
->snd_lst
)
if ((tp
->tc_flags
&TC_SND_FIN
) && !forced
&&
(tp
->seq_fin
== tp
->iss
|| tp
->snd_nxt
<= tp
->seq_fin
)) {
tp
->seq_fin
= tp
->snd_lst
++;
if (tp
->snd_nxt
>= tp
->snd_lst
)
if (tp
->tc_flags
& TC_SND_URG
)
sent
= tcp_output(tp
, flags
, tp
->snd_lst
- tp
->snd_nxt
, m
);
tp
->t_rexmt
= tp
->t_xmtime
;
tp
->t_rexmt_val
= tp
->snd_lst
;
if ((tp
->tc_flags
&TC_REXMT
) == 0) {
tp
->t_rexmttl
= T_REXMTTL
;
tp
->t_rtl_val
= tp
->snd_lst
;
tp
->snd_nxt
= tp
->snd_lst
;
if ((tp
->tc_flags
&TC_SYN_ACKED
) &&
tp
->snd_una
> tp
->t_xmt_val
) {
tp
->t_xmt_val
= tp
->snd_lst
;
tp
->tc_flags
&= ~(TC_ACK_DUE
|TC_REXMT
|TC_FORCE_ONE
);
tp
->snd_hi
= MAX(tp
->snd_nxt
, tp
->snd_hi
);
* Create template to be used to send tcp packets on a connection.
* Call after host entry created, allocates an mbuf and fills
* in a skeletal tcp/ip header, minimizing the amount of work
* necessary when the connection is used.
register struct host
*h
= tp
->t_host
;
m
->m_off
= MMAXOFF
- sizeof (struct th
);
m
->m_len
= sizeof (struct th
);
n
= mtod(m
, struct th
*);
n
->t_next
= n
->t_prev
= 0;
n
->t_len
= htons(sizeof (struct th
) - sizeof (struct ip
));
n
->t_s
.s_addr
= n_lhost
.s_addr
;
n
->t_d
.s_addr
= h
->h_addr
.s_addr
;
n
->t_src
= htons(tp
->t_lport
);
n
->t_dst
= htons(tp
->t_fport
);
tcp_output(tp
, flags
, len
, dat
)
register struct th
*t
; /* known to be r9 */
if ((t
= tp
->t_template
) == 0)
m
->m_off
= MMAXOFF
- sizeof(struct th
);
m
->m_len
= sizeof (struct th
);
bcopy((caddr_t
)t
, mtod(m
, caddr_t
), sizeof (struct th
));
t
= mtod(m
, struct th
*);
if (tp
->tc_flags
&TC_SND_RST
) {
if (tp
->tc_flags
&TC_SYN_RCVD
)
t
->t_urp
= htons(tp
->snd_urp
);
tp
->t_socket
->so_rcv
.sb_hiwat
-
(tp
->t_socket
->so_rcv
.sb_cc
+ tp
->seqcnt
);
if (tp
->rcv_nxt
+ t
->t_win
> tp
->rcv_adv
)
tp
->rcv_adv
= tp
->rcv_nxt
+ t
->t_win
;
t
->t_len
= htons(len
+ TCPSIZE
);
t
->t_win
= htons(t
->t_win
);
if ((tp
->t_socket
->so_options
& SO_DEBUG
) || tcpconsdebug
) {
t
->t_ackno
= tp
->rcv_nxt
;
tdb_setup(tp
, t
, INSEND
, &tdb
);
t
->t_seq
= htonl(tp
->snd_nxt
);
t
->t_ackno
= htonl(tp
->rcv_nxt
);
t
->t_sum
= 0; /* gratuitous? */
CKSUM_TCPSET(m
, t
, r9
, sizeof (struct th
) + len
);
ip
->ip_len
= len
+ sizeof(struct th
);
register struct th
*p
, *q
;
if ((p
= tp
->tcb_hd
.seg_next
) == (struct th
*)tp
||
while ((q
= p
->t_next
) != (struct th
*)tp
&&
(t_end(p
) + 1) == q
->t_seq
)
tcp_sndcopy(tp
, start
, end
)
register struct mbuf
*m
, *n
, **np
;
m
= tp
->t_socket
->so_snd
.sb_mb
;
while (m
!= NULL
&& start
>= (off
+ m
->m_len
)) {
n
->m_len
= MIN(len
, m
->m_len
- adj
);
if (m
->m_off
> MMAXOFF
) {
p
= mtod(m
, struct mbuf
*);
n
->m_off
= ((int)p
- (int)n
) + adj
;
bcopy(mtod(m
, caddr_t
)+adj
, mtod(n
, caddr_t
),
/* SHOULD TRY PACKING INTO SMALL MBUFS HERE */
/* SHOULD NEVER RUN OUT OF m WHEN LEN */
printf("snd_copy: m %x len %d\n", m
, len
);
printf("snd_copy: no space\n");