socket.c revision 0874abad14e3e9ecfc3dc1a1a2b9969f2f027724
#include <unistd.h>
#ifdef ISC_PLATFORM_HAVESYSUNH
#ifdef ISC_PLATFORM_HAVEKQUEUE
#ifdef ISC_PLATFORM_HAVEEPOLL
#ifdef ISC_PLATFORM_HAVEDEVPOLL
#if defined(HAVE_SYS_DEVPOLL_H)
#include <devpoll.h>
#include "errno2result.h"
/* See task.c about the following definition: */
#ifdef BIND9
#ifdef ISC_PLATFORM_USETHREADS
#define USE_WATCHER_THREAD
#define USE_SHARED_MANAGER
#ifndef USE_WATCHER_THREAD
#include "socket_p.h"
#include "../task_p.h"
#ifdef ISC_PLATFORM_HAVEKQUEUE
#define USE_KQUEUE
#define USE_EPOLL
#define USE_DEVPOLL
} pollinfo_t;
#define USE_SELECT
#ifndef USE_WATCHER_THREAD
struct isc_socketwait {
int nevents;
struct isc_socketwait {
int nfds;
int maxfd;
#ifndef ISC_SOCKET_MAXSOCKETS
#ifdef USE_SELECT
#ifdef __APPLE__
#define _DARWIN_UNLIMITED_SELECT
#ifdef ISC_SOCKET_USE_POLLWATCH
#ifndef ISC_SOCKET_POLLWATCH_TIMEOUT
#ifdef ISC_PLATFORM_USETHREADS
#ifndef ISC_SOCKET_MAXEVENTS
#ifndef ISC_SOCKADDR_LEN_T
#define ISC_SOCKADDR_LEN_T unsigned int
(e) == EWOULDBLOCK || \
(e) == EINTR || \
* DLVL(20) -- Socket creation/destruction.
#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
#ifndef USE_CMSG
#ifdef SO_TIMESTAMP
#ifndef USE_CMSG
struct isc__socket {
unsigned int references;
int fd;
int pf;
void * tag;
#ifdef ISC_NET_RECVOVERFLOW
char *recvcmsgbuf;
char *sendcmsgbuf;
void *fdwatcharg;
int fdwatchflags;
struct isc__socketmgr {
#ifdef USE_KQUEUE
int kqueue_fd;
int nevents;
#ifdef USE_EPOLL
int epoll_fd;
int nevents;
#ifdef USE_DEVPOLL
int devpoll_fd;
int nevents;
#ifdef USE_SELECT
int fd_bufsize;
unsigned int maxsocks;
#ifdef ISC_PLATFORM_USETHREADS
int *fdstate;
#ifdef USE_DEVPOLL
#ifdef USE_SELECT
int maxfd;
#ifdef USE_WATCHER_THREAD
unsigned int refs;
int maxudp;
#ifdef USE_SHARED_MANAGER
#ifdef ISC_NET_RECVOVERFLOW
isc__socket_t **);
#ifdef USE_WATCHER_THREAD
#ifdef BIND9
#define ISC_SOCKETFUNC_SCOPE
#define ISC_SOCKETFUNC_SCOPE static
ISC_SOCKETFUNC_SCOPE void
ISC_SOCKETFUNC_SCOPE void
unsigned int maxsocks);
ISC_SOCKETFUNC_SCOPE void
ISC_SOCKETFUNC_SCOPE void
unsigned int options);
const void *arg);
ISC_SOCKETFUNC_SCOPE void
ISC_SOCKETFUNC_SCOPE void
ISC_SOCKETFUNC_SCOPE void
#ifndef BIND9
} socketmethods = {
#ifndef BIND9
(void *)isc__socket_isbound
STATID_OPEN = 0,
defined(USE_WATCHER_THREAD)
const char *fmt, ...)
const char *fmt, ...)
strbuf);
static inline isc_result_t
#ifdef USE_KQUEUE
return (result);
return (result);
return (result);
return (result);
static inline isc_result_t
#ifdef USE_KQUEUE
return (result);
return (result);
return (result);
return (result);
#ifdef USE_WATCHER_THREAD
int cc;
#ifdef ENOSR
if (cc < 0) {
strbuf);
int cc;
if (cc < 0) {
strbuf);
else if (fd >= 0)
static isc_result_t
int ret;
int flags;
#ifdef USE_FIONBIO_IOCTL
#ifdef USE_FIONBIO_IOCTL
strbuf);
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
#ifdef USE_CMSG
static inline ISC_SOCKADDR_LEN_T
#ifdef CMSG_LEN
static inline ISC_SOCKADDR_LEN_T
#ifdef CMSG_SPACE
#ifdef USE_CMSG
#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
#ifdef SO_TIMESTAMP
#ifdef ISC_NET_BSD44MSGHDR
#ifdef MSG_TRUNC
#ifdef MSG_CTRUNC
#ifndef USE_CMSG
#ifdef SO_TIMESTAMP
#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
sizeof(struct in6_pktinfo));
goto next;
#ifdef SO_TIMESTAMP
goto next;
next:
unsigned int iovcount;
write_count = 0;
iovcount = 0;
goto config;
+ skip_count);
skip_count = 0;
iovcount++;
#ifdef ISC_NET_BSD44MSGHDR
unsigned int iovcount;
#ifdef BROKEN_RECVMSG
#ifdef ISC_PLATFORM_HAVESYSUNH
#ifdef ISC_NET_RECVOVERFLOW
maxiov--;
read_count = 0;
goto config;
iovcount = 0;
iovcount++;
#ifdef ISC_NET_RECVOVERFLOW
iovcount++;
#ifdef ISC_NET_BSD44MSGHDR
#if defined(USE_CMSG)
static isc_socketevent_t *
sizeof(*ev));
return (NULL);
ev->n = 0;
return (ev);
#if defined(ISC_SOCKET_DEBUG)
#ifdef ISC_NET_BSD44MSGHDR
int cc;
int recv_errno;
#if defined(ISC_SOCKET_DEBUG)
#if defined(ISC_SOCKET_DEBUG)
if (cc < 0) {
return (DOIO_SOFT);
return (DOIO_HARD); \
return (DOIO_SOFT); \
return (DOIO_HARD); \
#ifdef EPROTO
return (DOIO_HARD);
case isc_sockettype_tcp:
case isc_sockettype_unix:
if (cc == 0)
return (DOIO_EOF);
case isc_sockettype_udp:
case isc_sockettype_fdwatch:
INSIST(0);
return (DOIO_SOFT);
return (DOIO_SOFT);
#ifdef ISC_NET_RECVOVERFLOW
cc--;
actual_count = 0;
return (DOIO_SOFT);
return (DOIO_SUCCESS);
int cc;
int attempts = 0;
int send_errno;
if (cc < 0) {
goto resend;
return (DOIO_SOFT);
return (DOIO_HARD); \
return (DOIO_SOFT); \
return (DOIO_HARD); \
#ifdef EHOSTDOWN
return (DOIO_HARD);
if (cc == 0) {
return (DOIO_SOFT);
return (DOIO_SUCCESS);
#ifdef USE_SELECT
#ifdef ISC_PLATFORM_USETHREADS
int fd;
#ifdef USE_WATCHER_THREAD
static isc_result_t
return (ISC_R_NOMEMORY);
cmsgbuflen = 0;
goto error;
cmsgbuflen = 0;
goto error;
goto error;
return (ISC_R_SUCCESS);
return (result);
#ifdef SO_BSDCOMPAT
clear_bsdcompat(void) {
#ifdef __linux__
char *endp;
long int major;
long int minor;
static isc_result_t
int tries = 0;
#if defined(SO_RCVBUF)
int size;
case isc_sockettype_udp:
case isc_sockettype_tcp:
case isc_sockettype_unix:
case isc_sockettype_fdwatch:
INSIST(0);
goto again;
#ifdef F_DUPFD
return (ISC_R_NORESOURCES);
switch (errno) {
case EMFILE:
case ENFILE:
case ENOBUFS:
return (ISC_R_NORESOURCES);
case EPROTONOSUPPORT:
case EPFNOSUPPORT:
case EAFNOSUPPORT:
case EINVAL:
return (ISC_R_FAMILYNOSUPPORT);
strbuf);
return (ISC_R_UNEXPECTED);
return (ISC_R_UNEXPECTED);
#ifdef SO_BSDCOMPAT
strbuf);
#ifdef SO_NOSIGPIPE
strbuf);
#if defined(USE_CMSG)
#if defined(SO_TIMESTAMP)
strbuf);
#if defined(ISC_PLATFORM_HAVEIPV6)
#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
#ifdef IPV6_RECVPKTINFO
strbuf);
strbuf);
#if defined(IPV6_MTU)
#if defined(IP_DONTFRAG)
int off = 0;
#if defined(SO_RCVBUF)
strbuf);
return (ISC_R_SUCCESS);
int lockid;
return (result);
case isc_sockettype_udp:
case isc_sockettype_tcp:
case isc_sockettype_unix:
INSIST(0);
return (result);
#ifdef USE_DEVPOLL
#ifdef USE_SELECT
return (ISC_R_SUCCESS);
#ifdef BIND9
#ifdef USE_DEVPOLL
#ifdef USE_SELECT
return (result);
int lockid;
return (result);
#ifdef USE_SELECT
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
ISC_SOCKETFUNC_SCOPE void
ISC_SOCKETFUNC_SCOPE void
if (kill_socket)
#ifdef BIND9
int fd;
return (ISC_R_SUCCESS);
int fd;
(void *)&addrlen);
#ifdef F_DUPFD
if (fd < 0) {
goto soft_error;
switch (errno) {
case ENFILE:
case EMFILE:
err);
goto soft_error;
case ENOBUFS:
case ENOMEM:
case ECONNRESET:
case ECONNABORTED:
case EHOSTUNREACH:
case EHOSTDOWN:
case ENETUNREACH:
case ENETDOWN:
case ECONNREFUSED:
#ifdef EPROTO
case EPROTO:
#ifdef ENONET
case ENONET:
goto soft_error;
strbuf);
if (addrlen == 0U) {
goto soft_error;
goto soft_error;
goto soft_error;
#ifdef USE_SELECT
case DOIO_SOFT:
goto poke;
case DOIO_EOF:
goto poke;
case DOIO_SUCCESS:
case DOIO_HARD:
poke:
case DOIO_SOFT:
goto poke;
case DOIO_HARD:
case DOIO_SUCCESS:
poke:
int more_data;
if (more_data)
int more_data;
if (more_data)
if (readable) {
goto check_write;
if (writeable) {
goto unlock_fd;
if (!unlock_sock) {
if (unlock_sock)
if (unwatch_read)
if (unwatch_write)
#ifdef USE_KQUEUE
static isc_boolean_t
#ifdef USE_WATCHER_THREAD
nevents);
for (i = 0; i < nevents; i++) {
#ifdef USE_WATCHER_THREAD
#ifdef USE_WATCHER_THREAD
if (have_ctlevent)
return (done);
static isc_boolean_t
#ifdef USE_WATCHER_THREAD
nevents);
for (i = 0; i < nevents; i++) {
#ifdef USE_WATCHER_THREAD
#ifdef USE_WATCHER_THREAD
if (have_ctlevent)
return (done);
static isc_boolean_t
#ifdef USE_WATCHER_THREAD
nevents);
for (i = 0; i < nevents; i++) {
#ifdef USE_WATCHER_THREAD
#ifdef USE_WATCHER_THREAD
if (have_ctlevent)
return (done);
for (i = 0; i < maxfd; i++) {
#ifdef USE_WATCHER_THREAD
#ifdef USE_WATCHER_THREAD
static isc_boolean_t
return (ISC_TRUE);
return (ISC_FALSE);
static isc_threadresult_t
int ctlfd;
int cc;
#ifdef USE_KQUEUE
int maxfd;
#ifdef ISC_SOCKET_USE_POLLWATCH
while (!done) {
#ifdef USE_KQUEUE
#ifndef ISC_SOCKET_USE_POLLWATCH
if (cc == 0) {
} else if (cc > 0) {
} while (cc < 0);
return ((isc_threadresult_t)0);
#ifdef BIND9
ISC_SOCKETFUNC_SCOPE void
ISC_SOCKETFUNC_SCOPE void
static isc_result_t
#ifdef USE_KQUEUE
return (ISC_R_NOMEMORY);
strbuf);
return (result);
#ifdef USE_WATCHER_THREAD
return (result);
return (ISC_R_NOMEMORY);
strbuf);
return (result);
#ifdef USE_WATCHER_THREAD
return (result);
return (ISC_R_NOMEMORY);
return (ISC_R_NOMEMORY);
strbuf);
return (result);
#ifdef USE_WATCHER_THREAD
return (result);
sizeof(fd_mask);
return (ISC_R_NOMEMORY);
#ifdef USE_WATCHER_THREAD
return (ISC_R_SUCCESS);
#ifdef USE_WATCHER_THREAD
#ifdef USE_KQUEUE
unsigned int maxsocks)
#ifdef USE_WATCHER_THREAD
#ifdef USE_SHARED_MANAGER
return (ISC_R_EXISTS);
return (ISC_R_SUCCESS);
if (maxsocks == 0)
return (ISC_R_NOMEMORY);
goto free_manager;
goto free_manager;
goto free_manager;
goto cleanup_lock;
for (i = 0; i < FDLOCK_COUNT; i++) {
goto cleanup_lock;
#ifdef USE_WATCHER_THREAD
goto cleanup_lock;
strbuf);
goto cleanup_condition;
#ifdef USE_SHARED_MANAGER
goto cleanup;
#ifdef USE_WATCHER_THREAD
goto cleanup;
#ifdef USE_SHARED_MANAGER
return (ISC_R_SUCCESS);
#ifdef USE_WATCHER_THREAD
#ifdef USE_WATCHER_THREAD
for (i = 0; i < FDLOCK_COUNT; i++)
return (result);
#ifdef BIND9
return (ISC_R_SUCCESS);
ISC_SOCKETFUNC_SCOPE void
#ifdef USE_SHARED_MANAGER
#ifdef USE_WATCHER_THREAD
#ifdef USE_WATCHER_THREAD
#ifdef USE_WATCHER_THREAD
(void)close(i);
for (i = 0; i < FDLOCK_COUNT; i++)
#ifdef USE_SHARED_MANAGER
static isc_result_t
unsigned int flags)
int io_state;
switch (io_state) {
case DOIO_SOFT:
if (!have_lock) {
case DOIO_EOF:
case DOIO_HARD:
case DOIO_SUCCESS:
if (have_lock)
return (result);
unsigned int iocount;
return (ISC_R_NOMEMORY);
if (minimum == 0)
return (ISC_R_NOMEMORY);
event->n = 0;
if (minimum == 0)
static isc_result_t
unsigned int flags)
int io_state;
switch (io_state) {
case DOIO_SOFT:
if (!have_lock) {
case DOIO_HARD:
case DOIO_SUCCESS:
if (have_lock)
return (result);
NULL));
return (ISC_R_NOMEMORY);
NULL));
unsigned int iocount;
return (ISC_R_NOMEMORY);
event->n = 0;
ISC_SOCKETFUNC_SCOPE void
#ifdef ISC_PLATFORM_HAVESYSUNH
#ifndef S_ISSOCK
#ifndef S_ISFIFO
#ifndef S_ISFIFO
#ifndef S_ISSOCK
if (active) {
switch (errno) {
goto cleanup;
goto cleanup;
switch (errno) {
case ECONNREFUSED:
case ECONNRESET:
strbuf);
close(s);
#ifdef ISC_PLATFORM_HAVESYSUNH
#ifdef NEED_SECURE_DIRECTORY
char *slash;
#ifdef NEED_SECURE_DIRECTORY
strbuf);
return (result);
return (ISC_R_NOTIMPLEMENTED);
unsigned int options) {
return (ISC_R_FAMILYMISMATCH);
#ifdef AF_UNIX
goto bind_socket;
sizeof(on)) < 0) {
#ifdef AF_UNIX
switch (errno) {
case EACCES:
return (ISC_R_NOPERM);
case EADDRNOTAVAIL:
return (ISC_R_ADDRNOTAVAIL);
case EADDRINUSE:
return (ISC_R_ADDRINUSE);
case EINVAL:
return (ISC_R_BOUND);
strbuf);
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
strbuf);
return (ISC_R_FAILURE);
return (ISC_R_SUCCESS);
return (ISC_R_NOTIMPLEMENTED);
if (backlog == 0)
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
return (result);
return (ISC_R_SHUTTINGDOWN);
if (do_poke)
return (ISC_R_SUCCESS);
int cc;
return (ISC_R_MULTICAST);
sizeof(*dev));
return (ISC_R_NOMEMORY);
if (cc < 0) {
cc = 0;
goto success;
goto queue;
switch (errno) {
#ifdef EHOSTDOWN
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
if (cc == 0) {
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
int cc;
if (errno != 0) {
switch (errno) {
#ifdef EHOSTDOWN
sizeof(peerbuf));
return (result);
goto out;
strbuf);
goto out;
out:
return (result);
ISC_SOCKETFUNC_SCOPE void
if (how == 0)
ev_link);
return (val);
ISC_SOCKETFUNC_SCOPE void
#if defined(IPV6_V6ONLY)
#ifdef IPV6_V6ONLY
(void *)&onoff, sizeof(int)) < 0) {
strbuf);
#ifndef USE_WATCHER_THREAD
#ifdef USE_KQUEUE
#ifdef USE_EPOLL
int timeout;
#ifdef USE_DEVPOLL
#ifdef USE_SHARED_MANAGER
#ifdef USE_KQUEUE
tsp);
#ifdef USE_SHARED_MANAGER
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
#ifdef BIND9
ISC_SOCKETFUNC_SCOPE const char *
#ifdef USE_SOCKETIMPREGISTER
ISC_SOCKETFUNC_SCOPE void
#ifdef USE_SHARED_MANAGER
sizeof(peerbuf));