aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@suse.de>2019-05-13 11:06:26 +0200
committerLaurent Vivier <laurent@vivier.eu>2020-02-19 11:17:40 +0100
commit405dc4cfc62a7c526405c8aba9152c2ac19b588e (patch)
treecf1a5541791abf4b22dce6bcf5e31fbdc12c5771 /linux-user
parent8500476f3cc4d9e1f710290be9fcf86429dd8dda (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.c36
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;