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
This commit is contained in:
Mitsuru IWASAKI 2003-10-11 15:08:32 +00:00
parent d03a9dc77a
commit 84b11cd80a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=121008

View File

@ -224,6 +224,17 @@ linux_to_bsd_sockopt_level(int level)
return (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 (msg.msg_control != NULL) {
nmsg->msg_control = (struct cmsghdr *)stackgap_alloc(&sg,
msg.msg_controllen);
if (nmsg->msg_control == NULL)
return (ENOMEM);
if (control == NULL)
goto done;
bcopy(msg.msg_control, nmsg->msg_control, msg.msg_controllen);
cmsg = (struct cmsghdr*)nmsg->msg_control;
error = copyin(&((struct cmsghdr*)control)->cmsg_level, &level,
sizeof(int));
if (error)
return (error);
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);