mirror of
https://gitlab.com/qemu-project/qemu.git
synced 2026-10-28 14:04:39 +08:00
Add bsd-socket.c with target_to_host_sockaddr, host_to_target_sockaddr, and target_to_host_ip_mreq helper functions, and add it to the build. Signed-off-by: Stacey Son <sson@FreeBSD.org> Assisted-by: Claude Opus 4.6 (1M context) Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com> Acked-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Warner Losh <imp@bsdimp.com>
99 lines
2.7 KiB
C
99 lines
2.7 KiB
C
/*
|
|
* BSD socket system call related helpers
|
|
*
|
|
* Copyright (c) 2013 Stacey D. Son
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
#include "qemu/osdep.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include "qemu.h"
|
|
#include "qemu-bsd.h"
|
|
|
|
/*
|
|
* socket conversion
|
|
*/
|
|
abi_long target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
|
|
socklen_t len)
|
|
{
|
|
const socklen_t unix_maxlen = sizeof(struct sockaddr_un);
|
|
sa_family_t sa_family;
|
|
struct target_sockaddr *target_saddr;
|
|
|
|
target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
|
|
if (target_saddr == 0) {
|
|
return -TARGET_EFAULT;
|
|
}
|
|
|
|
sa_family = target_saddr->sa_family;
|
|
|
|
/*
|
|
* Oops. The caller might send a incomplete sun_path; sun_path
|
|
* must be terminated by \0 (see the manual page), but unfortunately
|
|
* it is quite common to specify sockaddr_un length as
|
|
* "strlen(x->sun_path)" while it should be "strlen(...) + 1". We will
|
|
* fix that here if needed.
|
|
*/
|
|
if (target_saddr->sa_family == AF_UNIX) {
|
|
if (len < unix_maxlen && len > 0) {
|
|
char *cp = (char *)target_saddr;
|
|
|
|
if (cp[len - 1] && !cp[len]) {
|
|
len++;
|
|
}
|
|
}
|
|
if (len > unix_maxlen) {
|
|
len = unix_maxlen;
|
|
}
|
|
}
|
|
|
|
memcpy(addr, target_saddr, len);
|
|
addr->sa_family = sa_family; /* type uint8_t */
|
|
addr->sa_len = target_saddr->sa_len; /* type uint8_t */
|
|
unlock_user(target_saddr, target_addr, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
abi_long host_to_target_sockaddr(abi_ulong target_addr, struct sockaddr *addr,
|
|
socklen_t len)
|
|
{
|
|
struct target_sockaddr *target_saddr;
|
|
|
|
target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
|
|
if (target_saddr == 0) {
|
|
return -TARGET_EFAULT;
|
|
}
|
|
memcpy(target_saddr, addr, len);
|
|
target_saddr->sa_family = addr->sa_family; /* type uint8_t */
|
|
target_saddr->sa_len = addr->sa_len; /* type uint8_t */
|
|
unlock_user(target_saddr, target_addr, len);
|
|
|
|
return 0;
|
|
}
|
|
|
|
abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, abi_ulong target_addr,
|
|
socklen_t len)
|
|
{
|
|
struct target_ip_mreqn *target_smreqn;
|
|
|
|
target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
|
|
if (target_smreqn == 0) {
|
|
return -TARGET_EFAULT;
|
|
}
|
|
mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
|
|
mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
|
|
if (len == sizeof(struct target_ip_mreqn)) {
|
|
mreqn->imr_ifindex = tswap32(target_smreqn->imr_ifindex);
|
|
}
|
|
unlock_user(target_smreqn, target_addr, 0);
|
|
|
|
return 0;
|
|
}
|
|
|