diff options
author | Andreas Schwab <schwab@suse.de> | 2019-05-13 11:06:26 +0200 |
---|---|---|
committer | Laurent Vivier <laurent@vivier.eu> | 2020-02-19 11:17:40 +0100 |
commit | 405dc4cfc62a7c526405c8aba9152c2ac19b588e (patch) | |
tree | cf1a5541791abf4b22dce6bcf5e31fbdc12c5771 /linux-user | |
parent | 8500476f3cc4d9e1f710290be9fcf86429dd8dda (diff) |
linux-user: implement getsockopt SO_RCVTIMEO and SO_SNDTIMEO
Signed-off-by: Andreas Schwab <schwab@suse.de>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <mvmlfzaoh9p.fsf@suse.de>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/syscall.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 7aaa9d9639..9fa722f238 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2310,10 +2310,42 @@ static abi_long do_getsockopt(int sockfd, int level, int optname, level = SOL_SOCKET; switch (optname) { /* These don't just return a single integer */ - case TARGET_SO_RCVTIMEO: - case TARGET_SO_SNDTIMEO: case TARGET_SO_PEERNAME: goto unimplemented; + case TARGET_SO_RCVTIMEO: { + struct timeval tv; + socklen_t tvlen; + + optname = SO_RCVTIMEO; + +get_timeout: + if (get_user_u32(len, optlen)) { + return -TARGET_EFAULT; + } + if (len < 0) { + return -TARGET_EINVAL; + } + + tvlen = sizeof(tv); + ret = get_errno(getsockopt(sockfd, level, optname, + &tv, &tvlen)); + if (ret < 0) { + return ret; + } + if (len > sizeof(struct target_timeval)) { + len = sizeof(struct target_timeval); + } + if (copy_to_user_timeval(optval_addr, &tv)) { + return -TARGET_EFAULT; + } + if (put_user_u32(len, optlen)) { + return -TARGET_EFAULT; + } + break; + } + case TARGET_SO_SNDTIMEO: + optname = SO_SNDTIMEO; + goto get_timeout; case TARGET_SO_PEERCRED: { struct ucred cr; socklen_t crlen; |