for some socket operations and trivial compiler warning fix
PATCH 1/1 for some socket operations and trivial compiler warning fix
The patch should add support for SO_LINGER, SO_RCVTIMEO, SO_SNDTIMEO, SO_PEERCRED and SO_PEERNAME.
Index: linux-user/syscall.c
===================================================================
RCS file: /sources/qemu/qemu/linux-user/syscall.c,v retrieving revision 1.75
syscall.c +93 -17
@@ -509,20 +509,28 @@ msgh->msg_controllen =tswapl (space); } +static long do_setsockopt_timehelper (int sockfd,int level,int optname, +target_ulong optval,target_ulong optlen) +{ +int len; +struct timeval tv; +if (get_user (len, &optlen) || + !access_ok (VERIFY_READ ,optval,sizeof (struct target_timeval ))) +return -EFAULT ; + +if (len !=sizeof (struct target_timeval )) +return -EINVAL ; + +target_to_host_timeval (&tv,optval); +return get_errno (setsockopt (sockfd, level, optname, &tv,sizeof (struct timeval ))); +} +static long do_setsockopt (int sockfd,int level,int optname,target_ulong optval,socklen_t optlen) {int val, ret;switch (level) { -case SOL_TCP : -/* TCP options all take an 'int' value. */ -if (optlen <sizeof (uint32_t )) -return -EINVAL ; - - val =tget32 (optval); - ret =get_errno (setsockopt (sockfd, level, optname, &val,sizeof (val))); -break ;case SOL_IP :switch (optname) {case IP_TOS :
@@ -606,20 +614,39 @@ optname =SO_RCVLOWAT ;break ;case TARGET_SO_RCVTIMEO : - optname =SO_RCVTIMEO ; + ret =do_setsockopt_timehelper (sockfd,level,SO_RCVTIMEO ,optval,optlen);break ;case TARGET_SO_SNDTIMEO : - optname =SO_SNDTIMEO ; + ret =do_setsockopt_timehelper (sockfd,level,SO_SNDTIMEO ,optval,optlen);break ; +case TARGET_SO_LINGER : { +struct linger tmp; +struct linger *target = (struct linger *) optval; +if (optlen ==sizeof (struct linger ) && +get_user (tmp.l_onoff,&target->l_onoff) && +get_user (tmp.l_linger,&target->l_linger)) { + ret =get_errno (setsockopt (sockfd, level,SO_LINGER , &tmp,sizeof (struct linger ))); + }else { +/* Just to make strace look better */ + ret =get_errno (setsockopt (sockfd, level,SO_LINGER , &optval,optlen)); + } +return ret; +break ; + }break ;default : goto unimplemented; } -if (optlen <sizeof (uint32_t )) -return -EINVAL ; - - val =tget32 (optval); - ret =get_errno (setsockopt (sockfd,SOL_SOCKET , optname, &val,sizeof (val))); + goto int_case; +break ; +case SOL_TCP : + int_case: +/* TCP options all take an 'int' value. */ +if (optlen <sizeof (uint32_t )) +return -EINVAL ; + + val =tget32 (optval); + ret =get_errno (setsockopt (sockfd, level, optname, &val,sizeof (val)));break ;default : unimplemented:
@@ -629,6 +656,40 @@return ret; } +static long do_getsockopt_structhelper (int sockfd,int level,int optname, +target_ulong optval,target_ulong optlen) +{ +int ret,len,i; +/* Let's assume 32-bit parameters */ +if (get_user (len, &optlen)) +return -EFAULT ; +if (len <0 ) +return -EINVAL ; + ret =get_errno (getsockopt (sockfd, level, optname, &optval, &len)); +for (i =0 ; i < len && optval !=0 ; i +=4 ) { +/* This could propably be done more efficiently */ +tput32 (optval + i, optval + i); + } +return ret; +} + +static long do_getsockopt_timehelper (int sockfd,int level,int optname, +target_ulong optval,target_ulong optlen) +{ +int ret,len; +struct timeval tv; +static socklen_t olen=sizeof (struct timeval ); +if (get_user (len, &optlen)) +return -EFAULT ; +if (len !=sizeof (struct target_timeval )) +return -EINVAL ; + ret =get_errno (getsockopt (sockfd, level, optname, &tv, &olen)); +if (ret==0 ) { +host_to_target_timeval (optval,&tv); + } +return ret; +} +static long do_getsockopt (int sockfd,int level,int optname,target_ulong optval,target_ulong optlen) {
@@ -638,13 +699,28 @@case TARGET_SOL_SOCKET : level =SOL_SOCKET ;switch (optname) { +/* These don't just return a single integer */ case TARGET_SO_LINGER : + ret =do_getsockopt_structhelper (sockfd,level,SO_LINGER ,optval,optlen); +break ;case TARGET_SO_RCVTIMEO : + ret =do_getsockopt_timehelper (sockfd,level,SO_RCVTIMEO ,optval,optlen); +break ;case TARGET_SO_SNDTIMEO : + ret =do_getsockopt_timehelper (sockfd,level,SO_SNDTIMEO ,optval,optlen); +break ;case TARGET_SO_PEERCRED : + ret =do_getsockopt_structhelper (sockfd,level,SO_PEERCRED ,optval,optlen); +break ;case TARGET_SO_PEERNAME : -/* These don't just return a single integer */ - goto unimplemented; +if (get_user (len, &optlen)) +return -EFAULT ; +if (len <0 ) +return -EINVAL ; + ret =get_errno (getsockopt (sockfd, level, optname, &optval, &len)); +if (put_user (len, &optlen)) +return -EFAULT ; +break ;default : goto int_case; }
Index: linux-user/syscall.c
===================================================================
RCS file: /sources/qemu/qemu/linux-user/syscall.c,v retrieving revision 1.75
syscall.c +8 -0
@@ -1054,6 +1141,13 @@/* XXX: suppress this function and call directly the related socket functions */ +#if defined(TARGET_NR_accept) || defined(TARGET_NR_getpeername) || \ + defined(TARGET_NR_getsockname) || defined(TARGET_NR_listen) || \ + defined(TARGET_NR_recv) || defined(TARGET_NR_recvfrom) || \ + defined(TARGET_NR_recvmsg) || defined(TARGET_NR_send) || \ + defined(TARGET_NR_sendto) || defined(TARGET_NR_shutdown) || \ + defined(TARGET_NR_socketpair) +static long do_socketcallwrapper (int num,long arg1,long arg2,long arg3,long arg4,long arg5,long arg6) {
@@ -1068,6 +1162,7 @@ return do_socketcall(num, (target_ulong) args); } +#endif #define N_SHM_REGIONS 32