diff options
| author | itojun <itojun@NetBSD.org> | 2002-08-14 00:23:27 +0000 |
|---|---|---|
| committer | itojun <itojun@NetBSD.org> | 2002-08-14 00:23:27 +0000 |
| commit | c00fa8dfd94473cd4d82faf337bc894fd05b1788 (patch) | |
| tree | aed1c45a959ac358e9e677f0a0eb639a23390106 /sys/netinet/ip_input.c | |
| parent | f5435ff1382d4883cd1fc56ae5cdd40fff8de1fd (diff) | |
avoid swapping endian of ip_len and ip_off on mbuf, to meet with M_LEADINGSPACE
optimization made last year. should solve PR 17867 and 10195.
IP_HDRINCL behavior of raw ip socket is kept unchanged. we may want to
provide IP_HDRINCL variant that does not swap endian.
Diffstat (limited to 'sys/netinet/ip_input.c')
| -rw-r--r-- | sys/netinet/ip_input.c | 76 |
1 files changed, 42 insertions, 34 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 3c7150446be..595079b346f 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.154 2002/06/30 22:40:34 thorpej Exp $ */ +/* $NetBSD: ip_input.c,v 1.155 2002/08/14 00:23:31 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -102,7 +102,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.154 2002/06/30 22:40:34 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.155 2002/08/14 00:23:31 itojun Exp $"); #include "opt_gateway.h" #include "opt_pfil_hooks.h" @@ -572,12 +572,6 @@ ip_input(struct mbuf *m) #endif /* - * Convert fields to host representation. - */ - NTOHS(ip->ip_len); - NTOHS(ip->ip_off); - - /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an * error was detected (causing an icmp message @@ -722,7 +716,15 @@ ours: * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) */ - if (ip->ip_off & ~(IP_DF|IP_RF)) { + if (ip->ip_off & ~htons(IP_DF|IP_RF)) { + if (M_READONLY(m)) { + if ((m = m_pullup(m, hlen)) == NULL) { + ipstat.ips_toosmall++; + goto bad; + } + ip = mtod(m, struct ip *); + } + /* * Look for queue of fragments * of this datagram. @@ -742,27 +744,28 @@ found: * set ipqe_mff if more fragments are expected, * convert offset of this to bytes. */ - ip->ip_len -= hlen; - mff = (ip->ip_off & IP_MF) != 0; + ip->ip_len = htons(ntohs(ip->ip_len) - hlen); + mff = (ip->ip_off & htons(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) { + if (ntohs(ip->ip_len) == 0 || + (ntohs(ip->ip_len) & 0x7) != 0) { ipstat.ips_badfrags++; IPQ_UNLOCK(); goto bad; } } - ip->ip_off <<= 3; + ip->ip_off = htons((ntohs(ip->ip_off) & IP_OFFMASK) << 3); /* * If datagram marked as having more fragments * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ - if (mff || ip->ip_off) { + if (mff || ip->ip_off != htons(0)) { ipstat.ips_fragments++; ipqe = pool_get(&ipqent_pool, PR_NOWAIT); if (ipqe == NULL) { @@ -781,7 +784,7 @@ found: ipstat.ips_reassembled++; ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; - ip->ip_len += hlen; + ip->ip_len = htons(ntohs(ip->ip_len) + hlen); } else if (fp) ip_freef(fp); @@ -806,7 +809,7 @@ found: */ #if IFA_STATS if (ia && ip) - ia->ia_ifa.ifa_data.ifad_inbytes += ip->ip_len; + ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len); #endif ipstat.ips_delivered++; { @@ -886,7 +889,7 @@ ip_reass(ipqe, fp) */ for (p = NULL, q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL; p = q, q = TAILQ_NEXT(q, ipqe_q)) - if (q->ipqe_ip->ip_off > ipqe->ipqe_ip->ip_off) + if (ntohs(q->ipqe_ip->ip_off) > ntohs(ipqe->ipqe_ip->ip_off)) break; /* @@ -895,14 +898,16 @@ ip_reass(ipqe, fp) * segment. If it provides all of our data, drop us. */ if (p != NULL) { - i = p->ipqe_ip->ip_off + p->ipqe_ip->ip_len - - ipqe->ipqe_ip->ip_off; + i = ntohs(p->ipqe_ip->ip_off) + ntohs(p->ipqe_ip->ip_len) - + ntohs(ipqe->ipqe_ip->ip_off); if (i > 0) { - if (i >= ipqe->ipqe_ip->ip_len) + if (i >= ntohs(ipqe->ipqe_ip->ip_len)) goto dropfrag; m_adj(ipqe->ipqe_m, i); - ipqe->ipqe_ip->ip_off += i; - ipqe->ipqe_ip->ip_len -= i; + ipqe->ipqe_ip->ip_off = + htons(ntohs(ipqe->ipqe_ip->ip_off) + i); + ipqe->ipqe_ip->ip_len = + htons(ntohs(ipqe->ipqe_ip->ip_len) - i); } } @@ -910,13 +915,16 @@ ip_reass(ipqe, fp) * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ - 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; + for (; q != NULL && + ntohs(ipqe->ipqe_ip->ip_off) + ntohs(ipqe->ipqe_ip->ip_len) > + ntohs(q->ipqe_ip->ip_off); q = nq) { + i = (ntohs(ipqe->ipqe_ip->ip_off) + + ntohs(ipqe->ipqe_ip->ip_len)) - ntohs(q->ipqe_ip->ip_off); + if (i < ntohs(q->ipqe_ip->ip_len)) { + q->ipqe_ip->ip_len = + htons(ntohs(q->ipqe_ip->ip_len) - i); + q->ipqe_ip->ip_off = + htons(ntohs(q->ipqe_ip->ip_off) + i); m_adj(q->ipqe_m, i); break; } @@ -939,9 +947,9 @@ insert: next = 0; for (p = NULL, q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL; p = q, q = TAILQ_NEXT(q, ipqe_q)) { - if (q->ipqe_ip->ip_off != next) + if (ntohs(q->ipqe_ip->ip_off) != next) return (0); - next += q->ipqe_ip->ip_len; + next += ntohs(q->ipqe_ip->ip_len); } if (p->ipqe_mff) return (0); @@ -976,7 +984,7 @@ insert: * dequeue and discard fragment reassembly header. * Make header visible. */ - ip->ip_len = next; + ip->ip_len = htons(next); ip->ip_src = fp->ipq_src; ip->ip_dst = fp->ipq_dst; LIST_REMOVE(fp, ipq_q); @@ -1459,7 +1467,7 @@ ip_stripoptions(m, mopt) m->m_len -= olen; if (m->m_flags & M_PKTHDR) m->m_pkthdr.len -= olen; - ip->ip_len -= olen; + ip->ip_len = htons(ntohs(ip->ip_len) - olen); ip->ip_hl = sizeof (struct ip) >> 2; } @@ -1549,7 +1557,7 @@ ip_forward(m, srcrt) * we need to generate an ICMP message to the src. * Pullup to avoid sharing mbuf cluster between m and mcopy. */ - mcopy = m_copym(m, 0, imin((int)ip->ip_len, 68), M_DONTWAIT); + mcopy = m_copym(m, 0, imin(ntohs(ip->ip_len), 68), M_DONTWAIT); if (mcopy) mcopy = m_pullup(mcopy, ip->ip_hl << 2); |
