* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
* \brief Provides TCP and UDP sockets for network I/O. The sockets are event
* sources in the task system.
* When I/O completes, a completion event for the socket is posted to the
* event queue of the task which requested the I/O.
* The module ensures appropriate synchronization of data structures it
* creates and manipulates.
* Clients of this module must not be holding a socket's task's lock when
* making a call that affects that socket. Failure to follow this rule
* can result in deadlock.
* The caller must ensure that isc_socketmgr_destroy() is called only
* once for a given manager.
#include <isc/eventclass.h>
#include <isc/sockaddr.h>
/* from the old namespace.h */
#define isc_socket_create isc__socket_create
#define isc_socket_dup isc__socket_dup
#define isc_socket_attach isc__socket_attach
#define isc_socket_detach isc__socket_detach
#define isc_socketmgr_create isc__socketmgr_create
#define isc_socketmgr_create2 isc__socketmgr_create2
#define isc_socketmgr_destroy isc__socketmgr_destroy
#define isc_socket_open isc__socket_open
#define isc_socket_close isc__socket_close
#define isc_socket_recvv isc__socket_recvv
#define isc_socket_recv isc__socket_recv
#define isc_socket_recv2 isc__socket_recv2
#define isc_socket_send isc__socket_send
#define isc_socket_sendto isc__socket_sendto
#define isc_socket_sendv isc__socket_sendv
#define isc_socket_sendtov isc__socket_sendtov
#define isc_socket_sendtov2 isc__socket_sendtov2
#define isc_socket_sendto2 isc__socket_sendto2
#define isc_socket_cleanunix isc__socket_cleanunix
#define isc_socket_permunix isc__socket_permunix
#define isc_socket_bind isc__socket_bind
#define isc_socket_filter isc__socket_filter
#define isc_socket_listen isc__socket_listen
#define isc_socket_accept isc__socket_accept
#define isc_socket_connect isc__socket_connect
#define isc_socket_getfd isc__socket_getfd
#define isc_socket_getname isc__socket_getname
#define isc_socket_gettag isc__socket_gettag
#define isc_socket_getpeername isc__socket_getpeername
#define isc_socket_getsockname isc__socket_getsockname
#define isc_socket_cancel isc__socket_cancel
#define isc_socket_gettype isc__socket_gettype
#define isc_socket_isbound isc__socket_isbound
#define isc_socket_ipv6only isc__socket_ipv6only
#define isc_socket_setname isc__socket_setname
#define isc_socketmgr_getmaxsockets isc__socketmgr_getmaxsockets
#define isc_socketmgr_setstats isc__socketmgr_setstats
#define isc_socketmgr_setreserved isc__socketmgr_setreserved
#define isc__socketmgr_maxudp isc___socketmgr_maxudp
#define isc_socket_fdwatchcreate isc__socket_fdwatchcreate
#define isc_socket_fdwatchpoke isc__socket_fdwatchpoke
#define isc_socket_dscp isc__socket_dscp
* Maximum number of buffers in a scatter/gather read/write. The operating
* system in use must support at least this number (plus one on some.)
#define ISC_SOCKET_MAXSCATTERGATHER 8
* In isc_socket_bind() set socket option SO_REUSEADDR prior to calling
* bind() if a non zero port is specified (AF_INET and AF_INET6).
#define ISC_SOCKET_REUSEADDRESS 0x01U
* Statistics counters. Used as isc_statscounter_t values.
isc_sockstatscounter_udp4open = 0,
isc_sockstatscounter_udp6open = 1,
isc_sockstatscounter_tcp4open = 2,
isc_sockstatscounter_tcp6open = 3,
isc_sockstatscounter_unixopen = 4,
isc_sockstatscounter_udp4openfail = 5,
isc_sockstatscounter_udp6openfail = 6,
isc_sockstatscounter_tcp4openfail = 7,
isc_sockstatscounter_tcp6openfail = 8,
isc_sockstatscounter_unixopenfail = 9,
isc_sockstatscounter_udp4close = 10,
isc_sockstatscounter_udp6close = 11,
isc_sockstatscounter_tcp4close = 12,
isc_sockstatscounter_tcp6close = 13,
isc_sockstatscounter_unixclose = 14,
isc_sockstatscounter_fdwatchclose = 15,
isc_sockstatscounter_udp4bindfail = 16,
isc_sockstatscounter_udp6bindfail = 17,
isc_sockstatscounter_tcp4bindfail = 18,
isc_sockstatscounter_tcp6bindfail = 19,
isc_sockstatscounter_unixbindfail = 20,
isc_sockstatscounter_fdwatchbindfail = 21,
isc_sockstatscounter_udp4connect = 22,
isc_sockstatscounter_udp6connect = 23,
isc_sockstatscounter_tcp4connect = 24,
isc_sockstatscounter_tcp6connect = 25,
isc_sockstatscounter_unixconnect = 26,
isc_sockstatscounter_fdwatchconnect = 27,
isc_sockstatscounter_udp4connectfail = 28,
isc_sockstatscounter_udp6connectfail = 29,
isc_sockstatscounter_tcp4connectfail = 30,
isc_sockstatscounter_tcp6connectfail = 31,
isc_sockstatscounter_unixconnectfail = 32,
isc_sockstatscounter_fdwatchconnectfail = 33,
isc_sockstatscounter_tcp4accept = 34,
isc_sockstatscounter_tcp6accept = 35,
isc_sockstatscounter_unixaccept = 36,
isc_sockstatscounter_tcp4acceptfail = 37,
isc_sockstatscounter_tcp6acceptfail = 38,
isc_sockstatscounter_unixacceptfail = 39,
isc_sockstatscounter_udp4sendfail = 40,
isc_sockstatscounter_udp6sendfail = 41,
isc_sockstatscounter_tcp4sendfail = 42,
isc_sockstatscounter_tcp6sendfail = 43,
isc_sockstatscounter_unixsendfail = 44,
isc_sockstatscounter_fdwatchsendfail = 45,
isc_sockstatscounter_udp4recvfail = 46,
isc_sockstatscounter_udp6recvfail = 47,
isc_sockstatscounter_tcp4recvfail = 48,
isc_sockstatscounter_tcp6recvfail = 49,
isc_sockstatscounter_unixrecvfail = 50,
isc_sockstatscounter_fdwatchrecvfail = 51,
isc_sockstatscounter_udp4active = 52,
isc_sockstatscounter_udp6active = 53,
isc_sockstatscounter_tcp4active = 54,
isc_sockstatscounter_tcp6active = 55,
isc_sockstatscounter_unixactive = 56,
isc_sockstatscounter_rawopen = 57,
isc_sockstatscounter_rawopenfail = 58,
isc_sockstatscounter_rawclose = 59,
isc_sockstatscounter_rawrecvfail = 60,
isc_sockstatscounter_rawactive = 61,
isc_sockstatscounter_max = 62
ISC_EVENT_COMMON(isc_socketevent_t);
isc_result_t result; /*%< OK, EOF, whatever else */
unsigned int minimum; /*%< minimum i/o for event */
unsigned int n; /*%< bytes read or written */
unsigned int offset; /*%< offset into buffer list */
isc_region_t region; /*%< for single-buffer i/o */
isc_bufferlist_t bufferlist; /*%< list of buffers */
isc_sockaddr_t address; /*%< source address */
isc_time_t timestamp; /*%< timestamp of packet recv */
struct in6_pktinfo pktinfo; /*%< ipv6 pktinfo */
uint32_t attributes; /*%< see below */
isc_eventdestructor_t destroy; /*%< original destructor */
unsigned int dscp; /*%< UDP dscp value */
typedef struct isc_socket_newconnev isc_socket_newconnev_t;
struct isc_socket_newconnev {
ISC_EVENT_COMMON(isc_socket_newconnev_t);
isc_socket_t * newsocket;
isc_result_t result; /*%< OK, EOF, whatever else */
isc_sockaddr_t address; /*%< source address */
typedef struct isc_socket_connev isc_socket_connev_t;
struct isc_socket_connev {
ISC_EVENT_COMMON(isc_socket_connev_t);
isc_result_t result; /*%< OK, EOF, whatever else */
* _ATTACHED: Internal use only.
* _TRUNC: Packet was truncated on receive.
* _CTRUNC: Packet control information was truncated. This can
* indicate that the packet is not complete, even though
* _TIMESTAMP: The timestamp member is valid.
* _PKTINFO: The pktinfo member is valid.
* _MULTICAST: The UDP packet was received via a multicast transmission.
* _DSCP: The UDP DSCP value is valid.
* _USEMINMTU: Set the per packet IPV6_USE_MIN_MTU flag.
#define ISC_SOCKEVENTATTR_ATTACHED 0x10000000U /* internal */
#define ISC_SOCKEVENTATTR_TRUNC 0x00800000U /* public */
#define ISC_SOCKEVENTATTR_CTRUNC 0x00400000U /* public */
#define ISC_SOCKEVENTATTR_TIMESTAMP 0x00200000U /* public */
#define ISC_SOCKEVENTATTR_PKTINFO 0x00100000U /* public */
#define ISC_SOCKEVENTATTR_MULTICAST 0x00080000U /* public */
#define ISC_SOCKEVENTATTR_DSCP 0x00040000U /* public */
#define ISC_SOCKEVENTATTR_USEMINMTU 0x00020000U /* public */
#define ISC_SOCKEVENT_ANYEVENT (0)
#define ISC_SOCKEVENT_RECVDONE (ISC_EVENTCLASS_SOCKET + 1)
#define ISC_SOCKEVENT_SENDDONE (ISC_EVENTCLASS_SOCKET + 2)
#define ISC_SOCKEVENT_NEWCONN (ISC_EVENTCLASS_SOCKET + 3)
#define ISC_SOCKEVENT_CONNECT (ISC_EVENTCLASS_SOCKET + 4)
#define ISC_SOCKEVENT_INTR (ISC_EVENTCLASS_SOCKET + 256)
#define ISC_SOCKEVENT_INTW (ISC_EVENTCLASS_SOCKET + 257)
isc_sockettype_fdwatch = 4,
* How a socket should be shutdown in isc_socket_shutdown() calls.
#define ISC_SOCKSHUT_RECV 0x00000001 /*%< close read side */
#define ISC_SOCKSHUT_SEND 0x00000002 /*%< close write side */
#define ISC_SOCKSHUT_ALL 0x00000003 /*%< close them all */
* What I/O events to cancel in isc_socket_cancel() calls.
#define ISC_SOCKCANCEL_RECV 0x00000001 /*%< cancel recv */
#define ISC_SOCKCANCEL_SEND 0x00000002 /*%< cancel send */
#define ISC_SOCKCANCEL_ACCEPT 0x00000004 /*%< cancel accept */
#define ISC_SOCKCANCEL_CONNECT 0x00000008 /*%< cancel connect */
#define ISC_SOCKCANCEL_ALL 0x0000000f /*%< cancel everything */
* Flags for isc_socket_send() and isc_socket_recv() calls.
#define ISC_SOCKFLAG_IMMEDIATE 0x00000001 /*%< send event only if needed */
#define ISC_SOCKFLAG_NORETRY 0x00000002 /*%< drop failed UDP sends */
* Flags for fdwatchcreate.
#define ISC_SOCKFDWATCH_READ 0x00000001 /*%< watch for readable */
#define ISC_SOCKFDWATCH_WRITE 0x00000002 /*%< watch for writable */
/*% Socket and socket manager methods */
typedef struct isc_socketmgrmethods {
void (*destroy)(isc_socketmgr_t **managerp);
isc_result_t (*socketcreate)(isc_socketmgr_t *manager, int pf,
isc_result_t (*fdwatchcreate)(isc_socketmgr_t *manager, int fd,
isc_sockfdwatch_t callback,
void *cbarg, isc_task_t *task,
} isc_socketmgrmethods_t;
typedef struct isc_socketmethods {
void (*attach)(isc_socket_t *socket,
void (*detach)(isc_socket_t **socketp);
isc_result_t (*bind)(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
isc_result_t (*sendto)(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task, isc_taskaction_t action,
void *arg, isc_sockaddr_t *address,
struct in6_pktinfo *pktinfo);
isc_result_t (*sendto2)(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task, isc_sockaddr_t *address,
struct in6_pktinfo *pktinfo,
isc_socketevent_t *event,
isc_result_t (*connect)(isc_socket_t *sock, isc_sockaddr_t *addr,
isc_task_t *task, isc_taskaction_t action,
isc_result_t (*recv)(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum, isc_task_t *task,
isc_taskaction_t action, void *arg);
isc_result_t (*recv2)(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum, isc_task_t *task,
isc_socketevent_t *event, unsigned int flags);
void (*cancel)(isc_socket_t *sock, isc_task_t *task,
isc_result_t (*getsockname)(isc_socket_t *sock,
isc_sockaddr_t *addressp);
isc_sockettype_t (*gettype)(isc_socket_t *sock);
void (*ipv6only)(isc_socket_t *sock, bool yes);
isc_result_t (*fdwatchpoke)(isc_socket_t *sock, int flags);
isc_result_t (*dup)(isc_socket_t *socket,
int (*getfd)(isc_socket_t *socket);
void (*dscp)(isc_socket_t *socket, isc_dscp_t dscp);
* This structure is actually just the common prefix of a socket manager
* object implementation's version of an isc_socketmgr_t.
* Direct use of this structure by clients is forbidden. socket implementations
* may change the structure. 'magic' must be ISCAPI_SOCKETMGR_MAGIC for any
* of the isc_socket_ routines to work. socket implementations must maintain
* In effect, this definition is used only for non-BIND9 version ("export")
* of the library, and the export version does not work for win32. So, to avoid
* the definition conflict with win32/socket.c, we enable this definition only
* for non-Win32 (i.e. Unix) platforms.
isc_socketmgrmethods_t *methods;
#define ISCAPI_SOCKETMGR_MAGIC ISC_MAGIC('A','s','m','g')
#define ISCAPI_SOCKETMGR_VALID(m) ((m) != NULL && \
(m)->magic == ISCAPI_SOCKETMGR_MAGIC)
* This is the common prefix of a socket object. The same note as
* that for the socketmgr structure applies.
isc_socketmethods_t *methods;
#define ISCAPI_SOCKET_MAGIC ISC_MAGIC('A','s','c','t')
#define ISCAPI_SOCKET_VALID(s) ((s) != NULL && \
(s)->magic == ISCAPI_SOCKET_MAGIC)
*** Socket and Socket Manager Functions
*** Note: all Ensures conditions apply only if the result is success for
*** those functions which return an isc_result.
isc_socket_fdwatchcreate(isc_socketmgr_t *manager,
isc_sockfdwatch_t callback,
* Create a new file descriptor watch socket managed by 'manager'.
*\li 'fd' is the already-opened file descriptor (must be less
*\li This function is not available on Windows.
*\li The callback function is called "in-line" - this means the function
* needs to return as fast as possible, as all other I/O will be suspended
* until the callback completes.
*\li 'manager' is a valid manager
*\li 'socketp' is a valid pointer, and *socketp == NULL
* '*socketp' is attached to the newly created fdwatch socket
isc_socket_fdwatchpoke(isc_socket_t *sock,
* Poke a file descriptor watch socket informing the manager that it
* should restart watching the socket
*\li 'sock' is the socket returned by isc_socket_fdwatchcreate
*\li 'flags' indicates what the manager should watch for on the socket
* in addition to what it may already be watching. It can be one or
* both of ISC_SOCKFDWATCH_READ and ISC_SOCKFDWATCH_WRITE. To
* temporarily disable watching on a socket the value indicating
* no more data should be returned from the call back routine.
*\li This function is not available on Windows.
*\li 'sock' is a valid isc socket
isc_socket_create(isc_socketmgr_t *manager,
* Create a new 'type' socket managed by 'manager'.