summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_input.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-12-14 06:51:12 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-12-14 06:51:12 +0000
commit4999ff4b43ac2d7fd722821f43575a2d6e6d8798 (patch)
treea59013a98998bd12d51ac3c8c38d676f02b6a99d /sys/netinet/ip_input.c
parenta2d742ba04b0e50a993d51980923004ca0f3efde (diff)
from netbsd:
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.
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r--sys/netinet/ip_input.c235
1 files changed, 97 insertions, 138 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 100f1865298..f7457607ee8 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -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,45 +567,19 @@ 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
* queue, discard it.
@@ -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);
}