before overlay
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 15 Nov 1981 08:41:14 +0000 (00:41 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 15 Nov 1981 08:41:14 +0000 (00:41 -0800)
SCCS-vsn: sys/netinet/tcp_var.h 4.2
SCCS-vsn: sys/netinet/tcp.h 1.15
SCCS-vsn: sys/vax/if/if_en.c 4.7
SCCS-vsn: sys/netinet/ip.h 1.7
SCCS-vsn: sys/netinet/ip_icmp.c 4.3
SCCS-vsn: sys/netinet/tcp_input.c 1.22
SCCS-vsn: sys/netinet/tcp_output.c 4.11
SCCS-vsn: sys/netinet/tcp_usrreq.c 1.27
SCCS-vsn: sys/netinet/udp_usrreq.c 4.3

usr/src/sys/netinet/ip.h
usr/src/sys/netinet/ip_icmp.c
usr/src/sys/netinet/tcp.h
usr/src/sys/netinet/tcp_input.c
usr/src/sys/netinet/tcp_output.c
usr/src/sys/netinet/tcp_usrreq.c
usr/src/sys/netinet/tcp_var.h
usr/src/sys/netinet/udp_usrreq.c
usr/src/sys/vax/if/if_en.c

index 2e10618..d73cee9 100644 (file)
@@ -1,4 +1,4 @@
-/* ip.h 1.6 81/11/08 */
+/* ip.h 1.7 81/11/14 */
 
 /*
  * Definitions for internet protocol version 4.
 
 /*
  * Definitions for internet protocol version 4.
@@ -9,40 +9,23 @@
 /*
  * Structure of an internet header, naked of options.
  *
 /*
  * Structure of an internet header, naked of options.
  *
- * SHOULD MAKE A VERSION OF THIS FOR KERNEL SO USER
- * VERSION CAN BE union FREE AND INITIALIZABLE.
+ * We declare ip_len and ip_off to be short, rather than u_short
+ * pragmatically since otherwise unsigned comparisons can result
+ * against negative integers quite easily, and fail in subtle ways.
  */
 struct ip {
        u_char  ip_hl:4,                /* header length */
                ip_v:4;                 /* version */
        u_char  ip_tos;                 /* type of service */
  */
 struct ip {
        u_char  ip_hl:4,                /* header length */
                ip_v:4;                 /* version */
        u_char  ip_tos;                 /* type of service */
-/* we copy the IP_MF to ip_tos on input */
-#define        ip_mff  ip_tos                  /* more fragments flag */
-/* by rights, ip_len should be a u_short, but this makes operations */
-/* on it very dangerous as comparisons become unsigned and comparing */
-/* against negative numbers then fails... we don't expect any > 32767 */
-/* byte packets, so pragmatically delcare it to be a short */
        short   ip_len;                 /* total length */
        u_short ip_id;                  /* identification */
        short   ip_len;                 /* total length */
        u_short ip_id;                  /* identification */
-/* ip_off should also, by rights, be u_short, ala ip_len */
        short   ip_off;                 /* fragment offset field */
 #define        IP_DF 0x4000                    /* dont fragment flag */
 #define        IP_MF 0x2000                    /* more fragments flag */
        u_char  ip_ttl;                 /* time to live */
        u_char  ip_p;                   /* protocol */
        u_short ip_sum;                 /* checksum */
        short   ip_off;                 /* fragment offset field */
 #define        IP_DF 0x4000                    /* dont fragment flag */
 #define        IP_MF 0x2000                    /* more fragments flag */
        u_char  ip_ttl;                 /* time to live */
        u_char  ip_p;                   /* protocol */
        u_short ip_sum;                 /* checksum */
-       union {
-               struct ip_addr ip_s;    /* source address */
-               struct ip *ip_nxt;      /* next fragment */
-       } I_sun;
-#define        ip_src  I_sun.ip_s
-#define        ip_next I_sun.ip_nxt
-       union {
-               struct ip_addr ip_d;    /* destination address */
-               struct ip *ip_prv;      /* prev fragment */
-       } I_dun;
-#define        ip_dst  I_dun.ip_d
-#define        ip_prev I_dun.ip_prv
+       struct  ip_addr ip_src,ip_dst;  /* source and dest address */
 };
 
 /*
 };
 
 /*
@@ -99,29 +82,8 @@ struct       ip_timestamp {
 #define        IPOPT_SECUR_SECRET      0xd788
 #define        IPOPT_SECUR_TOPSECRET   0x6bc5
 
 #define        IPOPT_SECUR_SECRET      0xd788
 #define        IPOPT_SECUR_TOPSECRET   0x6bc5
 
-/*
- * Ip reassembly queue structure.  Each fragment
- * being reassambled is attached to one of these structures.
- * They are timed out after ipq_ttl drops to 0, and may also
- * be reclaimed if memory becomes tight.
- */
-struct ipq {
-       struct  ipq *next,*prev;        /* to other reass headers */
-       u_char  ipq_ttl;                /* time for reass q to live */
-       u_char  ipq_p;                  /* protocol of this fragment */
-       u_short ipq_id;                 /* sequence id for reassembly */
-       struct  ip *ipq_next,*ipq_prev; /* to ip headers of fragments */
-       struct  ip_addr ipq_src,ipq_dst;
-};
-
 /*
  * Internet implementation parameters.
  */
 #define        MAXTTL          255             /* maximum time to live (seconds) */
 #define        IPFRAGTTL       15              /* time to live for frag chains */
 /*
  * Internet implementation parameters.
  */
 #define        MAXTTL          255             /* maximum time to live (seconds) */
 #define        IPFRAGTTL       15              /* time to live for frag chains */
-
-#ifdef KERNEL
-struct ipq     ipq;                    /* ip reass. queue */
-struct ipq     *ip_freef();
-u_short        ip_id;                          /* ip packet ctr, for ids */
-#endif
index 083303d..c64f5e3 100644 (file)
@@ -1,4 +1,4 @@
-/* ip_icmp.c 4.2 81/11/08 */
+/* ip_icmp.c 4.3 81/11/14 */
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
@@ -171,7 +171,7 @@ icmp_send(ip, icp)
 {
 
        icp->icmp_cksum = 0;
 {
 
        icp->icmp_cksum = 0;
-       icp->icmp_inet_cksum = cksum(dtom(ip), 0);              /* ### */
+       icp->icmp_cksum = inet_cksum(dtom(ip), 0);              /* XXX */
        /* what about ttl? */
        ip_output(ip);
 }
        /* what about ttl? */
        ip_output(ip);
 }
index f206690..648ec87 100644 (file)
@@ -1,13 +1,13 @@
-/* tcp.h 1.14 81/11/08 */
+/* tcp.h 1.15 81/11/14 */
 
 /*
  * Tcp header.  Fits over the ip header after option removed.
  *
  * SHOULD MAKE A CLEAN HEADER FOR USE BY USERS.
  */
 
 /*
  * Tcp header.  Fits over the ip header after option removed.
  *
  * SHOULD MAKE A CLEAN HEADER FOR USE BY USERS.
  */
-struct th {
-       struct  th *t_next;             /* -> next tcp on rcv chain */
-       struct  th *t_prev;             /* -> prev tcp on rcv chain */
+struct tcpiphdr {
+       struct  tcpiphdr *t_next;               /* -> next tcp on rcv chain */
+       struct  tcpiphdr *t_prev;               /* -> prev tcp on rcv chain */
        u_char  t_x1;                   /* (unused) */
        u_char  t_pr;                   /* protocol */
 /* by rights, t_len should be a u_short, but this makes operations */
        u_char  t_x1;                   /* (unused) */
        u_char  t_pr;                   /* protocol */
 /* by rights, t_len should be a u_short, but this makes operations */
index d50a229..fcd86e3 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_input.c 1.21 81/11/08 */
+/* tcp_input.c 1.22 81/11/14 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -7,6 +7,7 @@
 #include "../h/socketvar.h"
 #include "../net/inet_cksum.h"
 #include "../net/inet.h"
 #include "../h/socketvar.h"
 #include "../net/inet_cksum.h"
 #include "../net/inet.h"
+#include "../net/inet_pcb.h"
 #include "../net/inet_systm.h"
 #include "../net/imp.h"
 #include "../net/inet_host.h"
 #include "../net/inet_systm.h"
 #include "../net/imp.h"
 #include "../net/inet_host.h"
 
 int    tcpcksum = 1;
 
 
 int    tcpcksum = 1;
 
-tcp_advise(mp)
-       struct mbuf *mp;
+tcp_drain()
+{
+       register struct inpcb *ip;
+
+       for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next)
+               tcp_drainunack(intotcpcb(ip));
+}
+
+tcp_drainunack(tp)
+       register struct tcpcb *tp;
+{
+       register struct mbuf *m;
+
+       for (m = tp->seg_unack; m; m = m->m_act)
+               m_freem(m);
+       tp->seg_unack = 0;
+}
+       
+tcp_ctlinput(m)
+       struct mbuf *m;
 {
 
 {
 
+       m_freem(m);
 }
 
 tcp_input(mp)
        register struct mbuf *mp;
 {
 }
 
 tcp_input(mp)
        register struct mbuf *mp;
 {
-       register struct th *n;          /* known to be r10 */
+       register struct tcpiphdr *n;            /* known to be r10 */
        register int j;
        register int j;
-       register struct tcb *tp;
+       register struct tcpcb *tp;
+       struct inpcb *inp;
        register int thflags;
        int nstate;
        struct mbuf *m;
        register int thflags;
        int nstate;
        struct mbuf *m;
@@ -44,7 +65,7 @@ COUNT(TCP_INPUT);
        /*
         * Build extended tcp header
         */
        /*
         * Build extended tcp header
         */
-       n = mtod(mp, struct th *);
+       n = mtod(mp, struct tcpiphdr *);
        thflags = n->th_flags;
        tlen = ((struct ip *)n)->ip_len;
        n->t_len = htons(tlen);
        thflags = n->th_flags;
        tlen = ((struct ip *)n)->ip_len;
        n->t_len = htons(tlen);
@@ -71,22 +92,11 @@ COUNT(TCP_INPUT);
        }
 
        /*
        }
 
        /*
-        * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!)
+        * Find tcb for message.
         */
         */
-       tp = tcb.tcb_next;
-       for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next)
-               if (tp->t_lport == lport && tp->t_fport == fport &&
-                   tp->t_host->h_addr.s_addr == n->t_s.s_addr)
-                       goto found;
-       tp = tcb.tcb_next;
-       for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next)
-               if (tp->t_lport == lport &&
-                   (tp->t_fport==fport || tp->t_fport==0) &&
-                   (tp->t_host->h_addr.s_addr == n->t_s.s_addr ||
-                    tp->t_host->h_addr.s_addr == 0))
-                       goto found;
-       goto notwanted;
-found:
+       inp = in_pcblookup(&tcb, &n->t_s, fport, &n_lhost, lport);
+       if (inp == 0)
+               goto notwanted;
 
        /*
         * Byte swap header
 
        /*
         * Byte swap header
@@ -139,8 +149,8 @@ found:
                        tp->t_rexmt = 0;
                        tp->t_rexmttl = 0;
                        tp->t_persist = 0;
                        tp->t_rexmt = 0;
                        tp->t_rexmttl = 0;
                        tp->t_persist = 0;
-                       h_free(tp->t_host);
-                       tp->t_host = 0;
+                       h_free(inp->inp_fhost);
+                       inp->inp_fhost = 0;
                        tp->t_state = LISTEN;
                        goto badseg;
 
                        tp->t_state = LISTEN;
                        goto badseg;
 
@@ -172,7 +182,7 @@ goodseg:
        /*
         * Defer processing if no buffer space for this connection.
         */
        /*
         * Defer processing if no buffer space for this connection.
         */
-       so = tp->t_socket;
+       so = inp->inp_socket;
        if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat &&
             n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) {
 /*
        if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat &&
             n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) {
 /*
@@ -209,11 +219,11 @@ goodseg:
 
        case LISTEN:
                if (!syn_ok(tp, n) ||
 
        case LISTEN:
                if (!syn_ok(tp, n) ||
-                   ((tp->t_host = h_make(&n->t_s)) == 0)) {
+                   ((inp->inp_lhost = in_hmake(&n->t_s)) == 0)) {
                        nstate = EFAILEC;
                        goto done;
                }
                        nstate = EFAILEC;
                        goto done;
                }
-               tp->t_fport = n->t_src;
+               inp->inp_fport = n->t_src;
                tp->t_template = tcp_template(tp);
                tcp_ctldat(tp, n, 1);
                if (tp->tc_flags&TC_FIN_RCVD) {
                tp->t_template = tcp_template(tp);
                tcp_ctldat(tp, n, 1);
                if (tp->tc_flags&TC_FIN_RCVD) {
@@ -221,7 +231,7 @@ goodseg:
                        tp->tc_flags &= ~TC_WAITED_2_ML;
                        nstate = CLOSE_WAIT;
                } else {
                        tp->tc_flags &= ~TC_WAITED_2_ML;
                        nstate = CLOSE_WAIT;
                } else {
-/* XXX */              /* tp->t_init = T_INIT / 2; */          /* 4 */
+                       tp->t_init = T_INIT / 2;                /* 4 */
                        nstate = L_SYN_RCVD;
                }
                goto done;
                        nstate = L_SYN_RCVD;
                }
                goto done;
@@ -320,7 +330,7 @@ input:
                if (j) {
                        if (tp->tc_flags&TC_WAITED_2_ML)
                                if (rcv_empty(tp)) {
                if (j) {
                        if (tp->tc_flags&TC_WAITED_2_ML)
                                if (rcv_empty(tp)) {
-                                       sowakeup(tp->t_socket); /* ### */
+                                       sorwakeup(inp->inp_socket);
                                        nstate = CLOSED;        /* 15 */
                                } else
                                        nstate = RCV_WAIT;      /* 18 */
                                        nstate = CLOSED;        /* 15 */
                                } else
                                        nstate = RCV_WAIT;      /* 18 */
@@ -332,9 +342,8 @@ input:
 
        case LAST_ACK:
                if (ack_fin(tp, n)) {
 
        case LAST_ACK:
                if (ack_fin(tp, n)) {
-                       if (rcv_empty(tp)) {                    /* 16 */
-                               sowakeup(tp->t_socket); /* ### */
-/* XXX */                      /* tcp_close(tp, UCLOSED); */
+                       if (rcv_empty(tp)) {            /* 16 */
+                               sorwakeup(inp->inp_socket);
                                nstate = CLOSED;
                        } else
                                nstate = RCV_WAIT;              /* 19 */
                                nstate = CLOSED;
                        } else
                                nstate = RCV_WAIT;              /* 19 */
@@ -396,7 +405,7 @@ done:
 notwanted:
        m_freem(mp->m_next);
        mp->m_next = NULL;
 notwanted:
        m_freem(mp->m_next);
        mp->m_next = NULL;
-       mp->m_len = sizeof(struct th);
+       mp->m_len = sizeof(struct tcpiphdr);
 #define xchg(a,b) j=a; a=b; b=j
        xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src);
 #undef xchg
 #define xchg(a,b) j=a; a=b; b=j
        xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src);
 #undef xchg
@@ -409,22 +418,29 @@ notwanted:
        n->th_flags = ((thflags & TH_ACK) ? 0 : TH_ACK) | TH_RST;
        n->t_len = htons(TCPSIZE);
        n->t_off = 5;
        n->th_flags = ((thflags & TH_ACK) ? 0 : TH_ACK) | TH_RST;
        n->t_len = htons(TCPSIZE);
        n->t_off = 5;
-       n->t_sum = inet_cksum(mp, sizeof(struct th));
-       ((struct ip *)n)->ip_len = sizeof(struct th);
+       n->t_sum = inet_cksum(mp, sizeof(struct tcpiphdr));
+       ((struct ip *)n)->ip_len = sizeof(struct tcpiphdr);
        ip_output(mp);
        netstat.t_badsegs++;
 }
 
        ip_output(mp);
        netstat.t_badsegs++;
 }
 
-tcp_ctldat(tp, n, dataok)
-       register struct tcb *tp;
-       register struct th *n;
+tcp_ctldat(tp, n0, dataok)
+       register struct tcpcb *tp;
+       struct tcpiphdr *n0;
+       int dataok;
 {
        register struct mbuf *m;
 {
        register struct mbuf *m;
+       register struct tcpiphdr *n = n0;
        register int thflags = n->th_flags;
        register int thflags = n->th_flags;
+       struct socket *so = tp->t_inpcb->inp_socket;
+       seq_t past = n->t_seq + n->t_len;
+       seq_t urgent;
        int sent;
 COUNT(TCP_CTLDAT);
 
        int sent;
 COUNT(TCP_CTLDAT);
 
-       tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW);
+       if (thflags & TH_URG)
+               urgent = n->t_seq + n->t_urp;
+       tp->tc_flags &= ~(TC_ACK_DUE|TC_NEW_WINDOW);
 /* syn */
        if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (thflags&TH_SYN)) {
                tp->irs = n->t_seq;
 /* syn */
        if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (thflags&TH_SYN)) {
                tp->irs = n->t_seq;
@@ -436,42 +452,29 @@ COUNT(TCP_CTLDAT);
        if ((thflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) &&
            n->t_ackno > tp->snd_una) {
                register struct mbuf *mn;
        if ((thflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) &&
            n->t_ackno > tp->snd_una) {
                register struct mbuf *mn;
-               register struct socket *so;
-               int len;
-
-               so = tp->t_socket;
 
 
-               /* update snd_una and snd_nxt */
+               /*
+                * Reflect newly acknowledged data.
+                */
                tp->snd_una = n->t_ackno;
                if (tp->snd_una > tp->snd_nxt)
                        tp->snd_nxt = tp->snd_una;
                tp->snd_una = n->t_ackno;
                if (tp->snd_una > tp->snd_nxt)
                        tp->snd_nxt = tp->snd_una;
-               /* if timed msg acked, set retrans time value */
+
+               /*
+                * If timed msg acked, update retransmit time value.
+                */
                if ((tp->tc_flags&TC_SYN_ACKED) &&
                    tp->snd_una > tp->t_xmt_val) {
                if ((tp->tc_flags&TC_SYN_ACKED) &&
                    tp->snd_una > tp->t_xmt_val) {
+                       /* NEED SMOOTHING HERE */
                        tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT);
                        if (tp->t_xmtime > T_REMAX)
                                tp->t_xmtime = T_REMAX;
                }
 
                        tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT);
                        if (tp->t_xmtime > T_REMAX)
                                tp->t_xmtime = T_REMAX;
                }
 
-               /* remove acked data from send buf */
-               len = tp->snd_una - tp->snd_off;
-               m = so->so_snd.sb_mb;
-               while (len > 0 && m != NULL)
-                       if (m->m_len <= len) {
-                               len -= m->m_len;
-                               if (m->m_off > MMAXOFF)
-                                       so->so_snd.sb_mbcnt -= NMBPG;
-                               MFREE(m, mn);
-                               m = mn;
-                               so->so_snd.sb_mbcnt--;
-                               if (so->so_snd.sb_mbcnt <= 0)
-                                       panic("tcp_ctldat");
-                       } else {
-                               m->m_len -= len;
-                               m->m_off += len;
-                               break;
-                       }
-               so->so_snd.sb_mb = m;
+               /*
+                * Remove acked data from send buf
+                */
+               sbdrop(&so->so_snd, tp->snd_una - tp->snd_off);
                tp->snd_off = tp->snd_una;
                if ((tp->tc_flags&TC_SYN_ACKED) == 0 &&
                    (tp->snd_una > tp->iss)) {
                tp->snd_off = tp->snd_una;
                if ((tp->tc_flags&TC_SYN_ACKED) == 0 &&
                    (tp->snd_una > tp->iss)) {
@@ -483,7 +486,7 @@ COUNT(TCP_CTLDAT);
                tp->t_rexmt = 0;
                tp->t_rexmttl = 0;
                tp->tc_flags |= TC_CANCELLED;
                tp->t_rexmt = 0;
                tp->t_rexmttl = 0;
                tp->tc_flags |= TC_CANCELLED;
-               sowakeup(tp->t_socket);         /* wasteful */
+               sowwakeup(tp->t_inpcb->inp_socket);
        }
 /* win */
        if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) {
        }
 /* win */
        if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) {
@@ -492,169 +495,137 @@ COUNT(TCP_CTLDAT);
                tp->tc_flags |= TC_NEW_WINDOW;
                tp->t_persist = 0;
        }
                tp->tc_flags |= TC_NEW_WINDOW;
                tp->t_persist = 0;
        }
-       if (dataok == 0)
-               goto ctlonly;
 /* text */
 /* text */
-       if (n->t_len == 0)
-               goto notext;
-       { register int i;
-         register struct th *p, *q;
-         register struct mbuf *m;
-         int overage;
-
-       /*
-        * Discard duplicate data already passed to user.
-        */
-       if (SEQ_LT(n->t_seq, tp->rcv_nxt)) {
-               i = tp->rcv_nxt - n->t_seq;
-               if (i >= n->t_len)
-                       goto notext;
-               n->t_seq += i;
-               n->t_len -= i;
-               m_adj(dtom(n), i);
-       }
+       if (dataok && n->t_len) {
+               register struct tcpiphdr *p, *q;
+               int overage;
 
 
-       /*
-        * Find a segment which begins after this one does.
-        */
-       for (q = tp->tcb_hd.seg_next; q != (struct th *)tp; q = q->t_next)
-               if (SEQ_GT(q->t_seq, n->t_seq))
-                       break;
+/* eol */
+               if ((thflags&TH_EOL)) {
+                       register struct mbuf *m;
+                       for (m = dtom(n); m->m_next; m = m->m_next)
+                               ;
+                       m->m_act = (struct mbuf *)(mtod(m, caddr_t) - 1);
+               }
 
 
-       /*
-        * If there is a preceding segment, it may provide some of
-        * our data already.  If so, drop the data from the incoming
-        * segment.  If it provides all of our data, drop us.
-        */
-       if (q->t_prev != (struct th *)tp) {
-               /* conversion to int (in i) handles seq wraparound */
-               i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq;
-               if (i > 0) {
+/* text */
+               /*
+                * Discard duplicate data already passed to user.
+                */
+               if (SEQ_LT(n->t_seq, tp->rcv_nxt)) {
+                       register int i = tp->rcv_nxt - n->t_seq;
                        if (i >= n->t_len)
                        if (i >= n->t_len)
-                               goto notext;    /* w/o setting TC_NET_KEEP */
-                       m_adj(dtom(tp), i);
-                       n->t_len -= i;
+                               goto notext;
                        n->t_seq += i;
                        n->t_seq += i;
+                       n->t_len -= i;
+                       m_adj(dtom(n), i);
                }
                }
-       }
 
 
-       /*
-        * While we overlap succeeding segments trim them or,
-        * if they are completely covered, dequeue them.
-        */
-       while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) {
-               i = (n->t_seq + n->t_len) - q->t_seq;
-               if (i < q->t_len) {
-                       q->t_len -= i;
-                       m_adj(dtom(q), i);
-                       break;
-               }
-               q = q->t_next;
-               m_freem(dtom(q->t_prev));
-               remque(q->t_prev);
-       }
+               /*
+                * Find a segment which begins after this one does.
+                */
+               for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
+                   q = q->t_next)
+                       if (SEQ_GT(q->t_seq, n->t_seq))
+                               break;
 
 
-       /*
-        * Stick new segment in its place.
-        */
-       insque(n, q->t_prev);
-       tp->seqcnt += n->t_len;
+               /*
+                * If there is a preceding segment, it may provide some of
+                * our data already.  If so, drop the data from the incoming
+                * segment.  If it provides all of our data, drop us.
+                */
+               if (q->t_prev != (struct tcpiphdr *)tp) {
+                       /* conversion to int (in i) handles seq wraparound */
+                       register int i =
+                           q->t_prev->t_seq + q->t_prev->t_len - n->t_seq;
+                       if (i > 0) {
+                               if (i >= n->t_len)
+                                       goto notext;
+                                               /* w/o setting TC_NET_KEEP */
+                               m_adj(dtom(tp), i);
+                               n->t_len -= i;
+                               n->t_seq += i;
+                       }
+               }
 
 
-       /*
-        * Calculate available space and discard segments for
-        * which there is too much.
-        */
-       q = tp->tcb_hd.seg_prev;
-       overage = 
-           (tp->t_socket->so_rcv.sb_cc /* + tp->rcv_seqcnt XXX */) -
-               tp->t_socket->so_rcv.sb_hiwat;
-       if (overage > 0)
-               for (;;) {
-                       i = MIN(q->t_len, overage);
-                       overage -= i;
-                       q->t_len -= i;
-                       m_adj(q, -i);
-                       if (q == n)
-                               tp->tc_flags |= TC_DROPPED_TXT;
-                       if (q->t_len)
+               /*
+                * While we overlap succeeding segments trim them or,
+                * if they are completely covered, dequeue them.
+                */
+               while (q != (struct tcpiphdr *)tp &&
+                   SEQ_GT(n->t_seq + n->t_len, q->t_seq)) {
+                       register int i = (n->t_seq + n->t_len) - q->t_seq;
+                       if (i < q->t_len) {
+                               q->t_len -= i;
+                               m_adj(dtom(q), i);
                                break;
                                break;
-                       if (q == n)
-                               panic("tcp_text dropall");
-                       q = q->t_prev;
-                       remque(q->t_next);
+                       }
+                       q = q->t_next;
+                       m_freem(dtom(q->t_prev));
+                       remque(q->t_prev);
                }
 
                }
 
-       /*
-        * Advance rcv_next through
-        * newly completed sequence space
-        * and return forcing an ack.
-        */
-       while (n->t_seq == tp->rcv_nxt) {
-               /* present data belongs here */
-               tp->rcv_nxt += n->t_len;
-               n = n->t_next;
-               if (n == (struct th *)tp)
-                       break;
-       }
-       tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP);
-       }
-notext:
-/* urg */
-
-       if (thflags & (TH_URG|TH_EOL|TH_FIN)) {
-               if (thflags&TH_URG) {
-                       unsigned urgent;
+               /*
+                * Stick new segment in its place.
+                */
+               insque(n, q->t_prev);
+               tp->seqcnt += n->t_len;
 
 
-                       urgent = n->t_urp + n->t_seq;
-                       if (tp->rcv_nxt < urgent) {
-                               if (tp->rcv_urp <= tp->rcv_nxt) {
-                                       /* DO SOMETHING WITH URGENT!!! ### */
-                               }
-                               tp->rcv_urp = urgent;
+               /*
+                * Calculate available space and discard segments for
+                * which there is too much.
+                */
+               overage = 
+                   (so->so_rcv.sb_cc /*XXX+tp->rcv_seqcnt*/) - so->so_rcv.sb_hiwat;
+               if (overage > 0) {
+                       q = tp->seg_prev;
+                       for (;;) {
+                               register int i = MIN(q->t_len, overage);
+                               overage -= i;
+                               q->t_len -= i;
+                               m_adj(q, -i);
+                               if (q->t_len)
+                                       break;
+                               if (q == n)
+                                       panic("tcp_text dropall");
+                               q = q->t_prev;
+                               remque(q->t_next);
                        }
                }
                        }
                }
-/* eol */
-               if ((thflags&TH_EOL) &&
-                   (tp->tc_flags&TC_DROPPED_TXT) == 0 &&
-                   tp->tcb_hd.seg_prev != (struct th *)tp) {
-                       /* mark last mbuf */
-                       m = dtom(tp->tcb_hd.seg_prev);
-                       if (m != NULL) {
-                               while (m->m_next != NULL)
-                                       m = m->m_next;
-                               m->m_act =
-                                   (struct mbuf *)(m->m_off + m->m_len - 1);
-                       }
+
+               /*
+                * Advance rcv_next through newly completed sequence space.
+                */
+               while (n->t_seq == tp->rcv_nxt) {
+                       tp->rcv_nxt += n->t_len;
+                       n = n->t_next;
+                       if (n == (struct tcpiphdr *)tp)
+                               break;
+               }
+/* urg */
+               if (thflags&TH_URG) {
+                       /* ... */
+                       if (SEQ_GT(urgent, tp->rcv_urp))
+                               tp->rcv_urp = urgent;
                }
                }
-ctlonly:
+               tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP);
+       }
+notext:
 /* fin */
 /* fin */
-               if ((thflags&TH_FIN) &&
-                   (tp->tc_flags&TC_DROPPED_TXT) == 0) {
-                       seq_t last;
-
-                       if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
-                               /* do we really have fin ? */
-                               last = firstempty(tp);
-                               if (tp->tcb_hd.seg_prev == (struct th *)tp ||
-                                   last == t_end(tp->tcb_hd.seg_prev)) {
-                                       tp->tc_flags |= TC_FIN_RCVD;
-                                       sowakeup(tp->t_socket); /* ### */
-                               }
-                               if ((tp->tc_flags&TC_FIN_RCVD) &&
-                                   tp->rcv_nxt >= last) {
-                                       tp->rcv_nxt = last + 1;
-                                       tp->tc_flags |= TC_ACK_DUE;
-                               }
-                       } else
-                               tp->tc_flags |= TC_ACK_DUE;
+       if ((thflags&TH_FIN) && past == tp->rcv_nxt) {
+               if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
+                       tp->tc_flags |= TC_FIN_RCVD;
+                       sorwakeup(so);
+                       tp->rcv_nxt++;
                }
                }
+               tp->tc_flags |= TC_ACK_DUE;
        }
 /* respond */
        sent = 0;
        if (tp->tc_flags&TC_ACK_DUE)
                sent = tcp_sndctl(tp);
        else if ((tp->tc_flags&TC_NEW_WINDOW))
        }
 /* respond */
        sent = 0;
        if (tp->tc_flags&TC_ACK_DUE)
                sent = tcp_sndctl(tp);
        else if ((tp->tc_flags&TC_NEW_WINDOW))
-               if (tp->snd_nxt <= tp->snd_off + tp->t_socket->so_snd.sb_cc ||
+               if (tp->snd_nxt <= tp->snd_off + so->so_snd.sb_cc ||
                    (tp->tc_flags&TC_SND_FIN))
                        sent = tcp_send(tp);
 
                    (tp->tc_flags&TC_SND_FIN))
                        sent = tcp_send(tp);
 
@@ -667,41 +638,16 @@ ctlonly:
                tp->tc_flags &= ~TC_CANCELLED;
        }
 /* present data to user */
                tp->tc_flags &= ~TC_CANCELLED;
        }
 /* present data to user */
-       { register struct mbuf **mp;
-         register struct socket *so = tp->t_socket;
-         seq_t ready;
-
-       /* connection must be synced and data available for user */
        if ((tp->tc_flags&TC_SYN_ACKED) == 0)
                return;
        if ((tp->tc_flags&TC_SYN_ACKED) == 0)
                return;
-       so = tp->t_socket;
-       mp = &so->so_rcv.sb_mb;
-       while (*mp)
-               mp = &(*mp)->m_next;
-       n = tp->tcb_hd.seg_next;
-       /* SHOULD PACK DATA IN HERE */
-       while (n != (struct th *)tp && n->t_seq < tp->rcv_nxt) {
+       n = tp->seg_next;
+       while (n != (struct tcpiphdr *)tp && n->t_seq < tp->rcv_nxt) {
                remque(n);
                remque(n);
-               m = dtom(n);
-               so->so_rcv.sb_cc += n->t_len;
+               sbappend(so->so_rcv, dtom(n));
                tp->seqcnt -= n->t_len;
                tp->seqcnt -= n->t_len;
-               if (tp->seqcnt < 0) panic("present_data");
+               if (tp->seqcnt < 0)
+                       panic("tcp_input present");
                n = n->t_next;
                n = n->t_next;
-               while (m) {
-                       if (m->m_len == 0) {
-                               MFREE(m, *mp);
-                       } else {
-                               *mp = m;
-                               mp = &m->m_next;
-                       }
-                       m = *mp;
-               }
-       }
-       sowakeup(so);           /* should be macro/conditional */
        }
        }
-}
-
-tcp_drain()
-{
-
+       sorwakeup(so);
 }
 }
index 1a4a224..ec408d1 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_output.c 4.10 81/11/08 */
+/* tcp_output.c 4.11 81/11/14 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -8,6 +8,7 @@
 #include "../net/inet_cksum.h"
 #include "../net/inet.h"
 #include "../net/inet_host.h"
 #include "../net/inet_cksum.h"
 #include "../net/inet.h"
 #include "../net/inet_host.h"
+#include "../net/inet_pcb.h"
 #include "../net/inet_systm.h"
 #include "../net/imp.h"
 #include "../net/ip.h"
 #include "../net/inet_systm.h"
 #include "../net/imp.h"
 #include "../net/ip.h"
@@ -20,7 +21,7 @@
  * Special routines to send control messages.
  */
 tcp_sndctl(tp)
  * Special routines to send control messages.
  */
 tcp_sndctl(tp)
-       struct tcb *tp;
+       struct tcpcb *tp;
 {
 COUNT(TCP_SNDCTL);
 
 {
 COUNT(TCP_SNDCTL);
 
@@ -31,13 +32,14 @@ COUNT(TCP_SNDCTL);
 }
 
 tcp_sndwin(tp)
 }
 
 tcp_sndwin(tp)
-       struct tcb *tp;
+       struct tcpcb *tp;
 {
        int ihave, hehas;
 {
        int ihave, hehas;
-       register struct socket *so = tp->t_socket;
 COUNT(TCP_SNDWIN);
 
        if (tp->rcv_adv) {
 COUNT(TCP_SNDWIN);
 
        if (tp->rcv_adv) {
+               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;
                ihave = so->so_rcv.sb_hiwat -
                    (so->so_rcv.sb_cc + tp->seqcnt);
                hehas = tp->rcv_adv - tp->rcv_nxt;
@@ -51,7 +53,7 @@ COUNT(TCP_SNDWIN);
 }
 
 tcp_sndnull(tp)
 }
 
 tcp_sndnull(tp)
-       register struct tcb *tp;
+       register struct tcpcb *tp;
 {
 COUNT(TCP_SNDNULL);
 
 {
 COUNT(TCP_SNDNULL);
 
@@ -60,8 +62,8 @@ COUNT(TCP_SNDNULL);
 }
 
 tcp_sndrst(tp, n)
 }
 
 tcp_sndrst(tp, n)
-       register struct tcb *tp;
-       register struct th *n;
+       register struct tcpcb *tp;
+       register struct tcpiphdr *n;
 {
 COUNT(TCP_SNDRST);
 
 {
 COUNT(TCP_SNDRST);
 
@@ -80,17 +82,14 @@ COUNT(TCP_SNDRST);
  * Tcp segment output routine.
  */
 tcp_send(tp)
  * Tcp segment output routine.
  */
 tcp_send(tp)
-       register struct tcb *tp;
+       register struct tcpcb *tp;
 {
 {
-       register struct socket *so;
        register unsigned long last, wind;
        register unsigned long last, wind;
+       register struct socket *so = tp->t_inpcb->inp_socket;
        struct mbuf *m;
        struct mbuf *m;
-       int flags = 0, forced, sent;
-       struct mbuf *tcp_sndcopy();
-       int len;
+       int flags = 0, forced, sent, len;
 
 COUNT(TCP_SEND);
 
 COUNT(TCP_SEND);
-       so = tp->t_socket;
        tp->snd_lst = tp->snd_nxt;
        forced = 0;
        m = NULL;
        tp->snd_lst = tp->snd_nxt;
        forced = 0;
        m = NULL;
@@ -122,7 +121,9 @@ COUNT(TCP_SEND);
                        forced = 1;
                } else if (tp->snd_nxt >= tp->snd_lst && (tp->tc_flags&TC_SND_FIN) == 0)
                        return (0);
                        forced = 1;
                } else if (tp->snd_nxt >= tp->snd_lst && (tp->tc_flags&TC_SND_FIN) == 0)
                        return (0);
-               m = tcp_sndcopy(tp, MAX(tp->iss+1,tp->snd_nxt), tp->snd_lst);
+               m = sb_copy(&so->so_snd,
+                     MAX(tp->iss+1,tp->snd_nxt) - tp->snd_off,
+                     tp->snd_lst - tp->snd_off);
                if (tp->snd_end > tp->iss && tp->snd_end <= tp->snd_lst)
                        flags |= TH_EOL;
                if ((tp->tc_flags&TC_SND_FIN) && !forced &&
                if (tp->snd_end > tp->iss && tp->snd_end <= tp->snd_lst)
                        flags |= TH_EOL;
                if ((tp->tc_flags&TC_SND_FIN) && !forced &&
@@ -163,31 +164,31 @@ COUNT(TCP_SEND);
  * in a skeletal tcp/ip header, minimizing the amount of work
  * necessary when the connection is used.
  */
  * in a skeletal tcp/ip header, minimizing the amount of work
  * necessary when the connection is used.
  */
-struct th *
+struct tcpiphdr *
 tcp_template(tp)
 tcp_template(tp)
-       struct tcb *tp;
+       struct tcpcb *tp;
 {
 {
-       register struct host *h = tp->t_host;
+       register struct inpcb *inp = tp->t_inpcb;
+       register struct in_host *h = inp->inp_fhost;
        register struct mbuf *m;
        register struct mbuf *m;
-       register struct th *n;
-       register struct ip *ip;
+       register struct tcpiphdr *n;
 
        if (h == 0)
                return (0);
        m = m_get(1);
        if (m == 0)
                return (0);
 
        if (h == 0)
                return (0);
        m = m_get(1);
        if (m == 0)
                return (0);
-       m->m_off = MMAXOFF - sizeof (struct th);
-       m->m_len = sizeof (struct th);
-       n = mtod(m, struct th *);
+       m->m_off = MMAXOFF - sizeof (struct tcpiphdr);
+       m->m_len = sizeof (struct tcpiphdr);
+       n = mtod(m, struct tcpiphdr *);
        n->t_next = n->t_prev = 0;
        n->t_x1 = 0;
        n->t_pr = IPPROTO_TCP;
        n->t_next = n->t_prev = 0;
        n->t_x1 = 0;
        n->t_pr = IPPROTO_TCP;
-       n->t_len = htons(sizeof (struct th) - sizeof (struct ip));
+       n->t_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
        n->t_s.s_addr = n_lhost.s_addr;
        n->t_d.s_addr = h->h_addr.s_addr;
        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);
+       n->t_src = htons(inp->inp_lport);
+       n->t_dst = htons(inp->inp_fport);
        n->t_seq = 0;
        n->t_ackno = 0;
        n->t_x2 = 0;
        n->t_seq = 0;
        n->t_ackno = 0;
        n->t_x2 = 0;
@@ -200,13 +201,14 @@ tcp_template(tp)
 }
 
 tcp_output(tp, flags, len, dat)
 }
 
 tcp_output(tp, flags, len, dat)
-       register struct tcb *tp;
+       register struct tcpcb *tp;
        register int flags;
        int len;
        struct mbuf *dat;
 {
        register int flags;
        int len;
        struct mbuf *dat;
 {
-       register struct th *t;                  /* known to be r9 */
+       register struct tcpiphdr *t;                    /* known to be r9 */
        register struct mbuf *m;
        register struct mbuf *m;
+       struct socket *so = tp->t_inpcb->inp_socket;
        register struct ip *ip;
        int i;
 #ifdef TCPDEBUG
        register struct ip *ip;
        int i;
 #ifdef TCPDEBUG
@@ -219,15 +221,15 @@ COUNT(TCP_OUTPUT);
        MGET(m, 0);
        if (m == 0)
                return (0);
        MGET(m, 0);
        if (m == 0)
                return (0);
-       m->m_off = MMAXOFF - sizeof(struct th);
-       m->m_len = sizeof (struct th);
+       m->m_off = MMAXOFF - sizeof(struct tcpiphdr);
+       m->m_len = sizeof (struct tcpiphdr);
        m->m_next = dat;
        if (flags & TH_SYN)
                len--;
        if (flags & TH_FIN)
                len--;
        m->m_next = dat;
        if (flags & TH_SYN)
                len--;
        if (flags & TH_FIN)
                len--;
-       bcopy((caddr_t)t, mtod(m, caddr_t), sizeof (struct th));
-       t = mtod(m, struct th *);
+       bcopy((caddr_t)t, mtod(m, caddr_t), sizeof (struct tcpiphdr));
+       t = mtod(m, struct tcpiphdr *);
        if (tp->tc_flags&TC_SND_RST) {
                flags &= ~TH_SYN;
                flags |= TH_RST;
        if (tp->tc_flags&TC_SND_RST) {
                flags &= ~TH_SYN;
                flags |= TH_RST;
@@ -238,15 +240,15 @@ COUNT(TCP_OUTPUT);
        if (flags & TH_URG)
                t->t_urp = htons(tp->snd_urp);
        t->t_win =
        if (flags & TH_URG)
                t->t_urp = htons(tp->snd_urp);
        t->t_win =
-           tp->t_socket->so_rcv.sb_hiwat -
-               (tp->t_socket->so_rcv.sb_cc + tp->seqcnt);
+           so->so_rcv.sb_hiwat -
+               (so->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;
        if (len)
                t->t_len = htons(len + TCPSIZE);
        t->t_win = htons(t->t_win);
 #ifdef TCPDEBUG
        if (tp->rcv_nxt + t->t_win > tp->rcv_adv)
                tp->rcv_adv = tp->rcv_nxt + t->t_win;
        if (len)
                t->t_len = htons(len + TCPSIZE);
        t->t_win = htons(t->t_win);
 #ifdef TCPDEBUG
-       if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) {
+       if ((so->so_options & SO_DEBUG) || tcpconsdebug) {
                t->t_seq = tp->snd_nxt;
                t->t_ackno = tp->rcv_nxt;
                tdb_setup(tp, t, INSEND, &tdb);
                t->t_seq = tp->snd_nxt;
                t->t_ackno = tp->rcv_nxt;
                tdb_setup(tp, t, INSEND, &tdb);
@@ -256,12 +258,12 @@ COUNT(TCP_OUTPUT);
        t->t_seq = htonl(tp->snd_nxt);
        t->t_ackno = htonl(tp->rcv_nxt);
        t->t_sum = 0;           /* gratuitous? */
        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);
+       CKSUM_TCPSET(m, t, r9, sizeof (struct tcpiphdr) + len);
        ip = (struct ip *)t;
        ip->ip_v = IPVERSION;
        ip->ip_hl = 5;
        ip->ip_tos = 0;
        ip = (struct ip *)t;
        ip->ip_v = IPVERSION;
        ip->ip_hl = 5;
        ip->ip_tos = 0;
-       ip->ip_len = len + sizeof(struct th);
+       ip->ip_len = len + sizeof(struct tcpiphdr);
        ip->ip_id = ip_id++;
        ip->ip_off = 0;
        ip->ip_ttl = MAXTTL;
        ip->ip_id = ip_id++;
        ip->ip_off = 0;
        ip->ip_ttl = MAXTTL;
@@ -269,76 +271,6 @@ COUNT(TCP_OUTPUT);
        return (i);
 }
 
        return (i);
 }
 
-firstempty(tp)
-       register struct tcb *tp;
-{
-       register struct th *p, *q;
-COUNT(FIRSTEMPTY);
-
-       if ((p = tp->tcb_hd.seg_next) == (struct th *)tp ||
-           tp->rcv_nxt < p->t_seq)
-               return (tp->rcv_nxt);
-       while ((q = p->t_next) != (struct th *)tp &&
-           (t_end(p) + 1) == q->t_seq)
-               p = q;
-       return (t_end(p) + 1);
-}
-
-struct mbuf *
-tcp_sndcopy(tp, start, end)
-       struct tcb *tp;
-       u_long start, end;
-{
-       register struct mbuf *m, *n, **np;
-       u_long off;
-       register int len;
-       int adj;
-       struct mbuf *top, *p;
-COUNT(TCP_SNDCOPY);
-
-       if (start >= end)    
-               return (NULL);
-       off = tp->snd_off;
-       m = tp->t_socket->so_snd.sb_mb;
-       while (m != NULL && start >= (off + m->m_len)) {
-               off += m->m_len;
-               m = m->m_next;
-       }
-       np = &top;
-       top = 0;
-       adj = start - off;
-       len = end - start;
-       while (m && len > 0) {
-               MGET(n, 1);
-               *np = n;
-               if (n == 0)
-                       goto nospace;
-               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;
-                       mprefcnt[mtopf(p)]++;
-               } else {
-                       n->m_off = MMINOFF;
-                       bcopy(mtod(m, caddr_t)+adj, mtod(n, caddr_t),
-                           n->m_len);
-               }
-               len -= n->m_len;
-               adj = 0;
-               m = m->m_next;
-               /* SHOULD TRY PACKING INTO SMALL MBUFS HERE */
-               np = &n->m_next;
-       }
-       /* SHOULD NEVER RUN OUT OF m WHEN LEN */
-       if (len)
-               printf("snd_copy: m %x len %d\n", m, len);
-       return (top);
-nospace:
-       printf("snd_copy: no space\n");
-       m_freem(top);
-       return (0);
-}
-
 tcp_fasttimo()
 {
 
 tcp_fasttimo()
 {
 
index dfe68ea..d73fd28 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_usrreq.c 1.26 81/11/08 */
+/* tcp_usrreq.c 1.27 81/11/14 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -7,6 +7,8 @@
 #include "../h/socketvar.h"
 #include "../h/protosw.h"
 #include "../net/inet.h"
 #include "../h/socketvar.h"
 #include "../h/protosw.h"
 #include "../net/inet.h"
+#include "../net/inet_host.h"
+#include "../net/inet_pcb.h"
 #include "../net/inet_systm.h"
 #include "../net/imp.h"
 #include "../net/ip.h"
 #include "../net/inet_systm.h"
 #include "../net/imp.h"
 #include "../net/ip.h"
@@ -19,8 +21,6 @@
 #include "../net/tcp_var.h"
 #include "/usr/include/errno.h"
 
 #include "../net/tcp_var.h"
 #include "/usr/include/errno.h"
 
-struct tcb *tcp_attach();
-
 /*
  * Tcp initialization
  */
 /*
  * Tcp initialization
  */
@@ -28,7 +28,7 @@ tcp_init()
 {
 
        tcp_iss = 1;            /* wrong */
 {
 
        tcp_iss = 1;            /* wrong */
-       tcb.tcb_next = tcb.tcb_prev = (struct tcb *)&tcb;
+       tcb.inp_next = tcb.inp_prev = &tcb;
 }
 
 /*
 }
 
 /*
@@ -47,7 +47,8 @@ tcp_init()
  */
 tcp_slowtimo()
 {
  */
 tcp_slowtimo()
 {
-       register struct tcb *tp;
+       register struct inpcb *ip;
+       register struct tcpcb *tp;
        int s = splnet();
        register short *tmp;
        register int i;
        int s = splnet();
        register short *tmp;
        register int i;
@@ -56,12 +57,13 @@ COUNT(TCP_TIMEO);
        /*
         * Search through tcb's and update active timers.
         */
        /*
         * Search through tcb's and update active timers.
         */
-       tp = tcb.tcb_next;
-       for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next) {
+       for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) {
+               tp = intotcpcb(ip);
                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(tp->t_socket, PRU_SLOWTIMO, 0, i);
+                               tcp_usrreq(tp->t_inpcb->inp_socket,
+                                   PRU_SLOWTIMO, 0, i);
                        tmp++;
                }
                tp->t_xmt++;
                        tmp++;
                }
                tp->t_xmt++;
@@ -74,7 +76,7 @@ COUNT(TCP_TIMEO);
  * Cancel all timers for tcp tp.
  */
 tcp_tcancel(tp)
  * Cancel all timers for tcp tp.
  */
 tcp_tcancel(tp)
-       struct tcb *tp;
+       struct tcpcb *tp;
 {
        register short *tmp = &tp->t_init;
        register int i;
 {
        register short *tmp = &tp->t_init;
        register int i;
@@ -94,7 +96,8 @@ tcp_usrreq(so, req, m, addr)
        struct mbuf *m;
        caddr_t addr;
 {
        struct mbuf *m;
        caddr_t addr;
 {
-       register struct tcb *tp = (struct tcb *)so->so_pcb;
+       register struct inpcb *inp = sotoinpcb(so);
+       register struct tcpcb *tp = intotcpcb(inp);
        int s = splnet();
        register int nstate;
 #ifdef TCPDEBUG
        int s = splnet();
        register int nstate;
 #ifdef TCPDEBUG
@@ -103,93 +106,85 @@ tcp_usrreq(so, req, m, addr)
        int error = 0;
 COUNT(TCP_USRREQ);
 
        int error = 0;
 COUNT(TCP_USRREQ);
 
+       /*
+        * Make sure attached.  If not,
+        * only PRU_ATTACH is valid.
+        */
        if (tp) {
                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);
+       } else
+               if (req != PRU_ATTACH) {
+                       splx(s);
+                       return (EINVAL);
+               }
+
+       /*
+        * Do tracing and accounting.
+        */
 #ifdef KPROF
        acounts[nstate][req]++;
 #endif
 #ifdef TCPDEBUG
        if (tp && ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug)) {
 #ifdef KPROF
        acounts[nstate][req]++;
 #endif
 #ifdef TCPDEBUG
        if (tp && ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug)) {
-               tdb_setup(tp, (struct th *)0, req, &tdb);
+               tdb_setup(tp, (struct tcpiphdr *)0, req, &tdb);
                tdb.td_tim = timertype;
        } else
                tdb.td_tod = 0;
 #endif
        switch (req) {
 
                tdb.td_tim = timertype;
        } else
                tdb.td_tod = 0;
 #endif
        switch (req) {
 
-       /*
-        * Attach a tcp control block to this socket.
-        * TCP is not multicast, so this is possible
-        * only if no connection currently exists.
-        */
        case PRU_ATTACH:
                if (tp)
                        error = EISCONN;
        case PRU_ATTACH:
                if (tp)
                        error = EISCONN;
-               else
-                       tp = tcp_attach(so, &error);
-               nstate = CLOSED;
+               else {
+                       tcp_attach(so);
+                       tp = sototcpcb(so);
+               }
+               if (so->so_options & SO_ACCEPTCONN) {
+                       inp->inp_lhost = h_make(&n_lhost);
+                       in_pcbgenport(&tcb, inp);
+                       nstate = LISTEN;
+               } else
+                       nstate = CLOSED;
                break;
 
                break;
 
-       /*
-        * Detach the TCP from this socket.  This
-        * is possible only if a connection currently exists.
-        */
        case PRU_DETACH:
        case PRU_DETACH:
-               so->so_pcb = 0;
+               tcp_detach(so);
                break;
 
                break;
 
-       /*
-        * Form connection: send a SYN.
-        */
        case PRU_CONNECT:
        case PRU_CONNECT:
-               if (nstate != 0 && nstate != CLOSED)
+               if (tp->t_state != 0 && tp->t_state != CLOSED)
                        goto bad;
                        goto bad;
+               inp->inp_fhost = in_hmake((struct in_addr *)addr, &error);
+               if (inp->inp_fhost == 0)
+                       break;
                tcp_sndctl(tp);
                nstate = SYN_SENT;
                tcp_sndctl(tp);
                nstate = SYN_SENT;
+               soisconnecting(so);
                break;
 
        case PRU_DISCONNECT:
                break;
 
        case PRU_DISCONNECT:
-               so->so_pcb = 0;
-               tcp_destroy(tp);
+               if ((tp->tc_flags & TC_FIN_RCVD) == 0)
+                       goto abort;
+               if (nstate < ESTAB)
+                       tcp_disconnect(so);
+               else {
+                       tp->tc_flags |= TC_SND_FIN;
+                       tcp_sendctl(tp);
+                       tp->tc_flags |= TC_USR_CLOSED;
+                       soisdisconnecting(so);
+               }
                break;
 
                break;
 
-       /*
-        * 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.
-        */
        case PRU_SHUTDOWN:
                switch (nstate) {
 
        case PRU_SHUTDOWN:
                switch (nstate) {
 
-               /*
-                * If we are aborting out of a listener or a active
-                * connection which has not yet completed we can just
-                * delete the tcb.
-                */
                case LISTEN:
                case SYN_SENT:
                        nstate = CLOSED;
                        break;
 
                case LISTEN:
                case SYN_SENT:
                        nstate = CLOSED;
                        break;
 
-               /*
-                * If we have gotten as far as receiving a syn from
-                * our foreign peer, we must be sure to send a FIN.
-                * If we have gotten a FIN from the foreign peer already
-                * (CLOSE_WAIT state), then all that remains is to wait
-                * for his ack of the FIN (LAST_ACK state).  If we have
-                * not gotten a FIN from the foreign peer then we need
-                * to either:
-                *      1. rcv ack of our FIN (to FIN_W2) and then
-                *         send an ACK (to TIME_WAIT) and timeout at 2*MSL.
-                * or   2. receive hist FIN (to CLOSING), send an ACK
-                *         (to TIME_WAIT), and then timeout.
-                * In any case this starts with a transition to FIN_W1 here.
-                */
                case SYN_RCVD:
                case L_SYN_RCVD:
                case ESTAB:     
                case SYN_RCVD:
                case L_SYN_RCVD:
                case ESTAB:     
@@ -200,10 +195,6 @@ COUNT(TCP_USRREQ);
                        nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK;
                        break;
                        
                        nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK;
                        break;
                        
-               /*
-                * In these states the user has already closed;
-                * trying to close again is an error.
-                */
                case FIN_W1:
                case FIN_W2:
                case TIME_WAIT:
                case FIN_W1:
                case FIN_W2:
                case TIME_WAIT:
@@ -217,16 +208,6 @@ COUNT(TCP_USRREQ);
                }
                break;
 
                }
                break;
 
-       /*
-        * User notification of more window availability after
-        * reading out data.  This should not happen before a connection
-        * is established or after it is closed.
-        * If the foreign peer has closed and the local entity
-        * has not, inform him of the FIN (give end of file).
-        * If the local entity is in RCV_WAIT state (draining data
-        * out of the TCP buffers after foreign close) and there
-        * is no more data, institute a close.
-        */
        case PRU_RCVD:
                if (nstate < ESTAB || nstate == CLOSED)
                        goto bad;
        case PRU_RCVD:
                if (nstate < ESTAB || nstate == CLOSED)
                        goto bad;
@@ -234,84 +215,38 @@ COUNT(TCP_USRREQ);
                if ((tp->tc_flags&TC_FIN_RCVD) &&
                    (tp->tc_flags&TC_USR_CLOSED) == 0 &&
                    rcv_empty(tp))
                if ((tp->tc_flags&TC_FIN_RCVD) &&
                    (tp->tc_flags&TC_USR_CLOSED) == 0 &&
                    rcv_empty(tp))
-                       tcp_error(tp, ESHUTDOWN);
+                       error = ESHUTDOWN;
                if (nstate == RCV_WAIT && rcv_empty(tp))
                        nstate = CLOSED;
                break;
 
                if (nstate == RCV_WAIT && rcv_empty(tp))
                        nstate = CLOSED;
                break;
 
-       /*
-        * Send request on open connection.
-        * Should not happen if the connection is not yet established.
-        * Allowed only on ESTAB connection and after FIN from
-        * foreign peer.
-        */
        case PRU_SEND:
                switch (nstate) {
 
                case ESTAB:
                case CLOSE_WAIT:
        case PRU_SEND:
                switch (nstate) {
 
                case ESTAB:
                case CLOSE_WAIT:
-                       nstate = tcp_usrsend(tp, m);
+                       tcp_usrsend(tp, m);
                        break;
                
                default:
                        if (nstate < ESTAB)
                                goto bad;
                        m_freem(m);
                        break;
                
                default:
                        if (nstate < ESTAB)
                                goto bad;
                        m_freem(m);
-                       /* tcp_user(tp, UCLSERR); */
+                       error = ENOTCONN;
                        break;
                }
                break;
 
                        break;
                }
                break;
 
-       /*
-        * User abort of connection.
-        * If a SYN has been received, but we have not exchanged FINs
-        * then we need to send an RST.  In any case we then 
-        * enter closed state.
-        */
+abort:
        case PRU_ABORT:
        case PRU_ABORT:
-               if (nstate == 0 || nstate == CLOSED)
-                       break;
-               switch (nstate) {
-
-               case 0:
-               case CLOSED:
-                       break;
-
-               case SYN_RCVD:
-               case ESTAB:
-               case FIN_W1:
-               case FIN_W2:
-               case CLOSE_WAIT:
-                       tp->tc_flags |= TC_SND_RST;
-                       tcp_sndnull(tp);
-                       /* fall into ... */
-
-               default:
-                       nstate = CLOSED;
-               }
-               break;
-
-       /*
-        * Network down entry.  Discard the tcb and force
-        * the state to be closed, ungracefully.
-        */
-       case PRU_CLEAR:
-               if (nstate == 0 || nstate == CLOSED)
-                       break;
+               tcp_abort(tp);
                nstate = CLOSED;
                break;
 
                nstate = CLOSED;
                break;
 
-       /*
-        * Ioctl on protocols.
-        */
        case PRU_CONTROL:
        case PRU_CONTROL:
+               error = EOPNOTSUPP;
                break;
 
                break;
 
-       /*
-        * TCP Timer processing.
-        * Timers should expire only on open connections
-        * not in LISTEN state.
-        */
        case PRU_SLOWTIMO:
                switch (nstate) {
 
        case PRU_SLOWTIMO:
                switch (nstate) {
 
@@ -337,7 +272,6 @@ COUNT(TCP_USRREQ);
        if (tdb.td_tod)
                tdb_stuff(&tdb, nstate);
 #endif
        if (tdb.td_tod)
                tdb_stuff(&tdb, nstate);
 #endif
-       /* YECH */
        switch (nstate) {
 
        case CLOSED:
        switch (nstate) {
 
        case CLOSED:
@@ -354,37 +288,22 @@ COUNT(TCP_USRREQ);
                break;
        }
        splx(s);
                break;
        }
        splx(s);
+       return (error);
 }
 
 }
 
-tcp_sense()
-{
-
-}
-
-/*
- * Open routine, called to initialize newly created tcb fields.
- */
-struct tcb *
 tcp_attach(so)
        register struct socket *so;
 {
 tcp_attach(so)
        register struct socket *so;
 {
-       register struct tcb *tp;
+       register struct tcpcb *tp;
 COUNT(TCP_ATTACH);
 
        /*
 COUNT(TCP_ATTACH);
 
        /*
-        * Link in tcb queue and make
-        * initialize empty reassembly queue.
+        * Make empty reassembly queue.
         */
         */
-       tp->tcb_hd.tcb_next = tcb.tcb_next;
-       tcb.tcb_next->tcb_hd.tcb_prev = tp;
-       tp->tcb_hd.tcb_prev = (struct tcb *)&tcb;
-       tcb.tcb_next = tp;
-       tp->tcb_hd.seg_next = tp->tcb_hd.seg_prev = (struct th *)tp;
+       tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
 
        /*
 
        /*
-        * Initialize sequence numbers and
-        * round trip retransmit timer.
-        * (Other fields were init'd to zero when tcb allocated.)
+        * Initialize sequence numbers and round trip retransmit timer.
         */
        tp->t_xmtime = T_REXMT;
        tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una =
         */
        tp->t_xmtime = T_REXMT;
        tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una =
@@ -393,130 +312,90 @@ COUNT(TCP_ATTACH);
        tcp_iss += (ISSINCR >> 1) + 1;
 }
 
        tcp_iss += (ISSINCR >> 1) + 1;
 }
 
-/*
- * Destroy a tcb.
- */
-tcp_detach(tp)
-       register struct tcb *tp;
+tcp_detach(so)
+       register struct socket *so;
 {
 {
-       register struct socket *so = tp->t_socket;
-       register struct th *t;
+       register struct tcpcb *tp = (struct tcpcb *)so->so_pcb;
+       register struct tcpiphdr *t;
        register struct mbuf *m;
 COUNT(TCP_DETACH);
 
        register struct mbuf *m;
 COUNT(TCP_DETACH);
 
-       /*
-        * Remove from tcb queue and cancel timers.
-        */
-       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.
-        */
-       for (t = tp->tcb_hd.seg_next; t != (struct th *)tp; t = t->t_next)
-               m_freem(dtom(t));
-       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)
-               m_freem(m);
-       tp->seg_unack = 0;
+       wmemfree((caddr_t)tp, 1024);
+       m_release(so->so_rcv.sb_hiwat + so->so_snd.sb_hiwat + 2 * MSIZE);
+}
 
 
-       /*
-        * Free routing table entry.
-        */
-       if (tp->t_host) {
-               h_free(tp->t_host);
-               tp->t_host = 0;
-       }
+tcp_disconnect(tp)
+       register struct tcpcb *tp;
+{
+       register struct tcpiphdr *t;
+       register struct mbuf *m;
+       register struct socket *so;
 
 
-       /*
-        * Free tcp send template, the tcb itself,
-        * and the space we had reserved in the meory pool.
-        */
+       tcp_tcancel(tp);
+       t = tp->seg_next;
+       for (; t != (struct tcpiphdr *)tp; t = t->t_next)
+               m_freem(dtom(t));
+       tcp_drainunack(tp);
        if (tp->t_template) {
                m_free(dtom(tp->t_template));
                tp->t_template = 0;
        }
        if (tp->t_template) {
                m_free(dtom(tp->t_template));
                tp->t_template = 0;
        }
-       wmemfree((caddr_t)tp, 1024);
-       m_release(so->so_rcv.sb_hiwat + so->so_snd.sb_hiwat + 2 * MSIZE);
+       in_pcbfree(tp->t_inpcb);
+}
+
+tcp_abort(so)
+       register struct socket *so;
+{
+       register struct tcpcb *tp = sototcpcb(so);
+
+       switch (tp->t_state) {
+
+       case SYN_RCVD:
+       case ESTAB:
+       case FIN_W1:
+       case FIN_W2:
+       case CLOSE_WAIT:
+               tp->tc_flags |= TC_SND_RST;
+               tcp_sndnull(tp);
+       }
+       if (so)
+               soisdisconnected(so);
 }
 
 /*
  * Send data queue headed by m0 into the protocol.
  */
 tcp_usrsend(tp, m0)
 }
 
 /*
  * Send data queue headed by m0 into the protocol.
  */
 tcp_usrsend(tp, m0)
-       register struct tcb *tp;
+       register struct tcpcb *tp;
        struct mbuf *m0;
 {
        register struct mbuf *m, *n;
        struct mbuf *m0;
 {
        register struct mbuf *m, *n;
-       register struct socket *so = tp->t_socket;
+       register struct socket *so = tp->t_inpcb->inp_socket;
        register off;
        seq_t last;
 COUNT(TCP_USRSEND);
 
        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++;
-               if (m->m_off > MMAXOFF)
-                       so->so_snd.sb_mbcnt += NMBPG;
-               last += m->m_len;
-       }
-       if ((m = so->so_snd.sb_mb) == NULL)
-               so->so_snd.sb_mb = n;
-       else {
-               while (m->m_next != NULL) {
-                       m = m->m_next;
-                       last += m->m_len;
-               }
-               if (m->m_off <= MMAXOFF) {
-                       last += m->m_len;
-                       off = m->m_off + m->m_len;
-                       while (n && n->m_off <= MMAXOFF &&
-                           (MMAXOFF - off) >= n->m_len) {
-                               bcopy((caddr_t)((int)n + n->m_off),
-                                     (caddr_t)((int)m + off), n->m_len);
-                               m->m_len += n->m_len;
-                               off += n->m_len;
-                               so->so_snd.sb_mbcnt--;
-                               n = m_free(n);
-                       }
-               }
-               m->m_next = n;
-       }
+       sbappend(&so->so_snd, m0);
        if (tp->t_options & TO_EOL)
        if (tp->t_options & TO_EOL)
-               tp->snd_end = last;
+               tp->snd_end = tp->snd_off + so->so_snd.sb_cc;
        if (tp->t_options & TO_URG) {
        if (tp->t_options & TO_URG) {
-               tp->snd_urp = last+1;
+               tp->snd_urp = tp->snd_off + so->so_snd.sb_cc + 1;
                tp->tc_flags |= TC_SND_URG;
        }
        tcp_send(tp);
                tp->tc_flags |= TC_SND_URG;
        }
        tcp_send(tp);
-       return (SAME);
 }
 
 /*
  * TCP timer went off processing.
  */
 tcp_timers(tp, timertype)
 }
 
 /*
  * TCP timer went off processing.
  */
 tcp_timers(tp, timertype)
-       register struct tcb *tp;
+       register struct tcpcb *tp;
        int timertype;
 {
 
 COUNT(TCP_TIMERS);
        switch (timertype) {
 
        int timertype;
 {
 
 COUNT(TCP_TIMERS);
        switch (timertype) {
 
-       case TINIT:             /* initialization timer */
-               if ((tp->tc_flags&TC_SYN_ACKED) == 0) {         /* 35 */
-/* XXX */              /* tcp_close(tp, UINTIMO); */
-                       return (CLOSED);
-               }
-               return (SAME);
-
        case TFINACK:           /* fin-ack timer */
                switch (tp->t_state) {
 
        case TFINACK:           /* fin-ack timer */
                switch (tp->t_state) {
 
@@ -526,7 +405,7 @@ COUNT(TCP_TIMERS);
                         * 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)) {
-/* XXX */                      /* tcp_close(tp, UCLOSED); */   /* 14 */
+                               tcp_disconnect(tp);
                                return (CLOSED);
                        }
                        return (RCV_WAIT);                      /* 17 */
                                return (CLOSED);
                        }
                        return (RCV_WAIT);                      /* 17 */
@@ -556,12 +435,12 @@ COUNT(TCP_TIMERS);
 
        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 */
-/* XXX */              /* to_user(tp->t_socket, URXTIMO); */;
+                       tcp_error(EIO);         /* 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) {
-/* XXX */              /* tcp_close(tp, URXTIMO); */
+                       tcp_abort(tp);
                        return (CLOSED);
                }
                return (SAME);
                        return (CLOSED);
                }
                return (SAME);
@@ -577,6 +456,13 @@ COUNT(TCP_TIMERS);
        panic("tcp_timers");
 }
 
        panic("tcp_timers");
 }
 
+tcp_sense(m)
+       struct mbuf *m;
+{
+
+       return (EOPNOTSUPP);
+}
+
 tcp_error(so, errno)
        struct socket *so;
        int errno;
 tcp_error(so, errno)
        struct socket *so;
        int errno;
@@ -584,7 +470,8 @@ tcp_error(so, errno)
 COUNT(TO_USER);
 
        so->so_error = errno;
 COUNT(TO_USER);
 
        so->so_error = errno;
-       sowakeup(so);
+       sorwakeup(so);
+       sowwakeup(so);
 }
 
 #ifdef TCPDEBUG
 }
 
 #ifdef TCPDEBUG
@@ -593,8 +480,8 @@ COUNT(TO_USER);
  * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID.
  */
 tdb_setup(tp, n, input, tdp)
  * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID.
  */
 tdb_setup(tp, n, input, tdp)
-       struct tcb *tp;
-       register struct th *n;
+       struct tcpcb *tp;
+       register struct tcpiphdr *n;
        int input;
        register struct tcp_debug *tdp;
 {
        int input;
        register struct tcp_debug *tdp;
 {
index c97a58c..eaf6f45 100644 (file)
@@ -1,4 +1,4 @@
-/*     tcp_var.h       4.1     81/11/08        */
+/*     tcp_var.h       4.2     81/11/14        */
 
 /*
  * Kernel variables for tcp.
 
 /*
  * Kernel variables for tcp.
@@ -7,17 +7,10 @@
 /*
  * Tcp control block.
  */
 /*
  * Tcp control block.
  */
-struct tcb {
-       struct tcb_hd {
-               struct  th *seg_next,*seg_prev;         /* seq queue */
-               struct  tcb *tcb_next,*tcb_prev;        /* other tcb's */
-       } tcb_hd;
-       struct  th *t_template;         /* skeletal packet for transmit */
-       struct  socket *t_socket;       /* back pointer to socket */
-       struct  mbuf *seg_unack;        /* unacked message queue */
-       struct  host *t_host;
-       short   seqcnt;
-       short   xxx;
+struct tcpcb {
+       struct  tcpiphdr *seg_next,*seg_prev;   /* seq queue */
+       struct  tcpiphdr *t_template;   /* skeletal packet for transmit */
+       struct  inpcb *t_inpcb;
        seq_t   iss;                    /* initial send seq # */
        seq_t   irs;                    /* initial recv seq # */
        seq_t   rcv_urp;                /* rcv urgent pointer */
        seq_t   iss;                    /* initial send seq # */
        seq_t   irs;                    /* initial recv seq # */
        seq_t   rcv_urp;                /* rcv urgent pointer */
@@ -37,16 +30,16 @@ struct tcb {
        seq_t   t_rtl_val;              /* val saved in rexmt too long timer */
        seq_t   t_xmt_val;              /* seq # sent when xmt timer started */
        seq_t   rcv_adv;                /* advertised window */
        seq_t   t_rtl_val;              /* val saved in rexmt too long timer */
        seq_t   t_xmt_val;              /* seq # sent when xmt timer started */
        seq_t   rcv_adv;                /* advertised window */
+       struct  mbuf *seg_unack;        /* unacked message queue */
+       short   seqcnt;
        u_short tc_flags;               /* flags and state; see below */
        u_short t_options;
 #define        TO_EOL          0x01            /* eol mode */
 #define        TO_URG          0x02            /* urgent mode */
        u_short tc_flags;               /* flags and state; see below */
        u_short t_options;
 #define        TO_EOL          0x01            /* eol mode */
 #define        TO_URG          0x02            /* urgent mode */
-       u_short t_lport;                /* local port */
-       u_short t_fport;                /* foreign port */
        u_char  t_state;                /* state of this connection */
        u_char  t_xmtime;               /* current rexmt time */
 /* timers... must be in order */
        u_char  t_state;                /* state of this connection */
        u_char  t_xmtime;               /* current rexmt time */
 /* timers... must be in order */
-       short   t_init;                 /* initialization too long */
+       short   t_init;                 /* init */
        short   t_rexmt;                /* retransmission */
        short   t_rexmttl;              /* retransmit too long */
        short   t_persist;              /* retransmit persistance */
        short   t_rexmt;                /* retransmission */
        short   t_rexmttl;              /* retransmit too long */
        short   t_persist;              /* retransmit persistance */
@@ -58,7 +51,7 @@ struct tcb {
 /* tc_flags values */
 #define        TC_ACK_DUE      0x0001          /* must we send ACK */
 #define        TC_CANCELLED    0x0002          /* retransmit timer cancelled */
 /* tc_flags values */
 #define        TC_ACK_DUE      0x0001          /* must we send ACK */
 #define        TC_CANCELLED    0x0002          /* retransmit timer cancelled */
-#define        TC_DROPPED_TXT  0x0004          /* dropped incoming data */
+/* ... */
 #define        TC_FIN_RCVD     0x0008          /* FIN received */
 #define        TC_FORCE_ONE    0x0010          /* force sending of one byte */
 #define        TC_NEW_WINDOW   0x0020          /* received new window size */
 #define        TC_FIN_RCVD     0x0008          /* FIN received */
 #define        TC_FORCE_ONE    0x0010          /* force sending of one byte */
 #define        TC_NEW_WINDOW   0x0020          /* received new window size */
@@ -83,6 +76,9 @@ struct tcb {
 #define        TFINACK         4
 #define        TNTIMERS        5
 
 #define        TFINACK         4
 #define        TNTIMERS        5
 
+#define        intotcpcb(ip)   ((struct tcpcb *)(ip)->inp_ppcb)
+#define        sototcpcb(so)   (intotcpcb(sotoinpcb(so)))
+
 /*
  * Tcp machine predicates
  */
 /*
  * Tcp machine predicates
  */
@@ -98,8 +94,8 @@ struct tcb {
 
 #define        rcv_empty(x) \
     (((x)->tc_flags&TC_USR_ABORT) || \
 
 #define        rcv_empty(x) \
     (((x)->tc_flags&TC_USR_ABORT) || \
-      ((x)->t_socket->so_rcv.sb_mb == NULL && \
-       (x)->tcb_hd.seg_next == (x)->tcb_hd.seg_prev))
+      ((x)->t_inpcb->inp_socket->so_rcv.sb_mb == NULL && \
+       (x)->seg_next == (x)->seg_prev))
 
 #define        ISSINCR         128             /* increment for iss each second */
 #define        TCPSIZE         20              /* size of TCP leader (bytes) */
 
 #define        ISSINCR         128             /* increment for iss each second */
 #define        TCPSIZE         20              /* size of TCP leader (bytes) */
@@ -109,6 +105,7 @@ struct tcb {
  *
  * *2 here is because slow timeout routine called every 1/2 second.
  */
  *
  * *2 here is because slow timeout routine called every 1/2 second.
  */
+#define        T_INIT          (30*2)
 #define        T_2ML           (10*2)          /* 2*maximum packet lifetime */
 #define        T_PERS          (5*2)           /* persist time */
 #define        T_REXMT         (1*2)           /* base for retransmission time */
 #define        T_2ML           (10*2)          /* 2*maximum packet lifetime */
 #define        T_PERS          (5*2)           /* persist time */
 #define        T_REXMT         (1*2)           /* base for retransmission time */
@@ -122,7 +119,7 @@ struct tcb {
  */
 struct tcp_debug {
        long    td_tod;                 /* time of day */
  */
 struct tcp_debug {
        long    td_tod;                 /* time of day */
-       struct  tcb *td_tcb;            /* -> tcb */
+       struct  tcbcb *td_tcb;          /* -> tcb */
        char    td_old;                 /* old state */
        char    td_inp;                 /* input */
        char    td_tim;                 /* timer id */
        char    td_old;                 /* old state */
        char    td_inp;                 /* input */
        char    td_tim;                 /* timer id */
@@ -136,18 +133,17 @@ struct tcp_debug {
 #endif
 
 #ifdef KERNEL
 #endif
 
 #ifdef KERNEL
-struct tcb_hd tcb;                     /* tcp tcb list head */
 seq_t  tcp_iss;                        /* tcp initial send seq # */
 int    tcpconsdebug;                   /* set to 1 traces on console */
 seq_t  tcp_iss;                        /* tcp initial send seq # */
 int    tcpconsdebug;                   /* set to 1 traces on console */
+struct inpcb tcb;
 #ifdef TCPDEBUG
 struct tcp_debug tcp_debug[TDBSIZE];
 #endif
 int    tdbx;                   /* rotating index into tcp_debug */
 #ifdef TCPDEBUG
 struct tcp_debug tcp_debug[TDBSIZE];
 #endif
 int    tdbx;                   /* rotating index into tcp_debug */
-struct th *tcp_template();
+struct tcpiphdr *tcp_template();
 #endif
 
 #define        SEQ_LT(a,b)     ((int)((a)-(b)) < 0)
 #define        SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)
 #define        SEQ_GT(a,b)     ((int)((a)-(b)) > 0)
 #define        SEQ_GEQ(a,b)    ((int)((a)-(b)) >= 0)
 #endif
 
 #define        SEQ_LT(a,b)     ((int)((a)-(b)) < 0)
 #define        SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)
 #define        SEQ_GT(a,b)     ((int)((a)-(b)) > 0)
 #define        SEQ_GEQ(a,b)    ((int)((a)-(b)) >= 0)
-struct th *tcp_template();
index e815c78..b0c42d8 100644 (file)
@@ -1,20 +1,47 @@
-/*     udp_usrreq.c    4.2     81/11/08        */
+/*     udp_usrreq.c    4.3     81/11/14        */
 
 #include "../h/param.h"
 
 #include "../h/param.h"
+#include "../h/dir.h"
+#include "../h/user.h"
 #include "../h/mbuf.h"
 #include "../h/protosw.h"
 #include "../h/mbuf.h"
 #include "../h/protosw.h"
+#include "../h/socket.h"
+#include "../h/socketvar.h"
 #include "../net/inet.h"
 #include "../net/inet.h"
+#include "../net/inet_host.h"
+#include "../net/inet_pcb.h"
 #include "../net/inet_systm.h"
 #include "../net/inet_systm.h"
+#include "../net/udp.h"
+#include "../net/udp_var.h"
 
 udp_init()
 {
 
 
 udp_init()
 {
 
+       udb.inp_next = udb.inp_prev = &udp;
 }
 
 udp_input(m)
        struct mbuf *m;
 {
 }
 
 udp_input(m)
        struct mbuf *m;
 {
+       register struct inpcb *inp;
+       int raddr, rport;
+       int addr, port;
+
+       inp = inpcb_lookup(&udb, addr, port);
+       if (inp == 0)
+               goto bad;
+       /* sostuff(inp->inp_socket, m, raddr, rport); */
+       return;
+bad:
+       m_freem(m);
+       /* gen icmp? */
+}
 
 
+udp_ctlinput(m)
+       struct mbuf *m;
+{
+
+       m_freem(m);
 }
 
 udp_advise(m)
 }
 
 udp_advise(m)
@@ -24,51 +51,83 @@ udp_advise(m)
        m_freem(m);
 }
 
        m_freem(m);
 }
 
-udp_output(xx, m)
+udp_output(raddr, rport, m)
+       int raddr, rport;
        struct mbuf *m;
 {
 
        struct mbuf *m;
 {
 
+       /* setup header */
+       ip_output(m);
 }
 
 }
 
-udp_usrreq(up, req, m, addr)
-       struct socket *up;
+udp_usrreq(so, req, m, addr)
+       struct socket *so;
        int req;
        struct mbuf *m;
        struct in_addr *addr;
 {
        int req;
        struct mbuf *m;
        struct in_addr *addr;
 {
+       struct inpcb *inp = sotoinpcb(so);
+       int error;
 
        switch (req) {
 
        case PRU_ATTACH:
 
        switch (req) {
 
        case PRU_ATTACH:
+               if (inp != 0)
+                       return (EINVAL);
+               inp = in_pcballoc();
+               if (inp == NULL)
+                       return (ENOBUFS);
+               so->so_pcb = (caddr_t)inp;
+               break;
 
        case PRU_DETACH:
 
        case PRU_DETACH:
+               if (inp == 0)
+                       return (ENOTCONN);
+               sofree(inp->inp_socket);
+               udp_detach(inp);
+               break;
 
        case PRU_CONNECT:
 
        case PRU_CONNECT:
-
-       case PRU_DISCONNECT:
-
-       case PRU_ISCONN:
-
-       case PRU_ISDISCONN:
+               if (inp->inp_fhost)
+                       return (EISCONN);
+               inp->inp_fhost = in_hmake((struct in_addr *)addr, &error);
+               if (inp->inp_fhost == 0)
+                       return (error);
+               soisconnected(so);
                break;
 
                break;
 
-       case PRU_RCVD:
+       case PRU_DISCONNECT:
+               if (inp->inp_fhost == 0)
+                       return (ENOTCONN);
+               h_free(inp->inp_fhost);
+               inp->inp_fhost = 0;
+               soisdisconnected(so);
                break;
 
        case PRU_SEND:
                break;
 
        case PRU_SEND:
-               udp_output(0, m);
+#if 0
+               if (addr) {
+                       if (inp->inp_fhost)
+                               return (EISCONN);
+                       udp_output(addr->in_fhost, addr->in_fport, m);
+               } else
+                       udp_output(inp->inp_fhost->h_addr, ip->inp_fport, m);
+#endif
                break;
 
        case PRU_ABORT:
                break;
 
        case PRU_ABORT:
-       case PRU_CLEAR:
+               in_pcbfree(inp);
+               sofree(so);
+               soisdisconnected(so);
                break;
 
        case PRU_CONTROL:
                break;
 
        case PRU_CONTROL:
-               break;
+               return (EOPNOTSUPP);
 
        default:
                panic("udp_usrreq");
        }
 
        default:
                panic("udp_usrreq");
        }
+       return (0);
 }
 
 udp_sense()
 }
 
 udp_sense()
index 0ebcd4b..773668a 100644 (file)
@@ -1,4 +1,4 @@
-/* if_en.c 4.6 81/11/08 */
+/* if_en.c 4.7 81/11/14 */
 
 #include "en.h"
 /*
 
 #include "en.h"
 /*
@@ -12,7 +12,7 @@
 #include "../net/inet_systm.h"
 #include "../net/imp.h"
 #include "../net/ip.h"
 #include "../net/inet_systm.h"
 #include "../net/imp.h"
 #include "../net/ip.h"
-#include "../net/tcp.h"                        /* ### */
+#include "../net/tcp.h"                        /* XXX */
 #include "../h/map.h"
 #include "../h/pte.h"
 #include "../h/buf.h"
 #include "../h/map.h"
 #include "../h/pte.h"
 #include "../h/buf.h"
@@ -39,7 +39,7 @@ struct        uba_driver endriver =
 struct en_packet *xpkt, *rpkt;
 struct en_prefix {
        struct en_header enp_h;
 struct en_packet *xpkt, *rpkt;
 struct en_prefix {
        struct en_header enp_h;
-       struct th enp_th;
+       struct tcpiphdr enp_th;
 };
 struct uba_regs *enuba;
 struct pte *enrmr, *enxmr;
 };
 struct uba_regs *enuba;
 struct pte *enrmr, *enxmr;
@@ -384,7 +384,7 @@ COUNT(ENRINT);
        switch (ip->ip_p) {
 
        case IPPROTO_TCP:
        switch (ip->ip_p) {
 
        case IPPROTO_TCP:
-               hlen += ((struct th *)ip)->t_off * 4;
+               hlen += ((struct tcpiphdr *)ip)->t_off * 4;
                break;
        }
        MGET(m, 0);
                break;
        }
        MGET(m, 0);