NetBSD Problem Report #31368

From cliff@vixen.snipe444.org  Wed Sep 21 23:16:08 2005
Return-Path: <cliff@vixen.snipe444.org>
Received: from vixen.snipe444.org (c-24-18-15-230.hsd1.wa.comcast.net [24.18.15.230])
	by narn.netbsd.org (Postfix) with ESMTP id 86D2C63B852
	for <gnats-bugs@gnats.NetBSD.org>; Wed, 21 Sep 2005 23:16:08 +0000 (UTC)
Message-Id: <200509212316.j8LNG1ag013722@vixen.snipe444.org>
Date: Wed, 21 Sep 2005 16:16:01 -0700 (PDT)
From: Cliff Wright <cliff@vixen.snipe444.org>
Reply-To: cliff@vixen.snipe444.org
To: gnats-bugs@netbsd.org
Subject: Linux compatibility raw inet protocol handling changes
X-Send-Pr-Version: 3.95

>Number:         31368
>Category:       kern
>Synopsis:       Linux compatibility raw inet protocol handling changes
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Sep 21 23:17:00 +0000 2005
>Last-Modified:  Sun Jan 24 20:24:14 +0000 2010
>Originator:     Cliff Wright
>Release:        NetBSD 2.0_BETA
>Organization:

>Environment:


System: NetBSD vixen 2.0_BETA NetBSD 2.0_BETA (vixen) #2: Tue Jun 7 16:15:17 PDT 2005 cliff@vixen:/usr/src/sys/arch/i386/compile/vixen i386
Architecture: i386
Machine: i386
>Description:

	When running a vendor network analysis program in Linux
	compatibility mode, some missing features, and problems
	were observed. A patch is included that fixes these.

	1. The rarely used get interface mtu (SIOCGIFMTU) was
	   not implemented.
	2. The raw inet protocol option header include (IP_HDRINCL)
	    was not implemented.
	3. When using bind on a raw inet socket, Linux ignores some
	   bytes that BSD does not, so needed to adjust these bytes
	   for the BSD call.
	4. When using the header include option, BSD has 2 fields of
	   the packet in host byte order, whereas Linux does not,
	   so may need to adjust these fields.
>How-To-Repeat:

>Fix:

--- src/sys/compat/linux/common/linux_socket.h.orig	2003-07-27 12:30:03.000000000 -0700
+++ src/sys/compat/linux/common/linux_socket.h	2005-09-20 14:08:13.000000000 -0700
@@ -110,6 +110,7 @@

 #define LINUX_IP_TOS		1
 #define LINUX_IP_TTL		2
+#define LINUX_IP_HDRINCL	3
 #define	LINUX_IP_MULTICAST_IF	32
 #define	LINUX_IP_MULTICAST_TTL	33
 #define	LINUX_IP_MULTICAST_LOOP	34
--- src/sys/compat/linux/common/linux_sockio.h.orig	2000-12-22 03:24:43.000000000 -0800
+++ src/sys/compat/linux/common/linux_sockio.h	2005-09-19 14:41:11.000000000 -0700
@@ -47,6 +47,7 @@
 #define	LINUX_SIOCGIFDSTADDR	_LINUX_IO(0x89, 0x17)
 #define	LINUX_SIOCGIFBRDADDR	_LINUX_IO(0x89, 0x19)
 #define	LINUX_SIOCGIFNETMASK	_LINUX_IO(0x89, 0x1b)
+#define LINUX_SIOCGIFMTU	_LINUX_IO(0x89, 0x21)
 #define LINUX_SIOCADDMULTI	_LINUX_IO(0x89, 0x31)
 #define LINUX_SIOCDELMULTI	_LINUX_IO(0x89, 0x32)
 #define LINUX_SIOCGIFHWADDR	_LINUX_IO(0x89, 0x27)
--- src/sys/compat/linux/common/linux_socket.c.orig	2003-10-25 11:38:42.000000000 -0700
+++ src/sys/compat/linux/common/linux_socket.c	2005-09-21 14:56:05.000000000 -0700
@@ -64,6 +64,10 @@
 #include <net/if_dl.h>
 #include <net/if_types.h>
 #include <netinet/in.h>
+#if BYTE_ORDER == LITTLE_ENDIAN
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#endif
 #include <netinet/tcp.h>
 #include <sys/mount.h>
 #include <sys/proc.h>
@@ -385,10 +389,41 @@
 		struct sockaddr *sa;
 		int error;
 		caddr_t sg = stackgap_init(p, 0);
+#if BYTE_ORDER == LITTLE_ENDIAN
+		struct file	*fp;
+#endif

 		if ((error = linux_sa_get(p, &sg, &sa, SCARG(uap, to), &tolen)))
 			return (error);

+#if BYTE_ORDER == LITTLE_ENDIAN
+		/* For raw inet header included data, BSD has 2 fields
+		 * in host byte order that Linux does not, so need to
+		 * adjust for this. cliff
+		 */
+
+		if( sa->sa_family == AF_INET &&
+		    getsock(p->p_fd, SCARG(uap, s), &fp) == 0) {
+			if(((struct socket *)fp->f_data)->so_type == SOCK_RAW) {
+				struct mbuf	*m;
+
+				error = sogetopt((struct socket *)fp->f_data,
+				IPPROTO_IP, IP_HDRINCL, &m);
+				if(!error && m != NULL) {
+					if(*mtod(m, int *)) {
+						struct ip *ip_head;
+
+						ip_head = (struct ip *)
+						  SCARG(uap, msg);
+						NTOHS(ip_head->ip_len);
+						NTOHS(ip_head->ip_off);
+					}
+					m_free(m);
+				}
+			}
+			FILE_UNUSE(fp, p);
+		}
+#endif
 		SCARG(&bsa, to) = sa;
 	} else
 		SCARG(&bsa, to) = NULL;
@@ -917,6 +952,8 @@
 		return IP_TOS;
 	case LINUX_IP_TTL:
 		return IP_TTL;
+	case LINUX_IP_HDRINCL:
+		return IP_HDRINCL;
 	case LINUX_IP_MULTICAST_TTL:
 		return IP_MULTICAST_TTL;
 	case LINUX_IP_MULTICAST_LOOP:
@@ -1275,6 +1312,9 @@
 	case LINUX_SIOCGIFNETMASK:
 		SCARG(&ia, com) = OSIOCGIFNETMASK;
 		break;
+	case LINUX_SIOCGIFMTU:
+		SCARG(&ia, com) = SIOCGIFMTU;
+		break;
 	case LINUX_SIOCADDMULTI:
 		SCARG(&ia, com) = SIOCADDMULTI;
 		break;
@@ -1374,11 +1414,12 @@
 	struct proc *p = l->l_proc;
 	int		error, namlen;
 	struct sys_bind_args bsa;
+	struct sockaddr *sa;
+	struct file	*fp;

 	namlen = SCARG(uap, namelen);
 	SCARG(&bsa, s) = SCARG(uap, s);
 	if (SCARG(uap, name)) {
-		struct sockaddr *sa;
 		caddr_t sg = stackgap_init(p, 0);

 		error = linux_sa_get(p, &sg, &sa, SCARG(uap, name), &namlen);
@@ -1390,6 +1431,20 @@
 		SCARG(&bsa, name) = NULL;
 	SCARG(&bsa, namelen) = namlen;

+	/* For raw inet sockets Linux only looks at 4 byte inet address,
+	 * BSD looks at full address, so have to clean up the address
+	 * for BSD. cliff
+	 */
+	if( sa->sa_family == AF_INET &&
+	    getsock(p->p_fd, SCARG(uap, s), &fp) == 0) {
+		if(((struct socket *)fp->f_data)->so_type == SOCK_RAW) {
+			int i;
+			sa->sa_data[0] = sa->sa_data[1] = 0;
+			for (i = 0; i < 8; i++) sa->sa_data[i + 6] = 0;
+		}
+		FILE_UNUSE(fp, p);
+	}
+
 	return (sys_bind(l, &bsa, retval));
 }


>Release-Note:

>Audit-Trail:

From: David Laight <dsl@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/31358 CVS commit: src/sys/compat
Date: Sat, 28 Nov 2009 22:11:42 +0000

 Module Name:	src
 Committed By:	dsl
 Date:		Sat Nov 28 22:11:42 UTC 2009

 Modified Files:
 	src/sys/compat/linux/common: linux_socket.c linux_socket.h
 	    linux_sockio.h
 	src/sys/compat/sys: sockio.h

 Log Message:
 Add LINUX_SIOCGIFMTU and LINUX_IP_HDRINCL support.
 Fixes part of PR/31368
 The other parts are rather too intrusive to be fixed as in the PR.


 To generate a diff of this commit:
 cvs rdiff -u -r1.106 -r1.107 src/sys/compat/linux/common/linux_socket.c
 cvs rdiff -u -r1.18 -r1.19 src/sys/compat/linux/common/linux_socket.h
 cvs rdiff -u -r1.17 -r1.18 src/sys/compat/linux/common/linux_sockio.h
 cvs rdiff -u -r1.7 -r1.8 src/sys/compat/sys/sockio.h

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.