diff options
-rw-r--r-- | linux-user/syscall.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 280137da8c..29bac79b61 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2352,6 +2352,45 @@ static abi_long do_getsockopt(int sockfd, int level, int optname, break; } break; + case SOL_IPV6: + switch (optname) { + case IPV6_MTU_DISCOVER: + case IPV6_MTU: + case IPV6_V6ONLY: + case IPV6_RECVPKTINFO: + case IPV6_UNICAST_HOPS: + case IPV6_MULTICAST_HOPS: + case IPV6_MULTICAST_LOOP: + case IPV6_RECVERR: + case IPV6_RECVHOPLIMIT: + case IPV6_2292HOPLIMIT: + case IPV6_CHECKSUM: + if (get_user_u32(len, optlen)) + return -TARGET_EFAULT; + if (len < 0) + return -TARGET_EINVAL; + lv = sizeof(lv); + ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); + if (ret < 0) + return ret; + if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) { + len = 1; + if (put_user_u32(len, optlen) + || put_user_u8(val, optval_addr)) + return -TARGET_EFAULT; + } else { + if (len > sizeof(int)) + len = sizeof(int); + if (put_user_u32(len, optlen) + || put_user_u32(val, optval_addr)) + return -TARGET_EFAULT; + } + break; + default: + ret = -TARGET_ENOPROTOOPT; + break; + } + break; default: unimplemented: gemu_log("getsockopt level=%d optname=%d not yet supported\n", |