socket: implement SOCK_CLOEXEC and SOCK_NONBLOCK
Change-Id: I3fa36fa999c82a192d402cb4d913bd397e106e53
This commit is contained in:
parent
fd610ba1b0
commit
fa78dc389f
7 changed files with 89 additions and 41 deletions
|
@ -18,12 +18,17 @@ __weak_alias(socket, _socket)
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
|
|
||||||
static int _tcp_socket(int protocol);
|
static int _tcp_socket(int type, int protocol);
|
||||||
static int _udp_socket(int protocol);
|
static int _udp_socket(int type, int protocol);
|
||||||
static int _uds_socket(int type, int protocol);
|
static int _uds_socket(int type, int protocol);
|
||||||
|
static void _socket_flags(int type, int *result);
|
||||||
|
|
||||||
int socket(int domain, int type, int protocol)
|
int socket(int domain, int type, int protocol)
|
||||||
{
|
{
|
||||||
|
int sock_type;
|
||||||
|
|
||||||
|
sock_type = type & ~SOCK_FLAGS_MASK;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
fprintf(stderr, "socket: domain %d, type %d, protocol %d\n",
|
fprintf(stderr, "socket: domain %d, type %d, protocol %d\n",
|
||||||
domain, type, protocol);
|
domain, type, protocol);
|
||||||
|
@ -37,15 +42,16 @@ int socket(int domain, int type, int protocol)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domain == AF_UNIX && (type == SOCK_STREAM ||
|
if (domain == AF_UNIX && (sock_type == SOCK_STREAM ||
|
||||||
type == SOCK_DGRAM || type == SOCK_SEQPACKET))
|
sock_type == SOCK_DGRAM ||
|
||||||
|
sock_type == SOCK_SEQPACKET))
|
||||||
return _uds_socket(type, protocol);
|
return _uds_socket(type, protocol);
|
||||||
|
|
||||||
if (domain == AF_INET && type == SOCK_STREAM)
|
if (domain == AF_INET && sock_type == SOCK_STREAM)
|
||||||
return _tcp_socket(protocol);
|
return _tcp_socket(type, protocol);
|
||||||
|
|
||||||
if (domain == AF_INET && type == SOCK_DGRAM)
|
if (domain == AF_INET && sock_type == SOCK_DGRAM)
|
||||||
return _udp_socket(protocol);
|
return _udp_socket(type, protocol);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
fprintf(stderr, "socket: nothing for domain %d, type %d, protocol %d\n",
|
fprintf(stderr, "socket: nothing for domain %d, type %d, protocol %d\n",
|
||||||
|
@ -55,9 +61,25 @@ int socket(int domain, int type, int protocol)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _tcp_socket(int protocol)
|
static void
|
||||||
|
_socket_flags(int type, int *result)
|
||||||
{
|
{
|
||||||
int fd;
|
/* Process socket flags */
|
||||||
|
if (type & SOCK_CLOEXEC) {
|
||||||
|
*result |= O_CLOEXEC;
|
||||||
|
}
|
||||||
|
if (type & SOCK_NONBLOCK) {
|
||||||
|
*result |= O_NONBLOCK;
|
||||||
|
}
|
||||||
|
if (type & SOCK_NOSIGPIPE) {
|
||||||
|
*result |= O_NOSIGPIPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _tcp_socket(int type, int protocol)
|
||||||
|
{
|
||||||
|
int flags = O_RDWR;
|
||||||
|
|
||||||
if (protocol != 0 && protocol != IPPROTO_TCP)
|
if (protocol != 0 && protocol != IPPROTO_TCP)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -66,13 +88,15 @@ static int _tcp_socket(int protocol)
|
||||||
errno= EPROTONOSUPPORT;
|
errno= EPROTONOSUPPORT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fd= open(TCP_DEVICE, O_RDWR);
|
|
||||||
return fd;
|
_socket_flags(type, &flags);
|
||||||
|
|
||||||
|
return open(TCP_DEVICE, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _udp_socket(int protocol)
|
static int _udp_socket(int type, int protocol)
|
||||||
{
|
{
|
||||||
int r, fd, t_errno;
|
int r, fd, t_errno, flags = O_RDWR;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
|
|
||||||
if (protocol != 0 && protocol != IPPROTO_UDP)
|
if (protocol != 0 && protocol != IPPROTO_UDP)
|
||||||
|
@ -83,7 +107,8 @@ static int _udp_socket(int protocol)
|
||||||
errno= EPROTONOSUPPORT;
|
errno= EPROTONOSUPPORT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fd= open(UDP_DEVICE, O_RDWR);
|
_socket_flags(type, &flags);
|
||||||
|
fd= open(UDP_DEVICE, flags);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
|
@ -104,7 +129,7 @@ static int _udp_socket(int protocol)
|
||||||
|
|
||||||
static int _uds_socket(int type, int protocol)
|
static int _uds_socket(int type, int protocol)
|
||||||
{
|
{
|
||||||
int fd, r;
|
int fd, r, flags = O_RDWR, sock_type;
|
||||||
if (protocol != 0)
|
if (protocol != 0)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -114,7 +139,8 @@ static int _uds_socket(int type, int protocol)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd= open(UDS_DEVICE, O_RDWR);
|
_socket_flags(type, &flags);
|
||||||
|
fd= open(UDS_DEVICE, flags);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +148,8 @@ static int _uds_socket(int type, int protocol)
|
||||||
/* set the type for the socket via ioctl (SOCK_DGRAM,
|
/* set the type for the socket via ioctl (SOCK_DGRAM,
|
||||||
* SOCK_STREAM, SOCK_SEQPACKET, etc)
|
* SOCK_STREAM, SOCK_SEQPACKET, etc)
|
||||||
*/
|
*/
|
||||||
r= ioctl(fd, NWIOSUDSTYPE, &type);
|
sock_type = type & ~SOCK_FLAGS_MASK;
|
||||||
|
r= ioctl(fd, NWIOSUDSTYPE, &sock_type);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
int ioctl_errno;
|
int ioctl_errno;
|
||||||
|
|
||||||
|
|
|
@ -286,7 +286,16 @@ int do_fcntl()
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case F_GETNOSIGPIPE:
|
||||||
|
/* POSIX: return value other than -1 is flag is set, else -1 */
|
||||||
|
r = -1;
|
||||||
|
if (f->filp_flags & O_NOSIGPIPE)
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
case F_SETNOSIGPIPE:
|
||||||
|
fl = (O_NOSIGPIPE);
|
||||||
|
f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
r = EINVAL;
|
r = EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,7 @@ endpoint_t map_to_fs_e;
|
||||||
* pipe_check *
|
* pipe_check *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int pipe_check(
|
int pipe_check(
|
||||||
struct vnode *vp, /* the inode of the pipe */
|
struct filp *filp, /* the filp of the pipe */
|
||||||
int rw_flag, /* READING or WRITING */
|
int rw_flag, /* READING or WRITING */
|
||||||
int oflags, /* flags set by open or fcntl */
|
int oflags, /* flags set by open or fcntl */
|
||||||
int bytes, /* bytes to be read or written (all chunks) */
|
int bytes, /* bytes to be read or written (all chunks) */
|
||||||
|
@ -186,9 +186,12 @@ int notouch /* check only */
|
||||||
* and there is no writer, return 0 bytes. If a process is writing to a
|
* and there is no writer, return 0 bytes. If a process is writing to a
|
||||||
* pipe and no one is reading from it, give a broken pipe error.
|
* pipe and no one is reading from it, give a broken pipe error.
|
||||||
*/
|
*/
|
||||||
|
struct vnode *vp;
|
||||||
off_t pos;
|
off_t pos;
|
||||||
int r = OK;
|
int r = OK;
|
||||||
|
|
||||||
|
vp = filp->filp_vno;
|
||||||
|
|
||||||
/* Reads start at the beginning; writes append to pipes */
|
/* Reads start at the beginning; writes append to pipes */
|
||||||
if (notouch) /* In this case we don't actually care whether data transfer
|
if (notouch) /* In this case we don't actually care whether data transfer
|
||||||
* would succeed. See POSIX 1003.1-2008 */
|
* would succeed. See POSIX 1003.1-2008 */
|
||||||
|
@ -221,10 +224,6 @@ int notouch /* check only */
|
||||||
|
|
||||||
/* Process is writing to a pipe. */
|
/* Process is writing to a pipe. */
|
||||||
if (find_filp(vp, R_BIT) == NULL) {
|
if (find_filp(vp, R_BIT) == NULL) {
|
||||||
/* Process is writing, but there is no reader. Tell kernel to generate
|
|
||||||
* a SIGPIPE signal. */
|
|
||||||
if (!notouch) sys_kill(fp->fp_endpoint, SIGPIPE);
|
|
||||||
|
|
||||||
return(EPIPE);
|
return(EPIPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ int do_check_perms(void);
|
||||||
int do_pipe(void);
|
int do_pipe(void);
|
||||||
int map_vnode(struct vnode *vp, endpoint_t fs_e);
|
int map_vnode(struct vnode *vp, endpoint_t fs_e);
|
||||||
void unpause(endpoint_t proc_e);
|
void unpause(endpoint_t proc_e);
|
||||||
int pipe_check(struct vnode *vp, int rw_flag, int oflags, int bytes,
|
int pipe_check(struct filp *filp, int rw_flag, int oflags, int bytes,
|
||||||
int notouch);
|
int notouch);
|
||||||
void release(struct vnode *vp, int op, int count);
|
void release(struct vnode *vp, int op, int count);
|
||||||
void revive(endpoint_t proc_e, int returned);
|
void revive(endpoint_t proc_e, int returned);
|
||||||
|
|
|
@ -124,27 +124,23 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
|
||||||
register struct vnode *vp;
|
register struct vnode *vp;
|
||||||
u64_t position, res_pos, new_pos;
|
u64_t position, res_pos, new_pos;
|
||||||
unsigned int cum_io, cum_io_incr, res_cum_io;
|
unsigned int cum_io, cum_io_incr, res_cum_io;
|
||||||
int op, oflags, r;
|
int op, r;
|
||||||
|
|
||||||
position = f->filp_pos;
|
position = f->filp_pos;
|
||||||
oflags = f->filp_flags;
|
|
||||||
vp = f->filp_vno;
|
vp = f->filp_vno;
|
||||||
r = OK;
|
r = OK;
|
||||||
cum_io = 0;
|
cum_io = 0;
|
||||||
|
|
||||||
if (size > SSIZE_MAX) return(EINVAL);
|
if (size > SSIZE_MAX) return(EINVAL);
|
||||||
|
|
||||||
if (S_ISFIFO(vp->v_mode)) {
|
op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
|
||||||
|
|
||||||
|
if (S_ISFIFO(vp->v_mode)) { /* Pipes */
|
||||||
if (fp->fp_cum_io_partial != 0) {
|
if (fp->fp_cum_io_partial != 0) {
|
||||||
panic("VFS: read_write: fp_cum_io_partial not clear");
|
panic("VFS: read_write: fp_cum_io_partial not clear");
|
||||||
}
|
}
|
||||||
r = rw_pipe(rw_flag, for_e, f, buf, size);
|
r = rw_pipe(rw_flag, for_e, f, buf, size);
|
||||||
return(r);
|
} else if (S_ISCHR(vp->v_mode)) { /* Character special files. */
|
||||||
}
|
|
||||||
|
|
||||||
op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
|
|
||||||
|
|
||||||
if (S_ISCHR(vp->v_mode)) { /* Character special files. */
|
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
int suspend_reopen;
|
int suspend_reopen;
|
||||||
|
|
||||||
|
@ -154,7 +150,7 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
|
||||||
suspend_reopen = (f->filp_state & FS_NEEDS_REOPEN);
|
suspend_reopen = (f->filp_state & FS_NEEDS_REOPEN);
|
||||||
dev = (dev_t) vp->v_sdev;
|
dev = (dev_t) vp->v_sdev;
|
||||||
|
|
||||||
r = dev_io(op, dev, for_e, buf, position, size, oflags,
|
r = dev_io(op, dev, for_e, buf, position, size, f->filp_flags,
|
||||||
suspend_reopen);
|
suspend_reopen);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
cum_io = r;
|
cum_io = r;
|
||||||
|
@ -178,7 +174,7 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
|
||||||
} else { /* Regular files */
|
} else { /* Regular files */
|
||||||
if (rw_flag == WRITING) {
|
if (rw_flag == WRITING) {
|
||||||
/* Check for O_APPEND flag. */
|
/* Check for O_APPEND flag. */
|
||||||
if (oflags & O_APPEND) position = cvul64(vp->v_size);
|
if (f->filp_flags & O_APPEND) position = cvul64(vp->v_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Issue request */
|
/* Issue request */
|
||||||
|
@ -208,7 +204,18 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
|
||||||
|
|
||||||
f->filp_pos = position;
|
f->filp_pos = position;
|
||||||
|
|
||||||
if (r == OK) return(cum_io);
|
if (r == EPIPE && rw_flag == WRITING) {
|
||||||
|
/* Process is writing, but there is no reader. Tell the kernel to
|
||||||
|
* generate s SIGPIPE signal.
|
||||||
|
*/
|
||||||
|
if (!(f->filp_flags & O_NOSIGPIPE)) {
|
||||||
|
sys_kill(fp->fp_endpoint, SIGPIPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == OK) {
|
||||||
|
return(cum_io);
|
||||||
|
}
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +284,7 @@ size_t req_size;
|
||||||
/* fp->fp_cum_io_partial is only nonzero when doing partial writes */
|
/* fp->fp_cum_io_partial is only nonzero when doing partial writes */
|
||||||
cum_io = fp->fp_cum_io_partial;
|
cum_io = fp->fp_cum_io_partial;
|
||||||
|
|
||||||
r = pipe_check(vp, rw_flag, oflags, req_size, 0);
|
r = pipe_check(f, rw_flag, oflags, req_size, 0);
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
if (r == SUSPEND) pipe_suspend(f, buf, req_size);
|
if (r == SUSPEND) pipe_suspend(f, buf, req_size);
|
||||||
return(r);
|
return(r);
|
||||||
|
|
|
@ -453,7 +453,7 @@ static int select_request_pipe(struct filp *f, int *ops, int block)
|
||||||
|
|
||||||
if ((*ops & (SEL_RD|SEL_ERR))) {
|
if ((*ops & (SEL_RD|SEL_ERR))) {
|
||||||
/* Check if we can read 1 byte */
|
/* Check if we can read 1 byte */
|
||||||
err = pipe_check(f->filp_vno, READING, f->filp_flags & ~O_NONBLOCK, 1,
|
err = pipe_check(f, READING, f->filp_flags & ~O_NONBLOCK, 1,
|
||||||
1 /* Check only */);
|
1 /* Check only */);
|
||||||
|
|
||||||
if (err != SUSPEND)
|
if (err != SUSPEND)
|
||||||
|
@ -470,7 +470,7 @@ static int select_request_pipe(struct filp *f, int *ops, int block)
|
||||||
|
|
||||||
if ((*ops & (SEL_WR|SEL_ERR))) {
|
if ((*ops & (SEL_WR|SEL_ERR))) {
|
||||||
/* Check if we can write 1 byte */
|
/* Check if we can write 1 byte */
|
||||||
err = pipe_check(f->filp_vno, WRITING, f->filp_flags & ~O_NONBLOCK, 1,
|
err = pipe_check(f, WRITING, f->filp_flags & ~O_NONBLOCK, 1,
|
||||||
1 /* Check only */);
|
1 /* Check only */);
|
||||||
|
|
||||||
if (err != SUSPEND)
|
if (err != SUSPEND)
|
||||||
|
|
|
@ -73,7 +73,9 @@
|
||||||
* restart
|
* restart
|
||||||
*/
|
*/
|
||||||
#define O_CLOEXEC 020000 /* close on exec */
|
#define O_CLOEXEC 020000 /* close on exec */
|
||||||
|
#if defined(_NETBSD_SOURCE)
|
||||||
|
#define O_NOSIGPIPE 040000 /* don't deliver sigpipe */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __minix /* NOT SUPPORTED! */
|
#ifndef __minix /* NOT SUPPORTED! */
|
||||||
#if defined(_NETBSD_SOURCE)
|
#if defined(_NETBSD_SOURCE)
|
||||||
|
@ -126,6 +128,10 @@
|
||||||
#define F_SETLK 6 /* set record locking information */
|
#define F_SETLK 6 /* set record locking information */
|
||||||
#define F_SETLKW 7 /* set record locking info; wait if blocked */
|
#define F_SETLKW 7 /* set record locking info; wait if blocked */
|
||||||
#define F_FREESP 8 /* free a section of a regular file */
|
#define F_FREESP 8 /* free a section of a regular file */
|
||||||
|
#if defined(_NETBSD_SOURCE)
|
||||||
|
#define F_GETNOSIGPIPE 9
|
||||||
|
#define F_SETNOSIGPIPE 10
|
||||||
|
#endif
|
||||||
|
|
||||||
/* File descriptor flags used for fcntl(). POSIX Table 6-2. */
|
/* File descriptor flags used for fcntl(). POSIX Table 6-2. */
|
||||||
#define FD_CLOEXEC 1 /* close on exec flag for third arg of fcntl */
|
#define FD_CLOEXEC 1 /* close on exec flag for third arg of fcntl */
|
||||||
|
|
Loading…
Reference in a new issue