mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-22 11:30:01 +08:00
[SAL] Update SAL,Add socketpair sendmsg recvmsg function (#8293)
This commit is contained in:
@@ -3535,6 +3535,150 @@ static int netflags_muslc_2_lwip(int flags)
|
||||
return flgs;
|
||||
}
|
||||
|
||||
#ifdef ARCH_MM_MMU
|
||||
static int copy_msghdr_from_user(struct msghdr *kmsg, struct msghdr *umsg,
|
||||
struct iovec **out_iov, void **out_msg_control)
|
||||
{
|
||||
size_t iovs_size;
|
||||
struct iovec *uiov, *kiov;
|
||||
size_t iovs_buffer_size = 0;
|
||||
void *iovs_buffer;
|
||||
|
||||
if (!lwp_user_accessable(umsg, sizeof(*umsg)))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
lwp_get_from_user(kmsg, umsg, sizeof(*kmsg));
|
||||
|
||||
iovs_size = sizeof(*kmsg->msg_iov) * kmsg->msg_iovlen;
|
||||
if (!lwp_user_accessable(kmsg->msg_iov, iovs_size))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* user and kernel */
|
||||
kiov = kmem_get(iovs_size * 2);
|
||||
if (!kiov)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
uiov = (void *)kiov + iovs_size;
|
||||
lwp_get_from_user(uiov, kmsg->msg_iov, iovs_size);
|
||||
|
||||
if (out_iov)
|
||||
{
|
||||
*out_iov = uiov;
|
||||
}
|
||||
kmsg->msg_iov = kiov;
|
||||
|
||||
for (int i = 0; i < kmsg->msg_iovlen; ++i)
|
||||
{
|
||||
/*
|
||||
* We MUST check we can copy data to user after socket done in uiov
|
||||
* otherwise we will be lost the messages from the network!
|
||||
*/
|
||||
if (!lwp_user_accessable(uiov->iov_base, uiov->iov_len))
|
||||
{
|
||||
kmem_put(kmsg->msg_iov);
|
||||
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
iovs_buffer_size += uiov->iov_len;
|
||||
kiov->iov_len = uiov->iov_len;
|
||||
|
||||
++kiov;
|
||||
++uiov;
|
||||
}
|
||||
|
||||
/* msg_iov and msg_control */
|
||||
iovs_buffer = kmem_get(iovs_buffer_size + kmsg->msg_controllen);
|
||||
|
||||
if (!iovs_buffer)
|
||||
{
|
||||
kmem_put(kmsg->msg_iov);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
kiov = kmsg->msg_iov;
|
||||
|
||||
for (int i = 0; i < kmsg->msg_iovlen; ++i)
|
||||
{
|
||||
kiov->iov_base = iovs_buffer;
|
||||
iovs_buffer += kiov->iov_len;
|
||||
++kiov;
|
||||
}
|
||||
|
||||
*out_msg_control = kmsg->msg_control;
|
||||
/* msg_control is the end of the iovs_buffer */
|
||||
kmsg->msg_control = iovs_buffer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* ARCH_MM_MMU */
|
||||
|
||||
sysret_t sys_recvmsg(int socket, struct msghdr *msg, int flags)
|
||||
{
|
||||
int flgs, ret = -1;
|
||||
struct msghdr kmsg;
|
||||
#ifdef ARCH_MM_MMU
|
||||
void *msg_control;
|
||||
struct iovec *uiov, *kiov;
|
||||
#endif
|
||||
|
||||
if (!msg)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
flgs = netflags_muslc_2_lwip(flags);
|
||||
|
||||
#ifdef ARCH_MM_MMU
|
||||
ret = copy_msghdr_from_user(&kmsg, msg, &uiov, &msg_control);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
ret = recvmsg(socket, &kmsg, flgs);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
goto _free_res;
|
||||
}
|
||||
|
||||
kiov = kmsg.msg_iov;
|
||||
|
||||
for (int i = 0; i < kmsg.msg_iovlen; ++i)
|
||||
{
|
||||
lwp_put_to_user(uiov->iov_base, kiov->iov_base, kiov->iov_len);
|
||||
|
||||
++kiov;
|
||||
++uiov;
|
||||
}
|
||||
|
||||
lwp_put_to_user(msg_control, kmsg.msg_control, kmsg.msg_controllen);
|
||||
lwp_put_to_user(&msg->msg_flags, &kmsg.msg_flags, sizeof(kmsg.msg_flags));
|
||||
|
||||
_free_res:
|
||||
kmem_put(kmsg.msg_iov->iov_base);
|
||||
kmem_put(kmsg.msg_iov);
|
||||
}
|
||||
#else
|
||||
rt_memcpy(&kmsg, msg, sizeof(kmsg));
|
||||
|
||||
ret = recvmsg(socket, &kmsg, flgs);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
msg->msg_flags = kmsg.msg_flags;
|
||||
}
|
||||
#endif /* ARCH_MM_MMU */
|
||||
|
||||
return (ret < 0 ? GET_ERRNO() : ret);
|
||||
}
|
||||
|
||||
sysret_t sys_recvfrom(int socket, void *mem, size_t len, int flags,
|
||||
struct musl_sockaddr *from, socklen_t *fromlen)
|
||||
{
|
||||
@@ -3633,6 +3777,57 @@ sysret_t sys_recv(int socket, void *mem, size_t len, int flags)
|
||||
return (ret < 0 ? GET_ERRNO() : ret);
|
||||
}
|
||||
|
||||
sysret_t sys_sendmsg(int socket, const struct msghdr *msg, int flags)
|
||||
{
|
||||
int flgs, ret = -1;
|
||||
struct msghdr kmsg;
|
||||
#ifdef ARCH_MM_MMU
|
||||
void *msg_control;
|
||||
struct iovec *uiov, *kiov;
|
||||
#endif
|
||||
if (!msg)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
flgs = netflags_muslc_2_lwip(flags);
|
||||
|
||||
#ifdef ARCH_MM_MMU
|
||||
ret = copy_msghdr_from_user(&kmsg, (struct msghdr *)msg, &uiov, &msg_control);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
kiov = kmsg.msg_iov;
|
||||
|
||||
for (int i = 0; i < kmsg.msg_iovlen; ++i)
|
||||
{
|
||||
lwp_get_from_user(kiov->iov_base, uiov->iov_base, kiov->iov_len);
|
||||
|
||||
++kiov;
|
||||
++uiov;
|
||||
}
|
||||
|
||||
lwp_get_from_user(kmsg.msg_control, msg_control, kmsg.msg_controllen);
|
||||
|
||||
ret = sendmsg(socket, &kmsg, flgs);
|
||||
|
||||
kmem_put(kmsg.msg_iov->iov_base);
|
||||
kmem_put(kmsg.msg_iov);
|
||||
}
|
||||
#else
|
||||
rt_memcpy(&kmsg, msg, sizeof(kmsg));
|
||||
|
||||
ret = sendmsg(socket, &kmsg, flgs);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
msg->msg_flags = kmsg.msg_flags;
|
||||
}
|
||||
#endif /* ARCH_MM_MMU */
|
||||
|
||||
return (ret < 0 ? GET_ERRNO() : ret);
|
||||
}
|
||||
|
||||
sysret_t sys_sendto(int socket, const void *dataptr, size_t size, int flags,
|
||||
const struct musl_sockaddr *to, socklen_t tolen)
|
||||
{
|
||||
@@ -3757,6 +3952,30 @@ out:
|
||||
return (fd < 0 ? GET_ERRNO() : fd);
|
||||
}
|
||||
|
||||
sysret_t sys_socketpair(int domain, int type, int protocol, int fd[2])
|
||||
{
|
||||
#ifdef RT_USING_SAL
|
||||
int ret = 0;
|
||||
int k_fd[2];
|
||||
|
||||
if (!lwp_user_accessable((void *)fd, sizeof(int [2])))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = socketpair(domain, type, protocol, k_fd);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
lwp_put_to_user(fd, k_fd, sizeof(int [2]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ELIBACC;
|
||||
#endif
|
||||
}
|
||||
|
||||
sysret_t sys_closesocket(int socket)
|
||||
{
|
||||
return closesocket(socket);
|
||||
@@ -6688,8 +6907,8 @@ const static struct rt_syscall_def func_table[] =
|
||||
SYSCALL_NET(SYSCALL_SIGN(sys_getaddrinfo)),
|
||||
SYSCALL_NET(SYSCALL_SIGN(sys_gethostbyname2_r)), /* 85 */
|
||||
|
||||
SYSCALL_SIGN(sys_notimpl), //network,
|
||||
SYSCALL_SIGN(sys_notimpl), //network,
|
||||
SYSCALL_NET(SYSCALL_SIGN(sys_sendmsg)),
|
||||
SYSCALL_NET(SYSCALL_SIGN(sys_recvmsg)),
|
||||
SYSCALL_SIGN(sys_notimpl), //network,
|
||||
SYSCALL_SIGN(sys_notimpl), //network,
|
||||
SYSCALL_SIGN(sys_notimpl), //network, /* 90 */
|
||||
@@ -6826,6 +7045,8 @@ const static struct rt_syscall_def func_table[] =
|
||||
SYSCALL_SIGN(sys_ftruncate),
|
||||
SYSCALL_SIGN(sys_setitimer),
|
||||
SYSCALL_SIGN(sys_utimensat),
|
||||
SYSCALL_SIGN(sys_notimpl),
|
||||
SYSCALL_SIGN(sys_socketpair), /* 205 */
|
||||
};
|
||||
|
||||
const void *lwp_get_sys_api(rt_uint32_t number)
|
||||
|
||||
Reference in New Issue
Block a user