* [Qemu-devel] [PATCH] linux-user: add SIOCADDRT/SIOCDELRT support
@ 2013-05-27 18:48 Laurent Vivier
2013-06-07 18:17 ` Laurent Vivier
2013-06-13 16:53 ` Peter Maydell
0 siblings, 2 replies; 3+ messages in thread
From: Laurent Vivier @ 2013-05-27 18:48 UTC (permalink / raw)
To: Riku Voipio; +Cc: qemu-devel, Laurent Vivier
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>
---
linux-user/ioctls.h | 6 +++--
linux-user/syscall.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 8a47767..439c2a9 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -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)))
@@ -379,3 +377,7 @@
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)))
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1b3c0ed..a5cd166 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -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"
@@ -3714,6 +3715,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__ } },
--
1.8.1.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH] linux-user: add SIOCADDRT/SIOCDELRT support
2013-05-27 18:48 [Qemu-devel] [PATCH] linux-user: add SIOCADDRT/SIOCDELRT support Laurent Vivier
@ 2013-06-07 18:17 ` Laurent Vivier
2013-06-13 16:53 ` Peter Maydell
1 sibling, 0 replies; 3+ messages in thread
From: Laurent Vivier @ 2013-06-07 18:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Riku Voipio
Ping
Le 27/05/2013 20:48, Laurent Vivier a écrit :
> 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>
> ---
> linux-user/ioctls.h | 6 +++--
> linux-user/syscall.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 68 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
> index 8a47767..439c2a9 100644
> --- a/linux-user/ioctls.h
> +++ b/linux-user/ioctls.h
> @@ -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)))
> @@ -379,3 +377,7 @@
> 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)))
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 1b3c0ed..a5cd166 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -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"
>
> @@ -3714,6 +3715,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__ } },
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH] linux-user: add SIOCADDRT/SIOCDELRT support
2013-05-27 18:48 [Qemu-devel] [PATCH] linux-user: add SIOCADDRT/SIOCDELRT support Laurent Vivier
2013-06-07 18:17 ` Laurent Vivier
@ 2013-06-13 16:53 ` Peter Maydell
1 sibling, 0 replies; 3+ messages in thread
From: Peter Maydell @ 2013-06-13 16:53 UTC (permalink / raw)
To: Laurent Vivier; +Cc: Riku Voipio, qemu-devel
On 27 May 2013 19:48, Laurent Vivier <laurent@vivier.eu> wrote:
> 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>
Incidentally, the command works without the patch if the
guest base is zero (eg x86_64-on-x86_64); but now we use
guest base more often so the patch is required.
(Having thunk_convert treat pointers in structs just like
longs, ie simple byteswap, is a bit dubious. I'd be tempted
to put in a warning at least if we hit that code path,
except I suspect we have some current uses which do a
thunk_convert of the whole struct and then fix up the
pointer afterwards.)
thanks
-- PMM
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2013-06-13 16:53 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-27 18:48 [Qemu-devel] [PATCH] linux-user: add SIOCADDRT/SIOCDELRT support Laurent Vivier
2013-06-07 18:17 ` Laurent Vivier
2013-06-13 16:53 ` Peter Maydell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).