Skip to content

add accept4 support, and LINUX_SOCK_CLOEXEC/LINUX_SOCK_NONBLOCK support for ff_socket #878

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions adapter/syscall/ff_hook_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ static __thread struct ff_getsockname_args *getsockname_args = NULL;
static __thread struct ff_getpeername_args *getpeername_args = NULL;
static __thread struct ff_setsockopt_args *setsockopt_args = NULL;
static __thread struct ff_accept_args *accept_args = NULL;
static __thread struct ff_accept4_args *accept4_args = NULL;
static __thread struct ff_connect_args *connect_args = NULL;
static __thread struct ff_recvfrom_args *recvfrom_args = NULL;
static __thread struct ff_recvmsg_args *recvmsg_args = NULL;
Expand Down Expand Up @@ -680,8 +681,62 @@ ff_hook_accept4(int fd, struct sockaddr *addr,

CHECK_FD_OWNERSHIP(accept4, (fd, addr, addrlen, flags));

errno = ENOSYS;
return -1;
DEFINE_REQ_ARGS_STATIC(accept4);
static __thread struct sockaddr *sh_addr = NULL;
static __thread socklen_t sh_addr_len = 0;
static __thread socklen_t *sh_addrlen = NULL;

if (addr != NULL) {
if (sh_addr == NULL || sh_addr_len < *addrlen) {
if(sh_addr) {
share_mem_free(sh_addr);
}

sh_addr_len = *addrlen;
sh_addr = share_mem_alloc(sh_addr_len);
if (sh_addr == NULL) {
RETURN_ERROR_NOFREE(ENOMEM);
}
}

if (sh_addrlen == NULL) {
sh_addrlen = share_mem_alloc(sizeof(socklen_t));
if (sh_addrlen == NULL) {
//share_mem_free(sh_addr); // Don't free
RETURN_ERROR_NOFREE(ENOMEM);
}
}
*sh_addrlen = *addrlen;

args->addr = sh_addr;
args->addrlen = sh_addrlen;
args->flags = flags;
}else {
args->addr = NULL;
args->addrlen = NULL;
args->flags = flags;
}

args->fd = fd;

SYSCALL(FF_SO_ACCEPT4, args);

if (ret > 0) {
ret = convert_fstack_fd(ret);
}

if (addr) {
if (ret > 0) {
socklen_t cplen = *sh_addrlen > *addrlen ?
*addrlen : *sh_addrlen;
rte_memcpy(addr, sh_addr, cplen);
*addrlen = *sh_addrlen;
}
//share_mem_free(sh_addr); // Don't free
//share_mem_free(sh_addrlen);
}

RETURN_NOFREE();
}

int
Expand Down
3 changes: 1 addition & 2 deletions adapter/syscall/ff_socket_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,7 @@ ff_sys_accept(struct ff_accept_args *args)
static int
ff_sys_accept4(struct ff_accept4_args *args)
{
errno = ENOSYS;
return -1;
return ff_accept4(args->fd, args->addr, args->addrlen, args->flags);
}

static int
Expand Down
1 change: 1 addition & 0 deletions lib/ff_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ int ff_getsockopt(int s, int level, int optname, void *optval,
int ff_listen(int s, int backlog);
int ff_bind(int s, const struct linux_sockaddr *addr, socklen_t addrlen);
int ff_accept(int s, struct linux_sockaddr *addr, socklen_t *addrlen);
int ff_accept4(int s, struct linux_sockaddr *addr, socklen_t *addrlen, int flags);
int ff_connect(int s, const struct linux_sockaddr *name, socklen_t namelen);
int ff_close(int fd);
int ff_shutdown(int s, int how);
Expand Down
1 change: 1 addition & 0 deletions lib/ff_api.symlist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ff_fcntl
ff_socketpair
ff_poll
ff_accept
ff_accept4
ff_listen
ff_bind
ff_connect
Expand Down
53 changes: 52 additions & 1 deletion lib/ff_syscall_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@

/* af define end */

/* Flags for socket, socketpair, accept4 */

#define LINUX_SOCK_CLOEXEC LINUX_O_CLOEXEC
#define LINUX_SOCK_NONBLOCK LINUX_O_NONBLOCK

/* msghdr define start */

static /*__thread*/ struct iovec msg_iov_tmp[UIO_MAXIOV];
Expand Down Expand Up @@ -655,6 +660,20 @@ linux2freebsd_opt(int level, int optname)
}
}

static int
linux2freebsd_socket_flags(int flags)
{
if (flags & LINUX_SOCK_NONBLOCK) {
flags &= ~LINUX_SOCK_NONBLOCK;
flags |= SOCK_NONBLOCK;
}
if (flags & LINUX_SOCK_CLOEXEC) {
flags &= ~LINUX_SOCK_CLOEXEC;
flags |= SOCK_CLOEXEC;
}
return flags;
}

static void
linux2freebsd_sockaddr(const struct linux_sockaddr *linux,
socklen_t addrlen, struct sockaddr *freebsd)
Expand Down Expand Up @@ -880,7 +899,7 @@ ff_socket(int domain, int type, int protocol)
int rc;
struct socket_args sa;
sa.domain = domain == LINUX_AF_INET6 ? AF_INET6 : domain;
sa.type = type;
sa.type = linux2freebsd_socket_flags(type);
sa.protocol = protocol;
if ((rc = sys_socket(curthread, &sa)))
goto kern_fail;
Expand Down Expand Up @@ -1352,6 +1371,38 @@ ff_accept(int s, struct linux_sockaddr * addr,
return (-1);
}

int
ff_accept4(int s, struct linux_sockaddr * addr,
socklen_t * addrlen, int flags)
{
int rc;
struct file *fp;
struct sockaddr *pf = NULL;
socklen_t socklen = sizeof(struct sockaddr_storage);

if ((rc = kern_accept4(curthread, s, &pf, &socklen, linux2freebsd_socket_flags(flags), &fp)))
goto kern_fail;

rc = curthread->td_retval[0];
fdrop(fp, curthread);

if (addr && pf)
freebsd2linux_sockaddr(addr, pf);

if (addrlen)
*addrlen = pf->sa_len;

if(pf != NULL)
free(pf, M_SONAME);
return (rc);

kern_fail:
if(pf != NULL)
free(pf, M_SONAME);
ff_os_errno(rc);
return (-1);
}

int
ff_listen(int s, int backlog)
{
Expand Down