From 0699cbd82b577a4358d199a627e9bc4497f436e7 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Wed, 4 Jul 2018 20:25:49 +0300 Subject: initial commit --- common/packet.h | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 common/packet.h (limited to 'common') diff --git a/common/packet.h b/common/packet.h new file mode 100644 index 0000000..35c57e1 --- /dev/null +++ b/common/packet.h @@ -0,0 +1,79 @@ +#pragma once + +enum packet_type { + PACKET_IOCTL, + PACKET_WRITE, +}; + +enum ioctl_dir { + IOCTL_NONE, + IOCTL_IOR, + IOCTL_IOW, + IOCTL_IOWR, +}; + +enum ioctl_arg { + IOCTL_ARG_INT, + IOCTL_ARG_OTHER, // All bets off, can't assure portability +}; + +/** + * Lackluster "network transparent" ioctl call + * Implements enough to have remote uinput interface. + */ +struct ioctl { + /** + * Because the 32bit encoding of ioctl message is not stable ABI interface between CPU architectures, + * we'll write the raw _IOC arguments on the wire and reconstruct the 32bit encoding on uinputd. + */ + uint8_t dir; // enum ioctl_dir, we can't use bitmask directly, as it's not portable + uint8_t type; // type of ioctl, e.g. UINPUT_IOCTL_BASE + uint8_t nr; // command code (nr), e.g. 100 of UINPUT_IOCTL_BASE which means UI_SET_EVBIT + + /** + * Ioctl ABI also includes argument size part, which is mainly used for typechecking. + * However since the arguments are not exact size types, but again CPU architecture dependant sizes, and even + * compiler dependant for structs (even though they use __u32 and friends, the padding may differ), we can't + * really do generic network abstraction. + * + * To avoid creating wrapper/shim over uinput/evdev (or for other linux interfaces if ever needed to be expanded), we + * use another type enum for ioctl argument type, for structs all bets are off, they may work or not work at all. + * (e.g. the ioctl will fail since it won't pass typecheck due to different sized of structs in between client <-> server) + */ + + uint8_t arg; // enum ioctl_arg, ^ read above + + union { + uint32_t integer; + uint16_t bytes; // max ioctl parameter size can be 16kB -1 + }; + + // payload, for IOCTL_ARG_OTHER, read the amount of bytes indicated by 'bytes' +}; + +/** + * Network transparent write call + * + * The call itself is portable, the underlying data may not be. + * E.g. structs used by evdev aren't packed, and some of them contain non explicit types such as POSIX struct timeval. + */ +struct write { + uint64_t bytes; // amount of bytes to be written + + // payload, read the amount of bytes indicated by 'bytes' +}; + +/** + * Binary specification for uinputd messages. + * All fields must be in little-endian. + * + * All packet operations are applied into the open uinput fd. + */ +struct packet { + uint8_t type; // enum packet_type + + union { + struct ioctl ioctl; + struct write write; + }; +} __attribute__((packed)) __attribute__((scalar_storage_order("little-endian"))); -- cgit v1.2.3