lint and interface cleanups
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Mon, 30 Nov 1981 14:03:49 +0000 (06:03 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Mon, 30 Nov 1981 14:03:49 +0000 (06:03 -0800)
SCCS-vsn: sys/net/if.c 4.4
SCCS-vsn: sys/net/if.h 4.4
SCCS-vsn: sys/vax/if/if_en.c 4.15
SCCS-vsn: sys/vax/if/if_uba.c 4.3
SCCS-vsn: sys/netinet/in.h 4.6
SCCS-vsn: sys/netinet/in_pcb.c 4.10
SCCS-vsn: sys/netinet/in_systm.h 4.7
SCCS-vsn: sys/netinet/ip_icmp.c 4.9
SCCS-vsn: sys/netinet/ip_input.c 1.20
SCCS-vsn: sys/netinet/tcp_input.c 1.33
SCCS-vsn: sys/netinet/tcp_output.c 4.20
SCCS-vsn: sys/netinet/tcp_subr.c 4.4
SCCS-vsn: sys/netinet/tcp_timer.c 4.4
SCCS-vsn: sys/netinet/tcp_usrreq.c 1.37
SCCS-vsn: sys/netinet/tcp_var.h 4.10
SCCS-vsn: sys/netinet/udp_usrreq.c 4.12

16 files changed:
usr/src/sys/net/if.c
usr/src/sys/net/if.h
usr/src/sys/netinet/in.h
usr/src/sys/netinet/in_pcb.c
usr/src/sys/netinet/in_systm.h
usr/src/sys/netinet/ip_icmp.c
usr/src/sys/netinet/ip_input.c
usr/src/sys/netinet/tcp_input.c
usr/src/sys/netinet/tcp_output.c
usr/src/sys/netinet/tcp_subr.c
usr/src/sys/netinet/tcp_timer.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
usr/src/sys/vax/if/if_uba.c

index c09068a..1cd6adb 100644 (file)
@@ -1,4 +1,4 @@
-/*     if.c    4.3     81/11/26        */
+/*     if.c    4.4     81/11/29        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -36,6 +36,7 @@ COUNT(IF_IFONNETOF);
        return (ifp);
 }
 
        return (ifp);
 }
 
+/*ARGSUSED*/
 struct ifnet *
 if_gatewayfor(addr)
        struct in_addr addr;
 struct ifnet *
 if_gatewayfor(addr)
        struct in_addr addr;
@@ -44,3 +45,19 @@ if_gatewayfor(addr)
 COUNT(IF_GATEWAYFOR);
        return (0);
 }
 COUNT(IF_GATEWAYFOR);
        return (0);
 }
+
+struct in_addr
+if_makeaddr(net, host)
+       int net, host;
+{
+       u_long addr;
+
+       if (net < 128)
+               addr = (host << 8) | net;
+       else if (net < 65536)
+               addr = (host << 16) | net;
+       else
+               addr = (host << 24) | net;
+       addr = htonl(addr);
+       return (*(struct in_addr *)&addr);
+}
index 70cb7c6..428833f 100644 (file)
@@ -1,12 +1,30 @@
-/*     if.h    4.3     81/11/26        */
+/*     if.h    4.4     81/11/29        */
 
 /*
 
 /*
- * Definitions for network interfaces.
+ * Structures defining a network interface, providing a packet
+ * transport mechanism (ala level 0 of the PUP protocols).
+ *
+ * Each interface accepts output datagrams of a specified maximum
+ * length, and provides higher level routines with input datagrams
+ * received from its medium.
+ *
+ * Output occurs when the routine if_output is called, with three parameters:
+ *     (*ifp->if_output)(ifp, m, pf)
+ * Here m is the mbuf chain to be sent and pf is the protocol family
+ * of the internetwork datagram format in which the data is wrapped
+ * (e.g. PF_PUP or PF_INET).  The output routine encapsulates the
+ * supplied datagram if necessary, and then transmits it on its medium.
+ *
+ * On input, each interface unwraps the data received by it, and either
+ * places it on the input queue of a internetwork datagram routine
+ * and posts the associated software interrupt, or passes the datagram to a raw
+ * packet input routine.
+ *
+ * Routines exist for locating interfaces by their internet addresses
+ * or for locating a interface on a certain network, as well as more general
+ * routing and gateway routines maintaining information used to locate
+ * interfaces.  These routines live in the files if.c and ip_ggp.c.
  */
  */
-struct ifqueue {
-       struct  mbuf *ifq_head;
-       struct  mbuf *ifq_tail;
-};
 
 /*
  * Structure defining a queue for a network interface.
 
 /*
  * Structure defining a queue for a network interface.
@@ -19,15 +37,28 @@ struct ifnet {
        short   if_net;                 /* network number of interface */
        int     if_host[2];             /* local net host number */
        struct  in_addr if_addr;        /* internet address of interface */
        short   if_net;                 /* network number of interface */
        int     if_host[2];             /* local net host number */
        struct  in_addr if_addr;        /* internet address of interface */
-       struct  ifqueue if_snd;         /* output queue */
+       struct  ifqueue {
+               struct  mbuf *ifq_head;
+               struct  mbuf *ifq_tail;
+       } if_snd;                       /* output queue */
+/* procedure handles */
+       int     (*if_init)();           /* init routine */
        int     (*if_output)();         /* output routine */
        int     (*if_ubareset)();       /* uba reset routine */
        int     (*if_output)();         /* output routine */
        int     (*if_ubareset)();       /* uba reset routine */
-       int     if_collisions;
-       int     if_ierrors;
-       int     if_oerrors;
+/* generic interface statistics */
+       int     if_collisions;          /* collisions on csma interfaces */
+       int     if_ierrors;             /* input errors */
+       int     if_oerrors;             /* output errors */
+/* end statistics */
        struct  ifnet *if_next;
 };
 
        struct  ifnet *if_next;
 };
 
+/*
+ * Output queues (ifp->if_snd) and internetwork datagram level (pup level 1)
+ * input routines have queues of messages stored on ifqueue structures
+ * (defined above).  Entries are added to and deleted from these structures
+ * by these macros, which should be called with ipl raised to splimp().
+ */
 #define        IF_ENQUEUE(ifq, m) { \
        (m)->m_act = 0; \
        if ((ifq)->ifq_tail == 0) \
 #define        IF_ENQUEUE(ifq, m) { \
        (m)->m_act = 0; \
        if ((ifq)->ifq_tail == 0) \
@@ -48,6 +79,8 @@ struct ifnet {
 #ifdef INET
 struct ifqueue ipintrq;                /* ip packet input queue */
 #endif
 #ifdef INET
 struct ifqueue ipintrq;                /* ip packet input queue */
 #endif
+struct ifqueue rawintrq;               /* raw packet input queue */
 struct ifnet *ifnet;
 struct ifnet *if_ifwithaddr(), *if_ifonnetof(), *if_gatewayfor();
 struct ifnet *ifnet;
 struct ifnet *if_ifwithaddr(), *if_ifonnetof(), *if_gatewayfor();
+struct in_addr if_makeaddr();
 #endif
 #endif
index 5c0b7fd..d2fe71b 100644 (file)
@@ -1,4 +1,4 @@
-/* in.h 4.5 81/11/26 */
+/* in.h 4.6 81/11/29 */
 
 /*
  * Constants and structures defined by the internet system,
 
 /*
  * Constants and structures defined by the internet system,
index c9f1585..f41c868 100644 (file)
@@ -1,4 +1,4 @@
-/* in_pcb.c 4.9 81/11/26 */
+/* in_pcb.c 4.10 81/11/29 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -37,7 +37,7 @@ in_pcballoc(so, head, sndcc, rcvcc, sin)
                lport = sin->sin_port;
                if (lport) {
                        xp = head->inp_next;
                lport = sin->sin_port;
                if (lport) {
                        xp = head->inp_next;
-                       for (; xp != head; xp = inp->inp_next) 
+                       for (; xp != head; xp = xp->inp_next) 
                                if (xp->inp_laddr.s_addr ==
                                    sin->sin_addr.s_addr &&
                                    xp->inp_lport == lport &&
                                if (xp->inp_laddr.s_addr ==
                                    sin->sin_addr.s_addr &&
                                    xp->inp_lport == lport &&
index 167f207..ab7e6a9 100644 (file)
@@ -1,4 +1,4 @@
-/* in_systm.h 4.6 81/11/26 */
+/* in_systm.h 4.7 81/11/29 */
 
 /*
  * Miscellaneous internetwork
 
 /*
  * Miscellaneous internetwork
@@ -32,6 +32,7 @@ typedef       u_long  n_time;                 /* ms since 00:00 GMT, byte rev */
  */
 #define        splimp          spl5
 #define        setipintr()     mtpr(SIRR, 12)
  */
 #define        splimp          spl5
 #define        setipintr()     mtpr(SIRR, 12)
+#define        setrawintr()    mtpr(SIRR, 13)
 /* splnet is defined in ../sys/asm.sed */
 
 #ifdef KERNEL
 /* splnet is defined in ../sys/asm.sed */
 
 #ifdef KERNEL
index 51656bc..4bd9cb3 100644 (file)
@@ -1,4 +1,4 @@
-/*     ip_icmp.c       4.8     81/11/26        */
+/*     ip_icmp.c       4.9     81/11/29        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -179,7 +179,7 @@ COUNT(ICMP_SEND);
        icp->icmp_cksum = 0;
        icp->icmp_cksum = in_cksum(dtom(ip), 0);                /* XXX */
        ip->ip_ttl = MAXTTL;
        icp->icmp_cksum = 0;
        icp->icmp_cksum = in_cksum(dtom(ip), 0);                /* XXX */
        ip->ip_ttl = MAXTTL;
-       ip_output(dtom(ip), (struct mbuf *)0);
+       (void) ip_output(dtom(ip), (struct mbuf *)0);
 }
 
 /*
 }
 
 /*
index 014e589..b4fc9cc 100644 (file)
@@ -1,4 +1,4 @@
-/* ip_input.c 1.19 81/11/26 */
+/* ip_input.c 1.20 81/11/29 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -119,7 +119,7 @@ next:
                        icmp_error(ip, ICMP_TIMXCEED, 0);
                        goto next;
                }
                        icmp_error(ip, ICMP_TIMXCEED, 0);
                        goto next;
                }
-               ip_output(dtom(ip), (struct mbuf *)0);
+               (void) ip_output(dtom(ip), (struct mbuf *)0);
                goto next;
        }
 
                goto next;
        }
 
index 5c5b308..c42be63 100644 (file)
@@ -1,4 +1,4 @@
-/*     tcp_input.c     1.32    81/11/26        */
+/*     tcp_input.c     1.33    81/11/29        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
-#include "/usr/include/errno.h"
+#include "../errno.h"
 
 int    tcpcksum = 1;
 
 
 int    tcpcksum = 1;
 
-struct sockaddr_in tcp_sockaddr = { AF_INET };
-
 /*
  * TCP input routine, follows pages 65-76 of the
  * protocol specification dated September, 1981 very closely.
 /*
  * TCP input routine, follows pages 65-76 of the
  * protocol specification dated September, 1981 very closely.
@@ -38,8 +36,7 @@ tcp_input(m0)
        register struct tcpcb *tp;
        register int tiflags;
        struct socket *so;
        register struct tcpcb *tp;
        register int tiflags;
        struct socket *so;
-       int acceptable;
-       tcp_seq todrop, acked;
+       int todrop, acked;
 
 COUNT(TCP_INPUT);
        /*
 
 COUNT(TCP_INPUT);
        /*
@@ -112,6 +109,7 @@ COUNT(TCP_INPUT);
        tp = intotcpcb(inp);
        if (tp == 0)
                goto dropwithreset;
        tp = intotcpcb(inp);
        if (tp == 0)
                goto dropwithreset;
+       so = inp->inp_socket;
 
        /*
         * Calculate amount of space in receive window,
 
        /*
         * Calculate amount of space in receive window,
@@ -533,11 +531,11 @@ dropwithreset:
        if (tiflags & TH_RST)
                goto drop;
        if (tiflags & TH_ACK)
        if (tiflags & TH_RST)
                goto drop;
        if (tiflags & TH_ACK)
-               tcp_respond(ti, 0, ti->ti_ack, TH_RST);
+               tcp_respond(ti, (tcp_seq)0, ti->ti_ack, TH_RST);
        else {
                if (tiflags & TH_SYN)
                        ti->ti_len++;
        else {
                if (tiflags & TH_SYN)
                        ti->ti_len++;
-               tcp_respond(ti, ti->ti_seq+ti->ti_len, 0, TH_RST|TH_ACK);
+               tcp_respond(ti, ti->ti_seq+ti->ti_len, (tcp_seq)0, TH_RST|TH_ACK);
        }
        goto drop;
 
        }
        goto drop;
 
@@ -553,10 +551,9 @@ drop:
  * control block tp.  Return TH_FIN if reassembly now includes
  * a segment with FIN.
  */
  * control block tp.  Return TH_FIN if reassembly now includes
  * a segment with FIN.
  */
-tcp_reass(tp, ti, endp)
+tcp_reass(tp, ti)
        register struct tcpcb *tp;
        register struct tcpiphdr *ti;
        register struct tcpcb *tp;
        register struct tcpiphdr *ti;
-       int *endp;
 {
        register struct tcpiphdr *q;
        struct socket *so = tp->t_inpcb->inp_socket;
 {
        register struct tcpiphdr *q;
        struct socket *so = tp->t_inpcb->inp_socket;
index 7bca688..a3799fd 100644 (file)
@@ -1,4 +1,4 @@
-/*     tcp_output.c    4.19    81/11/26        */
+/*     tcp_output.c    4.20    81/11/29        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -17,7 +17,7 @@
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
-#include "/usr/include/errno.h"
+#include "../errno.h"
 
 /*
  * Tcp output routine: figure out what should be sent
 
 /*
  * Tcp output routine: figure out what should be sent
@@ -76,7 +76,7 @@ COUNT(TCP_OUTPUT);
        /*
         * No reason to send a segment, just return.
         */
        /*
         * No reason to send a segment, just return.
         */
-       return;
+       return (0);
 
 send:
        /*
 
 send:
        /*
@@ -97,7 +97,7 @@ send:
        ti = mtod(m, struct tcpiphdr *);
        if (tp->t_template == 0)
                panic("tcp_output");
        ti = mtod(m, struct tcpiphdr *);
        if (tp->t_template == 0)
                panic("tcp_output");
-       bcopy((caddr_t)tp->t_template, ti, sizeof (struct tcpiphdr));
+       bcopy((caddr_t)tp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr));
 
        /*
         * Fill in fields, remembering maximum advertised
 
        /*
         * Fill in fields, remembering maximum advertised
@@ -106,22 +106,24 @@ send:
        ti->ti_seq = htonl(tp->snd_nxt);
        ti->ti_ack = htonl(tp->rcv_nxt);
        if (tp->t_tcpopt) {
        ti->ti_seq = htonl(tp->snd_nxt);
        ti->ti_ack = htonl(tp->rcv_nxt);
        if (tp->t_tcpopt) {
+               m0 = m->m_next;
                m->m_next = m_get(0);
                if (m->m_next == 0) {
                        (void) m_free(m);
                m->m_next = m_get(0);
                if (m->m_next == 0) {
                        (void) m_free(m);
+                       m_freem(m);
                        return (0);
                }
                m->m_next->m_next = m0;
                m->m_off = MMINOFF;
                m->m_len = tp->t_tcpopt->m_len;
                bcopy(mtod(tp->t_tcpopt, caddr_t), mtod(m, caddr_t),
                        return (0);
                }
                m->m_next->m_next = m0;
                m->m_off = MMINOFF;
                m->m_len = tp->t_tcpopt->m_len;
                bcopy(mtod(tp->t_tcpopt, caddr_t), mtod(m, caddr_t),
-                   tp->t_tcpopt->m_len);
+                   (unsigned)tp->t_tcpopt->m_len);
                ti->ti_off = (sizeof (struct tcphdr)+tp->t_tcpopt->m_len) >> 2;
        }
        ti->ti_flags = flags;
        win = sbspace(&so->so_rcv);
        if (win > 0)
                ti->ti_off = (sizeof (struct tcphdr)+tp->t_tcpopt->m_len) >> 2;
        }
        ti->ti_flags = flags;
        win = sbspace(&so->so_rcv);
        if (win > 0)
-               ti->ti_win = htons(win);
+               ti->ti_win = htons((u_short)win);
        if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
                ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
                ti->ti_flags |= TH_URG;
        if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
                ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
                ti->ti_flags |= TH_URG;
index 68ffd1e..471e467 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_subr.c 4.3 81/11/26 */
+/* tcp_subr.c 4.4 81/11/29 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -19,7 +19,7 @@
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
-#include "/usr/include/errno.h"
+#include "../errno.h"
 
 /*
  * Tcp initialization
 
 /*
  * Tcp initialization
@@ -103,7 +103,7 @@ COUNT(TCP_RESPOND);
        ti->ti_sum = in_cksum(m, sizeof(struct tcpiphdr));
        ((struct ip *)ti)->ip_len = sizeof(struct tcpiphdr);
        ((struct ip *)ti)->ip_ttl = TCP_TTL;
        ti->ti_sum = in_cksum(m, sizeof(struct tcpiphdr));
        ((struct ip *)ti)->ip_len = sizeof(struct tcpiphdr);
        ((struct ip *)ti)->ip_ttl = TCP_TTL;
-       ip_output(m, (struct mbuf *)0);
+       (void) ip_output(m, (struct mbuf *)0);
 }
 
 /*
 }
 
 /*
@@ -178,18 +178,8 @@ COUNT(TCP_CLOSE);
        socantsendmore(so);
 }
 
        socantsendmore(so);
 }
 
-/*ARGSUSED*/
-tcp_sense(m)
-       struct mbuf *m;
-{
-
-COUNT(TCP_SENSE);
-       return (EOPNOTSUPP);
-}
-
 tcp_drain()
 {
 tcp_drain()
 {
-       register struct inpcb *ip;
 
 COUNT(TCP_DRAIN);
 }
 
 COUNT(TCP_DRAIN);
 }
index 5e6a849..31ce879 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_timer.c 4.3 81/11/26 */
+/* tcp_timer.c 4.4 81/11/29 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -18,7 +18,7 @@
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
-#include "/usr/include/errno.h"
+#include "../errno.h"
 
 /*
  * Fast timeout routine for processing delayed acks
 
 /*
  * Fast timeout routine for processing delayed acks
@@ -39,7 +39,6 @@ tcp_slowtimo()
        register struct inpcb *ip;
        register struct tcpcb *tp;
        int s = splnet();
        register struct inpcb *ip;
        register struct tcpcb *tp;
        int s = splnet();
-       register short *tmp;
        register int i;
 COUNT(TCP_SLOWTIMO);
 
        register int i;
 COUNT(TCP_SLOWTIMO);
 
@@ -53,7 +52,6 @@ COUNT(TCP_SLOWTIMO);
                                (void) tcp_usrreq(tp->t_inpcb->inp_socket,
                                    PRU_SLOWTIMO, (struct mbuf *)0,
                                    (caddr_t)i);
                                (void) tcp_usrreq(tp->t_inpcb->inp_socket,
                                    PRU_SLOWTIMO, (struct mbuf *)0,
                                    (caddr_t)i);
-                       tmp++;
                }
        }
        tcp_iss += TCP_ISSINCR/PR_SLOWHZ;               /* increment iss */
                }
        }
        tcp_iss += TCP_ISSINCR/PR_SLOWHZ;               /* increment iss */
index 6131b5f..3202c3d 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_usrreq.c 1.36 81/11/26 */
+/* tcp_usrreq.c 1.37 81/11/29 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -18,7 +18,7 @@
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
 #include "../net/tcp_timer.h"
 #include "../net/tcp_var.h"
 #include "../net/tcpip.h"
-#include "/usr/include/errno.h"
+#include "../errno.h"
 
 struct tcpcb *tcp_newtcpcb();
 /*
 
 struct tcpcb *tcp_newtcpcb();
 /*
@@ -36,7 +36,6 @@ tcp_usrreq(so, req, m, addr)
        register struct tcpcb *tp;
        int s = splnet();
        int error = 0;
        register struct tcpcb *tp;
        int s = splnet();
        int error = 0;
-       struct tcpiphdr ti;
 COUNT(TCP_USRREQ);
 
        /*
 COUNT(TCP_USRREQ);
 
        /*
@@ -93,7 +92,7 @@ COUNT(TCP_USRREQ);
                inp->inp_ppcb = (caddr_t)tp;
                soisconnecting(so);
                tp->t_state = TCPS_SYN_SENT;
                inp->inp_ppcb = (caddr_t)tp;
                soisconnecting(so);
                tp->t_state = TCPS_SYN_SENT;
-               tcp_output(tp);
+               (void) tcp_output(tp);
                break;
 
        case PRU_ACCEPT:
                break;
 
        case PRU_ACCEPT:
@@ -105,7 +104,7 @@ COUNT(TCP_USRREQ);
                        tcp_close(tp);
                else {
                        soisdisconnecting(so);
                        tcp_close(tp);
                else {
                        soisdisconnecting(so);
-                       tcp_output(tp);
+                       (void) tcp_output(tp);
                }
                break;
 
                }
                break;
 
@@ -121,18 +120,18 @@ COUNT(TCP_USRREQ);
                case TCPS_SYN_RECEIVED:
                case TCPS_ESTABLISHED:
                        tp->t_state = TCPS_FIN_WAIT_1;
                case TCPS_SYN_RECEIVED:
                case TCPS_ESTABLISHED:
                        tp->t_state = TCPS_FIN_WAIT_1;
-                       tcp_output(tp);
+                       (void) tcp_output(tp);
                        break;
 
                case TCPS_CLOSE_WAIT:
                        tp->t_state = TCPS_LAST_ACK;
                        break;
 
                case TCPS_CLOSE_WAIT:
                        tp->t_state = TCPS_LAST_ACK;
-                       tcp_output(tp);
+                       (void) tcp_output(tp);
                        break;
                }
                break;
 
        case PRU_RCVD:
                        break;
                }
                break;
 
        case PRU_RCVD:
-               tcp_output(tp);
+               (void) tcp_output(tp);
                break;
 
        case PRU_SEND:
                break;
 
        case PRU_SEND:
@@ -143,7 +142,7 @@ COUNT(TCP_USRREQ);
  */
                if (tp->t_flags & TF_URG)
                        tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1;
  */
                if (tp->t_flags & TF_URG)
                        tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1;
-               tcp_output(tp);
+               (void) tcp_output(tp);
                break;
 
        case PRU_ABORT:
                break;
 
        case PRU_ABORT:
@@ -154,6 +153,18 @@ COUNT(TCP_USRREQ);
                error = EOPNOTSUPP;
                break;
 
                error = EOPNOTSUPP;
                break;
 
+       case PRU_SENSE:
+               error = EOPNOTSUPP;
+               break;
+
+       case PRU_RCVOOB:
+               error = EOPNOTSUPP;
+               break;
+
+       case PRU_SENDOOB:
+               error = EOPNOTSUPP;
+               break;
+
        case PRU_SLOWTIMO:
                tcp_timers(tp, (int)addr);
                break;
        case PRU_SLOWTIMO:
                tcp_timers(tp, (int)addr);
                break;
index 604140c..96a4ca0 100644 (file)
@@ -1,4 +1,4 @@
-/*     tcp_var.h       4.9     81/11/26        */
+/*     tcp_var.h       4.10    81/11/29        */
 
 /*
  * Kernel variables for tcp.
 
 /*
  * Kernel variables for tcp.
@@ -54,13 +54,9 @@ struct tcpcb {
        short   rxt_cnt;
 };
 
        short   rxt_cnt;
 };
 
-#define        tcp_finisacked(tp)      0               /* XXX */
-
 #define        intotcpcb(ip)   ((struct tcpcb *)(ip)->inp_ppcb)
 #define        sototcpcb(so)   (intotcpcb(sotoinpcb(so)))
 
 #define        intotcpcb(ip)   ((struct tcpcb *)(ip)->inp_ppcb)
 #define        sototcpcb(so)   (intotcpcb(sotoinpcb(so)))
 
-#define        TCP_ISSINCR     128             /* increment for iss each second */
-
 struct tcpstat {
        int     tcps_badsum;
        int     tcps_badoff;
 struct tcpstat {
        int     tcps_badsum;
        int     tcps_badoff;
index c878fe5..062ff7b 100644 (file)
@@ -1,4 +1,4 @@
-/*     udp_usrreq.c    4.11    81/11/26        */
+/*     udp_usrreq.c    4.12    81/11/29        */
 
 #include "../h/param.h"
 #include "../h/dir.h"
 
 #include "../h/param.h"
 #include "../h/dir.h"
@@ -160,7 +160,7 @@ COUNT(UDP_OUTPUT);
        ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len);
        ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
        ((struct ip *)ui)->ip_ttl = MAXTTL;
        ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len);
        ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
        ((struct ip *)ui)->ip_ttl = MAXTTL;
-       ip_output(m, (struct mbuf *)0);
+       (void) ip_output(m, (struct mbuf *)0);
        return;
 bad:
        m_freem(m);
        return;
 bad:
        m_freem(m);
index 188a16f..9048145 100644 (file)
@@ -1,8 +1,9 @@
-/*     if_en.c 4.14    81/11/26        */
+/*     if_en.c 4.15    81/11/29        */
 
 #include "en.h"
 
 #include "en.h"
+
 /*
 /*
- * Ethernet interface driver
+ * Xerox prototype (3 Mb) Ethernet interface driver.
  */
 
 #include "../h/param.h"
  */
 
 #include "../h/param.h"
@@ -35,17 +36,34 @@ struct      uba_driver endriver =
        { enprobe, 0, enattach, 0, enstd, "es", eninfo };
 #define        ENUNIT(x)       minor(x)
 
        { enprobe, 0, enattach, 0, enstd, "es", eninfo };
 #define        ENUNIT(x)       minor(x)
 
+int    eninit(),enoutput(),enreset();
+
+/*
+ * Ethernet software status per interface.
+ *
+ * Each interface is referenced by a network interface structure,
+ * es_if, which the routing code uses to locate the interface.
+ * This structure contains the output queue for the interface, its address, ...
+ * We also have, for each interface, a UBA interface structure, which
+ * contains information about the UNIBUS resources held by the interface:
+ * map registers, buffered data paths, etc.  Information is cached in this
+ * structure for use by the if_uba.c routines in running the interface
+ * efficiently.
+ */
 struct en_softc {
 struct en_softc {
-       struct  ifnet *es_if;
-       struct  ifuba *es_ifuba;
-       short   es_delay;
-       short   es_mask;
-       u_char  es_addr;
-       u_char  es_lastx;
-       short   es_oactive;
-       short   es_olen;
+       struct  ifnet es_if;            /* network-visible interface */
+       struct  ifuba es_ifuba;         /* UNIBUS resources */
+       short   es_delay;               /* current output delay */
+       short   es_mask;                /* mask for current output delay */
+       u_char  es_lastx;               /* host last transmitted to */
+       short   es_oactive;             /* is output active? */
+       short   es_olen;                /* length of last output */
 } en_softc[NEN];
 
 } en_softc[NEN];
 
+/*
+ * Do output DMA to determine interface presence and
+ * interrupt vector.  DMA is too short to disturb other hosts.
+ */
 enprobe(reg)
        caddr_t reg;
 {
 enprobe(reg)
        caddr_t reg;
 {
@@ -66,56 +84,89 @@ COUNT(ENPROBE);
        return (1);
 }
 
        return (1);
 }
 
-/*ARGSUSED*/
+/*
+ * Interface exists: make available by filling in network interface
+ * record.  System will initialize the interface when it is ready
+ * to accept packets.
+ */
 enattach(ui)
        struct uba_device *ui;
 {
 enattach(ui)
        struct uba_device *ui;
 {
-
+       register struct en_softc *es = &en_softc[ui->ui_unit];
 COUNT(ENATTACH);
 COUNT(ENATTACH);
-       eninit(ui->ui_unit);
-       /* net initialization, based on ui->ui_flags?!? */
+
+       es->es_if.if_unit = ui->ui_unit;
+       es->es_if.if_mtu = ENMTU;
+       es->es_if.if_net = ui->ui_flags;
+       es->es_if.if_host[0] =
+           ~(((struct endevice *)eninfo[ui->ui_unit])->en_addr) & 0xff;
+       es->es_if.if_addr =
+           if_makeaddr(es->es_if.if_net, es->es_if.if_host[0]);
+       es->es_if.if_output = enoutput;
+       es->es_if.if_init = eninit;
+       es->es_if.if_ubareset = enreset;
 }
 
 }
 
-eninit(unit)
-       int unit;
+/*
+ * Reset of interface after UNIBUS reset.
+ * If interface is on specified uba, reset its state.
+ */
+enreset(unit, uban)
+       int unit, uban;
 {
        register struct uba_device *ui;
 {
        register struct uba_device *ui;
-       register struct endevice *addr;
-       register struct en_softc *es;
+COUNT(ENRESET);
 
 
-COUNT(ENINIT);
        if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0) {
                printf("es%d: not alive\n", unit);
                return;
        }
        if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0) {
                printf("es%d: not alive\n", unit);
                return;
        }
+       if (ui->ui_ubanum != uban)
+               return;
+       eninit(unit);
+}
+
+/*
+ * Initialization of interface; clear recorded pending
+ * operations, and reinitialize UNIBUS usage.
+ */
+eninit(unit)
+       int unit;
+{
+       register struct uba_device *ui;
+       register struct endevice *addr;
+       register struct en_softc *es;
+       int s;
+
        es = &en_softc[unit];
        es = &en_softc[unit];
-       if (if_ubainit(es->es_ifuba, ui->ui_ubanum,
-           sizeof (struct en_header), btop(ENMTU)) == 0) { 
+       ui = eninfo[unit];
+       if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
+           sizeof (struct en_header), (int)btop(ENMTU)) == 0) { 
                printf("es%d: can't initialize\n", unit);
                return;
        }
        addr = (struct endevice *)ui->ui_addr;
        addr->en_istat = addr->en_ostat = 0;
                printf("es%d: can't initialize\n", unit);
                return;
        }
        addr = (struct endevice *)ui->ui_addr;
        addr->en_istat = addr->en_ostat = 0;
-}
-
-enreset(uban)
-       int uban;
-{
-       register int unit;
-       struct uba_device *ui;
 
 
-COUNT(ENRESET);
-       for (unit = 0; unit < NEN; unit++) {
-               ui = eninfo[unit];
-               if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
-                       continue;
-               eninit(unit);
-               printf("es%d ", unit);
-       }
+       /*
+        * Hang pending read, start any writes.
+        */
+       s = splimp();
+       enstart(unit);
+       enxint(unit);
+       splx(s);
 }
 
 int    enlastdel = 25;
 
 }
 
 int    enlastdel = 25;
 
+/*
+ * Start or restart output on interface.
+ * If interface is already active, then this is a retransmit
+ * after a collision, and just restuff registers and delay.
+ * If interface is not already active, get another datagram
+ * to send off of the interface queue, and map it to the interface
+ * before starting the output.
+ */
 enstart(dev)
        dev_t dev;
 {
 enstart(dev)
        dev_t dev;
 {
@@ -123,7 +174,6 @@ enstart(dev)
        struct uba_device *ui;
        register struct endevice *addr;
        register struct en_softc *es;
        struct uba_device *ui;
        register struct endevice *addr;
        register struct en_softc *es;
-       register struct ifuba *ifu;
        struct mbuf *m;
        int dest;
 COUNT(ENSTART);
        struct mbuf *m;
        int dest;
 COUNT(ENSTART);
@@ -133,28 +183,49 @@ COUNT(ENSTART);
        es = &en_softc[unit];
        if (es->es_oactive)
                goto restart;
        es = &en_softc[unit];
        if (es->es_oactive)
                goto restart;
-       IF_DEQUEUE(&es->es_if->if_snd, m);
+
+       /*
+        * Not already active: dequeue another request
+        * and map it to the UNIBUS.  If no more requests,
+        * just return.
+        */
+       IF_DEQUEUE(&es->es_if.if_snd, m);
        if (m == 0) {
                es->es_oactive = 0;
                return;
        }
        if (m == 0) {
                es->es_oactive = 0;
                return;
        }
-       dest = mtod(m, struct en_header *)->en_dhost;
        es->es_olen = if_wubaput(&es->es_ifuba, m);
        es->es_olen = if_wubaput(&es->es_ifuba, m);
+
+       /*
+        * Ethernet cannot take back-to-back packets (no
+        * buffering in interface.  To avoid overrunning
+        * receiver, enforce a small delay (about 1ms) in interface
+        * on successive packets sent to same host.
+        */
+       dest = mtod(m, struct en_header *)->en_dhost;
        if (es->es_lastx && es->es_lastx == dest)
                es->es_delay = enlastdel;
        else
                es->es_lastx = dest;
        if (es->es_lastx && es->es_lastx == dest)
                es->es_delay = enlastdel;
        else
                es->es_lastx = dest;
+
 restart:
 restart:
-       ifu = es->es_ifuba;
-       UBAPURGE(ifu->ifu_uba, ifu->ifu_w.ifrw_bdp);
+       /*
+        * Have request mapped to UNIBUS for transmission.
+        * Purge any stale data from this BDP, and start the otput.
+        */
+       UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);
        addr = (struct endevice *)ui->ui_addr;
        addr = (struct endevice *)ui->ui_addr;
-       addr->en_oba = (int)ifu->ifu_w.ifrw_addr;
+       addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_addr;
        addr->en_odelay = es->es_delay;
        addr->en_owc = -((es->es_olen + 1) >> 1);
        addr->en_ostat = EN_IEN|EN_GO;
        es->es_oactive = 1;
 }
 
        addr->en_odelay = es->es_delay;
        addr->en_owc = -((es->es_olen + 1) >> 1);
        addr->en_ostat = EN_IEN|EN_GO;
        es->es_oactive = 1;
 }
 
+/*
+ * Ethernet interface transmitter interrupt.
+ * Start another output if more data to send.
+ */
 enxint(unit)
        int unit;
 {
 enxint(unit)
        int unit;
 {
@@ -174,13 +245,18 @@ COUNT(ENXINT);
        es->es_mask = ~0;
        if (addr->en_ostat&EN_OERROR)
                printf("es%d: output error\n", unit);
        es->es_mask = ~0;
        if (addr->en_ostat&EN_OERROR)
                printf("es%d: output error\n", unit);
-       if (es->es_if->if_snd.ifq_head == 0) {
+       if (es->es_if.if_snd.ifq_head == 0) {
                es->es_lastx = 0;
                return;
        }
        enstart(unit);
 }
 
                es->es_lastx = 0;
                return;
        }
        enstart(unit);
 }
 
+/*
+ * Collision on ethernet interface.  Do exponential
+ * backoff, and retransmit.  If have backed off all
+ * the way printing warning diagnostic, and drop packet.
+ */
 encollide(unit)
        int unit;
 {
 encollide(unit)
        int unit;
 {
@@ -188,7 +264,7 @@ encollide(unit)
 COUNT(ENCOLLIDE);
 
        es = &en_softc[unit];
 COUNT(ENCOLLIDE);
 
        es = &en_softc[unit];
-       es->es_if->if_collisions++;
+       es->es_if.if_collisions++;
        if (es->es_oactive == 0)
                return;
        if (es->es_mask == 0) {
        if (es->es_oactive == 0)
                return;
        if (es->es_mask == 0) {
@@ -201,12 +277,20 @@ COUNT(ENCOLLIDE);
        }
 }
 
        }
 }
 
+/*
+ * Ethernet interface receiver interrupt.
+ * If input error just drop packet.
+ * Otherwise purge input buffered data path and examine 
+ * packet to determine type.  If can't determine length
+ * from type, then have to drop packet.  Othewise decapsulate
+ * packet based on type and pass to type specific higher-level
+ * input routine.
+ */
 enrint(unit)
        int unit;
 {
        struct endevice *addr;
        register struct en_softc *es;
 enrint(unit)
        int unit;
 {
        struct endevice *addr;
        register struct en_softc *es;
-       register struct ifuba *ifu;
        struct en_header *en;
        struct mbuf *m;
        struct ifqueue *inq;
        struct en_header *en;
        struct mbuf *m;
        struct ifqueue *inq;
@@ -214,15 +298,26 @@ enrint(unit)
        int off;
 COUNT(ENRINT);
 
        int off;
 COUNT(ENRINT);
 
+       es = &en_softc[unit];
        addr = (struct endevice *)eninfo[unit]->ui_addr;
        addr = (struct endevice *)eninfo[unit]->ui_addr;
+
+       /*
+        * Purge BDP; drop error packets.
+        */
+       UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp);
        if (addr->en_istat&EN_IERROR) {
        if (addr->en_istat&EN_IERROR) {
-               es->es_if->if_ierrors++;
+               es->es_if.if_ierrors++;
                printf("es%d: input error\n", unit);
                goto setup;
        }
                printf("es%d: input error\n", unit);
                goto setup;
        }
-       ifu = en_softc[unit].es_ifuba;
-       UBAPURGE(ifu->ifu_uba, ifu->ifu_r.ifrw_bdp);
-       en = (struct en_header *)(ifu->ifu_r.ifrw_addr);
+
+       /*
+        * Get pointer to ethernet header (in input buffer).
+        * Deal with trailer protocol: if type is PUP trailer
+        * get true type from first 16-bit word past data.
+        * Remember that type was trailer by setting off.
+        */
+       en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr);
 #define        endataaddr(en, off, type)       ((type)(((caddr_t)((en)+1)+(off))))
        if (en->en_type >= ENPUP_TRAIL &&
            en->en_type < ENPUP_TRAIL+ENPUP_NTRAILER) {
 #define        endataaddr(en, off, type)       ((type)(((caddr_t)((en)+1)+(off))))
        if (en->en_type >= ENPUP_TRAIL &&
            en->en_type < ENPUP_TRAIL+ENPUP_NTRAILER) {
@@ -231,6 +326,11 @@ COUNT(ENRINT);
                off += 2;
        } else
                off = 0;
                off += 2;
        } else
                off = 0;
+
+       /*
+        * Attempt to infer packet length from type;
+        * can't deal with packet if can't infer length.
+        */
        switch (en->en_type) {
 
 #ifdef INET
        switch (en->en_type) {
 
 #ifdef INET
@@ -247,10 +347,26 @@ COUNT(ENRINT);
        }
        if (len == 0)
                goto setup;
        }
        if (len == 0)
                goto setup;
-       m = if_rubaget(&ifu->ifu_r, len, off);
+
+       /*
+        * Pull packet off interface.  Off is nonzero if packet
+        * has trailing header; if_rubaget will then force this header
+        * information to be at the front, but we still have to drop
+        * the two-byte type which is at the front of the trailer data
+        * (which we ``consumed'' above).
+        */
+       m = if_rubaget(&es->es_ifuba, len, off);
+       if (off) {
+               m->m_off += 2;
+               m->m_len -= 2;
+       }
        IF_ENQUEUE(inq, m);
        IF_ENQUEUE(inq, m);
+
 setup:
 setup:
-       addr->en_iba = es->es_ifuba->ifu_r.ifrw_info;
+       /*
+        * Reset for next packet.
+        */
+       addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
        addr->en_iwc = -(sizeof (struct en_header) + ENMTU) >> 1;
        addr->en_istat = EN_IEN|EN_GO;
 }
        addr->en_iwc = -(sizeof (struct en_header) + ENMTU) >> 1;
        addr->en_istat = EN_IEN|EN_GO;
 }
@@ -258,6 +374,8 @@ setup:
 /*
  * Ethernet output routine.
  * Encapsulate a packet of type family for the local net.
 /*
  * Ethernet output routine.
  * Encapsulate a packet of type family for the local net.
+ * Use trailer local net encapsulation if enough data in first
+ * packet leaves a multiple of 512 bytes of data in remainder.
  */
 enoutput(ifp, m0, pf)
        struct ifnet *ifp;
  */
 enoutput(ifp, m0, pf)
        struct ifnet *ifp;
@@ -265,7 +383,7 @@ enoutput(ifp, m0, pf)
        int pf;
 {
        int type, dest;
        int pf;
 {
        int type, dest;
-       register struct mbuf *m;
+       register struct mbuf *m = m0;
        register struct en_header *en;
        int s;
 
        register struct en_header *en;
        int s;
 
@@ -276,19 +394,19 @@ enoutput(ifp, m0, pf)
                register struct ip *ip = mtod(m0, struct ip *);
                int off;
 
                register struct ip *ip = mtod(m0, struct ip *);
                int off;
 
-               off = ip->ip_len - (ip->ip_hl << 2);
-               if (off && off % 512 == 0 && m0->m_off >= MMINOFF + 2) {
+               dest = ip->ip_dst.s_addr >> 24;
+               off = ip->ip_len - m->m_len;
+               if (off && off % 512 == 0 && m->m_off >= MMINOFF + 2) {
                        type = ENPUP_TRAIL + (off>>9);
                        type = ENPUP_TRAIL + (off>>9);
-                       m0->m_off -= 2;
-                       m0->m_len += 2;
-                       *mtod(m0, u_short *) = ENPUP_IPTYPE;
-               } else {
-                       type = ENPUP_IPTYPE;
-                       off = 0;
+                       m->m_off -= 2;
+                       m->m_len += 2;
+                       *mtod(m, u_short *) = ENPUP_IPTYPE;
+                       goto gottrailertype;
                }
                }
-               dest = ip->ip_dst.s_addr >> 24;
+               type = ENPUP_IPTYPE;
+               off = 0;
+               goto gottype;
                }
                }
-               break;
 #endif
 
        default:
 #endif
 
        default:
@@ -296,7 +414,25 @@ enoutput(ifp, m0, pf)
                m_freem(m0);
                return (0);
        }
                m_freem(m0);
                return (0);
        }
-       if (MMINOFF + sizeof (struct en_header) > m0->m_off) {
+
+       /*
+        * Packet to be sent as trailer: move first packet
+        * (control information) to end of chain.
+        */
+gottrailertype:
+       while (m->m_next)
+               m = m->m_next;
+       m->m_next = m0;
+       m = m0->m_next;
+       m0->m_next = 0;
+
+       /*
+        * Add local net header.  If no space in first mbuf,
+        * allocate another.
+        */
+gottype:
+       m0 = m;
+       if (MMINOFF + sizeof (struct en_header) > m->m_off) {
                m = m_get(0);
                if (m == 0) {
                        m_freem(m0);
                m = m_get(0);
                if (m == 0) {
                        m_freem(m0);
@@ -314,9 +450,15 @@ enoutput(ifp, m0, pf)
        en->en_shost = ifp->if_host[0];
        en->en_dhost = dest;
        en->en_type = type;
        en->en_shost = ifp->if_host[0];
        en->en_dhost = dest;
        en->en_type = type;
+
+       /*
+        * Queue message on interface, and start output if interface
+        * not yet active.
+        */
        s = splimp();
        IF_ENQUEUE(&ifp->if_snd, m);
        splx(s);
        if (en_softc[ifp->if_unit].es_oactive == 0)
                enstart(ifp->if_unit);
        s = splimp();
        IF_ENQUEUE(&ifp->if_snd, m);
        splx(s);
        if (en_softc[ifp->if_unit].es_oactive == 0)
                enstart(ifp->if_unit);
+       return (1);
 }
 }
index 5d99b97..d08870f 100644 (file)
@@ -1,4 +1,4 @@
-/*     if_uba.c        4.2     81/11/26        */
+/*     if_uba.c        4.3     81/11/29        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -85,46 +85,38 @@ COUNT(IF_UBAALLOC);
 }
 
 /*
 }
 
 /*
- * Pull read data off a interface, given length.
- * Map the header into a mbuf, and then copy or
- * remap the data into a chain of mbufs.
- * Return 0 if there is no space, or a pointer
- * to the assembled mbuf chain.
+ * Pull read data off a interface.
+ * Len is length of data, with local net header stripped.
+ * Off is non-zero if a trailer protocol was used, and
+ * gives the offset of the trailer information.
+ * We copy the trailer information and then all the normal
+ * data into mbufs.  When full cluster sized units are present
+ * on the interface on cluster boundaries we can get them more
+ * easily by remapping, and take advantage of this here.
  */
 struct mbuf *
  */
 struct mbuf *
-if_rubaget(ifu, len)
+if_rubaget(ifu, totlen, off0)
        register struct ifuba *ifu;
        register struct ifuba *ifu;
-       int len;
+       int totlen, off0;
 {
        register struct mbuf *m;
        register caddr_t cp;
 {
        register struct mbuf *m;
        register caddr_t cp;
-       struct mbuf *mp, *p, *top;
+       struct mbuf **mp, *p, *top;
+       int len, off = off0;
 
 COUNT(IF_RUBAGET);
 
 COUNT(IF_RUBAGET);
-       /*
-        * First pull local net header off into a mbuf.
-        */
-       MGET(m, 0);
-       if (m == 0)
-               return (0);
-       m->m_off = MMINOFF;
-       m->m_len = ifu->ifu_hlen;
-       top = m;
-       cp = ifu->ifu_r.ifrw_addr;
-       bcopy(cp, mtod(m, caddr_t), ifu->ifu_hlen);
-       len -= ifu->ifu_hlen;
-       cp += ifu->ifu_hlen;
 
 
-       /*
-        * Now pull data off.  If whole pages
-        * are there, pull into pages if possible,
-        * otherwise copy small blocks into mbufs.
-        */
-       mp = m;
-       while (len > 0) {
+       top = 0;
+       mp = &top;
+       while (totlen > 0) {
                MGET(m, 0);
                if (m == 0)
                        goto bad;
                MGET(m, 0);
                if (m == 0)
                        goto bad;
+               if (off) {
+                       len = totlen - off;
+                       cp = ifu->ifu_r.ifrw_addr + ifu->ifu_hlen + off;
+               } else
+                       len = totlen;
                if (len >= CLSIZE) {
                        struct pte *cpte, *ppte;
                        int i, x, *ip;
                if (len >= CLSIZE) {
                        struct pte *cpte, *ppte;
                        int i, x, *ip;
@@ -181,9 +173,16 @@ copy:
                bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);
                cp += m->m_len;
 nocopy:
                bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);
                cp += m->m_len;
 nocopy:
-               len -= m->m_len;
-               mp->m_next = m;
-               mp = m;
+               *mp = m;
+               mp = &m->m_next;
+               if (off) {
+                       off += m->m_len;
+                       if (off == totlen) {
+                               cp = ifu->ifu_r.ifrw_addr + ifu->ifu_hlen;
+                               off = 0;
+                               totlen -= off0;
+                       }
+               }
        }
        return (top);
 bad:
        }
        return (top);
 bad:
@@ -239,4 +238,5 @@ COUNT(IF_WUBAPUT);
                                i++;
                        }
                }
                                i++;
                        }
                }
+       return (cp - ifu->ifu_w.ifrw_addr);
 }
 }