/* tcp_output.c 4.14 81/11/18 */
#include "../h/socketvar.h"
#include "../net/inet_host.h"
#include "../net/inet_pcb.h"
#include "../net/inet_systm.h"
#include "../net/ip_var.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_inpcb
->inp_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)
register struct tcpcb
*tp
;
(void) tcp_output(tp
, 0, 0, (struct mbuf
*)0);
tp
->tc_flags
&= ~TC_ACK_DUE
;
register struct tcpcb
*tp
;
register struct tcpiphdr
*n
;
/* don't send a reset in response to a reset */
tp
->tc_flags
|= TC_SND_RST
;
tp
->snd_nxt
= n
->ti_ackno
;
tp
->tc_flags
&= ~TC_SYN_RCVD
;
tp
->tc_flags
&= ~TC_SND_RST
;
* Tcp segment output routine.
register struct tcpcb
*tp
;
register unsigned long last
, wind
;
register struct socket
*so
= tp
->t_inpcb
->inp_socket
;
int flags
= 0, forced
, sent
, len
;
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)
(int)(MAX(tp
->iss
+1,tp
->snd_nxt
) - tp
->snd_off
),
(int)(tp
->snd_lst
- tp
->snd_off
));
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
, (int)(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 inpcb
*inp
= tp
->t_inpcb
;
register struct in_host
*h
= inp
->inp_fhost
;
register struct tcpiphdr
*n
;
m
->m_off
= MMAXOFF
- sizeof (struct tcpiphdr
);
m
->m_len
= sizeof (struct tcpiphdr
);
n
= mtod(m
, struct tcpiphdr
*);
n
->ti_next
= n
->ti_prev
= 0;
n
->ti_len
= htons(sizeof (struct tcpiphdr
) - sizeof (struct ip
));
n
->ti_src
.s_addr
= n_lhost
.s_addr
;
n
->ti_dst
.s_addr
= h
->h_addr
.s_addr
;
n
->ti_sport
= htons(inp
->inp_lport
);
n
->ti_dport
= htons(inp
->inp_fport
);
tcp_output(tp
, flags
, len
, dat
)
register struct tcpcb
*tp
;
register struct tcpiphdr
*t
; /* known to be r9 */
struct socket
*so
= tp
->t_inpcb
->inp_socket
;
if ((t
= tp
->t_template
) == 0)
m
->m_off
= MMAXOFF
- sizeof(struct tcpiphdr
);
m
->m_len
= sizeof (struct tcpiphdr
);
bcopy((caddr_t
)t
, mtod(m
, caddr_t
), sizeof (struct tcpiphdr
));
t
= mtod(m
, struct tcpiphdr
*);
if (tp
->tc_flags
&TC_SND_RST
) {
if (tp
->tc_flags
&TC_SYN_RCVD
)
t
->ti_urp
= htons((u_short
)tp
->snd_urp
); /*XXX */
(so
->so_rcv
.sb_cc
+ tp
->seqcnt
);
if (tp
->rcv_nxt
+ t
->ti_win
> tp
->rcv_adv
)
tp
->rcv_adv
= tp
->rcv_nxt
+ t
->ti_win
;
t
->ti_len
= htons((u_short
)(len
+ TCPSIZE
));
t
->ti_win
= htons(t
->ti_win
);
if ((so
->so_options
& SO_DEBUG
) || tcpconsdebug
) {
t
->ti_ackno
= tp
->rcv_nxt
;
tdb_setup(tp
, t
, INSEND
, &tdb
);
t
->ti_seq
= htonl(tp
->snd_nxt
);
t
->ti_ackno
= htonl(tp
->rcv_nxt
);
t
->ti_sum
= 0; /* gratuitous? */
t
->ti_sum
= inet_cksum(m
, sizeof (struct tcpiphdr
) + len
);
ip
->ip_len
= len
+ sizeof(struct tcpiphdr
);