* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.c,v 1.9.18.8 2008/04/02 23:45:58 tbox Exp $ */
+/* $Id: net.c,v 1.9.18.9 2008/07/01 02:10:06 each Exp $ */
#include <config.h>
#include <isc/string.h>
#include <isc/util.h>
+/*%
+ * Definitions about UDP port range specification. This is a total mess of
+ * portability variants: some use sysctl (but the sysctl names vary), some use
+ * system-specific interfaces, some have the same interface for IPv4 and IPv6,
+ * some separate them, etc...
+ */
+
+/*%
+ * The last resort defaults: use all non well known port space
+ */
+#ifndef ISC_NET_PORTRANGELOW
+#define ISC_NET_PORTRANGELOW 1024
+#endif /* ISC_NET_PORTRANGELOW */
+#ifndef ISC_NET_PORTRANGEHIGH
+#define ISC_NET_PORTRANGEHIGH 65535
+#endif /* ISC_NET_PORTRANGEHIGH */
+
#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY)
const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
#endif
return (ipv6pktinfo_result);
}
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
+ int result = ISC_R_FAILURE;
+
+ REQUIRE(low != NULL && high != NULL);
+
+ UNUSED(af);
+
+ if (result != ISC_R_SUCCESS) {
+ *low = ISC_NET_PORTRANGELOW;
+ *high = ISC_NET_PORTRANGEHIGH;
+ }
+
+ return (ISC_R_SUCCESS); /* we currently never fail in this function */
+}
+
void
isc_net_disableipv4(void) {
initialize();
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: socket.c,v 1.30.18.22 2008/06/25 23:46:08 tbox Exp $ */
+/* $Id: socket.c,v 1.30.18.23 2008/07/01 02:10:06 each Exp $ */
/* This code has been rewritten to take advantage of Windows Sockets
* I/O Completion Ports and Events. I/O Completion Ports is ONLY
memset(msg, 0, sizeof(*msg));
- if (sock->type == isc_sockettype_udp) {
+ if (!sock->connected) {
msg->msg_name = (void *)&dev->address.type.sa;
msg->msg_namelen = dev->address.length;
} else {
*socketp = NULL;
}
-/*
- * Create a new 'type' socket managed by 'manager'. Events
- * will be posted to 'task' and when dispatched 'action' will be
- * called with 'arg' as the arg value. The new socket is returned
- * in 'socketp'.
- */
-isc_result_t
-isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
- isc_socket_t **socketp) {
- isc_socket_t *sock = NULL;
+static isc_result_t
+internal_open(isc_socketmgr_t *manager, isc_socket_t *sock) {
isc_result_t result;
#if defined(USE_CMSG)
int on = 1;
int socket_errno;
char strbuf[ISC_STRERRORSIZE];
- REQUIRE(VALID_MANAGER(manager));
- REQUIRE(socketp != NULL && *socketp == NULL);
-
- result = allocate_socket(manager, type, &sock);
- if (result != ISC_R_SUCCESS)
- return (result);
-
- sock->pf = pf;
- switch (type) {
+ switch (sock->type) {
case isc_sockettype_udp:
- sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+ sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
if (sock->fd != INVALID_SOCKET) {
result = connection_reset_fix(sock->fd);
if (result != ISC_R_SUCCESS) {
}
break;
case isc_sockettype_tcp:
- sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
+ sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
break;
}
if (sock->fd == INVALID_SOCKET) {
socket_errno = WSAGetLastError();
- free_socket(&sock);
switch (socket_errno) {
case WSAEMFILE:
result = make_nonblock(sock->fd);
if (result != ISC_R_SUCCESS) {
closesocket(sock->fd);
- free_socket(&sock);
return (result);
}
-
#if defined(USE_CMSG) || defined(SO_RCVBUF)
- if (type == isc_sockettype_udp) {
+ if (sock->type == isc_sockettype_udp) {
#if defined(USE_CMSG)
#if defined(ISC_PLATFORM_HAVEIPV6)
#ifdef IPV6_RECVPKTINFO
/* 2292bis */
- if ((pf == AF_INET6)
+ if ((sock->pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
(void *)&on, sizeof(on)) < 0)) {
isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
}
#else
/* 2292 */
- if ((pf == AF_INET6)
+ if ((sock->pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
(void *)&on, sizeof(on)) < 0)) {
isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
#endif /* IPV6_RECVPKTINFO */
#ifdef IPV6_USE_MIN_MTU /*2292bis, not too common yet*/
/* use minimum MTU */
- if (pf == AF_INET6) {
+ if (sock->pf == AF_INET6) {
(void)setsockopt(sock->fd, IPPROTO_IPV6,
IPV6_USE_MIN_MTU,
(void *)&on, sizeof(on));
}
#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
+ return (ISC_R_SUCCESS);
+}
+
+
+/*
+ * Create a new 'type' socket managed by 'manager'. Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * called with 'arg' as the arg value. The new socket is returned
+ * in 'socketp'.
+ */
+isc_result_t
+isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp) {
+ isc_socket_t *sock = NULL;
+ isc_result_t result;
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ result = allocate_socket(manager, type, &sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ sock->pf = pf;
+ result = internal_open(manager, sock);
+ if (result != ISC_R_SUCCESS) {
+ free_socket(&sock);
+ return (result);
+ }
+
sock->references = 1;
*socketp = sock;
return (ISC_R_SUCCESS);
}
+isc_result_t
+isc_socket_open(isc_socket_t *sock) {
+ isc_result_t result;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ REQUIRE(sock->references == 1);
+ UNLOCK(&sock->lock);
+
+ /*
+ * We don't need to retain the lock hereafter, since no one else has
+ * this socket.
+ */
+ REQUIRE(sock->fd == -1);
+
+ result = internal_open(sock->manager, sock);
+ if (result != ISC_R_SUCCESS)
+ sock->fd = -1;
+
+ return (result);
+}
+
/*
* Attach to a socket. Caller must explicitly detach when it is done.
*/
*socketp = NULL;
}
+void
+isc_socket_close(isc_socket_t *sock) {
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ REQUIRE(sock->references == 1);
+ UNLOCK(&sock->lock);
+ /*
+ * We don't need to retain the lock hereafter, since no one else has
+ * this socket.
+ */
+ REQUIRE(sock->fd >= 0);
+
+ INSIST(!sock->connecting);
+ INSIST(!sock->pending_recv);
+ INSIST(!sock->pending_send);
+ INSIST(!sock->pending_accept);
+ INSIST(ISC_LIST_EMPTY(sock->recv_list));
+ INSIST(ISC_LIST_EMPTY(sock->send_list));
+ INSIST(ISC_LIST_EMPTY(sock->accept_list));
+ INSIST(sock->connect_ev == NULL);
+
+ sock->fd = -1;
+ sock->listener = 0;
+ sock->connected = 0;
+ sock->connecting = 0;
+ sock->bound = 0;
+ isc_sockaddr_any(&sock->address);
+
+ socket_close(sock);
+}
+
/*
* Dequeue an item off the given socket's read queue, set the result code
* in the done event to the one provided, and send it to the task it was