From: David van Moolenbroek Date: Fri, 4 Oct 2013 14:46:18 +0000 (+0200) Subject: UDS: clean up source code X-Git-Tag: v3.3.0~540 X-Git-Url: http://zhaoyanbai.com/repos/%22../static/icons/zlib_tech.html?a=commitdiff_plain;h=1e07186cafdc3553a19e60c38be60e5e2baeb1aa;p=minix.git UDS: clean up source code - move VFS calls to a separate source file; - solve a few subtle bugs, mostly in error handling; - simplify debug reporting code; - make a few definitions more independent; - restyle to something closer to KNF. Change-Id: I7b0537adfccac8b92b5cc3e78dac9f5ce3c79f03 --- diff --git a/drivers/uds/Makefile b/drivers/uds/Makefile index 8f339297d..1348ec41b 100644 --- a/drivers/uds/Makefile +++ b/drivers/uds/Makefile @@ -1,6 +1,6 @@ # Makefile for the UNIX Domain Sockets driver (UDS) PROG= uds -SRCS= uds.c ioc_uds.c +SRCS= uds.c ioc_uds.c vfs_uds.c DPADD+= ${LIBCHARDRIVER} ${LIBSYS} LDADD+= -lchardriver -lsys diff --git a/drivers/uds/ioc_uds.c b/drivers/uds/ioc_uds.c index da6e28c1e..fe62a88e0 100644 --- a/drivers/uds/ioc_uds.c +++ b/drivers/uds/ioc_uds.c @@ -6,233 +6,37 @@ * 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; } @@ -245,12 +49,10 @@ do_accept(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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 @@ -259,98 +61,73 @@ do_accept(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) * 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); } @@ -364,134 +141,96 @@ do_connect(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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; @@ -503,72 +242,47 @@ do_listen(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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; @@ -577,45 +291,29 @@ do_listen(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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; } } @@ -625,58 +323,42 @@ do_bind(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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; } @@ -684,59 +366,39 @@ do_bind(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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 @@ -744,54 +406,41 @@ do_shutdown(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) { 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; @@ -805,33 +454,20 @@ do_socketpair(devminor_t minorx, endpoint_t endpt, cp_grant_id_t grant) 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'; @@ -845,23 +481,14 @@ do_getsockopt_sotype(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_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 @@ -871,54 +498,36 @@ do_getsockopt_peercred(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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 @@ -927,46 +536,29 @@ 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", 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 @@ -975,27 +567,17 @@ 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", 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; } @@ -1005,36 +587,24 @@ do_sendto(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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; } @@ -1042,78 +612,57 @@ do_sendto(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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; } @@ -1122,29 +671,20 @@ send_fds(devminor_t minor, struct ancillary *data) { 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; } } @@ -1153,27 +693,22 @@ send_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 - * 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; } @@ -1192,11 +727,7 @@ recv_fds(devminor_t minor, struct ancillary *data, 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; @@ -1208,28 +739,27 @@ recv_fds(devminor_t minor, struct ancillary *data, 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; @@ -1247,24 +777,19 @@ recv_cred(devminor_t minor, struct ancillary *data, 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; } @@ -1275,67 +800,54 @@ do_sendmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) 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); } @@ -1345,64 +857,53 @@ do_recvmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) { 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 @@ -1411,132 +912,133 @@ uds_do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, { 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; diff --git a/drivers/uds/uds.c b/drivers/uds/uds.c index b5163be67..191eb1fd5 100644 --- a/drivers/uds/uds.c +++ b/drivers/uds/uds.c @@ -50,32 +50,23 @@ uds_open(devminor_t UNUSED(orig_minor), int access, 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; /* @@ -84,69 +75,40 @@ uds_open(devminor_t UNUSED(orig_minor), int access, * 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; @@ -157,41 +119,32 @@ uds_close(devminor_t 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)); @@ -211,33 +164,25 @@ uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt) 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) { @@ -246,22 +191,19 @@ uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt) } } } 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; @@ -280,64 +222,50 @@ uds_perform_read(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant, 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; } @@ -351,7 +279,7 @@ uds_perform_read(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant, /* 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; @@ -367,35 +295,27 @@ uds_perform_read(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant, } /* 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 @@ -405,120 +325,104 @@ uds_perform_write(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant, 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; @@ -535,28 +439,25 @@ uds_perform_write(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant, /* 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 @@ -565,19 +466,12 @@ uds_read(devminor_t minor, u64_t position, endpoint_t endpt, { 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); @@ -606,19 +500,12 @@ uds_write(devminor_t minor, u64_t position, endpoint_t endpt, { 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); @@ -647,24 +534,17 @@ uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, { 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. */ @@ -699,7 +579,7 @@ uds_unsuspend(devminor_t minor) 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; @@ -708,7 +588,7 @@ uds_unsuspend(devminor_t minor) 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; @@ -717,7 +597,8 @@ uds_unsuspend(devminor_t minor) 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; @@ -739,10 +620,7 @@ uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id) 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; @@ -755,48 +633,41 @@ uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id) /* 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; diff --git a/drivers/uds/uds.h b/drivers/uds/uds.h index 4b9c720af..202259970 100644 --- a/drivers/uds/uds.h +++ b/drivers/uds/uds.h @@ -16,9 +16,18 @@ /* Connection backlog size for incoming connections. */ #define UDS_SOMAXCONN 64 +/* Maximum UDS socket buffer size. */ +#define UDS_BUF PIPE_BUF + /* Output debugging information? */ #define DEBUG 0 +#if DEBUG +#define dprintf(x) printf x +#else +#define dprintf(x) +#endif + typedef void* filp_id_t; /* ancillary data to be sent */ @@ -29,6 +38,9 @@ struct ancillary { struct uucred cred; }; +#define UDS_R 0x1 +#define UDS_W 0x2 + /* * Internal State Information for a socket descriptor. */ @@ -61,9 +73,9 @@ struct uds_fd { size_t size; /* size of used part of ring buffer */ /* control read/write, set by uds_open() and shutdown(2). - * Can be set to R_BIT|W_BIT, R_BIT, W_BIT, or 0 + * Can be set to UDS_R|UDS_W, UDS_R, UDS_W, or 0 * for read and write, read only, write only, or neither. - * default is R_BIT|W_BIT. + * default is UDS_R|UDS_W. */ int mode; @@ -179,12 +191,20 @@ EXTERN uds_fd_t uds_fd_table[NR_FDS]; /* Function prototypes. */ -/* dev_uds.c */ -void uds_unsuspend(devminor_t minor); - -/* uds.c */ +/* ioc_uds.c */ 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); +/* uds.c */ +void uds_unsuspend(devminor_t minor); + +/* vfs_uds.c */ +int vfs_check_perms(endpoint_t ep, struct sockaddr_un *addr); +int vfs_verify_fd(endpoint_t ep, int fd, filp_id_t *filp); +int vfs_set_filp(filp_id_t sfilp); +int vfs_copy_filp(endpoint_t to_ep, filp_id_t cfilp); +int vfs_put_filp(filp_id_t pfilp); +int vfs_cancel_fd(endpoint_t ep, int fd); + #endif /* !__UDS_UDS_H */ diff --git a/drivers/uds/vfs_uds.c b/drivers/uds/vfs_uds.c new file mode 100644 index 000000000..7c8748ea2 --- /dev/null +++ b/drivers/uds/vfs_uds.c @@ -0,0 +1,168 @@ +/* + * Unix Domain Sockets Implementation (PF_UNIX, PF_LOCAL) + * This code provides communication stubs for backcalls to VFS. + */ + +#include "uds.h" + +/* + * Check the permissions of a socket file. + */ +int +vfs_check_perms(endpoint_t ep, struct sockaddr_un *addr) +{ + int rc; + message m; + cp_grant_id_t grant_id; + + dprintf(("UDS: vfs_check_perms(%d)\n", ep)); + + grant_id = cpf_grant_direct(VFS_PROC_NR, (vir_bytes) addr->sun_path, + UNIX_PATH_MAX, CPF_READ | CPF_WRITE); + + /* Ask VFS to verify the permissions. */ + memset(&m, '\0', sizeof(message)); + + m.m_type = VFS_UDS_CHECK_PERMS; + m.VFS_UDS_ENDPT = ep; + m.VFS_UDS_GRANT = grant_id; + m.VFS_UDS_COUNT = UNIX_PATH_MAX; + + if ((rc = sendrec(VFS_PROC_NR, &m)) != OK) + panic("error sending to VFS: %d\n", rc); + + cpf_revoke(grant_id); + + dprintf(("UDS: VFS reply => %d, \"%s\"\n", m.m_type, + addr->sun_path)); + + return m.m_type; /* reply code: OK, ELOOP, etc. */ +} + +/* + * Verify whether the given file descriptor is valid for the given process, and + * obtain a filp object identifier upon success. + */ +int +vfs_verify_fd(endpoint_t ep, int fd, filp_id_t *filp) +{ + int rc; + message m; + + dprintf(("UDS: vfs_verify_fd(%d, %d)\n", ep, fd)); + + memset(&m, '\0', sizeof(message)); + + m.m_type = VFS_UDS_VERIFY_FD; + m.VFS_UDS_ENDPT = ep; + m.VFS_UDS_FD = fd; + + if ((rc = sendrec(VFS_PROC_NR, &m)) != OK) + panic("error sending to VFS: %d\n", rc); + + dprintf(("UDS: VFS reply => %d, %p\n", m.m_type, m.VFS_UDS_FILP)); + + if (m.m_type != OK) + return m.m_type; + + *filp = m.VFS_UDS_FILP; + return OK; +} + +/* + * Mark a filp object as in flight, that is, in use by UDS. + */ +int +vfs_set_filp(filp_id_t sfilp) +{ + int rc; + message m; + + dprintf(("UDS: set_filp(%p)\n", sfilp)); + + memset(&m, '\0', sizeof(message)); + + m.m_type = VFS_UDS_SET_FILP; + m.VFS_UDS_FILP = sfilp; + + if ((rc = sendrec(VFS_PROC_NR, &m)) != OK) + panic("error sending to VFS: %d\n", rc); + + dprintf(("UDS: VFS reply => %d\n", m.m_type)); + + return m.m_type; /* reply code: OK, ELOOP, etc. */ +} + +/* + * Copy a filp object into a process, yielding a file descriptor. + */ +int +vfs_copy_filp(endpoint_t to_ep, filp_id_t cfilp) +{ + int rc; + message m; + + dprintf(("UDS: vfs_copy_filp(%d, %p)\n", to_ep, cfilp)); + + memset(&m, '\0', sizeof(message)); + + m.m_type = VFS_UDS_COPY_FILP; + m.VFS_UDS_ENDPT = to_ep; + m.VFS_UDS_FILP = cfilp; + + if ((rc = sendrec(VFS_PROC_NR, &m)) != OK) + panic("error sending to VFS: %d\n", rc); + + dprintf(("UDS: VFS reply => %d\n", m.m_type)); + + return m.m_type; +} + +/* + * Mark a filp object as no longer in flight. + */ +int +vfs_put_filp(filp_id_t pfilp) +{ + int rc; + message m; + + dprintf(("UDS: vfs_put_filp(%p)\n", pfilp)); + + memset(&m, '\0', sizeof(message)); + + m.m_type = VFS_UDS_PUT_FILP; + m.VFS_UDS_FILP = pfilp; + + if ((rc = sendrec(VFS_PROC_NR, &m)) != OK) + panic("error sending to VFS: %d\n", rc); + + dprintf(("UDS: VFS reply => %d\n", m.m_type)); + + return m.m_type; /* reply code: OK, ELOOP, etc. */ +} + +/* + * Undo creation of a file descriptor in a process. + */ +int +vfs_cancel_fd(endpoint_t ep, int fd) +{ + int rc; + message m; + + dprintf(("UDS: vfs_cancel_fd(%d,%d)\n", ep, fd)); + + memset(&m, '\0', sizeof(message)); + + m.m_type = VFS_UDS_CANCEL_FD; + m.VFS_UDS_ENDPT = ep; + m.VFS_UDS_FD = fd; + + if ((rc = sendrec(VFS_PROC_NR, &m)) != OK) + panic("error sending to VFS: %d\n", rc); + + dprintf(("UDS: VFS reply => %d\n", m.m_type)); + + return m.m_type; /* reply code: OK, ELOOP, etc. */ +}