Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions include/sys/ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,24 @@
#include <sys/msg.h>
#include <sys/types.h>

#include <phoenix/ioctl.h>


#ifdef __cplusplus
extern "C" {
#endif


#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_OUT 0x40000000
#define IOC_IN 0x80000000
#define IOC_INOUT (IOC_IN | IOC_OUT)
#define IOC_DIRMASK 0xe0000000
/* convenience macro to get sub-pointer `field` in a packed ioctl structure that is read-only */
#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 _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)
Expand Down Expand Up @@ -77,6 +70,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
Expand Down
54 changes: 27 additions & 27 deletions include/sys/sockios.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,37 @@
#include <net/if.h>
#include <net/route.h>

#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 _IOWR(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 _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
#endif // LIBPHOENIX_SYS_SOCKIOS_H
37 changes: 5 additions & 32 deletions sys/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,16 @@
* %LICENSE%
*/

#include <arch.h>

#include <errno.h>
#include <sys/ioctl.h>
#include <phoenix/ioctl.h>
#include <sys/minmax.h>
#include <stdlib.h>
#include <string.h>

/* SIOCGIFCONF handling */
#include <sys/socket.h>
#include <sys/sockios.h>
#include <net/if.h>
#include <stdlib.h>

#include "../unistd/ioctl-helper.h"


const void *ioctl_unpack(msg_t *msg, unsigned long *request, id_t *id)
Expand All @@ -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))) {
Expand All @@ -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 {
}

Expand Down
2 changes: 1 addition & 1 deletion unistd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
46 changes: 40 additions & 6 deletions unistd/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <termios.h>

#include "posix/utils.h"
#include "ioctl-helper.h"


extern ssize_t sys_read(int fildes, void *buf, size_t nbyte, off_t offset);
Expand Down Expand Up @@ -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));
}
}


Expand Down
Loading
Loading