SCCS-vsn: sys/vax/vax/in_cksum.c 1.8
SCCS-vsn: sys/netinet/tcp_fsm.h 4.3
SCCS-vsn: sys/netinet/tcp_usrreq.c 1.26
-/* tcp_usrreq.c 1.25 81/11/04 */
+/* tcp_usrreq.c 1.26 81/11/08 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/mbuf.h"
#include "../h/socket.h"
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/mbuf.h"
#include "../h/socket.h"
-#include "../inet/inet.h"
-#include "../inet/inet_systm.h"
-#include "../inet/imp.h"
-#include "../inet/ip.h"
-#include "../inet/tcp.h"
+#include "../h/socketvar.h"
+#include "../h/protosw.h"
+#include "../net/inet.h"
+#include "../net/inet_systm.h"
+#include "../net/imp.h"
+#include "../net/ip.h"
+#include "../net/tcp.h"
#define TCPFSTAB
#ifdef TCPDEBUG
#define TCPSTATES
#endif
#define TCPFSTAB
#ifdef TCPDEBUG
#define TCPSTATES
#endif
-#include "../inet/tcp_fsm.h"
+#include "../net/tcp_fsm.h"
+#include "../net/tcp_var.h"
+#include "/usr/include/errno.h"
+
+struct tcb *tcp_attach();
+
+/*
+ * Tcp initialization
+ */
+tcp_init()
+{
+
+ tcp_iss = 1; /* wrong */
+ tcb.tcb_next = tcb.tcb_prev = (struct tcb *)&tcb;
+}
/*
* Tcp finite state machine entries for timer and user generated
/*
* Tcp finite state machine entries for timer and user generated
- * Tcp protocol timeout routine called once per second.
+ * Tcp protocol timeout routine called every 500 ms.
* Updates the timers in all active tcb's and
* causes finite state machine actions if timers expire.
*/
* Updates the timers in all active tcb's and
* causes finite state machine actions if timers expire.
*/
{
register struct tcb *tp;
int s = splnet();
{
register struct tcb *tp;
int s = splnet();
register int i;
COUNT(TCP_TIMEO);
/*
* Search through tcb's and update active timers.
*/
register int i;
COUNT(TCP_TIMEO);
/*
* Search through tcb's and update active timers.
*/
- for (tp = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->tcb_next) {
+ tp = tcb.tcb_next;
+ for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next) {
tmp = &tp->t_init;
for (i = 0; i < TNTIMERS; i++) {
if (*tmp && --*tmp == 0)
tmp = &tp->t_init;
for (i = 0; i < TNTIMERS; i++) {
if (*tmp && --*tmp == 0)
- tcp_usrreq(ISTIMER, i, tp, 0);
+ tcp_usrreq(tp->t_socket, PRU_SLOWTIMO, 0, i);
- tcp_iss += ISSINCR; /* increment iss */
- timeout(tcp_timeo, 0, hz); /* reschedule every second */
+ tcp_iss += ISSINCR/2; /* increment iss */
tcp_tcancel(tp)
struct tcb *tp;
{
tcp_tcancel(tp)
struct tcb *tp;
{
- register u_char *tmp = &tp->t_init;
+ register short *tmp = &tp->t_init;
register int i;
for (i = 0; i < TNTIMERS; i++)
register int i;
for (i = 0; i < TNTIMERS; i++)
* then m is the mbuf chain of send data. If this is a timer expiration
* (called from the software clock routine), then timertype tells which timer.
*/
* then m is the mbuf chain of send data. If this is a timer expiration
* (called from the software clock routine), then timertype tells which timer.
*/
-tcp_usrreq(input, timertype, tp, m)
- int input, timertype;
- register struct tcb *tp;
+tcp_usrreq(so, req, m, addr)
+ struct socket *so;
+ int req;
+ register struct tcb *tp = (struct tcb *)so->so_pcb;
int s = splnet();
register int nstate;
#ifdef TCPDEBUG
struct tcp_debug tdb;
#endif
int s = splnet();
register int nstate;
#ifdef TCPDEBUG
struct tcp_debug tdb;
#endif
- nstate = tp->t_state;
- tp->tc_flags &= ~TC_NET_KEEP;
+ if (tp) {
+ nstate = tp->t_state;
+ tp->tc_flags &= ~TC_NET_KEEP;
+ } else
+ if (req != PRU_ATTACH)
+ return (ENOTCONN);
- acounts[nstate][input]++;
+ acounts[nstate][req]++;
- if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) {
- tdb_setup(tp, (struct th *)0, input, &tdb);
+ if (tp && ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug)) {
+ tdb_setup(tp, (struct th *)0, req, &tdb);
tdb.td_tim = timertype;
} else
tdb.td_tod = 0;
#endif
tdb.td_tim = timertype;
} else
tdb.td_tod = 0;
#endif
- * Passive open. Create a tcp control block
- * and enter listen state.
+ * Attach a tcp control block to this socket.
+ * TCP is not multicast, so this is possible
+ * only if no connection currently exists.
- case IUOPENA:
- if (nstate != 0 && nstate != CLOSED)
- goto bad;
- tcp_open(tp, PASSIVE);
- nstate = LISTEN;
+ case PRU_ATTACH:
+ if (tp)
+ error = EISCONN;
+ else
+ tp = tcp_attach(so, &error);
+ nstate = CLOSED;
- * Active open. Create a tcp control block,
- * send a SYN and enter SYN_SENT state.
+ * Detach the TCP from this socket. This
+ * is possible only if a connection currently exists.
+ case PRU_DETACH:
+ so->so_pcb = 0;
+ break;
+
+ /*
+ * Form connection: send a SYN.
+ */
+ case PRU_CONNECT:
if (nstate != 0 && nstate != CLOSED)
goto bad;
if (nstate != 0 && nstate != CLOSED)
goto bad;
tcp_sndctl(tp);
nstate = SYN_SENT;
break;
tcp_sndctl(tp);
nstate = SYN_SENT;
break;
+ case PRU_DISCONNECT:
+ so->so_pcb = 0;
+ tcp_destroy(tp);
+ break;
+
- * Tcp close call. Can be generated by a user ioctl (half-close),
+ * Declare no further transmissions.
+ * Can be generated by a user ioctl (half-close),
* or when higher level close occurs, if a close hasn't happened
* already.
*/
* or when higher level close occurs, if a close hasn't happened
* already.
*/
*/
case LISTEN:
case SYN_SENT:
*/
case LISTEN:
case SYN_SENT:
- tcp_close(tp, UCLOSED);
case CLOSING:
case LAST_ACK:
case RCV_WAIT:
case CLOSING:
case LAST_ACK:
case RCV_WAIT:
- to_user(tp->t_ucb, UCLSERR);
- /*
- * TCP Timer processing.
- * Timers should expire only on open connections
- * not in LISTEN state.
- */
- case ISTIMER:
- switch (nstate) {
-
- case 0:
- case CLOSED:
- case LISTEN:
- goto bad;
-
- default:
- nstate = tcp_timers(tp, timertype);
- }
- break;
-
/*
* User notification of more window availability after
* reading out data. This should not happen before a connection
/*
* User notification of more window availability after
* reading out data. This should not happen before a connection
* out of the TCP buffers after foreign close) and there
* is no more data, institute a close.
*/
* out of the TCP buffers after foreign close) and there
* is no more data, institute a close.
*/
if (nstate < ESTAB || nstate == CLOSED)
goto bad;
tcp_sndwin(tp);
if ((tp->tc_flags&TC_FIN_RCVD) &&
(tp->tc_flags&TC_USR_CLOSED) == 0 &&
rcv_empty(tp))
if (nstate < ESTAB || nstate == CLOSED)
goto bad;
tcp_sndwin(tp);
if ((tp->tc_flags&TC_FIN_RCVD) &&
(tp->tc_flags&TC_USR_CLOSED) == 0 &&
rcv_empty(tp))
- to_user(tp, UCLOSED);
- if (nstate == RCV_WAIT && rcv_empty(tp)) {
- tcp_close(tp, UCLOSED);
+ tcp_error(tp, ESHUTDOWN);
+ if (nstate == RCV_WAIT && rcv_empty(tp))
* Allowed only on ESTAB connection and after FIN from
* foreign peer.
*/
* Allowed only on ESTAB connection and after FIN from
* foreign peer.
*/
switch (nstate) {
case ESTAB:
switch (nstate) {
case ESTAB:
default:
if (nstate < ESTAB)
goto bad;
default:
if (nstate < ESTAB)
goto bad;
+ m_freem(m);
+ /* tcp_user(tp, UCLSERR); */
* then we need to send an RST. In any case we then
* enter closed state.
*/
* then we need to send an RST. In any case we then
* enter closed state.
*/
if (nstate == 0 || nstate == CLOSED)
break;
switch (nstate) {
if (nstate == 0 || nstate == CLOSED)
break;
switch (nstate) {
/* fall into ... */
default:
/* fall into ... */
default:
nstate = CLOSED;
}
break;
nstate = CLOSED;
}
break;
* Network down entry. Discard the tcb and force
* the state to be closed, ungracefully.
*/
* Network down entry. Discard the tcb and force
* the state to be closed, ungracefully.
*/
if (nstate == 0 || nstate == CLOSED)
break;
if (nstate == 0 || nstate == CLOSED)
break;
- tcp_close(tp, UNETDWN);
+ /*
+ * Ioctl on protocols.
+ */
+ case PRU_CONTROL:
+ break;
+
+ /*
+ * TCP Timer processing.
+ * Timers should expire only on open connections
+ * not in LISTEN state.
+ */
+ case PRU_SLOWTIMO:
+ switch (nstate) {
+
+ case 0:
+ case CLOSED:
+ case LISTEN:
+ goto bad;
+
+ default:
+ nstate = tcp_timers(tp, (int)addr);
+ }
+ break;
+
default:
panic("tcp_usrreq");
bad:
printf("tcp: bad state: tcb=%x state=%d input=%d\n",
default:
panic("tcp_usrreq");
bad:
printf("tcp: bad state: tcb=%x state=%d input=%d\n",
- tp, tp->t_state, input);
nstate = EFAILEC;
break;
}
nstate = EFAILEC;
break;
}
/*
* Open routine, called to initialize newly created tcb fields.
*/
/*
* Open routine, called to initialize newly created tcb fields.
*/
-tcp_open(tp, mode)
- register struct tcb *tp;
- int mode;
+struct tcb *
+tcp_attach(so)
+ register struct socket *so;
- register struct ucb *up = tp->t_ucb;
-COUNT(TCP_OPEN);
+ register struct tcb *tp;
+COUNT(TCP_ATTACH);
/*
* Link in tcb queue and make
* initialize empty reassembly queue.
*/
/*
* Link in tcb queue and make
* initialize empty reassembly queue.
*/
- tp->tcb_next = tcb.tcb_next;
- tcb.tcb_next->tcb_prev = tp;
- tp->tcb_prev = (struct tcb *)&tcb;
+ tp->tcb_hd.tcb_next = tcb.tcb_next;
+ tcb.tcb_next->tcb_hd.tcb_prev = tp;
+ tp->tcb_hd.tcb_prev = (struct tcb *)&tcb;
- tp->t_rcv_next = tp->t_rcv_prev = (struct th *)tp;
+ tp->tcb_hd.seg_next = tp->tcb_hd.seg_prev = (struct th *)tp;
/*
* Initialize sequence numbers and
/*
* Initialize sequence numbers and
tp->iss = tcp_iss;
tp->snd_off = tp->iss + 1;
tcp_iss += (ISSINCR >> 1) + 1;
tp->iss = tcp_iss;
tp->snd_off = tp->iss + 1;
tcp_iss += (ISSINCR >> 1) + 1;
-
- /*
- * Set timeout for open.
- * SHOULD THIS BE A HIGHER LEVEL FUNCTION!?! THINK SO.
- */
- if (up->uc_timeo)
- tp->t_init = up->uc_timeo;
- else if (mode == ACTIVE)
- tp->t_init = T_INIT;
- /* else
- tp->t_init = 0; */
- up->uc_timeo = 0; /* ### */
- * Internal close of a connection, shutting down the tcb.
- register struct ucb *up = tp->t_ucb;
+ register struct socket *so = tp->t_socket;
register struct th *t;
register struct mbuf *m;
register struct th *t;
register struct mbuf *m;
/*
* Remove from tcb queue and cancel timers.
*/
/*
* Remove from tcb queue and cancel timers.
*/
- tp->tcb_prev->tcb_next = tp->tcb_next;
- tp->tcb_next->tcb_prev = tp->tcb_prev;
+ tp->tcb_hd.tcb_prev->tcb_hd.tcb_next = tp->tcb_hd.tcb_next;
+ tp->tcb_hd.tcb_next->tcb_hd.tcb_prev = tp->tcb_hd.tcb_prev;
tcp_tcancel(tp);
/*
* Discard all buffers.
*/
tcp_tcancel(tp);
/*
* Discard all buffers.
*/
- for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next)
+ for (t = tp->tcb_hd.seg_next; t != (struct th *)tp; t = t->t_next)
- if (up->uc_rbuf) {
- m_freem(up->uc_rbuf);
- up->uc_rbuf = NULL;
- }
- up->uc_rcc = 0;
- if (up->uc_sbuf) {
- m_freem(up->uc_sbuf);
- up->uc_sbuf = NULL;
- }
- up->uc_ssize = 0;
- for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) {
+ if (so->so_rcv.sb_mb)
+ { m_freem(so->so_rcv.sb_mb); so->so_rcv.sb_mb = 0; }
+ so->so_rcv.sb_cc = 0; so->so_rcv.sb_mbcnt = 0;
+ if (so->so_snd.sb_mb)
+ { m_freem(so->so_snd.sb_mb); so->so_rcv.sb_mb = 0; }
+ so->so_snd.sb_cc = 0; so->so_snd.sb_mbcnt = 0;
+
+ for (m = tp->seg_unack; m; m = m->m_act)
- tp->t_rcv_unack = NULL;
+ tp->seg_unack = 0;
+
+ /*
+ * Free routing table entry.
+ */
+ if (tp->t_host) {
+ h_free(tp->t_host);
+ tp->t_host = 0;
}
/*
* Free tcp send template, the tcb itself,
}
/*
* Free tcp send template, the tcb itself,
- * the routing table entry, and the space we had reserved
- * in the meory pool.
+ * and the space we had reserved in the meory pool.
*/
if (tp->t_template) {
m_free(dtom(tp->t_template));
tp->t_template = 0;
}
wmemfree((caddr_t)tp, 1024);
*/
if (tp->t_template) {
m_free(dtom(tp->t_template));
tp->t_template = 0;
}
wmemfree((caddr_t)tp, 1024);
- up->uc_pcb = 0;
- if (up->uc_host) {
- h_free(up->uc_host);
- up->uc_host = 0;
- }
- m_release(up->uc_snd + (up->uc_rhiwat/MSIZE) + 2);
-
- /*
- * If user has initiated close (via close call), delete ucb
- * entry, otherwise just wakeup so user can issue close call
- */
- if (tp->tc_flags&TC_USR_ABORT) /* ### */
- up->uc_proc = NULL; /* ### */
- else /* ### */
- to_user(up, state); /* ### */
+ m_release(so->so_rcv.sb_hiwat + so->so_snd.sb_hiwat + 2 * MSIZE);
struct mbuf *m0;
{
register struct mbuf *m, *n;
struct mbuf *m0;
{
register struct mbuf *m, *n;
- register struct ucb *up = tp->t_ucb;
+ register struct socket *so = tp->t_socket;
register off;
seq_t last;
COUNT(TCP_USRSEND);
last = tp->snd_off;
for (m = n = m0; m != NULL; m = m->m_next) {
register off;
seq_t last;
COUNT(TCP_USRSEND);
last = tp->snd_off;
for (m = n = m0; m != NULL; m = m->m_next) {
+ so->so_snd.sb_mbcnt += NMBPG;
- if ((m = up->uc_sbuf) == NULL)
- up->uc_sbuf = n;
+ if ((m = so->so_snd.sb_mb) == NULL)
+ so->so_snd.sb_mb = n;
else {
while (m->m_next != NULL) {
m = m->m_next;
else {
while (m->m_next != NULL) {
m = m->m_next;
(caddr_t)((int)m + off), n->m_len);
m->m_len += n->m_len;
off += n->m_len;
(caddr_t)((int)m + off), n->m_len);
m->m_len += n->m_len;
off += n->m_len;
n = m_free(n);
}
}
m->m_next = n;
}
n = m_free(n);
}
}
m->m_next = n;
}
- if (up->uc_flags & UEOL)
+ if (tp->t_options & TO_EOL)
- if (up->uc_flags & UURG) {
+ if (tp->t_options & TO_URG) {
tp->snd_urp = last+1;
tp->tc_flags |= TC_SND_URG;
}
tp->snd_urp = last+1;
tp->tc_flags |= TC_SND_URG;
}
case TINIT: /* initialization timer */
if ((tp->tc_flags&TC_SYN_ACKED) == 0) { /* 35 */
case TINIT: /* initialization timer */
if ((tp->tc_flags&TC_SYN_ACKED) == 0) { /* 35 */
- tcp_close(tp, UINTIMO);
+/* XXX */ /* tcp_close(tp, UINTIMO); */
return (CLOSED);
}
return (SAME);
return (CLOSED);
}
return (SAME);
* and can close if no data left for user.
*/
if (rcv_empty(tp)) {
* and can close if no data left for user.
*/
if (rcv_empty(tp)) {
- tcp_close(tp, UCLOSED); /* 14 */
+/* XXX */ /* tcp_close(tp, UCLOSED); */ /* 14 */
return (CLOSED);
}
return (RCV_WAIT); /* 17 */
return (CLOSED);
}
return (RCV_WAIT); /* 17 */
case TREXMT: /* retransmission timer */
if (tp->t_rexmt_val > tp->snd_una) { /* 34 */
/*
case TREXMT: /* retransmission timer */
if (tp->t_rexmt_val > tp->snd_una) { /* 34 */
/*
- * Set up for a retransmission, increase rexmt time
+ * Set so for a retransmission, increase rexmt time
* in case of multiple retransmissions.
*/
tp->snd_nxt = tp->snd_una;
* in case of multiple retransmissions.
*/
tp->snd_nxt = tp->snd_una;
case TREXMTTL: /* retransmit too long */
if (tp->t_rtl_val > tp->snd_una) /* 36 */
case TREXMTTL: /* retransmit too long */
if (tp->t_rtl_val > tp->snd_una) /* 36 */
- to_user(tp->t_ucb, URXTIMO);
+/* XXX */ /* to_user(tp->t_socket, URXTIMO); */;
/*
* If user has already closed, abort the connection.
*/
if (tp->tc_flags & TC_USR_CLOSED) {
/*
* If user has already closed, abort the connection.
*/
if (tp->tc_flags & TC_USR_CLOSED) {
- tcp_close(tp, URXTIMO);
+/* XXX */ /* tcp_close(tp, URXTIMO); */
return (CLOSED);
}
return (SAME);
return (CLOSED);
}
return (SAME);
-/* THIS ROUTINE IS A CROCK */
-to_user(up, state)
- register struct ucb *up;
- register short state;
+tcp_error(so, errno)
+ struct socket *so;
+ int errno;
- up->uc_state |= state;
- netwakeup(up);
- if (state == UURGENT)
- psignal(up->uc_proc, SIGURG);
+ so->so_error = errno;
+ sowakeup(so);
-/* in_cksum.c 1.7 81/10/29 */
+/* inet_cksum.c 1.7 81/10/29 */
#include <sys/types.h>
#include "../h/mbuf.h"
#include <sys/types.h>
#include "../h/mbuf.h"
-#include "../inet/inet.h"
-#include "../inet/inet_systm.h"
+#include "../net/inet.h"
+#include "../net/inet_systm.h"
/*
* Network primitives; this file varies per-cpu,
/*
* Network primitives; this file varies per-cpu,
* code and should be rewritten for each CPU
* to be as fast as possible.
*/
* code and should be rewritten for each CPU
* to be as fast as possible.
*/
register struct mbuf *m;
register int len;
{
register struct mbuf *m;
register int len;
{
register int sum = 0; /* known to be r8 */
register u_short *w; /* known to be r7 */
register int mlen = 0;
register int sum = 0; /* known to be r8 */
register u_short *w; /* known to be r7 */
register int mlen = 0;
for (;;) {
w = (u_short *)((int)m + m->m_off);
for (;;) {
w = (u_short *)((int)m + m->m_off);