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
 
_______________________________________________
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel

Reply via email to