Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Nov 2000 18:04:16 +0200
From:      Ruslan Ermilov <ru@FreeBSD.org>
To:        net@FreeBSD.org
Subject:   Please review... ip header length subtraction elimination
Message-ID:  <20001103180416.A21617@sunbay.com>

next in thread | raw e-mail | index | archive | help

--Qxx1br4bt0+wmkIi
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi!

ip_input() currently subtracts the header length from ip_len before
delivery to protocol input routines.  This is bogus for many reasons.

This patch preserves the ip_len with original value.  Protocol input
routines are modified accordingly.

<PS>
The goal of this patch (and successive ones) is to preserve the whole
packet's mbuf chain (whenever possible) unchanged, so that the shared
mbuf clusters don't get screwed.  This will include, in particular,
elimination of byte-swapping of header fields.
</PS>

-- 
Ruslan Ermilov		Oracle Developer/DBA,
ru@sunbay.com		Sunbay Software AG,
ru@FreeBSD.org		FreeBSD committer,
+380.652.512.251	Simferopol, Ukraine

http://www.FreeBSD.org	The Power To Serve
http://www.oracle.com	Enabling The Information Age

--Qxx1br4bt0+wmkIi
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=p

Index: netinet/igmp.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/igmp.c,v
retrieving revision 1.30
diff -u -p -r1.30 igmp.c
--- netinet/igmp.c	2000/05/06 18:19:58	1.30
+++ netinet/igmp.c	2000/11/03 15:47:34
@@ -168,7 +168,7 @@ igmp_input(m, off, proto)
 	++igmpstat.igps_rcv_total;
 
 	ip = mtod(m, struct ip *);
-	igmplen = ip->ip_len;
+	igmplen = ip->ip_len - iphlen;
 
 	/*
 	 * Validate lengths
Index: netinet/ip_icmp.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.46
diff -u -p -r1.46 ip_icmp.c
--- netinet/ip_icmp.c	2000/11/02 09:46:23	1.46
+++ netinet/ip_icmp.c	2000/11/03 15:47:34
@@ -235,12 +235,13 @@ icmp_input(m, off, proto)
 	int hlen = off;
 	register struct icmp *icp;
 	register struct ip *ip = mtod(m, struct ip *);
-	int icmplen = ip->ip_len;
+	int icmplen;
 	register int i;
 	struct in_ifaddr *ia;
 	void (*ctlfunc) __P((int, struct sockaddr *, void *));
 	int code;
 
+	icmplen = ip->ip_len - hlen;
 	/*
 	 * Locate icmp structure in mbuf, and check
 	 * that not corrupted and of at least minimum length.
@@ -265,11 +266,11 @@ icmp_input(m, off, proto)
 	ip = mtod(m, struct ip *);
 	m->m_len -= hlen;
 	m->m_data += hlen;
-	icp = mtod(m, struct icmp *);
 	if (in_cksum(m, icmplen)) {
 		icmpstat.icps_checksum++;
 		goto freeit;
 	}
+	icp = mtod(m, struct icmp *);
 	m->m_len += hlen;
 	m->m_data -= hlen;
 
@@ -501,7 +502,6 @@ icmp_input(m, off, proto)
 			    ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
 		}
 reflect:
-		ip->ip_len += hlen;	/* since ip_input deducts this */
 		icmpstat.icps_reflect++;
 		icmpstat.icps_outhist[icp->icmp_type]++;
 		icmp_reflect(m);
Index: netinet/ip_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.148
diff -u -p -r1.148 ip_input.c
--- netinet/ip_input.c	2000/11/01 11:21:45	1.148
+++ netinet/ip_input.c	2000/11/03 15:47:34
@@ -668,10 +668,10 @@ found:
 		ip = mtod(m, struct ip *);
 		/* Get the header length of the reassembled packet */
 		hlen = IP_VHL_HL(ip->ip_vhl) << 2;
+		ip->ip_len += hlen;
 #ifdef IPDIVERT
 		/* Restore original checksum before diverting packet */
 		if (divert_info != 0) {
-			ip->ip_len += hlen;
 			HTONS(ip->ip_len);
 			HTONS(ip->ip_off);
 			ip->ip_sum = 0;
@@ -681,11 +681,9 @@ found:
 				ip->ip_sum = in_cksum(m, hlen);
 			NTOHS(ip->ip_off);
 			NTOHS(ip->ip_len);
-			ip->ip_len -= hlen;
 		}
 #endif
-	} else
-		ip->ip_len -= hlen;
+	}
 
 #ifdef IPDIVERT
 	/*
@@ -702,7 +700,6 @@ found:
 			clone = m_dup(m, M_DONTWAIT);
 
 		/* Restore packet header fields to original values */
-		ip->ip_len += hlen;
 		HTONS(ip->ip_len);
 		HTONS(ip->ip_off);
 
@@ -1412,6 +1409,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_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2);
 }
 
Index: netinet/raw_ip.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.71
diff -u -p -r1.71 raw_ip.c
--- netinet/raw_ip.c	2000/10/29 16:06:48	1.71
+++ netinet/raw_ip.c	2000/11/03 15:47:34
@@ -121,6 +121,13 @@ rip_input(m, off, proto)
 	struct mbuf *opts = 0;
 
 	ripsrc.sin_addr = ip->ip_src;
+
+	/*
+	 * XXX Compatibility: programs using raw IP expect
+	 * ip_len to have the header length subtracted.
+	 */
+	ip->ip_len -= off;
+
 	LIST_FOREACH(inp, &ripcb, inp_list) {
 #ifdef INET6
 		if ((inp->inp_vflag & INP_IPV4) == 0)
Index: netinet/tcp_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.118
diff -u -p -r1.118 tcp_input.c
--- netinet/tcp_input.c	2000/07/21 23:26:37	1.118
+++ netinet/tcp_input.c	2000/11/03 15:47:34
@@ -430,7 +430,7 @@ tcp_input(m, off0, proto)
 	ip = mtod(m, struct ip *);
 	ipov = (struct ipovly *)ip;
 	th = (struct tcphdr *)((caddr_t)ip + off0);
-	tlen = ip->ip_len;
+	tlen = ip->ip_len - off0;
 
 	if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
 		if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
@@ -438,7 +438,7 @@ tcp_input(m, off0, proto)
 		else
 	                th->th_sum = in_pseudo(ip->ip_src.s_addr,
 			    ip->ip_dst.s_addr, htonl(m->m_pkthdr.csum_data +
-			    ip->ip_len + IPPROTO_TCP));
+			    tlen + IPPROTO_TCP));
 		th->th_sum ^= 0xffff;
 	} else {
 		/*
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.78
diff -u -p -r1.78 udp_usrreq.c
--- netinet/udp_usrreq.c	2000/11/01 16:56:33	1.78
+++ netinet/udp_usrreq.c	2000/11/03 15:47:34
@@ -177,14 +177,13 @@ udp_input(m, off, proto)
 	/*
 	 * Get IP and UDP header together in first mbuf.
 	 */
-	ip = mtod(m, struct ip *);
 	if (m->m_len < iphlen + sizeof(struct udphdr)) {
 		if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
 			udpstat.udps_hdrops++;
 			return;
 		}
-		ip = mtod(m, struct ip *);
 	}
+	ip = mtod(m, struct ip *);
 	uh = (struct udphdr *)((caddr_t)ip + iphlen);
 
 	/* destination port of 0 is illegal, based on RFC768. */
@@ -196,13 +195,12 @@ udp_input(m, off, proto)
 	 * If not enough data to reflect UDP length, drop.
 	 */
 	len = ntohs((u_short)uh->uh_ulen);
-	if (ip->ip_len != len) {
-		if (len > ip->ip_len || len < sizeof(struct udphdr)) {
+	if (ip->ip_len != iphlen + len) {
+		if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) {
 			udpstat.udps_badlen++;
 			goto bad;
 		}
-		m_adj(m, len - ip->ip_len);
-		/* ip->ip_len = len; */
+		m_adj(m, iphlen + len - ip->ip_len);
 	}
 	/*
 	 * Save a copy of the IP header in case we want restore it
@@ -358,7 +356,6 @@ udp_input(m, off, proto)
 		if (blackhole)
 			goto bad;
 		*ip = save_ip;
-		ip->ip_len += iphlen;
 		icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
 		return;
 	}
Index: netinet6/ah_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/ah_input.c,v
retrieving revision 1.5
diff -u -p -r1.5 ah_input.c
--- netinet6/ah_input.c	2000/09/14 14:42:04	1.5
+++ netinet6/ah_input.c	2000/11/03 15:47:35
@@ -290,7 +290,7 @@ ah4_input(m, va_alist)
 	 * some of IP header fields are flipped to the host endian.
 	 * convert them back to network endian.  VERY stupid.
 	 */
-	ip->ip_len = htons(ip->ip_len + hlen);
+	ip->ip_len = htons(ip->ip_len);
 	ip->ip_off = htons(ip->ip_off);
 #endif
 	if (ah4_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) {
@@ -303,7 +303,7 @@ ah4_input(m, va_alist)
 	/*
 	 * flip them back.
 	 */
-	ip->ip_len = ntohs(ip->ip_len) - hlen;
+	ip->ip_len = ntohs(ip->ip_len);
 	ip->ip_off = ntohs(ip->ip_off);
 #endif
     }

--Qxx1br4bt0+wmkIi--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001103180416.A21617>