bind9/lib/isc/include/isc/socket.h
2000-09-07 01:59:57 +00:00

663 lines
16 KiB
C

/*
* Copyright (C) 1998-2000 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: socket.h,v 1.50 2000/09/07 01:59:56 explorer Exp $ */
#ifndef ISC_SOCKET_H
#define ISC_SOCKET_H 1
/*****
***** Module Info
*****/
/*
* Sockets
*
* 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.
*
* MP:
* 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.
*
* Reliability:
* No anticipated impact.
*
* Resources:
* <TBS>
*
* Security:
* No anticipated impact.
*
* Standards:
* None.
*/
/***
*** Imports
***/
#include <isc/lang.h>
#include <isc/types.h>
#include <isc/event.h>
#include <isc/eventclass.h>
#include <isc/time.h>
#include <isc/region.h>
#include <isc/sockaddr.h>
ISC_LANG_BEGINDECLS
/***
*** Constants
***/
/*
* 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
/***
*** Types
***/
struct isc_socketevent {
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 */
isc_uint32_t attributes; /* see below */
};
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
* all the data is valid.
* _TIMESTAMP: The timestamp member is valid.
* _PKTINFO: The pktinfo member is valid.
* _MULTICAST: The UDP packet was received via a multicast transmission.
*/
#define ISC_SOCKEVENTATTR_ATTACHED 0x80000000U /* 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_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_RECVMARK (ISC_EVENTCLASS_SOCKET + 5)
#define ISC_SOCKEVENT_SENDMARK (ISC_EVENTCLASS_SOCKET + 6)
/*
* Internal events.
*/
#define ISC_SOCKEVENT_INTR (ISC_EVENTCLASS_SOCKET + 256)
#define ISC_SOCKEVENT_INTW (ISC_EVENTCLASS_SOCKET + 257)
typedef enum {
isc_sockettype_udp = 1,
isc_sockettype_tcp = 2
} isc_sockettype_t;
/*
* 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 */
/***
*** 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_result_t
isc_socket_create(isc_socketmgr_t *manager,
int pf,
isc_sockettype_t type,
isc_socket_t **socketp);
/*
* Create a new 'type' socket managed by 'manager'.
*
* Note:
*
* 'pf' is the desired protocol family, e.g. PF_INET or PF_INET6.
*
* Requires:
*
* 'manager' is a valid manager
*
* 'socketp' is a valid pointer, and *socketp == NULL
*
* Ensures:
*
* '*socketp' is attached to the newly created socket
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_NORESOURCES
* ISC_R_UNEXPECTED
*/
void
isc_socket_cancel(isc_socket_t *sock, isc_task_t *task,
unsigned int how);
/*
* Cancel pending I/O of the type specified by "how".
*
* Note: if "task" is NULL, then the cancel applies to all tasks using the
* socket.
*
* Requires:
*
* "socket" is a valid socket
*
* "task" is NULL or a valid task
*
* "how" is a bitmask describing the type of cancelation to perform.
* The type ISC_SOCKCANCEL_ALL will cancel all pending I/O on this
* socket.
*
* ISC_SOCKCANCEL_RECV:
* Cancel pending isc_socket_recv() calls.
*
* ISC_SOCKCANCEL_SEND:
* Cancel pending isc_socket_send() and isc_socket_sendto() calls.
*
* ISC_SOCKCANCEL_ACCEPT:
* Cancel pending isc_socket_accept() calls.
*
* ISC_SOCKCANCEL_CONNECT:
* Cancel pending isc_socket_connect() call.
*/
void
isc_socket_shutdown(isc_socket_t *sock, unsigned int how);
/*
* Shutdown 'socket' according to 'how'.
*
* Requires:
*
* 'socket' is a valid socket.
*
* 'task' is NULL or is a valid task.
*
* If 'how' is 'ISC_SOCKSHUT_RECV' or 'ISC_SOCKSHUT_ALL' then
*
* The read queue must be empty.
*
* No further read requests may be made.
*
* If 'how' is 'ISC_SOCKSHUT_SEND' or 'ISC_SOCKSHUT_ALL' then
*
* The write queue must be empty.
*
* No further write requests may be made.
*/
void
isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp);
/*
* Attach *socketp to socket.
*
* Requires:
*
* 'socket' is a valid socket.
*
* 'socketp' points to a NULL socket.
*
* Ensures:
*
* *socketp is attached to socket.
*/
void
isc_socket_detach(isc_socket_t **socketp);
/*
* Detach *socketp from its socket.
*
* Requires:
*
* 'socketp' points to a valid socket.
*
* If '*socketp' is the last reference to the socket,
* then:
*
* There must be no pending I/O requests.
*
* Ensures:
*
* *socketp is NULL.
*
* If '*socketp' is the last reference to the socket,
* then:
*
* The socket will be shutdown (both reading and writing)
* for all tasks.
*
* All resources used by the socket have been freed
*/
isc_result_t
isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *addressp);
/*
* Bind 'socket' to '*addressp'.
*
* Requires:
*
* 'socket' is a valid socket
*
* 'addressp' points to a valid isc_sockaddr.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOPERM
* ISC_R_ADDRNOTAVAIL
* ISC_R_ADDRINUSE
* ISC_R_BOUND
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_listen(isc_socket_t *sock, unsigned int backlog);
/*
* Set listen mode on the socket. After this call, the only function that
* can be used (other than attach and detach) is isc_socket_accept().
*
* Notes:
*
* 'backlog' is as in the UNIX system call listen() and may be
* ignored by non-UNIX implementations.
*
* If 'backlog' is zero, a reasonable system default is used, usually
* SOMAXCONN.
*
* Requires:
*
* 'socket' is a valid, bound TCP socket.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_accept(isc_socket_t *sock,
isc_task_t *task, isc_taskaction_t action, const void *arg);
/*
* Queue accept event. When a new connection is received, the task will
* get an ISC_SOCKEVENT_NEWCONN event with the sender set to the listen
* socket. The new socket structure is sent inside the isc_socket_newconnev_t
* event type, and is attached to the task 'task'.
*
* REQUIRES:
* 'socket' is a valid TCP socket that isc_socket_listen() was called
* on.
*
* 'task' is a valid task
*
* 'action' is a valid action
*
* RETURNS:
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addressp,
isc_task_t *task, isc_taskaction_t action,
const void *arg);
/*
* Connect 'socket' to peer with address *saddr. When the connection
* succeeds, or when an error occurs, a CONNECT event with action 'action'
* and arg 'arg' will be posted to the event queue for 'task'.
*
* Requires:
*
* 'socket' is a valid TCP socket
*
* 'addressp' points to a valid isc_sockaddr
*
* 'task' is a valid task
*
* 'action' is a valid action
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*
* Posted event's result code:
*
* ISC_R_SUCCESS
* ISC_R_TIMEDOUT
* ISC_R_CONNREFUSED
* ISC_R_NETUNREACH
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp);
/*
* Get the name of the peer connected to 'socket'.
*
* Requires:
*
* 'socket' is a valid TCP socket.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_TOOSMALL
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp);
/*
* Get the name of 'socket'.
*
* Requires:
*
* 'socket' is a valid socket.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_TOOSMALL
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_recv(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum,
isc_task_t *task, isc_taskaction_t action, const void *arg);
isc_result_t
isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
unsigned int minimum,
isc_task_t *task, isc_taskaction_t action, const void *arg);
/*
* Receive from 'socket', storing the results in region.
*
* Notes:
*
* Let 'length' refer to the length of 'region' or to the sum of all
* available regions in the list of buffers '*buflist'.
*
* If 'minimum' is non-zero and at least that many bytes are read,
* the completion event will be posted to the task 'task.' If minimum
* is zero, the exact number of bytes requested in the region must
* be read for an event to be posted. This only makes sense for TCP
* connections, and is always set to 1 byte for UDP.
*
* The read will complete when the desired number of bytes have been
* read, if end-of-input occurs, or if an error occurs. A read done
* event with the given 'action' and 'arg' will be posted to the
* event queue of 'task'.
*
* The caller may not modify 'region', the buffers which are passed
* into this function, or any data they refer to until the completion
* event is received.
*
* For isc_socket_recvv():
* On successful completion, '*buflist' will be empty, and the list of
* all buffers will be returned in the done event's 'bufferlist'
* member. On error return, '*buflist' will be unchanged.
*
* Requires:
*
* 'socket' is a valid, bound socket.
*
* For isc_socket_recv():
* 'region' is a valid region
*
* For isc_socket_recvv():
* 'buflist' is non-NULL, and '*buflist' contain at least one buffer.
*
* 'task' is a valid task
*
* action != NULL and is a valid action
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*
* Event results:
*
* ISC_R_SUCCESS
* ISC_R_UNEXPECTED
* XXX needs other net-type errors
*/
isc_result_t
isc_socket_send(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task, isc_taskaction_t action, const void *arg);
isc_result_t
isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task, isc_taskaction_t action, const void *arg,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
isc_result_t
isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, const void *arg);
isc_result_t
isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, const void *arg,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
/*
* Send the contents of 'region' to the socket's peer.
*
* Notes:
*
* Shutting down the requestor's task *may* result in any
* still pending writes being dropped or completed, depending on the
* underlying OS implementation.
*
* If 'action' is NULL, then no completion event will be posted.
*
* The caller may not modify 'region', the buffers which are passed
* into this function, or any data they refer to until the completion
* event is received.
*
* For isc_socket_sendv() and isc_socket_sendtov():
* On successful completion, '*buflist' will be empty, and the list of
* all buffers will be returned in the done event's 'bufferlist'
* member. On error return, '*buflist' will be unchanged.
*
* Requires:
*
* 'socket' is a valid, bound socket.
*
* For isc_socket_send():
* 'region' is a valid region
*
* For isc_socket_sendv() and isc_socket_sendtov():
* 'buflist' is non-NULL, and '*buflist' contain at least one buffer.
*
* 'task' is a valid task
*
* action == NULL or is a valid action
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*
* Event results:
*
* ISC_R_SUCCESS
* ISC_R_UNEXPECTED
* XXX needs other net-type errors
*/
isc_result_t
isc_socket_recvmark(isc_socket_t *sock, isc_task_t *task,
isc_taskaction_t action, const void *arg);
isc_result_t
isc_socket_sendmark(isc_socket_t *sock, isc_task_t *task,
isc_taskaction_t action, const void *arg);
/*
* Insert a recv/send marker for the socket.
*
* This marker is processed when all I/O requests in the proper queue
* have been processed.
*
* Requires:
*
* 'socket' is a valid, bound socket.
*
* 'task' is a valid task, 'action' is a valid action.
*
* Notes:
*
* If the queue is empty, the event will be posted immediately to the
* task.
*
* On return, the event's 'result' member will sometimes contain useful
* information. If the mark was processed after a fatal error, it will
* contain the same error that the last isc_socket_recv(), _send(),
* or sendto() returned, depending on the mark type.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
/*
* Create a socket manager.
*
* Notes:
*
* All memory will be allocated in memory context 'mctx'.
*
* Requires:
*
* 'mctx' is a valid memory context.
*
* 'managerp' points to a NULL isc_socketmgr_t.
*
* Ensures:
*
* '*managerp' is a valid isc_socketmgr_t.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*/
void
isc_socketmgr_destroy(isc_socketmgr_t **managerp);
/*
* Destroy a socket manager.
*
* Notes:
*
* This routine blocks until there are no sockets left in the manager,
* so if the caller holds any socket references using the manager, it
* must detach them before calling isc_socketmgr_destroy() or it will
* block forever.
*
* Requires:
*
* '*managerp' is a valid isc_socketmgr_t.
*
* All sockets managed by this manager are fully detached.
*
* Ensures:
*
* *managerp == NULL
*
* All resources used by the manager have been freed.
*/
isc_sockettype_t
isc_socket_gettype(isc_socket_t *sock);
/*
* Returns the socket type for "sock."
*
* Requires:
*
* "sock" is a valid socket.
*/
isc_boolean_t
isc_socket_isbound(isc_socket_t *sock);
ISC_LANG_ENDDECLS
#endif /* ISC_SOCKET_H */