summary refs log tree commit diff stats
path: root/linux-user/syscall.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-07-23 15:10:20 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-07-23 15:10:20 +0000
commit2efbe911d3ea518f5d4648954379f9d5aa02e806 (patch)
treecd03eb65457d54d9f2ed13c88a74b37a3c98d8d9 /linux-user/syscall.c
parent667f38b167caebb38a16aef6df56db0dcb34d684 (diff)
downloadfocaccia-qemu-2efbe911d3ea518f5d4648954379f9d5aa02e806.tar.gz
focaccia-qemu-2efbe911d3ea518f5d4648954379f9d5aa02e806.zip
more set/getsockopt values
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1516 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r--linux-user/syscall.c78
1 files changed, 71 insertions, 7 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5a6d3821f5..e51f513532 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -547,7 +547,21 @@ static long do_setsockopt(int sockfd, int level, int optname,
         break;
     case SOL_IP:
         switch(optname) {
+        case IP_TOS:
+        case IP_TTL:
         case IP_HDRINCL:
+        case IP_ROUTER_ALERT:
+        case IP_RECVOPTS:
+        case IP_RETOPTS:
+        case IP_PKTINFO:
+        case IP_MTU_DISCOVER:
+        case IP_RECVERR:
+        case IP_RECVTOS:
+#ifdef IP_FREEBIND
+        case IP_FREEBIND:
+#endif
+        case IP_MULTICAST_TTL:
+        case IP_MULTICAST_LOOP:
             val = 0;
             if (optlen >= sizeof(uint32_t)) {
                 if (get_user(val, (uint32_t *)optval))
@@ -619,6 +633,45 @@ static long do_getsockopt(int sockfd, int level, int optname,
 	    /* These don't just return a single integer */
 	    goto unimplemented;
         default:
+            goto int_case;
+        }
+        break;
+    case SOL_TCP:
+        /* TCP options all take an 'int' value.  */
+    int_case:
+        if (get_user(len, optlen))
+            return -EFAULT;
+        if (len < 0)
+            return -EINVAL;
+        lv = sizeof(int);
+        ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
+        if (ret < 0)
+            return ret;
+        val = tswap32(val);
+        if (len > lv)
+            len = lv;
+        if (copy_to_user(optval, &val, len))
+            return -EFAULT;
+        if (put_user(len, optlen))
+            return -EFAULT;
+        break;
+    case SOL_IP:
+        switch(optname) {
+        case IP_TOS:
+        case IP_TTL:
+        case IP_HDRINCL:
+        case IP_ROUTER_ALERT:
+        case IP_RECVOPTS:
+        case IP_RETOPTS:
+        case IP_PKTINFO:
+        case IP_MTU_DISCOVER:
+        case IP_RECVERR:
+        case IP_RECVTOS:
+#ifdef IP_FREEBIND
+        case IP_FREEBIND:
+#endif
+        case IP_MULTICAST_TTL:
+        case IP_MULTICAST_LOOP:
             if (get_user(len, optlen))
                 return -EFAULT;
             if (len < 0)
@@ -627,14 +680,25 @@ static long do_getsockopt(int sockfd, int level, int optname,
             ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
             if (ret < 0)
                 return ret;
-            val = tswap32(val);
-            if (len > lv)
-                len = lv;
-            if (copy_to_user(optval, &val, len))
-                return -EFAULT;
-            if (put_user(len, optlen))
-                return -EFAULT;
+            if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
+                unsigned char ucval = val;
+                len = 1;
+		if (put_user(len, optlen))
+                    return -EFAULT;
+		if (copy_to_user(optval,&ucval,1))
+                    return -EFAULT;
+            } else {
+                val = tswap32(val);
+                if (len > sizeof(int))
+                    len = sizeof(int);
+                if (put_user(len, optlen))
+                    return -EFAULT;
+                if (copy_to_user(optval, &val, len))
+                    return -EFAULT;
+            }
             break;
+        default:
+            goto unimplemented;
         }
         break;
     default: