UDS: split off from PFS

Change-Id: I769cbd64aa6e5e85a797caf0f8bbb4c20e145263
This commit is contained in:
David van Moolenbroek 2013-10-04 16:29:40 +02:00 committed by Lionel Sambuc
parent 6d466f941b
commit b003ed0929
22 changed files with 399 additions and 447 deletions

View file

@ -4758,6 +4758,7 @@
./usr/sbin/rs minix-sys ./usr/sbin/rs minix-sys
./usr/sbin/sched minix-sys ./usr/sbin/sched minix-sys
./usr/sbin/tty minix-sys ./usr/sbin/tty minix-sys
./usr/sbin/uds minix-sys
./usr/sbin/unlink minix-sys ./usr/sbin/unlink minix-sys
./usr/sbin/user minix-sys ./usr/sbin/user minix-sys
./usr/sbin/useradd minix-sys ./usr/sbin/useradd minix-sys

View file

@ -18,13 +18,13 @@ SUBDIR= tty
.if ${MACHINE_ARCH} == "i386" .if ${MACHINE_ARCH} == "i386"
SUBDIR= ahci amddev atl2 at_wini audio dec21140A dp8390 dpeth \ SUBDIR= ahci amddev atl2 at_wini audio dec21140A dp8390 dpeth \
e1000 fbd filter floppy fxp hello lance log mmc orinoco pci pckbd \ e1000 fbd filter floppy fxp hello lance log mmc orinoco pci pckbd \
printer random readclock rtl8139 rtl8169 ti1225 tty vbox acpi \ printer random readclock rtl8139 rtl8169 ti1225 tty uds vbox acpi \
virtio_blk virtio_net vnd virtio_blk virtio_net vnd
.endif .endif
.if ${MACHINE_ARCH} == "earm" .if ${MACHINE_ARCH} == "earm"
SUBDIR= bmp085 cat24c256 fb gpio i2c mmc lan8710a log readclock \ SUBDIR= bmp085 cat24c256 fb gpio i2c mmc lan8710a log readclock \
sht21 tda19988 tps65217 tps65950 tsl2550 tty random vnd sht21 tda19988 tps65217 tps65950 tsl2550 tty random uds vnd
.endif .endif
.endif # ${MKIMAGEONLY} != "yes" .endif # ${MKIMAGEONLY} != "yes"

12
drivers/uds/Makefile Normal file
View file

@ -0,0 +1,12 @@
# Makefile for the UNIX Domain Sockets driver (UDS)
PROG= uds
SRCS= uds.c ioc_uds.c
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
LDADD+= -lchardriver -lsys
MAN=
BINDIR?= /usr/sbin
.include <minix.service.mk>

View file

@ -5,37 +5,17 @@
* *
* The entry points into this file are... * The entry points into this file are...
* *
* uds_init: initialize the descriptor table.
* uds_do_ioctl: process an IOCTL request. * uds_do_ioctl: process an IOCTL request.
* uds_clear_fds: calls put_filp for undelivered FDs. * uds_clear_fds: calls put_filp for undelivered FDs.
*
* Also see...
*
* dev_uds.c, uds.h
*/ */
#define DEBUG 0
#include "inc.h"
#include "const.h"
#include "glo.h"
#include "uds.h" #include "uds.h"
/* File Descriptor Table */
uds_fd_t uds_fd_table[NR_FDS];
/* initialize the descriptor table */
void uds_init(void)
{
/* /*
* Setting everything to NULL implicitly sets the * Check the permissions of a socket file.
* state to UDS_FREE.
*/ */
memset(uds_fd_table, '\0', sizeof(uds_fd_t) * NR_FDS); static int
} check_perms(devminor_t minor, struct sockaddr_un *addr)
/* check the permissions of a socket file */
static int check_perms(devminor_t minor, struct sockaddr_un *addr)
{ {
int rc; int rc;
message vfs_m; message vfs_m;
@ -47,10 +27,10 @@ static int check_perms(devminor_t minor, struct sockaddr_un *addr)
/* ask the VFS to verify the permissions */ /* ask the VFS to verify the permissions */
memset(&vfs_m, '\0', sizeof(message)); memset(&vfs_m, '\0', sizeof(message));
vfs_m.m_type = VFS_PFS_CHECK_PERMS; vfs_m.m_type = VFS_UDS_CHECK_PERMS;
vfs_m.VFS_PFS_ENDPT = uds_fd_table[minor].owner; vfs_m.VFS_UDS_ENDPT = uds_fd_table[minor].owner;
vfs_m.VFS_PFS_GRANT = grant_id; vfs_m.VFS_UDS_GRANT = grant_id;
vfs_m.VFS_PFS_COUNT = UNIX_PATH_MAX; vfs_m.VFS_UDS_COUNT = UNIX_PATH_MAX;
rc = sendrec(VFS_PROC_NR, &vfs_m); rc = sendrec(VFS_PROC_NR, &vfs_m);
cpf_revoke(grant_id); cpf_revoke(grant_id);
@ -69,7 +49,8 @@ static int check_perms(devminor_t minor, struct sockaddr_un *addr)
return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */ return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
} }
static filp_id_t verify_fd(endpoint_t ep, int fd) static filp_id_t
verify_fd(endpoint_t ep, int fd)
{ {
int rc; int rc;
message vfs_m; message vfs_m;
@ -82,9 +63,9 @@ static filp_id_t verify_fd(endpoint_t ep, int fd)
memset(&vfs_m, '\0', sizeof(message)); memset(&vfs_m, '\0', sizeof(message));
vfs_m.m_type = VFS_PFS_VERIFY_FD; vfs_m.m_type = VFS_UDS_VERIFY_FD;
vfs_m.VFS_PFS_ENDPT = ep; vfs_m.VFS_UDS_ENDPT = ep;
vfs_m.VFS_PFS_FD = fd; vfs_m.VFS_UDS_FD = fd;
rc = sendrec(VFS_PROC_NR, &vfs_m); rc = sendrec(VFS_PROC_NR, &vfs_m);
if (OK != rc) { if (OK != rc) {
@ -97,10 +78,11 @@ static filp_id_t verify_fd(endpoint_t ep, int fd)
printf("(uds) VFS reply => %d\n", vfs_m.m_type); printf("(uds) VFS reply => %d\n", vfs_m.m_type);
#endif #endif
return vfs_m.VFS_PFS_FILP; return vfs_m.VFS_UDS_FILP;
} }
static int set_filp(filp_id_t sfilp) static int
set_filp(filp_id_t sfilp)
{ {
int rc; int rc;
message vfs_m; message vfs_m;
@ -112,8 +94,8 @@ static int set_filp(filp_id_t sfilp)
memset(&vfs_m, '\0', sizeof(message)); memset(&vfs_m, '\0', sizeof(message));
vfs_m.m_type = VFS_PFS_SET_FILP; vfs_m.m_type = VFS_UDS_SET_FILP;
vfs_m.VFS_PFS_FILP = sfilp; vfs_m.VFS_UDS_FILP = sfilp;
rc = sendrec(VFS_PROC_NR, &vfs_m); rc = sendrec(VFS_PROC_NR, &vfs_m);
if (OK != rc) { if (OK != rc) {
@ -128,7 +110,8 @@ static int set_filp(filp_id_t sfilp)
return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */ return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
} }
static int copy_filp(endpoint_t to_ep, filp_id_t cfilp) static int
copy_filp(endpoint_t to_ep, filp_id_t cfilp)
{ {
int rc; int rc;
message vfs_m; message vfs_m;
@ -141,9 +124,9 @@ static int copy_filp(endpoint_t to_ep, filp_id_t cfilp)
memset(&vfs_m, '\0', sizeof(message)); memset(&vfs_m, '\0', sizeof(message));
vfs_m.m_type = VFS_PFS_COPY_FILP; vfs_m.m_type = VFS_UDS_COPY_FILP;
vfs_m.VFS_PFS_ENDPT = to_ep; vfs_m.VFS_UDS_ENDPT = to_ep;
vfs_m.VFS_PFS_FILP = cfilp; vfs_m.VFS_UDS_FILP = cfilp;
rc = sendrec(VFS_PROC_NR, &vfs_m); rc = sendrec(VFS_PROC_NR, &vfs_m);
if (OK != rc) { if (OK != rc) {
@ -158,7 +141,8 @@ static int copy_filp(endpoint_t to_ep, filp_id_t cfilp)
return vfs_m.m_type; return vfs_m.m_type;
} }
static int put_filp(filp_id_t pfilp) static int
put_filp(filp_id_t pfilp)
{ {
int rc; int rc;
message vfs_m; message vfs_m;
@ -170,8 +154,8 @@ static int put_filp(filp_id_t pfilp)
memset(&vfs_m, '\0', sizeof(message)); memset(&vfs_m, '\0', sizeof(message));
vfs_m.m_type = VFS_PFS_PUT_FILP; vfs_m.m_type = VFS_UDS_PUT_FILP;
vfs_m.VFS_PFS_FILP = pfilp; vfs_m.VFS_UDS_FILP = pfilp;
rc = sendrec(VFS_PROC_NR, &vfs_m); rc = sendrec(VFS_PROC_NR, &vfs_m);
if (OK != rc) { if (OK != rc) {
@ -186,7 +170,8 @@ static int put_filp(filp_id_t pfilp)
return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */ return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
} }
static int cancel_fd(endpoint_t ep, int fd) static int
cancel_fd(endpoint_t ep, int fd)
{ {
int rc; int rc;
message vfs_m; message vfs_m;
@ -198,9 +183,9 @@ static int cancel_fd(endpoint_t ep, int fd)
memset(&vfs_m, '\0', sizeof(message)); memset(&vfs_m, '\0', sizeof(message));
vfs_m.m_type = VFS_PFS_CANCEL_FD; vfs_m.m_type = VFS_UDS_CANCEL_FD;
vfs_m.VFS_PFS_ENDPT = ep; vfs_m.VFS_UDS_ENDPT = ep;
vfs_m.VFS_PFS_FD = fd; vfs_m.VFS_UDS_FD = fd;
rc = sendrec(VFS_PROC_NR, &vfs_m); rc = sendrec(VFS_PROC_NR, &vfs_m);
if (OK != rc) { if (OK != rc) {
@ -215,7 +200,8 @@ static int cancel_fd(endpoint_t ep, int fd)
return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */ return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
} }
static int perform_connection(devminor_t minorx, devminor_t minory, static int
perform_connection(devminor_t minorx, devminor_t minory,
struct sockaddr_un *addr) struct sockaddr_un *addr)
{ {
/* there are several places were a connection is established. */ /* there are several places were a connection is established. */
@ -251,7 +237,8 @@ static int perform_connection(devminor_t minorx, devminor_t minory,
return OK; return OK;
} }
static int do_accept(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) static int
do_accept(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
devminor_t minorparent; /* minor number of parent (server) */ devminor_t minorparent; /* minor number of parent (server) */
devminor_t minorpeer; devminor_t minorpeer;
@ -370,7 +357,8 @@ static int do_accept(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
return OK; return OK;
} }
static int do_connect(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) static int
do_connect(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int child; int child;
struct sockaddr_un addr; struct sockaddr_un addr;
@ -509,7 +497,8 @@ static int do_connect(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
return EDONTREPLY; return EDONTREPLY;
} }
static int do_listen(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) static int
do_listen(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
int backlog_size; int backlog_size;
@ -585,7 +574,8 @@ static int do_listen(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
return OK; return OK;
} }
static int do_socket(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;
@ -629,7 +619,8 @@ static int do_socket(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
} }
} }
static int do_bind(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) static int
do_bind(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
struct sockaddr_un addr; struct sockaddr_un addr;
int rc, i; int rc, i;
@ -690,8 +681,8 @@ static int do_bind(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
return OK; return OK;
} }
static int do_getsockname(devminor_t minor, endpoint_t endpt, static int
cp_grant_id_t grant) do_getsockname(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
@ -714,8 +705,8 @@ static int do_getsockname(devminor_t minor, endpoint_t endpt,
return rc ? EIO : OK; return rc ? EIO : OK;
} }
static int do_getpeername(devminor_t minor, endpoint_t endpt, static int
cp_grant_id_t grant) do_getpeername(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
@ -748,7 +739,8 @@ static int do_getpeername(devminor_t minor, endpoint_t endpt,
} }
} }
static int do_shutdown(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) static int
do_shutdown(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc, how; int rc, how;
@ -784,12 +776,12 @@ static int do_shutdown(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
switch (how) { switch (how) {
case SHUT_RD: case SHUT_RD:
/* take away read permission */ /* take away read permission */
uds_fd_table[minor].mode &= ~S_IRUSR; uds_fd_table[minor].mode &= ~R_BIT;
break; break;
case SHUT_WR: case SHUT_WR:
/* take away write permission */ /* take away write permission */
uds_fd_table[minor].mode &= ~S_IWUSR; uds_fd_table[minor].mode &= ~W_BIT;
break; break;
case SHUT_RDWR: case SHUT_RDWR:
@ -805,8 +797,8 @@ static int do_shutdown(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
return OK; return OK;
} }
static int do_socketpair(devminor_t minorx, endpoint_t endpt, static int
cp_grant_id_t grant) do_socketpair(devminor_t minorx, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
dev_t minorin; dev_t minorin;
@ -848,8 +840,8 @@ static int do_socketpair(devminor_t minorx, endpoint_t endpt,
return perform_connection(minorx, minory, &addr); return perform_connection(minorx, minory, &addr);
} }
static int do_getsockopt_sotype(devminor_t minor, endpoint_t endpt, static int
cp_grant_id_t grant) do_getsockopt_sotype(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
@ -872,8 +864,8 @@ static int do_getsockopt_sotype(devminor_t minor, endpoint_t endpt,
return rc ? EIO : OK; return rc ? EIO : OK;
} }
static int do_getsockopt_peercred(devminor_t minor, endpoint_t endpt, static int
cp_grant_id_t grant) do_getsockopt_peercred(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int peer_minor; int peer_minor;
int rc; int rc;
@ -911,8 +903,8 @@ static int do_getsockopt_peercred(devminor_t minor, endpoint_t endpt,
return rc ? EIO : OK; return rc ? EIO : OK;
} }
static int do_getsockopt_sndbuf(devminor_t minor, endpoint_t endpt, static int
cp_grant_id_t grant) do_getsockopt_sndbuf(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
size_t sndbuf = PIPE_BUF; size_t sndbuf = PIPE_BUF;
@ -929,8 +921,8 @@ static int do_getsockopt_sndbuf(devminor_t minor, endpoint_t endpt,
return rc ? EIO : OK; return rc ? EIO : OK;
} }
static int do_setsockopt_sndbuf(devminor_t minor, endpoint_t endpt, static int
cp_grant_id_t grant) do_setsockopt_sndbuf(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
size_t sndbuf; size_t sndbuf;
@ -959,8 +951,8 @@ static int do_setsockopt_sndbuf(devminor_t minor, endpoint_t endpt,
return OK; return OK;
} }
static int do_getsockopt_rcvbuf(devminor_t minor, endpoint_t endpt, static int
cp_grant_id_t grant) do_getsockopt_rcvbuf(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
size_t rcvbuf = PIPE_BUF; size_t rcvbuf = PIPE_BUF;
@ -977,8 +969,8 @@ static int do_getsockopt_rcvbuf(devminor_t minor, endpoint_t endpt,
return rc ? EIO : OK; return rc ? EIO : OK;
} }
static int do_setsockopt_rcvbuf(devminor_t minor, endpoint_t endpt, static int
cp_grant_id_t grant) do_setsockopt_rcvbuf(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
size_t rcvbuf; size_t rcvbuf;
@ -1007,7 +999,8 @@ static int do_setsockopt_rcvbuf(devminor_t minor, endpoint_t endpt,
return OK; return OK;
} }
static int do_sendto(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) static int
do_sendto(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
struct sockaddr_un addr; struct sockaddr_un addr;
@ -1046,7 +1039,8 @@ static int do_sendto(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
return OK; return OK;
} }
static int do_recvfrom(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; int rc;
@ -1063,8 +1057,9 @@ static int do_recvfrom(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
return rc ? EIO : OK; return rc ? EIO : OK;
} }
static int msg_control_read(struct msg_control *msg_ctrl, static int
struct ancillary *data, devminor_t minor) msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
devminor_t minor)
{ {
int rc; int rc;
struct msghdr msghdr; struct msghdr msghdr;
@ -1122,7 +1117,8 @@ static int msg_control_read(struct msg_control *msg_ctrl,
return OK; return OK;
} }
static int send_fds(devminor_t minor, struct ancillary *data) static int
send_fds(devminor_t minor, struct ancillary *data)
{ {
int rc, i, j; int rc, i, j;
@ -1156,13 +1152,15 @@ static int send_fds(devminor_t minor, struct ancillary *data)
return OK; return OK;
} }
int uds_clear_fds(devminor_t minor, struct ancillary *data) /*
{ * This function calls put_filp() for all of the FDs in 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 * This is used when a Unix Domain Socket is closed and there
* exists references to file descriptors that haven't been received * exists references to file descriptors that haven't been received
* with recvmsg(). * with recvmsg().
*/ */
int
uds_clear_fds(devminor_t minor, struct ancillary *data)
{
int i; int i;
#if DEBUG == 1 #if DEBUG == 1
@ -1185,7 +1183,8 @@ int uds_clear_fds(devminor_t minor, struct ancillary *data)
return OK; return OK;
} }
static int recv_fds(devminor_t minor, struct ancillary *data, static int
recv_fds(devminor_t minor, struct ancillary *data,
struct msg_control *msg_ctrl) struct msg_control *msg_ctrl)
{ {
int rc, i, j; int rc, i, j;
@ -1241,7 +1240,8 @@ static int recv_fds(devminor_t minor, struct ancillary *data,
return OK; return OK;
} }
static int recv_cred(devminor_t minor, struct ancillary *data, static int
recv_cred(devminor_t minor, struct ancillary *data,
struct msg_control *msg_ctrl) struct msg_control *msg_ctrl)
{ {
struct msghdr msghdr; struct msghdr msghdr;
@ -1269,7 +1269,8 @@ static int recv_cred(devminor_t minor, struct ancillary *data,
return OK; return OK;
} }
static int do_sendmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) static int
do_sendmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int peer, rc, i; int peer, rc, i;
struct msg_control msg_ctrl; struct msg_control msg_ctrl;
@ -1339,7 +1340,8 @@ static int do_sendmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
return send_fds(minor, &uds_fd_table[peer].ancillary_data); return send_fds(minor, &uds_fd_table[peer].ancillary_data);
} }
static int do_recvmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) static int
do_recvmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
{ {
int rc; int rc;
struct msg_control msg_ctrl; struct msg_control msg_ctrl;
@ -1403,7 +1405,8 @@ static int do_recvmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
return rc ? EIO : OK; return rc ? EIO : OK;
} }
int uds_do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, int
uds_do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
cp_grant_id_t grant) cp_grant_id_t grant)
{ {
int rc; int rc;

View file

@ -4,41 +4,31 @@
* *
* The entry points into this file are... * The entry points into this file are...
* *
* uds_request: process a character device request * uds_unsuspend: resume a previously suspended socket call
* * main: driver main loop
* Also See...
*
* uds.c, uds.h
*
* Overview
* *
* The interface to unix domain sockets is similar to the interface to network * The interface to unix domain sockets is similar to the interface to network
* sockets. There is a character device (/dev/uds) and this server is a * sockets. There is a character device (/dev/uds) and this server is a
* 'driver' for that device. * 'driver' for that device.
*/ */
#define DEBUG 0
#include "inc.h"
#include "const.h"
#include "glo.h"
#include "uds.h" #include "uds.h"
static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt, static ssize_t uds_perform_read(devminor_t, endpoint_t, cp_grant_id_t, size_t,
cp_grant_id_t grant, size_t size, int pretend); int);
static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt, static ssize_t uds_perform_write(devminor_t, endpoint_t, cp_grant_id_t, size_t,
cp_grant_id_t grant, size_t size, int pretend); int);
static int uds_open(devminor_t orig_minor, int access, endpoint_t user_endpt); static int uds_open(devminor_t, int, endpoint_t);
static int uds_close(devminor_t minor); static int uds_close(devminor_t);
static ssize_t uds_read(devminor_t minor, u64_t position, endpoint_t endpt, static ssize_t uds_read(devminor_t, u64_t, endpoint_t, cp_grant_id_t, size_t,
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id); int, cdev_id_t);
static ssize_t uds_write(devminor_t minor, u64_t position, endpoint_t endpt, static ssize_t uds_write(devminor_t, u64_t, endpoint_t, cp_grant_id_t, size_t,
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id); int, cdev_id_t);
static int uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, static int uds_ioctl(devminor_t, unsigned long, endpoint_t, cp_grant_id_t, int,
cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id); endpoint_t, cdev_id_t);
static int uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id); static int uds_cancel(devminor_t, endpoint_t, cdev_id_t);
static int uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt); static int uds_select(devminor_t, unsigned int, endpoint_t);
static struct chardriver uds_tab = { static struct chardriver uds_tab = {
.cdr_open = uds_open, .cdr_open = uds_open,
@ -50,19 +40,18 @@ static struct chardriver uds_tab = {
.cdr_select = uds_select .cdr_select = uds_select
}; };
void uds_request(message *m_ptr, int ipc_status) /* File Descriptor Table */
{ uds_fd_t uds_fd_table[NR_FDS];
/* Use libchardriver to process character device requests. */
chardriver_process(&uds_tab, m_ptr, ipc_status);
}
static int uds_open(devminor_t UNUSED(orig_minor), int access, static unsigned int uds_exit_left;
static int
uds_open(devminor_t UNUSED(orig_minor), int access,
endpoint_t user_endpt) endpoint_t user_endpt)
{ {
message fs_m_in, fs_m_out;
struct uucred ucred;
devminor_t minor; devminor_t minor;
int rc, i; int i;
char *buf;
#if DEBUG == 1 #if DEBUG == 1
static int call_count = 0; static int call_count = 0;
@ -77,7 +66,6 @@ static int uds_open(devminor_t UNUSED(orig_minor), int access,
* minor number. The minor number must be different from the * minor number. The minor number must be different from the
* the /dev/uds device's minor number (currently 0). * the /dev/uds device's minor number (currently 0).
*/ */
minor = -1; /* to trap error */ minor = -1; /* to trap error */
for (i = 1; i < NR_FDS; i++) { for (i = 1; i < NR_FDS; i++) {
@ -91,8 +79,14 @@ static int uds_open(devminor_t UNUSED(orig_minor), int access,
return ENFILE; return ENFILE;
/* /*
* We found a slot in uds_fd_table, now initialize the descriptor * Allocate memory for the ringer buffer. In order to save on memory
* in the common case, the buffer is allocated only when the socket is
* 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,
MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return ENOMEM;
/* mark this one as 'in use' so that it doesn't get assigned to /* mark this one as 'in use' so that it doesn't get assigned to
* another socket * another socket
@ -105,8 +99,7 @@ static int uds_open(devminor_t UNUSED(orig_minor), int access,
/* setup select(2) framework */ /* setup select(2) framework */
uds_fd_table[minor].sel_endpt = NONE; uds_fd_table[minor].sel_endpt = NONE;
uds_fd_table[minor].sel_ops = 0; uds_fd_table[minor].sel_ops = 0;
uds_fd_table[minor].buf = buf;
/* initialize the data pointer (pos) to the start of the PIPE */
uds_fd_table[minor].pos = 0; uds_fd_table[minor].pos = 0;
/* the PIPE is initially empty */ /* the PIPE is initially empty */
@ -115,7 +108,7 @@ static int uds_open(devminor_t UNUSED(orig_minor), int access,
/* the default for a new socket is to allow reading and writing. /* the default for a new socket is to allow reading and writing.
* shutdown(2) will remove one or both flags. * shutdown(2) will remove one or both flags.
*/ */
uds_fd_table[minor].mode = S_IRUSR|S_IWUSR; uds_fd_table[minor].mode = R_BIT | W_BIT;
/* In libc socket(2) sets this to the actual value later with the /* In libc socket(2) sets this to the actual value later with the
* NWIOSUDSTYPE ioctl(). * NWIOSUDSTYPE ioctl().
@ -156,46 +149,13 @@ static int uds_open(devminor_t UNUSED(orig_minor), int access,
/* Initially the socket isn't suspended. */ /* Initially the socket isn't suspended. */
uds_fd_table[minor].suspended = UDS_NOT_SUSPENDED; uds_fd_table[minor].suspended = UDS_NOT_SUSPENDED;
/* get the effective user id and effective group id from the endpoint */
/* this is needed in the REQ_NEWNODE request to PFS. */
rc = getnucred(user_endpt, &ucred);
if (rc == -1) {
/* roll back the changes we made to the descriptor */
memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));
/* likely error: invalid endpoint / proc doesn't exist */
return EIO;
}
/* Prepare Request to the FS side of PFS */
fs_m_in.m_type = REQ_NEWNODE;
fs_m_in.REQ_MODE = I_NAMED_PIPE;
fs_m_in.REQ_DEV = NO_DEV;
fs_m_in.REQ_UID = ucred.cr_uid;
fs_m_in.REQ_GID = ucred.cr_gid;
/* Request a new inode on the pipe file system */
rc = fs_newnode(&fs_m_in, &fs_m_out);
if (rc != OK) {
/* roll back the changes we made to the descriptor */
memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));
/* likely error: get_block() failed */
return rc;
}
/* Process the response */
uds_fd_table[minor].inode_nr = fs_m_out.RES_INODE_NR;
return CDEV_CLONED | minor; return CDEV_CLONED | minor;
} }
static int uds_close(devminor_t minor) static int
uds_close(devminor_t minor)
{ {
message fs_m_in, fs_m_out; int peer;
int rc;
#if DEBUG == 1 #if DEBUG == 1
static int call_count = 0; static int call_count = 0;
@ -213,7 +173,7 @@ static int uds_close(devminor_t minor)
/* if the socket is connected, disconnect it */ /* if the socket is connected, disconnect it */
if (uds_fd_table[minor].peer != -1) { if (uds_fd_table[minor].peer != -1) {
int peer = uds_fd_table[minor].peer; peer = uds_fd_table[minor].peer;
/* set peer of this peer to -1 */ /* set peer of this peer to -1 */
uds_fd_table[peer].peer = -1; uds_fd_table[peer].peer = -1;
@ -230,28 +190,23 @@ static int uds_close(devminor_t minor)
uds_clear_fds(minor, &uds_fd_table[minor].ancillary_data); uds_clear_fds(minor, &uds_fd_table[minor].ancillary_data);
} }
/* Prepare Request to the FS side of PFS */ /* Release the memory for the ring buffer. */
minix_munmap(uds_fd_table[minor].buf, PIPE_BUF);
fs_m_in.m_type = REQ_PUTNODE; /* Set the socket back to its original UDS_FREE state. */
fs_m_in.REQ_INODE_NR = uds_fd_table[minor].inode_nr; memset(&uds_fd_table[minor], '\0', sizeof(uds_fd_t));
fs_m_in.REQ_COUNT = 1;
/* set the socket back to its original UDS_FREE state */ /* If terminating, and this was the last open socket, exit now. */
memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t)); if (uds_exit_left > 0) {
if (--uds_exit_left == 0)
/* Request the removal of the inode from the pipe file system */ chardriver_terminate();
rc = fs_putnode(&fs_m_in, &fs_m_out);
if (rc != OK) {
printf("PFS: fs_putnode returned %d\n", rc);
return rc;
} }
return OK; return OK;
} }
static int uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt) static int
uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
{ {
unsigned int ready_ops; unsigned int ready_ops;
int i, bytes, watch; int i, bytes, watch;
@ -297,8 +252,7 @@ static int uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
/* check if we can write without blocking */ /* check if we can write without blocking */
if (ops & CDEV_OP_WR) { if (ops & CDEV_OP_WR) {
bytes = uds_perform_write(minor, NONE, GRANT_INVALID, PIPE_BUF, bytes = uds_perform_write(minor, NONE, GRANT_INVALID, 1, 1);
1);
if (bytes != 0 && bytes != SUSPEND) { if (bytes != 0 && bytes != SUSPEND) {
/* There is room to write or there is an error /* There is room to write or there is an error
* condition. * condition.
@ -319,12 +273,12 @@ static int uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
return ready_ops; return ready_ops;
} }
static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt, static ssize_t
cp_grant_id_t grant, size_t size, int pretend) uds_perform_read(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant,
size_t size, int pretend)
{ {
int rc, peer; size_t pos, subsize;
message fs_m_in; int r, peer;
message fs_m_out;
#if DEBUG == 1 #if DEBUG == 1
static int call_count = 0; static int call_count = 0;
@ -340,7 +294,7 @@ static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
} }
/* check if we are allowed to read */ /* check if we are allowed to read */
if (!(uds_fd_table[minor].mode & S_IRUSR)) { if (!(uds_fd_table[minor].mode & R_BIT)) {
/* socket is shutdown for reading */ /* socket is shutdown for reading */
return EPIPE; return EPIPE;
} }
@ -352,6 +306,7 @@ static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
if (uds_fd_table[minor].type == SOCK_STREAM || if (uds_fd_table[minor].type == SOCK_STREAM ||
uds_fd_table[minor].type == SOCK_SEQPACKET) { uds_fd_table[minor].type == SOCK_SEQPACKET) {
if (uds_fd_table[minor].err == ECONNRESET) { if (uds_fd_table[minor].err == ECONNRESET) {
if (!pretend)
uds_fd_table[minor].err = 0; uds_fd_table[minor].err = 0;
return ECONNRESET; return ECONNRESET;
} else { } else {
@ -361,7 +316,7 @@ static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
} }
/* Check if process is reading from a closed pipe */ /* Check if process is reading from a closed pipe */
if (peer != -1 && !(uds_fd_table[peer].mode & S_IWUSR) && if (peer != -1 && !(uds_fd_table[peer].mode & W_BIT) &&
uds_fd_table[minor].size == 0) { uds_fd_table[minor].size == 0) {
return 0; return 0;
} }
@ -386,40 +341,34 @@ static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
return EDONTREPLY; return EDONTREPLY;
} }
if (pretend) { /* How much can we get from the ring buffer? */
return (size > uds_fd_table[minor].size) ? if (size > uds_fd_table[minor].size)
uds_fd_table[minor].size : size; size = uds_fd_table[minor].size;
if (pretend)
return size;
/* Get the data from the tail of the ring buffer. */
pos = uds_fd_table[minor].pos;
subsize = PIPE_BUF - pos;
if (subsize > size)
subsize = size;
if ((r = sys_safecopyto(endpt, grant, 0,
(vir_bytes) &uds_fd_table[minor].buf[pos], subsize)) != OK)
return r;
if (subsize < size) {
if ((r = sys_safecopyto(endpt, grant, subsize,
(vir_bytes) uds_fd_table[minor].buf,
size - subsize)) != OK)
return r;
} }
/* Prepare Request to the FS side of PFS */ /* Advance the buffer tail. */
fs_m_in.m_source = endpt; uds_fd_table[minor].pos = (pos + size) % PIPE_BUF;
fs_m_in.m_type = REQ_READ; uds_fd_table[minor].size -= size;
fs_m_in.REQ_INODE_NR = uds_fd_table[minor].inode_nr;
fs_m_in.REQ_GRANT = grant;
fs_m_in.REQ_SEEK_POS_HI = 0;
fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[minor].pos;
fs_m_in.REQ_NBYTES = (size > uds_fd_table[minor].size) ?
uds_fd_table[minor].size : size;
/* perform the read */
rc = fs_readwrite(&fs_m_in, &fs_m_out);
if (rc != OK) {
printf("PFS: fs_readwrite returned %d\n", rc);
return rc;
}
/* Process the response */
#if DEBUG == 1
printf("(uds) [%d] read complete\n", minor);
#endif
/* move the position of the data pointer up to data we haven't
* read yet
*/
uds_fd_table[minor].pos += fs_m_out.RES_NBYTES;
/* decrease the number of unread bytes */
uds_fd_table[minor].size -= fs_m_out.RES_NBYTES;
/* if we have 0 unread bytes, move the data pointer back to the /* if we have 0 unread bytes, move the data pointer back to the
* start of the buffer * start of the buffer
@ -439,22 +388,22 @@ static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
* and it doesn't know about it already, then let the peer know. * and it doesn't know about it already, then let the peer know.
*/ */
if (peer != -1 && (uds_fd_table[peer].sel_ops & CDEV_OP_WR) && if (peer != -1 && (uds_fd_table[peer].sel_ops & CDEV_OP_WR) &&
(uds_fd_table[minor].size+uds_fd_table[minor].pos + 1 < PIPE_BUF)){ size > 0) {
/* a write on peer is possible now */ /* a write on peer is possible now */
chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer, 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; uds_fd_table[peer].sel_ops &= ~CDEV_OP_WR;
} }
return fs_m_out.RES_NBYTES; /* return number of bytes read */ return size; /* return number of bytes read */
} }
static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt, static ssize_t
cp_grant_id_t grant, size_t size, int pretend) uds_perform_write(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant,
size_t size, int pretend)
{ {
int rc, peer, i; size_t subsize, pos;
message fs_m_in; int i, r, peer;
message fs_m_out;
#if DEBUG == 1 #if DEBUG == 1
static int call_count = 0; static int call_count = 0;
@ -462,13 +411,12 @@ static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
++call_count); ++call_count);
#endif #endif
/* skip reads and writes of 0 (or less!) bytes */ /* Skip writes of zero bytes. */
if (size <= 0) { if (size == 0)
return 0; return 0;
}
/* check if we are allowed to write */ /* check if we are allowed to write */
if (!(uds_fd_table[minor].mode & S_IWUSR)) { if (!(uds_fd_table[minor].mode & W_BIT)) {
/* socket is shutdown for writing */ /* socket is shutdown for writing */
return EPIPE; return EPIPE;
} }
@ -522,7 +470,7 @@ static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
} }
/* check if we write to a closed pipe */ /* check if we write to a closed pipe */
if (!(uds_fd_table[peer].mode & S_IRUSR)) { if (!(uds_fd_table[peer].mode & R_BIT)) {
return EPIPE; return EPIPE;
} }
@ -535,14 +483,13 @@ static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
return size; return size;
} }
/* check if write would overrun buffer. check if message /*
* SEQPACKET wouldn't write to an empty buffer. check if * Check if the ring buffer is already full, and if the SEQPACKET
* connectionless sockets have a target to write to. * message wouldn't write to an empty buffer.
*/ */
if ((uds_fd_table[peer].pos+uds_fd_table[peer].size+size > PIPE_BUF) || if (uds_fd_table[peer].size == PIPE_BUF ||
((uds_fd_table[minor].type == SOCK_SEQPACKET) && (uds_fd_table[minor].type == SOCK_SEQPACKET &&
uds_fd_table[peer].size > 0)) { uds_fd_table[peer].size > 0)) {
if (pretend) { if (pretend) {
return SUSPEND; return SUSPEND;
} }
@ -561,33 +508,32 @@ static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
return EDONTREPLY; return EDONTREPLY;
} }
if (pretend) { /* 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 (pretend)
return size; 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;
subsize = PIPE_BUF - pos;
if (subsize > size)
subsize = size;
if ((r = sys_safecopyfrom(endpt, grant, 0,
(vir_bytes) &uds_fd_table[peer].buf[pos], subsize)) != OK)
return r;
if (subsize < size) {
if ((r = sys_safecopyfrom(endpt, grant, subsize,
(vir_bytes) uds_fd_table[peer].buf, size - subsize)) != OK)
return r;
} }
/* Prepare Request to the FS side of PFS */ /* Advance the buffer head. */
fs_m_in.m_source = endpt; uds_fd_table[peer].size += size;
fs_m_in.m_type = REQ_WRITE;
fs_m_in.REQ_INODE_NR = uds_fd_table[peer].inode_nr;
fs_m_in.REQ_GRANT = grant;
fs_m_in.REQ_SEEK_POS_HI = 0;
fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[peer].pos +
uds_fd_table[peer].size;
fs_m_in.REQ_NBYTES = size;
/* Request the write */
rc = fs_readwrite(&fs_m_in, &fs_m_out);
if (rc != OK) {
printf("PFS: fs_readwrite returned %d\n", rc);
return rc;
}
/* Process the response */
#if DEBUG == 1
printf("(uds) [%d] write complete\n", minor);
#endif
/* increase the count of unread bytes */
uds_fd_table[peer].size += fs_m_out.RES_NBYTES;
/* fill in the source address to be returned by recvfrom & recvmsg */ /* fill in the source address to be returned by recvfrom & recvmsg */
if (uds_fd_table[minor].type == SOCK_DGRAM) { if (uds_fd_table[minor].type == SOCK_DGRAM) {
@ -603,18 +549,18 @@ static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
* data ready to read and it doesn't know about it already, then let * data ready to read and it doesn't know about it already, then let
* the peer know we have data for it. * the peer know we have data for it.
*/ */
if ((uds_fd_table[peer].sel_ops & CDEV_OP_RD) && if ((uds_fd_table[peer].sel_ops & CDEV_OP_RD) && size > 0) {
fs_m_out.RES_NBYTES > 0) {
/* a read on peer is possible now */ /* a read on peer is possible now */
chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer, 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; uds_fd_table[peer].sel_ops &= ~CDEV_OP_RD;
} }
return fs_m_out.RES_NBYTES; /* return number of bytes written */ return size; /* return number of bytes written */
} }
static ssize_t uds_read(devminor_t minor, u64_t position, endpoint_t endpt, static ssize_t
uds_read(devminor_t minor, u64_t position, endpoint_t endpt,
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id) cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
{ {
ssize_t rc; ssize_t rc;
@ -654,7 +600,8 @@ static ssize_t uds_read(devminor_t minor, u64_t position, endpoint_t endpt,
return rc; return rc;
} }
static ssize_t uds_write(devminor_t minor, u64_t position, endpoint_t endpt, static ssize_t
uds_write(devminor_t minor, u64_t position, endpoint_t endpt,
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id) cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
{ {
ssize_t rc; ssize_t rc;
@ -694,7 +641,8 @@ static ssize_t uds_write(devminor_t minor, u64_t position, endpoint_t endpt,
return rc; return rc;
} }
static int uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, static int
uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id) cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id)
{ {
int rc; int rc;
@ -740,7 +688,8 @@ static int uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
return rc; return rc;
} }
void uds_unsuspend(devminor_t minor) void
uds_unsuspend(devminor_t minor)
{ {
int r; int r;
uds_fd_t *fdp; uds_fd_t *fdp;
@ -784,7 +733,8 @@ void uds_unsuspend(devminor_t minor)
fdp->suspended = UDS_NOT_SUSPENDED; fdp->suspended = UDS_NOT_SUSPENDED;
} }
static int uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id) static int
uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
{ {
uds_fd_t *fdp; uds_fd_t *fdp;
int i, j; int i, j;
@ -799,7 +749,7 @@ static int uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
fdp = &uds_fd_table[minor]; fdp = &uds_fd_table[minor];
if (fdp->state != UDS_INUSE) { if (fdp->state != UDS_INUSE) {
printf("PFS: cancel request for closed minor %d\n", minor); printf("UDS: cancel request for closed minor %d\n", minor);
return EDONTREPLY; return EDONTREPLY;
} }
@ -863,3 +813,63 @@ static int uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
return EINTR; /* reply to the original request */ return EINTR; /* reply to the original request */
} }
/*
* Initialize the server.
*/
static int
uds_init(int UNUSED(type), sef_init_info_t *UNUSED(info))
{
/* Setting everything to NULL implicitly sets the state to UDS_FREE. */
memset(uds_fd_table, '\0', sizeof(uds_fd_t) * NR_FDS);
uds_exit_left = 0;
return(OK);
}
static void
uds_signal(int signo)
{
int i;
/* Only check for termination signal, ignore anything else. */
if (signo != SIGTERM) return;
/* Only exit once all sockets have been closed. */
uds_exit_left = 0;
for (i = 0; i < NR_FDS; i++)
if (uds_fd_table[i].state == UDS_INUSE)
uds_exit_left++;
if (uds_exit_left == 0)
chardriver_terminate();
}
static void
uds_startup(void)
{
/* Register init callbacks. */
sef_setcb_init_fresh(uds_init);
/* No live update support for now. */
/* Register signal callbacks. */
sef_setcb_signal_handler(uds_signal);
/* Let SEF perform startup. */
sef_startup();
}
/*
* The UNIX domain sockets driver.
*/
int
main(void)
{
uds_startup();
chardriver_task(&uds_tab);
return(OK);
}

View file

@ -1,25 +1,24 @@
#ifndef __PFS_UDS_H__ #ifndef __UDS_UDS_H
#define __PFS_UDS_H__ #define __UDS_UDS_H
/* #include <minix/drivers.h>
* Unix Domain Sockets Implementation (PF_UNIX, PF_LOCAL) #include <minix/chardriver.h>
* #undef send
* Also See... #include <sys/socket.h>
* #include <sys/ioctl.h>
* dev_uds.c, table.c, uds.c
*/
#include <limits.h>
#include <sys/types.h>
#include <sys/ucred.h> #include <sys/ucred.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/mman.h>
#include <minix/endpoint.h> /* Maximum number of UNIX domain sockets. */
#include <minix/chardriver.h> #define NR_FDS 256
/* max connection backlog for incoming connections */ /* Connection backlog size for incoming connections. */
#define UDS_SOMAXCONN 64 #define UDS_SOMAXCONN 64
/* Output debugging information? */
#define DEBUG 0
typedef void* filp_id_t; typedef void* filp_id_t;
/* ancillary data to be sent */ /* ancillary data to be sent */
@ -57,26 +56,16 @@ struct uds_fd {
/* Pipe Housekeeping */ /* Pipe Housekeeping */
/* inode number on PFS -- each descriptor is backed by 1 char *buf; /* ring buffer */
* PIPE which is allocated in uds_open() and freed in size_t pos; /* tail position into ring buffer */
* uds_close(). Data is sent/written to a peer's PIPE. size_t size; /* size of used part of ring buffer */
* Data is recv/read from this PIPE.
*/
pino_t inode_nr;
/* position in the PIPE where the data starts */
off_t pos;
/* size of data in the PIPE */
size_t size;
/* control read/write, set by uds_open() and shutdown(2). /* control read/write, set by uds_open() and shutdown(2).
* Can be set to S_IRUSR|S_IWUSR, S_IRUSR, S_IWUSR, or 0 * Can be set to R_BIT|W_BIT, R_BIT, W_BIT, or 0
* for read and write, read only, write only, or neither. * for read and write, read only, write only, or neither.
* default is S_IRUSR|S_IWUSR. * default is R_BIT|W_BIT.
*/ */
pmode_t mode; int mode;
/* Socket Info */ /* Socket Info */
@ -188,4 +177,14 @@ typedef struct uds_fd uds_fd_t;
/* File Descriptor Table -- Defined in uds.c */ /* File Descriptor Table -- Defined in uds.c */
EXTERN uds_fd_t uds_fd_table[NR_FDS]; EXTERN uds_fd_t uds_fd_table[NR_FDS];
#endif /* Function prototypes. */
/* dev_uds.c */
void uds_unsuspend(devminor_t minor);
/* 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);
#endif /* !__UDS_UDS_H */

View file

@ -687,7 +687,7 @@ service vbox
service fbd service fbd
{ {
ipc ipc
SYSTEM VFS RS DS VM SYSTEM vfs rs ds vm
ahci ahci
at_wini at_wini
; ;
@ -696,7 +696,15 @@ service fbd
service vnd service vnd
{ {
ipc ipc
SYSTEM VFS RS VM SYSTEM vfs rs vm
; ;
uid 0; # only for dupfrom(2) uid 0; # only for dupfrom(2)
}; };
service uds
{
ipc
SYSTEM vfs rs vm
;
uid 0; # for various VFS backcalls, until we have ACLs
};

View file

@ -193,6 +193,8 @@ start)
up inet -script /etc/rs.inet -dev /dev/ip up inet -script /etc/rs.inet -dev /dev/ip
fi fi
up uds -dev /dev/uds
up -n ipc up -n ipc
up log -dev /dev/klog up log -dev /dev/klog

View file

@ -112,9 +112,9 @@
#define MAPDRIVER 122 /* to VFS, map a device */ #define MAPDRIVER 122 /* to VFS, map a device */
#define GETRUSAGE 123 /* to PM, VFS */ #define GETRUSAGE 123 /* to PM, VFS */
#define VFS_PFS_CHECK_PERMS 124 /* to VFS */ #define VFS_UDS_CHECK_PERMS 124 /* to VFS */
#define VFS_PFS_VERIFY_FD 125 /* to VFS */ #define VFS_UDS_VERIFY_FD 125 /* to VFS */
#define VFS_PFS_SET_FILP 126 /* to VFS */ #define VFS_UDS_SET_FILP 126 /* to VFS */
#define VFS_PFS_COPY_FILP 127 /* to VFS */ #define VFS_UDS_COPY_FILP 127 /* to VFS */
#define VFS_PFS_PUT_FILP 128 /* to VFS */ #define VFS_UDS_PUT_FILP 128 /* to VFS */
#define VFS_PFS_CANCEL_FD 129 /* to VFS */ #define VFS_UDS_CANCEL_FD 129 /* to VFS */

View file

@ -882,12 +882,12 @@
#define VFS_IOCTL_REQ m2_i3 #define VFS_IOCTL_REQ m2_i3
#define VFS_IOCTL_ARG m2_p1 #define VFS_IOCTL_ARG m2_p1
/* Field names for the PFS backcalls to VFS. */ /* Field names for the UDS backcalls to VFS. */
#define VFS_PFS_ENDPT m2_i1 #define VFS_UDS_ENDPT m2_i1
#define VFS_PFS_GRANT m2_i2 #define VFS_UDS_GRANT m2_i2
#define VFS_PFS_COUNT m2_i3 #define VFS_UDS_COUNT m2_i3
#define VFS_PFS_FD m2_i3 #define VFS_UDS_FD m2_i3
#define VFS_PFS_FILP m2_p1 #define VFS_UDS_FILP m2_p1
/* Field names for the dupfrom(2) call. */ /* Field names for the dupfrom(2) call. */
#define VFS_DUPFROM_ENDPT m1_i1 #define VFS_DUPFROM_ENDPT m1_i1

View file

@ -1,8 +1,7 @@
# Makefile for Pipe File System (PFS) # Makefile for Pipe File System (PFS)
PROG= pfs PROG= pfs
SRCS= open.c table.c inode.c main.c super.c link.c \ SRCS= open.c table.c inode.c main.c super.c link.c \
buffer.c read.c misc.c mount.c utility.c stadir.c \ buffer.c read.c misc.c mount.c utility.c stadir.c
uds.c dev_uds.c
DPADD+= ${LIBCHARDRIVER} ${LIBSYS} DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
LDADD+= -lchardriver -lsys LDADD+= -lchardriver -lsys

View file

@ -3,40 +3,20 @@
#define PFS_NR_INODES 512 /* # slots in "in core" inode table */ #define PFS_NR_INODES 512 /* # slots in "in core" inode table */
/* Size of descriptor table for unix domain sockets. This should be
* equal to the maximum number of minor devices (currently 256).
*/
#define NR_FDS 256
#define INODE_HASH_LOG2 7 /* 2 based logarithm of the inode hash size */ #define INODE_HASH_LOG2 7 /* 2 based logarithm of the inode hash size */
#define INODE_HASH_SIZE ((unsigned long)1<<INODE_HASH_LOG2) #define INODE_HASH_SIZE ((unsigned long)1<<INODE_HASH_LOG2)
#define INODE_HASH_MASK (((unsigned long)1<<INODE_HASH_LOG2)-1) #define INODE_HASH_MASK (((unsigned long)1<<INODE_HASH_LOG2)-1)
/* The type of sizeof may be (unsigned) long. Use the following macro for
* taking the sizes of small objects so that there are no surprises like
* (small) long constants being passed to routines expecting an int.
*/
#define usizeof(t) ((unsigned) sizeof(t))
/* Miscellaneous constants */
#define INVAL_UID ((uid_t) -1) /* Invalid user ID */
#define INVAL_GID ((gid_t) -1) /* Invalid group ID */
#define NORMAL 0 /* forces get_block to do disk read */
#define NO_READ 1 /* prevents get_block from doing disk read */
#define PREFETCH 2 /* tells get_block not to read or mark dev */
#define NO_BIT ((bit_t) 0) /* returned by alloc_bit() to signal failure */ #define NO_BIT ((bit_t) 0) /* returned by alloc_bit() to signal failure */
#define ATIME 002 /* set if atime field needs updating */ #define ATIME 002 /* set if atime field needs updating */
#define CTIME 004 /* set if ctime field needs updating */ #define CTIME 004 /* set if ctime field needs updating */
#define MTIME 010 /* set if mtime field needs updating */ #define MTIME 010 /* set if mtime field needs updating */
#define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk */ #define FS_BITMAP_CHUNKS(b) ((b)/sizeof (bitchunk_t))/* # map chunks/blk */
#define FS_BITCHUNK_BITS (usizeof(bitchunk_t) * CHAR_BIT) #define FS_BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT)
#define FS_BITS_PER_BLOCK(b) (FS_BITMAP_CHUNKS(b) * FS_BITCHUNK_BITS) #define FS_BITS_PER_BLOCK(b) (FS_BITMAP_CHUNKS(b) * FS_BITCHUNK_BITS)
#define FS_CALL_VEC_SIZE 31 #define FS_CALL_VEC_SIZE 31
#define DEV_CALL_VEC_SIZE 25
#endif #endif

View file

@ -1,36 +0,0 @@
#define _SYSTEM 1 /* get OK and negative error codes */
#define _NETBSD_SOURCE 1 /* tell headers to include MINIX stuff */
#define VERBOSE 0 /* display diagnostics */
#include <sys/ioc_net.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/ucred.h>
#include <limits.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <minix/callnr.h>
#include <minix/config.h>
#include <minix/dmap.h>
#include <minix/type.h>
#include <minix/const.h>
#include <minix/com.h>
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <minix/bitmap.h>
#include <minix/vfsif.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include "proto.h"

View file

@ -10,7 +10,6 @@
#include <pwd.h> #include <pwd.h>
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
#include "uds.h"
static void get_work(message *m_in, int *status); static void get_work(message *m_in, int *status);
@ -41,13 +40,6 @@ int main(int argc, char *argv[])
/* Wait for request message. */ /* Wait for request message. */
get_work(&pfs_m_in, &ipc_status); get_work(&pfs_m_in, &ipc_status);
/* If this is a UDS device request, process it and continue. */
if (IS_CDEV_RQ(pfs_m_in.m_type)) {
uds_request(&pfs_m_in, ipc_status);
continue;
}
transid = TRNS_GET_ID(pfs_m_in.m_type); transid = TRNS_GET_ID(pfs_m_in.m_type);
pfs_m_in.m_type = TRNS_DEL_ID(pfs_m_in.m_type); pfs_m_in.m_type = TRNS_DEL_ID(pfs_m_in.m_type);
if (pfs_m_in.m_type == 0) { if (pfs_m_in.m_type == 0) {
@ -119,10 +111,8 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info)
} }
init_inode_cache(); init_inode_cache();
uds_init();
buf_pool(); buf_pool();
/* Drop root privileges */ /* Drop root privileges */
if ((pw = getpwnam(SERVICE_LOGIN)) == NULL) { if ((pw = getpwnam(SERVICE_LOGIN)) == NULL) {
printf("PFS: unable to retrieve uid of SERVICE_LOGIN, " printf("PFS: unable to retrieve uid of SERVICE_LOGIN, "

View file

@ -6,8 +6,6 @@
/* Structs used in prototypes must be declared as such first. */ /* Structs used in prototypes must be declared as such first. */
struct buf; struct buf;
struct inode; struct inode;
struct sockaddr_un;
struct ancillary;
/* buffer.c */ /* buffer.c */
struct buf *get_block(dev_t dev, pino_t inum); struct buf *get_block(dev_t dev, pino_t inum);
@ -32,7 +30,6 @@ void wipe_inode(struct inode *rip);
int fs_ftrunc(message *fs_m_in, message *fs_m_out); int fs_ftrunc(message *fs_m_in, message *fs_m_out);
int truncate_inode(struct inode *rip, off_t newsize); int truncate_inode(struct inode *rip, off_t newsize);
/* main.c */ /* main.c */
void reply(endpoint_t who, message *m_out); void reply(endpoint_t who, message *m_out);
@ -60,13 +57,4 @@ int fs_stat(message *fs_m_in, message *fs_m_out);
bit_t alloc_bit(void); bit_t alloc_bit(void);
void free_bit(bit_t bit_returned); void free_bit(bit_t bit_returned);
/* dev_uds.c */
void uds_request(message *m_ptr, int ipc_status);
void uds_unsuspend(devminor_t minor);
/* uds.c */
void uds_init(void);
int uds_clear_fds(devminor_t minor, struct ancillary *data);
int uds_do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
cp_grant_id_t grant);
#endif #endif

View file

@ -5,11 +5,9 @@
#define _TABLE #define _TABLE
#include "inc.h"
#include "fs.h" #include "fs.h"
#include "inode.h" #include "inode.h"
#include "buf.h" #include "buf.h"
#include "uds.h"
/* File System Handlers (pfs) */ /* File System Handlers (pfs) */
int (*fs_call_vec[])(message *fs_m_in, message *fs_m_out) = { int (*fs_call_vec[])(message *fs_m_in, message *fs_m_out) = {

View file

@ -45,7 +45,6 @@ struct boot_image_dev boot_image_dev_table[] = {
/*endpoint, flags, dev_nr, dev_style, dev_style2 */ /*endpoint, flags, dev_nr, dev_style, dev_style2 */
{ TTY_PROC_NR, SRV_DF, TTY_MAJOR, STYLE_TTY, STYLE_CTTY }, { TTY_PROC_NR, SRV_DF, TTY_MAJOR, STYLE_TTY, STYLE_CTTY },
{ MEM_PROC_NR, SRV_DF, MEMORY_MAJOR, STYLE_DEV, STYLE_NDEV }, { MEM_PROC_NR, SRV_DF, MEMORY_MAJOR, STYLE_DEV, STYLE_NDEV },
{ PFS_PROC_NR, SRV_DF, UDS_MAJOR, STYLE_DEV, STYLE_NDEV },
{ DEFAULT_BOOT_NR, SRV_DF, 0, STYLE_NDEV, STYLE_NDEV } /* default { DEFAULT_BOOT_NR, SRV_DF, 0, STYLE_NDEV, STYLE_NDEV } /* default
* entry * entry
*/ */

View file

@ -380,13 +380,13 @@ int do_verify_fd(message *m_out)
int fd; int fd;
/* This should be replaced with an ACL check. */ /* This should be replaced with an ACL check. */
if (who_e != PFS_PROC_NR) return EPERM; if (!super_user) return EPERM;
proc_e = job_m_in.VFS_PFS_ENDPT; proc_e = job_m_in.VFS_UDS_ENDPT;
fd = job_m_in.VFS_PFS_FD; fd = job_m_in.VFS_UDS_FD;
rfilp = (struct filp *) verify_fd(proc_e, fd); rfilp = (struct filp *) verify_fd(proc_e, fd);
m_out->VFS_PFS_FILP = (void *) rfilp; m_out->VFS_UDS_FILP = (void *) rfilp;
if (rfilp != NULL) unlock_filp(rfilp); if (rfilp != NULL) unlock_filp(rfilp);
return (rfilp != NULL) ? OK : EINVAL; return (rfilp != NULL) ? OK : EINVAL;
} }
@ -414,9 +414,9 @@ int do_set_filp(message *UNUSED(m_out))
filp_id_t f; filp_id_t f;
/* This should be replaced with an ACL check. */ /* This should be replaced with an ACL check. */
if (who_e != PFS_PROC_NR) return EPERM; if (!super_user) return EPERM;
f = (filp_id_t) job_m_in.VFS_PFS_FILP; f = (filp_id_t) job_m_in.VFS_UDS_FILP;
return set_filp(f); return set_filp(f);
} }
@ -457,10 +457,10 @@ int do_copy_filp(message *UNUSED(m_out))
filp_id_t f; filp_id_t f;
/* This should be replaced with an ACL check. */ /* This should be replaced with an ACL check. */
if (who_e != PFS_PROC_NR) return EPERM; if (!super_user) return EPERM;
proc_e = job_m_in.VFS_PFS_ENDPT; proc_e = job_m_in.VFS_UDS_ENDPT;
f = (filp_id_t) job_m_in.VFS_PFS_FILP; f = (filp_id_t) job_m_in.VFS_UDS_FILP;
return copy_filp(proc_e, f); return copy_filp(proc_e, f);
} }
@ -488,9 +488,9 @@ int do_put_filp(message *UNUSED(m_out))
filp_id_t f; filp_id_t f;
/* This should be replaced with an ACL check. */ /* This should be replaced with an ACL check. */
if (who_e != PFS_PROC_NR) return EPERM; if (!super_user) return EPERM;
f = (filp_id_t) job_m_in.VFS_PFS_FILP; f = (filp_id_t) job_m_in.VFS_UDS_FILP;
return put_filp(f); return put_filp(f);
} }
@ -537,10 +537,10 @@ int do_cancel_fd(message *UNUSED(m_out))
int fd; int fd;
/* This should be replaced with an ACL check. */ /* This should be replaced with an ACL check. */
if (who_e != PFS_PROC_NR) return EPERM; if (!super_user) return EPERM;
proc_e = job_m_in.VFS_PFS_ENDPT; proc_e = job_m_in.VFS_UDS_ENDPT;
fd = job_m_in.VFS_PFS_FD; fd = job_m_in.VFS_UDS_FD;
return cancel_fd(proc_e, fd); return cancel_fd(proc_e, fd);
} }

View file

@ -238,9 +238,9 @@ static void do_work(void)
} else { } else {
/* At this point we assume that we're dealing with a call that has been /* At this point we assume that we're dealing with a call that has been
* made specifically to VFS. Typically it will be a POSIX call from a * made specifically to VFS. Typically it will be a POSIX call from a
* normal process, but we also handle a few calls made by system * normal process, but we also handle a few calls made by drivers such
* processes (such as PFS) through here. Call the internal function * such as UDS and VND through here. Call the internal function that
* that does the work. * does the work.
*/ */
if (job_call_nr < 0 || job_call_nr >= NCALLS) { if (job_call_nr < 0 || job_call_nr >= NCALLS) {
error = ENOSYS; error = ENOSYS;

View file

@ -834,8 +834,8 @@ size_t pathlen;
if (pathlen < UNIX_PATH_MAX || pathlen >= PATH_MAX) return(EINVAL); if (pathlen < UNIX_PATH_MAX || pathlen >= PATH_MAX) return(EINVAL);
rfp = &(fproc[slot]); rfp = &(fproc[slot]);
r = sys_safecopyfrom(PFS_PROC_NR, io_gr, (vir_bytes) 0, r = sys_safecopyfrom(who_e, io_gr, (vir_bytes) 0, (vir_bytes) canon_path,
(vir_bytes) canon_path, pathlen); pathlen);
if (r != OK) return(r); if (r != OK) return(r);
canon_path[pathlen] = '\0'; canon_path[pathlen] = '\0';
@ -843,8 +843,8 @@ size_t pathlen;
if ((r = canonical_path(canon_path, rfp)) != OK) return(r); if ((r = canonical_path(canon_path, rfp)) != OK) return(r);
if (strlen(canon_path) >= pathlen) return(ENAMETOOLONG); if (strlen(canon_path) >= pathlen) return(ENAMETOOLONG);
/* copy canon_path back to PFS */ /* copy canon_path back to the caller */
r = sys_safecopyto(PFS_PROC_NR, (cp_grant_id_t) io_gr, (vir_bytes) 0, r = sys_safecopyto(who_e, (cp_grant_id_t) io_gr, (vir_bytes) 0,
(vir_bytes) canon_path, pathlen); (vir_bytes) canon_path, pathlen);
if (r != OK) return(r); if (r != OK) return(r);
@ -870,8 +870,8 @@ size_t pathlen;
int do_check_perms(message *UNUSED(m_out)) int do_check_perms(message *UNUSED(m_out))
{ {
/* This should be replaced by an ACL check. */ /* This should be replaced by an ACL check. */
if (who_e != PFS_PROC_NR) return EPERM; if (!super_user) return EPERM;
return check_perms(job_m_in.VFS_PFS_ENDPT, job_m_in.VFS_PFS_GRANT, return check_perms(job_m_in.VFS_UDS_ENDPT, job_m_in.VFS_UDS_GRANT,
(size_t) job_m_in.VFS_PFS_COUNT); (size_t) job_m_in.VFS_UDS_COUNT);
} }

View file

@ -188,11 +188,10 @@ int do_select(message *UNUSED(m_out))
* *
* In our case, terminal and pseudo-terminal devices are handled by the * In our case, terminal and pseudo-terminal devices are handled by the
* TTY major and sockets by either INET major (socket type AF_INET) or * TTY major and sockets by either INET major (socket type AF_INET) or
* PFS major (socket type AF_UNIX). PFS acts as an FS when it handles * UDS major (socket type AF_UNIX). Additionally, we give other
* pipes and as a driver when it handles sockets. Additionally, we * character drivers the chance to handle select for any of their
* give other character drivers the chance to handle select for any of * device nodes. Some may not implement support for select and let
* their device nodes. Some may not implement support for select and * libchardriver return EBADF, which we then pass to the calling
* let libchardriver return EBADF, which we then pass to the calling
* process once we receive the reply. * process once we receive the reply.
*/ */
se->type[fd] = -1; se->type[fd] = -1;

View file

@ -138,12 +138,12 @@ int (*call_vec[])(message *m_out) = {
no_sys, /* 121 = (task reply) */ no_sys, /* 121 = (task reply) */
do_mapdriver, /* 122 = mapdriver */ do_mapdriver, /* 122 = mapdriver */
do_getrusage, /* 123 = getrusage */ do_getrusage, /* 123 = getrusage */
do_check_perms, /* 124 = from PFS: check_perms */ do_check_perms, /* 124 = from UDS: check_perms */
do_verify_fd, /* 125 = from PFS: verify_fd */ do_verify_fd, /* 125 = from UDS: verify_fd */
do_set_filp, /* 126 = from PFS: set_filp */ do_set_filp, /* 126 = from UDS: set_filp */
do_copy_filp, /* 127 = from PFS: copy_filp */ do_copy_filp, /* 127 = from UDS: copy_filp */
do_put_filp, /* 128 = from PFS: put_filp */ do_put_filp, /* 128 = from UDS: put_filp */
do_cancel_fd, /* 129 = from PFS: cancel_fd */ do_cancel_fd, /* 129 = from UDS: cancel_fd */
}; };
/* This should not fail with "array size is negative": */ /* This should not fail with "array size is negative": */
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1]; extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];