Date: Fri, 18 Oct 1996 16:22:30 -0400 From: "Kurt J. Lidl" <lidl@va.pubnix.com> To: freebsd-arch@freebsd.org, tech-net@netbsd.org Cc: freebsd-bugs@freebsd.org, netbsd-bugs@netbsd.org, lidl@va.pubnix.com Subject: proposed kernel change for IP_HDRINCL Message-ID: <QAA01789.199610182022@arrow.va.pubnix.com>
next in thread | raw e-mail | index | archive | help
I'm trying to coordinate this "fixing the interface" issue with three groups: BSDi NetBSD OpenBSD So far, BSDi (which is the system where I first noticed this issue) has committed to fixing this interface if both the FreeBSD and NetBSD groups will commit to fixing it also. One line description: --------------------- There is a byte order dependency problem with the IP_HDRINCL option to setsockopt() Full Description: ----------------- Currently, when using setsockopt() with the IP_HDRINCL flag, most fields of the IP header are passed into the kernel in network byte order, except for the ip_off and ip_len fields. Any IP checksum that is placed on the packet in user-mode will be incorrect on little-endian machines, because those two fields are not in network byte order. Internally, the kernel carries around mbufs with the ip_off and ip_len fields host byte order. The kernel then switches those two fields to network order just before queuing a mbuf for an interface. To make the kernel's network API consistant, the ip_off and ip_len fields should be changed to be passed in network byte order, not host byte order. The kernel should then change the fields to the host byte order for ip_off and ip_len, since that is what the rest of the internal networking code are expecting. How to fix the problem: ----------------------- Here's the diff for BSDi's kernel tree, but I expect it will be similar or identical in both the NetBSD and FreeBSD kernel trees. *** raw_ip.c 1996/08/28 19:30:23 1.2 --- raw_ip.c 1996/10/07 18:38:06 1.3 *************** *** 153,158 **** --- 153,161 ---- opts = inp->inp_options; } else { ip = mtod(m, struct ip *); + /* ip_output expects these in host byte order */ + NTOHS(ip->ip_len); + NTOHS(ip->ip_off); if (ip->ip_len > m->m_pkthdr.len) { m_freem(m); return (EMSGSIZE); As well, the utilites that use IP_HDRINCL setsockopt() flag need to be changed. On BSD/OS (v2.1), this is only traceroute and mrouted. I've included patches for those two programs at the end of this message. Any other programs that use the IP_HDRINCL flag would also need to be changed. NOTE: ----- This change will break backwards binary compatibility with programs that use IP_HDRINCL and don't ntohs() the arguments for little endian machines. Please reply and let me know if you are willing to make this change. Thanks for your consideration, -Kurt Contact information: Email: lidl@uu.net lidl@va.pubnix.com Kurt J. Lidl UUNET Technologies 3060 Williams Drive Fairfax, VA 20031 +1 703 206 5836 (voice) +1 703 206 5601 (fax) *** traceroute.c 1996/10/09 14:45:19 1.1 --- traceroute.c 1996/10/09 14:59:00 *************** *** 582,591 **** struct udphdr *up = &op->udp; int i; ! ip->ip_off = 0; ip->ip_hl = sizeof(*ip) >> 2; ip->ip_p = IPPROTO_UDP; ! ip->ip_len = datalen; ip->ip_ttl = ttl; ip->ip_v = IPVERSION; ip->ip_id = htons(ident+seq); --- 582,591 ---- struct udphdr *up = &op->udp; int i; ! ip->ip_off = htons(0); ip->ip_hl = sizeof(*ip) >> 2; ip->ip_p = IPPROTO_UDP; ! ip->ip_len = htons(datalen); ip->ip_ttl = ttl; ip->ip_v = IPVERSION; ip->ip_id = htons(ident+seq); *** igmp.c 1996/10/18 20:12:38 1.1 --- igmp.c 1996/10/18 20:13:57 *************** *** 56,62 **** ip->ip_hl = sizeof(struct ip) >> 2; ip->ip_v = IPVERSION; ip->ip_tos = 0; ! ip->ip_off = 0; ip->ip_p = IPPROTO_IGMP; ip->ip_ttl = MAXTTL; /* applies to unicasts only */ --- 56,62 ---- ip->ip_hl = sizeof(struct ip) >> 2; ip->ip_v = IPVERSION; ip->ip_tos = 0; ! ip->ip_off = htons(0); ip->ip_p = IPPROTO_IGMP; ip->ip_ttl = MAXTTL; /* applies to unicasts only */ *************** *** 315,321 **** ip = (struct ip *)send_buf; ip->ip_src.s_addr = src; ip->ip_dst.s_addr = dst; ! ip->ip_len = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen; igmp = (struct igmp *)(send_buf + MIN_IP_HEADER_LEN); igmp->igmp_type = type; --- 315,321 ---- ip = (struct ip *)send_buf; ip->ip_src.s_addr = src; ip->ip_dst.s_addr = dst; ! ip->ip_len = htons(MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen); igmp = (struct igmp *)(send_buf + MIN_IP_HEADER_LEN); igmp->igmp_type = type;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?QAA01789.199610182022>