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>