qemu-devel
[Top][All Lists]
Advanced

[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
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]