from netbsd:
authorderaadt <deraadt@openbsd.org>
Thu, 14 Dec 1995 06:50:40 +0000 (06:50 +0000)
committerderaadt <deraadt@openbsd.org>
Thu, 14 Dec 1995 06:50:40 +0000 (06:50 +0000)
make netinet work on systems where pointers and longs are 64 bits
(like the alpha).  Biggest problem: IP headers were overlayed with
structure which included pointers, and which therefore didn't overlay
properly on 64-bit machines.  Solution: instead of threading pointers
through IP header overlays, add a "queue element" structure to do
the threading, and point it at the ip headers.

sys/netinet/ip_input.c
sys/netinet/ip_var.h
sys/netinet/raw_ip.c
sys/netinet/tcp_input.c
sys/netinet/tcp_subr.c
sys/netinet/tcp_var.h
sys/netinet/tcpip.h
sys/netinet/udp_usrreq.c
sys/netinet/udp_var.h
sys/netiso/tuba_subr.c
sys/netiso/tuba_table.c

index 100f186..f745760 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_input.c,v 1.24 1995/08/12 23:59:36 mycroft Exp $    */
+/*     $NetBSD: ip_input.c,v 1.25 1995/11/21 01:07:34 cgd Exp $        */
 
 /*
  * Copyright (c) 1982, 1986, 1988, 1993
@@ -45,7 +45,6 @@
 #include <sys/errno.h>
 #include <sys/time.h>
 #include <sys/kernel.h>
-#include <sys/syslog.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -70,7 +69,6 @@
 #endif
 int    ipforwarding = IPFORWARDING;
 int    ipsendredirects = IPSENDREDIRECTS;
-int    ip_dosourceroute = 0;   /* no source routing unless sysctl'd to enable */
 int    ip_defttl = IPDEFTTL;
 #ifdef DIAGNOSTIC
 int    ipprintfs = 0;
@@ -83,18 +81,6 @@ int  ipqmaxlen = IFQ_MAXLEN;
 struct in_ifaddrhead in_ifaddr;
 struct ifqueue ipintrq;
 
-char *
-inet_ntoa(ina)
-       struct in_addr ina;
-{
-       static char buf[4*sizeof "123"];
-       unsigned char *ucp = (unsigned char *)&ina;
-
-       sprintf(buf, "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff,
-           ucp[2] & 0xff, ucp[3] & 0xff);
-       return (buf);
-}
-
 /*
  * We need to save the IP options in case a protocol wants to respond
  * to an incoming packet over the same route if the packet got here
@@ -131,7 +117,7 @@ ip_init()
                if (pr->pr_domain->dom_family == PF_INET &&
                    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
                        ip_protox[pr->pr_protocol] = pr - inetsw;
-       ipq.next = ipq.prev = &ipq;
+       LIST_INIT(&ipq);
        ip_id = time.tv_sec & 0xffff;
        ipintrq.ifq_maxlen = ipqmaxlen;
        TAILQ_INIT(&in_ifaddr);
@@ -151,7 +137,8 @@ ipintr()
        register struct mbuf *m;
        register struct ipq *fp;
        register struct in_ifaddr *ia;
-       int hlen, s;
+       struct ipqent *ipqe;
+       int hlen, mff, s;
 
 next:
        /*
@@ -352,7 +339,7 @@ ours:
                 * Look for queue of fragments
                 * of this datagram.
                 */
-               for (fp = ipq.next; fp != &ipq; fp = fp->next)
+               for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next)
                        if (ip->ip_id == fp->ipq_id &&
                            ip->ip_src.s_addr == fp->ipq_src.s_addr &&
                            ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
@@ -363,21 +350,20 @@ found:
 
                /*
                 * Adjust ip_len to not reflect header,
-                * set ip_mff if more fragments are expected,
+                * set ipqe_mff if more fragments are expected,
                 * convert offset of this to bytes.
                 */
                ip->ip_len -= hlen;
-               ((struct ipasfrag *)ip)->ipf_mff &= ~1;
-               if (ip->ip_off & IP_MF) {
-                       /*
-                        * Make sure that fragments have a data length
+               mff = (ip->ip_off & IP_MF) != 0;
+               if (mff) {
+                       /*
+                        * Make sure that fragments have a data length
                         * that's a non-zero multiple of 8 bytes.
-                        */
+                        */
                        if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) {
                                ipstat.ips_badfrags++;
                                goto bad;
                        }
-                       ((struct ipasfrag *)ip)->ipf_mff |= 1;
                }
                ip->ip_off <<= 3;
 
@@ -386,9 +372,17 @@ found:
                 * or if this is not the first fragment,
                 * attempt reassembly; if it succeeds, proceed.
                 */
-               if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
+               if (mff || ip->ip_off) {
                        ipstat.ips_fragments++;
-                       ip = ip_reass((struct ipasfrag *)ip, fp);
+                       MALLOC(ipqe, struct ipqent *, sizeof (struct ipqent),
+                           M_IPQ, M_NOWAIT);
+                       if (ipqe == NULL) {
+                               ipstat.ips_rcvmemdrop++;
+                               goto bad;
+                       }
+                       ipqe->ipqe_mff = mff;
+                       ipqe->ipqe_ip = ip;
+                       ip = ip_reass(ipqe, fp);
                        if (ip == 0)
                                goto next;
                        ipstat.ips_reassembled++;
@@ -417,14 +411,15 @@ bad:
  * is given as fp; otherwise have to make a chain.
  */
 struct ip *
-ip_reass(ip, fp)
-       register struct ipasfrag *ip;
+ip_reass(ipqe, fp)
+       register struct ipqent *ipqe;
        register struct ipq *fp;
 {
-       register struct mbuf *m = dtom(ip);
-       register struct ipasfrag *q;
+       register struct mbuf *m = dtom(ipqe->ipqe_ip);
+       register struct ipqent *nq, *p, *q;
+       struct ip *ip;
        struct mbuf *t;
-       int hlen = ip->ip_hl << 2;
+       int hlen = ipqe->ipqe_ip->ip_hl << 2;
        int i, next;
 
        /*
@@ -441,22 +436,23 @@ ip_reass(ip, fp)
                if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
                        goto dropfrag;
                fp = mtod(t, struct ipq *);
-               insque(fp, &ipq);
+               LIST_INSERT_HEAD(&ipq, fp, ipq_q);
                fp->ipq_ttl = IPFRAGTTL;
-               fp->ipq_p = ip->ip_p;
-               fp->ipq_id = ip->ip_id;
-               fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp;
-               fp->ipq_src = ((struct ip *)ip)->ip_src;
-               fp->ipq_dst = ((struct ip *)ip)->ip_dst;
-               q = (struct ipasfrag *)fp;
+               fp->ipq_p = ipqe->ipqe_ip->ip_p;
+               fp->ipq_id = ipqe->ipqe_ip->ip_id;
+               LIST_INIT(&fp->ipq_fragq);
+               fp->ipq_src = ipqe->ipqe_ip->ip_src;
+               fp->ipq_dst = ipqe->ipqe_ip->ip_dst;
+               p = NULL;
                goto insert;
        }
 
        /*
         * Find a segment which begins after this one does.
         */
-       for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next)
-               if (q->ip_off > ip->ip_off)
+       for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL;
+           p = q, q = q->ipqe_q.le_next)
+               if (q->ipqe_ip->ip_off > ipqe->ipqe_ip->ip_off)
                        break;
 
        /*
@@ -464,14 +460,15 @@ ip_reass(ip, fp)
         * our data already.  If so, drop the data from the incoming
         * segment.  If it provides all of our data, drop us.
         */
-       if (q->ipf_prev != (struct ipasfrag *)fp) {
-               i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off;
+       if (p != NULL) {
+               i = p->ipqe_ip->ip_off + p->ipqe_ip->ip_len -
+                   ipqe->ipqe_ip->ip_off;
                if (i > 0) {
-                       if (i >= ip->ip_len)
+                       if (i >= ipqe->ipqe_ip->ip_len)
                                goto dropfrag;
-                       m_adj(dtom(ip), i);
-                       ip->ip_off += i;
-                       ip->ip_len -= i;
+                       m_adj(dtom(ipqe->ipqe_ip), i);
+                       ipqe->ipqe_ip->ip_off += i;
+                       ipqe->ipqe_ip->ip_len -= i;
                }
        }
 
@@ -479,17 +476,20 @@ ip_reass(ip, fp)
         * While we overlap succeeding segments trim them or,
         * if they are completely covered, dequeue them.
         */
-       while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
-               i = (ip->ip_off + ip->ip_len) - q->ip_off;
-               if (i < q->ip_len) {
-                       q->ip_len -= i;
-                       q->ip_off += i;
-                       m_adj(dtom(q), i);
+       for (; q != NULL && ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len >
+           q->ipqe_ip->ip_off; q = nq) {
+               i = (ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len) -
+                   q->ipqe_ip->ip_off;
+               if (i < q->ipqe_ip->ip_len) {
+                       q->ipqe_ip->ip_len -= i;
+                       q->ipqe_ip->ip_off += i;
+                       m_adj(dtom(q->ipqe_ip), i);
                        break;
                }
-               q = q->ipf_next;
-               m_freem(dtom(q->ipf_prev));
-               ip_deq(q->ipf_prev);
+               nq = q->ipqe_q.le_next;
+               m_freem(dtom(q->ipqe_ip));
+               LIST_REMOVE(q, ipqe_q);
+               FREE(q, M_IPQ);
        }
 
 insert:
@@ -497,28 +497,36 @@ insert:
         * Stick new segment in its place;
         * check for complete reassembly.
         */
-       ip_enq(ip, q->ipf_prev);
+       if (p == NULL) {
+               LIST_INSERT_HEAD(&fp->ipq_fragq, ipqe, ipqe_q);
+       } else {
+               LIST_INSERT_AFTER(p, ipqe, ipqe_q);
+       }
        next = 0;
-       for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) {
-               if (q->ip_off != next)
+       for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL;
+           p = q, q = q->ipqe_q.le_next) {
+               if (q->ipqe_ip->ip_off != next)
                        return (0);
-               next += q->ip_len;
+               next += q->ipqe_ip->ip_len;
        }
-       if (q->ipf_prev->ipf_mff & 1)
+       if (p->ipqe_mff)
                return (0);
 
        /*
         * Reassembly is complete; concatenate fragments.
         */
-       q = fp->ipq_next;
-       m = dtom(q);
+       q = fp->ipq_fragq.lh_first;
+       ip = q->ipqe_ip;
+       m = dtom(q->ipqe_ip);
        t = m->m_next;
        m->m_next = 0;
        m_cat(m, t);
-       q = q->ipf_next;
-       while (q != (struct ipasfrag *)fp) {
-               t = dtom(q);
-               q = q->ipf_next;
+       nq = q->ipqe_q.le_next;
+       FREE(q, M_IPQ);
+       for (q = nq; q != NULL; q = nq) {
+               t = dtom(q->ipqe_ip);
+               nq = q->ipqe_q.le_next;
+               FREE(q, M_IPQ);
                m_cat(m, t);
        }
 
@@ -528,14 +536,11 @@ insert:
         * dequeue and discard fragment reassembly header.
         * Make header visible.
         */
-       ip = fp->ipq_next;
        ip->ip_len = next;
-       ip->ipf_mff &= ~1;
-       ((struct ip *)ip)->ip_src = fp->ipq_src;
-       ((struct ip *)ip)->ip_dst = fp->ipq_dst;
-       remque(fp);
+       ip->ip_src = fp->ipq_src;
+       ip->ip_dst = fp->ipq_dst;
+       LIST_REMOVE(fp, ipq_q);
        (void) m_free(dtom(fp));
-       m = dtom(ip);
        m->m_len += (ip->ip_hl << 2);
        m->m_data -= (ip->ip_hl << 2);
        /* some debugging cruft by sklower, below, will go away soon */
@@ -545,11 +550,12 @@ insert:
                        plen += m->m_len;
                t->m_pkthdr.len = plen;
        }
-       return ((struct ip *)ip);
+       return (ip);
 
 dropfrag:
        ipstat.ips_fragdropped++;
        m_freem(m);
+       FREE(ipqe, M_IPQ);
        return (0);
 }
 
@@ -561,44 +567,18 @@ void
 ip_freef(fp)
        struct ipq *fp;
 {
-       register struct ipasfrag *q, *p;
+       register struct ipqent *q, *p;
 
-       for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) {
-               p = q->ipf_next;
-               ip_deq(q);
-               m_freem(dtom(q));
+       for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) {
+               p = q->ipqe_q.le_next;
+               m_freem(dtom(q->ipqe_ip));
+               LIST_REMOVE(q, ipqe_q);
+               FREE(q, M_IPQ);
        }
-       remque(fp);
+       LIST_REMOVE(fp, ipq_q);
        (void) m_free(dtom(fp));
 }
 
-/*
- * Put an ip fragment on a reassembly chain.
- * Like insque, but pointers in middle of structure.
- */
-void
-ip_enq(p, prev)
-       register struct ipasfrag *p, *prev;
-{
-
-       p->ipf_prev = prev;
-       p->ipf_next = prev->ipf_next;
-       prev->ipf_next->ipf_prev = p;
-       prev->ipf_next = p;
-}
-
-/*
- * To ip_enq as remque is to insque.
- */
-void
-ip_deq(p)
-       register struct ipasfrag *p;
-{
-
-       p->ipf_prev->ipf_next = p->ipf_next;
-       p->ipf_next->ipf_prev = p->ipf_prev;
-}
-
 /*
  * IP timer processing;
  * if a timer expires on a reassembly
@@ -607,20 +587,14 @@ ip_deq(p)
 void
 ip_slowtimo()
 {
-       register struct ipq *fp;
+       register struct ipq *fp, *nfp;
        int s = splsoftnet();
 
-       fp = ipq.next;
-       if (fp == 0) {
-               splx(s);
-               return;
-       }
-       while (fp != &ipq) {
-               --fp->ipq_ttl;
-               fp = fp->next;
-               if (fp->prev->ipq_ttl == 0) {
+       for (fp = ipq.lh_first; fp != NULL; fp = nfp) {
+               nfp = fp->ipq_q.le_next;
+               if (--fp->ipq_ttl == 0) {
                        ipstat.ips_fragtimeout++;
-                       ip_freef(fp->prev);
+                       ip_freef(fp);
                }
        }
        splx(s);
@@ -633,9 +607,9 @@ void
 ip_drain()
 {
 
-       while (ipq.next != &ipq) {
+       while (ipq.lh_first != NULL) {
                ipstat.ips_fragdropped++;
-               ip_freef(ipq.next);
+               ip_freef(ipq.lh_first);
        }
 }
 
@@ -716,19 +690,6 @@ ip_dooptions(m)
                                save_rte(cp, ip->ip_src);
                                break;
                        }
-
-                       if (!ip_dosourceroute) {
-                               char buf[4*sizeof "123"];
-
-                               strcpy(buf, inet_ntoa(ip->ip_dst));
-                               log(LOG_WARNING,
-                                   "attempted source route from %s to %s\n",
-                                   inet_ntoa(ip->ip_src), buf);
-                               type = ICMP_UNREACH;
-                               code = ICMP_UNREACH_SRCFAIL;
-                               goto bad;
-                       }
-
                        /*
                         * locate outgoing interface
                         */
@@ -1032,8 +993,8 @@ ip_forward(m, srcrt)
        dest = 0;
 #ifdef DIAGNOSTIC
        if (ipprintfs)
-               printf("forward: src %lx dst %x ttl %x\n", ip->ip_src.s_addr,
-                       ip->ip_dst.s_addr, ip->ip_ttl);
+               printf("forward: src %x dst %x ttl %x\n", ip->ip_src,
+                       ip->ip_dst, ip->ip_ttl);
 #endif
        if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
                ipstat.ips_cantforward++;
@@ -1096,7 +1057,7 @@ ip_forward(m, srcrt)
                    code = ICMP_REDIRECT_HOST;
 #ifdef DIAGNOSTIC
                    if (ipprintfs)
-                       printf("redirect (%d) to %lx\n", code, (u_int32_t)dest);
+                       printf("redirect (%d) to %lx\n", code, (u_int32_t)dest);
 #endif
                }
        }
@@ -1178,8 +1139,6 @@ ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
        case IPCTL_DEFMTU:
                return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
 #endif
-       case IPCTL_SOURCEROUTE:
-               return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_dosourceroute));
        default:
                return (EOPNOTSUPP);
        }
index 58707e8..c78365d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_var.h,v 1.14 1995/06/12 00:47:47 mycroft Exp $      */
+/*     $NetBSD: ip_var.h,v 1.15 1995/11/21 01:07:38 cgd Exp $  */
 
 /*
  * Copyright (c) 1982, 1986, 1993
  *     @(#)ip_var.h    8.1 (Berkeley) 6/10/93
  */
 
+#include <sys/queue.h>
+
 /*
  * Overlay for ip header used by other protocols (tcp, udp).
  */
 struct ipovly {
-       caddr_t  ih_next, ih_prev;      /* for protocol sequence q's */
-       u_int8_t ih_x1;                 /* (unused) */
+       u_int8_t ih_x1[9];              /* (unused) */
        u_int8_t ih_pr;                 /* protocol */
        int16_t  ih_len;                /* protocol length */
        struct   in_addr ih_src;        /* source internet address */
        struct   in_addr ih_dst;        /* destination internet address */
 };
 
+/*
+ * Ip (reassembly or sequence) queue structures.
+ *
+ * XXX -- The following explains why the ipqe_m field is here, for TCP's use:
+ * We want to avoid doing m_pullup on incoming packets but that
+ * means avoiding dtom on the tcp reassembly code.  That in turn means
+ * keeping an mbuf pointer in the reassembly queue (since we might
+ * have a cluster).  As a quick hack, the source & destination
+ * port numbers (which are no longer needed once we've located the
+ * tcpcb) are overlayed with an mbuf pointer.
+ */
+LIST_HEAD(ipqehead, ipqent);
+struct ipqent {
+       LIST_ENTRY(ipqent) ipqe_q;
+       union {
+               struct ip       *_ip;
+               struct tcpiphdr *_tcp;
+       } _ipqe_u1;
+       union {
+               u_int8_t        _mff;   /* for IP fragmentation */
+               struct mbuf     *_m;    /* XXX for TCP; see above */
+       } _ipqe_u2;
+};
+#define        ipqe_ip         _ipqe_u1._ip
+#define        ipqe_tcp        _ipqe_u1._tcp
+#define        ipqe_mff        _ipqe_u2._mff
+#define        ipqe_m          _ipqe_u2._m
+
 /*
  * Ip reassembly queue structure.  Each fragment
  * being reassembled is attached to one of these structures.
@@ -54,42 +83,14 @@ struct ipovly {
  * be reclaimed if memory becomes tight.
  */
 struct ipq {
-       struct    ipq *next, *prev;     /* to other reass headers */
+       LIST_ENTRY(ipq) ipq_q;          /* to other reass headers */
        u_int8_t  ipq_ttl;              /* time for reass q to live */
        u_int8_t  ipq_p;                /* protocol of this fragment */
        u_int16_t ipq_id;               /* sequence id for reassembly */
-       struct    ipasfrag *ipq_next, *ipq_prev;
-                                       /* to ip headers of fragments */
+       struct    ipqehead ipq_fragq;   /* to ip fragment queue */
        struct    in_addr ipq_src, ipq_dst;
 };
 
-/*
- * Ip header, when holding a fragment.
- *
- * Note: ipf_next must be at same offset as ipq_next above
- */
-struct ipasfrag {
-#if BYTE_ORDER == LITTLE_ENDIAN
-       u_int8_t  ip_hl:4,
-                 ip_v:4;
-#endif
-#if BYTE_ORDER == BIG_ENDIAN
-       u_int8_t  ip_v:4,
-                 ip_hl:4;
-#endif
-       u_int8_t  ipf_mff;              /* XXX overlays ip_tos: use low bit
-                                        * to avoid destroying tos;
-                                        * copied from (ip_off&IP_MF) */
-       int16_t   ip_len;
-       u_int16_t ip_id;
-       int16_t   ip_off;
-       u_int8_t  ip_ttl;
-       u_int8_t  ip_p;
-       u_int16_t ip_sum;
-       struct    ipasfrag *ipf_next, *ipf_prev;
-                                       /* list of fragments */
-};
-
 /*
  * Structure stored in mbuf in inpcb.ip_options
  * and passed to ip_output when ip options are in use.
@@ -141,6 +142,7 @@ struct      ipstat {
        u_long  ips_badvers;            /* ip version != 4 */
        u_long  ips_rawout;             /* total raw ip packets generated */
        u_long  ips_badfrags;           /* malformed fragments (bad length) */
+       u_long  ips_rcvmemdrop;         /* frags dropped for lack of memory */
 };
 
 #ifdef _KERNEL
@@ -151,15 +153,13 @@ struct    ipstat {
 #define        IP_ALLOWBROADCAST       SO_BROADCAST    /* can send broadcast packets */
 
 struct   ipstat ipstat;
-struct   ipq    ipq;                   /* ip reass. queue */
-u_int16_t ip_id;                               /* ip packet ctr, for ids */
+LIST_HEAD(ipqhead, ipq)        ipq;            /* ip reass. queue */
+u_int16_t ip_id;                       /* ip packet ctr, for ids */
 int      ip_defttl;                    /* default IP ttl */
 
 int     ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
-void    ip_deq __P((struct ipasfrag *));
 int     ip_dooptions __P((struct mbuf *));
 void    ip_drain __P((void));
-void    ip_enq __P((struct ipasfrag *, struct ipasfrag *));
 void    ip_forward __P((struct mbuf *, int));
 void    ip_freef __P((struct ipq *));
 void    ip_freemoptions __P((struct ip_moptions *));
@@ -171,7 +171,7 @@ int  ip_output __P((struct mbuf *,
            struct mbuf *, struct route *, int, struct ip_moptions *));
 int     ip_pcbopts __P((struct mbuf **, struct mbuf *));
 struct ip *
-        ip_reass __P((struct ipasfrag *, struct ipq *));
+        ip_reass __P((struct ipqent *, struct ipq *));
 struct in_ifaddr *
         ip_rtaddr __P((struct in_addr));
 int     ip_setmoptions __P((int, struct ip_moptions **, struct mbuf *));
index 88fc13d..785e4b3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: raw_ip.c,v 1.21 1995/06/18 20:01:15 cgd Exp $  */
+/*     $NetBSD: raw_ip.c,v 1.22 1995/11/30 16:42:18 pk Exp $   */
 
 /*
  * Copyright (c) 1982, 1986, 1988, 1993
@@ -255,6 +255,15 @@ rip_usrreq(so, req, m, nam, control)
 #ifdef MROUTING
        extern struct socket *ip_mrouter;
 #endif
+       if (req == PRU_CONTROL)
+               return (in_control(so, (long)m, (caddr_t)nam,
+                       (struct ifnet *)control));
+
+       if (inp == NULL && req != PRU_ATTACH) {
+               error = EINVAL;
+               goto release;
+       }
+
        switch (req) {
 
        case PRU_ATTACH:
@@ -396,6 +405,7 @@ rip_usrreq(so, req, m, nam, control)
        default:
                panic("rip_usrreq");
        }
+release:
        if (m != NULL)
                m_freem(m);
        return (error);
index 8354c36..b49c0e9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_input.c,v 1.19 1995/08/04 01:12:23 mycroft Exp $   */
+/*     $NetBSD: tcp_input.c,v 1.20 1995/11/21 01:07:39 cgd Exp $       */
 
 /*
  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994
@@ -87,7 +87,7 @@ extern u_long sb_max;
  */
 #define        TCP_REASS(tp, ti, m, so, flags) { \
        if ((ti)->ti_seq == (tp)->rcv_nxt && \
-           (tp)->seg_next == (struct tcpiphdr *)(tp) && \
+           (tp)->segq.lh_first == NULL && \
            (tp)->t_state == TCPS_ESTABLISHED) { \
                if ((ti)->ti_flags & TH_PUSH) \
                        tp->t_flags |= TF_ACKNOW; \
@@ -112,7 +112,7 @@ tcp_reass(tp, ti, m)
        register struct tcpiphdr *ti;
        struct mbuf *m;
 {
-       register struct tcpiphdr *q;
+       register struct ipqent *p, *q, *nq, *tiqe;
        struct socket *so = tp->t_inpcb->inp_socket;
        int flags;
 
@@ -123,12 +123,23 @@ tcp_reass(tp, ti, m)
        if (ti == 0)
                goto present;
 
+       /*
+        * Allocate a new queue entry, before we throw away any data.
+        * If we can't, just drop the packet.  XXX
+        */
+       MALLOC(tiqe, struct ipqent *, sizeof (struct ipqent), M_IPQ, M_NOWAIT);
+       if (tiqe == NULL) {
+               tcpstat.tcps_rcvmemdrop++;
+               m_freem(m);
+               return (0);
+       }
+
        /*
         * Find a segment which begins after this one does.
         */
-       for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
-           q = (struct tcpiphdr *)q->ti_next)
-               if (SEQ_GT(q->ti_seq, ti->ti_seq))
+       for (p = NULL, q = tp->segq.lh_first; q != NULL;
+           p = q, q = q->ipqe_q.le_next)
+               if (SEQ_GT(q->ipqe_tcp->ti_seq, ti->ti_seq))
                        break;
 
        /*
@@ -136,52 +147,58 @@ tcp_reass(tp, ti, m)
         * our data already.  If so, drop the data from the incoming
         * segment.  If it provides all of our data, drop us.
         */
-       if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
+       if (p != NULL) {
+               register struct tcpiphdr *phdr = p->ipqe_tcp;
                register int i;
-               q = (struct tcpiphdr *)q->ti_prev;
+
                /* conversion to int (in i) handles seq wraparound */
-               i = q->ti_seq + q->ti_len - ti->ti_seq;
+               i = phdr->ti_seq + phdr->ti_len - ti->ti_seq;
                if (i > 0) {
                        if (i >= ti->ti_len) {
                                tcpstat.tcps_rcvduppack++;
                                tcpstat.tcps_rcvdupbyte += ti->ti_len;
                                m_freem(m);
+                               FREE(tiqe, M_IPQ);
                                return (0);
                        }
                        m_adj(m, i);
                        ti->ti_len -= i;
                        ti->ti_seq += i;
                }
-               q = (struct tcpiphdr *)(q->ti_next);
        }
        tcpstat.tcps_rcvoopack++;
        tcpstat.tcps_rcvoobyte += ti->ti_len;
-       REASS_MBUF(ti) = m;             /* XXX */
 
        /*
         * While we overlap succeeding segments trim them or,
         * if they are completely covered, dequeue them.
         */
-       while (q != (struct tcpiphdr *)tp) {
-               register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
+       for (; q != NULL; q = nq) {
+               register struct tcpiphdr *qhdr = q->ipqe_tcp;
+               register int i = (ti->ti_seq + ti->ti_len) - qhdr->ti_seq;
+
                if (i <= 0)
                        break;
-               if (i < q->ti_len) {
-                       q->ti_seq += i;
-                       q->ti_len -= i;
-                       m_adj(REASS_MBUF(q), i);
+               if (i < qhdr->ti_len) {
+                       qhdr->ti_seq += i;
+                       qhdr->ti_len -= i;
+                       m_adj(q->ipqe_m, i);
                        break;
                }
-               q = (struct tcpiphdr *)q->ti_next;
-               m = REASS_MBUF((struct tcpiphdr *)q->ti_prev);
-               remque(q->ti_prev);
-               m_freem(m);
+               nq = q->ipqe_q.le_next;
+               m_freem(q->ipqe_m);
+               LIST_REMOVE(q, ipqe_q);
+               FREE(q, M_IPQ);
        }
 
-       /*
-        * Stick new segment in its place.
-        */
-       insque(ti, q->ti_prev);
+       /* Insert the new fragment queue entry into place. */
+       tiqe->ipqe_m = m;
+       tiqe->ipqe_tcp = ti;
+       if (p == NULL) {
+               LIST_INSERT_HEAD(&tp->segq, tiqe, ipqe_q);
+       } else {
+               LIST_INSERT_AFTER(p, tiqe, ipqe_q);
+       }
 
 present:
        /*
@@ -190,22 +207,24 @@ present:
         */
        if (TCPS_HAVEESTABLISHED(tp->t_state) == 0)
                return (0);
-       ti = tp->seg_next;
-       if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
+       q = tp->segq.lh_first;
+       if (q == NULL || q->ipqe_tcp->ti_seq != tp->rcv_nxt)
                return (0);
-       if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)
+       if (tp->t_state == TCPS_SYN_RECEIVED && q->ipqe_tcp->ti_len)
                return (0);
        do {
-               tp->rcv_nxt += ti->ti_len;
-               flags = ti->ti_flags & TH_FIN;
-               remque(ti);
-               m = REASS_MBUF(ti);
-               ti = (struct tcpiphdr *)ti->ti_next;
+               tp->rcv_nxt += q->ipqe_tcp->ti_len;
+               flags = q->ipqe_tcp->ti_flags & TH_FIN;
+
+               nq = q->ipqe_q.le_next;
+               LIST_REMOVE(q, ipqe_q);
                if (so->so_state & SS_CANTRCVMORE)
-                       m_freem(m);
+                       m_freem(q->ipqe_m);
                else
-                       sbappend(&so->so_rcv, m);
-       } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
+                       sbappend(&so->so_rcv, q->ipqe_m);
+               FREE(q, M_IPQ);
+               q = nq;
+       } while (q != NULL && q->ipqe_tcp->ti_seq == tp->rcv_nxt);
        sorwakeup(so);
        return (flags);
 }
@@ -257,8 +276,7 @@ tcp_input(m, iphlen)
         */
        tlen = ((struct ip *)ti)->ip_len;
        len = sizeof (struct ip) + tlen;
-       ti->ti_next = ti->ti_prev = 0;
-       ti->ti_x1 = 0;
+       bzero(ti->ti_x1, sizeof ti->ti_x1);
        ti->ti_len = (u_int16_t)tlen;
        HTONS(ti->ti_len);
        if (ti->ti_sum = in_cksum(m, len)) {
@@ -479,7 +497,7 @@ findpcb:
                                return;
                        }
                } else if (ti->ti_ack == tp->snd_una &&
-                   tp->seg_next == (struct tcpiphdr *)tp &&
+                   tp->segq.lh_first == NULL &&
                    ti->ti_len <= sbspace(&so->so_rcv)) {
                        /*
                         * this is a pure, in-sequence data packet
index 76f8c9d..c64a868 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_subr.c,v 1.19 1995/06/12 06:48:54 mycroft Exp $    */
+/*     $NetBSD: tcp_subr.c,v 1.20 1995/11/21 01:07:41 cgd Exp $        */
 
 /*
  * Copyright (c) 1982, 1986, 1988, 1990, 1993
@@ -104,8 +104,7 @@ tcp_template(tp)
                m->m_len = sizeof (struct tcpiphdr);
                n = mtod(m, struct tcpiphdr *);
        }
-       n->ti_next = n->ti_prev = 0;
-       n->ti_x1 = 0;
+       bzero(n->ti_x1, sizeof n->ti_x1);
        n->ti_pr = IPPROTO_TCP;
        n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
        n->ti_src = inp->inp_laddr;
@@ -176,13 +175,12 @@ tcp_respond(tp, ti, m, ack, seq, flags)
                xchg(ti->ti_dport, ti->ti_sport, u_int16_t);
 #undef xchg
        }
-       ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
+       ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) + tlen));
        tlen += sizeof (struct tcpiphdr);
        m->m_len = tlen;
        m->m_pkthdr.len = tlen;
        m->m_pkthdr.rcvif = (struct ifnet *) 0;
-       ti->ti_next = ti->ti_prev = 0;
-       ti->ti_x1 = 0;
+       bzero(ti->ti_x1, sizeof ti->ti_x1);
        ti->ti_seq = htonl(seq);
        ti->ti_ack = htonl(ack);
        ti->ti_x2 = 0;
@@ -215,7 +213,7 @@ tcp_newtcpcb(inp)
        if (tp == NULL)
                return ((struct tcpcb *)0);
        bzero((char *) tp, sizeof(struct tcpcb));
-       tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
+       LIST_INIT(&tp->segq);
        tp->t_maxseg = tcp_mssdflt;
 
        tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
@@ -271,7 +269,7 @@ struct tcpcb *
 tcp_close(tp)
        register struct tcpcb *tp;
 {
-       register struct tcpiphdr *t;
+       register struct ipqent *qe;
        struct inpcb *inp = tp->t_inpcb;
        struct socket *so = inp->inp_socket;
        register struct mbuf *m;
@@ -346,12 +344,10 @@ tcp_close(tp)
        }
 #endif /* RTV_RTT */
        /* free the reassembly queue, if any */
-       t = tp->seg_next;
-       while (t != (struct tcpiphdr *)tp) {
-               t = (struct tcpiphdr *)t->ti_next;
-               m = REASS_MBUF((struct tcpiphdr *)t->ti_prev);
-               remque(t->ti_prev);
-               m_freem(m);
+       while ((qe = tp->segq.lh_first) != NULL) {
+               LIST_REMOVE(qe, ipqe_q);
+               m_freem(qe->ipqe_m);
+               FREE(qe, M_IPQ);
        }
        if (tp->t_template)
                (void) m_free(dtom(tp->t_template));
index c97afca..99ab071 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_var.h,v 1.14 1995/09/30 07:02:08 thorpej Exp $     */
+/*     $NetBSD: tcp_var.h,v 1.15 1995/11/21 01:07:43 cgd Exp $ */
 
 /*
  * Copyright (c) 1982, 1986, 1993, 1994
@@ -43,8 +43,7 @@
  * Tcp control block, one per tcp; fields:
  */
 struct tcpcb {
-       struct  tcpiphdr *seg_next, *seg_prev;
-                                       /* list of control blocks */
+       struct ipqehead segq;           /* sequencing queue */
        short   t_state;                /* state of this connection */
        short   t_timer[TCPT_NTIMERS];  /* tcp timers */
        short   t_rxtshift;             /* log(2) of rexmt exp. backoff */
@@ -163,16 +162,6 @@ struct tcpcb {
 #define        TCP_REXMTVAL(tp) \
        ((((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) >> 2)
 
-/* XXX
- * We want to avoid doing m_pullup on incoming packets but that
- * means avoiding dtom on the tcp reassembly code.  That in turn means
- * keeping an mbuf pointer in the reassembly queue (since we might
- * have a cluster).  As a quick hack, the source & destination
- * port numbers (which are no longer needed once we've located the
- * tcpcb) are overlayed with an mbuf pointer.
- */
-#define REASS_MBUF(ti) (*(struct mbuf **)&((ti)->ti_t))
-
 /*
  * TCP statistics.
  * Many of these should be kept per connection,
@@ -211,6 +200,7 @@ struct      tcpstat {
        u_long  tcps_rcvbyte;           /* bytes received in sequence */
        u_long  tcps_rcvbadsum;         /* packets received with ccksum errs */
        u_long  tcps_rcvbadoff;         /* packets received with bad offset */
+       u_long  tcps_rcvmemdrop;        /* packets dropped for lack of memory */
        u_long  tcps_rcvshort;          /* packets received too short */
        u_long  tcps_rcvduppack;        /* duplicate-only packets received */
        u_long  tcps_rcvdupbyte;        /* duplicate-only bytes received */
index 9fbfb26..ba09485 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcpip.h,v 1.5 1994/06/29 06:38:55 cgd Exp $    */
+/*     $NetBSD: tcpip.h,v 1.6 1995/11/21 01:07:44 cgd Exp $    */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -42,8 +42,6 @@ struct tcpiphdr {
        struct  ipovly ti_i;            /* overlaid ip structure */
        struct  tcphdr ti_t;            /* tcp header */
 };
-#define        ti_next         ti_i.ih_next
-#define        ti_prev         ti_i.ih_prev
 #define        ti_x1           ti_i.ih_x1
 #define        ti_pr           ti_i.ih_pr
 #define        ti_len          ti_i.ih_len
index 3742a68..b764735 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: udp_usrreq.c,v 1.24 1995/08/12 23:59:42 mycroft Exp $  */
+/*     $NetBSD: udp_usrreq.c,v 1.25 1995/11/21 01:07:46 cgd Exp $      */
 
 /*
  * Copyright (c) 1982, 1986, 1988, 1990, 1993
@@ -142,9 +142,8 @@ udp_input(m, iphlen)
         * Checksum extended UDP header and data.
         */
        if (udpcksum && uh->uh_sum) {
-               ((struct ipovly *)ip)->ih_next = 0;
-               ((struct ipovly *)ip)->ih_prev = 0;
-               ((struct ipovly *)ip)->ih_x1 = 0;
+               bzero(((struct ipovly *)ip)->ih_x1,
+                   sizeof ((struct ipovly *)ip)->ih_x1);
                ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
                if (uh->uh_sum = in_cksum(m, len + sizeof (struct ip))) {
                        udpstat.udps_badsum++;
@@ -437,8 +436,7 @@ udp_output(inp, m, addr, control)
         * and addresses and length put into network format.
         */
        ui = mtod(m, struct udpiphdr *);
-       ui->ui_next = ui->ui_prev = 0;
-       ui->ui_x1 = 0;
+       bzero(ui->ui_x1, sizeof ui->ui_x1);
        ui->ui_pr = IPPROTO_UDP;
        ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr));
        ui->ui_src = inp->inp_laddr;
index 6dadf4f..c58dbce 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: udp_var.h,v 1.9 1995/06/12 00:48:09 mycroft Exp $      */
+/*     $NetBSD: udp_var.h,v 1.10 1995/11/21 01:07:48 cgd Exp $ */
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -42,8 +42,6 @@ struct        udpiphdr {
        struct  ipovly ui_i;            /* overlaid ip structure */
        struct  udphdr ui_u;            /* udp header */
 };
-#define        ui_next         ui_i.ih_next
-#define        ui_prev         ui_i.ih_prev
 #define        ui_x1           ui_i.ih_x1
 #define        ui_pr           ui_i.ih_pr
 #define        ui_len          ui_i.ih_len
index 465af62..927fea3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tuba_subr.c,v 1.4 1995/06/13 07:58:24 mycroft Exp $    */
+/*     $NetBSD: tuba_subr.c,v 1.5 1995/11/21 01:07:54 cgd Exp $        */
 
 /*
  * Copyright (c) 1992, 1993
@@ -326,8 +326,8 @@ tuba_tcpinput(m, src, dst)
                ti->ti_src.s_addr = tuba_table[findex]->tc_sum;
        else
                ti->ti_src.s_addr = tuba_table[findex]->tc_ssum;
-       ti->ti_prev = ti->ti_next = 0;
-       ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP;
+       bzero(ti->ti_x1, sizeof ti->ti_x1);
+       ti->ti_pr = ISOPROTO_TCP;
        ti->ti_len = htons((u_short)tlen);
        if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) {
                tcpstat.tcps_rcvbadsum++;
index 1f87ef6..e9663a1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tuba_table.c,v 1.4 1995/08/12 23:59:53 mycroft Exp $   */
+/*     $NetBSD: tuba_table.c,v 1.5 1995/10/16 05:28:58 mycroft Exp $   */
 
 /*
  * Copyright (c) 1992, 1993
@@ -91,7 +91,7 @@ tuba_lookup(siso, wait)
        struct tuba_cache **new;
        int dupentry = 0, sum_a = 0, sum_b = 0, old_size, i;
 
-       if ((rn = rn_match((caddr_t)&siso->siso_addr, tuba_tree->rnh_treetop))
+       if ((rn = rn_match((caddr_t)&siso->siso_addr, tuba_tree))
             && ((rn->rn_flags & RNF_ROOT) == 0)) {
                tc = (struct tuba_cache *)rn;
                tc->tc_time = time.tv_sec;