<p>The default values on Windows are:</p>
<highlight language="config">
-AcceptFilter http data
-AcceptFilter https data
+AcceptFilter http connect
+AcceptFilter https connect
</highlight>
<p>Window's mpm_winnt interprets the AcceptFilter to toggle the AcceptEx()
- API, and does not support http protocol buffering. There are two values
- which utilize the Windows AcceptEx() API and will recycle network
- sockets between connections. <code>data</code> waits until data has
- been transmitted as documented above, and the initial data buffer and
- network endpoint addresses are all retrieved from the single AcceptEx()
- invocation. <code>connect</code> will use the AcceptEx() API, also
- retrieve the network endpoint addresses, but like <code>none</code>
- the <code>connect</code> option does not wait for the initial data
- transmission.</p>
+ API, and does not support http protocol buffering. <code>connect</code>
+ will use the AcceptEx() API, also retrieve the network endpoint
+ addresses, but like <code>none</code> the <code>connect</code> option
+ does not wait for the initial data transmission.</p>
<p>On Windows, <code>none</code> uses accept() rather than AcceptEx()
and will not recycle sockets between connections. This is useful for
network providers such as vpn drivers, or spam, virus or spyware
filters.</p>
+ <note type="warning">
+ <title>The <code>data</code> AcceptFilter (Windows)</title>
+
+ <p>For versions 2.4.23 and prior, the Windows <code>data</code> accept
+ filter waited until data had been transmitted and the initial data
+ buffer and network endpoint addresses had been retrieved from the
+ single AcceptEx() invocation. This implementation was subject to a
+ denial of service attack and has been disabled.</p>
+
+ <p>Current releases of httpd default to the <code>connect</code> filter
+ on Windows, and will fall back to <code>connect</code> if
+ <code>data</code> is specified. Users of prior releases are encouraged
+ to add an explicit setting of <code>connect</code> for their
+ AcceptFilter, as shown above.</p>
+ </note>
+
</usage>
<seealso><directive module="core">Protocol</directive></seealso>
</directivesynopsis>
"no known accept filter. Using 'none' instead",
lr->protocol);
}
- else if (strcmp(accf_name, "data") == 0)
- accf = 2;
+ else if (strcmp(accf_name, "data") == 0) {
+ accf = 1;
+ accf_name = "connect";
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
+ APLOGNO(03458) "winnt_accept: 'data' accept filter is no "
+ "longer supported. Using 'connect' instead");
+ }
else if (strcmp(accf_name, "connect") == 0)
accf = 1;
else if (strcmp(accf_name, "none") == 0)
}
#endif
- if (accf > 0) /* 'data' or 'connect' */
+ if (accf > 0) /* 'connect' */
{
if (WSAIoctl(nlsd, SIO_GET_EXTENSION_FUNCTION_POINTER,
&GuidAcceptEx, sizeof GuidAcceptEx,
}
else /* accf == 0, 'none' */
{
-reinit: /* target of data or connect upon too many AcceptEx failures */
+reinit: /* target of connect upon too many AcceptEx failures */
/* last, low priority event is a not yet accepted connection */
events[0] = exit_event;
}
}
- if (accf > 0) /* Either 'connect' or 'data' */
+ if (accf > 0) /* 'connect' */
{
- DWORD len;
char *buf;
/* Create and initialize the accept socket */
continue;
}
- if (accf == 2) { /* 'data' */
- len = APR_BUCKET_BUFF_SIZE;
- buf = apr_bucket_alloc(len, context->ba);
- len -= PADDED_ADDR_SIZE * 2;
- }
- else /* (accf == 1) 'connect' */ {
- len = 0;
- buf = context->buff;
- }
+ buf = context->buff;
/* AcceptEx on the completion context. The completion context will be
* signaled when a connection is accepted.
*/
- if (!lpfnAcceptEx(nlsd, context->accept_socket, buf, len,
+ if (!lpfnAcceptEx(nlsd, context->accept_socket, buf, 0,
PADDED_ADDR_SIZE, PADDED_ADDR_SIZE, &BytesRead,
&context->overlapped)) {
rv = apr_get_netos_error();
* 1) the client disconnects early
* 2) handshake was incomplete
*/
- if (accf == 2)
- apr_bucket_free(buf);
closesocket(context->accept_socket);
context->accept_socket = INVALID_SOCKET;
continue;
* 3) the dynamic address / adapter has changed
* Give five chances, then fall back on AcceptFilter 'none'
*/
- if (accf == 2)
- apr_bucket_free(buf);
closesocket(context->accept_socket);
context->accept_socket = INVALID_SOCKET;
++err_count;
}
else if ((rv != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) &&
(rv != APR_FROM_OS_ERROR(WSA_IO_PENDING))) {
- if (accf == 2)
- apr_bucket_free(buf);
closesocket(context->accept_socket);
context->accept_socket = INVALID_SOCKET;
++err_count;
/* exit_event triggered or event handle was closed */
closesocket(context->accept_socket);
context->accept_socket = INVALID_SOCKET;
- if (accf == 2)
- apr_bucket_free(buf);
break;
}
if (context->accept_socket == INVALID_SOCKET) {
- if (accf == 2)
- apr_bucket_free(buf);
continue;
}
}
/* Get the local & remote address
* TODO; error check
*/
- lpfnGetAcceptExSockaddrs(buf, len, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE,
+ lpfnGetAcceptExSockaddrs(buf, 0, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE,
&context->sa_server, &context->sa_server_len,
&context->sa_client, &context->sa_client_len);
- /* For 'data', craft a bucket for our data result
- * and pass to worker_main as context->overlapped.Pointer
- */
- if (accf == 2 && BytesRead)
- {
- apr_bucket *b;
- b = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
- apr_bucket_free, context->ba);
- /* Adjust the bucket to refer to the actual bytes read */
- b->length = BytesRead;
- context->overlapped.Pointer = b;
- }
- else {
- if (accf == 2) {
- apr_bucket_free(buf);
- }
- context->overlapped.Pointer = NULL;
- }
+ context->overlapped.Pointer = NULL;
}
else /* (accf = 0) e.g. 'none' */
{