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
14 changes: 14 additions & 0 deletions include/ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,23 @@
#ifndef _PH_IOCTL_H_
#define _PH_IOCTL_H_

#define IOCPARM_MASK 0x1fffUL
#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16))
#define IOCGROUP(x) (((x) >> 8) & 0xffU)

#define IOC_VOID 0x00000000UL
#define IOC_NESTED 0x20000000UL
#define IOC_OUT 0x40000000UL
#define IOC_IN 0x80000000UL
#define IOC_INOUT (IOC_IN | IOC_OUT)
#define IOC_DIRMASK 0xc0000000UL

#define _IOC(inout, group, num, len) ((unsigned long)((inout) | (((len) & IOCPARM_MASK) << 16) | ((group) << 8) | (num)))

typedef struct {
unsigned long request;
unsigned long size;
char data[];
} ioctl_in_t;

Expand Down
81 changes: 29 additions & 52 deletions posix/posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -1641,25 +1641,9 @@ int posix_fcntl(int fd, unsigned int cmd, u8 *ustack)
}


#define IOCPARM_MASK 0x1fffUL
#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)

#define IOC_OUT 0x40000000UL
#define IOC_IN 0x80000000UL
#define IOC_INOUT (IOC_IN | IOC_OUT)
#define _IOC(inout, group, num, len) ((unsigned long)((inout) | (((len) & IOCPARM_MASK) << 16) | (((unsigned int)(group)) << 8) | (num)))

#define SIOCGIFCONF _IOC(IOC_INOUT, 'S', 0x12U, sizeof(struct ifconf))
#define SIOCADDRT _IOC(IOC_IN, 'S', 0x44U, sizeof(struct rtentry))
#define SIOCDELRT _IOC(IOC_IN, 'S', 0x45U, sizeof(struct rtentry))


static void ioctl_pack(msg_t *msg, unsigned long request, void *data, oid_t *oid)
static void ioctl_pack(msg_t *msg, unsigned long request, void *data, size_t size, oid_t *oid)
{
size_t size = IOCPARM_LEN(request);
ioctl_in_t *ioctl = (ioctl_in_t *)msg->i.raw;
struct ifconf *ifc;
struct rtentry *rt;

hal_memcpy(&msg->oid, oid, sizeof(*oid));
msg->type = mtDevCtl;
Expand All @@ -1669,6 +1653,7 @@ static void ioctl_pack(msg_t *msg, unsigned long request, void *data, oid_t *oid
msg->o.size = 0;

ioctl->request = request;
ioctl->size = size;

if ((request & IOC_INOUT) != 0U) {
if ((request & IOC_IN) != 0U) {
Expand All @@ -1692,46 +1677,21 @@ static void ioctl_pack(msg_t *msg, unsigned long request, void *data, oid_t *oid
hal_memcpy(ioctl->data, &data, size);
}
else {
/* No action required */
}


/* ioctl special case: arg is structure with pointer - has to be custom-packed into message */
if (request == SIOCGIFCONF) {
ifc = (struct ifconf *)data;
msg->o.data = ifc->ifc_buf;
msg->o.size = ifc->ifc_len;
}
else if ((request == SIOCADDRT) || (request == SIOCDELRT)) {
rt = (struct rtentry *)data;
if (rt->rt_dev != NULL) {
msg->o.data = rt->rt_dev;
msg->o.size = hal_strlen(rt->rt_dev) + 1U;
}
}
else {
/* No action required */
/* Nothing to do */
}
}


static int ioctl_processResponse(const msg_t *msg, unsigned long request, void *data)
static int ioctl_processResponse(const msg_t *msg, unsigned long request, void *data, size_t size)
{
size_t size = IOCPARM_LEN(request);
int err;
struct ifconf *ifc;

err = msg->o.err;

if (((request & IOC_OUT) != 0U) && (size <= sizeof(msg->o.raw))) {
hal_memcpy(data, msg->o.raw, size);
}

if (request == SIOCGIFCONF) { /* restore overridden userspace pointer */
ifc = (struct ifconf *)data;
ifc->ifc_buf = msg->o.data;
}

return err;
}

Expand All @@ -1744,19 +1704,36 @@ int posix_ioctl(int fildes, unsigned long request, u8 *ustack)
int err;
msg_t msg;
void *data = NULL;
size_t size = IOCPARM_LEN(request);

err = posix_getOpenFile(fildes, &f);
if (err == 0) {
/* TODO: handle POSIX defined requests with `switch (request)` */
if (((request & IOC_INOUT) != 0U) || (IOCPARM_LEN(request) > 0U)) {
GETFROMSTACK(ustack, void *, data, 2U);
if (err == EOK) {
/* TODO: handle POSIX defined requests */
if (size > 0U) {
GETFROMSTACK(ustack, void *, data, 2);
/* the actual size of the pointed-to structure: >= IOCPARM_LEN(request) */
GETFROMSTACK(ustack, size_t, size, 3);

if ((request & IOC_INOUT) != 0U) {
if (data == NULL) {
err = -EFAULT;
}
else if (vm_mapBelongs(proc_current()->process, data, size) < 0) {
err = -EFAULT;
}
else {
/* Nothing to do */
}
}
}

ioctl_pack(&msg, request, data, &f->oid);

err = proc_send(f->oid.port, &msg);
if (err == EOK) {
err = ioctl_processResponse(&msg, request, data);
ioctl_pack(&msg, request, data, size, &f->oid);

err = proc_send(f->oid.port, &msg);
if (err == EOK) {
err = ioctl_processResponse(&msg, request, data, size);
}
}

(void)posix_fileDeref(f);
Expand Down
20 changes: 0 additions & 20 deletions posix/posix_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,26 +123,6 @@ typedef struct _process_info_t {
} process_info_t;


/* SIOCGIFCONF ioctl special case: arg is structure with pointer */
struct ifconf {
unsigned int ifc_len; /* size of buffer */
char *ifc_buf; /* buffer address */
};

/* SIOADDRT and SIOCDELRT ioctls special case: arg is structure with pointer */
struct rtentry {
struct sockaddr rt_dst;
struct sockaddr rt_gateway;
struct sockaddr rt_genmask;
short rt_flags;
short rt_metric;
char *rt_dev;
unsigned long rt_mss;
unsigned long rt_window;
unsigned short rt_irtt;
};


int posix_fileDeref(open_file_t *f);


Expand Down
1 change: 1 addition & 0 deletions syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,7 @@ int syscalls_sys_ioctl(u8 *ustack)
GETFROMSTACK(ustack, int, fildes, 0U);
GETFROMSTACK(ustack, unsigned long, request, 1U);

/* vm_mapBelongs on optional data pointer checked in posix_ioctl */
return posix_ioctl(fildes, request, ustack);
}

Expand Down
Loading