/* tcp_subr.c 4.30 82/10/09 */
#include "../h/socketvar.h"
#include "../h/protosw.h"
#include "../netinet/in.h"
#include "../net/route.h"
#include "../netinet/in_pcb.h"
#include "../netinet/in_systm.h"
#include "../netinet/ip.h"
#include "../netinet/ip_var.h"
#include "../netinet/ip_icmp.h"
#include "../netinet/tcp.h"
#include "../netinet/tcp_fsm.h"
#include "../netinet/tcp_seq.h"
#include "../netinet/tcp_timer.h"
#include "../netinet/tcp_var.h"
#include "../netinet/tcpip.h"
tcb
.inp_next
= tcb
.inp_prev
= &tcb
;
* 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 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
= inp
->inp_laddr
;
n
->ti_dst
= inp
->inp_faddr
;
n
->ti_sport
= inp
->inp_lport
;
n
->ti_dport
= inp
->inp_fport
;
* Send a single message to the TCP at address specified by
* the given TCP/IP header. If flags==0, then we make a copy
* of the tcpiphdr at ti and send directly to the addressed host.
* This is used to force keep alive messages out using the TCP
* template for a connection tp->t_template. If flags are given
* then we send a message back to the TCP which originated the
* segment ti, and discard the mbuf containing it and any other
* In any case the ack and sequence number of the transmitted
* segment are as specified by the parameters.
tcp_respond(tp
, ti
, ack
, seq
, flags
)
register struct tcpiphdr
*ti
;
win
= sbspace(&tp
->t_inpcb
->inp_socket
->so_rcv
);
ro
= &tp
->t_inpcb
->inp_route
;
m
->m_len
= sizeof (struct tcpiphdr
) + 1;
*mtod(m
, struct tcpiphdr
*) = *ti
;
ti
= mtod(m
, struct tcpiphdr
*);
m
->m_off
= (int)ti
- (int)m
;
m
->m_len
= sizeof (struct tcpiphdr
);
#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
xchg(ti
->ti_dst
.s_addr
, ti
->ti_src
.s_addr
, u_long
);
xchg(ti
->ti_dport
, ti
->ti_sport
, u_short
);
ti
->ti_next
= ti
->ti_prev
= 0;
ti
->ti_len
= sizeof (struct tcphdr
) + tlen
;
ti
->ti_len
= htons((u_short
)ti
->ti_len
);
ti
->ti_seq
= htonl(ti
->ti_seq
);
ti
->ti_ack
= htonl(ti
->ti_ack
);
ti
->ti_off
= sizeof (struct tcphdr
) >> 2;
ti
->ti_win
= htons(ti
->ti_win
);
ti
->ti_sum
= in_cksum(m
, sizeof (struct tcpiphdr
) + tlen
);
((struct ip
*)ti
)->ip_len
= sizeof (struct tcpiphdr
) + tlen
;
((struct ip
*)ti
)->ip_ttl
= TCP_TTL
;
(void) ip_output(m
, (struct mbuf
*)0, ro
, 0);
* Create a new TCP control block, making an
* empty reassembly queue and hooking it to the argument
* protocol control block.
struct mbuf
*m
= m_getclr(M_DONTWAIT
);
register struct tcpcb
*tp
;
tp
= mtod(m
, struct tcpcb
*);
tp
->seg_next
= tp
->seg_prev
= (struct tcpiphdr
*)tp
;
tp
->t_maxseg
= 576; /* satisfy the rest of the world */
tp
->t_flags
= 0; /* sends options! */
inp
->inp_ppcb
= (caddr_t
)tp
;
* Drop a TCP connection, reporting
* the specified error. If connection is synchronized,
* then send a RST to peer.
struct socket
*so
= tp
->t_inpcb
->inp_socket
;
if (TCPS_HAVERCVDSYN(tp
->t_state
)) {
tp
->t_state
= TCPS_CLOSED
;
tcp_close(inp
->inp_ppcb
);
* Close a TCP control block:
* discard all space held by the tcp
* discard internet protocol block
register struct tcpcb
*tp
;
register struct tcpiphdr
*t
;
struct inpcb
*inp
= tp
->t_inpcb
;
struct socket
*so
= inp
->inp_socket
;
for (; t
!= (struct tcpiphdr
*)tp
; t
= (struct tcpiphdr
*)t
->ti_next
)
(void) m_free(dtom(tp
->t_template
));
(void) m_free(dtom(tp
->t_tcpopt
));
(void) m_free(dtom(tp
->t_ipopt
));
extern u_char inetctlerrmap
[];
if (cmd
< 0 || cmd
> PRC_NCMDS
)
/* these are handled by ip */
sin
= &((struct icmp
*)arg
)->icmp_ip
.ip_dst
;
in_pcbnotify(&tcb
, sin
, inetctlerrmap
[cmd
], tcp_abort
);