summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2003-10-11 15:08:32 +0000
committeriwasaki <iwasaki@FreeBSD.org>2003-10-11 15:08:32 +0000
commit324480cbaf22f812dbbff8d773d2f51c15a59e1d (patch)
tree838ecf698f233895709cc02db410ed0624a7a772
parent8f0a204f9bab012d324a4ca5a65811b0360ec4f5 (diff)
downloadFreeBSD-src-324480cbaf22f812dbbff8d773d2f51c15a59e1d.zip
FreeBSD-src-324480cbaf22f812dbbff8d773d2f51c15a59e1d.tar.gz
Fix some problems in linux_sendmsg() and linux_recvmsg().
- Allocate storage for uap->msg always because it is copyin()'ed in native sendmsg(). - Convert sockopt level from Linux to FreeBSD after native recvmsg() calling. - Some cleanups. Tested with: Oracle 9i shared server connection mode. MFC after: 1 week
-rw-r--r--sys/compat/linux/linux_socket.c74
1 files changed, 38 insertions, 36 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index a8d8128..bf9d217 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -225,6 +225,17 @@ linux_to_bsd_sockopt_level(int level)
}
static int
+bsd_to_linux_sockopt_level(int level)
+{
+
+ switch (level) {
+ case SOL_SOCKET:
+ return (LINUX_SOL_SOCKET);
+ }
+ return (level);
+}
+
+static int
linux_to_bsd_ip_sockopt(int opt)
{
@@ -995,9 +1006,9 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
} */ bsd_args;
struct msghdr msg;
struct msghdr *nmsg = NULL;
+ struct cmsghdr *cmsg;
int error;
- int level;
- caddr_t control;
+ caddr_t sg;
if ((error = copyin(args, &linux_args, sizeof(linux_args))))
return (error);
@@ -1006,54 +1017,39 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
if (error)
return (error);
- if (msg.msg_name) {
- struct sockaddr *sa;
- caddr_t sg = stackgap_init();
+ sg = stackgap_init();
+ nmsg = (struct msghdr *)stackgap_alloc(&sg, sizeof(struct msghdr));
+ if (nmsg == NULL)
+ return (ENOMEM);
- nmsg = (struct msghdr *) stackgap_alloc(&sg,
- sizeof(struct msghdr));
- if (!nmsg)
- return (ENOMEM);
+ bcopy(&msg, nmsg, sizeof(struct msghdr));
+
+ if (msg.msg_name != NULL) {
+ struct sockaddr *sa;
error = linux_sa_get(&sg, &sa,
(struct osockaddr *) msg.msg_name, &msg.msg_namelen);
if (error)
return (error);
- msg.msg_name = (struct sockaddr *) sa;
- error = copyout(&msg, nmsg, sizeof(struct msghdr));
- if (error)
- return (error);
+ nmsg->msg_name = sa;
}
- error = copyin(&linux_args.msg->msg_control, &control,
- sizeof(caddr_t));
- if (error)
- return (error);
-
- if (control == NULL)
- goto done;
+ if (msg.msg_control != NULL) {
+ nmsg->msg_control = (struct cmsghdr *)stackgap_alloc(&sg,
+ msg.msg_controllen);
+ if (nmsg->msg_control == NULL)
+ return (ENOMEM);
- error = copyin(&((struct cmsghdr*)control)->cmsg_level, &level,
- sizeof(int));
- if (error)
- return (error);
+ bcopy(msg.msg_control, nmsg->msg_control, msg.msg_controllen);
+ cmsg = (struct cmsghdr*)nmsg->msg_control;
- if (level == 1) {
- /*
- * Linux thinks that SOL_SOCKET is 1; we know
- * that it's really 0xffff, of course.
- */
- level = SOL_SOCKET;
- error = copyout(&level,
- &((struct cmsghdr *)control)->cmsg_level, sizeof(int));
- if (error)
- return (error);
+ cmsg->cmsg_level = linux_to_bsd_sockopt_level(cmsg->cmsg_level);
}
-done:
+
bsd_args.s = linux_args.s;
bsd_args.msg = (caddr_t)nmsg;
- bsd_args.flags = linux_args.flags;
+ bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
return (sendmsg(td, &bsd_args));
}
@@ -1073,6 +1069,7 @@ linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
int flags;
} */ bsd_args;
struct msghdr msg;
+ struct cmsghdr *cmsg;
int error;
if ((error = copyin(args, &linux_args, sizeof(linux_args))))
@@ -1085,6 +1082,11 @@ linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
if (error)
return (error);
+ if (bsd_args.msg->msg_control != NULL) {
+ cmsg = (struct cmsghdr*)bsd_args.msg->msg_control;
+ cmsg->cmsg_level = bsd_to_linux_sockopt_level(cmsg->cmsg_level);
+ }
+
error = copyin(linux_args.msg, &msg, sizeof(msg));
if (error)
return (error);
OpenPOWER on IntegriCloud