[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] for some socket operations and trivial compiler war
From: |
Pablo Virolainen |
Subject: |
[Qemu-devel] [PATCH] for some socket operations and trivial compiler warning fix |
Date: |
Thu, 13 Jul 2006 15:50:21 +0300 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.13) Gecko/20060427 Debian/1.7.13-0ubuntu5.10 |
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
diff -u -r1.75 syscall.c
--- linux-user/syscall.c 27 Jun 2006 21:08:10 -0000 1.75
+++ linux-user/syscall.c 13 Jul 2006 10:00:09 -0000
@@ -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
diff -u -r1.75 syscall.c
--- linux-user/syscall.c 27 Jun 2006 21:08:10 -0000 1.75
+++ linux-user/syscall.c 13 Jul 2006 10:00:09 -0000
@@ -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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] for some socket operations and trivial compiler warning fix,
Pablo Virolainen <=