From 5e82b94b916847811e84e2c8395bd187186b375d Mon Sep 17 00:00:00 2001 From: julianuziemblo Date: Fri, 23 May 2025 19:45:45 +0200 Subject: [PATCH 1/3] ioctl: serialize special ioctls in userspace There are some special cases where the input to the ioctl syscall is a structure with a pointer, which has to be detected and treated uniquely by the kernel. This leads to asymmetric behaviour (serialization in kernel, but deserialization in userspace) and code duplication. This change introduces simple packing and unpacking functions, which work only for the special cases, allocating memory for the whole request to be sent in the syscall and deallocating it when the syscall returns. This change also introduces function `ioctl_getPointerField` and convenience IOC_GET_PTR_FIELD macro, which allow the user to easily get the pointed-to values passed in by ioctl without knowing the inner serialization structure. JIRA: RTOS-1205 --- include/sys/ioctl.h | 13 +- sys/ioctl.c | 37 +---- unistd/Makefile | 2 +- unistd/file.c | 46 ++++++- unistd/ioctl-helper.c | 314 ++++++++++++++++++++++++++++++++++++++++++ unistd/ioctl-helper.h | 36 +++++ 6 files changed, 408 insertions(+), 40 deletions(-) create mode 100644 unistd/ioctl-helper.c create mode 100644 unistd/ioctl-helper.h diff --git a/include/sys/ioctl.h b/include/sys/ioctl.h index 96394fc0..dc634dcc 100644 --- a/include/sys/ioctl.h +++ b/include/sys/ioctl.h @@ -27,13 +27,18 @@ extern "C" { #endif +/* convenience macro to get sub-pointer `field` in a packed ioctl structure that is read-only */ +#define IOC_GET_PTR_FIELD(request, subptr, val, field) ioctl_getPointerField(request, subptr, val, offsetof(typeof(*val), field)) + + #define IOCPARM_MASK 0x1fff #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK) #define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16)) #define IOCGROUP(x) (((x) >> 8) & 0xff) -#define IOC_VOID 0x20000000 +#define IOC_VOID 0x00000000 +#define IOC_NESTED 0x20000000 #define IOC_OUT 0x40000000 #define IOC_IN 0x80000000 #define IOC_INOUT (IOC_IN | IOC_OUT) @@ -46,6 +51,7 @@ extern "C" { #define _IOR(g, n, t) _IOC(IOC_OUT, (g), (n), sizeof(t)) #define _IOW(g, n, t) _IOC(IOC_IN, (g), (n), sizeof(t)) #define _IOWR(g, n, t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) +#define _IOC_NESTED(inout, g, n, t) (IOC_NESTED | _IOC(inout, g, n, sizeof(t))) #define TIOCGPTN _IOR('T', 0x30, unsigned int) @@ -77,6 +83,11 @@ static inline pid_t ioctl_getSenderPid(const msg_t *msg) void ioctl_setResponse(msg_t *msg, unsigned long request, int err, const void *data); +/* get value pointed to by a sub-pointer at offset in nested ioctl structure + pointed to by val and place it in subptr */ +int ioctl_getPointerField(unsigned long request, void **subptr, const void *val, size_t offset); + + #ifdef __cplusplus } #endif diff --git a/sys/ioctl.c b/sys/ioctl.c index ad74da9b..5040b7ee 100644 --- a/sys/ioctl.c +++ b/sys/ioctl.c @@ -13,18 +13,16 @@ * %LICENSE% */ -#include - +#include #include #include #include +#include #include -/* SIOCGIFCONF handling */ #include -#include -#include -#include + +#include "../unistd/ioctl-helper.h" const void *ioctl_unpack(msg_t *msg, unsigned long *request, id_t *id) @@ -47,7 +45,7 @@ const void *ioctl_unpackEx(msg_t *msg, unsigned long *request, id_t *id, void ** *id = msg->oid.id; } - size = IOCPARM_LEN(ioctl->request); + size = ioctl->size; if ((ioctl->request & IOC_IN) != 0) { if (size <= (sizeof(msg->i.raw) - sizeof(ioctl_in_t))) { @@ -62,31 +60,6 @@ const void *ioctl_unpackEx(msg_t *msg, unsigned long *request, id_t *id, void ** size = min(size, sizeof(void *)); (void)memcpy(&data, ioctl->data, size); } - - /* ioctl special case: arg is structure with pointer - has to be custom-packed into message */ - if (ioctl->request == SIOCGIFCONF) { - struct ifconf *ifc = (struct ifconf *)data; - if (ifc->ifc_len > 0) { - ifc->ifc_buf = msg->o.data; - } - } - else if ((ioctl->request == SIOCADDRT) || (ioctl->request == SIOCDELRT)) { - /* input data is read only so we have allocate the in_data if - * we want to change it. TODO: find better place to allocate and free - * message */ - struct rtentry *rt = malloc(msg->i.size); - if (rt == NULL) { - return NULL; - } - (void)memcpy(rt, msg->i.data, msg->i.size); - rt->rt_dev = malloc(msg->o.size); - if (rt->rt_dev == NULL) { - free(rt); - return NULL; - } - (void)memcpy(rt->rt_dev, msg->o.data, msg->o.size); - data = (void *)rt; - } else { } diff --git a/unistd/Makefile b/unistd/Makefile index 192278d0..3f5d4183 100644 --- a/unistd/Makefile +++ b/unistd/Makefile @@ -4,5 +4,5 @@ # Copyright 2020 Phoenix Systems # -OBJS += $(addprefix $(PREFIX_O)unistd/, alarm.o conf.o crypt.o dir.o file.o hostname.o getlogin.o getopt.o getpass.o group.o \ +OBJS += $(addprefix $(PREFIX_O)unistd/, alarm.o conf.o crypt.o dir.o ioctl-helper.o file.o hostname.o getlogin.o getopt.o getpass.o group.o \ hostid.o pause.o pwd.o sys.o user.o) diff --git a/unistd/file.c b/unistd/file.c index bce8b792..98caa6f5 100644 --- a/unistd/file.c +++ b/unistd/file.c @@ -29,6 +29,7 @@ #include #include "posix/utils.h" +#include "ioctl-helper.h" extern ssize_t sys_read(int fildes, void *buf, size_t nbyte, off_t offset); @@ -644,20 +645,53 @@ int fcntl(int fd, int cmd, ...) } -extern int sys_ioctl(int fildes, unsigned long request, void *val); +extern int sys_ioctl(int fildes, unsigned long request, void *val, size_t size); int ioctl(int fildes, unsigned long request, ...) { va_list ap; void *val; + void *packed; + size_t size = IOCPARM_LEN(request); + int ret; + + if ((request & IOC_INOUT) != 0 || size > 0) { + /* assume `args` is one structure passed by pointer */ + va_start(ap, request); + val = va_arg(ap, void *); + va_end(ap); + } + else { + val = NULL; + } - /* FIXME: handle varargs properly */ - va_start(ap, request); - val = va_arg(ap, void *); - va_end(ap); + if ((request & IOC_NESTED) != 0) { + ret = ioctl_serialize(request, val, &packed, &size); + if (ret < 0) { + ioctl_free(request, packed); + return SET_ERRNO(ret); + } - return SET_ERRNO(sys_ioctl(fildes, request, val)); + if (packed != NULL) { + ret = sys_ioctl(fildes, request, packed, size); + } + else { + ret = sys_ioctl(fildes, request, val, size); + } + + if (ret < 0) { + ioctl_free(request, packed); + return SET_ERRNO(ret); + } + + ioctl_deserialize(request, val, packed); + + return SET_ERRNO(ret); + } + else { + return SET_ERRNO(sys_ioctl(fildes, request, val, size)); + } } diff --git a/unistd/ioctl-helper.c b/unistd/ioctl-helper.c new file mode 100644 index 00000000..f40ea271 --- /dev/null +++ b/unistd/ioctl-helper.c @@ -0,0 +1,314 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * ioctl special case input serialization/deserialization + * + * Copyright 2025 Phoenix Systems + * Author: Julian Uziemblo + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ +#include +#include +#include +#include +#include + +#include "ioctl-helper.h" + +#define PTR_ADD(ptr, offset) ((void *)(((uint8_t *)(ptr)) + (offset))) +#define PTR_ADD_AND_DEREF(ptr, offset) (*(void **)PTR_ADD(ptr, offset)) +#define SIZEOF_ARRAY(arr) (sizeof(arr) / sizeof(arr[0])) + + +typedef struct { + const size_t offset; + /* returns: < 0 on error; 0 when no serialization needed; > 0 the size of subptr */ + ssize_t (*const getSize)(const void *val); +} subptr_t; + + +typedef struct { + const subptr_t *const subptrs; + const size_t nsubptrs; +} nestedLayout_t; + + +typedef struct { + const unsigned long request; + void **packed; + size_t *packedSize; + void *ioctlVal; + size_t ioctlValSize; + const nestedLayout_t *layout; +} ioctl_ctx_t; + + +typedef int (*ioctl_op_t)(ioctl_ctx_t *ctx); + + +/* + * Extendable support for nested structures in ioctl commands + * + * To support new nested ioctl: + * 1) Define `Subptrs[]` - an array of `subptr_t` structures + * representing the inner layout of the nested ioctl structure. Each + * entry corresponds to one sub-pointer and describes its offset in + * the structure and provides a function to calculate the size of the + * pointed-to structure (it shall return: 0 when no serialization is + * needed, negative value on error and positive size value on success). + * 2) Define `Layout`. This structure consists of a pointer + * to the defined above sub-pointers array and its size. + * 3) Add a branch to the switch statement in `ioctl_dispatchOp` function + * with the ioctl's request number as a matcher that assigns created + * layout structure to the `layout` pointer variable. + */ + + +static ssize_t ioctl_rtDevSize(const void *val) +{ + const struct rtentry *rt = val; + if (rt->rt_dev == NULL) { + return -EINVAL; + } + return strlen(rt->rt_dev) + 1; +} + + +static const subptr_t rtentrySubptrs[] = { { + .offset = offsetof(struct rtentry, rt_dev), + .getSize = ioctl_rtDevSize, +} }; + + +static const nestedLayout_t rtentryLayout = { + .subptrs = rtentrySubptrs, + .nsubptrs = SIZEOF_ARRAY(rtentrySubptrs), +}; + + +static ssize_t ioctl_ifcBufLen(const void *val) +{ + const struct ifconf *ifc = val; + size_t ifc_buf_len = ifc->ifc_len; + if (ifc->ifc_buf == NULL) { + if (ifc_buf_len == 0) { + /* device returns the needed length + -> no packing/unpacking needed */ + return 0; + } + else { + return -EINVAL; + } + } + + return ifc_buf_len; +} + + +static const subptr_t ifconfSubptrs[] = { { + .offset = offsetof(struct ifconf, ifc_buf), + .getSize = ioctl_ifcBufLen, +} }; + + +static const nestedLayout_t ifconfLayout = { + .subptrs = ifconfSubptrs, + .nsubptrs = SIZEOF_ARRAY(ifconfSubptrs), +}; + + +static inline int ioctl_dispatchOp(unsigned long request, void **packed, size_t *packedSize, void *ioctlVal, size_t ioctlValSize, ioctl_op_t op) +{ + /* IOC_NESTED checked before this in ioctl() */ + const nestedLayout_t *layout; + + switch (request) { + case SIOCADDRT: + case SIOCDELRT: + layout = &rtentryLayout; + break; + + case SIOCGIFCONF: + layout = &ifconfLayout; + break; + + default: + return -EOPNOTSUPP; + } + + ioctl_ctx_t ctx = { + .request = request, + .packed = packed, + .packedSize = packedSize, + .ioctlVal = ioctlVal, + .ioctlValSize = ioctlValSize, + .layout = layout, + }; + + return op(&ctx); +} + + +/* + * Common routines + */ + + +static inline ssize_t ioctl_totalSizeNeeded(ioctl_ctx_t *ctx) +{ + ssize_t size; + size_t totalSize = ctx->ioctlValSize; + + for (size_t i = 0; i < ctx->layout->nsubptrs; i++) { + size = ctx->layout->subptrs[i].getSize(ctx->ioctlVal); + if (size < 0) { + return size; + } + totalSize += size; + } + + return totalSize; +} + + +static int ioctl_opSerialize(ioctl_ctx_t *ctx) +{ + size_t totalSize; + size_t offset = 0; + + ssize_t size = ioctl_totalSizeNeeded(ctx); + if (size < 0) { + return size; + } + totalSize = size; + + if (totalSize == ctx->ioctlValSize) { + /* no packing needed - ioctl is already the right size */ + return 0; + } + + void *mem = malloc(totalSize); + if (mem == NULL) { + return -ENOMEM; + } + + (void)memcpy(PTR_ADD(mem, offset), ctx->ioctlVal, ctx->ioctlValSize); + offset += ctx->ioctlValSize; + + for (size_t i = 0; i < ctx->layout->nsubptrs; i++) { + size = ctx->layout->subptrs[i].getSize(ctx->ioctlVal); + if (size < 0) { + free(mem); + return size; + } + (void)memcpy(PTR_ADD(mem, offset), PTR_ADD_AND_DEREF(ctx->ioctlVal, ctx->layout->subptrs[i].offset), size); + offset += size; + } + + *ctx->packed = mem; + *ctx->packedSize = totalSize; + + return 0; +} + + +static int ioctl_opDeserialize(ioctl_ctx_t *ctx) +{ + if (*ctx->packed == NULL) { + /* no unpacking needed - val wasn't packed */ + return 0; + } + + size_t offset = ctx->ioctlValSize; + ssize_t size; + + for (size_t i = 0; i < ctx->layout->nsubptrs; i++) { + size = ctx->layout->subptrs[i].getSize(ctx->ioctlVal); + if (size < 0) { + return size; + } + if (size == 0) { + continue; + } + /* copy old pointer value to helper variable */ + void *subptr = PTR_ADD_AND_DEREF(ctx->ioctlVal, ctx->layout->subptrs[i].offset); + + if (subptr != NULL) { + /* set pointer value in allocated structure to copy the right pointer at the end */ + PTR_ADD_AND_DEREF(*ctx->packed, ctx->layout->subptrs[i].offset) = subptr; + + /* copy current substructure */ + (void)memcpy(subptr, PTR_ADD(*ctx->packed, offset), size); + offset += size; + } + } + + /* copy back the main struct */ + (void)memcpy(ctx->ioctlVal, *ctx->packed, ctx->ioctlValSize); + + return 0; +} + + +static int ioctl_opFree(ioctl_ctx_t *ctx) +{ + if (*ctx->packed != NULL) { + free(*ctx->packed); + } + return 0; +} + + +static int ioctl_opGetPointerField(ioctl_ctx_t *ctx) +{ + ssize_t size; + size_t offset = IOCPARM_LEN(ctx->request); + + for (size_t i = 0; i < ctx->layout->nsubptrs; i++) { + if (ctx->layout->subptrs[i].offset == ctx->ioctlValSize) { + *ctx->packed = PTR_ADD(ctx->ioctlVal, offset); + return 0; + } + size = ctx->layout->subptrs[i].getSize(ctx->ioctlVal); + if (size < 0) { + return size; + } + offset += size; + } + + return -ENODATA; +} + + +void ioctl_free(unsigned long request, void *packed) +{ + (void)ioctl_dispatchOp(request, &packed, NULL, NULL, 0, ioctl_opFree); +} + + +int ioctl_serialize(unsigned long request, void *ioctlVal, void **packed, size_t *packedSize) +{ + /* set to NULL so if we don't allocate the memory, we won't call free on it */ + *packed = NULL; + return ioctl_dispatchOp(request, packed, packedSize, ioctlVal, IOCPARM_LEN(request), ioctl_opSerialize); +} + + +void ioctl_deserialize(unsigned long request, void *ioctlVal, void *packed) +{ + if (ioctl_dispatchOp(request, &packed, NULL, ioctlVal, IOCPARM_LEN(request), ioctl_opDeserialize) != -EOPNOTSUPP) { + ioctl_free(request, packed); + } +} + + +int ioctl_getPointerField(unsigned long request, void **subptr, const void *val, size_t offset) +{ + /* ioctl_opGetPointerField doesn't change val: const signalizes to user that val will not be changed */ + return ioctl_dispatchOp(request, subptr, NULL, (void *)val, offset, ioctl_opGetPointerField); +} diff --git a/unistd/ioctl-helper.h b/unistd/ioctl-helper.h new file mode 100644 index 00000000..3c73dbfa --- /dev/null +++ b/unistd/ioctl-helper.h @@ -0,0 +1,36 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * ioctl special case input serialization/deserialization + * + * Copyright 2025 Phoenix Systems + * Author: Julian Uziembło + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _LIBPHOENIX_IOCTL_HELPER_H_ +#define _LIBPHOENIX_IOCTL_HELPER_H_ + +#include + + +/* deallocates memory if it was allocated by ioctl_serialize */ +void ioctl_free(unsigned long request, void *packed); + + +/* serialize the request's structure into packed. + allocates memory in special cases to be freed by ioctl_free */ +int ioctl_serialize(unsigned long request, void *ioctlVal, void **packed, size_t *packedSize); + + +/* deserialize the request's structure from packed back into ioctlVal. + deallocates memory if it was allocated by ioctl_serialize */ +void ioctl_deserialize(unsigned long request, void *ioctlVal, void *packed); + + +#endif /* _LIBPHOENIX_IOCTL_HELPER_H_ */ From 74582f1a46675d8063765a98acaa337a93ede0b8 Mon Sep 17 00:00:00 2001 From: julianuziemblo Date: Wed, 18 Feb 2026 11:22:22 +0100 Subject: [PATCH 2/3] !include/sys/ioctl: include phoenix/ioctl.h for common IOC* defines IOC* defines transferred to kernel to reduce code duplication JIRA: RTOS-1205 --- include/sys/ioctl.h | 31 +++++++++---------------------- include/sys/sockios.h | 6 +++--- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/include/sys/ioctl.h b/include/sys/ioctl.h index dc634dcc..db0874ce 100644 --- a/include/sys/ioctl.h +++ b/include/sys/ioctl.h @@ -21,6 +21,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { @@ -28,30 +30,15 @@ extern "C" { /* convenience macro to get sub-pointer `field` in a packed ioctl structure that is read-only */ -#define IOC_GET_PTR_FIELD(request, subptr, val, field) ioctl_getPointerField(request, subptr, val, offsetof(typeof(*val), field)) - - -#define IOCPARM_MASK 0x1fff -#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK) -#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16)) -#define IOCGROUP(x) (((x) >> 8) & 0xff) - - -#define IOC_VOID 0x00000000 -#define IOC_NESTED 0x20000000 -#define IOC_OUT 0x40000000 -#define IOC_IN 0x80000000 -#define IOC_INOUT (IOC_IN | IOC_OUT) -#define IOC_DIRMASK 0xe0000000 +#define IOC_NESTED_GET_PTR_FIELD(request, subptr, val, field) ioctl_getPointerField(request, subptr, val, offsetof(typeof(*val), field)) -#define _IOC(inout, group, num, len) ((unsigned long)(inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))) -#define _IO(g, n) _IOC(IOC_VOID, (g), (n), 0) -#define _IOV(g, n, t) _IOC(IOC_VOID, (g), (n), sizeof(t)) /* IOW with passing by value */ -#define _IOR(g, n, t) _IOC(IOC_OUT, (g), (n), sizeof(t)) -#define _IOW(g, n, t) _IOC(IOC_IN, (g), (n), sizeof(t)) -#define _IOWR(g, n, t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) -#define _IOC_NESTED(inout, g, n, t) (IOC_NESTED | _IOC(inout, g, n, sizeof(t))) +#define _IO(g, n) _IOC(IOC_VOID, (g), (n), 0) +#define _IOV(g, n, t) _IOC(IOC_VOID, (g), (n), sizeof(t)) /* IOW with passing by value */ +#define _IOR(g, n, t) _IOC(IOC_OUT, (g), (n), sizeof(t)) +#define _IOW(g, n, t) _IOC(IOC_IN, (g), (n), sizeof(t)) +#define _IOWR(g, n, t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) +#define _IOC_NESTED(inout, g, n, t) _IOC((inout) | IOC_NESTED, (g), (n), sizeof(t)) /* passed structure is nested */ #define TIOCGPTN _IOR('T', 0x30, unsigned int) diff --git a/include/sys/sockios.h b/include/sys/sockios.h index 9c4c9367..1b6f4fb7 100644 --- a/include/sys/sockios.h +++ b/include/sys/sockios.h @@ -24,7 +24,7 @@ /* Socket configuration controls. */ #define SIOCGIFNAME _IOWR(SOCK_IOC_TYPE, 0x10, struct ifreq) /* get name of interface with given index */ -#define SIOCGIFCONF _IOWR(SOCK_IOC_TYPE, 0x12, struct ifconf) /* get iface list */ +#define SIOCGIFCONF _IOC_NESTED(IOC_INOUT, SOCK_IOC_TYPE, 0x12, struct ifconf) /* get iface list */ #define SIOCGIFFLAGS _IOWR(SOCK_IOC_TYPE, 0x13, struct ifreq) /* get interface flags */ #define SIOCSIFFLAGS _IOW( SOCK_IOC_TYPE, 0x14, struct ifreq) /* Set interface flags */ #define SIOCGIFADDR _IOWR(SOCK_IOC_TYPE, 0x15, struct ifreq) /* get device address */ @@ -50,7 +50,7 @@ #define SIOCSIFTXQLEN _IOWR(SOCK_IOC_TYPE, 0x43, struct ifreq) /* set the tx queue length */ /* Routing table calls. */ -#define SIOCADDRT _IOW(SOCK_IOC_TYPE, 0x44, struct rtentry) /* add routing table entry */ -#define SIOCDELRT _IOW(SOCK_IOC_TYPE, 0x45, struct rtentry) /* delete routing table entry */ +#define SIOCADDRT _IOC_NESTED(IOC_IN, SOCK_IOC_TYPE, 0x44, struct rtentry) /* add routing table entry */ +#define SIOCDELRT _IOC_NESTED(IOC_IN, SOCK_IOC_TYPE, 0x45, struct rtentry) /* delete routing table entry */ #endif // LIBPHOENIX_SYS_SOCKIOS_H From d27bdb36e3afb8792e6dd49b245bfe5c7ce30f5e Mon Sep 17 00:00:00 2001 From: julianuziemblo Date: Wed, 18 Feb 2026 12:40:12 +0100 Subject: [PATCH 3/3] include/sys/sockios: format JIRA: RTOS-1205 --- include/sys/sockios.h | 54 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/include/sys/sockios.h b/include/sys/sockios.h index 1b6f4fb7..15c108a1 100644 --- a/include/sys/sockios.h +++ b/include/sys/sockios.h @@ -20,37 +20,37 @@ #include #include -#define SOCK_IOC_TYPE 'S' +#define SOCK_IOC_TYPE 'S' /* Socket configuration controls. */ -#define SIOCGIFNAME _IOWR(SOCK_IOC_TYPE, 0x10, struct ifreq) /* get name of interface with given index */ -#define SIOCGIFCONF _IOC_NESTED(IOC_INOUT, SOCK_IOC_TYPE, 0x12, struct ifconf) /* get iface list */ -#define SIOCGIFFLAGS _IOWR(SOCK_IOC_TYPE, 0x13, struct ifreq) /* get interface flags */ -#define SIOCSIFFLAGS _IOW( SOCK_IOC_TYPE, 0x14, struct ifreq) /* Set interface flags */ -#define SIOCGIFADDR _IOWR(SOCK_IOC_TYPE, 0x15, struct ifreq) /* get device address */ -#define SIOCSIFADDR _IOW( SOCK_IOC_TYPE, 0x16, struct ifreq) /* Set device address */ -#define SIOCGIFDSTADDR _IOWR(SOCK_IOC_TYPE, 0x17, struct ifreq) /* get remote address (point-to-point interfaces) */ -#define SIOCSIFDSTADDR _IOW( SOCK_IOC_TYPE, 0x18, struct ifreq) /* set remote address (point-to-point interfaces) */ -#define SIOCGIFBRDADDR _IOWR(SOCK_IOC_TYPE, 0x19, struct ifreq) /* get broadcast address */ -#define SIOCSIFBRDADDR _IOW( SOCK_IOC_TYPE, 0x1a, struct ifreq) /* set broadcast address */ -#define SIOCGIFNETMASK _IOWR(SOCK_IOC_TYPE, 0x1b, struct ifreq) /* get network mask */ -#define SIOCSIFNETMASK _IOW( SOCK_IOC_TYPE, 0x1c, struct ifreq) /* set network mask */ -#define SIOCGIFMETRIC _IOWR(SOCK_IOC_TYPE, 0x1d, struct ifreq) /* get metric */ -#define SIOCSIFMETRIC _IOW( SOCK_IOC_TYPE, 0x1e, struct ifreq) /* set metric */ -#define SIOCGIFMTU _IOWR(SOCK_IOC_TYPE, 0x21, struct ifreq) /* get MTU size */ -#define SIOCSIFMTU _IOW( SOCK_IOC_TYPE, 0x22, struct ifreq) /* set MTU size */ -#define SIOCSIFHWADDR _IOW( SOCK_IOC_TYPE, 0x24, struct ifreq) /* set interface MAC address */ -#define SIOCGIFHWADDR _IOWR(SOCK_IOC_TYPE, 0x27, struct ifreq) /* get interface MAC address */ -#define SIOCADDMULTI _IOWR(SOCK_IOC_TYPE, 0x31, struct ifreq) /* add multicast address */ -#define SIOCDELMULTI _IOWR(SOCK_IOC_TYPE, 0x32, struct ifreq) /* remove multicast address */ -#define SIOCGIFINDEX _IOWR(SOCK_IOC_TYPE, 0x33, struct ifreq) /* get index of interface with given name */ +#define SIOCGIFNAME _IOWR(SOCK_IOC_TYPE, 0x10, struct ifreq) /* get name of interface with given index */ +#define SIOCGIFCONF _IOC_NESTED(IOC_INOUT, SOCK_IOC_TYPE, 0x12, struct ifconf) /* get iface list */ +#define SIOCGIFFLAGS _IOWR(SOCK_IOC_TYPE, 0x13, struct ifreq) /* get interface flags */ +#define SIOCSIFFLAGS _IOW(SOCK_IOC_TYPE, 0x14, struct ifreq) /* Set interface flags */ +#define SIOCGIFADDR _IOWR(SOCK_IOC_TYPE, 0x15, struct ifreq) /* get device address */ +#define SIOCSIFADDR _IOW(SOCK_IOC_TYPE, 0x16, struct ifreq) /* Set device address */ +#define SIOCGIFDSTADDR _IOWR(SOCK_IOC_TYPE, 0x17, struct ifreq) /* get remote address (point-to-point interfaces) */ +#define SIOCSIFDSTADDR _IOW(SOCK_IOC_TYPE, 0x18, struct ifreq) /* set remote address (point-to-point interfaces) */ +#define SIOCGIFBRDADDR _IOWR(SOCK_IOC_TYPE, 0x19, struct ifreq) /* get broadcast address */ +#define SIOCSIFBRDADDR _IOW(SOCK_IOC_TYPE, 0x1a, struct ifreq) /* set broadcast address */ +#define SIOCGIFNETMASK _IOWR(SOCK_IOC_TYPE, 0x1b, struct ifreq) /* get network mask */ +#define SIOCSIFNETMASK _IOW(SOCK_IOC_TYPE, 0x1c, struct ifreq) /* set network mask */ +#define SIOCGIFMETRIC _IOWR(SOCK_IOC_TYPE, 0x1d, struct ifreq) /* get metric */ +#define SIOCSIFMETRIC _IOW(SOCK_IOC_TYPE, 0x1e, struct ifreq) /* set metric */ +#define SIOCGIFMTU _IOWR(SOCK_IOC_TYPE, 0x21, struct ifreq) /* get MTU size */ +#define SIOCSIFMTU _IOW(SOCK_IOC_TYPE, 0x22, struct ifreq) /* set MTU size */ +#define SIOCSIFHWADDR _IOW(SOCK_IOC_TYPE, 0x24, struct ifreq) /* set interface MAC address */ +#define SIOCGIFHWADDR _IOWR(SOCK_IOC_TYPE, 0x27, struct ifreq) /* get interface MAC address */ +#define SIOCADDMULTI _IOWR(SOCK_IOC_TYPE, 0x31, struct ifreq) /* add multicast address */ +#define SIOCDELMULTI _IOWR(SOCK_IOC_TYPE, 0x32, struct ifreq) /* remove multicast address */ +#define SIOCGIFINDEX _IOWR(SOCK_IOC_TYPE, 0x33, struct ifreq) /* get index of interface with given name */ /* unused but needed by busybox ifconfig */ -#define SIOCGIFTXQLEN _IOWR(SOCK_IOC_TYPE, 0x42, struct ifreq) /* get the tx queue length */ -#define SIOCSIFTXQLEN _IOWR(SOCK_IOC_TYPE, 0x43, struct ifreq) /* set the tx queue length */ +#define SIOCGIFTXQLEN _IOWR(SOCK_IOC_TYPE, 0x42, struct ifreq) /* get the tx queue length */ +#define SIOCSIFTXQLEN _IOWR(SOCK_IOC_TYPE, 0x43, struct ifreq) /* set the tx queue length */ /* Routing table calls. */ -#define SIOCADDRT _IOC_NESTED(IOC_IN, SOCK_IOC_TYPE, 0x44, struct rtentry) /* add routing table entry */ -#define SIOCDELRT _IOC_NESTED(IOC_IN, SOCK_IOC_TYPE, 0x45, struct rtentry) /* delete routing table entry */ +#define SIOCADDRT _IOC_NESTED(IOC_IN, SOCK_IOC_TYPE, 0x44, struct rtentry) /* add routing table entry */ +#define SIOCDELRT _IOC_NESTED(IOC_IN, SOCK_IOC_TYPE, 0x45, struct rtentry) /* delete routing table entry */ -#endif // LIBPHOENIX_SYS_SOCKIOS_H +#endif // LIBPHOENIX_SYS_SOCKIOS_H