* The entry points into this file are...
*
* uds_do_ioctl: process an IOCTL request.
- * uds_clear_fds: calls put_filp for undelivered FDs.
+ * uds_clear_fds: calls vfs_put_filp for undelivered FDs.
*/
#include "uds.h"
-/*
- * Check the permissions of a socket file.
- */
-static int
-check_perms(devminor_t minor, struct sockaddr_un *addr)
-{
- int rc;
- message vfs_m;
- cp_grant_id_t grant_id;
-
- grant_id = cpf_grant_direct(VFS_PROC_NR, (vir_bytes) addr->sun_path,
- UNIX_PATH_MAX, CPF_READ | CPF_WRITE);
-
- /* ask the VFS to verify the permissions */
- memset(&vfs_m, '\0', sizeof(message));
-
- vfs_m.m_type = VFS_UDS_CHECK_PERMS;
- vfs_m.VFS_UDS_ENDPT = uds_fd_table[minor].owner;
- vfs_m.VFS_UDS_GRANT = grant_id;
- vfs_m.VFS_UDS_COUNT = UNIX_PATH_MAX;
-
- rc = sendrec(VFS_PROC_NR, &vfs_m);
- cpf_revoke(grant_id);
- if (OK != rc) {
- printf("(uds) sendrec error... req_nr: %d err: %d\n",
- vfs_m.m_type, rc);
-
- return EIO;
- }
-
-#if DEBUG == 1
- printf("(uds) VFS reply => %d\n", vfs_m.m_type);
- printf("(uds) Canonical Path => %s\n", addr->sun_path);
-#endif
-
- return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
-}
-
-static filp_id_t
-verify_fd(endpoint_t ep, int fd)
-{
- int rc;
- message vfs_m;
-
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) verify_fd(%d,%d) call_count=%d\n", ep, fd,
- ++call_count);
-#endif
-
- memset(&vfs_m, '\0', sizeof(message));
-
- vfs_m.m_type = VFS_UDS_VERIFY_FD;
- vfs_m.VFS_UDS_ENDPT = ep;
- vfs_m.VFS_UDS_FD = fd;
-
- rc = sendrec(VFS_PROC_NR, &vfs_m);
- if (OK != rc) {
- printf("(uds) sendrec error... req_nr: %d err: %d\n",
- vfs_m.m_type, rc);
- return NULL;
- }
-
-#if DEBUG == 1
- printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
-
- return vfs_m.VFS_UDS_FILP;
-}
-
-static int
-set_filp(filp_id_t sfilp)
-{
- int rc;
- message vfs_m;
-
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) set_filp(%p) call_count=%d\n", sfilp, ++call_count);
-#endif
-
- memset(&vfs_m, '\0', sizeof(message));
-
- vfs_m.m_type = VFS_UDS_SET_FILP;
- vfs_m.VFS_UDS_FILP = sfilp;
-
- rc = sendrec(VFS_PROC_NR, &vfs_m);
- if (OK != rc) {
- printf("(uds) sendrec error... req_nr: %d err: %d\n",
- vfs_m.m_type, rc);
- return EIO;
- }
-
-#if DEBUG == 1
- printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
- return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
-}
-
-static int
-copy_filp(endpoint_t to_ep, filp_id_t cfilp)
-{
- int rc;
- message vfs_m;
-
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) copy_filp(%d, %p) call_count=%d\n",to_ep, cfilp,
- ++call_count);
-#endif
-
- memset(&vfs_m, '\0', sizeof(message));
-
- vfs_m.m_type = VFS_UDS_COPY_FILP;
- vfs_m.VFS_UDS_ENDPT = to_ep;
- vfs_m.VFS_UDS_FILP = cfilp;
-
- rc = sendrec(VFS_PROC_NR, &vfs_m);
- if (OK != rc) {
- printf("(uds) sendrec error... req_nr: %d err: %d\n",
- vfs_m.m_type, rc);
- return EIO;
- }
-
-#if DEBUG == 1
- printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
- return vfs_m.m_type;
-}
-
-static int
-put_filp(filp_id_t pfilp)
-{
- int rc;
- message vfs_m;
-
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) put_filp(%p) call_count=%d\n", pfilp, ++call_count);
-#endif
-
- memset(&vfs_m, '\0', sizeof(message));
-
- vfs_m.m_type = VFS_UDS_PUT_FILP;
- vfs_m.VFS_UDS_FILP = pfilp;
-
- rc = sendrec(VFS_PROC_NR, &vfs_m);
- if (OK != rc) {
- printf("(uds) sendrec error... req_nr: %d err: %d\n",
- vfs_m.m_type, rc);
- return EIO;
- }
-
-#if DEBUG == 1
- printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
- return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
-}
-
-static int
-cancel_fd(endpoint_t ep, int fd)
-{
- int rc;
- message vfs_m;
-
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) cancel_fd(%d,%d) call_count=%d\n", ep, fd, ++call_count);
-#endif
-
- memset(&vfs_m, '\0', sizeof(message));
-
- vfs_m.m_type = VFS_UDS_CANCEL_FD;
- vfs_m.VFS_UDS_ENDPT = ep;
- vfs_m.VFS_UDS_FD = fd;
-
- rc = sendrec(VFS_PROC_NR, &vfs_m);
- if (OK != rc) {
- printf("(uds) sendrec error... req_nr: %d err: %d\n",
- vfs_m.m_type, rc);
- return EIO;
- }
-
-#if DEBUG == 1
- printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
- return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
-}
-
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) */
- /* This is a helper function to make sure it is done in the */
- /* same way in each place with the same validation checks. */
-
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] perform_connection() call_count=%d\n", minorx,
- ++call_count);
-#endif
-
- /* only connection oriented types are acceptable and only like
- * types can connect to each other
+ /*
+ * There are several places were a connection is established, the
+ * initiating call being one of accept(2), connect(2), socketpair(2).
*/
- if ((uds_fd_table[minorx].type != SOCK_SEQPACKET &&
- uds_fd_table[minorx].type != SOCK_STREAM) ||
- uds_fd_table[minorx].type != uds_fd_table[minory].type) {
+ dprintf(("UDS: perform_connection(%d, %d)\n", minorx, minory));
- /* sockets are not in a valid state */
+ /*
+ * Only connection-oriented types are acceptable and only equal
+ * types can connect to each other.
+ */
+ if ((uds_fd_table[minorx].type != SOCK_SEQPACKET &&
+ uds_fd_table[minorx].type != SOCK_STREAM) ||
+ uds_fd_table[minorx].type != uds_fd_table[minory].type)
return EINVAL;
- }
- /* connect the pair of sockets */
+ /* Connect the pair of sockets. */
uds_fd_table[minorx].peer = minory;
uds_fd_table[minory].peer = minorx;
/* Set the address of both sockets */
- memcpy(&(uds_fd_table[minorx].addr), addr, sizeof(struct sockaddr_un));
- memcpy(&(uds_fd_table[minory].addr), addr, sizeof(struct sockaddr_un));
+ memcpy(&uds_fd_table[minorx].addr, addr, sizeof(struct sockaddr_un));
+ memcpy(&uds_fd_table[minory].addr, addr, sizeof(struct sockaddr_un));
return OK;
}
int rc, i;
struct sockaddr_un addr;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_accept() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: do_accept(%d)\n", minor));
- /* Somewhat weird logic is used in this function, so here's an
+ /*
+ * Somewhat weird logic is used in this function, so here's an
* overview... The minor number is the server's client socket
* (the socket to be returned by accept()). The data waiting
* for us in the IO Grant is the address that the server is
* connection or suspend and wait for a connect().
*/
- if (uds_fd_table[minor].type != -1) {
- /* this IOCTL must be called on a 'fresh' socket */
+ /* This IOCTL must be called on a 'fresh' socket. */
+ if (uds_fd_table[minor].type != -1)
return EINVAL;
- }
/* Get the server's address */
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
- sizeof(struct sockaddr_un));
-
- if (rc != OK) {
- return EIO;
- }
-
- /* locate server socket */
- rc = -1; /* to trap error */
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+ sizeof(struct sockaddr_un))) != OK)
+ return rc;
+ /* Locate the server socket. */
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,
- UNIX_PATH_MAX) &&
- uds_fd_table[i].listening == 1) {
-
- rc = 0;
+ !strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path,
+ UNIX_PATH_MAX) && uds_fd_table[i].listening == 1)
break;
- }
}
- if (rc == -1) {
- /* there is no server listening on addr. Maybe someone
- * screwed up the ioctl()?
- */
+ if (i == NR_FDS)
return EINVAL;
- }
minorparent = i; /* parent */
- /* we are the parent's child */
+ /* We are the parent's child. */
uds_fd_table[minorparent].child = minor;
- /* the peer has the same type as the parent. we need to be that
+ /*
+ * The peer has the same type as the parent. we need to be that
* type too.
*/
uds_fd_table[minor].type = uds_fd_table[minorparent].type;
- /* locate peer to accept in the parent's backlog */
- minorpeer = -1; /* to trap error */
+ /* Locate the peer to accept in the parent's backlog. */
+ minorpeer = -1;
for (i = 0; i < uds_fd_table[minorparent].backlog_size; i++) {
if (uds_fd_table[minorparent].backlog[i] != -1) {
minorpeer = uds_fd_table[minorparent].backlog[i];
uds_fd_table[minorparent].backlog[i] = -1;
- rc = 0;
break;
}
}
if (minorpeer == -1) {
+ dprintf(("UDS: do_accept(%d): suspend\n", minor));
-#if DEBUG == 1
- printf("(uds) [%d] {do_accept} suspend\n", minor);
-#endif
-
- /* there are no peers in the backlog, suspend and wait
- * for some to show up
+ /*
+ * There are no peers in the backlog, suspend and wait for one
+ * to show up.
*/
uds_fd_table[minor].suspended = UDS_SUSPENDED_ACCEPT;
return EDONTREPLY;
}
-#if DEBUG == 1
- printf("(uds) [%d] connecting to %d -- parent is %d\n", minor,
- minorpeer, minorparent);
-#endif
-
- rc = perform_connection(minor, minorpeer, &addr);
- if (rc != OK) {
-#if DEBUG == 1
- printf("(uds) [%d] {do_accept} connection not performed\n",
- minor);
-#endif
+ dprintf(("UDS: connecting %d to %d -- parent is %d\n", minor,
+ minorpeer, minorparent));
+
+ if ((rc = perform_connection(minor, minorpeer, &addr)) != OK) {
+ dprintf(("UDS: do_accept(%d): connection failed\n", minor));
+
return rc;
}
uds_fd_table[minorparent].child = -1;
- /* if peer is blocked on connect() revive peer */
+ /* If the peer is blocked on connect(), revive the peer. */
if (uds_fd_table[minorpeer].suspended) {
-#if DEBUG == 1
- printf("(uds) [%d] {do_accept} revive %d\n", minor,
- minorpeer);
-#endif
+ dprintf(("UDS: do_accept(%d): revive %d\n", minor, minorpeer));
uds_unsuspend(minorpeer);
}
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", minor, ++call_count);
-#endif
+ dprintf(("UDS: do_connect(%d)\n", minor));
- /* only connection oriented sockets can connect */
+ /* Only connection oriented sockets can connect. */
if (uds_fd_table[minor].type != SOCK_STREAM &&
- uds_fd_table[minor].type != SOCK_SEQPACKET) {
+ uds_fd_table[minor].type != SOCK_SEQPACKET)
return EINVAL;
- }
- if (uds_fd_table[minor].peer != -1) {
- /* socket is already connected */
+ /* The socket must not be connected already. */
+ if (uds_fd_table[minor].peer != -1)
return EISCONN;
- }
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
- sizeof(struct sockaddr_un));
-
- if (rc != OK) {
- return EIO;
- }
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+ sizeof(struct sockaddr_un))) != OK)
+ return rc;
- rc = check_perms(minor, &addr);
- if (rc != OK) {
- /* permission denied, socket file doesn't exist, etc. */
+ if ((rc = vfs_check_perms(uds_fd_table[minor].owner, &addr)) != OK)
return rc;
- }
- /* look for a socket of the same type that is listening on the
- * address we want to connect to
+ /*
+ * Look for a socket of the same type that is listening on the
+ * 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 &&
- !strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path,
- UNIX_PATH_MAX)) {
-
- if ((child = uds_fd_table[i].child) != -1) {
-
- /* the server is blocked on accept(2) --
- * perform connection to the child
- */
-
- rc = perform_connection(minor, child, &addr);
-
- if (rc == OK) {
- uds_fd_table[i].child = -1;
-
-#if DEBUG == 1
- printf("(uds) [%d] {do_connect} revive %d\n", minor, child);
-#endif
-
- /* wake the parent (server) */
- uds_unsuspend(child);
- }
-
- return rc;
- } else {
-#if DEBUG == 1
- printf("(uds) [%d] adding to %d's backlog\n",
- minor, i);
-#endif
-
- /* tell the server were waiting to be served */
-
- /* look for a free slot in the backlog */
- rc = -1; /* to trap error */
- for (j = 0; j < uds_fd_table[i].backlog_size;
- j++) {
-
- if (uds_fd_table[i].backlog[j] == -1) {
-
- uds_fd_table[i].backlog[j] =
- minor;
-
- rc = 0;
- break;
- }
- }
-
- if (rc == -1) {
- /* backlog is full */
- break;
- }
-
- /* see if the server is blocked on select() */
- if (uds_fd_table[i].sel_ops & CDEV_OP_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.
- */
- chardriver_reply_select(
- uds_fd_table[i].sel_endpt, i,
- CDEV_OP_RD);
-
- uds_fd_table[i].sel_ops &= ~CDEV_OP_RD;
- }
-
- /* we found our server */
- uds_fd_table[minor].peer = i;
-
- /* set the address */
- memcpy(&(uds_fd_table[minor].addr), &addr,
- sizeof(struct sockaddr_un));
+ if (uds_fd_table[minor].type != uds_fd_table[i].type)
+ continue;
+ if (!uds_fd_table[i].listening)
+ continue;
+ if (uds_fd_table[i].addr.sun_family != AF_UNIX)
+ continue;
+ if (strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path,
+ UNIX_PATH_MAX))
+ continue;
+
+ /* Found a matching socket. */
+ break;
+ }
- break;
- }
+ if (i == NR_FDS)
+ return ECONNREFUSED;
+
+ /* If the server is blocked on an accept, perform the connection. */
+ if ((child = uds_fd_table[i].child) != -1) {
+ rc = perform_connection(minor, child, &addr);
+
+ if (rc != OK)
+ return rc;
+
+ uds_fd_table[i].child = -1;
+
+ dprintf(("UDS: do_connect(%d): revive %d\n", minor, child));
+
+ /* Wake up the accepting party. */
+ uds_unsuspend(child);
+
+ return OK;
+ }
+
+ dprintf(("UDS: adding %d to %d's backlog\n", minor, i));
+
+ /* Look for a free slot in the backlog. */
+ rc = -1;
+ for (j = 0; j < uds_fd_table[i].backlog_size; j++) {
+ if (uds_fd_table[i].backlog[j] == -1) {
+ uds_fd_table[i].backlog[j] = minor;
+
+ rc = 0;
+ break;
}
}
- if (uds_fd_table[minor].peer == -1) {
- /* could not find another open socket listening on the
- * specified address with room in the backlog
- */
- return ECONNREFUSED;
+ if (rc == -1)
+ return ECONNREFUSED; /* backlog is full */
+
+ /* See if the server is blocked on select(). */
+ if (uds_fd_table[i].sel_ops & CDEV_OP_RD) {
+ /* Satisfy a read-type select on the server. */
+ chardriver_reply_select(uds_fd_table[i].sel_endpt, i,
+ CDEV_OP_RD);
+
+ uds_fd_table[i].sel_ops &= ~CDEV_OP_RD;
}
-#if DEBUG == 1
- printf("(uds) [%d] {do_connect} suspend\n", minor);
-#endif
+ /* We found our server. */
+ uds_fd_table[minor].peer = i;
- /* suspend until the server side completes the connection with accept()
- */
+ memcpy(&uds_fd_table[minor].addr, &addr, sizeof(struct sockaddr_un));
+
+ dprintf(("UDS: do_connect(%d): suspend\n", minor));
+ /* Suspend until the server side accepts the connection. */
uds_fd_table[minor].suspended = UDS_SUSPENDED_CONNECT;
return EDONTREPLY;
int rc;
int backlog_size;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_listen() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: do_listen(%d)\n", minor));
- /* ensure the socket has a type and is bound */
+ /* 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) {
-
- /* probably trying to call listen() before bind() */
+ uds_fd_table[minor].addr.sun_family != AF_UNIX)
return EINVAL;
- }
- /* the two supported types for listen(2) are SOCK_STREAM and
- * SOCK_SEQPACKET
- */
+ /* listen(2) supports only two socket types. */
if (uds_fd_table[minor].type != SOCK_STREAM &&
- uds_fd_table[minor].type != SOCK_SEQPACKET) {
-
- /* probably trying to call listen() with a SOCK_DGRAM */
+ uds_fd_table[minor].type != SOCK_SEQPACKET)
return EOPNOTSUPP;
- }
- /* The POSIX standard doesn't say what to do if listen() has
- * already been called. Well, there isn't an errno. we silently
+ /*
+ * The POSIX standard doesn't say what to do if listen() has
+ * already been called. Well, there isn't an errno. We silently
* let it happen, but if listen() has already been called, we
- * don't allow the backlog to shrink
+ * don't allow the backlog to shrink.
*/
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &backlog_size,
- sizeof(int));
-
- if (rc != OK) {
- return EIO;
- }
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &backlog_size,
+ sizeof(backlog_size))) != OK)
+ return rc;
if (uds_fd_table[minor].listening == 0) {
+ /* Set the backlog size to a reasonable value. */
+ if (backlog_size <= 0 || backlog_size > UDS_SOMAXCONN)
+ backlog_size = UDS_SOMAXCONN;
- /* See if backlog_size is between 0 and UDS_SOMAXCONN */
- if (backlog_size >= 0 && backlog_size < UDS_SOMAXCONN) {
-
- /* use the user provided backlog_size */
- uds_fd_table[minor].backlog_size = backlog_size;
-
- } else {
-
- /* the user gave an invalid size, use
- * UDS_SOMAXCONN instead
- */
- uds_fd_table[minor].backlog_size = UDS_SOMAXCONN;
- }
+ uds_fd_table[minor].backlog_size = backlog_size;
} else {
-
- /* See if the user is trying to expand the backlog_size */
+ /* Allow the user to expand the backlog size. */
if (backlog_size > uds_fd_table[minor].backlog_size &&
- backlog_size < UDS_SOMAXCONN) {
-
- /* expand backlog_size */
+ backlog_size < UDS_SOMAXCONN)
uds_fd_table[minor].backlog_size = backlog_size;
- }
- /* Don't let the user shrink the backlog_size (we might
- * have clients waiting in those slots
+ /*
+ * Don't let the user shrink the backlog_size, as we might
+ * have clients waiting in those slots.
*/
}
- /* perform listen(2) */
+ /* This socket is now listening. */
uds_fd_table[minor].listening = 1;
return OK;
static int
do_socket(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int rc;
+ int rc, type;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_socket() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: do_socket(%d)\n", minor));
- /* see if this socket already has a type */
- if (uds_fd_table[minor].type != -1) {
- /* socket type can only be set once */
+ /* The socket type can only be set once. */
+ if (uds_fd_table[minor].type != -1)
return EINVAL;
- }
- /* get the requested type */
- 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;
- }
-
- /* validate the type */
- switch (uds_fd_table[minor].type) {
- 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.
- */
+ /* Get the requested type. */
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &type,
+ sizeof(type))) != OK)
+ return rc;
- /* set the type back to '-1' (no type set) */
- uds_fd_table[minor].type = -1;
+ /* Assign the type if it is valid only. */
+ switch (type) {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ case SOCK_SEQPACKET:
+ uds_fd_table[minor].type = type;
+ return OK;
- return EINVAL;
+ default:
+ return EINVAL;
}
}
struct sockaddr_un addr;
int rc, i;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_bind() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: do_bind(%d)\n", minor));
+ /* If the type hasn't been set by do_socket() yet, OR an attempt
+ * to re-bind() a non-SOCK_DGRAM socket is made, fail the call.
+ */
if ((uds_fd_table[minor].type == -1) ||
- (uds_fd_table[minor].addr.sun_family == AF_UNIX &&
- uds_fd_table[minor].type != SOCK_DGRAM)) {
-
- /* the type hasn't been set by do_socket() yet OR attempting
- * to re-bind() a non-SOCK_DGRAM socket
- */
+ (uds_fd_table[minor].addr.sun_family == AF_UNIX &&
+ uds_fd_table[minor].type != SOCK_DGRAM))
return EINVAL;
- }
-
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
- sizeof(struct sockaddr_un));
- if (rc != OK) {
- return EIO;
- }
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+ sizeof(struct sockaddr_un))) != OK)
+ return rc;
- /* do some basic sanity checks on the address */
- if (addr.sun_family != AF_UNIX) {
- /* bad family */
+ /* Do some basic sanity checks on the address. */
+ if (addr.sun_family != AF_UNIX)
return EAFNOSUPPORT;
- }
- if (addr.sun_path[0] == '\0') {
- /* bad address */
+ if (addr.sun_path[0] == '\0')
return ENOENT;
- }
- rc = check_perms(minor, &addr);
- if (rc != OK) {
- /* permission denied, socket file doesn't exist, etc. */
+ if ((rc = vfs_check_perms(uds_fd_table[minor].owner, &addr)) != OK)
return rc;
- }
- /* make sure the address isn't already in use by another socket. */
+ /* Make sure the address isn't already in use by another socket. */
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, UNIX_PATH_MAX)) {
-
- /* another socket is bound to this sun_path */
+ if (uds_fd_table[i].addr.sun_family == AF_UNIX &&
+ !strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path,
+ UNIX_PATH_MAX)) {
+ /* Another socket is bound to this sun_path. */
return EADDRINUSE;
}
}
- /* looks good, perform the bind() */
- memcpy(&(uds_fd_table[minor].addr), &addr, sizeof(struct sockaddr_un));
+ /* Looks good, perform the bind(). */
+ memcpy(&uds_fd_table[minor].addr, &addr, sizeof(struct sockaddr_un));
return OK;
}
static int
do_getsockname(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int rc;
+ dprintf(("UDS: do_getsockname(%d)\n", minor));
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_getsockname() call_count=%d\n", minor,
- ++call_count);
-#endif
-
- /* 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.
+ /*
+ * 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(endpt, grant, 0,
- (vir_bytes) &uds_fd_table[minor].addr,
- sizeof(struct sockaddr_un));
-
- return rc ? EIO : OK;
+ return sys_safecopyto(endpt, grant, 0,
+ (vir_bytes) &uds_fd_table[minor].addr, sizeof(struct sockaddr_un));
}
static int
do_getpeername(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int rc;
+ int rc, peer_minor;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_getpeername() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: do_getpeername(%d)\n", minor));
- /* check that the socket is connected with a valid peer */
+ /* 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(endpt, grant, 0,
- (vir_bytes) &uds_fd_table[peer_minor].addr,
- sizeof(struct sockaddr_un));
-
- return rc ? EIO : OK;
- } else {
- if (uds_fd_table[minor].err == ECONNRESET) {
- uds_fd_table[minor].err = 0;
+ /* Copy the address from the peer. */
+ return sys_safecopyto(endpt, grant, 0,
+ (vir_bytes) &uds_fd_table[peer_minor].addr,
+ sizeof(struct sockaddr_un));
+ } else if (uds_fd_table[minor].err == ECONNRESET) {
+ uds_fd_table[minor].err = 0;
- return ECONNRESET;
- } else {
- return ENOTCONN;
- }
- }
+ return ECONNRESET;
+ } else
+ return ENOTCONN;
}
static int
{
int rc, how;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_shutdown() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: do_shutdown(%d)\n", minor));
+ /* The socket must be connection oriented. */
if (uds_fd_table[minor].type != SOCK_STREAM &&
- uds_fd_table[minor].type != SOCK_SEQPACKET) {
-
- /* socket must be a connection oriented socket */
+ uds_fd_table[minor].type != SOCK_SEQPACKET)
return EINVAL;
- }
if (uds_fd_table[minor].peer == -1) {
- /* shutdown(2) is only valid for connected sockets */
- if (uds_fd_table[minor].err == ECONNRESET) {
+ /* shutdown(2) is only valid for connected sockets. */
+ if (uds_fd_table[minor].err == ECONNRESET)
return ECONNRESET;
- } else {
+ else
return ENOTCONN;
- }
}
- /* get the 'how' parameter from the process */
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &how, sizeof(int));
-
- if (rc != OK) {
- return EIO;
- }
+ /* Get the 'how' parameter from the caller. */
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &how,
+ sizeof(how))) != OK)
+ return rc;
switch (how) {
- case SHUT_RD:
- /* take away read permission */
- uds_fd_table[minor].mode &= ~R_BIT;
- break;
+ case SHUT_RD: /* Take away read permission. */
+ uds_fd_table[minor].mode &= ~UDS_R;
+ break;
- case SHUT_WR:
- /* take away write permission */
- uds_fd_table[minor].mode &= ~W_BIT;
- break;
+ case SHUT_WR: /* Take away write permission. */
+ uds_fd_table[minor].mode &= ~UDS_W;
+ break;
- case SHUT_RDWR:
- /* completely shutdown */
- uds_fd_table[minor].mode = 0;
- break;
+ case SHUT_RDWR: /* Shut down completely. */
+ uds_fd_table[minor].mode = 0;
+ break;
- default:
- /* the 'how' parameter is invalid */
- return EINVAL;
+ default:
+ return EINVAL;
}
return OK;
devminor_t minory;
struct sockaddr_un addr;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_socketpair() call_count=%d\n", minorx,
- ++call_count);
-#endif
-
- /* ioctl argument is the minor number of the second socket */
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &minorin,
- sizeof(dev_t));
+ dprintf(("UDS: do_socketpair(%d)\n", minorx));
- if (rc != OK) {
- return EIO;
- }
+ /* The ioctl argument is the minor number of the second socket. */
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &minorin,
+ sizeof(minorin))) != OK)
+ return rc;
minory = minor(minorin);
-#if DEBUG == 1
- printf("socketpair() %d - %d\n", minorx, minory);
-#endif
+ dprintf(("UDS: socketpair(%d, %d,)\n", minorx, minory));
- /* 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
- */
+ /* Security check: both sockets must have the same owner endpoint. */
+ if (uds_fd_table[minorx].owner != uds_fd_table[minory].owner)
return EPERM;
- }
addr.sun_family = AF_UNIX;
addr.sun_path[0] = 'X';
{
int rc;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_getsockopt_sotype() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: do_getsockopt_sotype(%d)\n", minor));
- if (uds_fd_table[minor].type == -1) {
- /* the type hasn't been set yet. instead of returning an
- * invalid type, we fail with EINVAL
- */
+ /* If the type hasn't been set yet, we fail the call. */
+ if (uds_fd_table[minor].type == -1)
return EINVAL;
- }
- rc = sys_safecopyto(endpt, grant, 0,
- (vir_bytes) &uds_fd_table[minor].type, sizeof(int));
-
- return rc ? EIO : OK;
+ return sys_safecopyto(endpt, grant, 0,
+ (vir_bytes) &uds_fd_table[minor].type, sizeof(int));
}
static int
int rc;
struct uucred cred;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: do_getsockopt_peercred(%d)\n", minor));
if (uds_fd_table[minor].peer == -1) {
-
if (uds_fd_table[minor].err == ECONNRESET) {
uds_fd_table[minor].err = 0;
return ECONNRESET;
- } else {
+ } else
return ENOTCONN;
- }
}
peer_minor = uds_fd_table[minor].peer;
- /* obtain the peer's credentials */
- rc = getnucred(uds_fd_table[peer_minor].owner, &cred);
- if (rc == -1) {
- /* likely error: invalid endpoint / proc doesn't exist */
- return errno;
- }
-
- rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &cred,
- sizeof(struct uucred));
+ /* Obtain the peer's credentials and copy them out. */
+ if ((rc = getnucred(uds_fd_table[peer_minor].owner, &cred)) < 0)
+ return -errno;
- return rc ? EIO : OK;
+ return sys_safecopyto(endpt, grant, 0, (vir_bytes) &cred,
+ sizeof(struct uucred));
}
static int
do_getsockopt_sndbuf(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int rc;
- size_t sndbuf = PIPE_BUF;
+ size_t sndbuf = UDS_BUF;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_getsockopt_sndbuf() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: do_getsockopt_sndbuf(%d)\n", minor));
- rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &sndbuf,
- sizeof(size_t));
-
- return rc ? EIO : OK;
+ return sys_safecopyto(endpt, grant, 0, (vir_bytes) &sndbuf,
+ sizeof(sndbuf));
}
static int
int rc;
size_t sndbuf;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n", minor,
- ++call_count);
-#endif
-
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &sndbuf,
- sizeof(size_t));
+ dprintf(("UDS: do_setsockopt_sndbuf(%d)\n", minor));
- if (rc != OK) {
- return EIO;
- }
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &sndbuf,
+ sizeof(sndbuf))) != OK)
+ return rc;
- if (sndbuf > PIPE_BUF) {
- /* The send buffer is limited to 32K at the moment. */
+ /* The send buffer is limited to 32KB at the moment. */
+ if (sndbuf > UDS_BUF)
return ENOSYS;
- }
- /* There is no way to reduce the send buffer, do we have to
- * let this call fail for smaller buffers?
- */
+ /* FIXME: actually shrink the buffer. */
return OK;
}
static int
do_getsockopt_rcvbuf(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int rc;
- size_t rcvbuf = PIPE_BUF;
+ size_t rcvbuf = UDS_BUF;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_getsockopt_rcvbuf() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: do_getsockopt_rcvbuf(%d)\n", minor));
- rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &rcvbuf,
- sizeof(size_t));
-
- return rc ? EIO : OK;
+ return sys_safecopyto(endpt, grant, 0, (vir_bytes) &rcvbuf,
+ sizeof(rcvbuf));
}
static int
int rc;
size_t rcvbuf;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n", minor,
- ++call_count);
-#endif
-
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &rcvbuf,
- sizeof(size_t));
+ dprintf(("UDS: do_setsockopt_rcvbuf(%d)\n", minor));
- if (rc != OK) {
- return EIO;
- }
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &rcvbuf,
+ sizeof(rcvbuf))) != OK)
+ return rc;
- if (rcvbuf > PIPE_BUF) {
- /* The send buffer is limited to 32K at the moment. */
+ /* The receive buffer is limited to 32KB at the moment. */
+ if (rcvbuf > UDS_BUF)
return ENOSYS;
- }
- /* There is no way to reduce the send buffer, do we have to
- * let this call fail for smaller buffers?
- */
+ /* FIXME: actually shrink the buffer. */
return OK;
}
int rc;
struct sockaddr_un addr;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_sendto() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: do_sendto(%d)\n", minor));
- if (uds_fd_table[minor].type != SOCK_DGRAM) {
- /* This IOCTL is only for SOCK_DGRAM sockets */
+ /* This IOCTL is only for SOCK_DGRAM sockets. */
+ if (uds_fd_table[minor].type != SOCK_DGRAM)
return EINVAL;
- }
-
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
- sizeof(struct sockaddr_un));
- if (rc != OK) {
- return EIO;
- }
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+ sizeof(struct sockaddr_un))) != OK)
+ return rc;
- /* do some basic sanity checks on the address */
- if (addr.sun_family != AF_UNIX || addr.sun_path[0] == '\0') {
- /* bad address */
+ /* Do some basic sanity checks on the address. */
+ if (addr.sun_family != AF_UNIX || addr.sun_path[0] == '\0')
return EINVAL;
- }
- rc = check_perms(minor, &addr);
- if (rc != OK) {
+ if ((rc = vfs_check_perms(uds_fd_table[minor].owner, &addr)) != OK)
return rc;
- }
- memcpy(&(uds_fd_table[minor].target), &addr,
- sizeof(struct sockaddr_un));
+ memcpy(&uds_fd_table[minor].target, &addr, sizeof(struct sockaddr_un));
return OK;
}
static int
do_recvfrom(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{
- int rc;
-
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] do_recvfrom() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: do_recvfrom(%d)\n", minor));
- rc = sys_safecopyto(endpt, grant, 0,
- (vir_bytes) &uds_fd_table[minor].source,
- sizeof(struct sockaddr_un));
-
- return rc ? EIO : OK;
+ return sys_safecopyto(endpt, grant, 0,
+ (vir_bytes) &uds_fd_table[minor].source,
+ sizeof(struct sockaddr_un));
}
static int
msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
devminor_t minor)
{
- int rc;
+ int i, rc, nfds, totalfds;
struct msghdr msghdr;
struct cmsghdr *cmsg = NULL;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] msg_control_read() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: msg_control_read(%d)\n", minor));
- data->nfiledes = 0;
+ /* Obtain this socket's credentials. */
+ if ((rc = getnucred(uds_fd_table[minor].owner, &data->cred)) < 0)
+ return -errno;
+
+ dprintf(("UDS: minor=%d cred={%d,%d,%d}\n", minor, data->cred.pid,
+ data->cred.uid, data->cred.gid));
+
+ totalfds = data->nfiledes;
memset(&msghdr, '\0', sizeof(struct msghdr));
msghdr.msg_control = msg_ctrl->msg_control;
msghdr.msg_controllen = msg_ctrl->msg_controllen;
- for(cmsg = CMSG_FIRSTHDR(&msghdr); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
-
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
-
- int i;
- int nfds =
- MIN((cmsg->cmsg_len-CMSG_LEN(0))/sizeof(int),
- OPEN_MAX);
-
- for (i = 0; i < nfds; i++) {
- if (data->nfiledes == OPEN_MAX) {
- return EOVERFLOW;
- }
-
- data->fds[data->nfiledes] =
- ((int *) CMSG_DATA(cmsg))[i];
-#if DEBUG == 1
- printf("(uds) [%d] fd[%d]=%d\n", minor,
- data->nfiledes, data->fds[data->nfiledes]);
-#endif
- data->nfiledes++;
- }
+ for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
+ if (cmsg->cmsg_level != SOL_SOCKET ||
+ cmsg->cmsg_type != SCM_RIGHTS)
+ continue;
+
+ nfds = MIN((cmsg->cmsg_len-CMSG_LEN(0))/sizeof(int), OPEN_MAX);
+
+ for (i = 0; i < nfds; i++) {
+ if (totalfds == OPEN_MAX)
+ return EOVERFLOW;
+
+ data->fds[totalfds] = ((int *) CMSG_DATA(cmsg))[i];
+ dprintf(("UDS: minor=%d fd[%d]=%d\n", minor, totalfds,
+ data->fds[totalfds]));
+ totalfds++;
}
}
- /* obtain this socket's credentials */
- rc = getnucred(uds_fd_table[minor].owner, &(data->cred));
- if (rc == -1) {
- return errno;
- }
-#if DEBUG == 1
- printf("(uds) [%d] cred={%d,%d,%d}\n", minor,
- data->cred.pid, data->cred.uid,
- data->cred.gid);
-#endif
+ data->nfiledes = totalfds;
+
return OK;
}
{
int rc, i, j;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] send_fds() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: send_fds(%d)\n", minor));
- /* verify the file descriptors and get their filps. */
+ /* Verify the file descriptors and get their filps. */
for (i = 0; i < data->nfiledes; i++) {
- data->filps[i] = verify_fd(uds_fd_table[minor].owner,
- data->fds[i]);
-
- if (data->filps[i] == NULL) {
- return EINVAL;
- }
+ if ((rc = vfs_verify_fd(uds_fd_table[minor].owner,
+ data->fds[i], &data->filps[i])) != OK)
+ return rc;
}
- /* set them as in-flight */
+ /* Set them as in-flight. */
for (i = 0; i < data->nfiledes; i++) {
- rc = set_filp(data->filps[i]);
- if (rc != OK) {
- /* revert set_filp() calls */
- for (j = i; j >= 0; j--) {
- put_filp(data->filps[j]);
- }
+ if ((rc = vfs_set_filp(data->filps[i])) != OK) {
+ for (j = i - 1; j >= 0; j--)
+ vfs_put_filp(data->filps[j]); /* revert */
return rc;
}
}
}
/*
- * This function calls put_filp() for all of the FDs in data.
- * This is used when a Unix Domain Socket is closed and there
- * exists references to file descriptors that haven't been received
- * with recvmsg().
+ * This function calls put_filp() for all of the FDs in data. This is used
+ * when a Unix Domain Socket is closed and there exists references to file
+ * descriptors that haven't been received with recvmsg().
*/
int
uds_clear_fds(devminor_t minor, struct ancillary *data)
{
int i;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] uds_clear_fds() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: uds_clear_fds(%d)\n", minor));
for (i = 0; i < data->nfiledes; i++) {
- put_filp(data->filps[i]);
-#if DEBUG == 1
- printf("(uds) uds_clear_fds() => %d\n", data->fds[i]);
-#endif
+ dprintf(("UDS: uds_clear_fds() => %d\n", data->fds[i]));
+
+ vfs_put_filp(data->filps[i]);
+
data->fds[i] = -1;
data->filps[i] = NULL;
}
struct cmsghdr *cmsg;
endpoint_t to_ep;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: recv_fds(%d)\n", minor));
msghdr.msg_control = msg_ctrl->msg_control;
msghdr.msg_controllen = msg_ctrl->msg_controllen;
to_ep = uds_fd_table[minor].owner;
- /* copy to the target endpoint */
+ /* Copy to the target endpoint. */
for (i = 0; i < data->nfiledes; i++) {
- rc = copy_filp(to_ep, data->filps[i]);
- if (rc < 0) {
- /* revert set_filp() calls */
- for (j = 0; j < data->nfiledes; j++) {
- put_filp(data->filps[j]);
- }
- /* revert copy_filp() calls */
- for (j = i; j >= 0; j--) {
- cancel_fd(to_ep, data->fds[j]);
- }
+ if ((rc = vfs_copy_filp(to_ep, data->filps[i])) < 0) {
+ /* Revert vfs_set_filp() calls. */
+ for (j = 0; j < data->nfiledes; j++)
+ vfs_put_filp(data->filps[j]);
+
+ /* Revert vfs_copy_filp() calls. */
+ for (j = i - 1; j >= 0; j--)
+ vfs_cancel_fd(to_ep, data->fds[j]);
+
return rc;
}
data->fds[i] = rc; /* data->fds[i] now has the new FD */
}
for (i = 0; i < data->nfiledes; i++) {
- put_filp(data->filps[i]);
-#if DEBUG == 1
- printf("(uds) recv_fds() => %d\n", data->fds[i]);
-#endif
+ vfs_put_filp(data->filps[i]);
+
+ dprintf(("UDS: recv_fds() => %d\n", data->fds[i]));
+
((int *)CMSG_DATA(cmsg))[i] = data->fds[i];
data->fds[i] = -1;
data->filps[i] = NULL;
struct msghdr msghdr;
struct cmsghdr *cmsg;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] recv_cred() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: recv_cred(%d)\n", minor));
msghdr.msg_control = msg_ctrl->msg_control;
msghdr.msg_controllen = msg_ctrl->msg_controllen;
cmsg = CMSG_FIRSTHDR(&msghdr);
- if (cmsg->cmsg_len > 0) {
+ if (cmsg->cmsg_len > 0)
cmsg = CMSG_NXTHDR(&msghdr, cmsg);
- }
cmsg->cmsg_len = CMSG_LEN(sizeof(struct uucred));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_CREDENTIALS;
- memcpy(CMSG_DATA(cmsg), &(data->cred), sizeof(struct uucred));
+ memcpy(CMSG_DATA(cmsg), &data->cred, sizeof(struct uucred));
return OK;
}
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", minor, ++call_count);
-#endif
+ dprintf(("UDS: do_sendmsg(%d)\n", minor));
memset(&msg_ctrl, '\0', sizeof(struct msg_control));
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &msg_ctrl,
- sizeof(struct msg_control));
-
- if (rc != OK) {
- return EIO;
- }
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &msg_ctrl,
+ sizeof(struct msg_control))) != OK)
+ return rc;
- /* locate peer */
+ /* Locate the peer. */
peer = -1;
if (uds_fd_table[minor].type == SOCK_DGRAM) {
if (uds_fd_table[minor].target.sun_path[0] == '\0' ||
- uds_fd_table[minor].target.sun_family != AF_UNIX) {
-
+ uds_fd_table[minor].target.sun_family != AF_UNIX)
return EDESTADDRREQ;
- }
for (i = 0; i < NR_FDS; i++) {
-
- /* look for a SOCK_DGRAM socket that is bound on
- * the target address
+ /*
+ * Look for a SOCK_DGRAM socket that is bound on the
+ * target address.
*/
if (uds_fd_table[i].type == SOCK_DGRAM &&
- uds_fd_table[i].addr.sun_family == AF_UNIX &&
- !strncmp(uds_fd_table[minor].target.sun_path,
- uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)){
-
+ uds_fd_table[i].addr.sun_family == AF_UNIX &&
+ !strncmp(uds_fd_table[minor].target.sun_path,
+ uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) {
peer = i;
break;
}
}
- if (peer == -1) {
+ if (peer == -1)
return ENOENT;
- }
} else {
peer = uds_fd_table[minor].peer;
- if (peer == -1) {
+ if (peer == -1)
return ENOTCONN;
- }
}
-#if DEBUG == 1
- printf("(uds) [%d] sendmsg() -- peer=%d\n", minor, peer);
-#endif
- /* note: it's possible that there is already some file
- * descriptors in ancillary_data if the peer didn't call
- * recvmsg() yet. That's okay. The receiver will
- * get the current file descriptors plus the new ones.
+ dprintf(("UDS: sendmsg(%d) -- peer=%d\n", minor, peer));
+
+ /*
+ * Note: it's possible that there is already some file descriptors in
+ * ancillary_data if the peer didn't call recvmsg() yet. That's okay.
+ * The receiver will get the current file descriptors plus the new
+ * ones.
*/
- rc = msg_control_read(&msg_ctrl, &uds_fd_table[peer].ancillary_data,
- minor);
- if (rc != OK) {
+ if ((rc = msg_control_read(&msg_ctrl,
+ &uds_fd_table[peer].ancillary_data, minor)) != OK)
return rc;
- }
return send_fds(minor, &uds_fd_table[peer].ancillary_data);
}
{
int rc;
struct msg_control msg_ctrl;
- socklen_t controllen_avail = 0;
- socklen_t controllen_needed = 0;
- socklen_t controllen_desired = 0;
-
-#if DEBUG == 1
- static int call_count = 0;
- 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,
- uds_fd_table[minor].ancillary_data.cred.gid);
-#endif
+ socklen_t clen_avail = 0;
+ socklen_t clen_needed = 0;
+ socklen_t clen_desired = 0;
+
+ dprintf(("UDS: do_recvmsg(%d)\n", minor));
+ dprintf(("UDS: minor=%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,
+ uds_fd_table[minor].ancillary_data.cred.gid));
memset(&msg_ctrl, '\0', sizeof(struct msg_control));
- /* get the msg_control from the user, it will include the
+ /*
+ * Get the msg_control from the user. It will include the
* amount of space the user has allocated for control data.
*/
- rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &msg_ctrl,
- sizeof(struct msg_control));
-
- if (rc != OK) {
- return EIO;
- }
+ if ((rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &msg_ctrl,
+ sizeof(struct msg_control))) != OK)
+ return rc;
- controllen_avail = MIN(msg_ctrl.msg_controllen, MSG_CONTROL_MAX);
+ clen_avail = MIN(msg_ctrl.msg_controllen, MSG_CONTROL_MAX);
if (uds_fd_table[minor].ancillary_data.nfiledes > 0) {
- controllen_needed = CMSG_LEN(sizeof(int) *
- (uds_fd_table[minor].ancillary_data.nfiledes));
+ clen_needed = CMSG_LEN(sizeof(int) *
+ uds_fd_table[minor].ancillary_data.nfiledes);
}
/* if there is room we also include credentials */
- controllen_desired = controllen_needed +
- CMSG_LEN(sizeof(struct uucred));
+ clen_desired = clen_needed + CMSG_LEN(sizeof(struct uucred));
- if (controllen_needed > controllen_avail) {
+ if (clen_needed > clen_avail)
return EOVERFLOW;
- }
rc = recv_fds(minor, &uds_fd_table[minor].ancillary_data, &msg_ctrl);
- if (rc != OK) {
+ if (rc != OK)
return rc;
- }
- if (controllen_desired <= controllen_avail) {
+ if (clen_desired <= clen_avail) {
rc = recv_cred(minor, &uds_fd_table[minor].ancillary_data,
- &msg_ctrl);
- if (rc != OK) {
+ &msg_ctrl);
+ if (rc != OK)
return rc;
- }
}
- /* send the user the control data */
- rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &msg_ctrl,
- sizeof(struct msg_control));
-
- return rc ? EIO : OK;
+ /* Send the control data to the user. */
+ return sys_safecopyto(endpt, grant, 0, (vir_bytes) &msg_ctrl,
+ sizeof(struct msg_control));
}
int
{
int rc;
- switch (request) { /* Handle the ioctl(2) command */
+ switch (request) {
case NWIOSUDSCONN:
- /* connect to a listening socket -- connect() */
+ /* Connect to a listening socket -- connect(). */
rc = do_connect(minor, endpt, grant);
break;
case NWIOSUDSACCEPT:
- /* accept an incoming connection -- accept() */
+ /* 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()
+ /*
+ * 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()
- */
+ /* Set the SOCK_ type for this socket -- socket(). */
rc = do_socket(minor, endpt, grant);
break;
case NWIOSUDSADDR:
- /* set the address for this socket -- bind() */
+ /* Set the address for this socket -- bind(). */
rc = do_bind(minor, endpt, grant);
break;
case NWIOGUDSADDR:
- /* get the address for this socket -- getsockname() */
+ /* Get the address for this socket -- getsockname(). */
rc = do_getsockname(minor, endpt, grant);
break;
case NWIOGUDSPADDR:
- /* get the address for the peer -- getpeername() */
+ /* 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()
+ /*
+ * Shut down a socket for reading, writing, or both --
+ * shutdown().
*/
rc = do_shutdown(minor, endpt, grant);
break;
case NWIOSUDSPAIR:
- /* connect two sockets -- socketpair() */
+ /* Connect two sockets -- socketpair(). */
rc = do_socketpair(minor, endpt, grant);
break;
case NWIOGUDSSOTYPE:
- /* get socket type -- getsockopt(SO_TYPE) */
+ /* Get socket type -- getsockopt(SO_TYPE). */
rc = do_getsockopt_sotype(minor, endpt, grant);
break;
case NWIOGUDSPEERCRED:
- /* get peer endpoint -- getsockopt(SO_PEERCRED) */
+ /* Get peer endpoint -- getsockopt(SO_PEERCRED). */
rc = do_getsockopt_peercred(minor, endpt, grant);
break;
case NWIOSUDSTADDR:
- /* set target address -- sendto() */
+ /* Set target address -- sendto(). */
rc = do_sendto(minor, endpt, grant);
break;
case NWIOGUDSFADDR:
- /* get from address -- recvfrom() */
+ /* Get from address -- recvfrom(). */
rc = do_recvfrom(minor, endpt, grant);
break;
case NWIOGUDSSNDBUF:
- /* get the send buffer size -- getsockopt(SO_SNDBUF) */
+ /* 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) */
+ /* 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) */
+ /* 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) */
+ /* Set the send buffer size -- setsockopt(SO_SNDBUF). */
rc = do_setsockopt_rcvbuf(minor, endpt, grant);
break;
case NWIOSUDSCTRL:
- /* set the control data -- sendmsg() */
+ /* Set the control data -- sendmsg(). */
rc = do_sendmsg(minor, endpt, grant);
break;
case NWIOGUDSCTRL:
- /* set the control data -- recvmsg() */
+ /* 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.
+ /*
+ * 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 unrecognized requests simply
+ * get an ENOTTY response.
*/
rc = ENOTTY;
endpoint_t user_endpt)
{
devminor_t minor;
- int i;
char *buf;
+ int i;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [-] uds_open() call_count=%d\n", ++call_count);
- printf("Endpoint: 0x%x\n", user_endpt);
-#endif
+ dprintf(("UDS: uds_open() from %d\n", user_endpt));
/*
* Find a slot in the descriptor table for the new descriptor.
* The index of the descriptor in the table will be returned.
* Subsequent calls to read/write/close/ioctl/etc will use this
- * minor number. The minor number must be different from the
- * the /dev/uds device's minor number (currently 0).
+ * minor number. The minor number must be different from the
+ * the /dev/uds device's minor number (0).
*/
- minor = -1; /* to trap error */
-
- for (i = 1; i < NR_FDS; i++) {
- if (uds_fd_table[i].state == UDS_FREE) {
- minor = i;
+ for (minor = 1; minor < NR_FDS; minor++)
+ if (uds_fd_table[minor].state == UDS_FREE)
break;
- }
- }
- if (minor == -1)
+ if (minor == NR_FDS)
return ENFILE;
/*
* in use. We use mmap instead of malloc to allow the memory to be
* actually freed later.
*/
- if ((buf = minix_mmap(NULL, PIPE_BUF, PROT_READ | PROT_WRITE,
+ if ((buf = minix_mmap(NULL, UDS_BUF, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return ENOMEM;
- /* mark this one as 'in use' so that it doesn't get assigned to
- * another socket
+ /*
+ * Allocate the socket, and set its initial parameters.
*/
uds_fd_table[minor].state = UDS_INUSE;
-
- /* set the socket owner */
uds_fd_table[minor].owner = user_endpt;
-
- /* setup select(2) framework */
uds_fd_table[minor].sel_endpt = NONE;
uds_fd_table[minor].sel_ops = 0;
uds_fd_table[minor].buf = buf;
uds_fd_table[minor].pos = 0;
-
- /* the PIPE is initially empty */
uds_fd_table[minor].size = 0;
-
- /* the default for a new socket is to allow reading and writing.
- * shutdown(2) will remove one or both flags.
- */
- uds_fd_table[minor].mode = R_BIT | W_BIT;
-
- /* In libc socket(2) sets this to the actual value later with the
- * NWIOSUDSTYPE ioctl().
- */
+ uds_fd_table[minor].mode = UDS_R | UDS_W;
uds_fd_table[minor].type = -1;
- /* Clear the backlog by setting each entry to -1 */
- for (i = 0; i < UDS_SOMAXCONN; i++) {
- /* initially no connections are pending */
+ for (i = 0; i < UDS_SOMAXCONN; i++)
uds_fd_table[minor].backlog[i] = -1;
- }
+ uds_fd_table[minor].backlog_size = UDS_SOMAXCONN;
- memset(&uds_fd_table[minor].ancillary_data, '\0', sizeof(struct
- ancillary));
- for (i = 0; i < OPEN_MAX; i++) {
+ memset(&uds_fd_table[minor].ancillary_data, '\0',
+ sizeof(struct ancillary));
+ for (i = 0; i < OPEN_MAX; i++)
uds_fd_table[minor].ancillary_data.fds[i] = -1;
- }
- /* default the size to UDS_SOMAXCONN */
- uds_fd_table[minor].backlog_size = UDS_SOMAXCONN;
-
- /* the socket isn't listening for incoming connections until
- * listen(2) is called
- */
uds_fd_table[minor].listening = 0;
-
- /* initially the socket is not connected to a peer */
uds_fd_table[minor].peer = -1;
-
- /* there isn't a child waiting to be accept(2)'d */
uds_fd_table[minor].child = -1;
- /* initially the socket is not bound or listening on an address */
- memset(&(uds_fd_table[minor].addr), '\0', sizeof(struct sockaddr_un));
- memset(&(uds_fd_table[minor].source), '\0', sizeof(struct sockaddr_un));
- memset(&(uds_fd_table[minor].target), '\0', sizeof(struct sockaddr_un));
+ memset(&uds_fd_table[minor].addr, '\0', sizeof(struct sockaddr_un));
+ memset(&uds_fd_table[minor].source, '\0', sizeof(struct sockaddr_un));
+ memset(&uds_fd_table[minor].target, '\0', sizeof(struct sockaddr_un));
- /* Initially the socket isn't suspended. */
uds_fd_table[minor].suspended = UDS_NOT_SUSPENDED;
return CDEV_CLONED | minor;
{
int peer;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] uds_close() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: uds_close(%d)\n", minor));
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 :(
- */
+ if (uds_fd_table[minor].state != UDS_INUSE)
return EINVAL;
- }
- /* if the socket is connected, disconnect it */
+ /* If the socket is connected, disconnect it. */
if (uds_fd_table[minor].peer != -1) {
peer = uds_fd_table[minor].peer;
- /* set peer of this peer to -1 */
uds_fd_table[peer].peer = -1;
- /* error to pass to peer */
+ /* The error to pass to the peer. */
uds_fd_table[peer].err = ECONNRESET;
- /* if peer was blocked on I/O revive peer */
+ /* If the peer was blocked on I/O, revive it. */
if (uds_fd_table[peer].suspended != UDS_NOT_SUSPENDED)
uds_unsuspend(peer);
}
- if (uds_fd_table[minor].ancillary_data.nfiledes > 0) {
+ if (uds_fd_table[minor].ancillary_data.nfiledes > 0)
uds_clear_fds(minor, &uds_fd_table[minor].ancillary_data);
- }
/* Release the memory for the ring buffer. */
- minix_munmap(uds_fd_table[minor].buf, PIPE_BUF);
+ minix_munmap(uds_fd_table[minor].buf, UDS_BUF);
/* Set the socket back to its original UDS_FREE state. */
memset(&uds_fd_table[minor], '\0', sizeof(uds_fd_t));
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", minor, ++call_count);
-#endif
+ dprintf(("UDS: uds_select(%d)\n", minor));
if (minor < 0 || minor >= NR_FDS) return ENXIO;
- if (uds_fd_table[minor].state != UDS_INUSE) {
- /* attempted to select on a socket that hasn't been opened --
- * something is very wrong :(
- */
+ if (uds_fd_table[minor].state != UDS_INUSE)
return EINVAL;
- }
watch = (ops & CDEV_NOTIFY);
ops &= (CDEV_OP_RD | CDEV_OP_WR | CDEV_OP_ERR);
ready_ops = 0;
- /* check if there is data available to read */
+ /* Check if there is data available to read. */
if (ops & CDEV_OP_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 |= CDEV_OP_RD;
+ ready_ops |= CDEV_OP_RD; /* data available */
} else if (uds_fd_table[minor].listening == 1) {
- /* check for pending connections */
+ /* Check for pending connections. */
for (i = 0; i < uds_fd_table[minor].backlog_size; i++)
{
if (uds_fd_table[minor].backlog[i] != -1) {
}
}
} else if (bytes != SUSPEND) {
- ready_ops |= CDEV_OP_RD;
+ ready_ops |= CDEV_OP_RD; /* error */
}
}
- /* check if we can write without blocking */
+ /* Check if we can write without blocking. */
if (ops & CDEV_OP_WR) {
bytes = uds_perform_write(minor, NONE, GRANT_INVALID, 1, 1);
- if (bytes != 0 && bytes != SUSPEND) {
- /* There is room to write or there is an error
- * condition.
- */
+ if (bytes != 0 && bytes != SUSPEND)
ready_ops |= CDEV_OP_WR;
- }
}
- /* If not all requested ops were ready, and the caller requests to be
+ /*
+ * 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;
size_t pos, subsize;
int r, peer;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] uds_perform_read() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: uds_perform_read(%d)\n", minor));
peer = uds_fd_table[minor].peer;
- /* skip reads and writes of 0 (or less!) bytes */
- if (size <= 0) {
+ /* Skip reads of zero bytes. */
+ if (size == 0)
return 0;
- }
- /* check if we are allowed to read */
- if (!(uds_fd_table[minor].mode & R_BIT)) {
- /* socket is shutdown for reading */
+ /* Check if the socket isn't shut down for reads. */
+ if (!(uds_fd_table[minor].mode & UDS_R))
return EPIPE;
- }
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. */
+ /*
+ * We're not connected. That's only a problem when this
+ * socket is connection oriented.
+ */
if (uds_fd_table[minor].type == SOCK_STREAM ||
uds_fd_table[minor].type == SOCK_SEQPACKET) {
if (uds_fd_table[minor].err == ECONNRESET) {
if (!pretend)
uds_fd_table[minor].err = 0;
return ECONNRESET;
- } else {
+ } else
return ENOTCONN;
- }
}
}
- /* Check if process is reading from a closed pipe */
- if (peer != -1 && !(uds_fd_table[peer].mode & W_BIT) &&
- uds_fd_table[minor].size == 0) {
+ /* Check if process is reading from a closed pipe. */
+ if (peer != -1 && !(uds_fd_table[peer].mode & UDS_W) &&
+ uds_fd_table[minor].size == 0)
return 0;
- }
- if (pretend) {
+ 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_SUSPENDED_WRITE)
- uds_unsuspend(peer);
+ panic("writer blocked on empty socket");
-#if DEBUG == 1
- printf("(uds) [%d] suspending read request\n", minor);
-#endif
- /* Process is reading from an empty pipe,
- * suspend it so some bytes can be written
- */
+ dprintf(("UDS: suspending read request on %d\n", minor));
+
+ /* Process is reading from an empty pipe. Suspend it. */
return EDONTREPLY;
}
/* Get the data from the tail of the ring buffer. */
pos = uds_fd_table[minor].pos;
- subsize = PIPE_BUF - pos;
+ subsize = UDS_BUF - pos;
if (subsize > size)
subsize = size;
}
/* Advance the buffer tail. */
- uds_fd_table[minor].pos = (pos + size) % PIPE_BUF;
+ uds_fd_table[minor].pos = (pos + size) % UDS_BUF;
uds_fd_table[minor].size -= size;
- /* if we have 0 unread bytes, move the data pointer back to the
- * start of the buffer
- */
- if (uds_fd_table[minor].size == 0) {
+ /* Reset position if the buffer is empty (it may save a copy call). */
+ if (uds_fd_table[minor].size == 0)
uds_fd_table[minor].pos = 0;
- }
- /* maybe a big write was waiting for us to read some data, if
- * needed revive the writer
- */
+ /* See if we can wake up a blocked writer. */
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); if the peer wants to know about write being possible
- * and it doesn't know about it already, then let the peer know.
- */
+ /* See if we can satisfy an ongoing select. */
if (peer != -1 && (uds_fd_table[peer].sel_ops & CDEV_OP_WR) &&
- size > 0) {
- /* a write on peer is possible now */
+ uds_fd_table[minor].size < UDS_BUF) {
+ /* A write on the peer is possible now. */
chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
- CDEV_OP_WR);
+ CDEV_OP_WR);
uds_fd_table[peer].sel_ops &= ~CDEV_OP_WR;
}
- return size; /* return number of bytes read */
+ return size; /* number of bytes read */
}
static ssize_t
size_t subsize, pos;
int i, r, peer;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] uds_perform_write() call_count=%d\n", minor,
- ++call_count);
-#endif
+ dprintf(("UDS: uds_perform_write(%d)\n", minor));
/* Skip writes of zero bytes. */
if (size == 0)
return 0;
- /* check if we are allowed to write */
- if (!(uds_fd_table[minor].mode & W_BIT)) {
- /* socket is shutdown for writing */
+ /* Check if the socket isn't shut down for writes. */
+ if (!(uds_fd_table[minor].mode & UDS_W))
return EPIPE;
- }
- if (size > PIPE_BUF) {
- /* message is too big to ever write to the PIPE */
+ /* We cannot handle input beyond the buffer size. */
+ if (size > UDS_BUF)
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
+ uds_fd_table[minor].type == SOCK_SEQPACKET) {
+ /*
+ * If we're writing to a connection-oriented socket,
+ * then it needs a peer to write to.
*/
- if (uds_fd_table[minor].peer == -1) {
- if (uds_fd_table[minor].err == ECONNRESET) {
+ peer = uds_fd_table[minor].peer;
- uds_fd_table[minor].err = 0;
+ if (peer == -1) {
+ if (uds_fd_table[minor].err == ECONNRESET) {
+ if (!pretend)
+ uds_fd_table[minor].err = 0;
return ECONNRESET;
- } else {
+ } else
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 */
+ /* Locate the "peer" we want to write to. */
for (i = 0; i < NR_FDS; i++) {
-
- /* look for a SOCK_DGRAM socket that is bound on
- * the target address
+ /*
+ * Look for a SOCK_DGRAM socket that is bound on
+ * the target address.
*/
if (uds_fd_table[i].type == SOCK_DGRAM &&
- uds_fd_table[i].addr.sun_family == AF_UNIX &&
- !strncmp(uds_fd_table[minor].target.sun_path,
- uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) {
-
+ uds_fd_table[i].addr.sun_family == AF_UNIX &&
+ !strncmp(uds_fd_table[minor].target.sun_path,
+ uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) {
peer = i;
break;
}
}
- }
- if (peer == -1) {
- if (pretend)
- return SUSPEND;
+ if (peer == -1) {
+ if (pretend)
+ return SUSPEND;
- return ENOENT;
+ return ENOENT;
+ }
}
- /* check if we write to a closed pipe */
- if (!(uds_fd_table[peer].mode & R_BIT)) {
+ /* Check if we write to a closed pipe. */
+ if (!(uds_fd_table[peer].mode & UDS_R))
return EPIPE;
- }
- /* we have to preserve the boundary for DGRAM. if there's
- * already a packet waiting, discard it silently and pretend
- * it was written.
+ /*
+ * We have to preserve the boundary for DGRAM. If there's already a
+ * packet waiting, discard it silently and pretend it was written.
*/
- if(uds_fd_table[minor].type == SOCK_DGRAM &&
- uds_fd_table[peer].size > 0) {
+ if (uds_fd_table[minor].type == SOCK_DGRAM &&
+ uds_fd_table[peer].size > 0)
return size;
- }
/*
* Check if the ring buffer is already full, and if the SEQPACKET
* message wouldn't write to an empty buffer.
*/
- if (uds_fd_table[peer].size == PIPE_BUF ||
+ if (uds_fd_table[peer].size == UDS_BUF ||
(uds_fd_table[minor].type == SOCK_SEQPACKET &&
uds_fd_table[peer].size > 0)) {
- if (pretend) {
+ if (pretend)
return SUSPEND;
- }
- /* if needed revive the reader */
if (uds_fd_table[peer].suspended == UDS_SUSPENDED_READ)
- uds_unsuspend(peer);
+ panic("reader blocked on full socket");
-#if DEBUG == 1
- printf("(uds) [%d] suspending write request\n", minor);
-#endif
+ dprintf(("UDS: suspending write request on %d\n", minor));
- /* Process is reading from an empty pipe,
- * suspend it so some bytes can be written
- */
+ /* Process is reading from an empty pipe. Suspend it. */
return EDONTREPLY;
}
/* How much can we add to the ring buffer? */
- if (size > PIPE_BUF - uds_fd_table[peer].size)
- size = PIPE_BUF - uds_fd_table[peer].size;
+ if (size > UDS_BUF - uds_fd_table[peer].size)
+ size = UDS_BUF - uds_fd_table[peer].size;
if (pretend)
return size;
/* Put the data at the head of the ring buffer. */
- pos = (uds_fd_table[peer].pos + uds_fd_table[peer].size) % PIPE_BUF;
+ pos = (uds_fd_table[peer].pos + uds_fd_table[peer].size) % UDS_BUF;
- subsize = PIPE_BUF - pos;
+ subsize = UDS_BUF - pos;
if (subsize > size)
subsize = size;
/* Advance the buffer head. */
uds_fd_table[peer].size += size;
- /* fill in the source address to be returned by recvfrom & recvmsg */
- if (uds_fd_table[minor].type == SOCK_DGRAM) {
+ /* 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,
- sizeof(struct sockaddr_un));
- }
+ sizeof(struct sockaddr_un));
- /* revive peer that was waiting for us to write */
+ /* See if we can wake up a blocked reader. */
if (uds_fd_table[peer].suspended == UDS_SUSPENDED_READ)
uds_unsuspend(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 & CDEV_OP_RD) && size > 0) {
- /* a read on peer is possible now */
+ /* See if we can satisfy an ongoing select. */
+ if ((uds_fd_table[peer].sel_ops & CDEV_OP_RD) &&
+ uds_fd_table[peer].size > 0) {
+ /* A read on the peer is possible now. */
chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
- CDEV_OP_RD);
+ CDEV_OP_RD);
uds_fd_table[peer].sel_ops &= ~CDEV_OP_RD;
}
- return size; /* return number of bytes written */
+ return size; /* number of bytes written */
}
static ssize_t
{
ssize_t rc;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] uds_read() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: uds_read(%d)\n", minor));
if (minor < 0 || minor >= NR_FDS) return ENXIO;
- if (uds_fd_table[minor].state != UDS_INUSE) {
- /* attempted to read from a socket that hasn't been opened --
- * something is very wrong :(
- */
+ if (uds_fd_table[minor].state != UDS_INUSE)
return EINVAL;
- }
rc = uds_perform_read(minor, endpt, grant, size, 0);
{
ssize_t rc;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] uds_write() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: uds_write(%d)\n", minor));
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 :(
- */
+ if (uds_fd_table[minor].state != UDS_INUSE)
return EINVAL;
- }
rc = uds_perform_write(minor, endpt, grant, size, 0);
{
int rc;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] uds_ioctl() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: uds_ioctl(%d, %lu)\n", minor, request));
if (minor < 0 || minor >= NR_FDS) return ENXIO;
- if (uds_fd_table[minor].state != UDS_INUSE) {
- /* attempted to perform I/O control on a socket that hasn't
- * been opened -- something is very wrong :(
- */
+ if (uds_fd_table[minor].state != UDS_INUSE)
return EINVAL;
- }
- /* update the owner endpoint */
+ /* Update the owner endpoint. */
uds_fd_table[minor].owner = user_endpt;
- /* let the UDS subsystem handle the actual request */
+ /* Let the UDS ioctl subsystem handle the actual request. */
rc = uds_do_ioctl(minor, request, endpt, grant);
/* If the call couldn't complete, suspend the caller. */
switch (fdp->suspended) {
case UDS_SUSPENDED_READ:
r = uds_perform_read(minor, fdp->susp_endpt, fdp->susp_grant,
- fdp->susp_size, 0);
+ fdp->susp_size, 0);
if (r == EDONTREPLY)
return;
case UDS_SUSPENDED_WRITE:
r = uds_perform_write(minor, fdp->susp_endpt, fdp->susp_grant,
- fdp->susp_size, 0);
+ fdp->susp_size, 0);
if (r == EDONTREPLY)
return;
case UDS_SUSPENDED_CONNECT:
case UDS_SUSPENDED_ACCEPT:
- /* In both cases, the caller already set up the connection.
+ /*
+ * In both cases, the caller already set up the connection.
* The only thing to do here is unblock.
*/
r = OK;
uds_fd_t *fdp;
int i, j;
-#if DEBUG == 1
- static int call_count = 0;
- printf("(uds) [%d] uds_cancel() call_count=%d\n", minor, ++call_count);
-#endif
+ dprintf(("UDS: uds_cancel(%d)\n", minor));
if (minor < 0 || minor >= NR_FDS) return EDONTREPLY;
/* 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) {
+ fdp->susp_id != id)
return EDONTREPLY; /* this happens. */
- }
- /* The system call was cancelled, so the socket is not suspended
+ /*
+ * The system call was cancelled, so the socket is not suspended
* anymore.
*/
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) {
+ /* A partial accept() only sets the server's child. */
+ for (i = 0; i < NR_FDS; i++)
+ if (uds_fd_table[i].child == minor)
uds_fd_table[i].child = -1;
- }
- }
break;
case UDS_SUSPENDED_CONNECT: /* connect() */
- /* partial connect() sets addr and adds minor to server backlog
+ /*
+ * A partial connect() sets the address and adds the minor to
+ * the server backlog.
*/
-
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 */
+ /* Remove the minor from the backlog of any server. */
for (j = 0; j < uds_fd_table[i].backlog_size; j++) {
- if (uds_fd_table[i].backlog[j] == minor) {
-
- /* remove from backlog */
+ if (uds_fd_table[i].backlog[j] == minor)
uds_fd_table[i].backlog[j] = -1;
- }
}
}
- /* clear the address */
- memset(&(uds_fd_table[minor].addr), '\0',
- sizeof(struct sockaddr_un));
+ /* Clear the address. */
+ memset(&uds_fd_table[minor].addr, '\0',
+ sizeof(struct sockaddr_un));
break;