buffer.c read.c misc.c mount.c utility.c stadir.c \
uds.c dev_uds.c
-DPADD+= ${LIBSYS}
-LDADD+= -lsys
+DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
+LDADD+= -lchardriver -lsys
LDADD+= -lc
*
* The entry points into this file are...
*
- * uds_open: handles the open(2) syscall on /dev/uds
- * uds_close: handles the close(2) syscall on /dev/uds
- * uds_select: handles the select(2) syscall on /dev/uds
- * uds_read: handles the read(2) syscall on /dev/uds
- * uds_write: handles the write(2) syscall on /dev/uds
- * uds_ioctl: handles the ioctl(2) syscall on /dev/uds
- * uds_status: handles status requests.
- * uds_cancel: handles cancelled syscalls.
+ * uds_request: process a character device request
*
* Also See...
*
- * table.c, uds.c, uds.h
+ * uds.c, uds.h
*
* Overview
*
#include "glo.h"
#include "uds.h"
-static int uds_perform_read(int minor, endpoint_t m_source, size_t
- size, int pretend);
-static int uds_perform_write(int minor, endpoint_t m_source, size_t
- size, int pretend);
+static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant, size_t size, int pretend);
+static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant, size_t size, int pretend);
+
+static int uds_open(devminor_t orig_minor, int access, endpoint_t user_endpt);
+static int uds_close(devminor_t minor);
+static ssize_t uds_read(devminor_t minor, u64_t position, endpoint_t endpt,
+ cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
+static ssize_t uds_write(devminor_t minor, u64_t position, endpoint_t endpt,
+ cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
+static int uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+ cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id);
+static int uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
+static int uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt);
+
+static struct chardriver uds_tab = {
+ .cdr_open = uds_open,
+ .cdr_close = uds_close,
+ .cdr_read = uds_read,
+ .cdr_write = uds_write,
+ .cdr_ioctl = uds_ioctl,
+ .cdr_cancel = uds_cancel,
+ .cdr_select = uds_select
+};
+
+void uds_request(message *m_ptr, int ipc_status)
+{
+ /* Use libchardriver to process character device requests. */
+ chardriver_process(&uds_tab, m_ptr, ipc_status);
+}
-int uds_open(message *dev_m_in, message *dev_m_out)
+static int uds_open(devminor_t UNUSED(orig_minor), int access,
+ endpoint_t user_endpt)
{
message fs_m_in, fs_m_out;
struct uucred ucred;
+ devminor_t minor;
int rc, i;
- int minor;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] uds_open() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
- printf("Endpoint: 0x%x\n", dev_m_in->USER_ENDPT);
+ printf("(uds) [-] uds_open() call_count=%d\n", ++call_count);
+ printf("Endpoint: 0x%x\n", user_endpt);
#endif
/*
}
}
- if (minor == -1) {
-
- /* descriptor table full */
- uds_set_reply(dev_m_out, DEV_OPEN_REPL, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, ENFILE);
+ if (minor == -1)
return ENFILE;
- }
/*
* We found a slot in uds_fd_table, now initialize the descriptor
*/
uds_fd_table[minor].state = UDS_INUSE;
- /* track the system call we are performing in case it gets cancelled */
- uds_fd_table[minor].call_nr = dev_m_in->m_type;
- uds_fd_table[minor].ioctl = 0;
- uds_fd_table[minor].syscall_done = 0;
-
/* set the socket owner */
- uds_fd_table[minor].owner = dev_m_in->USER_ENDPT;
- uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
+ uds_fd_table[minor].owner = user_endpt;
/* setup select(2) framework */
- uds_fd_table[minor].selecting = 0;
- uds_fd_table[minor].select_proc = 0;
- uds_fd_table[minor].sel_ops_in = 0;
- uds_fd_table[minor].sel_ops_out = 0;
- uds_fd_table[minor].status_updated = 0;
+ uds_fd_table[minor].sel_endpt = NONE;
+ uds_fd_table[minor].sel_ops = 0;
/* initialize the data pointer (pos) to the start of the PIPE */
uds_fd_table[minor].pos = 0;
/* Initially the socket isn't suspended. */
uds_fd_table[minor].suspended = UDS_NOT_SUSPENDED;
- /* and the socket doesn't have an I/O grant initially */
- uds_fd_table[minor].io_gr = GRANT_INVALID;
-
- /* since there is no I/O grant it effectively has no size either */
- uds_fd_table[minor].io_gr_size = 0;
-
- /* The process isn't suspended so we don't flag it as revivable */
- uds_fd_table[minor].ready_to_revive = 0;
-
/* get the effective user id and effective group id from the endpoint */
/* this is needed in the REQ_NEWNODE request to PFS. */
- rc = getnucred(uds_fd_table[minor].endpoint, &ucred);
+ rc = getnucred(user_endpt, &ucred);
if (rc == -1) {
/* roll back the changes we made to the descriptor */
memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));
/* likely error: invalid endpoint / proc doesn't exist */
- uds_set_reply(dev_m_out, DEV_OPEN_REPL, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, errno);
- return errno;
+ return EIO;
}
/* Prepare Request to the FS side of PFS */
memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));
/* likely error: get_block() failed */
- uds_set_reply(dev_m_out, DEV_OPEN_REPL, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, rc);
return rc;
}
/* Process the response */
-
uds_fd_table[minor].inode_nr = fs_m_out.RES_INODE_NR;
- /* prepare the reply */
-
- uds_fd_table[minor].syscall_done = 1;
- uds_set_reply(dev_m_out, DEV_OPEN_REPL, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, minor);
- return minor;
+ return minor; /* cloned! */
}
-int uds_close(message *dev_m_in, message *dev_m_out)
+static int uds_close(devminor_t minor)
{
- int minor;
message fs_m_in, fs_m_out;
int rc;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] uds_close() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
- printf("Endpoint: 0x%x\n", dev_m_in->USER_ENDPT);
+ printf("(uds) [%d] uds_close() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
+ if (minor < 0 || minor >= NR_FDS) return ENXIO;
if (uds_fd_table[minor].state != UDS_INUSE) {
/* attempted to close a socket that hasn't been opened --
* something is very wrong :(
*/
- uds_set_reply(dev_m_out, DEV_CLOSE_REPL, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
return EINVAL;
}
- /* no need to track the syscall in case of cancellation. close() is
- * atomic and can't be cancelled. no need to update the endpoint here,
- * we won't be needing it to kill the socket
- */
-
/* if the socket is connected, disconnect it */
if (uds_fd_table[minor].peer != -1) {
int peer = uds_fd_table[minor].peer;
uds_fd_table[peer].err = ECONNRESET;
/* if peer was blocked on I/O revive peer */
- if (uds_fd_table[peer].suspended) {
- uds_fd_table[peer].ready_to_revive = 1;
- uds_unsuspend(dev_m_in->m_source, peer);
- }
+ if (uds_fd_table[peer].suspended != UDS_NOT_SUSPENDED)
+ uds_unsuspend(peer);
}
if (uds_fd_table[minor].ancillary_data.nfiledes > 0) {
- clear_fds(minor, &(uds_fd_table[minor].ancillary_data));
+ uds_clear_fds(minor, &uds_fd_table[minor].ancillary_data);
}
/* Prepare Request to the FS side of PFS */
rc = fs_putnode(&fs_m_in, &fs_m_out);
if (rc != OK) {
- perror("fs_putnode");
- /* likely error: get_block() failed */
+ printf("PFS: fs_putnode returned %d\n", rc);
+
return rc;
}
- uds_set_reply(dev_m_out, DEV_CLOSE_REPL, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, OK);
return OK;
}
-int uds_select(message *dev_m_in, message *dev_m_out)
+static int uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
{
- int i, bytes;
- int minor;
+ unsigned int ready_ops;
+ int i, bytes, watch;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] uds_select() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
- printf("Endpoint: 0x%x\n", dev_m_in->USER_ENDPT);
+ printf("(uds) [%d] uds_select() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
+ if (minor < 0 || minor >= NR_FDS) return ENXIO;
if (uds_fd_table[minor].state != UDS_INUSE) {
-
- /* attempted to close a socket that hasn't been opened --
+ /* attempted to select on a socket that hasn't been opened --
* something is very wrong :(
*/
-
- uds_sel_reply(dev_m_out, DEV_SEL_REPL1, minor, EINVAL);
return EINVAL;
}
- /* setup select(2) framework */
- uds_fd_table[minor].selecting = 1;
- uds_fd_table[minor].select_proc = dev_m_in->m_source;
-
- /* track the system call we are performing in case it gets cancelled */
- uds_fd_table[minor].call_nr = dev_m_in->m_type;
- uds_fd_table[minor].ioctl = 0;
- uds_fd_table[minor].syscall_done = 0;
-
- /* Can't update the process endpoint here, no info. */
+ watch = (ops & SEL_NOTIFY);
+ ops &= (SEL_RD | SEL_WR | SEL_ERR);
- uds_fd_table[minor].sel_ops_in = dev_m_in->USER_ENDPT;
- uds_fd_table[minor].sel_ops_out = 0;
+ ready_ops = 0;
/* check if there is data available to read */
- bytes = uds_perform_read(minor, dev_m_in->m_source, 1, 1);
- if (bytes > 0) {
-
- /* there is data in the pipe for us to read */
- uds_fd_table[minor].sel_ops_out |= SEL_RD;
-
- } else if (uds_fd_table[minor].listening == 1) {
-
- /* check for pending connections */
- for (i = 0; i < uds_fd_table[minor].backlog_size; i++) {
- if (uds_fd_table[minor].backlog[i] != -1) {
- uds_fd_table[minor].sel_ops_out |= SEL_RD;
- break;
+ if (ops & SEL_RD) {
+ bytes = uds_perform_read(minor, NONE, GRANT_INVALID, 1, 1);
+ if (bytes > 0) {
+ /* there is data in the pipe for us to read */
+ ready_ops |= SEL_RD;
+ } else if (uds_fd_table[minor].listening == 1) {
+ /* check for pending connections */
+ for (i = 0; i < uds_fd_table[minor].backlog_size; i++)
+ {
+ if (uds_fd_table[minor].backlog[i] != -1) {
+ ready_ops |= SEL_RD;
+ break;
+ }
}
+ } else if (bytes != SUSPEND) {
+ ready_ops |= SEL_RD;
}
- } else if (bytes != SUSPEND) {
- uds_fd_table[minor].sel_ops_out |= SEL_RD;
}
/* check if we can write without blocking */
- bytes = uds_perform_write(minor, dev_m_in->m_source, PIPE_BUF, 1);
- if (bytes != 0 && bytes != SUSPEND) {
- /* There is room to write or there is an error condition */
- uds_fd_table[minor].sel_ops_out |= SEL_WR;
+ if (ops & SEL_WR) {
+ bytes = uds_perform_write(minor, NONE, GRANT_INVALID, PIPE_BUF,
+ 1);
+ if (bytes != 0 && bytes != SUSPEND) {
+ /* There is room to write or there is an error
+ * condition.
+ */
+ ready_ops |= SEL_WR;
+ }
}
- uds_fd_table[minor].syscall_done = 1;
- uds_sel_reply(dev_m_out, DEV_SEL_REPL1, minor,
- uds_fd_table[minor].sel_ops_out);
+ /* If not all requested ops were ready, and the caller requests to be
+ * notified about changes, we add the remaining ops to the saved set.
+ */
+ ops &= ~ready_ops;
+ if (ops && watch) {
+ uds_fd_table[minor].sel_endpt = endpt;
+ uds_fd_table[minor].sel_ops |= ops;
+ }
- return uds_fd_table[minor].sel_ops_out;
+ return ready_ops;
}
-static int uds_perform_read(int minor, endpoint_t m_source,
- size_t size, int pretend)
+static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant, size_t size, int pretend)
{
int rc, peer;
message fs_m_in;
peer = uds_fd_table[minor].peer;
+ /* skip reads and writes of 0 (or less!) bytes */
if (size <= 0) {
return 0;
}
/* check if we are allowed to read */
if (!(uds_fd_table[minor].mode & S_IRUSR)) {
-
/* socket is shutdown for reading */
return EPIPE;
}
- /* skip reads and writes of 0 (or less!) bytes */
if (uds_fd_table[minor].size == 0) {
-
if (peer == -1) {
/* We're not connected. That's only a problem when this
* socket is connection oriented. */
return 0;
}
-
if (pretend) {
return SUSPEND;
}
/* maybe a process is blocked waiting to write? if
* needed revive the writer
*/
- if (peer != -1 && uds_fd_table[peer].suspended) {
- uds_fd_table[peer].ready_to_revive = 1;
- uds_unsuspend(m_source, peer);
- }
+ if (peer != -1 &&
+ uds_fd_table[peer].suspended == UDS_SUSPENDED_WRITE)
+ uds_unsuspend(peer);
#if DEBUG == 1
printf("(uds) [%d] suspending read request\n", minor);
/* Process is reading from an empty pipe,
* suspend it so some bytes can be written
*/
- uds_fd_table[minor].suspended = UDS_SUSPENDED_READ;
- return SUSPEND;
+ return EDONTREPLY;
}
if (pretend) {
-
return (size > uds_fd_table[minor].size) ?
uds_fd_table[minor].size : size;
}
-
/* Prepare Request to the FS side of PFS */
+ fs_m_in.m_source = endpt;
fs_m_in.m_type = REQ_READ;
fs_m_in.REQ_INODE_NR = uds_fd_table[minor].inode_nr;
- fs_m_in.REQ_GRANT = uds_fd_table[minor].io_gr;
+ fs_m_in.REQ_GRANT = grant;
fs_m_in.REQ_SEEK_POS_HI = 0;
fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[minor].pos;
fs_m_in.REQ_NBYTES = (size > uds_fd_table[minor].size) ?
/* perform the read */
rc = fs_readwrite(&fs_m_in, &fs_m_out);
if (rc != OK) {
- perror("fs_readwrite");
+ printf("PFS: fs_readwrite returned %d\n", rc);
return rc;
}
/* maybe a big write was waiting for us to read some data, if
* needed revive the writer
*/
- if (peer != -1 && uds_fd_table[peer].suspended) {
- uds_fd_table[peer].ready_to_revive = 1;
- uds_unsuspend(m_source, peer);
- }
+ if (peer != -1 && uds_fd_table[peer].suspended == UDS_SUSPENDED_WRITE)
+ uds_unsuspend(peer);
- /* see if peer is blocked on select() and a write is possible
- * (from peer to minor)
+ /* see if peer is blocked on select() and a write is possible (from
+ * peer to minor); if the peer wants to know about write being possible
+ * and it doesn't know about it already, then let the peer know.
*/
- if (peer != -1 && uds_fd_table[peer].selecting == 1 &&
+ if (peer != -1 && (uds_fd_table[peer].sel_ops & SEL_WR) &&
(uds_fd_table[minor].size+uds_fd_table[minor].pos + 1 < PIPE_BUF)){
-
- /* if the peer wants to know about write being possible
- * and it doesn't know about it already, then let the peer know.
- */
- if (peer != -1 && (uds_fd_table[peer].sel_ops_in & SEL_WR) &&
- !(uds_fd_table[peer].sel_ops_out & SEL_WR)) {
-
- /* a write on peer is possible now */
- uds_fd_table[peer].sel_ops_out |= SEL_WR;
- uds_fd_table[peer].status_updated = 1;
- uds_unsuspend(m_source, peer);
- }
+ /* a write on peer is possible now */
+ chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
+ SEL_WR);
+ uds_fd_table[peer].sel_ops &= ~SEL_WR;
}
return fs_m_out.RES_NBYTES; /* return number of bytes read */
}
-static int uds_perform_write(int minor, endpoint_t m_source,
- size_t size, int pretend)
+static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant, size_t size, int pretend)
{
int rc, peer, i;
message fs_m_in;
/* check if we are allowed to write */
if (!(uds_fd_table[minor].mode & S_IWUSR)) {
-
/* socket is shutdown for writing */
return EPIPE;
}
if (size > PIPE_BUF) {
-
/* message is too big to ever write to the PIPE */
return EMSGSIZE;
}
if (uds_fd_table[minor].type == SOCK_STREAM ||
uds_fd_table[minor].type == SOCK_SEQPACKET) {
-
/* if we're writing with a connection oriented socket,
* then it needs a peer to write to
*/
return ENOTCONN;
}
} else {
-
peer = uds_fd_table[minor].peer;
}
-
} else /* uds_fd_table[minor].type == SOCK_DGRAM */ {
-
peer = -1;
/* locate the "peer" we want to write to */
}
/* if needed revive the reader */
- if (uds_fd_table[peer].suspended) {
- uds_fd_table[peer].ready_to_revive = 1;
- uds_unsuspend(m_source, peer);
- }
+ if (uds_fd_table[peer].suspended == UDS_SUSPENDED_READ)
+ uds_unsuspend(peer);
#if DEBUG == 1
printf("(uds) [%d] suspending write request\n", minor);
/* Process is reading from an empty pipe,
* suspend it so some bytes can be written
*/
- uds_fd_table[minor].suspended = UDS_SUSPENDED_WRITE;
- return SUSPEND;
+ return EDONTREPLY;
}
if (pretend) {
}
/* Prepare Request to the FS side of PFS */
+ fs_m_in.m_source = endpt;
fs_m_in.m_type = REQ_WRITE;
fs_m_in.REQ_INODE_NR = uds_fd_table[peer].inode_nr;
- fs_m_in.REQ_GRANT = uds_fd_table[minor].io_gr;
+ fs_m_in.REQ_GRANT = grant;
fs_m_in.REQ_SEEK_POS_HI = 0;
fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[peer].pos +
uds_fd_table[peer].size;
/* Request the write */
rc = fs_readwrite(&fs_m_in, &fs_m_out);
if (rc != OK) {
- perror("fs_readwrite");
+ printf("PFS: fs_readwrite returned %d\n", rc);
return rc;
}
/* increase the count of unread bytes */
uds_fd_table[peer].size += fs_m_out.RES_NBYTES;
-
/* fill in the source address to be returned by recvfrom & recvmsg */
if (uds_fd_table[minor].type == SOCK_DGRAM) {
memcpy(&uds_fd_table[peer].source, &uds_fd_table[minor].addr,
}
/* revive peer that was waiting for us to write */
- if (uds_fd_table[peer].suspended) {
- uds_fd_table[peer].ready_to_revive = 1;
- uds_unsuspend(m_source, peer);
- }
-
- /* see if peer is blocked on select()*/
- if (uds_fd_table[peer].selecting == 1 && fs_m_out.RES_NBYTES > 0) {
-
- /* if the peer wants to know about data ready to read
- * and it doesn't know about it already, then let the peer
- * know we have data for it.
- */
- if ((uds_fd_table[peer].sel_ops_in & SEL_RD) &&
- !(uds_fd_table[peer].sel_ops_out & SEL_RD)) {
+ if (uds_fd_table[peer].suspended == UDS_SUSPENDED_READ)
+ uds_unsuspend(peer);
- /* a read on peer is possible now */
- uds_fd_table[peer].sel_ops_out |= SEL_RD;
- uds_fd_table[peer].status_updated = 1;
- uds_unsuspend(m_source, peer);
- }
+ /* see if peer is blocked on select(); if the peer wants to know about
+ * data ready to read and it doesn't know about it already, then let
+ * the peer know we have data for it.
+ */
+ if ((uds_fd_table[peer].sel_ops & SEL_RD) && fs_m_out.RES_NBYTES > 0) {
+ /* a read on peer is possible now */
+ chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
+ SEL_RD);
+ uds_fd_table[peer].sel_ops &= ~SEL_RD;
}
return fs_m_out.RES_NBYTES; /* return number of bytes written */
}
-int uds_read(message *dev_m_in, message *dev_m_out)
+static ssize_t uds_read(devminor_t minor, u64_t position, endpoint_t endpt,
+ cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
{
- int bytes;
- int minor;
+ ssize_t rc;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] uds_read() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
- printf("Endpoint: 0x%x | Position 0x%x\n", dev_m_in->USER_ENDPT,
- dev_m_in->POSITION);
+ printf("(uds) [%d] uds_read() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
+ if (minor < 0 || minor >= NR_FDS) return ENXIO;
if (uds_fd_table[minor].state != UDS_INUSE) {
-
- /* attempted to close a socket that hasn't been opened --
+ /* attempted to read from a socket that hasn't been opened --
* something is very wrong :(
*/
- uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
-
return EINVAL;
}
- /* track the system call we are performing in case it gets cancelled */
- uds_fd_table[minor].call_nr = dev_m_in->m_type;
- uds_fd_table[minor].ioctl = 0;
- uds_fd_table[minor].syscall_done = 0;
+ rc = uds_perform_read(minor, endpt, grant, size, 0);
- /* Update the process endpoint. */
- uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
-
- /* setup select(2) framework */
- uds_fd_table[minor].selecting = 0;
-
- /* save I/O Grant info */
- uds_fd_table[minor].io_gr = (cp_grant_id_t) dev_m_in->IO_GRANT;
- uds_fd_table[minor].io_gr_size = dev_m_in->COUNT;
+ /* If the call couldn't complete, suspend the caller. */
+ if (rc == EDONTREPLY) {
+ uds_fd_table[minor].suspended = UDS_SUSPENDED_READ;
+ uds_fd_table[minor].susp_endpt = endpt;
+ uds_fd_table[minor].susp_grant = grant;
+ uds_fd_table[minor].susp_size = size;
+ uds_fd_table[minor].susp_id = id;
- bytes = uds_perform_read(minor, dev_m_in->m_source,
- uds_fd_table[minor].io_gr_size, 0);
+ /* If the call wasn't supposed to block, cancel immediately. */
+ if (flags & FLG_OP_NONBLOCK) {
+ uds_cancel(minor, endpt, id);
- uds_set_reply(dev_m_out, DEV_REVIVE, uds_fd_table[minor].endpoint,
- uds_fd_table[minor].io_gr, bytes);
+ rc = EAGAIN;
+ }
+ }
- return bytes;
+ return rc;
}
-int uds_write(message *dev_m_in, message *dev_m_out)
+static ssize_t uds_write(devminor_t minor, u64_t position, endpoint_t endpt,
+ cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
{
- int bytes;
- int minor;
+ ssize_t rc;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] uds_write() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
- printf("Endpoint: 0x%x | Position 0x%x\n", dev_m_in->USER_ENDPT,
- dev_m_in->POSITION);
+ printf("(uds) [%d] uds_write() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
+ if (minor < 0 || minor >= NR_FDS) return ENXIO;
if (uds_fd_table[minor].state != UDS_INUSE) {
-
/* attempted to write to a socket that hasn't been opened --
* something is very wrong :(
*/
- uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
-
return EINVAL;
}
- /* track the system call we are performing in case it gets cancelled */
- uds_fd_table[minor].call_nr = dev_m_in->m_type;
- uds_fd_table[minor].ioctl = 0;
- uds_fd_table[minor].syscall_done = 0;
-
- /* Update the process endpoint. */
- uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
-
- /* setup select(2) framework */
- uds_fd_table[minor].selecting = 0;
+ rc = uds_perform_write(minor, endpt, grant, size, 0);
- /* save I/O Grant info */
- uds_fd_table[minor].io_gr = (cp_grant_id_t) dev_m_in->IO_GRANT;
- uds_fd_table[minor].io_gr_size = dev_m_in->COUNT;
+ /* If the call couldn't complete, suspend the caller. */
+ if (rc == EDONTREPLY) {
+ uds_fd_table[minor].suspended = UDS_SUSPENDED_WRITE;
+ uds_fd_table[minor].susp_endpt = endpt;
+ uds_fd_table[minor].susp_grant = grant;
+ uds_fd_table[minor].susp_size = size;
+ uds_fd_table[minor].susp_id = id;
- bytes = uds_perform_write(minor, dev_m_in->m_source,
- uds_fd_table[minor].io_gr_size, 0);
+ /* If the call wasn't supposed to block, cancel immediately. */
+ if (flags & FLG_OP_NONBLOCK) {
+ uds_cancel(minor, endpt, id);
- uds_set_reply(dev_m_out, DEV_REVIVE, uds_fd_table[minor].endpoint,
- uds_fd_table[minor].io_gr, bytes);
+ rc = EAGAIN;
+ }
+ }
- return bytes;
+ return rc;
}
-int uds_ioctl(message *dev_m_in, message *dev_m_out)
+static int uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+ cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id)
{
- int rc, minor;
+ int rc;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] uds_ioctl() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
- printf("Endpoint: 0x%x | Position 0x%x\n", dev_m_in->USER_ENDPT,
- dev_m_in->POSITION);
+ printf("(uds) [%d] uds_ioctl() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
+ if (minor < 0 || minor >= NR_FDS) return ENXIO;
if (uds_fd_table[minor].state != UDS_INUSE) {
-
- /* attempted to close a socket that hasn't been opened --
- * something is very wrong :(
+ /* attempted to perform I/O control on a socket that hasn't
+ * been opened -- something is very wrong :(
*/
- uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
-
return EINVAL;
}
- /* track the system call we are performing in case it gets cancelled */
- uds_fd_table[minor].call_nr = dev_m_in->m_type;
- uds_fd_table[minor].ioctl = dev_m_in->COUNT;
- uds_fd_table[minor].syscall_done = 0;
-
- /* setup select(2) framework */
- uds_fd_table[minor].selecting = 0;
-
- /* update the owner endpoint - yes it's really stored in POSITION */
- uds_fd_table[minor].owner = dev_m_in->POSITION;
-
- /* update the process endpoint, which may well be different */
- uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
-
- /* save I/O Grant info */
- uds_fd_table[minor].io_gr = (cp_grant_id_t) dev_m_in->IO_GRANT;
- uds_fd_table[minor].io_gr_size = 0; /* should not be used here */
-
- switch (dev_m_in->COUNT) { /* Handle the ioctl(2) command */
-
- case NWIOSUDSCONN:
-
- /* connect to a listening socket -- connect() */
- rc = do_connect(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOSUDSACCEPT:
-
- /* accept an incoming connection -- accept() */
- rc = do_accept(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOSUDSBLOG:
-
- /* set the backlog_size and put the socket into the
- * listening state -- listen()
- */
- rc = do_listen(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOSUDSTYPE:
-
- /* set the type for this socket (i.e.
- * SOCK_STREAM, SOCK_DGRAM, etc) -- socket()
- */
- rc = do_socket(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOSUDSADDR:
-
- /* set the address for this socket -- bind() */
- rc = do_bind(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOGUDSADDR:
-
- /* get the address for this socket -- getsockname() */
- rc = do_getsockname(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOGUDSPADDR:
-
- /* get the address for the peer -- getpeername() */
- rc = do_getpeername(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOSUDSSHUT:
-
- /* shutdown a socket for reading, writing, or
- * both -- shutdown()
- */
- rc = do_shutdown(dev_m_in, dev_m_out);
+ /* update the owner endpoint */
+ uds_fd_table[minor].owner = user_endpt;
- break;
-
- case NWIOSUDSPAIR:
-
- /* connect two sockets -- socketpair() */
- rc = do_socketpair(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOGUDSSOTYPE:
+ /* let the UDS subsystem handle the actual request */
+ rc = uds_do_ioctl(minor, request, endpt, grant);
- /* get socket type -- getsockopt(SO_TYPE) */
- rc = do_getsockopt_sotype(dev_m_in, dev_m_out);
-
- break;
+ /* If the call couldn't complete, suspend the caller. */
+ if (rc == EDONTREPLY) {
+ /* The suspension type is already set by the IOCTL handler. */
+ if (uds_fd_table[minor].suspended == UDS_NOT_SUSPENDED)
+ panic("IOCTL did not actually suspend?");
+ uds_fd_table[minor].susp_endpt = endpt;
+ uds_fd_table[minor].susp_grant = grant;
+ uds_fd_table[minor].susp_size = 0; /* irrelevant */
+ uds_fd_table[minor].susp_id = id;
- case NWIOGUDSPEERCRED:
-
- /* get peer endpoint -- getsockopt(SO_PEERCRED) */
- rc = do_getsockopt_peercred(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOSUDSTADDR:
-
- /* set target address -- sendto() */
- rc = do_sendto(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOGUDSFADDR:
-
- /* get from address -- recvfrom() */
- rc = do_recvfrom(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOGUDSSNDBUF:
-
- /* get the send buffer size -- getsockopt(SO_SNDBUF) */
- rc = do_getsockopt_sndbuf(dev_m_in, dev_m_out);
-
- break;
+ /* If the call wasn't supposed to block, cancel immediately. */
+ if (flags & FLG_OP_NONBLOCK) {
+ uds_cancel(minor, endpt, id);
- case NWIOSUDSSNDBUF:
-
- /* set the send buffer size -- setsockopt(SO_SNDBUF) */
- rc = do_setsockopt_sndbuf(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOGUDSRCVBUF:
-
- /* get the send buffer size -- getsockopt(SO_SNDBUF) */
- rc = do_getsockopt_rcvbuf(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOSUDSRCVBUF:
-
- /* set the send buffer size -- setsockopt(SO_SNDBUF) */
- rc = do_setsockopt_rcvbuf(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOSUDSCTRL:
-
- /* set the control data -- sendmsg() */
- rc = do_sendmsg(dev_m_in, dev_m_out);
-
- break;
-
- case NWIOGUDSCTRL:
-
- /* set the control data -- recvmsg() */
- rc = do_recvmsg(dev_m_in, dev_m_out);
-
- break;
-
- default:
-
- /* the IOCTL command is not valid for /dev/uds --
- * this happens a lot and is normal. a lot of
- * libc functions determine the socket type with
- * IOCTLs. Any not for us simply get a EBADIOCTL
- * response.
- */
-
- rc = EBADIOCTL;
+ rc = EAGAIN;
+ }
}
- if (rc != SUSPEND)
- uds_fd_table[minor].syscall_done = 1;
-
- uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, rc);
-
return rc;
}
-int uds_unsuspend(endpoint_t m_source, int minor)
+void uds_unsuspend(devminor_t minor)
{
- int r = OK, bytes;
- message m_out;
+ int r;
uds_fd_t *fdp;
fdp = &uds_fd_table[minor];
- if (fdp->status_updated == 1) {
-
- /* clear the status_updated flag */
- fdp->status_updated = 0;
- fdp->selecting = 0;
+ switch (fdp->suspended) {
+ case UDS_SUSPENDED_READ:
+ r = uds_perform_read(minor, fdp->susp_endpt, fdp->susp_grant,
+ fdp->susp_size, 0);
- /* prepare the response */
- uds_sel_reply(&m_out, DEV_SEL_REPL2, minor, fdp->sel_ops_out);
- } else if (fdp->ready_to_revive == 1) {
+ if (r == EDONTREPLY)
+ return;
- /* clear the ready to revive flag */
- fdp->ready_to_revive = 0;
+ break;
- switch (fdp->suspended) {
+ case UDS_SUSPENDED_WRITE:
+ r = uds_perform_write(minor, fdp->susp_endpt, fdp->susp_grant,
+ fdp->susp_size, 0);
- case UDS_SUSPENDED_READ:
+ if (r == EDONTREPLY)
+ return;
- bytes = uds_perform_read(minor, m_source,
- fdp->io_gr_size, 0);
-
- if (bytes == SUSPEND) {
- r = SUSPEND;
- break;
- }
+ break;
- fdp->suspended = UDS_NOT_SUSPENDED;
-
- uds_set_reply(&m_out, DEV_REVIVE, fdp->endpoint,
- fdp->io_gr, bytes);
-
- break;
-
- case UDS_SUSPENDED_WRITE:
-
- bytes = uds_perform_write(minor, m_source,
- fdp->io_gr_size, 0);
-
- if (bytes == SUSPEND) {
- r = SUSPEND;
- break;
- }
-
- fdp->suspended = UDS_NOT_SUSPENDED;
-
- uds_set_reply(&m_out, DEV_REVIVE, fdp->endpoint,
- fdp->io_gr, bytes);
-
- break;
-
- case UDS_SUSPENDED_CONNECT:
- case UDS_SUSPENDED_ACCEPT:
-
- /* In both cases, the process
- * that send the notify()
- * already performed the connection.
- * The only thing to do here is
- * unblock.
- */
-
- fdp->suspended = UDS_NOT_SUSPENDED;
-
- uds_set_reply(&m_out, DEV_REVIVE, fdp->endpoint,
- fdp->io_gr, OK);
-
- break;
+ case UDS_SUSPENDED_CONNECT:
+ case UDS_SUSPENDED_ACCEPT:
+ /* In both cases, the caller already set up the connection.
+ * The only thing to do here is unblock.
+ */
+ r = OK;
- default:
- return(OK);
- }
+ break;
+ default:
+ panic("unknown suspension type %d", fdp->suspended);
}
- if (r == OK) reply(m_source, &m_out);
- return(r);
+ chardriver_reply_task(fdp->susp_endpt, fdp->susp_id, r);
+
+ fdp->suspended = UDS_NOT_SUSPENDED;
}
-int uds_cancel(message *dev_m_in, message *dev_m_out)
+static int uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
{
+ uds_fd_t *fdp;
int i, j;
- int minor;
- /* XXX: should become a noop? */
+
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] uds_cancel() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
- printf("Endpoint: 0x%x\n", dev_m_in->USER_ENDPT);
+ printf("(uds) [%d] uds_cancel() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
+ if (minor < 0 || minor >= NR_FDS) return EDONTREPLY;
- if (uds_fd_table[minor].state != UDS_INUSE) {
- /* attempted to cancel an unknown request - this happens */
- return SUSPEND;
- }
+ fdp = &uds_fd_table[minor];
- /* Update the process endpoint. */
- uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
+ if (fdp->state != UDS_INUSE) {
+ printf("PFS: cancel request for closed minor %d\n", minor);
+ return EDONTREPLY;
+ }
- /* setup select(2) framework */
- uds_fd_table[minor].selecting = 0;
+ /* Make sure the cancel request is for a request we're hanging on. */
+ if (fdp->suspended == UDS_NOT_SUSPENDED || fdp->susp_endpt != endpt ||
+ fdp->susp_id != id) {
+ return EDONTREPLY; /* this happens. */
+ }
- /* the system call was cancelled, so if the socket was suspended
- * (which is likely the case), then it is not suspended anymore.
+ /* The system call was cancelled, so the socket is not suspended
+ * anymore.
*/
- uds_fd_table[minor].suspended = UDS_NOT_SUSPENDED;
-
- /* If there is a system call and it isn't complete, roll back */
- if (uds_fd_table[minor].call_nr && !uds_fd_table[minor].syscall_done) {
-
-
- if (uds_fd_table[minor].call_nr == DEV_IOCTL_S) {
-
- switch (uds_fd_table[minor].ioctl) {
-
- case NWIOSUDSACCEPT: /* accept() */
-
- /* partial accept() only changes
- * uds_fd_table[minorparent].child
- */
-
- for (i = 0; i < NR_FDS; i++) {
- if (uds_fd_table[i].child ==
- minor) {
-
- uds_fd_table[i].child = -1;
-
- }
- }
-
- break;
-
- case NWIOSUDSCONN: /* connect() */
+ switch (fdp->suspended) {
+ case UDS_SUSPENDED_ACCEPT: /* accept() */
+ /* partial accept() only changes
+ * uds_fd_table[minorparent].child
+ */
+ for (i = 0; i < NR_FDS; i++) {
+ if (uds_fd_table[i].child == minor) {
+ uds_fd_table[i].child = -1;
+ }
+ }
- /* partial connect() sets addr
- * and adds minor to server backlog
- */
+ break;
- for (i = 0; i < NR_FDS; i++) {
+ case UDS_SUSPENDED_CONNECT: /* connect() */
+ /* partial connect() sets addr and adds minor to server backlog
+ */
- /* find a socket that is in
- * use.
- */
- if (uds_fd_table[i].state ==
- UDS_INUSE) {
+ for (i = 0; i < NR_FDS; i++) {
+ /* find a socket that is in use. */
+ if (uds_fd_table[i].state != UDS_INUSE)
+ continue;
- /* see if minor is in
- * the backlog
- */
+ /* see if minor is in the backlog */
for (j = 0; j < uds_fd_table[i].backlog_size; j++) {
-
if (uds_fd_table[i].backlog[j] == minor) {
/* remove from backlog */
uds_fd_table[i].backlog[j] = -1;
}
}
+ }
- }
- }
-
- /* clear the address */
- memset(&(uds_fd_table[minor].addr),
- '\0',
- sizeof(struct sockaddr_un));
-
- break;
+ /* clear the address */
+ memset(&(uds_fd_table[minor].addr), '\0',
+ sizeof(struct sockaddr_un));
- case NWIOSUDSTADDR: /* sendto() */
- case NWIOSUDSADDR: /* bind() */
- case NWIOGUDSADDR: /* getsockname() */
- case NWIOGUDSPADDR: /* getpeername() */
- case NWIOSUDSTYPE: /* socket() */
- case NWIOSUDSBLOG: /* listen() */
- case NWIOSUDSSHUT: /* shutdown() */
- case NWIOSUDSPAIR: /* socketpair() */
- case NWIOGUDSSOTYPE: /* SO_TYPE */
- case NWIOGUDSPEERCRED: /* SO_PEERCRED */
- default:
- /* these are atomic, never suspend,
- * and can't be cancelled once called
- */
- break;
- }
+ break;
- }
-
- /* DEV_READ_S or DEV_WRITE_S don't need to do anything
- * when cancelled. DEV_OPEN, DEV_REOPEN, DEV_SELECT,
- * DEV_CLOSE are atomic, never suspend, and can't
- * be cancelled once called.
- */
+ case UDS_SUSPENDED_READ:
+ case UDS_SUSPENDED_WRITE:
+ /* Nothing more to do. */
+ break;
- uds_fd_table[minor].syscall_done = 1;
+ default:
+ panic("unknown suspension type %d", fdp->suspended);
}
- uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
- (cp_grant_id_t) dev_m_in->IO_GRANT, EINTR);
+ fdp->suspended = UDS_NOT_SUSPENDED;
- return EINTR;
+ return EINTR; /* reply to the original request */
}
EXTERN int err_code; /* temporary storage for error number */
EXTERN int(*fs_call_vec[]) (message *fs_m_in, message *fs_m_out);
-EXTERN int(*dev_call_vec[]) (message *fs_m_in, message *fs_m_out);
-EXTERN uid_t caller_uid;
-EXTERN gid_t caller_gid;
-EXTERN int req_nr;
-EXTERN int SELF_E;
EXTERN int exitsignaled;
EXTERN int busy;
EXTERN int unmountdone;
/*===========================================================================*
* alloc_inode *
*===========================================================================*/
-struct inode *alloc_inode(dev_t dev, pmode_t bits)
+struct inode *alloc_inode(dev_t dev, pmode_t bits, uid_t uid, gid_t gid)
{
/* Allocate a free inode on 'dev', and return a pointer to it. */
rip->i_mode = bits; /* set up RWX bits */
rip->i_nlinks = NO_LINK; /* initial no links */
- rip->i_uid = caller_uid; /* file's uid is owner's */
- rip->i_gid = caller_gid; /* ditto group id */
+ rip->i_uid = uid; /* set file user id */
+ rip->i_gid = gid; /* ditto group id */
/* Fields not cleared already are cleared in wipe_inode(). They have
* been put there because truncate() needs to clear the same fields if
#include "inode.h"
#include "uds.h"
-static void get_work(message *m_in);
+static void get_work(message *m_in, int *status);
/* SEF functions and variables. */
static void sef_local_startup(void);
* three major activities: getting new work, processing the work, and
* sending the reply. The loop never terminates, unless a panic occurs.
*/
- int ind, do_reply, transid;
+ int ind, transid, req_nr, ipc_status;
message pfs_m_in;
message pfs_m_out;
+ endpoint_t src;
/* SEF local startup. */
env_setargs(argc, argv);
sef_local_startup();
while(!unmountdone || !exitsignaled) {
- endpoint_t src;
-
- do_reply = 1;
/* Wait for request message. */
- get_work(&pfs_m_in);
+ get_work(&pfs_m_in, &ipc_status);
+
+ /* If this is a UDS device request, process it and continue. */
+ if (IS_DEV_RQ(pfs_m_in.m_type)) {
+ uds_request(&pfs_m_in, ipc_status);
+
+ continue;
+ }
transid = TRNS_GET_ID(pfs_m_in.m_type);
pfs_m_in.m_type = TRNS_DEL_ID(pfs_m_in.m_type);
assert(IS_VFS_FS_TRANSID(transid) || transid == 0);
src = pfs_m_in.m_source;
- caller_uid = INVAL_UID; /* To trap errors */
- caller_gid = INVAL_GID;
req_nr = pfs_m_in.m_type;
- if (IS_DEV_RQ(req_nr)) {
- ind = req_nr - DEV_RQ_BASE;
- if (ind < 0 || ind >= DEV_CALL_VEC_SIZE) {
- printf("pfs: bad DEV request %d\n", req_nr);
- pfs_m_out.m_type = EINVAL;
- } else {
- int result;
- result = (*dev_call_vec[ind])(&pfs_m_in, &pfs_m_out);
- if (pfs_m_out.REP_STATUS == SUSPEND ||
- result == SUSPEND) {
- /* Nothing to tell, so not replying */
- do_reply = 0;
- }
- }
- } else if (IS_VFS_RQ(req_nr)) {
+ if (IS_VFS_RQ(req_nr)) {
ind = req_nr - VFS_BASE;
if (ind < 0 || ind >= FS_CALL_VEC_SIZE) {
printf("pfs: bad FS request %d\n", req_nr);
pfs_m_out.m_type = EINVAL;
}
- if (do_reply) {
- if (IS_VFS_RQ(req_nr) && IS_VFS_FS_TRANSID(transid)) {
- pfs_m_out.m_type = TRNS_ADD_ID(pfs_m_out.m_type,
- transid);
- }
- reply(src, &pfs_m_out);
+ if (IS_VFS_RQ(req_nr) && IS_VFS_FS_TRANSID(transid)) {
+ pfs_m_out.m_type = TRNS_ADD_ID(pfs_m_out.m_type, transid);
}
+ reply(src, &pfs_m_out);
}
return(OK);
}
panic("unable to drop privileges");
}
- SELF_E = getprocnr();
-
return(OK);
}
/*===========================================================================*
* get_work *
*===========================================================================*/
-static void get_work(m_in)
-message *m_in; /* pointer to message */
+static void get_work(message * m_in, int *status)
{
- int r, srcok = 0, status;
+ int r, srcok = 0;
endpoint_t src;
do {
/* wait for a message */
- if ((r = sef_receive_status(ANY, m_in, &status)) != OK)
+ if ((r = sef_receive_status(ANY, m_in, status)) != OK)
panic("sef_receive_status failed: %d", r);
src = m_in->m_source;
endpoint_t who;
message *m_out; /* report result */
{
- if (OK != send(who, m_out)) /* send the message */
- printf("PFS(%d) was unable to send reply\n", SELF_E);
+ int r;
+
+ if (OK != (r = send(who, m_out))) /* send the message */
+ printf("PFS: unable to send reply: %d\n", r);
}
register int r = OK;
pmode_t bits;
struct inode *rip;
+ uid_t uid;
+ gid_t gid;
dev_t dev;
- caller_uid = (uid_t) fs_m_in->REQ_UID;
- caller_gid = (gid_t) fs_m_in->REQ_GID;
+ uid = (uid_t) fs_m_in->REQ_UID;
+ gid = (gid_t) fs_m_in->REQ_GID;
bits = (pmode_t) fs_m_in->REQ_MODE;
dev = (dev_t) fs_m_in->REQ_DEV;
/* Try to allocate the inode */
- if( (rip = alloc_inode(dev, bits) ) == NULL) return(err_code);
+ if( (rip = alloc_inode(dev, bits, uid, gid) ) == NULL) return(err_code);
switch (bits & S_IFMT) {
case S_IFBLK:
void buf_pool(void);
/* inode.c */
-struct inode *alloc_inode(dev_t dev, pmode_t mode);
+struct inode *alloc_inode(dev_t dev, pmode_t mode, uid_t uid, gid_t gid);
void dup_inode(struct inode *ip);
struct inode *find_inode(pino_t numb);
void free_inode(struct inode *rip);
void free_bit(bit_t bit_returned);
/* dev_uds.c */
-int uds_open(message *dev_m_in, message *dev_m_out);
-int uds_close(message *dev_m_in, message *dev_m_out);
-int uds_read(message *dev_m_in, message *dev_m_out);
-int uds_write(message *dev_m_in, message *dev_m_out);
-int uds_ioctl(message *dev_m_in, message *dev_m_out);
-int uds_select(message *dev_m_in, message *dev_m_out);
-int uds_unsuspend(endpoint_t m_source, int minor);
-int uds_cancel(message *dev_m_in, message *dev_m_out);
+void uds_request(message *m_ptr, int ipc_status);
+void uds_unsuspend(devminor_t minor);
/* uds.c */
void uds_init(void);
-int do_accept(message *dev_m_in, message *dev_m_out);
-int do_connect(message *dev_m_in, message *dev_m_out);
-int do_listen(message *dev_m_in, message *dev_m_out);
-int do_socket(message *dev_m_in, message *dev_m_out);
-int do_bind(message *dev_m_in, message *dev_m_out);
-int do_getsockname(message *dev_m_in, message *dev_m_out);
-int do_getpeername(message *dev_m_in, message *dev_m_out);
-int do_shutdown(message *dev_m_in, message *dev_m_out);
-int do_socketpair(message *dev_m_in, message *dev_m_out);
-int do_getsockopt_sotype(message *dev_m_in, message *dev_m_out);
-int do_getsockopt_peercred(message *dev_m_in, message *dev_m_out);
-int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out);
-int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out);
-int do_getsockopt_rcvbuf(message *dev_m_in, message *dev_m_out);
-int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out);
-int do_sendto(message *dev_m_in, message *dev_m_out);
-int do_recvfrom(message *dev_m_in, message *dev_m_out);
-int do_sendmsg(message *dev_m_in, message *dev_m_out);
-int do_recvmsg(message *dev_m_in, message *dev_m_out);
-int perform_connection(message *dev_m_in, message *dev_m_out, struct
- sockaddr_un *addr, int minorx, int minory);
-int clear_fds(int minor, struct ancillary *data);
+int uds_clear_fds(devminor_t minor, struct ancillary *data);
+int uds_do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+ cp_grant_id_t grant);
#endif
if (rw_flag == READING) {
/* Copy a chunk from the block buffer to user space. */
- r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
+ r = sys_safecopyto(fs_m_in->m_source, gid, (vir_bytes) 0,
(vir_bytes) (bp->b_data+position), (size_t) nrbytes);
} else {
/* Copy a chunk from user space to the block buffer. */
- r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) 0,
+ r = sys_safecopyfrom(fs_m_in->m_source, gid, (vir_bytes) 0,
(vir_bytes) (bp->b_data+position), (size_t) nrbytes);
}
-/* This file contains the table used to map system call numbers onto the
+/* This file contains the table used to map VFS/FS call numbers onto the
* routines that perform them.
*/
#define _TABLE
+#include "inc.h"
#include "fs.h"
#include "inode.h"
#include "buf.h"
/* File System Handlers (pfs) */
int (*fs_call_vec[])(message *fs_m_in, message *fs_m_out) = {
-
no_sys, /* 0 not used */
no_sys, /* 1 */
fs_putnode, /* 2 */
no_sys, /* 31 */
no_sys, /* 32 */
};
-
-/* Device Handlers (/dev/uds) */
-int (*dev_call_vec[])(message *dev_m_in, message *dev_m_out) = {
-
- uds_cancel, /* 0 CANCEL */
- no_sys, /* 1 */
- no_sys, /* 2 */
- no_sys, /* 3 */
- no_sys, /* 4 */
- no_sys, /* 5 */
- uds_open, /* 6 DEV_OPEN */
- uds_close, /* 7 DEV_CLOSE */
- no_sys, /* 8 */
- no_sys, /* 9 */
- no_sys, /* 10 */
- no_sys, /* 11 */
- uds_select, /* 12 DEV_SELECT */
- no_sys, /* 13 */
- uds_open, /* 14 DEV_REOPEN */
- no_sys, /* 15 */
- no_sys, /* 16 */
- no_sys, /* 17 */
- no_sys, /* 18 */
- no_sys, /* 19 */
- uds_read, /* 20 DEV_READ_S */
- uds_write, /* 21 DEV_WRITE_S */
- no_sys, /* 22 DEV_SCATTER_S */
- no_sys, /* 23 DEV_GATHER_S */
- uds_ioctl, /* 24 DEV_IOCTL_S */
- no_sys, /* 25 DEV_MMAP_S */
-};
* The entry points into this file are...
*
* uds_init: initialize the descriptor table.
- * do_accept: handles the accept(2) syscall.
- * do_connect: handles the connect(2) syscall.
- * do_listen: handles the listen(2) syscall.
- * do_socket: handles the socket(2) syscall.
- * do_bind: handles the bind(2) syscall.
- * do_getsockname: handles the getsockname(2) syscall.
- * do_getpeername: handles the getpeername(2) syscall.
- * do_shutdown: handles the shutdown(2) syscall.
- * do_socketpair: handles the socketpair(2) syscall.
- * do_getsockopt_sotype: handles the getsockopt(2) syscall.
- * do_getsockopt_peercred: handles the getsockopt(2) syscall.
- * do_getsockopt_sndbuf: handles the getsockopt(2) syscall.
- * do_setsockopt_sndbuf: handles the setsockopt(2) syscall.
- * do_getsockopt_rcvbuf: handles the getsockopt(2) syscall.
- * do_setsockopt_rcvbuf: handles the setsockopt(2) syscall.
- * do_sendto: handles the sendto(2) syscall.
- * do_recvfrom: handles the recvfrom(2) syscall.
- * do_sendmsg: handles the sendmsg(2) syscall.
- * do_recvmsg: handles the recvmsg(2) syscall.
- * perform_connection: performs the connection of two descriptors.
- * clear_fds: calls put_filp for undelivered FDs.
+ * uds_do_ioctl: process an IOCTL request.
+ * uds_clear_fds: calls put_filp for undelivered FDs.
*
* Also see...
*
- * table.c, dev_uds.c, uds.h
+ * dev_uds.c, uds.h
*/
#define DEBUG 0
}
/* check the permissions of a socket file */
-static int check_perms(int minor, struct sockaddr_un *addr)
+static int check_perms(devminor_t minor, struct sockaddr_un *addr)
{
int rc;
message vfs_m;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) set_filp(0x%x) call_count=%d\n", sfilp, ++call_count);
+ printf("(uds) set_filp(%p) call_count=%d\n", sfilp, ++call_count);
#endif
memset(&vfs_m, '\0', sizeof(message));
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) copy_filp(%d, 0x%x) call_count=%d\n",to_ep, cfilp,
+ printf("(uds) copy_filp(%d, %p) call_count=%d\n",to_ep, cfilp,
++call_count);
#endif
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) put_filp(0x%x) call_count=%d\n", pfilp, ++call_count);
+ printf("(uds) put_filp(%p) call_count=%d\n", pfilp, ++call_count);
#endif
memset(&vfs_m, '\0', sizeof(message));
return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
}
-int perform_connection(message *dev_m_in, message *dev_m_out,
- struct sockaddr_un *addr, int minorx, int minory)
+static int perform_connection(devminor_t minorx, devminor_t minory,
+ struct sockaddr_un *addr)
{
/* there are several places were a connection is established. */
/* accept(2), connect(2), uds_status(2), socketpair(2) */
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] perform_connection() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] perform_connection() call_count=%d\n", minorx,
+ ++call_count);
#endif
/* only connection oriented types are acceptable and only like
return OK;
}
-
-int do_accept(message *dev_m_in, message *dev_m_out)
+static int do_accept(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int minor;
- int minorparent; /* minor number of parent (server) */
- int minorpeer;
+ devminor_t minorparent; /* minor number of parent (server) */
+ devminor_t minorpeer;
int rc, i;
struct sockaddr_un addr;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_accept() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_accept() call_count=%d\n", minor, ++call_count);
#endif
/* Somewhat weird logic is used in this function, so here's an
* connection or suspend and wait for a connect().
*/
- minor = uds_minor(dev_m_in);
-
if (uds_fd_table[minor].type != -1) {
/* this IOCTL must be called on a 'fresh' socket */
return EINVAL;
}
/* Get the server's address */
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+ sizeof(struct sockaddr_un));
if (rc != OK) {
return EIO;
rc = -1; /* to trap error */
for (i = 0; i < NR_FDS; i++) {
-
if (uds_fd_table[i].addr.sun_family == AF_UNIX &&
!strncmp(addr.sun_path,
uds_fd_table[i].addr.sun_path,
*/
uds_fd_table[minor].suspended = UDS_SUSPENDED_ACCEPT;
- return SUSPEND;
+ return EDONTREPLY;
}
#if DEBUG == 1
minorpeer, minorparent);
#endif
- rc = perform_connection(dev_m_in, dev_m_out, &addr, minor, minorpeer);
+ rc = perform_connection(minor, minorpeer, &addr);
if (rc != OK) {
#if DEBUG == 1
printf("(uds) [%d] {do_accept} connection not performed\n",
printf("(uds) [%d] {do_accept} revive %d\n", minor,
minorpeer);
#endif
- uds_fd_table[minorpeer].ready_to_revive = 1;
- uds_unsuspend(dev_m_in->m_source, minorpeer);
+ uds_unsuspend(minorpeer);
}
return OK;
}
-int do_connect(message *dev_m_in, message *dev_m_out)
+static int do_connect(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int minor, child;
+ int child;
struct sockaddr_un addr;
int rc, i, j;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_connect() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
+ printf("(uds) [%d] do_connect() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
/* only connection oriented sockets can connect */
if (uds_fd_table[minor].type != SOCK_STREAM &&
uds_fd_table[minor].type != SOCK_SEQPACKET) {
return EISCONN;
}
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &addr,
- sizeof(struct sockaddr_un));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+ sizeof(struct sockaddr_un));
if (rc != OK) {
return EIO;
* address we want to connect to
*/
for (i = 0; i < NR_FDS; i++) {
-
if (uds_fd_table[minor].type == uds_fd_table[i].type &&
uds_fd_table[i].listening &&
uds_fd_table[i].addr.sun_family == AF_UNIX &&
* perform connection to the child
*/
- rc = perform_connection(dev_m_in, dev_m_out,
- &addr, minor, child);
+ rc = perform_connection(minor, child, &addr);
if (rc == OK) {
-
uds_fd_table[i].child = -1;
#if DEBUG == 1
#endif
/* wake the parent (server) */
- uds_fd_table[child].ready_to_revive =
- 1;
- uds_unsuspend(dev_m_in->m_source,
- child);
+ uds_unsuspend(child);
}
return rc;
-
} else {
-
#if DEBUG == 1
printf("(uds) [%d] adding to %d's backlog\n",
minor, i);
}
if (rc == -1) {
-
/* backlog is full */
break;
}
/* see if the server is blocked on select() */
- if (uds_fd_table[i].selecting == 1) {
-
- /* if the server wants to know
- * about data ready to read and
- * it doesn't know about it
- * already, then let the server
- * know we have data for it.
+ if (uds_fd_table[i].sel_ops & SEL_RD) {
+ /* if the server wants to know about
+ * data ready to read and it doesn't
+ * doesn't know about it already, then
+ * let the server know we have data for
+ * it.
*/
- if ((uds_fd_table[i].sel_ops_in &
- SEL_RD) &&
- !(uds_fd_table[i].sel_ops_out &
- SEL_RD)) {
-
- uds_fd_table[i].sel_ops_out |=
- SEL_RD;
- uds_fd_table[i].status_updated
- = 1;
-
- uds_unsuspend(
- dev_m_in->m_source, i);
- }
+ chardriver_reply_select(
+ uds_fd_table[i].sel_endpt, i,
+ SEL_RD);
+
+ uds_fd_table[i].sel_ops &= ~SEL_RD;
}
/* we found our server */
uds_fd_table[minor].suspended = UDS_SUSPENDED_CONNECT;
- return SUSPEND;
+ return EDONTREPLY;
}
-int do_listen(message *dev_m_in, message *dev_m_out)
+static int do_listen(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int minor;
int rc;
int backlog_size;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_listen() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
+ printf("(uds) [%d] do_listen() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
/* ensure the socket has a type and is bound */
if (uds_fd_table[minor].type == -1 ||
uds_fd_table[minor].addr.sun_family != AF_UNIX) {
* let it happen, but if listen() has already been called, we
* don't allow the backlog to shrink
*/
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &backlog_size, sizeof(int));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &backlog_size,
+ sizeof(int));
if (rc != OK) {
return EIO;
return OK;
}
-int do_socket(message *dev_m_in, message *dev_m_out)
+static int do_socket(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
int rc;
- int minor;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_socket() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
+ printf("(uds) [%d] do_socket() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
/* see if this socket already has a type */
if (uds_fd_table[minor].type != -1) {
/* socket type can only be set once */
}
/* get the requested type */
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type),
- sizeof(int));
+ rc = sys_safecopyfrom(endpt, grant, 0,
+ (vir_bytes) &uds_fd_table[minor].type, sizeof(int));
if (rc != OK) {
-
/* something went wrong and we couldn't get the type */
return EIO;
}
case SOCK_STREAM:
case SOCK_DGRAM:
case SOCK_SEQPACKET:
-
/* the type is one of the 3 valid socket types */
return OK;
default:
-
/* if the type isn't one of the 3 valid socket
* types, then it must be invalid.
*/
}
}
-int do_bind(message *dev_m_in, message *dev_m_out)
+static int do_bind(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int minor;
struct sockaddr_un addr;
int rc, i;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_bind() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
+ printf("(uds) [%d] do_bind() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
if ((uds_fd_table[minor].type == -1) ||
(uds_fd_table[minor].addr.sun_family == AF_UNIX &&
uds_fd_table[minor].type != SOCK_DGRAM)) {
return EINVAL;
}
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+ sizeof(struct sockaddr_un));
if (rc != OK) {
return EIO;
/* do some basic sanity checks on the address */
if (addr.sun_family != AF_UNIX) {
-
/* bad family */
return EAFNOSUPPORT;
}
if (addr.sun_path[0] == '\0') {
-
/* bad address */
return ENOENT;
}
return OK;
}
-int do_getsockname(message *dev_m_in, message *dev_m_out)
+static int do_getsockname(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant)
{
- int minor;
int rc;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_getsockname() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_getsockname() call_count=%d\n", minor,
+ ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
/* Unconditionally send the address we have assigned to this socket.
* The POSIX standard doesn't say what to do if the address
* hasn't been set. If the address isn't currently set, then
* the user will get NULL bytes. Note: libc depends on this
* behavior.
*/
- rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].addr),
+ rc = sys_safecopyto(endpt, grant, 0,
+ (vir_bytes) &uds_fd_table[minor].addr,
sizeof(struct sockaddr_un));
return rc ? EIO : OK;
}
-int do_getpeername(message *dev_m_in, message *dev_m_out)
+static int do_getpeername(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant)
{
- int minor;
int rc;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_getpeername() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_getpeername() call_count=%d\n", minor,
+ ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
/* check that the socket is connected with a valid peer */
if (uds_fd_table[minor].peer != -1) {
int peer_minor;
peer_minor = uds_fd_table[minor].peer;
/* copy the address from the peer */
- rc = sys_safecopyto(VFS_PROC_NR,
- (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0,
- (vir_bytes) &(uds_fd_table[peer_minor].addr),
+ rc = sys_safecopyto(endpt, grant, 0,
+ (vir_bytes) &uds_fd_table[peer_minor].addr,
sizeof(struct sockaddr_un));
return rc ? EIO : OK;
}
}
-int do_shutdown(message *dev_m_in, message *dev_m_out)
+static int do_shutdown(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int minor;
int rc, how;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_shutdown() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_shutdown() call_count=%d\n", minor,
+ ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
if (uds_fd_table[minor].type != SOCK_STREAM &&
uds_fd_table[minor].type != SOCK_SEQPACKET) {
}
/* get the 'how' parameter from the process */
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &how, sizeof(int));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &how, sizeof(int));
if (rc != OK) {
return EIO;
return OK;
}
-int do_socketpair(message *dev_m_in, message *dev_m_out)
+static int do_socketpair(devminor_t minorx, endpoint_t endpt,
+ cp_grant_id_t grant)
{
int rc;
dev_t minorin;
- int minorx, minory;
+ devminor_t minory;
struct sockaddr_un addr;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_socketpair() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_socketpair() call_count=%d\n", minorx,
+ ++call_count);
#endif
- /* first ioctl param is the first socket */
- minorx = uds_minor(dev_m_in);
-
- /* third ioctl param is the minor number of the second socket */
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &minorin, sizeof(dev_t));
+ /* ioctl argument is the minor number of the second socket */
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &minorin,
+ sizeof(dev_t));
if (rc != OK) {
return EIO;
/* security check - both sockets must have the same endpoint (owner) */
if (uds_fd_table[minorx].owner != uds_fd_table[minory].owner) {
-
/* we won't allow you to magically connect your socket to
* someone elses socket
*/
addr.sun_path[0] = 'X';
addr.sun_path[1] = '\0';
- uds_fd_table[minorx].syscall_done = 1;
- return perform_connection(dev_m_in, dev_m_out, &addr, minorx, minory);
+ return perform_connection(minorx, minory, &addr);
}
-int do_getsockopt_sotype(message *dev_m_in, message *dev_m_out)
+static int do_getsockopt_sotype(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant)
{
- int minor;
int rc;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_getsockopt_sotype() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_getsockopt_sotype() call_count=%d\n", minor,
+ ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
if (uds_fd_table[minor].type == -1) {
-
/* the type hasn't been set yet. instead of returning an
* invalid type, we fail with EINVAL
*/
return EINVAL;
}
- rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type),
- sizeof(int));
+ rc = sys_safecopyto(endpt, grant, 0,
+ (vir_bytes) &uds_fd_table[minor].type, sizeof(int));
return rc ? EIO : OK;
}
-int do_getsockopt_peercred(message *dev_m_in, message *dev_m_out)
+static int do_getsockopt_peercred(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant)
{
- int minor;
int peer_minor;
int rc;
struct uucred cred;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n", minor,
+ ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
if (uds_fd_table[minor].peer == -1) {
if (uds_fd_table[minor].err == ECONNRESET) {
return errno;
}
- rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &cred, sizeof(struct uucred));
+ rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &cred,
+ sizeof(struct uucred));
return rc ? EIO : OK;
}
-int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
+static int do_getsockopt_sndbuf(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant)
{
int rc;
size_t sndbuf = PIPE_BUF;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_getsockopt_sndbuf() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_getsockopt_sndbuf() call_count=%d\n", minor,
+ ++call_count);
#endif
- rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &(sndbuf), sizeof(size_t));
+ rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &sndbuf,
+ sizeof(size_t));
return rc ? EIO : OK;
}
-int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
+static int do_setsockopt_sndbuf(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant)
{
int rc;
size_t sndbuf;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n", minor,
+ ++call_count);
#endif
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &sndbuf,
- sizeof(size_t));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &sndbuf,
+ sizeof(size_t));
if (rc != OK) {
return EIO;
return OK;
}
-int do_getsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
+static int do_getsockopt_rcvbuf(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant)
{
int rc;
size_t rcvbuf = PIPE_BUF;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_getsockopt_rcvbuf() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_getsockopt_rcvbuf() call_count=%d\n", minor,
+ ++call_count);
#endif
- rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &(rcvbuf), sizeof(size_t));
+ rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &rcvbuf,
+ sizeof(size_t));
return rc ? EIO : OK;
}
-int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
+static int do_setsockopt_rcvbuf(devminor_t minor, endpoint_t endpt,
+ cp_grant_id_t grant)
{
int rc;
size_t rcvbuf;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n", minor,
+ ++call_count);
#endif
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &rcvbuf,
- sizeof(size_t));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &rcvbuf,
+ sizeof(size_t));
if (rc != OK) {
return EIO;
return OK;
}
-
-int do_sendto(message *dev_m_in, message *dev_m_out)
+static int do_sendto(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int minor;
int rc;
struct sockaddr_un addr;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_sendto() call_count=%d\n", uds_minor(dev_m_in),
- ++call_count);
+ printf("(uds) [%d] do_sendto() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
if (uds_fd_table[minor].type != SOCK_DGRAM) {
/* This IOCTL is only for SOCK_DGRAM sockets */
return EINVAL;
}
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+ sizeof(struct sockaddr_un));
if (rc != OK) {
return EIO;
return OK;
}
-int do_recvfrom(message *dev_m_in, message *dev_m_out)
+static int do_recvfrom(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int minor;
int rc;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_recvfrom() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_recvfrom() call_count=%d\n", minor,
+ ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
- rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].source),
+ rc = sys_safecopyto(endpt, grant, 0,
+ (vir_bytes) &uds_fd_table[minor].source,
sizeof(struct sockaddr_un));
return rc ? EIO : OK;
}
-int msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
- int minor)
+static int msg_control_read(struct msg_control *msg_ctrl,
+ struct ancillary *data, devminor_t minor)
{
int rc;
struct msghdr msghdr;
return OK;
}
-static int send_fds(int minor, struct ancillary *data)
+static int send_fds(devminor_t minor, struct ancillary *data)
{
int rc, i, j;
return OK;
}
-int clear_fds(int minor, struct ancillary *data)
+int uds_clear_fds(devminor_t minor, struct ancillary *data)
{
/* This function calls put_filp() for all of the FDs in data.
* This is used when a Unix Domain Socket is closed and there
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
+ printf("(uds) [%d] uds_clear_fds() call_count=%d\n", minor,
++call_count);
#endif
for (i = 0; i < data->nfiledes; i++) {
put_filp(data->filps[i]);
#if DEBUG == 1
- printf("(uds) clear_fds() => %d\n", data->fds[i]);
+ printf("(uds) uds_clear_fds() => %d\n", data->fds[i]);
#endif
data->fds[i] = -1;
data->filps[i] = NULL;
return OK;
}
-static int recv_fds(int minor, struct ancillary *data,
+static int recv_fds(devminor_t minor, struct ancillary *data,
struct msg_control *msg_ctrl)
{
int rc, i, j;
return OK;
}
-static int recv_cred(int minor, struct ancillary *data,
+static int recv_cred(devminor_t minor, struct ancillary *data,
struct msg_control *msg_ctrl)
{
struct msghdr msghdr;
return OK;
}
-int do_sendmsg(message *dev_m_in, message *dev_m_out)
+static int do_sendmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int minor, peer, rc, i;
+ int peer, rc, i;
struct msg_control msg_ctrl;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_sendmsg() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
+ printf("(uds) [%d] do_sendmsg() call_count=%d\n", minor, ++call_count);
#endif
- minor = uds_minor(dev_m_in);
-
memset(&msg_ctrl, '\0', sizeof(struct msg_control));
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &msg_ctrl,
- sizeof(struct msg_control));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &msg_ctrl,
+ sizeof(struct msg_control));
if (rc != OK) {
return EIO;
return send_fds(minor, &uds_fd_table[peer].ancillary_data);
}
-int do_recvmsg(message *dev_m_in, message *dev_m_out)
+static int do_recvmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int minor;
int rc;
struct msg_control msg_ctrl;
socklen_t controllen_avail = 0;
#if DEBUG == 1
static int call_count = 0;
- printf("(uds) [%d] do_sendmsg() call_count=%d\n",
- uds_minor(dev_m_in), ++call_count);
-#endif
-
- minor = uds_minor(dev_m_in);
-
-
-#if DEBUG == 1
+ printf("(uds) [%d] do_sendmsg() call_count=%d\n", minor, ++call_count);
printf("(uds) [%d] CREDENTIALS {pid:%d,uid:%d,gid:%d}\n", minor,
uds_fd_table[minor].ancillary_data.cred.pid,
uds_fd_table[minor].ancillary_data.cred.uid,
/* get the msg_control from the user, it will include the
* amount of space the user has allocated for control data.
*/
- rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &msg_ctrl,
- sizeof(struct msg_control));
+ rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &msg_ctrl,
+ sizeof(struct msg_control));
if (rc != OK) {
return EIO;
}
/* send the user the control data */
- rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
- (vir_bytes) 0, (vir_bytes) &msg_ctrl,
+ rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &msg_ctrl,
sizeof(struct msg_control));
return rc ? EIO : OK;
}
+
+int uds_do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+ cp_grant_id_t grant)
+{
+ int rc;
+
+ switch (request) { /* Handle the ioctl(2) command */
+ case NWIOSUDSCONN:
+ /* connect to a listening socket -- connect() */
+ rc = do_connect(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSACCEPT:
+ /* accept an incoming connection -- accept() */
+ rc = do_accept(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSBLOG:
+ /* set the backlog_size and put the socket into the listening
+ * state -- listen()
+ */
+ rc = do_listen(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSTYPE:
+ /* set the type for this socket (i.e. SOCK_STREAM, SOCK_DGRAM,
+ * etc) -- socket()
+ */
+ rc = do_socket(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSADDR:
+ /* set the address for this socket -- bind() */
+ rc = do_bind(minor, endpt, grant);
+
+ break;
+
+ case NWIOGUDSADDR:
+ /* get the address for this socket -- getsockname() */
+ rc = do_getsockname(minor, endpt, grant);
+
+ break;
+
+ case NWIOGUDSPADDR:
+ /* get the address for the peer -- getpeername() */
+ rc = do_getpeername(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSSHUT:
+ /* shutdown a socket for reading, writing, or both --
+ * shutdown()
+ */
+ rc = do_shutdown(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSPAIR:
+ /* connect two sockets -- socketpair() */
+ rc = do_socketpair(minor, endpt, grant);
+
+ break;
+
+ case NWIOGUDSSOTYPE:
+ /* get socket type -- getsockopt(SO_TYPE) */
+ rc = do_getsockopt_sotype(minor, endpt, grant);
+
+ break;
+
+ case NWIOGUDSPEERCRED:
+ /* get peer endpoint -- getsockopt(SO_PEERCRED) */
+ rc = do_getsockopt_peercred(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSTADDR:
+ /* set target address -- sendto() */
+ rc = do_sendto(minor, endpt, grant);
+
+ break;
+
+ case NWIOGUDSFADDR:
+ /* get from address -- recvfrom() */
+ rc = do_recvfrom(minor, endpt, grant);
+
+ break;
+
+ case NWIOGUDSSNDBUF:
+ /* get the send buffer size -- getsockopt(SO_SNDBUF) */
+ rc = do_getsockopt_sndbuf(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSSNDBUF:
+ /* set the send buffer size -- setsockopt(SO_SNDBUF) */
+ rc = do_setsockopt_sndbuf(minor, endpt, grant);
+
+ break;
+
+ case NWIOGUDSRCVBUF:
+ /* get the send buffer size -- getsockopt(SO_SNDBUF) */
+ rc = do_getsockopt_rcvbuf(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSRCVBUF:
+ /* set the send buffer size -- setsockopt(SO_SNDBUF) */
+ rc = do_setsockopt_rcvbuf(minor, endpt, grant);
+
+ break;
+
+ case NWIOSUDSCTRL:
+ /* set the control data -- sendmsg() */
+ rc = do_sendmsg(minor, endpt, grant);
+
+ break;
+
+ case NWIOGUDSCTRL:
+ /* set the control data -- recvmsg() */
+ rc = do_recvmsg(minor, endpt, grant);
+
+ break;
+
+ default:
+ /* the IOCTL command is not valid for /dev/uds -- this happens
+ * a lot and is normal. a lot of libc functions determine the
+ * socket type with IOCTLs. Any not for us simply get an ENOTTY
+ * response.
+ */
+
+ rc = ENOTTY;
+ }
+
+ return rc;
+}
#include <sys/un.h>
#include <minix/endpoint.h>
+#include <minix/chardriver.h>
/* max connection backlog for incoming connections */
#define UDS_SOMAXCONN 64
/* Socket Owner */
endpoint_t owner;
- /* endpoint for suspend/resume */
- endpoint_t endpoint;
-
/* Pipe Housekeeping */
/* inode number on PFS -- each descriptor is backed by 1
/* Socket Info */
-
/* socket type - SOCK_STREAM, SOCK_DGRAM, or SOCK_SEQPACKET
* Set by uds_ioctl(NWIOSUDSTYPE). It defaults to -1 in
* uds_open(). Any action on a socket with type -1 besides
/* Suspend/Revive Housekeeping */
-
/* SUSPEND State Flags */
enum UDS_SUSPENDED {
UDS_SUSPENDED_ACCEPT = 8
} suspended;
- /* Flag (1 or 0) - thing socket was waiting for is ready.
- * If 1, then uds_status() will attempt the operation that
- * the socket was blocked on.
- */
- int ready_to_revive;
+ /* source endpoint, saved for later use by suspended procs */
+ endpoint_t susp_endpt;
/* i/o grant, saved for later use by suspended procs */
- cp_grant_id_t io_gr;
-
- /* is of i/o grant, saved for later use by suspended procs */
- size_t io_gr_size;
-
- /* Save the call number so that uds_cancel() can unwind the
- * call properly.
- */
- int call_nr;
+ cp_grant_id_t susp_grant;
- /* Save the IOCTL so uds_cancel() knows what got cancelled. */
- int ioctl;
+ /* size of request, saved for later use by suspended procs */
+ size_t susp_size;
- /* Flag (1 or 0) - the system call completed.
- * A doc I read said DEV_CANCEL might be called even though
- * the operation is finished. We use this variable to
- * determine if we should rollback the changes or not.
- */
- int syscall_done;
+ /* request ID, saved for later use by suspended procs */
+ cdev_id_t susp_id;
/* select() */
- /* Flag (1 or 0) - the process blocked on select(2). When
- * selecting is 1 and I/O happens on this socket, then
- * select_proc should be notified.
- */
- int selecting;
-
/* when a select is in progress, we notify() this endpoint
* of new data.
*/
- endpoint_t select_proc;
+ endpoint_t sel_endpt;
/* Options (SEL_RD, SEL_WR, SEL_ERR) that are requested. */
- int sel_ops_in;
-
- /* Options that are available for this socket. */
- int sel_ops_out;
-
- /* Flag (1 or 0) to be set to one before calling notify().
- * uds_status() will use the flag to locate this descriptor.
- */
- int status_updated;
+ unsigned int sel_ops;
};
typedef struct uds_fd uds_fd_t;
/* File Descriptor Table -- Defined in uds.c */
EXTERN uds_fd_t uds_fd_table[NR_FDS];
-/*
- * Take message m and get the index in uds_fd_table.
- */
-#define uds_minor(m) (minor((dev_t) m->DEVICE))
-
-/*
- * Fill in a reply message.
- */
-#define uds_set_reply(msg,type,endpoint,io_gr,status) \
- do { \
- (msg)->m_type = type; \
- (msg)->REP_ENDPT = endpoint; \
- (msg)->REP_IO_GRANT = io_gr; \
- (msg)->REP_STATUS = status; \
- } while (0)
-
-#define uds_sel_reply(msg,type,minor,ops) \
- do { \
- (msg)->m_type = type; \
- (msg)->DEV_MINOR = minor; \
- (msg)->DEV_SEL_OPS = ops; \
- } while (0)
-
-
-
-
#endif
int no_sys(message *pfs_m_in, message *pfs_m_out)
{
/* Somebody has used an illegal system call number */
- printf("no_sys: invalid call 0x%x to pfs\n", req_nr);
+ printf("no_sys: invalid call 0x%x to pfs\n", pfs_m_in->m_type);
return(EINVAL);
}