]> git.proxmox.com Git - qemu.git/commitdiff
linux-user: add SIOCADDRT/SIOCDELRT support
authorLaurent Vivier <laurent@vivier.eu>
Tue, 2 Jul 2013 13:04:12 +0000 (14:04 +0100)
committerRiku Voipio <riku.voipio@linaro.org>
Fri, 5 Jul 2013 12:45:40 +0000 (15:45 +0300)
This allows to pass the device name.

You can test this with the "route" command.

WITHOUT this patch:

$ sudo route add -net default gw 10.0.3.1 eth0
SIOCADDRT: Bad address
$ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Ifa
10.0.3.0        0.0.0.0         255.255.255.0   U         0 0          0 eth

WITH this patch:

$ sudo route add -net default gw 10.0.3.1 eth0
$ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Ifa
0.0.0.0         10.0.3.1        0.0.0.0         UG        0 0          0 eth
10.0.3.0        0.0.0.0         255.255.255.0   U         0 0          0 eth

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
linux-user/ioctls.h
linux-user/syscall.c

index 8a4776756a247dfae8b8e48a9e0a977209d7e9d0..439c2a9e32fe81cfe490ac51ec409d029f63bcdb 100644 (file)
@@ -88,8 +88,6 @@
 #endif
 
   IOCTL(SIOCATMARK, 0, TYPE_NULL)
-  IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
-  IOCTL(SIOCDELRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
   IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT))
   IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
   IOCTL(SIOCSIFFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
                 MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
   IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm,
                 MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(SIOCADDRT, IOC_W, do_ioctl_rt,
+                MK_PTR(MK_STRUCT(STRUCT_rtentry)))
+  IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
+                MK_PTR(MK_STRUCT(STRUCT_rtentry)))
index ed2c9305b1347e38bf82611ee191ea9012d49e42..4b134dda57c128840f54bce6141a068274cd4db7 100644 (file)
@@ -105,6 +105,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #include <linux/vt.h>
 #include <linux/dm-ioctl.h>
 #include <linux/reboot.h>
+#include <linux/route.h>
 #include "linux_loop.h"
 #include "cpu-uname.h"
 
@@ -3551,6 +3552,69 @@ out:
     return ret;
 }
 
+static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
+                                int fd, abi_long cmd, abi_long arg)
+{
+    const argtype *arg_type = ie->arg_type;
+    const StructEntry *se;
+    const argtype *field_types;
+    const int *dst_offsets, *src_offsets;
+    int target_size;
+    void *argptr;
+    abi_ulong *target_rt_dev_ptr;
+    unsigned long *host_rt_dev_ptr;
+    abi_long ret;
+    int i;
+
+    assert(ie->access == IOC_W);
+    assert(*arg_type == TYPE_PTR);
+    arg_type++;
+    assert(*arg_type == TYPE_STRUCT);
+    target_size = thunk_type_size(arg_type, 0);
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        return -TARGET_EFAULT;
+    }
+    arg_type++;
+    assert(*arg_type == (int)STRUCT_rtentry);
+    se = struct_entries + *arg_type++;
+    assert(se->convert[0] == NULL);
+    /* convert struct here to be able to catch rt_dev string */
+    field_types = se->field_types;
+    dst_offsets = se->field_offsets[THUNK_HOST];
+    src_offsets = se->field_offsets[THUNK_TARGET];
+    for (i = 0; i < se->nb_fields; i++) {
+        if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
+            assert(*field_types == TYPE_PTRVOID);
+            target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
+            host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
+            if (*target_rt_dev_ptr != 0) {
+                *host_rt_dev_ptr = (unsigned long)lock_user_string(
+                                                  tswapal(*target_rt_dev_ptr));
+                if (!*host_rt_dev_ptr) {
+                    unlock_user(argptr, arg, 0);
+                    return -TARGET_EFAULT;
+                }
+            } else {
+                *host_rt_dev_ptr = 0;
+            }
+            field_types++;
+            continue;
+        }
+        field_types = thunk_convert(buf_temp + dst_offsets[i],
+                                    argptr + src_offsets[i],
+                                    field_types, THUNK_HOST);
+    }
+    unlock_user(argptr, arg, 0);
+
+    ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+    if (*host_rt_dev_ptr != 0) {
+        unlock_user((void *)*host_rt_dev_ptr,
+                    *target_rt_dev_ptr, 0);
+    }
+    return ret;
+}
+
 static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, ...) \
     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },