Subject: Re: handling flags in linux compat recvfrom and recvmsg
To: None <thorpej@zembu.com>
From: Assar Westerlund <assar@netbsd.org>
List: tech-kern
Date: 12/20/2000 05:14:17
--=-=-=
Jason R Thorpe <thorpej@zembu.com> writes:
> On Tue, Dec 19, 2000 at 12:58:29PM +0100, Frank van der Linden wrote:
>
> > On Tue, Dec 19, 2000 at 09:05:07AM +0100, assar@netbsd.org wrote:
> > > Comments?
> >
> > Looks ok to me.
>
> Shouldn't we return an error for the flags that are not supported?
Yeah, new patch that does that included below (plus adding sendmsg
which I forgot in the last one). Shouldn't we also check the `flags'
value in the native system calls? That's done in the second patch
below.
/assar
--=-=-=
Content-Disposition: attachment; filename=nld
Content-Description: patch to add conversion of MSG_* to linux emulation
Index: sys/compat/linux/common/linux_socket.c
===================================================================
RCS file: /cvsroot/syssrc/sys/compat/linux/common/linux_socket.c,v
retrieving revision 1.25
diff -u -w -r1.25 linux_socket.c
--- sys/compat/linux/common/linux_socket.c 2000/12/18 14:46:36 1.25
+++ sys/compat/linux/common/linux_socket.c 2000/12/20 04:12:44
@@ -94,6 +94,7 @@
int linux_to_bsd_ip_sockopt __P((int));
int linux_to_bsd_tcp_sockopt __P((int));
int linux_to_bsd_udp_sockopt __P((int));
+int linux_to_bsd_msg_flags __P((int));
int linux_getifhwaddr __P((struct proc *, register_t *, u_int, void *));
/*
@@ -132,7 +133,40 @@
}
}
+/*
+ * convert sendto/recvfrom/sendmsg/recvmsg flags, returning -1 if any
+ * non-supported ones are set
+ */
int
+linux_to_bsd_msg_flags(flags)
+ int flags;
+{
+ int ret_flags = 0;
+
+ if (flags & LINUX_MSG_OOB)
+ ret_flags |= MSG_OOB;
+ if (flags & LINUX_MSG_PEEK)
+ ret_flags |= MSG_PEEK;
+ if (flags & LINUX_MSG_DONTROUTE)
+ ret_flags |= MSG_DONTROUTE;
+ if (flags & LINUX_MSG_CTRUNC)
+ ret_flags |= MSG_CTRUNC;
+ if (flags & LINUX_MSG_TRUNC)
+ ret_flags |= MSG_TRUNC;
+ if (flags & LINUX_MSG_DONTWAIT)
+ ret_flags |= MSG_DONTWAIT;
+ if (flags & LINUX_MSG_EOR)
+ ret_flags |= MSG_EOR;
+ if (flags & LINUX_MSG_WAITALL)
+ ret_flags |= MSG_WAITALL;
+ if (flags & ~(LINUX_MSG_OOB|LINUX_MSG_PEEK|LINUX_MSG_DONTROUTE|
+ LINUX_MSG_CTRUNC|LINUX_MSG_TRUNC|LINUX_MSG_DONTWAIT|
+ LINUX_MSG_EOR|LINUX_MSG_WAITALL))
+ return -1;
+ return ret_flags;
+}
+
+int
linux_sys_socket(p, v, retval)
struct proc *p;
void *v;
@@ -196,7 +230,9 @@
SCARG(&bsa, s) = SCARG(uap, s);
SCARG(&bsa, buf) = SCARG(uap, msg);
SCARG(&bsa, len) = SCARG(uap, len);
- SCARG(&bsa, flags) = SCARG(uap, flags);
+ SCARG(&bsa, flags) = linux_to_bsd_msg_flags(SCARG(uap, flags));
+ if (SCARG(&bsa, flags) == -1)
+ return EINVAL;
SCARG(&bsa, to) = (void *) SCARG(uap, to);
SCARG(&bsa, tolen) = SCARG(uap, tolen);
@@ -222,11 +258,57 @@
SCARG(&bra, s) = SCARG(uap, s);
SCARG(&bra, buf) = SCARG(uap, buf);
SCARG(&bra, len) = SCARG(uap, len);
- SCARG(&bra, flags) = SCARG(uap, flags);
+ SCARG(&bra, flags) = linux_to_bsd_msg_flags(SCARG(uap, flags));
+ if (SCARG(&bra, flags) == -1)
+ return EINVAL;
SCARG(&bra, from) = (caddr_t) SCARG(uap, from);
SCARG(&bra, fromlenaddr) = SCARG(uap, fromlen);
return compat_43_sys_recvfrom(p, &bra, retval);
+}
+
+int
+linux_sys_recvmsg(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_recvmsg_args /* {
+ syscallarg(int) s;
+ syscallarg(struct msghdr *) msg;
+ syscallarg(u_int) flags;
+ } */ *uap = v;
+ struct sys_recvmsg_args bra;
+
+ SCARG(&bra, s) = SCARG(uap, s);
+ SCARG(&bra, msg) = SCARG(uap, msg);
+ SCARG(&bra, flags) = linux_to_bsd_msg_flags(SCARG(uap, flags));
+ if (SCARG(&bra, flags) == -1)
+ return EINVAL;
+
+ return sys_recvmsg(p, &bra, retval);
+}
+
+int
+linux_sys_sendmsg(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_sendmsg_args /* {
+ syscallarg(int) s;
+ syscallarg(struct msghdr *) msg;
+ syscallarg(u_int) flags;
+ } */ *uap = v;
+ struct sys_sendmsg_args bsa;
+
+ SCARG(&bsa, s) = SCARG(uap, s);
+ SCARG(&bsa, msg) = SCARG(uap, msg);
+ SCARG(&bsa, flags) = linux_to_bsd_msg_flags(SCARG(uap, flags));
+ if (SCARG(&bsa, flags) == -1)
+ return EINVAL;
+
+ return sys_sendmsg(p, &bsa, retval);
}
/*
Index: sys/compat/linux/common/linux_socket.h
===================================================================
RCS file: /cvsroot/syssrc/sys/compat/linux/common/linux_socket.h,v
retrieving revision 1.7
diff -u -w -r1.7 linux_socket.h
--- sys/compat/linux/common/linux_socket.h 1998/12/15 19:31:40 1.7
+++ sys/compat/linux/common/linux_socket.h 2000/12/20 04:12:45
@@ -123,6 +123,26 @@
#define LINUX_TCP_NODELAY 1
#define LINUX_TCP_MAXSEG 2
+/*
+ * msg flags in recvfrom/recvmsg
+ */
+
+#define LINUX_MSG_OOB 0x01
+#define LINUX_MSG_PEEK 0x02
+#define LINUX_MSG_DONTROUTE 0x04
+#define LINUX_MSG_CTRUNC 0x08
+#define LINUX_MSG_PROXY 0x10
+#define LINUX_MSG_TRUNC 0x20
+#define LINUX_MSG_DONTWAIT 0x40
+#define LINUX_MSG_EOR 0x80
+#define LINUX_MSG_WAITALL 0x100
+#define LINUX_MSG_FIN 0x200
+#define LINUX_MSG_SYN 0x400
+#define LINUX_MSG_CONFIRM 0x800
+#define LINUX_MSG_RST 0x1000
+#define LINUX_MSG_ERRQUEUE 0x2000
+#define LINUX_MSG_NOSIGNAL 0x4000
+
#if defined(__i386__)
#include <compat/linux/arch/i386/linux_socket.h>
#elif defined(__m68k__)
Index: sys/compat/linux/common/linux_socketcall.c
===================================================================
RCS file: /cvsroot/syssrc/sys/compat/linux/common/linux_socketcall.c,v
retrieving revision 1.19
diff -u -w -r1.19 linux_socketcall.c
--- sys/compat/linux/common/linux_socketcall.c 1999/03/25 04:26:45 1.19
+++ sys/compat/linux/common/linux_socketcall.c 2000/12/20 04:12:45
@@ -156,9 +156,9 @@
case LINUX_SYS_getsockopt:
return linux_sys_getsockopt(p, (void *)&lda, retval);
case LINUX_SYS_sendmsg:
- return sys_sendmsg(p, (void *)&lda, retval);
+ return linux_sys_sendmsg(p, (void *)&lda, retval);
case LINUX_SYS_recvmsg:
- return sys_recvmsg(p, (void *)&lda, retval);
+ return linux_sys_recvmsg(p, (void *)&lda, retval);
default:
return ENOSYS;
}
Index: sys/compat/linux/common/linux_socketcall.h
===================================================================
RCS file: /cvsroot/syssrc/sys/compat/linux/common/linux_socketcall.h,v
retrieving revision 1.5
diff -u -w -r1.5 linux_socketcall.h
--- sys/compat/linux/common/linux_socketcall.h 1999/03/25 04:26:45 1.5
+++ sys/compat/linux/common/linux_socketcall.h 2000/12/20 04:12:45
@@ -233,6 +233,8 @@
int linux_sys_socketpair __P((struct proc *, void *, register_t *));
int linux_sys_sendto __P((struct proc *, void *, register_t *));
int linux_sys_recvfrom __P((struct proc *, void *, register_t *));
+int linux_sys_recvmsg __P((struct proc *, void *, register_t *));
+int linux_sys_sendmsg __P((struct proc *, void *, register_t *));
int linux_sys_setsockopt __P((struct proc *, void *, register_t *));
int linux_sys_getsockopt __P((struct proc *, void *, register_t *));
int linux_sys_connect __P((struct proc *, void *, register_t *));
--=-=-=
--=-=-=
Content-Disposition: attachment; filename=netbsd-msg-check
Content-Description: patch to test MSG_* in recv*/send*
Index: sys/sys/socket.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/socket.h,v
retrieving revision 1.59
diff -u -w -r1.59 socket.h
--- sys/sys/socket.h 2000/10/04 08:59:16 1.59
+++ sys/sys/socket.h 2000/12/20 03:49:57
@@ -392,6 +392,10 @@
#define MSG_BCAST 0x100 /* this message was rcvd using link-level brdcst */
#define MSG_MCAST 0x200 /* this message was rcvd using link-level mcast */
+/* all flags settable by system calls */
+#define MSG_MASK (MSG_OOB|MSG_PEEK|MSG_DONTWAIT|MSG_EOR|MSG_TRUNC|\
+ MSG_CTRUNC|MSG_WAITALL|MSG_DONTWAIT)
+
/*
* Header for ancillary data objects in msg_control buffer.
* Used for additional information with/about a datagram
Index: sys/kern/uipc_syscalls.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/uipc_syscalls.c,v
retrieving revision 1.56
diff -u -w -r1.56 uipc_syscalls.c
--- sys/kern/uipc_syscalls.c 2000/12/10 23:16:28 1.56
+++ sys/kern/uipc_syscalls.c 2000/12/20 03:49:58
@@ -399,6 +399,11 @@
} */ *uap = v;
struct msghdr msg;
struct iovec aiov;
+ int flags;
+
+ flags = SCARG(uap, flags);
+ if (flags & ~MSG_MASK)
+ return (EINVAL);
msg.msg_name = (caddr_t)SCARG(uap, to); /* XXX kills const */
msg.msg_namelen = SCARG(uap, tolen);
@@ -410,7 +415,7 @@
#endif
aiov.iov_base = (char *)SCARG(uap, buf); /* XXX kills const */
aiov.iov_len = SCARG(uap, len);
- return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
+ return (sendit(p, SCARG(uap, s), &msg, flags, retval));
}
int
@@ -427,6 +432,12 @@
struct msghdr msg;
struct iovec aiov[UIO_SMALLIOV], *iov;
int error;
+ int flags;
+
+ flags = SCARG(uap, flags);
+ if (flags & ~MSG_MASK)
+ return (EINVAL);
+
error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
if (error)
@@ -448,7 +459,7 @@
#ifdef COMPAT_OLDSOCK
msg.msg_flags = 0;
#endif
- error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
+ error = sendit(p, SCARG(uap, s), &msg, flags, retval);
done:
if (iov != aiov)
free(iov, M_IOV);
@@ -594,6 +605,11 @@
struct msghdr msg;
struct iovec aiov;
int error;
+ int flags;
+
+ flags = SCARG(uap, flags);
+ if (flags & ~MSG_MASK)
+ return (EINVAL);
if (SCARG(uap, fromlenaddr)) {
error = copyin((caddr_t)SCARG(uap, fromlenaddr),
@@ -609,7 +625,7 @@
aiov.iov_base = SCARG(uap, buf);
aiov.iov_len = SCARG(uap, len);
msg.msg_control = 0;
- msg.msg_flags = SCARG(uap, flags);
+ msg.msg_flags = flags;
return (recvit(p, SCARG(uap, s), &msg,
(caddr_t)SCARG(uap, fromlenaddr), retval));
}
@@ -628,6 +644,11 @@
struct msghdr msg;
struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
int error;
+ int flags;
+
+ flags = SCARG(uap, flags);
+ if (flags & ~MSG_MASK)
+ return (EINVAL);
error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
sizeof(msg));
@@ -649,9 +670,9 @@
uiov = msg.msg_iov;
msg.msg_iov = iov;
#ifdef COMPAT_OLDSOCK
- msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
+ msg.msg_flags = flags &~ MSG_COMPAT;
#else
- msg.msg_flags = SCARG(uap, flags);
+ msg.msg_flags = flags;
#endif
if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
msg.msg_iov = uiov;
Index: lib/libc/sys/recv.2
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/sys/recv.2,v
retrieving revision 1.16
diff -u -w -r1.16 recv.2
--- lib/libc/sys/recv.2 1999/12/02 21:42:38 1.16
+++ lib/libc/sys/recv.2 2000/12/20 03:49:58
@@ -257,7 +257,8 @@
address space.
.It Bq Er EINVAL
The total length of the I/O is more than can be expressed by the ssize_t
-return value.
+return value, or unsupported bits are set in
+.Fa flags .
.El
.Pp
.Fn recvmsg
Index: lib/libc/sys/send.2
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/sys/send.2,v
retrieving revision 1.15
diff -u -w -r1.15 send.2
--- lib/libc/sys/send.2 1999/12/02 21:42:39 1.15
+++ lib/libc/sys/send.2 2000/12/20 03:49:58
@@ -159,7 +159,8 @@
The destination for the message is unreachable.
.It Bq Er EINVAL
The total length of the I/O is more than can be expressed by the ssize_t
-return value.
+return value, or unsupported bits are set in
+.Fa flags .
.It Bq Er EAFNOSUPPORT
Addresses in the specified address family cannot be used with this socket.
.El
--=-=-=--