diff mbox

[3/3] linux-user: add SO_LINGER to getsockopt

Message ID 20170919230643.87425-3-carenas@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Carlo Marcelo Arenas Belón Sept. 19, 2017, 11:06 p.m. UTC
Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
---
 linux-user/syscall.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

Comments

Laurent Vivier Sept. 20, 2017, 9:09 a.m. UTC | #1
Le 20/09/2017 à 01:06, Carlo Marcelo Arenas Belón a écrit :
> Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
> ---
>  linux-user/syscall.c | 34 +++++++++++++++++++++++++++++++++-
>  1 file changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index ad689dad50..91bd27c63a 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -3178,7 +3178,6 @@ 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_LINGER:
>          case TARGET_SO_RCVTIMEO:
>          case TARGET_SO_SNDTIMEO:
>          case TARGET_SO_PEERNAME:
> @@ -3216,6 +3215,39 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
>              }
>              break;
>          }
> +        case TARGET_SO_LINGER:
> +        {
> +            struct linger lg;
> +            socklen_t lglen;
> +            struct target_linger *tlg;
> +
> +            if (get_user_u32(len, optlen)) {
> +                return -TARGET_EFAULT;
> +            }
> +            if (len < 0) {
> +                return -TARGET_EINVAL;
> +            }
> +
> +            lglen = sizeof(lg);
> +            ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
> +                                       &lg, &lglen));
> +            if (ret < 0) {
> +                return ret;
> +            }
> +            if (len > lglen) {
> +                len = lglen;
> +            }
> +            if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
> +                return -TARGET_EFAULT;
> +            }
> +            __put_user(lg.l_onoff, &tlg->l_onoff);
> +            __put_user(lg.l_linger, &tlg->l_linger);
> +            unlock_user_struct(tlg, optval_addr, 1);
> +            if (put_user_u32(len, optlen)) {
> +                return -TARGET_EFAULT;
> +            }
> +            break;
> +        }
>          /* Options with 'int' argument.  */
>          case TARGET_SO_DEBUG:
>              optname = SO_DEBUG;
> 

You should merge PATCH 2/3 and PATCH 3/3.

Reviewed-by: Laurent Vivier <laurent@vivier.eu>
diff mbox

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ad689dad50..91bd27c63a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3178,7 +3178,6 @@  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_LINGER:
         case TARGET_SO_RCVTIMEO:
         case TARGET_SO_SNDTIMEO:
         case TARGET_SO_PEERNAME:
@@ -3216,6 +3215,39 @@  static abi_long do_getsockopt(int sockfd, int level, int optname,
             }
             break;
         }
+        case TARGET_SO_LINGER:
+        {
+            struct linger lg;
+            socklen_t lglen;
+            struct target_linger *tlg;
+
+            if (get_user_u32(len, optlen)) {
+                return -TARGET_EFAULT;
+            }
+            if (len < 0) {
+                return -TARGET_EINVAL;
+            }
+
+            lglen = sizeof(lg);
+            ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
+                                       &lg, &lglen));
+            if (ret < 0) {
+                return ret;
+            }
+            if (len > lglen) {
+                len = lglen;
+            }
+            if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
+                return -TARGET_EFAULT;
+            }
+            __put_user(lg.l_onoff, &tlg->l_onoff);
+            __put_user(lg.l_linger, &tlg->l_linger);
+            unlock_user_struct(tlg, optval_addr, 1);
+            if (put_user_u32(len, optlen)) {
+                return -TARGET_EFAULT;
+            }
+            break;
+        }
         /* Options with 'int' argument.  */
         case TARGET_SO_DEBUG:
             optname = SO_DEBUG;