Subject: Re: linux emul & net config
To: Frank van der Linden <fvdl@wasabisystems.com>
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
List: tech-net
Date: 11/29/2002 09:27:04
>This looks like it won't work. You're assigning kernel space pointers
>to a syscall arg structure, and the system call will expect them
>to be in userspace. That's why emulations use stackgap_alloc.
>I wouldn't call sys_*, but a function one or more levels below that.

	i wanted to avoid code duplicates.  here's a second try.

itojun


Index: linux_socket.c
===================================================================
RCS file: /cvsroot/syssrc/sys/compat/linux/common/linux_socket.c,v
retrieving revision 1.40
diff -u -r1.40 linux_socket.c
--- linux_socket.c	2002/11/28 23:46:15	1.40
+++ linux_socket.c	2002/11/29 00:26:06
@@ -215,13 +215,48 @@
 		syscallarg(int) protocol;
 	} */ *uap = v;
 	struct sys_socket_args bsa;
+	struct sys_close_args bca;
+	struct file *fp;
+	int s;
 
 	SCARG(&bsa, protocol) = SCARG(uap, protocol);
 	SCARG(&bsa, type) = SCARG(uap, type);
 	SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
 	if (SCARG(&bsa, domain) == -1)
 		return EINVAL;
-	return sys_socket(p, &bsa, retval);
+	s = sys_socket(p, &bsa, retval);
+
+#ifdef INET6
+	/*
+	 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by default.
+	 * XXX interaction with native sysctl net.inet6.ip6.v6only?
+	 */
+	if (SCARG(&bsa, domain) == PF_INET6) {
+		int error;
+		struct mbuf *m;
+
+		/* duplicate of sys_setsockopt */
+		error = getsock(p->p_fd, s, &fp);
+		if (error)
+			goto fail;
+		m = m_get(M_WAIT, MT_SOOPTS);
+		m->m_len = sizeof(int);
+		*mtod(m, int *) = 0;
+		error = sosetopt((struct socket *)fp->f_data, IPPROTO_IPV6,
+		    IPV6_V6ONLY, m);
+		if (error)
+			goto fail;
+		FILE_UNUSE(fp, p);
+	}
+#endif
+	return s;
+
+fail:
+	FILE_UNUSE(fp, p);
+	SCARG(&bca, fd) = s;
+	sys_close(p, &bca, retval);
+	*retval = -1;
+	return (EINVAL);
 }
 
 int